Skip to content

Commit

Permalink
Merge pull request YaoApp#223 from trheyi/main
Browse files Browse the repository at this point in the history
[change] optimize forms
  • Loading branch information
trheyi authored Oct 22, 2022
2 parents 7e0732e + 6bbcfec commit 901a44b
Show file tree
Hide file tree
Showing 13 changed files with 595 additions and 487 deletions.
26 changes: 14 additions & 12 deletions service/guard.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ import (

"github.com/gin-gonic/gin"
"github.com/yaoapp/yao/helper"
"github.com/yaoapp/yao/table"
table_v0 "github.com/yaoapp/yao/table"

widget_table "github.com/yaoapp/yao/widgets/table"
"github.com/yaoapp/yao/widgets/form"
"github.com/yaoapp/yao/widgets/table"
)

// Guards 服务中间件
// Guards middlewares
var Guards = map[string]gin.HandlerFunc{
"bearer-jwt": bearerJWT, // JWT 鉴权
"cross-domain": crossDomain, // 跨域许可
"table-guard": table.Guard, // Table Guard
"widget-table": widget_table.Guard, // Widget Table Guard
"bearer-jwt": guardBearerJWT, // Bearer JWT
"cross-origin": guardCrossOrigin, // Cross-Origin Resource Sharing
"table-guard": table_v0.Guard, // Table Guard ( v0.9 table)
"widget-table": table.Guard, // Widget Table Guard
"widget-form": form.Guard, // Widget Form Guard
}

// JWT 鉴权
func bearerJWT(c *gin.Context) {
// JWT Bearer JWT
func guardBearerJWT(c *gin.Context) {
tokenString := c.Request.Header.Get("Authorization")
tokenString = strings.TrimSpace(strings.TrimPrefix(tokenString, "Bearer "))
if tokenString == "" {
Expand All @@ -32,15 +34,15 @@ func bearerJWT(c *gin.Context) {
c.Set("__sid", claims.SID)
}

// crossDomain 跨域访问
func crossDomain(c *gin.Context) {
// CORS Cross Origin
func guardCrossOrigin(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
244 changes: 244 additions & 0 deletions widgets/compute/compute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
package compute

import (
"fmt"
"reflect"
"strings"

"github.com/yaoapp/gou"
"github.com/yaoapp/kun/any"
"github.com/yaoapp/kun/maps"
"github.com/yaoapp/yao/widgets/field"
)

var views = map[string]bool{"find": true, "get": true, "search": true}

// ComputeEdit edit compute edit
func (c *Computable) ComputeEdit(name string, process *gou.Process, args []interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {
namer := strings.Split(strings.ToLower(name), ".")
name = namer[len(namer)-1]

switch name {
case "save", "create":
if len(args) == 0 {
return nil
}
switch args[0].(type) {
case maps.MapStr:
return c.editRow(process, args[0].(maps.MapStr), getField)

case map[string]interface{}:
return c.editRow(process, args[0].(map[string]interface{}), getField)
}
return nil

case "update", "updatewhere", "updatein":
if len(args) < 2 {
return nil
}

switch args[1].(type) {
case maps.MapStr:
return c.editRow(process, args[1].(maps.MapStr), getField)

case map[string]interface{}:
return c.editRow(process, args[1].(map[string]interface{}), getField)
}
return nil

case "insert":
if len(args) < 2 {
return nil
}

if _, ok := args[0].([]string); !ok {
return fmt.Errorf("args[0] is not a []string %s", reflect.ValueOf(args[0]).Type().Name())
}

if _, ok := args[1].([][]interface{}); !ok {
return fmt.Errorf("args[1] is not a [][] %s", reflect.ValueOf(args[1]).Type().Name())
}

return c.editRows(process, args[0].([]string), args[1].([][]interface{}), getField)
}

return nil
}

// EditRow edit row
func (c *Computable) editRow(process *gou.Process, res map[string]interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {

messages := []string{}
row := maps.MapOf(res).Dot()
data := maps.StrAny{"row": row}.Dot()
for key := range res {
if computes, has := c.Computes.Edit[key]; has {
unit := computes[0]
field, path, err := getField(unit.Name)
if err != nil {
messages = append(messages, err.Error())
continue
}

data.Set("value", res[key])
data.Merge(any.MapOf(field.Edit.Map()).MapStrAny.Dot())
new, err := field.Edit.Compute.Value(data, process.Sid, process.Global)
if err != nil {
messages = append(messages, fmt.Sprintf("%s.%s bind: %s, value: %v error: %s", path, unit.Name, key, res[key], err.Error()))
continue
}
res[key] = new
}
}

if len(messages) > 0 {
return fmt.Errorf("\n%s", strings.Join(messages, ";\n"))
}

return nil
}

// EditRows edit row
func (c *Computable) editRows(process *gou.Process, columns []string, res [][]interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {

messages := []string{}
keys := map[string]int{}
for i, name := range columns {
keys[name] = i
}

for i := range res {
if len(keys) != len(res[i]) {
continue
}

row := map[string]interface{}{}
for i, v := range res[i] {
row[columns[i]] = v
}

err := c.editRow(process, row, getField)
if err != nil {
messages = append(messages, err.Error())
}

for k, v := range row {
res[i][keys[k]] = v
}
}

if len(messages) > 0 {
return fmt.Errorf("\n%s", strings.Join(messages, ";\n"))
}

return nil
}

// ComputeView view view
func (c *Computable) ComputeView(name string, process *gou.Process, res interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {

namer := strings.Split(strings.ToLower(name), ".")
name = namer[len(namer)-1]
if _, has := views[name]; !has {
return nil
}

switch res.(type) {
case []maps.MapStrAny, []interface{}:
return c.viewRows(name, process, res, getField)

case map[string]interface{}:
return c.viewRow(name, process, res.(map[string]interface{}), getField)

case maps.MapStrAny:
return c.viewRow(name, process, res.(maps.MapStrAny), getField)
}

return fmt.Errorf("res should be a map or array, but got a %s", reflect.ValueOf(res).Kind().String())
}

// ViewRows viewrows
func (c *Computable) viewRows(name string, process *gou.Process, res interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {
switch res.(type) {

case []interface{}:
messages := []string{}
for i := range res.([]interface{}) {
err := c.ComputeView(name, process, res.([]interface{})[i], getField)
if err != nil {
messages = append(messages, err.Error())
}
}
if len(messages) > 0 {
return fmt.Errorf("\n%s", strings.Join(messages, ";\n"))
}
return nil

case []maps.MapStrAny:
messages := []string{}
for i := range res.([]maps.MapStrAny) {
err := c.ComputeView(name, process, res.([]maps.MapStrAny)[i], getField)
if err != nil {
messages = append(messages, fmt.Sprintf("%d %s", i, err.Error()))
}
}
if len(messages) > 0 {
return fmt.Errorf("\n%s", strings.Join(messages, ";\n"))
}
return nil
}

return nil
}

// ViewRow row
func (c *Computable) viewRow(name string, process *gou.Process, res map[string]interface{}, getField func(string) (*field.ColumnDSL, string, error)) error {

messages := []string{}
row := maps.MapOf(res).Dot()
data := maps.StrAny{"row": row}.Dot()

// page
if row.Has("data") && row.Has("total") &&
row.Has("pagesize") && row.Has("pagecnt") &&
row.Has("prev") && row.Has("next") {
switch res["data"].(type) {

case []maps.MapStrAny:
return c.viewRows(name, process, res["data"].([]maps.MapStrAny), getField)

case []interface{}:
return c.viewRows(name, process, res["data"].([]interface{}), getField)
}
}

for key, computes := range c.Computes.View {
unit := computes[0]
field, path, err := getField(unit.Name)
if err != nil {
messages = append(messages, err.Error())
continue
}

data.Set("value", res[key])
data.Merge(any.MapOf(field.View.Map()).MapStrAny.Dot())
new, err := field.View.Compute.Value(data, process.Sid, process.Global)
if err != nil {
res[key] = nil
messages = append(messages, fmt.Sprintf("%s.%s bind: %s, value: %v error: %s", path, unit.Name, key, res[key], err.Error()))
continue
}
res[key] = new
}

if len(messages) > 0 {
return fmt.Errorf("\n%s", strings.Join(messages, ";\n"))
}

return nil
}

// ComputeFilter filter
func (c *Computable) ComputeFilter(name string, process *gou.Process, args []interface{}, getFilter func(string) (*field.FilterDSL, string, error)) error {
return nil
}
28 changes: 28 additions & 0 deletions widgets/compute/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package compute

const (
// View View component
View uint8 = iota
// Edit Edit component
Edit
// Filter Filter component
Filter
)

// Computable with computes
type Computable struct {
Computes *Maps
}

// Maps compute mapping
type Maps struct {
Edit map[string][]Unit
View map[string][]Unit
Filter map[string][]Unit
}

// Unit the compute unit
type Unit struct {
Name string // index
Kind uint8 // Type
}
Loading

0 comments on commit 901a44b

Please sign in to comment.