From 4ce8f12adb73cd6ae0166b415c11cdd2ec0e4991 Mon Sep 17 00:00:00 2001 From: Max Date: Sat, 3 Dec 2022 23:33:05 +0800 Subject: [PATCH] [add] widget.actions & widget.models --- widgets/action.go | 64 +++++++++++++++++++++++++++++++++++++ widgets/chart/api.go | 4 +-- widgets/chart/chart.go | 33 +++++++++++++++++++ widgets/chart/types.go | 2 +- widgets/component/action.go | 39 ++++++++++++++++++++++ widgets/component/types.go | 9 ++++++ widgets/form/form.go | 20 ++++++++++++ widgets/form/types.go | 2 +- widgets/models.go | 40 +++++++++++++++++++++++ widgets/process.go | 11 +++++-- widgets/process_test.go | 20 ++++++++++++ widgets/table/table.go | 47 +++++++++++++++++++++++++++ widgets/table/types.go | 4 +-- 13 files changed, 286 insertions(+), 9 deletions(-) create mode 100644 widgets/component/action.go create mode 100644 widgets/models.go diff --git a/widgets/action.go b/widgets/action.go index dbe9a3e9..e2f1fd45 100644 --- a/widgets/action.go +++ b/widgets/action.go @@ -1 +1,65 @@ package widgets + +import ( + "fmt" + "os" + "strings" + + "github.com/yaoapp/yao/widgets/chart" + "github.com/yaoapp/yao/widgets/component" + "github.com/yaoapp/yao/widgets/form" + "github.com/yaoapp/yao/widgets/table" +) + +// WidgetAction the widget actionlist +type WidgetAction interface { + Actions() []component.ActionsExport +} + +// Actions return loaded widgets actions +func Actions() []Item { + + actions := map[string]interface{}{} + tableActions(actions) + formActions(actions) + chartActions(actions) + + grouping := Grouping(actions) + items := Array(grouping, []Item{}) + Sort(items, []string{"tables", "forms", "lists", "charts"}) + return items +} + +func tableActions(actions map[string]interface{}) { + for id, widget := range table.Tables { + dsl := fmt.Sprintf("tables%s%s.tab.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) + widgetActions(actions, widget, id, dsl, widget.Name) + } +} + +func formActions(actions map[string]interface{}) { + for id, widget := range form.Forms { + dsl := fmt.Sprintf("forms%s%s.form.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) + widgetActions(actions, widget, id, dsl, widget.Name) + } +} + +func chartActions(actions map[string]interface{}) { + for id, widget := range chart.Charts { + dsl := fmt.Sprintf("charts%s%s.chart.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) + widgetActions(actions, widget, id, dsl, widget.Name) + } +} + +func widgetActions(actions map[string]interface{}, widget WidgetAction, widgetID string, dsl string, name string) map[string]interface{} { + items := widget.Actions() + if len(items) > 0 { + actions[dsl] = map[string]interface{}{ + "items": widget.Actions(), + "DSL": dsl, + "ID": widgetID, + "name": name, + } + } + return nil +} diff --git a/widgets/chart/api.go b/widgets/chart/api.go index 2a465cc0..8ff0d61f 100644 --- a/widgets/chart/api.go +++ b/widgets/chart/api.go @@ -62,8 +62,8 @@ func (chart *DSL) getAction(path string) (*action.Process, error) { func exportAPI() error { http := gou.HTTP{ - Name: "Widget Form API", - Description: "Widget Form API", + Name: "Widget Chart API", + Description: "Widget Chart API", Version: share.VERSION, Guard: "widget-chart", Group: "__yao/chart", diff --git a/widgets/chart/chart.go b/widgets/chart/chart.go index fa6ffffc..30982cb7 100644 --- a/widgets/chart/chart.go +++ b/widgets/chart/chart.go @@ -197,3 +197,36 @@ func (dsl *DSL) Xgen() (map[string]interface{}, error) { return setting, nil } + +// Actions get the chart actions +func (dsl *DSL) Actions() []component.ActionsExport { + + res := []component.ActionsExport{} + + // layout.operation.actions + if dsl.Layout != nil && + dsl.Layout.Operation != nil && + dsl.Layout.Operation.Actions != nil && + len(dsl.Layout.Operation.Actions) > 0 { + + res = append(res, component.ActionsExport{ + Type: "operation", + Xpath: "layout.operation.actions", + Actions: dsl.Layout.Operation.Actions.Hash(), + }) + } + + // layout.filter.actions + if dsl.Layout != nil && + dsl.Layout.Filter != nil && + dsl.Layout.Filter.Actions != nil && + len(dsl.Layout.Filter.Actions) > 0 { + + res = append(res, component.ActionsExport{ + Type: "filter", + Xpath: "layout.filter.actions", + Actions: dsl.Layout.Filter.Actions.Hash(), + }) + } + return res +} diff --git a/widgets/chart/types.go b/widgets/chart/types.go index 5ea3fe1d..afcaed3c 100644 --- a/widgets/chart/types.go +++ b/widgets/chart/types.go @@ -52,7 +52,7 @@ type FilterLayoutDSL struct { // OperationLayoutDSL layout.operation type OperationLayoutDSL struct { - Actions []component.ActionDSL `json:"actions,omitempty"` + Actions component.Actions `json:"actions,omitempty"` } // ViewLayoutDSL layout.form diff --git a/widgets/component/action.go b/widgets/component/action.go new file mode 100644 index 00000000..d109cda9 --- /dev/null +++ b/widgets/component/action.go @@ -0,0 +1,39 @@ +package component + +import ( + "fmt" + "io" + "sort" + "strings" + + jsoniter "github.com/json-iterator/go" + "golang.org/x/crypto/md4" +) + +// 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 +} + +// Hash hash value +func (actions Actions) Hash() Actions { + h := md4.New() + for i := range actions { + keys := []string{} + for key, value := range actions[i].Action { + for k, v := range value { + data, _ := jsoniter.Marshal(v) + key = fmt.Sprintf("%s%s%s", key, k, data) + } + keys = append(keys, key) + } + sort.Strings(keys) + origin := strings.Join(keys, "|") + io.WriteString(h, origin) + actions[i].ID = fmt.Sprintf("%x", h.Sum(nil)) + } + return actions +} diff --git a/widgets/component/types.go b/widgets/component/types.go index 8f898100..f0ed0c57 100644 --- a/widgets/component/types.go +++ b/widgets/component/types.go @@ -21,12 +21,21 @@ type InstanceDSL struct { Height interface{} `json:"height,omitempty"` } +// ActionsExport the export actions +type ActionsExport struct { + Type string `json:"type,omitempty"` + Xpath string `json:"xpath"` + Actions Actions `json:"actions,omitempty"` +} + // ActionDSL the component action DSL type ActionDSL struct { Title string `json:"title,omitempty"` Width int `json:"width,omitempty"` Icon string `json:"icon,omitempty"` Style string `json:"style,omitempty"` + ID string `json:"id,omitempty"` + Xpath string `json:"xpath,omitempty"` Props PropsDSL `json:"props,omitempty"` Confirm *ConfirmActionDSL `json:"confirm,omitempty"` Action map[string]ParamsDSL `json:"action,omitempty"` diff --git a/widgets/form/form.go b/widgets/form/form.go index bb8b0147..e11b8944 100644 --- a/widgets/form/form.go +++ b/widgets/form/form.go @@ -258,3 +258,23 @@ func (dsl *DSL) Xgen() (map[string]interface{}, error) { setting["name"] = dsl.Name return setting, nil } + +// Actions get the form actions +func (dsl *DSL) Actions() []component.ActionsExport { + + res := []component.ActionsExport{} + + // layout.operation.actions + if dsl.Layout != nil && + dsl.Layout.Operation != nil && + dsl.Layout.Operation.Actions != nil && + len(dsl.Layout.Operation.Actions) > 0 { + + res = append(res, component.ActionsExport{ + Type: "operation", + Xpath: "layout.operation.actions", + Actions: dsl.Layout.Operation.Actions.Hash(), + }) + } + return res +} diff --git a/widgets/form/types.go b/widgets/form/types.go index 6920eecf..7079fead 100644 --- a/widgets/form/types.go +++ b/widgets/form/types.go @@ -65,7 +65,7 @@ type LayoutDSL struct { // OperationLayoutDSL layout.operation type OperationLayoutDSL struct { Preset map[string]map[string]interface{} `json:"preset,omitempty"` - Actions []component.ActionDSL `json:"actions,omitempty"` + Actions component.Actions `json:"actions,omitempty"` } // FieldsDSL the form fields DSL diff --git a/widgets/models.go b/widgets/models.go new file mode 100644 index 00000000..f547d9d1 --- /dev/null +++ b/widgets/models.go @@ -0,0 +1,40 @@ +package widgets + +import ( + "fmt" + "os" + "strings" + + "github.com/yaoapp/gou" +) + +// Models return loaded models +func Models() []Item { + + models := map[string]interface{}{} + for id, widget := range gou.Models { + + if strings.HasPrefix(id, "xiang.") { + continue + } + + name := fmt.Sprintf("%s.mod.json", strings.ReplaceAll(id, ".", string(os.PathSeparator))) + dsl := fmt.Sprintf("models%s%s.mod.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) + models[name] = map[string]interface{}{ + "DSL": dsl, + "ID": id, + "connector": widget.MetaData.Connector, + "table": widget.MetaData.Table, + "columns": widget.MetaData.Columns, + "indexes": widget.MetaData.Indexes, + "values": widget.MetaData.Values, + "option": widget.MetaData.Option, + "relations": widget.MetaData.Relations, + } + } + + grouping := Grouping(models) + items := Array(grouping, []Item{}) + Sort(items, []string{}) + return items +} diff --git a/widgets/process.go b/widgets/process.go index 2c49d81f..3a7c99c9 100644 --- a/widgets/process.go +++ b/widgets/process.go @@ -6,7 +6,9 @@ import ( // WidgetHandlers Processes var WidgetHandlers = map[string]gou.ProcessHandler{ - "apis": processApis, + "apis": processApis, + "actions": processActions, + "models": processModels, } func init() { @@ -19,11 +21,14 @@ func processApis(process *gou.Process) interface{} { } // Get the actions of each widget -func processActions() { +func processActions(process *gou.Process) interface{} { + return Actions() } // Get the loaded Models -func processModels() {} +func processModels(process *gou.Process) interface{} { + return Models() +} // Get the loaded flows func processFlows() {} diff --git a/widgets/process_test.go b/widgets/process_test.go index ff80a03b..83010a4b 100644 --- a/widgets/process_test.go +++ b/widgets/process_test.go @@ -18,6 +18,26 @@ func TestProcessApis(t *testing.T) { assert.Greater(t, len(res.([]Item)), 0) } +func TestProcessActions(t *testing.T) { + testData(t) + args := []interface{}{} + res, err := gou.NewProcess("widget.actions", args...).Exec() + if err != nil { + t.Fatal(err) + } + assert.Greater(t, len(res.([]Item)), 0) +} + +func TestProcessModels(t *testing.T) { + testData(t) + args := []interface{}{} + res, err := gou.NewProcess("widget.models", args...).Exec() + if err != nil { + t.Fatal(err) + } + assert.Greater(t, len(res.([]Item)), 0) +} + func testData(t *testing.T) { prepare(t) err := Load(config.Conf) diff --git a/widgets/table/table.go b/widgets/table/table.go index dce00bcb..12c79f95 100644 --- a/widgets/table/table.go +++ b/widgets/table/table.go @@ -294,3 +294,50 @@ func (dsl *DSL) Xgen() (map[string]interface{}, error) { setting["name"] = dsl.Name return setting, nil } + +// Actions get the table actions +func (dsl *DSL) Actions() []component.ActionsExport { + + res := []component.ActionsExport{} + + // 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 { + + res = append(res, component.ActionsExport{ + Type: "import", + Xpath: "layout.header.preset.import.actions", + Actions: dsl.Layout.Header.Preset.Import.Actions.Hash(), + }) + } + + // layout.filter.actions + if dsl.Layout != nil && + dsl.Layout.Filter != nil && + dsl.Layout.Filter.Actions != nil && + len(dsl.Layout.Filter.Actions) > 0 { + res = append(res, component.ActionsExport{ + Type: "filter", + Xpath: "layout.filter.actions", + Actions: dsl.Layout.Filter.Actions.Hash(), + }) + } + + // 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 { + res = append(res, component.ActionsExport{ + Type: "operation", + Xpath: "layout.table.operation.actions", + Actions: dsl.Layout.Table.Operation.Actions.Hash(), + }) + } + + return res +} diff --git a/widgets/table/types.go b/widgets/table/types.go index 41c089ce..7312aba8 100644 --- a/widgets/table/types.go +++ b/widgets/table/types.go @@ -103,8 +103,8 @@ type BatchPresetDSL struct { // ImportPresetDSL layout.header.preset.import type ImportPresetDSL struct { - Name string `json:"name,omitempty"` - Actions []component.ActionDSL `json:"actions,omitempty"` + Name string `json:"name,omitempty"` + Actions component.Actions `json:"actions,omitempty"` } // FilterLayoutDSL layout.filter