forked from entkit/entkit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
actions.go
194 lines (176 loc) · 5.57 KB
/
actions.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package entkit
import (
"strings"
)
// Action item related action
type Action struct {
Name *string `json:"Name,omitempty"` // Name of action (Required)
General *bool `json:"General,omitempty"` // Mark action as general (independent of record) (e.g. create, list)
Scope *string `json:"Scope,omitempty"` // Scope of resource authorization
Props *map[string]any `json:"Props,omitempty"` // Props are directly passing to react component
CustomComponent *string `json:"CustomComponent,omitempty"` // Custom component TODO: custom component
Description *string `json:"Description,omitempty"` // Description of action
Label *string `json:"Label,omitempty"` // Label of button
Icon *string `json:"Icon,omitempty"` // Icon of button
OnList *bool `json:"OnList,omitempty"` // Display on list
OnShow *bool `json:"OnShow,omitempty"` // Display on show
OnEdit *bool `json:"OnEdit,omitempty"` // Display on edit
OnCreate *bool `json:"OnCreate,omitempty"` // Display on edit
DisplayOn []string `json:"DisplayOn,omitempty"`
Route *Route `json:"Route,omitempty"` // Route of action
Operation *Operation `json:"Operation,omitempty"` // Operation of action
}
var (
// ListAction standard list action
ListAction = NewAction(
"list",
ActionAsGeneral(),
ActionWithLabel("List"),
ActionWithScope(ActionReadScope),
ActionWithIcon("AntdIcons.UnorderedListOutlined"),
ActionDisplayOn("show", "edgesDiagram"),
ActionWithRoute(NewRoute("/", "List.{name}List", RouteAsIndex())),
)
// EditAction standard edit action
EditAction = NewAction(
"edit",
ActionWithLabel("Edit"),
ActionWithScope(ActionUpdateScope),
ActionWithRoute(NewRoute("edit/:id", "Edit.{name}Edit")),
ActionWithIcon("AntdIcons.EditOutlined"),
ActionDisplayOn("list", "show", "edgesDiagram"),
)
// CreateAction standard create action
CreateAction = NewAction(
"create",
ActionAsGeneral(),
ActionWithLabel("Create"),
ActionWithScope(ActionCreateScope),
ActionWithIcon("AntdIcons.PlusCircleOutlined"),
ActionWithRoute(NewRoute("create", "Create.{name}Create")),
ActionDisplayOn("list"),
)
// ShowAction standard show action
ShowAction = NewAction(
"show",
ActionWithLabel("Show"),
ActionWithScope(ActionReadScope),
ActionWithIcon("AntdIcons.EyeOutlined"),
ActionWithRoute(NewRoute("show/:id", "Show.{name}MainShow")),
ActionDisplayOn("list", "edit", "edgesDiagram"),
)
// DeleteAction standard delete action
DeleteAction = NewAction(
"delete",
ActionWithLabel("Delete"),
ActionWithScope(ActionDeleteScope),
ActionWithIcon("AntdIcons.DeleteOutlined"),
ActionWithProps(map[string]any{
"danger": true,
}),
ActionDisplayOn("list", "show", "edgesDiagram"),
ActionWithOperation(NewOperation(
"delete",
OperationAsBulk(),
OperationAsMutation(),
)),
)
// EdgesDiagramAction edges diagram action (optional)
EdgesDiagramAction = NewAction(
"edgesDiagram",
ActionWithLabel("Edges Diagram"),
ActionWithScope(ActionReadScope),
ActionWithIcon("AntdIcons.ClusterOutlined"),
ActionWithRoute(NewRoute("edges/:id", "EdgesDiagram.{name}EdgesDiagram")),
ActionDisplayOn("show", "edit"),
)
DefaultActions = []*Action{
ShowAction, ListAction, CreateAction, EditAction, DeleteAction,
}
)
type ActionOption = func(*Action) error
func NewAction(name string, options ...ActionOption) *Action {
action := &Action{
Name: StringP(name),
}
for _, opt := range options {
if err := opt(action); err != nil {
panic(err)
}
}
if action.Scope == nil {
action.Scope = action.Name
}
return action
}
// region Options
func ActionWithLabel(label string) ActionOption {
return func(ac *Action) (err error) {
ac.Label = StringP(label)
return nil
}
}
func ActionWithRoute(route *Route) ActionOption {
return func(ac *Action) (err error) {
if ac.Operation != nil {
panic("Error: `operation` already set. One of `operation` and `route` should be defined.")
}
if !PBool(ac.General) && !strings.Contains(*route.Path, "/:id") {
panic("Not general actions routes must have a `:id` on path")
}
ac.Route = route
return nil
}
}
func ActionWithOperation(operation *Operation) ActionOption {
return func(ac *Action) (err error) {
if ac.Route != nil {
panic("Error: `route` already set. One of `operation` and `route` should be defined.")
}
ac.Operation = operation
return nil
}
}
func ActionWithIcon(icon string) ActionOption {
return func(ac *Action) (err error) {
ac.Icon = StringP(icon)
return nil
}
}
func WithDescription(description string) ActionOption {
return func(ac *Action) (err error) {
ac.Description = StringP(description)
return nil
}
}
func ActionWithScope(scope string) ActionOption {
return func(ac *Action) (err error) {
ac.Scope = StringP(scope)
return nil
}
}
func ActionWithProps(props map[string]any) ActionOption {
return func(ac *Action) (err error) {
ac.Props = &props
return nil
}
}
func WithCustomComponent(component string) ActionOption {
return func(ac *Action) (err error) {
ac.CustomComponent = StringP(component)
return nil
}
}
func ActionDisplayOn(actionNames ...string) ActionOption {
return func(ac *Action) (err error) {
ac.DisplayOn = actionNames
return nil
}
}
func ActionAsGeneral() ActionOption {
return func(ac *Action) (err error) {
ac.General = BoolP(true)
return nil
}
}
// endregion options