yao/widgets/component/action.go

144 lines
3 KiB
Go

package component
import (
"fmt"
"io"
"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("ACTION::%#v", action.Action)
// fmt.Println("Origin:", origin)
io.WriteString(h, origin)
return fmt.Sprintf("%x", h.Sum(nil)), nil
}
// 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 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
// }