commit
0f781ad059
8 changed files with 302 additions and 39 deletions
|
|
@ -212,7 +212,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "operation",
|
||||
Xpath: "layout.operation.actions",
|
||||
Actions: dsl.Layout.Operation.Actions.Hash(),
|
||||
Actions: dsl.Layout.Operation.Actions,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "filter",
|
||||
Xpath: "layout.filter.actions",
|
||||
Actions: dsl.Layout.Filter.Actions.Hash(),
|
||||
Actions: dsl.Layout.Filter.Actions,
|
||||
})
|
||||
}
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -3,13 +3,127 @@ package component
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"golang.org/x/crypto/md4"
|
||||
)
|
||||
|
||||
// UnmarshalJSON for json UnmarshalJSON
|
||||
func (action *ActionDSL) UnmarshalJSON(data []byte) error {
|
||||
var alias aliasActionDSL
|
||||
err := jsoniter.Unmarshal(data, &alias)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*action = ActionDSL(alias)
|
||||
action.ID, err = action.Hash()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if action.Action == nil {
|
||||
action.Action = ActionNodes{}
|
||||
}
|
||||
|
||||
err = action.Action.Parse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON for json UnmarshalJSON
|
||||
func (nodes *ActionNodes) UnmarshalJSON(data []byte) error {
|
||||
|
||||
var alias interface{}
|
||||
err := jsoniter.Unmarshal(data, &alias)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch values := alias.(type) {
|
||||
|
||||
case string: // "Actions.test.back"
|
||||
*nodes = ActionNodes{{
|
||||
"name": values,
|
||||
"type": values,
|
||||
"payload": map[string]interface{}{},
|
||||
}}
|
||||
return nil
|
||||
|
||||
case map[string]interface{}: // {"Form.delete": { "pathname": "/x/Table/env" }}
|
||||
node := ActionNode{}
|
||||
for name, payload := range values {
|
||||
node["name"] = name
|
||||
node["type"] = name
|
||||
node["payload"] = payload
|
||||
break
|
||||
}
|
||||
*nodes = ActionNodes{node}
|
||||
return nil
|
||||
|
||||
case []interface{}, []map[string]interface{}: // [{ "name": "Save", "type": "Form.save", "payload": { "id": ":id", "status": "cured" }}]
|
||||
new := aliasActionNodes{}
|
||||
err := jsoniter.Unmarshal(data, &new)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*nodes = ActionNodes(new)
|
||||
return nil
|
||||
|
||||
// case []ActionNode:
|
||||
// *nodes = ActionNodes(values)
|
||||
// return nil
|
||||
|
||||
// case ActionNodes:
|
||||
// *nodes = values
|
||||
// return nil
|
||||
|
||||
// case *ActionNodes:
|
||||
// nodes = values
|
||||
// return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("the format does not support. %s", string(data))
|
||||
}
|
||||
|
||||
// MarshalJSON for json MarshalJSON
|
||||
// func (nodes ActionNodes) MarshalJSON() ([]byte, error) {
|
||||
// return nil, nil
|
||||
// }
|
||||
|
||||
// Parse the custom nodes
|
||||
func (nodes *ActionNodes) Parse() error {
|
||||
for i := range *nodes {
|
||||
// merge the developer-defined actions
|
||||
if (*nodes)[i].Custom() {
|
||||
// (*nodes)[i]["custom"] = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Custom check if the action node is custom
|
||||
func (node ActionNode) Custom() bool {
|
||||
if name, ok := node["type"].(string); ok && strings.HasPrefix(strings.ToLower(name), "actions.") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Hash hash value
|
||||
func (action ActionDSL) Hash() (string, error) {
|
||||
h := md4.New()
|
||||
origin := fmt.Sprintf("%#v", action.Action)
|
||||
// fmt.Println(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 {
|
||||
|
|
@ -17,24 +131,3 @@ func (actions Actions) SetPath(root string) Actions {
|
|||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
// Hash hash value
|
||||
func (actions Actions) Hash() Actions {
|
||||
h := md4.New()
|
||||
for i := range actions {
|
||||
keys := []string{}
|
||||
for i, value := range actions[i].Action {
|
||||
key := fmt.Sprintf("%d", i)
|
||||
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
|
||||
}
|
||||
|
|
|
|||
163
widgets/component/action_test.go
Normal file
163
widgets/component/action_test.go
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package component
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestActionUnmarshalJSON(t *testing.T) {
|
||||
|
||||
data := testActionData()
|
||||
var action ActionDSL
|
||||
err := jsoniter.Unmarshal(data["one"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
|
||||
action = ActionDSL{}
|
||||
err = jsoniter.Unmarshal(data["many"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Len(t, action.Action, 2)
|
||||
assert.Equal(t, "Save", action.Action[0]["name"])
|
||||
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)
|
||||
|
||||
action = ActionDSL{}
|
||||
err = jsoniter.Unmarshal(data["flow"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assert.Len(t, action.Action, 2)
|
||||
assert.Equal(t, "Save", action.Action[0]["name"])
|
||||
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)
|
||||
|
||||
action = ActionDSL{}
|
||||
err = jsoniter.Unmarshal(data["sugar-string"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
|
||||
action = ActionDSL{}
|
||||
err = jsoniter.Unmarshal(data["sugar-map"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
|
||||
action = ActionDSL{}
|
||||
err = jsoniter.Unmarshal(data["sugar-map-custom"], &action)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
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)
|
||||
|
||||
}
|
||||
|
||||
// testActionData
|
||||
func testActionData() map[string][]byte {
|
||||
|
||||
return map[string][]byte{
|
||||
"one": []byte(`{
|
||||
"title": "Delete",
|
||||
"icon": "icon-trash-2",
|
||||
"style": "danger",
|
||||
"action": [
|
||||
{
|
||||
"name": "Delete",
|
||||
"type": "Form.delete",
|
||||
"payload": { "pathname": "/x/Table/env", "foo":"bar", "hello":"world" }
|
||||
}
|
||||
],
|
||||
"confirm": { "title": "Tips", "desc": "Delete Confirm" }
|
||||
}`),
|
||||
|
||||
"many": []byte(`{
|
||||
"title": "Cured",
|
||||
"icon": "icon-check",
|
||||
"style": "success",
|
||||
"action": [
|
||||
{
|
||||
"name": "Save",
|
||||
"type": "Form.save",
|
||||
"payload": { "id": ":id", "status": "cured" }
|
||||
},
|
||||
{
|
||||
"name": "historyPush",
|
||||
"type": "Common.historyPush",
|
||||
"payload": { "pathname": "/x/Form/pet/:id/edit" }
|
||||
}
|
||||
],
|
||||
"confirm": { "title": "Tips", "desc": "Cured Confirm" }
|
||||
}`),
|
||||
|
||||
"flow": []byte(`{
|
||||
"title": "Delete",
|
||||
"icon": "icon-trash-2",
|
||||
"style": "danger",
|
||||
"action": [
|
||||
{
|
||||
"name": "Save",
|
||||
"type": "Form.save",
|
||||
"payload": { "id": ":id", "status": "cured" }
|
||||
},
|
||||
{
|
||||
"name": "Flow",
|
||||
"type": "Actions.test.check",
|
||||
"payload": { "pathname": "/x/Form/pet/:id/edit" }
|
||||
}
|
||||
],
|
||||
"confirm": { "title": "Tips", "desc": "Delete Confirm" }
|
||||
}`),
|
||||
|
||||
"sugar-string": []byte(`{
|
||||
"title": "Delete",
|
||||
"icon": "icon-trash-2",
|
||||
"style": "danger",
|
||||
"action": "Actions.test.back",
|
||||
"confirm": { "title": "Tips", "desc": "Delete Confirm" }
|
||||
}`),
|
||||
|
||||
"sugar-map": []byte(`{
|
||||
"title": "Delete",
|
||||
"icon": "icon-trash-2",
|
||||
"style": "danger",
|
||||
"action": {
|
||||
"Form.delete": { "pathname": "/x/Table/env" }
|
||||
},
|
||||
"confirm": { "title": "Tips", "desc": "Delete Confirm" }
|
||||
}`),
|
||||
|
||||
"sugar-map-custom": []byte(`{
|
||||
"title": "Delete",
|
||||
"icon": "icon-trash-2",
|
||||
"style": "danger",
|
||||
"action": {
|
||||
"Actions.test.back": { "pathname": "/x/Table/env" }
|
||||
},
|
||||
"confirm": { "title": "Tips", "desc": "Delete Confirm" }
|
||||
}`),
|
||||
}
|
||||
}
|
||||
|
|
@ -28,19 +28,29 @@ type ActionsExport struct {
|
|||
Actions Actions `json:"actions,omitempty"`
|
||||
}
|
||||
|
||||
type aliasActionDSL ActionDSL
|
||||
|
||||
// ActionDSL the component action DSL
|
||||
type ActionDSL struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
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 []ParamsDSL `json:"action,omitempty"`
|
||||
Action ActionNodes `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
type aliasActionNodes []ActionNode
|
||||
|
||||
// ActionNodes the action nodes
|
||||
type ActionNodes []ActionNode
|
||||
|
||||
// ActionNode the action node
|
||||
type ActionNode map[string]interface{}
|
||||
|
||||
// ConfirmActionDSL action.confirm
|
||||
type ConfirmActionDSL struct {
|
||||
Title string `json:"title,omitempty"`
|
||||
|
|
@ -50,9 +60,6 @@ type ConfirmActionDSL struct {
|
|||
// PropsDSL component props
|
||||
type PropsDSL map[string]interface{}
|
||||
|
||||
// ParamsDSL action params
|
||||
type ParamsDSL map[string]interface{}
|
||||
|
||||
// Compute process
|
||||
type Compute struct {
|
||||
Process string `json:"process"`
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "operation",
|
||||
Xpath: "layout.operation.actions",
|
||||
Actions: dsl.Layout.Actions.Hash(),
|
||||
Actions: dsl.Layout.Actions,
|
||||
})
|
||||
}
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, formID string, fields *FieldsDS
|
|||
Title: "::Delete",
|
||||
Icon: "icon-trash-2",
|
||||
Style: "danger",
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "Delete",
|
||||
"type": "Form.delete",
|
||||
|
|
@ -97,7 +97,7 @@ func (layout *LayoutDSL) BindTable(tab *table.DSL, formID string, fields *Fields
|
|||
Title: "::Delete",
|
||||
Icon: "icon-trash-2",
|
||||
Style: "danger",
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "Delete",
|
||||
"type": "Form.delete",
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL, option map[s
|
|||
Title: "::Create",
|
||||
Icon: "icon-plus",
|
||||
Width: 3,
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "HistoryPush",
|
||||
"type": "Common.historyPush",
|
||||
|
|
@ -82,7 +82,7 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL, option map[s
|
|||
component.ActionDSL{
|
||||
Title: "::View",
|
||||
Icon: "icon-eye",
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "OpenModal",
|
||||
"type": "Common.openModal",
|
||||
|
|
@ -99,7 +99,7 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL, option map[s
|
|||
component.ActionDSL{
|
||||
Title: "::Edit",
|
||||
Icon: "icon-edit-2",
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "OpenModal",
|
||||
"type": "Common.openModal",
|
||||
|
|
@ -117,7 +117,7 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL, option map[s
|
|||
Title: "::Delete",
|
||||
Icon: "icon-trash-2",
|
||||
Style: "danger",
|
||||
Action: []component.ParamsDSL{
|
||||
Action: component.ActionNodes{
|
||||
{
|
||||
"name": "Delete",
|
||||
"type": "Table.delete",
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "import",
|
||||
Xpath: "layout.header.preset.import.actions",
|
||||
Actions: dsl.Layout.Header.Preset.Import.Actions.Hash(),
|
||||
Actions: dsl.Layout.Header.Preset.Import.Actions,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +323,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "filter",
|
||||
Xpath: "layout.filter.actions",
|
||||
Actions: dsl.Layout.Filter.Actions.Hash(),
|
||||
Actions: dsl.Layout.Filter.Actions,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +335,7 @@ func (dsl *DSL) Actions() []component.ActionsExport {
|
|||
res = append(res, component.ActionsExport{
|
||||
Type: "operation",
|
||||
Xpath: "layout.table.operation.actions",
|
||||
Actions: dsl.Layout.Table.Operation.Actions.Hash(),
|
||||
Actions: dsl.Layout.Table.Operation.Actions,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue