forked from YaoApp/yao
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
387 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package widgets |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
package widgets | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/yaoapp/gou" | ||
"github.com/yaoapp/yao/widgets/chart" | ||
"github.com/yaoapp/yao/widgets/form" | ||
"github.com/yaoapp/yao/widgets/list" | ||
"github.com/yaoapp/yao/widgets/table" | ||
) | ||
|
||
// Apis return loaded apis | ||
func Apis() []Item { | ||
apis := map[string]interface{}{} | ||
userApis(apis) | ||
tableApis(apis) | ||
formApis(apis) | ||
listApis(apis) | ||
chartApis(apis) | ||
|
||
grouping := Grouping(apis) | ||
items := Array(grouping, []Item{}) | ||
Sort(items, []string{"apis", "tables", "forms", "lists", "charts"}) | ||
return items | ||
} | ||
|
||
func userApis(apis map[string]interface{}) { | ||
|
||
// Name string `json:"name"` | ||
// Version string `json:"version"` | ||
// Description string `json:"description,omitempty"` | ||
// Group string `json:"group,omitempty"` | ||
// Guard string `json:"guard,omitempty"` | ||
// Paths []Path `json:"paths,omitempty"` | ||
for group, api := range gou.APIs { | ||
if strings.HasPrefix(group, "widgets") { | ||
continue | ||
} | ||
|
||
// Label string `json:"label,omitempty"` | ||
// Description string `json:"description,omitempty"` | ||
// Path string `json:"path"` | ||
// Method string `json:"method"` | ||
// Process string `json:"process"` | ||
// Guard string `json:"guard,omitempty"` | ||
// In []string `json:"in,omitempty"` | ||
// Out Out `json:"out,omitempty"` | ||
paths := []map[string]interface{}{} | ||
for _, path := range api.HTTP.Paths { | ||
guard := path.Guard | ||
if guard == "" { | ||
guard = api.HTTP.Guard | ||
} | ||
fullpath := fmt.Sprintf("/apis/%s%s", api.HTTP.Group, path.Path) | ||
paths = append(paths, map[string]interface{}{ | ||
"name": path.Label, | ||
"description": path.Description, | ||
"guard": guard, | ||
"method": path.Method, | ||
"path": path.Path, | ||
"router": fullpath, | ||
"fullpath": fullpath, | ||
"in": path.In, | ||
"out": path.Out, | ||
"process": path.Process, | ||
"params": map[string]interface{}{}, | ||
}) | ||
} | ||
|
||
dsl := fmt.Sprintf("apis%s%s.http.json", string(os.PathSeparator), strings.ReplaceAll(group, ".", string(os.PathSeparator))) | ||
apis[dsl] = map[string]interface{}{ | ||
"DSL": dsl, | ||
"name": api.HTTP.Name, | ||
"version": api.HTTP.Version, | ||
"group": fmt.Sprintf("/%s", api.HTTP.Group), | ||
"guard": api.HTTP.Guard, | ||
"description": api.HTTP.Description, | ||
"paths": paths, | ||
} | ||
} | ||
} | ||
|
||
func tableApis(apis map[string]interface{}) { | ||
|
||
api, has := gou.APIs["widgets.table"] | ||
if !has { | ||
return | ||
} | ||
|
||
for id, widget := range table.Tables { | ||
dsl := fmt.Sprintf("tables%s%s.tab.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) | ||
groupGuard := "bearer-jwt" | ||
pathGuards := []map[string]string{ | ||
{"name": "/:id/search", "guard": widget.Action.Search.Guard}, | ||
{"name": "/:id/get", "guard": widget.Action.Get.Guard}, | ||
{"name": "/:id/find/:primary", "guard": widget.Action.Find.Guard}, | ||
{"name": "/:id/save", "guard": widget.Action.Save.Guard}, | ||
{"name": "/:id/create", "guard": widget.Action.Create.Guard}, | ||
{"name": "/:id/insert", "guard": widget.Action.Insert.Guard}, | ||
{"name": "/:id/update/:primary", "guard": widget.Action.Update.Guard}, | ||
{"name": "/:id/update/in", "guard": widget.Action.UpdateIn.Guard}, | ||
{"name": "/:id/update/where", "guard": widget.Action.UpdateWhere.Guard}, | ||
{"name": "/:id/delete/:primary", "guard": widget.Action.Delete.Guard}, | ||
{"name": "/:id/delete/in", "guard": widget.Action.DeleteIn.Guard}, | ||
{"name": "/:id/delete/where", "guard": widget.Action.DeleteWhere.Guard}, | ||
{"name": "/:id/upload/:xpath/:method", "guard": widget.Action.Upload.Guard}, | ||
{"name": "/:id/download/:field", "guard": widget.Action.Download.Guard}, | ||
} | ||
widgetApis(apis, api, id, dsl, groupGuard, pathGuards) | ||
} | ||
} | ||
|
||
func formApis(apis map[string]interface{}) { | ||
|
||
api, has := gou.APIs["widgets.form"] | ||
if !has { | ||
return | ||
} | ||
|
||
for id, widget := range form.Forms { | ||
dsl := fmt.Sprintf("forms%s%s.form.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) | ||
groupGuard := "bearer-jwt" | ||
pathGuards := []map[string]string{ | ||
{"name": "/:id/find/:primary", "guard": widget.Action.Find.Guard}, | ||
{"name": "/:id/save", "guard": widget.Action.Save.Guard}, | ||
{"name": "/:id/create", "guard": widget.Action.Create.Guard}, | ||
{"name": "/:id/update/:primary", "guard": widget.Action.Update.Guard}, | ||
{"name": "/:id/delete/:primary", "guard": widget.Action.Delete.Guard}, | ||
{"name": "/:id/upload/:xpath/:method", "guard": widget.Action.Upload.Guard}, | ||
{"name": "/:id/download/:field", "guard": widget.Action.Download.Guard}, | ||
} | ||
widgetApis(apis, api, id, dsl, groupGuard, pathGuards) | ||
} | ||
} | ||
|
||
func listApis(apis map[string]interface{}) { | ||
|
||
api, has := gou.APIs["widgets.list"] | ||
if !has { | ||
return | ||
} | ||
|
||
for id, widget := range list.Lists { | ||
dsl := fmt.Sprintf("lists%s%s.list.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) | ||
groupGuard := "bearer-jwt" | ||
pathGuards := []map[string]string{ | ||
{"name": "/:id/get", "guard": widget.Action.Get.Guard}, | ||
{"name": "/:id/save", "guard": widget.Action.Save.Guard}, | ||
{"name": "/:id/upload/:xpath/:method", "guard": widget.Action.Upload.Guard}, | ||
{"name": "/:id/download/:field", "guard": widget.Action.Download.Guard}, | ||
} | ||
widgetApis(apis, api, id, dsl, groupGuard, pathGuards) | ||
} | ||
} | ||
|
||
func chartApis(apis map[string]interface{}) { | ||
|
||
api, has := gou.APIs["widgets.chart"] | ||
if !has { | ||
return | ||
} | ||
|
||
for id, widget := range chart.Charts { | ||
dsl := fmt.Sprintf("charts%s%s.chart.json", string(os.PathSeparator), strings.ReplaceAll(id, ".", string(os.PathSeparator))) | ||
groupGuard := "bearer-jwt" | ||
pathGuards := []map[string]string{ | ||
{"name": "/:id/data", "guard": widget.Action.Data.Guard}, | ||
} | ||
widgetApis(apis, api, id, dsl, groupGuard, pathGuards) | ||
} | ||
} | ||
|
||
func widgetApis(apis map[string]interface{}, api *gou.API, widgetID string, dsl string, groupGuard string, pathGuards []map[string]string) { | ||
|
||
pathMapping := map[string]gou.Path{} | ||
for _, path := range api.HTTP.Paths { | ||
pathMapping[path.Path] = path | ||
} | ||
|
||
// Label string `json:"label,omitempty"` | ||
// Description string `json:"description,omitempty"` | ||
// Path string `json:"path"` | ||
// Method string `json:"method"` | ||
// Process string `json:"process"` | ||
// Guard string `json:"guard,omitempty"` | ||
// In []string `json:"in,omitempty"` | ||
// Out Out `json:"out,omitempty"` | ||
paths := []map[string]interface{}{} | ||
for _, pathGuard := range pathGuards { | ||
|
||
name := pathGuard["name"] | ||
guard := pathGuard["guard"] | ||
|
||
path, has := pathMapping[name] | ||
if !has { | ||
continue | ||
} | ||
|
||
if guard == "" { | ||
guard = groupGuard | ||
} | ||
|
||
fullpath := fmt.Sprintf("/apis/%s%s", api.HTTP.Group, path.Path) | ||
paths = append(paths, map[string]interface{}{ | ||
"name": path.Label, | ||
"description": path.Description, | ||
"guard": guard, | ||
"method": path.Method, | ||
"path": path.Path, | ||
"fullpath": fullpath, | ||
"router": strings.ReplaceAll(fullpath, ":id", widgetID), | ||
"in": path.In, | ||
"out": path.Out, | ||
"process": path.Process, | ||
"params": map[string]interface{}{"id": widgetID}, | ||
}) | ||
} | ||
|
||
apis[dsl] = map[string]interface{}{ | ||
"DSL": dsl, | ||
"name": api.HTTP.Name, | ||
"version": api.HTTP.Version, | ||
"group": fmt.Sprintf("/%s", api.HTTP.Group), | ||
"guard": groupGuard, | ||
"description": api.HTTP.Description, | ||
"paths": paths, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package widgets | ||
|
||
import ( | ||
"os" | ||
"sort" | ||
"strings" | ||
) | ||
|
||
// Item the item | ||
type Item struct { | ||
Name string `json:"name,omitempty"` | ||
Data interface{} `json:"data,omitempty"` | ||
Children []Item `json:"children,omitempty"` | ||
} | ||
|
||
// Sort items | ||
func Sort(items []Item, orders []string) { | ||
|
||
rank := map[string]int{} | ||
if orders != nil { | ||
for i, name := range orders { | ||
rank[name] = i | ||
} | ||
} | ||
|
||
sort.Slice(items, func(i, j int) bool { | ||
rankI, hasI := rank[items[i].Name] | ||
rankJ, hasJ := rank[items[j].Name] | ||
if hasI && hasJ { | ||
return rankI < rankJ | ||
} | ||
return strings.Compare(items[i].Name, items[j].Name) < 0 | ||
}) | ||
|
||
// Sort Children | ||
for i := range items { | ||
if len(items[i].Children) > 0 { | ||
Sort(items[i].Children, nil) | ||
} | ||
} | ||
|
||
} | ||
|
||
// Grouping by name | ||
func Grouping(items map[string]interface{}) map[string]interface{} { | ||
grouping := map[string]interface{}{} | ||
for name, item := range items { | ||
paths := strings.Split(name, string(os.PathSeparator)) | ||
node := grouping | ||
for _, path := range paths { | ||
if strings.HasSuffix(path, ".json") { | ||
node[path] = Item{Name: path, Data: item, Children: []Item{}} | ||
continue | ||
} | ||
if _, has := node[path]; !has { | ||
node[path] = map[string]interface{}{"name": path, "data": map[string]interface{}{}} | ||
} | ||
node = node[path].(map[string]interface{}) | ||
} | ||
} | ||
return grouping | ||
} | ||
|
||
// Array to Array | ||
func Array(groupingItems map[string]interface{}, res []Item) []Item { | ||
|
||
for key, item := range groupingItems { | ||
|
||
switch it := item.(type) { | ||
|
||
case map[string]interface{}: // Path | ||
if it["name"] == nil { | ||
break | ||
} | ||
res = append(res, Item{ | ||
Name: key, | ||
Data: nil, | ||
Children: Array(it, []Item{}), | ||
}) | ||
break | ||
|
||
case Item: // Data | ||
res = append(res, it) | ||
break | ||
} | ||
} | ||
|
||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package widgets | ||
|
||
import ( | ||
"github.com/yaoapp/gou" | ||
) | ||
|
||
// WidgetHandlers Processes | ||
var WidgetHandlers = map[string]gou.ProcessHandler{ | ||
"apis": processApis, | ||
} | ||
|
||
func init() { | ||
gou.RegisterProcessGroup("widget", WidgetHandlers) | ||
} | ||
|
||
// Get the loaded APIs | ||
func processApis(process *gou.Process) interface{} { | ||
return Apis() | ||
} | ||
|
||
// Get the actions of each widget | ||
func processActions() { | ||
} | ||
|
||
// Get the loaded Models | ||
func processModels() {} | ||
|
||
// Get the loaded flows | ||
func processFlows() {} | ||
|
||
// Get the loaded Models | ||
func processScripts() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package widgets | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/yaoapp/gou" | ||
"github.com/yaoapp/yao/config" | ||
) | ||
|
||
func TestProcessApis(t *testing.T) { | ||
testData(t) | ||
args := []interface{}{} | ||
res, err := gou.NewProcess("widget.apis", 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) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} |
Oops, something went wrong.