|
package types |
|
|
|
import ( |
|
"fmt" |
|
"html" |
|
"html/template" |
|
"strings" |
|
|
|
"github.com/GoAdminGroup/go-admin/context" |
|
"github.com/GoAdminGroup/go-admin/modules/config" |
|
"github.com/GoAdminGroup/go-admin/template/types/form" |
|
"golang.org/x/text/cases" |
|
"golang.org/x/text/language" |
|
) |
|
|
|
type DisplayFnGenerator interface { |
|
Get(ctx *context.Context, args ...interface{}) FieldFilterFn |
|
JS() template.HTML |
|
HTML() template.HTML |
|
} |
|
|
|
type BaseDisplayFnGenerator struct{} |
|
|
|
func (base *BaseDisplayFnGenerator) JS() template.HTML { return "" } |
|
func (base *BaseDisplayFnGenerator) HTML() template.HTML { return "" } |
|
|
|
var displayFnGens = make(map[string]DisplayFnGenerator) |
|
|
|
func RegisterDisplayFnGenerator(key string, gen DisplayFnGenerator) { |
|
if _, ok := displayFnGens[key]; ok { |
|
panic("display function generator has been registered") |
|
} |
|
displayFnGens[key] = gen |
|
} |
|
|
|
type FieldDisplay struct { |
|
Display FieldFilterFn |
|
DisplayProcessChains DisplayProcessFnChains |
|
} |
|
|
|
func (f FieldDisplay) ToDisplay(value FieldModel) interface{} { |
|
val := f.Display(value) |
|
|
|
if len(f.DisplayProcessChains) > 0 && f.IsNotSelectRes(val) { |
|
valStr := fmt.Sprintf("%v", val) |
|
for _, process := range f.DisplayProcessChains { |
|
valStr = fmt.Sprintf("%v", process(FieldModel{ |
|
Row: value.Row, |
|
Value: valStr, |
|
ID: value.ID, |
|
})) |
|
} |
|
return valStr |
|
} |
|
|
|
return val |
|
} |
|
|
|
func (f FieldDisplay) IsNotSelectRes(v interface{}) bool { |
|
switch v.(type) { |
|
case template.HTML: |
|
return false |
|
case []string: |
|
return false |
|
case [][]string: |
|
return false |
|
default: |
|
return true |
|
} |
|
} |
|
|
|
func (f FieldDisplay) ToDisplayHTML(value FieldModel) template.HTML { |
|
v := f.ToDisplay(value) |
|
if h, ok := v.(template.HTML); ok { |
|
return h |
|
} else if s, ok := v.(string); ok { |
|
return template.HTML(s) |
|
} else if arr, ok := v.([]string); ok && len(arr) > 0 { |
|
return template.HTML(arr[0]) |
|
} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 { |
|
return arr[0] |
|
} else if v != nil { |
|
return template.HTML(fmt.Sprintf("%v", v)) |
|
} else { |
|
return "" |
|
} |
|
} |
|
|
|
func (f FieldDisplay) ToDisplayString(value FieldModel) string { |
|
v := f.ToDisplay(value) |
|
if h, ok := v.(template.HTML); ok { |
|
return string(h) |
|
} else if s, ok := v.(string); ok { |
|
return s |
|
} else if arr, ok := v.([]string); ok && len(arr) > 0 { |
|
return arr[0] |
|
} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 { |
|
return string(arr[0]) |
|
} else if v != nil { |
|
return fmt.Sprintf("%v", v) |
|
} else { |
|
return "" |
|
} |
|
} |
|
|
|
func (f FieldDisplay) ToDisplayStringArray(value FieldModel) []string { |
|
v := f.ToDisplay(value) |
|
if h, ok := v.(template.HTML); ok { |
|
return []string{string(h)} |
|
} else if s, ok := v.(string); ok { |
|
return []string{s} |
|
} else if arr, ok := v.([]string); ok && len(arr) > 0 { |
|
return arr |
|
} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 { |
|
ss := make([]string, len(arr)) |
|
for k, a := range arr { |
|
ss[k] = string(a) |
|
} |
|
return ss |
|
} else if v != nil { |
|
return []string{fmt.Sprintf("%v", v)} |
|
} else { |
|
return []string{} |
|
} |
|
} |
|
|
|
func (f FieldDisplay) ToDisplayStringArrayArray(value FieldModel) [][]string { |
|
v := f.ToDisplay(value) |
|
if h, ok := v.(template.HTML); ok { |
|
return [][]string{{string(h)}} |
|
} else if s, ok := v.(string); ok { |
|
return [][]string{{s}} |
|
} else if arr, ok := v.([]string); ok && len(arr) > 0 { |
|
return [][]string{arr} |
|
} else if arr, ok := v.([][]string); ok && len(arr) > 0 { |
|
return arr |
|
} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 { |
|
ss := make([]string, len(arr)) |
|
for k, a := range arr { |
|
ss[k] = string(a) |
|
} |
|
return [][]string{ss} |
|
} else if v != nil { |
|
return [][]string{{fmt.Sprintf("%v", v)}} |
|
} else { |
|
return [][]string{} |
|
} |
|
} |
|
|
|
func (f FieldDisplay) AddLimit(limit int) DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
if limit > len(value.Value) { |
|
return value.Value |
|
} else if limit < 0 { |
|
return "" |
|
} else { |
|
return value.Value[:limit] |
|
} |
|
}) |
|
} |
|
|
|
func (f FieldDisplay) AddTrimSpace() DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
return strings.TrimSpace(value.Value) |
|
}) |
|
} |
|
|
|
func (f FieldDisplay) AddSubstr(start int, end int) DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
if start > end || start > len(value.Value) || end < 0 { |
|
return "" |
|
} |
|
if start < 0 { |
|
start = 0 |
|
} |
|
if end > len(value.Value) { |
|
end = len(value.Value) |
|
} |
|
return value.Value[start:end] |
|
}) |
|
} |
|
|
|
func (f FieldDisplay) AddToTitle() DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
return cases.Title(language.Und).String(value.Value) |
|
}) |
|
} |
|
|
|
func (f FieldDisplay) AddToUpper() DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
return strings.ToUpper(value.Value) |
|
}) |
|
} |
|
|
|
func (f FieldDisplay) AddToLower() DisplayProcessFnChains { |
|
return f.DisplayProcessChains.Add(func(value FieldModel) interface{} { |
|
return strings.ToLower(value.Value) |
|
}) |
|
} |
|
|
|
type DisplayProcessFnChains []FieldFilterFn |
|
|
|
func (d DisplayProcessFnChains) Valid() bool { |
|
return len(d) > 0 |
|
} |
|
|
|
func (d DisplayProcessFnChains) Add(f FieldFilterFn) DisplayProcessFnChains { |
|
return append(d, f) |
|
} |
|
|
|
func (d DisplayProcessFnChains) Append(f DisplayProcessFnChains) DisplayProcessFnChains { |
|
return append(d, f...) |
|
} |
|
|
|
func (d DisplayProcessFnChains) Copy() DisplayProcessFnChains { |
|
if len(d) == 0 { |
|
return make(DisplayProcessFnChains, 0) |
|
} else { |
|
var newDisplayProcessFnChains = make(DisplayProcessFnChains, len(d)) |
|
copy(newDisplayProcessFnChains, d) |
|
return newDisplayProcessFnChains |
|
} |
|
} |
|
|
|
func chooseDisplayProcessChains(internal DisplayProcessFnChains) DisplayProcessFnChains { |
|
if len(internal) > 0 { |
|
return internal |
|
} |
|
return globalDisplayProcessChains.Copy() |
|
} |
|
|
|
var globalDisplayProcessChains = make(DisplayProcessFnChains, 0) |
|
|
|
func AddGlobalDisplayProcessFn(f FieldFilterFn) { |
|
globalDisplayProcessChains = globalDisplayProcessChains.Add(f) |
|
} |
|
|
|
func AddLimit(limit int) DisplayProcessFnChains { |
|
return addLimit(limit, globalDisplayProcessChains) |
|
} |
|
|
|
func AddTrimSpace() DisplayProcessFnChains { |
|
return addTrimSpace(globalDisplayProcessChains) |
|
} |
|
|
|
func AddSubstr(start int, end int) DisplayProcessFnChains { |
|
return addSubstr(start, end, globalDisplayProcessChains) |
|
} |
|
|
|
func AddToTitle() DisplayProcessFnChains { |
|
return addToTitle(globalDisplayProcessChains) |
|
} |
|
|
|
func AddToUpper() DisplayProcessFnChains { |
|
return addToUpper(globalDisplayProcessChains) |
|
} |
|
|
|
func AddToLower() DisplayProcessFnChains { |
|
return addToLower(globalDisplayProcessChains) |
|
} |
|
|
|
func AddXssFilter() DisplayProcessFnChains { |
|
return addXssFilter(globalDisplayProcessChains) |
|
} |
|
|
|
func AddXssJsFilter() DisplayProcessFnChains { |
|
return addXssJsFilter(globalDisplayProcessChains) |
|
} |
|
|
|
func addLimit(limit int, chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
if limit > len(value.Value) { |
|
return value |
|
} else if limit < 0 { |
|
return "" |
|
} else { |
|
return value.Value[:limit] |
|
} |
|
}) |
|
return chains |
|
} |
|
|
|
func addTrimSpace(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
return strings.TrimSpace(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func addSubstr(start int, end int, chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
if start > end || start > len(value.Value) || end < 0 { |
|
return "" |
|
} |
|
if start < 0 { |
|
start = 0 |
|
} |
|
if end > len(value.Value) { |
|
end = len(value.Value) |
|
} |
|
return value.Value[start:end] |
|
}) |
|
return chains |
|
} |
|
|
|
func addToTitle(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
return cases.Title(language.Und).String(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func addToUpper(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
return strings.ToUpper(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func addToLower(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
return strings.ToLower(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func addXssFilter(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
return html.EscapeString(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func addXssJsFilter(chains DisplayProcessFnChains) DisplayProcessFnChains { |
|
chains = chains.Add(func(value FieldModel) interface{} { |
|
replacer := strings.NewReplacer("<script>", "<script>", "</script>", "</script>") |
|
return replacer.Replace(value.Value) |
|
}) |
|
return chains |
|
} |
|
|
|
func setDefaultDisplayFnOfFormType(f *FormPanel, typ form.Type) { |
|
if typ.IsMultiFile() { |
|
f.FieldList[f.curFieldListIndex].Display = func(value FieldModel) interface{} { |
|
if value.Value == "" { |
|
return "" |
|
} |
|
arr := strings.Split(value.Value, ",") |
|
res := "[" |
|
for i, item := range arr { |
|
if i == len(arr)-1 { |
|
res += "'" + config.GetStore().URL(item) + "']" |
|
} else { |
|
res += "'" + config.GetStore().URL(item) + "'," |
|
} |
|
} |
|
return res |
|
} |
|
} |
|
if typ.IsSelect() { |
|
f.FieldList[f.curFieldListIndex].Display = func(value FieldModel) interface{} { |
|
return strings.Split(value.Value, ",") |
|
} |
|
} |
|
} |
|
|