[add] widget chart permission support
This commit is contained in:
parent
674bc35621
commit
db5e2f3968
7 changed files with 234 additions and 45 deletions
|
|
@ -86,10 +86,10 @@ func LoadFrom(dir string, prefix string) error {
|
|||
dsl.Layout = &LayoutDSL{}
|
||||
}
|
||||
|
||||
// Parse
|
||||
err = dsl.Parse()
|
||||
// mapping
|
||||
err = dsl.mapping()
|
||||
if err != nil {
|
||||
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error()))
|
||||
messages = append(messages, fmt.Sprintf("[%s] Mapping %s", id, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -138,39 +138,15 @@ func MustGet(chart interface{}) *DSL {
|
|||
return t
|
||||
}
|
||||
|
||||
// Parse Layout
|
||||
func (dsl *DSL) Parse() error {
|
||||
|
||||
// ComputeFields
|
||||
err := dsl.computeMapping()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Filters
|
||||
err = dsl.Fields.Filter.CPropsMerge(dsl.CProps, func(name string, filter field.FilterDSL) (xpath string) {
|
||||
return fmt.Sprintf("fields.filter.%s.edit.props", name)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Columns
|
||||
return dsl.Fields.Chart.CPropsMerge(dsl.CProps, func(name string, kind string, column field.ColumnDSL) (xpath string) {
|
||||
return fmt.Sprintf("fields.chart.%s.%s.props", name, kind)
|
||||
})
|
||||
}
|
||||
|
||||
// Xgen trans to xgen setting
|
||||
func (dsl *DSL) Xgen() (map[string]interface{}, error) {
|
||||
func (dsl *DSL) Xgen(data map[string]interface{}, excludes map[string]bool) (map[string]interface{}, error) {
|
||||
|
||||
setting, err := dsl.Layout.Xgen()
|
||||
layout, err := dsl.Layout.Xgen(data, excludes, dsl.Mapping)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fields, err := dsl.Fields.Xgen()
|
||||
fields, err := dsl.Fields.Xgen(layout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -180,6 +156,17 @@ func (dsl *DSL) Xgen() (map[string]interface{}, error) {
|
|||
dsl.Config["full"] = true
|
||||
}
|
||||
|
||||
setting := map[string]interface{}{}
|
||||
bytes, err := jsoniter.Marshal(layout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = jsoniter.Unmarshal(bytes, &setting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
setting["fields"] = fields
|
||||
setting["config"] = dsl.Config
|
||||
for _, cProp := range dsl.CProps {
|
||||
|
|
@ -189,7 +176,6 @@ func (dsl *DSL) Xgen() (map[string]interface{}, error) {
|
|||
"params": cProp.Query,
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,33 @@
|
|||
package chart
|
||||
|
||||
import jsoniter "github.com/json-iterator/go"
|
||||
import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/yao/widgets/field"
|
||||
)
|
||||
|
||||
// Xgen trans to xgen setting
|
||||
func (fields *FieldsDSL) Xgen() (map[string]interface{}, error) {
|
||||
func (fields *FieldsDSL) Xgen(layout *LayoutDSL) (map[string]interface{}, error) {
|
||||
res := map[string]interface{}{}
|
||||
data, err := jsoniter.Marshal(fields)
|
||||
|
||||
filters := map[string]field.FilterDSL{}
|
||||
if layout.Filter != nil && layout.Filter.Columns != nil {
|
||||
for _, inst := range layout.Filter.Columns {
|
||||
if c, has := fields.Filter[inst.Name]; has {
|
||||
filters[inst.Name] = c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
columns := map[string]field.ColumnDSL{}
|
||||
if layout.Chart != nil && layout.Chart.Columns != nil {
|
||||
for _, inst := range layout.Chart.Columns {
|
||||
if c, has := fields.Chart[inst.Name]; has {
|
||||
columns[inst.Name] = c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data, err := jsoniter.Marshal(map[string]interface{}{"filter": filters, "chart": columns})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,78 @@
|
|||
package chart
|
||||
|
||||
import jsoniter "github.com/json-iterator/go"
|
||||
import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/yaoapp/yao/widgets/component"
|
||||
"github.com/yaoapp/yao/widgets/mapping"
|
||||
)
|
||||
|
||||
// Xgen trans to Xgen setting
|
||||
func (layout *LayoutDSL) Xgen() (map[string]interface{}, error) {
|
||||
res := map[string]interface{}{}
|
||||
data, err := jsoniter.Marshal(layout)
|
||||
func (layout *LayoutDSL) Xgen(data map[string]interface{}, excludes map[string]bool, mapping *mapping.Mapping) (*LayoutDSL, error) {
|
||||
clone, err := layout.Clone()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = jsoniter.Unmarshal(data, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Filter
|
||||
if clone.Filter != nil {
|
||||
if clone.Filter.Actions != nil {
|
||||
clone.Filter.Actions = clone.Filter.Actions.Filter(excludes)
|
||||
}
|
||||
|
||||
if clone.Filter.Columns != nil {
|
||||
columns := []component.InstanceDSL{}
|
||||
for _, column := range clone.Filter.Columns {
|
||||
id, has := mapping.Filters[column.Name]
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, has := excludes[id]; has {
|
||||
continue
|
||||
}
|
||||
|
||||
columns = append(columns, column)
|
||||
}
|
||||
clone.Filter.Columns = columns
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
// Operations
|
||||
if clone.Operation != nil && clone.Operation.Actions != nil {
|
||||
clone.Operation.Actions = clone.Operation.Actions.Filter(excludes)
|
||||
}
|
||||
|
||||
// Columns
|
||||
if clone.Chart != nil && clone.Chart.Columns != nil {
|
||||
columns := []component.InstanceDSL{}
|
||||
for _, column := range clone.Chart.Columns {
|
||||
id, has := mapping.Columns[column.Name]
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, has := excludes[id]; has {
|
||||
continue
|
||||
}
|
||||
|
||||
columns = append(columns, column)
|
||||
}
|
||||
clone.Chart.Columns = columns
|
||||
}
|
||||
|
||||
return clone, nil
|
||||
}
|
||||
|
||||
// Clone layout for output
|
||||
func (layout *LayoutDSL) Clone() (*LayoutDSL, error) {
|
||||
new := LayoutDSL{}
|
||||
bytes, err := jsoniter.Marshal(layout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = jsoniter.Unmarshal(bytes, &new)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &new, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/yaoapp/yao/widgets/compute"
|
||||
"github.com/yaoapp/yao/widgets/field"
|
||||
"github.com/yaoapp/yao/widgets/mapping"
|
||||
)
|
||||
|
||||
func (dsl *DSL) getField() func(string) (*field.ColumnDSL, string, string, error) {
|
||||
|
|
@ -27,7 +28,8 @@ func (dsl *DSL) getFilter() func(string) (*field.FilterDSL, string, string, erro
|
|||
}
|
||||
}
|
||||
|
||||
func (dsl *DSL) computeMapping() error {
|
||||
func (dsl *DSL) mapping() error {
|
||||
|
||||
if dsl.Computes == nil {
|
||||
dsl.Computes = &compute.Maps{
|
||||
Filter: map[string][]compute.Unit{},
|
||||
|
|
@ -36,14 +38,32 @@ func (dsl *DSL) computeMapping() error {
|
|||
}
|
||||
}
|
||||
|
||||
if dsl.Mapping == nil {
|
||||
dsl.Mapping = &mapping.Mapping{}
|
||||
}
|
||||
|
||||
if dsl.Mapping.Filters == nil {
|
||||
dsl.Mapping.Filters = map[string]string{}
|
||||
}
|
||||
|
||||
if dsl.Mapping.Columns == nil {
|
||||
dsl.Mapping.Columns = map[string]string{}
|
||||
}
|
||||
|
||||
if dsl.Fields == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mapping compute and id
|
||||
// Filter
|
||||
if dsl.Fields.Filter != nil && dsl.Layout.Filter != nil && dsl.Layout.Filter.Columns != nil {
|
||||
for _, inst := range dsl.Layout.Filter.Columns {
|
||||
if filter, has := dsl.Fields.Filter[inst.Name]; has {
|
||||
|
||||
// Mapping ID
|
||||
dsl.Mapping.Filters[filter.ID] = inst.Name
|
||||
dsl.Mapping.Filters[inst.Name] = filter.ID
|
||||
|
||||
if filter.Edit != nil && filter.Edit.Compute != nil {
|
||||
bind := filter.FilterBind()
|
||||
if _, has := dsl.Computes.Filter[bind]; !has {
|
||||
|
|
@ -58,6 +78,11 @@ func (dsl *DSL) computeMapping() error {
|
|||
if dsl.Fields.Chart != nil && dsl.Layout.Chart != nil && dsl.Layout.Chart.Columns != nil {
|
||||
for _, inst := range dsl.Layout.Chart.Columns {
|
||||
if field, has := dsl.Fields.Chart[inst.Name]; has {
|
||||
|
||||
// Mapping ID
|
||||
dsl.Mapping.Columns[field.ID] = inst.Name
|
||||
dsl.Mapping.Columns[inst.Name] = field.ID
|
||||
|
||||
// View
|
||||
if field.View != nil && field.View.Compute != nil {
|
||||
bind := field.ViewBind()
|
||||
|
|
@ -70,5 +95,61 @@ func (dsl *DSL) computeMapping() error {
|
|||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
// Mapping Actions
|
||||
dsl.mappingActions()
|
||||
|
||||
// Filters
|
||||
err := dsl.Fields.Filter.CPropsMerge(dsl.CProps, func(name string, filter field.FilterDSL) (xpath string) {
|
||||
return fmt.Sprintf("fields.filter.%s.edit.props", name)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Columns
|
||||
return dsl.Fields.Chart.CPropsMerge(dsl.CProps, func(name string, kind string, column field.ColumnDSL) (xpath string) {
|
||||
return fmt.Sprintf("fields.chart.%s.%s.props", name, kind)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// Actions get the table actions
|
||||
func (dsl *DSL) mappingActions() {
|
||||
|
||||
if dsl.Mapping == nil {
|
||||
dsl.Mapping = &mapping.Mapping{}
|
||||
}
|
||||
|
||||
if dsl.Mapping.Actions == nil {
|
||||
dsl.Mapping.Actions = map[string]string{}
|
||||
}
|
||||
|
||||
// layout.operation.actions
|
||||
if dsl.Layout != nil &&
|
||||
dsl.Layout.Operation != nil &&
|
||||
dsl.Layout.Operation.Actions != nil &&
|
||||
len(dsl.Layout.Operation.Actions) > 0 {
|
||||
|
||||
for idx, action := range dsl.Layout.Operation.Actions {
|
||||
xpath := fmt.Sprintf("layout.operation.actions[%d]", idx)
|
||||
dsl.Mapping.Actions[action.ID] = xpath
|
||||
dsl.Mapping.Actions[xpath] = action.ID
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// layout.filter.actions
|
||||
if dsl.Layout != nil &&
|
||||
dsl.Layout.Filter != nil &&
|
||||
dsl.Layout.Filter.Actions != nil &&
|
||||
len(dsl.Layout.Filter.Actions) > 0 {
|
||||
|
||||
for idx, action := range dsl.Layout.Filter.Actions {
|
||||
xpath := fmt.Sprintf("layout.filter.actions[%d]", idx)
|
||||
dsl.Mapping.Actions[action.ID] = xpath
|
||||
dsl.Mapping.Actions[xpath] = action.ID
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/kun/exception"
|
||||
"github.com/yaoapp/yao/widgets/app"
|
||||
)
|
||||
|
||||
// Export process
|
||||
|
|
@ -18,7 +19,9 @@ func exportProcess() {
|
|||
func processXgen(process *gou.Process) interface{} {
|
||||
|
||||
chart := MustGet(process)
|
||||
setting, err := chart.Xgen()
|
||||
data := process.ArgsMap(1, map[string]interface{}{})
|
||||
excludes := app.Permissions(process, "charts", chart.ID)
|
||||
setting, err := chart.Xgen(data, excludes)
|
||||
if err != nil {
|
||||
exception.New(err.Error(), 500).Throw()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/gou/session"
|
||||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/yao/config"
|
||||
|
|
@ -82,6 +83,41 @@ func TestProcessXgen(t *testing.T) {
|
|||
assert.Equal(t, "/api/__yao/chart/dashboard/component/fields.filter."+url.QueryEscape("状态")+".edit.props.xProps/remote", data.Get("fields.filter.状态.edit.props.xProps.remote.api"))
|
||||
}
|
||||
|
||||
func TestProcessXgenWithPermissions(t *testing.T) {
|
||||
load(t)
|
||||
session.Global().Set("__permissions", map[string]interface{}{
|
||||
"charts.dashboard": []string{
|
||||
"7f46a38d7ff3f1832375ff63cd412f41", // operation.actions[0] 跳转至大屏
|
||||
"09302a46b1b6f13a346deeea79b859dd", // filter.columns[0].时间区间
|
||||
"f11f01be1f77fe6563f8577806a46158", // 综合评分
|
||||
},
|
||||
})
|
||||
|
||||
args := []interface{}{"dashboard"}
|
||||
res, err := gou.NewProcess("yao.chart.Xgen", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data := any.Of(res).MapStr().Dot()
|
||||
assert.Equal(t, "/api/__yao/chart/dashboard/component/fields.filter."+url.QueryEscape("状态")+".edit.props.xProps/remote", data.Get("fields.filter.状态.edit.props.xProps.remote.api"))
|
||||
assert.NotEqual(t, "时间区间", data.Get("filter.columns[0].name"))
|
||||
assert.Equal(t, nil, data.Get("operation.actions[0]"))
|
||||
assert.Equal(t, nil, data.Get("fields.chart.综合评分"))
|
||||
|
||||
session.Global().Set("__permissions", nil)
|
||||
res, err = gou.NewProcess("yao.chart.Xgen", args...).Exec()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data = any.Of(res).MapStr().Dot()
|
||||
assert.Equal(t, "/api/__yao/chart/dashboard/component/fields.filter."+url.QueryEscape("状态")+".edit.props.xProps/remote", data.Get("fields.filter.状态.edit.props.xProps.remote.api"))
|
||||
assert.Equal(t, "时间区间", data.Get("filter.columns[0].name"))
|
||||
assert.NotEqual(t, nil, data.Get("operation.actions[0]"))
|
||||
assert.NotEqual(t, nil, data.Get("fields.chart.综合评分"))
|
||||
}
|
||||
|
||||
func load(t *testing.T) {
|
||||
prepare(t)
|
||||
err := Load(config.Conf)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/yaoapp/yao/widgets/compute"
|
||||
"github.com/yaoapp/yao/widgets/field"
|
||||
"github.com/yaoapp/yao/widgets/hook"
|
||||
"github.com/yaoapp/yao/widgets/mapping"
|
||||
)
|
||||
|
||||
// DSL the chart DSL
|
||||
|
|
@ -18,6 +19,7 @@ type DSL struct {
|
|||
Config map[string]interface{} `json:"config,omitempty"`
|
||||
CProps field.CloudProps `json:"-"`
|
||||
compute.Computable
|
||||
*mapping.Mapping
|
||||
}
|
||||
|
||||
// ActionDSL the chart action DSL
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue