commit
c3b5242f52
6 changed files with 387 additions and 0 deletions
1
widgets/action.go
Normal file
1
widgets/action.go
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
package widgets
|
||||||
231
widgets/api.go
Normal file
231
widgets/api.go
Normal file
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
89
widgets/item.go
Normal file
89
widgets/item.go
Normal file
|
|
@ -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
|
||||||
|
}
|
||||||
32
widgets/process.go
Normal file
32
widgets/process.go
Normal file
|
|
@ -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() {}
|
||||||
27
widgets/process_test.go
Normal file
27
widgets/process_test.go
Normal file
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/yaoapp/yao/api"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/i18n"
|
"github.com/yaoapp/yao/i18n"
|
||||||
"github.com/yaoapp/yao/model"
|
"github.com/yaoapp/yao/model"
|
||||||
|
|
@ -42,4 +43,10 @@ func prepare(t *testing.T, language ...string) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load apis
|
||||||
|
err = api.Load(config.Conf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue