Merge pull request #188 from trheyi/main

[add] widget table bind table support
This commit is contained in:
Max 2022-10-07 11:57:03 +08:00 committed by GitHub
commit d7d723bae7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 270 additions and 63 deletions

View file

@ -6,6 +6,20 @@ import (
"github.com/yaoapp/gou" "github.com/yaoapp/gou"
) )
// CopyBefore copy a before hook
func CopyBefore(hook *Before, new *Before) {
if hook != nil {
*hook = *new
}
}
// CopyAfter copy a after hook
func CopyAfter(hook *After, new *After) {
if hook != nil {
*hook = *new
}
}
// Exec execute the hook // Exec execute the hook
func (hook *Before) Exec(args []interface{}, sid string, global map[string]interface{}) ([]interface{}, error) { func (hook *Before) Exec(args []interface{}, sid string, global map[string]interface{}) ([]interface{}, error) {

View file

@ -8,6 +8,7 @@ import (
"github.com/yaoapp/kun/log" "github.com/yaoapp/kun/log"
"github.com/yaoapp/kun/maps" "github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/widgets/action" "github.com/yaoapp/yao/widgets/action"
"github.com/yaoapp/yao/widgets/hook"
) )
var processActionDefaults = map[string]*action.Process{ var processActionDefaults = map[string]*action.Process{
@ -159,7 +160,7 @@ func (act *ActionDSL) SetDefaultProcess() {
} }
// BindModel bind model // BindModel bind model
func (act *ActionDSL) BindModel(m *gou.Model) { func (act *ActionDSL) BindModel(m *gou.Model) error {
name := m.ID name := m.ID
act.Search.Bind(fmt.Sprintf("models.%s.Paginate", name)) act.Search.Bind(fmt.Sprintf("models.%s.Paginate", name))
@ -181,6 +182,54 @@ func (act *ActionDSL) BindModel(m *gou.Model) {
act.Get.DefaultMerge([]interface{}{act.Bind.Option}) act.Get.DefaultMerge([]interface{}{act.Bind.Option})
act.Find.DefaultMerge([]interface{}{nil, act.Bind.Option}) act.Find.DefaultMerge([]interface{}{nil, act.Bind.Option})
} }
return nil
}
// BindTable bind table
func (act *ActionDSL) BindTable(tab *DSL) error {
// Copy Hooks
hook.CopyBefore(act.BeforeSearch, tab.Action.BeforeSearch)
hook.CopyBefore(act.BeforeGet, tab.Action.BeforeGet)
hook.CopyBefore(act.BeforeFind, tab.Action.BeforeFind)
hook.CopyBefore(act.BeforeSave, tab.Action.BeforeSave)
hook.CopyBefore(act.BeforeCreate, tab.Action.BeforeCreate)
hook.CopyBefore(act.BeforeInsert, tab.Action.BeforeInsert)
hook.CopyBefore(act.BeforeUpdate, tab.Action.BeforeUpdate)
hook.CopyBefore(act.BeforeUpdateWhere, tab.Action.BeforeUpdateWhere)
hook.CopyBefore(act.BeforeUpdateIn, tab.Action.BeforeUpdateIn)
hook.CopyBefore(act.BeforeDelete, tab.Action.BeforeDelete)
hook.CopyBefore(act.BeforeDeleteWhere, tab.Action.BeforeDeleteWhere)
hook.CopyBefore(act.BeforeDeleteIn, tab.Action.BeforeDeleteIn)
hook.CopyAfter(act.AfterSearch, tab.Action.AfterSearch)
hook.CopyAfter(act.AfterGet, tab.Action.AfterGet)
hook.CopyAfter(act.AfterFind, tab.Action.AfterFind)
hook.CopyAfter(act.AfterSave, tab.Action.AfterSave)
hook.CopyAfter(act.AfterCreate, tab.Action.AfterCreate)
hook.CopyAfter(act.AfterInsert, tab.Action.AfterInsert)
hook.CopyAfter(act.AfterUpdate, tab.Action.AfterUpdate)
hook.CopyAfter(act.AfterUpdateWhere, tab.Action.AfterUpdateWhere)
hook.CopyAfter(act.AfterUpdateIn, tab.Action.AfterUpdateIn)
hook.CopyAfter(act.AfterDelete, tab.Action.AfterDelete)
hook.CopyAfter(act.AfterDeleteWhere, tab.Action.AfterDeleteWhere)
hook.CopyAfter(act.AfterDeleteIn, tab.Action.AfterDeleteIn)
// Merge Actions
act.Search.Merge(tab.Action.Search)
act.Get.Merge(tab.Action.Get)
act.Find.Merge(tab.Action.Find)
act.Save.Merge(tab.Action.Save)
act.Create.Merge(tab.Action.Create)
act.Insert.Merge(tab.Action.Insert)
act.Update.Merge(tab.Action.Update)
act.UpdateWhere.Merge(tab.Action.UpdateWhere)
act.UpdateIn.Merge(tab.Action.UpdateIn)
act.Delete.Merge(tab.Action.Delete)
act.DeleteWhere.Merge(tab.Action.DeleteWhere)
act.DeleteIn.Merge(tab.Action.DeleteIn)
return nil
} }
func processHandler(p *action.Process, process *gou.Process) (interface{}, error) { func processHandler(p *action.Process, process *gou.Process) (interface{}, error) {

View file

@ -41,8 +41,57 @@ func (dsl *DSL) bindModel() error {
return err return err
} }
dsl.Action.BindModel(m) err = dsl.Action.BindModel(m)
dsl.Layout.BindModel(m, dsl.Fields) if err != nil {
return err
}
err = dsl.Layout.BindModel(m, dsl.Fields)
if err != nil {
return err
}
return nil
}
func (dsl *DSL) bindTable() error {
// Bind ID
id := dsl.Action.Bind.Table
if id == dsl.ID {
return fmt.Errorf("bind.table %s can't bind self table", id)
}
// Load table
if _, has := Tables[id]; !has {
if err := LoadID(id, dsl.Root); err != nil {
return err
}
}
tab, err := Get(id)
if err != nil {
return err
}
// Bind Fields
err = dsl.Fields.BindTable(tab)
if err != nil {
return err
}
// Bind Actions
err = dsl.Action.BindTable(tab)
if err != nil {
return err
}
// Bind Layout
err = dsl.Layout.BindTable(tab, dsl.Fields)
if err != nil {
return err
}
return nil return nil
} }
@ -50,8 +99,3 @@ func (dsl *DSL) bindStore() error {
id := dsl.Action.Bind.Store id := dsl.Action.Bind.Store
return fmt.Errorf("bind.store %s does not support yet", id) return fmt.Errorf("bind.store %s does not support yet", id)
} }
func (dsl *DSL) bindTable() error {
id := dsl.Action.Bind.Table
return fmt.Errorf("bind.table %s does not support yet", id)
}

View file

@ -41,6 +41,36 @@ func (fields *FieldsDSL) BindModel(m *gou.Model) error {
return nil return nil
} }
// BindTable bind table
func (fields *FieldsDSL) BindTable(tab *DSL) error {
// Bind filter
if fields.Filter == nil || len(fields.Filter) == 0 {
fields.Filter = tab.Fields.Filter
} else if tab.Fields.Filter != nil {
for key, filter := range tab.Fields.Filter {
if _, has := fields.Filter[key]; !has {
fields.Filter[key] = filter
}
}
}
// Bind Table
if fields.Table == nil || len(fields.Table) == 0 {
fields.Table = tab.Fields.Table
} else if tab.Fields.Table != nil {
for key, table := range tab.Fields.Table {
if _, has := fields.Table[key]; !has {
fields.Table[key] = table
}
}
}
return nil
}
// Xgen trans to xgen setting // Xgen trans to xgen setting
func (fields *FieldsDSL) Xgen(layout *LayoutDSL) (map[string]interface{}, error) { func (fields *FieldsDSL) Xgen(layout *LayoutDSL) (map[string]interface{}, error) {
res := map[string]interface{}{} res := map[string]interface{}{}

View file

@ -9,7 +9,7 @@ import (
) )
// BindModel bind model // BindModel bind model
func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL) { func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL) error {
if layout.Primary == "" { if layout.Primary == "" {
layout.Primary = m.PrimaryKey layout.Primary = m.PrimaryKey
@ -50,6 +50,28 @@ func (layout *LayoutDSL) BindModel(m *gou.Model, fields *FieldsDSL) {
} }
} }
return nil
}
// BindTable bind table
func (layout *LayoutDSL) BindTable(tab *DSL, fields *FieldsDSL) error {
if layout.Primary == "" {
layout.Primary = tab.Layout.Primary
}
if layout.Filter == nil && tab.Layout.Filter != nil {
layout.Filter = &FilterLayoutDSL{}
*layout.Filter = *tab.Layout.Filter
}
if layout.Table == nil && tab.Layout.Table != nil {
layout.Table = &ViewLayoutDSL{}
*layout.Table = *tab.Layout.Table
}
return nil
} }
// Xgen trans to Xgen setting // Xgen trans to Xgen setting

View file

@ -91,11 +91,11 @@ func New(id string) *DSL {
// LoadAndExport load table // LoadAndExport load table
func LoadAndExport(cfg config.Config) error { func LoadAndExport(cfg config.Config) error {
err := Load(cfg) err := Export()
if err != nil { if err != nil {
return err return err
} }
return Export() return Load(cfg)
} }
// Load load table // Load load table
@ -104,6 +104,21 @@ func Load(cfg config.Config) error {
return LoadFrom(root, "") return LoadFrom(root, "")
} }
// LoadID load by id
func LoadID(id string, root string) error {
dirs := strings.Split(id, ".")
name := fmt.Sprintf("%s.tab.json", dirs[len(dirs)-1])
elems := []string{root}
elems = append(elems, dirs[0:len(dirs)-1]...)
elems = append(elems, name)
filename := filepath.Join(elems...)
data, err := environment.ReadFile(filename)
if err != nil {
return fmt.Errorf("[%s] root=%s %s", id, root, err.Error())
}
return LoadData(data, id, root)
}
// LoadFrom load from dir // LoadFrom load from dir
func LoadFrom(dir string, prefix string) error { func LoadFrom(dir string, prefix string) error {
@ -115,13 +130,35 @@ func LoadFrom(dir string, prefix string) error {
err := share.Walk(dir, ".json", func(root, filename string) { err := share.Walk(dir, ".json", func(root, filename string) {
id := prefix + share.ID(root, filename) id := prefix + share.ID(root, filename)
data, err := environment.ReadFile(filename) data, err := environment.ReadFile(filename)
dsl := New(id)
err = jsoniter.Unmarshal(data, dsl)
if err != nil { if err != nil {
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error())) messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error()))
return return
} }
err = LoadData(data, id, root)
if err != nil {
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error()))
return
}
})
if len(messages) > 0 {
return fmt.Errorf(strings.Join(messages, ";"))
}
return err
}
// LoadData load table from source
func LoadData(data []byte, id string, root string) error {
dsl := New(id)
dsl.Root = root
err := jsoniter.Unmarshal(data, dsl)
if err != nil {
return fmt.Errorf("[%s] %s", id, err.Error())
}
if dsl.Action == nil { if dsl.Action == nil {
dsl.Action = &ActionDSL{} dsl.Action = &ActionDSL{}
} }
@ -143,22 +180,19 @@ func LoadFrom(dir string, prefix string) error {
// Bind model / store / table / ... // Bind model / store / table / ...
err = dsl.Bind() err = dsl.Bind()
if err != nil { if err != nil {
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error())) return fmt.Errorf("[%s] %s", id, err.Error())
return
} }
// Parse // Parse
err = dsl.Parse() err = dsl.Parse()
if err != nil { if err != nil {
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error())) return fmt.Errorf("[%s] %s", id, err.Error())
return
} }
// Validate // Validate
err = dsl.Validate() err = dsl.Validate()
if err != nil { if err != nil {
messages = append(messages, fmt.Sprintf("[%s] %s", id, err.Error())) return fmt.Errorf("[%s] %s", id, err.Error())
return
} }
// Apply a language pack // Apply a language pack
@ -167,13 +201,7 @@ func LoadFrom(dir string, prefix string) error {
} }
Tables[id] = dsl Tables[id] = dsl
}) return nil
if len(messages) > 0 {
return fmt.Errorf(strings.Join(messages, ";"))
}
return err
} }
// Get table via process or id // Get table via process or id

View file

@ -1,6 +1,7 @@
package table package table
import ( import (
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -17,12 +18,19 @@ import (
func TestLoad(t *testing.T) { func TestLoad(t *testing.T) {
prepare(t) prepare(t)
err := Load(config.Conf) err := Load(config.Conf)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
assert.Equal(t, 4, len(Tables)) assert.Equal(t, 5, len(Tables))
}
func TestLoadID(t *testing.T) {
prepare(t)
err := LoadID("pet", filepath.Join(config.Conf.Root, "tables"))
if err != nil {
t.Fatal(err)
}
} }
func prepare(t *testing.T, language ...string) { func prepare(t *testing.T, language ...string) {

View file

@ -9,6 +9,7 @@ import (
// DSL the table DSL // DSL the table DSL
type DSL struct { type DSL struct {
Root string `json:"-"`
ID string `json:"id,omitempty"` ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"` Name string `json:"name,omitempty"`
Action *ActionDSL `json:"action"` Action *ActionDSL `json:"action"`
@ -67,6 +68,7 @@ type BindActionDSL struct {
Model string `json:"model,omitempty"` // bind model Model string `json:"model,omitempty"` // bind model
Store string `json:"store,omitempty"` // bind store Store string `json:"store,omitempty"` // bind store
Table string `json:"table,omitempty"` // bind table Table string `json:"table,omitempty"` // bind table
Form string `json:"form,omitempty"` // bind form
Option map[string]interface{} `json:"option,omitempty"` // bind option Option map[string]interface{} `json:"option,omitempty"` // bind option
} }

View file

@ -1,6 +1,9 @@
package widgets package widgets
import ( import (
"fmt"
"strings"
"github.com/yaoapp/yao/config" "github.com/yaoapp/yao/config"
"github.com/yaoapp/yao/widgets/app" "github.com/yaoapp/yao/widgets/app"
"github.com/yaoapp/yao/widgets/chart" "github.com/yaoapp/yao/widgets/chart"
@ -15,51 +18,58 @@ import (
// Load the widgets // Load the widgets
func Load(cfg config.Config) error { func Load(cfg config.Config) error {
messages := []string{}
// load expression // load expression
err := expression.Export() err := expression.Export()
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// load component // load component
err = component.Export() err = component.Export()
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// load field transform // load field transform
err = field.LoadAndExport(config.Conf) err = field.LoadAndExport(config.Conf)
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// login widget // login widget
err = login.LoadAndExport(cfg) err = login.LoadAndExport(cfg)
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// app widget // app widget
err = app.LoadAndExport(cfg) err = app.LoadAndExport(cfg)
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// table widget // table widget
err = table.LoadAndExport(cfg) err = table.LoadAndExport(cfg)
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// form widget // form widget
err = form.LoadAndExport(cfg) err = form.LoadAndExport(cfg)
if err != nil { if err != nil {
return err messages = append(messages, err.Error())
} }
// chart widget // chart widget
err = chart.LoadAndExport(cfg) err = chart.LoadAndExport(cfg)
if err != nil { if err != nil {
messages = append(messages, err.Error())
}
if len(messages) > 0 {
err = fmt.Errorf(strings.Join(messages, ";\n"))
return err return err
} }