[add] widget table permission support
This commit is contained in:
parent
437a894505
commit
ef96535b41
16 changed files with 442 additions and 168 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
8
widgets/mapping/mapping.go
Normal file
8
widgets/mapping/mapping.go
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
package mapping
|
||||
|
||||
// Mapping common
|
||||
type Mapping struct {
|
||||
Filters map[string]string
|
||||
Columns map[string]string
|
||||
Actions map[string]string
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
176
widgets/table/mapping.go
Normal file
176
widgets/table/mapping.go
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 != "" {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue