diff --git a/widgets/app/app.go b/widgets/app/app.go index ca59a80d..bb1658cc 100644 --- a/widgets/app/app.go +++ b/widgets/app/app.go @@ -551,3 +551,34 @@ func (dsl *DSL) icons(cfg config.Config) { dsl.Logo = fmt.Sprintf("/api/__yao/app/icons/app.png") } } + +// Permissions get the permission blacklist +func Permissions(process *gou.Process) map[string]bool { + permissions := map[string]bool{} + sessionData, _ := session.Global().ID(process.Sid).Get("__permissions") + switch values := sessionData.(type) { + case []interface{}: + for _, value := range values { + permissions[fmt.Sprintf("%v", value)] = true + } + break + + case []string: + for _, value := range values { + permissions[value] = true + } + break + + case map[string]interface{}: + for key := range values { + permissions[key] = true + } + break + + case map[string]bool: + permissions = values + break + } + + return permissions +} diff --git a/widgets/component/action.go b/widgets/component/action.go index 952320f9..da492f21 100644 --- a/widgets/component/action.go +++ b/widgets/component/action.go @@ -118,16 +118,27 @@ func (node ActionNode) Custom() bool { // Hash hash value func (action ActionDSL) Hash() (string, error) { h := md4.New() - origin := fmt.Sprintf("%#v", action.Action) - // fmt.Println(origin) + origin := fmt.Sprintf("ACTION::%#v", action.Action) + // fmt.Println("Origin:", origin) io.WriteString(h, origin) return fmt.Sprintf("%x", h.Sum(nil)), nil } -// SetPath set actions xpath -func (actions Actions) SetPath(root string) Actions { - for i := range actions { - actions[i].Xpath = fmt.Sprintf("%s.%d", root, i) +// Filter actions +func (actions Actions) Filter(excludes map[string]bool) Actions { + new := []ActionDSL{} + for _, action := range actions { + if _, has := excludes[action.ID]; !has { + new = append(new, action) + } } - return actions + return new } + +// SetPath set actions xpath +// func (actions Actions) SetPath(root string) Actions { +// for i := range actions { +// actions[i].Xpath = fmt.Sprintf("%s.%d", root, i) +// } +// return actions +// } diff --git a/widgets/component/action_test.go b/widgets/component/action_test.go index a3c32148..aab6a1ca 100644 --- a/widgets/component/action_test.go +++ b/widgets/component/action_test.go @@ -18,7 +18,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Len(t, action.Action, 1) assert.Equal(t, "Delete", action.Action[0]["name"]) assert.Equal(t, "Form.delete", action.Action[0]["type"]) - assert.Equal(t, "6212f23054ddacf15e7a7c7354c6a5a6", action.ID) + assert.Equal(t, "408ebbf0c51d7a51417c04ac73a0a1bc", action.ID) action = ActionDSL{} err = jsoniter.Unmarshal(data["many"], &action) @@ -30,7 +30,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Equal(t, "Form.save", action.Action[0]["type"]) assert.Equal(t, "historyPush", action.Action[1]["name"]) assert.Equal(t, "Common.historyPush", action.Action[1]["type"]) - assert.Equal(t, "85f029739d324bcc3185c419000739e3", action.ID) + assert.Equal(t, "1c70ca190ae5259a37414f98ed9d86c3", action.ID) action = ActionDSL{} err = jsoniter.Unmarshal(data["flow"], &action) @@ -42,7 +42,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Equal(t, "Form.save", action.Action[0]["type"]) assert.Equal(t, "Flow", action.Action[1]["name"]) assert.Equal(t, "Actions.test.check", action.Action[1]["type"]) - assert.Equal(t, "0e1d99723154fbbeea64833be4151ada", action.ID) + assert.Equal(t, "c6d4ae7f02cea12a236bbae38956179c", action.ID) action = ActionDSL{} err = jsoniter.Unmarshal(data["sugar-string"], &action) @@ -52,7 +52,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Len(t, action.Action, 1) assert.Equal(t, "Actions.test.back", action.Action[0]["name"]) assert.Equal(t, "Actions.test.back", action.Action[0]["type"]) - assert.Equal(t, "9c8e6e7281ef5df76c2ef84c85308884", action.ID) + assert.Equal(t, "6188373a217ef9312bf14e6ca4b21fd2", action.ID) action = ActionDSL{} err = jsoniter.Unmarshal(data["sugar-map"], &action) @@ -62,7 +62,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Len(t, action.Action, 1) assert.Equal(t, "Form.delete", action.Action[0]["name"]) assert.Equal(t, "Form.delete", action.Action[0]["type"]) - assert.Equal(t, "d5d48c687da8afd46145cab1f5825523", action.ID) + assert.Equal(t, "1fe1bac887859171a97af154bb193821", action.ID) action = ActionDSL{} err = jsoniter.Unmarshal(data["sugar-map-custom"], &action) @@ -72,7 +72,7 @@ func TestActionUnmarshalJSON(t *testing.T) { assert.Len(t, action.Action, 1) assert.Equal(t, "Actions.test.back", action.Action[0]["name"]) assert.Equal(t, "Actions.test.back", action.Action[0]["type"]) - assert.Equal(t, "99434a339accfe83ff38b74358e0b3af", action.ID) + assert.Equal(t, "7daf632016d4d8ea77066bc54afd525e", action.ID) } diff --git a/widgets/field/column.go b/widgets/field/column.go index 7ffd6322..73741e34 100644 --- a/widgets/field/column.go +++ b/widgets/field/column.go @@ -30,7 +30,7 @@ func (column *ColumnDSL) UnmarshalJSON(data []byte) error { // Hash hash value func (column ColumnDSL) Hash() (string, error) { h := md4.New() - origin := fmt.Sprintf("%#v", column) + origin := fmt.Sprintf("COLUMN::%#v", column.Map()) // fmt.Println(origin) io.WriteString(h, origin) return fmt.Sprintf("%x", h.Sum(nil)), nil diff --git a/widgets/field/filter.go b/widgets/field/filter.go index d2cc4f11..e8e98bf3 100644 --- a/widgets/field/filter.go +++ b/widgets/field/filter.go @@ -30,7 +30,7 @@ func (filter *FilterDSL) UnmarshalJSON(data []byte) error { // Hash hash value func (filter FilterDSL) Hash() (string, error) { h := md4.New() - origin := fmt.Sprintf("%#v", filter) + origin := fmt.Sprintf("FILTER::%#v", filter.Map()) // fmt.Println(origin) io.WriteString(h, origin) return fmt.Sprintf("%x", h.Sum(nil)), nil diff --git a/widgets/mapping/mapping.go b/widgets/mapping/mapping.go new file mode 100644 index 00000000..1e03d254 --- /dev/null +++ b/widgets/mapping/mapping.go @@ -0,0 +1,8 @@ +package mapping + +// Mapping common +type Mapping struct { + Filters map[string]string + Columns map[string]string + Actions map[string]string +} diff --git a/widgets/table/compute.go b/widgets/table/compute.go deleted file mode 100644 index aadf67c0..00000000 --- a/widgets/table/compute.go +++ /dev/null @@ -1,83 +0,0 @@ -package table - -import ( - "fmt" - - "github.com/yaoapp/yao/widgets/compute" - "github.com/yaoapp/yao/widgets/field" -) - -func (dsl *DSL) getField() func(string) (*field.ColumnDSL, string, string, error) { - return func(name string) (*field.ColumnDSL, string, string, error) { - field, has := dsl.Fields.Table[name] - if !has { - return nil, "fields.table", dsl.ID, fmt.Errorf("fields.table.%s does not exist", name) - } - return &field, "fields.table", dsl.ID, nil - } -} - -func (dsl *DSL) getFilter() func(string) (*field.FilterDSL, string, string, error) { - return func(name string) (*field.FilterDSL, string, string, error) { - field, has := dsl.Fields.Filter[name] - if !has { - return nil, "fields.filter", dsl.ID, fmt.Errorf("fields.filter.%s does not exist", name) - } - return &field, "fields.filter", dsl.ID, nil - } -} - -func (dsl *DSL) computeMapping() error { - if dsl.Computes == nil { - dsl.Computes = &compute.Maps{ - Filter: map[string][]compute.Unit{}, - Edit: map[string][]compute.Unit{}, - View: map[string][]compute.Unit{}, - } - } - - if dsl.Fields == nil { - return nil - } - - // 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 { - if filter.Edit != nil && filter.Edit.Compute != nil { - bind := filter.FilterBind() - if _, has := dsl.Computes.Filter[bind]; !has { - dsl.Computes.Filter[bind] = []compute.Unit{} - } - dsl.Computes.Filter[bind] = append(dsl.Computes.Filter[bind], compute.Unit{Name: inst.Name, Kind: compute.Filter}) - } - } - } - } - - if dsl.Fields.Table != nil && dsl.Layout.Table != nil && dsl.Layout.Table.Columns != nil { - for _, inst := range dsl.Layout.Table.Columns { - if field, has := dsl.Fields.Table[inst.Name]; has { - // View - if field.View != nil && field.View.Compute != nil { - bind := field.ViewBind() - if _, has := dsl.Computes.View[bind]; !has { - dsl.Computes.View[bind] = []compute.Unit{} - } - dsl.Computes.View[bind] = append(dsl.Computes.View[bind], compute.Unit{Name: inst.Name, Kind: compute.View}) - } - - // Edit - if field.Edit != nil && field.Edit.Compute != nil { - bind := field.EditBind() - if _, has := dsl.Computes.Edit[bind]; !has { - dsl.Computes.Edit[bind] = []compute.Unit{} - } - dsl.Computes.Edit[bind] = append(dsl.Computes.Edit[bind], compute.Unit{Name: inst.Name, Kind: compute.Edit}) - } - } - } - } - - return nil -} diff --git a/widgets/table/fields.go b/widgets/table/fields.go index 6db2e5e6..566c5a6e 100644 --- a/widgets/table/fields.go +++ b/widgets/table/fields.go @@ -100,8 +100,8 @@ func (fields *FieldsDSL) BindTable(tab *DSL) error { // Xgen trans to xgen setting func (fields *FieldsDSL) Xgen(layout *LayoutDSL) (map[string]interface{}, error) { - res := map[string]interface{}{} + res := map[string]interface{}{} filters := map[string]interface{}{} tables := map[string]interface{}{} @@ -119,6 +119,7 @@ func (fields *FieldsDSL) Xgen(layout *LayoutDSL) (map[string]interface{}, error) } return nil, fmt.Errorf("fields.filter.%s not found, checking layout.filter.columns.%d.name", f.Name, i) } + filters[name] = field.Map() } } diff --git a/widgets/table/layout.go b/widgets/table/layout.go index cb35adbc..b50a4a04 100644 --- a/widgets/table/layout.go +++ b/widgets/table/layout.go @@ -7,6 +7,7 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/yaoapp/gou" "github.com/yaoapp/yao/widgets/component" + "github.com/yaoapp/yao/widgets/mapping" ) // BindModel bind model @@ -177,44 +178,110 @@ func (layout *LayoutDSL) BindTable(tab *DSL, fields *FieldsDSL) error { } // Xgen trans to Xgen setting -func (layout *LayoutDSL) Xgen() (map[string]interface{}, error) { - res := map[string]interface{}{} +func (layout *LayoutDSL) Xgen(data map[string]interface{}, excludes map[string]bool, mapping *mapping.Mapping) (*LayoutDSL, error) { - if layout.Table != nil { - if layout.Table.Props == nil { - layout.Table.Props = component.PropsDSL{} - } - - if _, has := layout.Table.Props["scroll"]; !has { - layout.Table.Props["scroll"] = map[string]interface{}{"x": "max-content"} - } - } - - data, err := jsoniter.Marshal(layout) + clone, err := layout.Clone() if err != nil { return nil, err } - err = jsoniter.Unmarshal(data, &res) - if err != nil { - return nil, err - } + if clone.Table != nil { + if clone.Table.Props == nil { + clone.Table.Props = component.PropsDSL{} + } - // replace import - if layout.Header != nil && layout.Header.Preset != nil && layout.Header.Preset.Import != nil { - name := layout.Header.Preset.Import.Name - res["header"].(map[string]interface{})["preset"].(map[string]interface{})["import"] = map[string]interface{}{ - "api": map[string]interface{}{ - "setting": fmt.Sprintf("/api/xiang/import/%s/setting", name), - "mapping": fmt.Sprintf("/api/xiang/import/%s/mapping", name), - "preview": fmt.Sprintf("/api/xiang/import/%s/data", name), - "import": fmt.Sprintf("/api/xiang/import/%s", name), - "mapping_setting_model": fmt.Sprintf("import_%s_mapping", name), - "preview_setting_model": fmt.Sprintf("import_%s_preview", name), - }, - "actions": layout.Header.Preset.Import.Actions, + if _, has := clone.Table.Props["scroll"]; !has { + clone.Table.Props["scroll"] = map[string]interface{}{"x": "max-content"} } } - return res, nil + // layout.header.preset.import.actions + if clone.Header != nil && + clone.Header.Preset != nil { + if clone.Header.Preset.Import != nil && + clone.Header.Preset.Import.Actions != nil && + len(clone.Header.Preset.Import.Actions) > 0 { + clone.Header.Preset.Import.Actions = clone.Header.Preset.Import.Actions.Filter(excludes) + } + + // layout.header.preset.batch.columns + if clone.Header.Preset.Batch != nil && clone.Header.Preset.Batch.Columns != nil { + columns := []component.InstanceDSL{} + for _, column := range clone.Header.Preset.Batch.Columns { + id, has := mapping.Filters[column.Name] + if !has { + continue + } + + if _, has := excludes[id]; has { + continue + } + + columns = append(columns, column) + } + clone.Header.Preset.Batch.Columns = columns + } + } + + // layout.filter.actions + if clone.Filter != nil { + if clone.Filter.Actions != nil && len(clone.Filter.Actions) > 0 { + clone.Filter.Actions = clone.Filter.Actions.Filter(excludes) + } + + if clone.Filter.Columns != nil && len(clone.Filter.Columns) > 0 { + 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 + } + } + + // layout.table.operation.actions + if clone.Table != nil { + if clone.Table.Operation.Actions != nil && len(clone.Table.Operation.Actions) > 0 { + clone.Table.Operation.Actions = clone.Table.Operation.Actions.Filter(excludes) + } + + if clone.Table.Columns != nil && len(clone.Table.Columns) > 0 { + columns := []component.InstanceDSL{} + for _, column := range clone.Table.Columns { + id, has := mapping.Columns[column.Name] + if !has { + continue + } + if _, has := excludes[id]; has { + continue + } + columns = append(columns, column) + } + clone.Table.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 } diff --git a/widgets/table/mapping.go b/widgets/table/mapping.go new file mode 100644 index 00000000..07b23b64 --- /dev/null +++ b/widgets/table/mapping.go @@ -0,0 +1,176 @@ +package table + +import ( + "fmt" + + "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) { + return func(name string) (*field.ColumnDSL, string, string, error) { + field, has := dsl.Fields.Table[name] + if !has { + return nil, "fields.table", dsl.ID, fmt.Errorf("fields.table.%s does not exist", name) + } + return &field, "fields.table", dsl.ID, nil + } +} + +func (dsl *DSL) getFilter() func(string) (*field.FilterDSL, string, string, error) { + return func(name string) (*field.FilterDSL, string, string, error) { + field, has := dsl.Fields.Filter[name] + if !has { + return nil, "fields.filter", dsl.ID, fmt.Errorf("fields.filter.%s does not exist", name) + } + return &field, "fields.filter", dsl.ID, nil + } +} + +// mapping id, compute and cloud props +func (dsl *DSL) mapping() error { + if dsl.Computes == nil { + dsl.Computes = &compute.Maps{ + Filter: map[string][]compute.Unit{}, + Edit: map[string][]compute.Unit{}, + View: map[string][]compute.Unit{}, + } + } + + 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 + + // Mapping Compute + if filter.Edit != nil && filter.Edit.Compute != nil { + bind := filter.FilterBind() + if _, has := dsl.Computes.Filter[bind]; !has { + dsl.Computes.Filter[bind] = []compute.Unit{} + } + dsl.Computes.Filter[bind] = append(dsl.Computes.Filter[bind], compute.Unit{Name: inst.Name, Kind: compute.Filter}) + } + } + } + } + + if dsl.Fields.Table != nil && dsl.Layout.Table != nil && dsl.Layout.Table.Columns != nil { + for _, inst := range dsl.Layout.Table.Columns { + if field, has := dsl.Fields.Table[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() + if _, has := dsl.Computes.View[bind]; !has { + dsl.Computes.View[bind] = []compute.Unit{} + } + dsl.Computes.View[bind] = append(dsl.Computes.View[bind], compute.Unit{Name: inst.Name, Kind: compute.View}) + } + + // Edit + if field.Edit != nil && field.Edit.Compute != nil { + bind := field.EditBind() + if _, has := dsl.Computes.Edit[bind]; !has { + dsl.Computes.Edit[bind] = []compute.Unit{} + } + dsl.Computes.Edit[bind] = append(dsl.Computes.Edit[bind], compute.Unit{Name: inst.Name, Kind: compute.Edit}) + } + } + } + } + + // Mapping Actions + dsl.mappingActions() + + // Mapping cloud props + // 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.Table.CPropsMerge(dsl.CProps, func(name string, kind string, column field.ColumnDSL) (xpath string) { + return fmt.Sprintf("fields.table.%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.header.preset.import.actions + if dsl.Layout != nil && + dsl.Layout.Header != nil && + dsl.Layout.Header.Preset != nil && + dsl.Layout.Header.Preset.Import != nil && + dsl.Layout.Header.Preset.Import.Actions != nil && + len(dsl.Layout.Header.Preset.Import.Actions) > 0 { + for idx, action := range dsl.Layout.Header.Preset.Import.Actions { + xpath := fmt.Sprintf("layout.header.preset.import.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 + } + } + + // layout.table.operation.actions + if dsl.Layout != nil && + dsl.Layout.Table != nil && + dsl.Layout.Table.Operation.Actions != nil && + len(dsl.Layout.Table.Operation.Actions) > 0 { + for idx, action := range dsl.Layout.Table.Operation.Actions { + xpath := fmt.Sprintf("layout.table.operation.actions[%d]", idx) + dsl.Mapping.Actions[action.ID] = xpath + dsl.Mapping.Actions[xpath] = action.ID + } + } + +} diff --git a/widgets/table/compute_test.go b/widgets/table/mapping_test.go similarity index 92% rename from widgets/table/compute_test.go rename to widgets/table/mapping_test.go index 890ced89..615a5ab6 100644 --- a/widgets/table/compute_test.go +++ b/widgets/table/mapping_test.go @@ -9,7 +9,7 @@ import ( "github.com/yaoapp/kun/any" ) -func TestComputeMapping(t *testing.T) { +func TestMapping(t *testing.T) { load(t) clear(t) testData(t) @@ -27,7 +27,7 @@ func TestComputeMapping(t *testing.T) { assert.Equal(t, 2, len(tab.Computes.Filter["where.name.like"])) } -func TestComputeFind(t *testing.T) { +func TestMappingFind(t *testing.T) { load(t) clear(t) @@ -42,7 +42,7 @@ func TestComputeFind(t *testing.T) { assert.Equal(t, "cat::Cookie-checked-compute", data.Get("name_view")) } -func TestComputeGet(t *testing.T) { +func TestMappingGet(t *testing.T) { load(t) clear(t) @@ -61,7 +61,7 @@ func TestComputeGet(t *testing.T) { } -func TestComputeSearch(t *testing.T) { +func TestMappingSearch(t *testing.T) { load(t) clear(t) @@ -77,7 +77,7 @@ func TestComputeSearch(t *testing.T) { assert.Equal(t, "cat::Cookie-checked-compute", data.Get("data.0.name_view")) } -func TestComputeSave(t *testing.T) { +func TestMappingSave(t *testing.T) { load(t) clear(t) testData(t) @@ -106,7 +106,7 @@ func TestComputeSave(t *testing.T) { assert.Equal(t, "New Pet", data.Get("name")) } -func TestComputeUpdate(t *testing.T) { +func TestMappingUpdate(t *testing.T) { load(t) clear(t) testData(t) @@ -134,7 +134,7 @@ func TestComputeUpdate(t *testing.T) { assert.Equal(t, "New Pet", data.Get("name")) } -func TestComputeInsert(t *testing.T) { +func TestMappingInsert(t *testing.T) { load(t) clear(t) args := []interface{}{"compute", diff --git a/widgets/table/process.go b/widgets/table/process.go index e32f811d..eafca9c2 100644 --- a/widgets/table/process.go +++ b/widgets/table/process.go @@ -17,6 +17,7 @@ import ( "github.com/yaoapp/kun/log" "github.com/yaoapp/kun/maps" "github.com/yaoapp/yao/helper" + "github.com/yaoapp/yao/widgets/app" ) // Export process @@ -45,11 +46,12 @@ func exportProcess() { func processXgen(process *gou.Process) interface{} { tab := MustGet(process) - setting, err := tab.Xgen() + data := process.ArgsMap(1, map[string]interface{}{}) + excludes := app.Permissions(process) + setting, err := tab.Xgen(data, excludes) if err != nil { exception.New(err.Error(), 500).Throw() } - return setting } diff --git a/widgets/table/process_test.go b/widgets/table/process_test.go index 5df0aa87..f2feae20 100644 --- a/widgets/table/process_test.go +++ b/widgets/table/process_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/yaoapp/gou" "github.com/yaoapp/gou/fs" + "github.com/yaoapp/gou/session" "github.com/yaoapp/kun/any" "github.com/yaoapp/yao/config" "github.com/yaoapp/yao/helper" @@ -432,6 +433,52 @@ func TestProcessXgen(t *testing.T) { } +func TestProcessXgenWithPermissions(t *testing.T) { + load(t) + clear(t) + testData(t) + + session.Global().Set("__permissions", []string{ + "8ca9bdf0fa2cbc8f1018f8566ed6ab5e", // fields.table.消费金额 + "f03f1ae60c46dd6cdeda87b919a51d7e", // fields.filter.状态 + "b1483ade34cd51261817558114e74e3f", // filter.actions[0] 添加宠物 + "e6a67850312980e8372e550c5b361097", // operation.actions[0] 查看 + }) + + args := []interface{}{"pet"} + res, err := gou.NewProcess("yao.table.Xgen", args...).Exec() + if err != nil { + t.Fatal(err) + } + + data := any.Of(res).MapStr().Dot() + assert.Equal(t, "/api/xiang/import/pet", data.Get("header.preset.import.api.import")) + assert.Equal(t, "查看详情1", data.Get("header.preset.import.actions[0].title")) + assert.Equal(t, "查看详情2", data.Get("header.preset.import.actions[1].title")) + assert.False(t, data.Has("fields.table.消费金额")) + assert.False(t, data.Has("fields.filter.状态")) + assert.False(t, data.Has("filter.actions[0]")) + assert.Len(t, data.Get("table.columns"), 3) + assert.Len(t, data.Get("table.operation.actions"), 4) + + session.Global().Set("__permissions", nil) + res, err = gou.NewProcess("yao.table.Xgen", args...).Exec() + if err != nil { + t.Fatal(err) + } + + data = any.Of(res).MapStr().Dot() + assert.Equal(t, "/api/xiang/import/pet", data.Get("header.preset.import.api.import")) + assert.Equal(t, "查看详情1", data.Get("header.preset.import.actions[0].title")) + assert.Equal(t, "查看详情2", data.Get("header.preset.import.actions[1].title")) + assert.True(t, data.Has("fields.table.消费金额")) + assert.True(t, data.Has("fields.filter.状态")) + assert.True(t, data.Has("filter.actions[0]")) + assert.Len(t, data.Get("table.columns"), 4) + assert.Len(t, data.Get("table.operation.actions"), 6) + +} + func TestProcessExport(t *testing.T) { load(t) clear(t) diff --git a/widgets/table/table.go b/widgets/table/table.go index 08e9644d..750fcd0c 100644 --- a/widgets/table/table.go +++ b/widgets/table/table.go @@ -186,10 +186,10 @@ func LoadData(data []byte, id string, root string) error { return fmt.Errorf("[Table] LoadData Bind %s %s", id, err.Error()) } - // Parse - err = dsl.Parse() + // Mapping + err = dsl.mapping() if err != nil { - return fmt.Errorf("[Table] LoadData Parse %s %s", id, err.Error()) + return fmt.Errorf("[Table] LoadData Mapping %s %s", id, err.Error()) } // Validate @@ -230,38 +230,15 @@ func MustGet(table 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.Table.CPropsMerge(dsl.CProps, func(name string, kind string, column field.ColumnDSL) (xpath string) { - return fmt.Sprintf("fields.table.%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(dsl.Layout) + fields, err := dsl.Fields.Xgen(layout) if err != nil { return nil, err } @@ -271,6 +248,34 @@ 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 + } + + // replace import + if layout.Header != nil && layout.Header.Preset != nil && layout.Header.Preset.Import != nil { + name := layout.Header.Preset.Import.Name + setting["header"].(map[string]interface{})["preset"].(map[string]interface{})["import"] = map[string]interface{}{ + "api": map[string]interface{}{ + "setting": fmt.Sprintf("/api/xiang/import/%s/setting", name), + "mapping": fmt.Sprintf("/api/xiang/import/%s/mapping", name), + "preview": fmt.Sprintf("/api/xiang/import/%s/data", name), + "import": fmt.Sprintf("/api/xiang/import/%s", name), + "mapping_setting_model": fmt.Sprintf("import_%s_mapping", name), + "preview_setting_model": fmt.Sprintf("import_%s_preview", name), + }, + "actions": layout.Header.Preset.Import.Actions, + } + } + + // Set Fields setting["fields"] = fields setting["config"] = dsl.Config for _, cProp := range dsl.CProps { diff --git a/widgets/table/types.go b/widgets/table/types.go index 7312aba8..e02eb9c8 100644 --- a/widgets/table/types.go +++ b/widgets/table/types.go @@ -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 table DSL @@ -19,6 +20,7 @@ type DSL struct { Config map[string]interface{} `json:"config,omitempty"` CProps field.CloudProps `json:"-"` compute.Computable + *mapping.Mapping } // ActionDSL the table action DSL diff --git a/widgets/test/engine.go b/widgets/test/engine.go index 15f051c8..9b9ca8cc 100644 --- a/widgets/test/engine.go +++ b/widgets/test/engine.go @@ -14,12 +14,19 @@ import ( // LoadEngine load engine func LoadEngine(language ...string) error { + runtime.Load(config.Conf) i18n.Load(config.Conf) share.DBConnect(config.Conf.DB) // removed later gou.LoadCrypt(`{}`, "PASSWORD") gou.LoadCrypt(`{}`, "AES") + // Session server + err := share.SessionStart() + if err != nil { + return err + } + // load engine models dev := os.Getenv("YAO_DEV") if dev != "" {