github.com/kotovmak/go-admin@v1.1.1/template/types/display.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"html"
     6  	"html/template"
     7  	"strings"
     8  
     9  	"github.com/kotovmak/go-admin/modules/config"
    10  	"github.com/kotovmak/go-admin/template/types/form"
    11  )
    12  
    13  type DisplayFnGenerator interface {
    14  	Get(args ...interface{}) FieldFilterFn
    15  	JS() template.HTML
    16  	HTML() template.HTML
    17  }
    18  
    19  type BaseDisplayFnGenerator struct{}
    20  
    21  func (base *BaseDisplayFnGenerator) JS() template.HTML   { return "" }
    22  func (base *BaseDisplayFnGenerator) HTML() template.HTML { return "" }
    23  
    24  var displayFnGens = make(map[string]DisplayFnGenerator)
    25  
    26  func RegisterDisplayFnGenerator(key string, gen DisplayFnGenerator) {
    27  	if _, ok := displayFnGens[key]; ok {
    28  		panic("display function generator has been registered")
    29  	}
    30  	displayFnGens[key] = gen
    31  }
    32  
    33  type FieldDisplay struct {
    34  	Display              FieldFilterFn
    35  	DisplayProcessChains DisplayProcessFnChains
    36  }
    37  
    38  func (f FieldDisplay) ToDisplay(value FieldModel) interface{} {
    39  	val := f.Display(value)
    40  
    41  	if len(f.DisplayProcessChains) > 0 && f.IsNotSelectRes(val) {
    42  		valStr := fmt.Sprintf("%v", val)
    43  		for _, process := range f.DisplayProcessChains {
    44  			valStr = fmt.Sprintf("%v", process(FieldModel{
    45  				Row:   value.Row,
    46  				Value: valStr,
    47  				ID:    value.ID,
    48  			}))
    49  		}
    50  		return valStr
    51  	}
    52  
    53  	return val
    54  }
    55  
    56  func (f FieldDisplay) IsNotSelectRes(v interface{}) bool {
    57  	switch v.(type) {
    58  	case template.HTML:
    59  		return false
    60  	case []string:
    61  		return false
    62  	case [][]string:
    63  		return false
    64  	default:
    65  		return true
    66  	}
    67  }
    68  
    69  func (f FieldDisplay) ToDisplayHTML(value FieldModel) template.HTML {
    70  	v := f.ToDisplay(value)
    71  	if h, ok := v.(template.HTML); ok {
    72  		return h
    73  	} else if s, ok := v.(string); ok {
    74  		return template.HTML(s)
    75  	} else if arr, ok := v.([]string); ok && len(arr) > 0 {
    76  		return template.HTML(arr[0])
    77  	} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 {
    78  		return arr[0]
    79  	} else if v != nil {
    80  		return template.HTML(fmt.Sprintf("%v", v))
    81  	} else {
    82  		return ""
    83  	}
    84  }
    85  
    86  func (f FieldDisplay) ToDisplayString(value FieldModel) string {
    87  	v := f.ToDisplay(value)
    88  	if h, ok := v.(template.HTML); ok {
    89  		return string(h)
    90  	} else if s, ok := v.(string); ok {
    91  		return s
    92  	} else if arr, ok := v.([]string); ok && len(arr) > 0 {
    93  		return arr[0]
    94  	} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 {
    95  		return string(arr[0])
    96  	} else if v != nil {
    97  		return fmt.Sprintf("%v", v)
    98  	} else {
    99  		return ""
   100  	}
   101  }
   102  
   103  func (f FieldDisplay) ToDisplayStringArray(value FieldModel) []string {
   104  	v := f.ToDisplay(value)
   105  	if h, ok := v.(template.HTML); ok {
   106  		return []string{string(h)}
   107  	} else if s, ok := v.(string); ok {
   108  		return []string{s}
   109  	} else if arr, ok := v.([]string); ok && len(arr) > 0 {
   110  		return arr
   111  	} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 {
   112  		ss := make([]string, len(arr))
   113  		for k, a := range arr {
   114  			ss[k] = string(a)
   115  		}
   116  		return ss
   117  	} else if v != nil {
   118  		return []string{fmt.Sprintf("%v", v)}
   119  	} else {
   120  		return []string{}
   121  	}
   122  }
   123  
   124  func (f FieldDisplay) ToDisplayStringArrayArray(value FieldModel) [][]string {
   125  	v := f.ToDisplay(value)
   126  	if h, ok := v.(template.HTML); ok {
   127  		return [][]string{{string(h)}}
   128  	} else if s, ok := v.(string); ok {
   129  		return [][]string{{s}}
   130  	} else if arr, ok := v.([]string); ok && len(arr) > 0 {
   131  		return [][]string{arr}
   132  	} else if arr, ok := v.([][]string); ok && len(arr) > 0 {
   133  		return arr
   134  	} else if arr, ok := v.([]template.HTML); ok && len(arr) > 0 {
   135  		ss := make([]string, len(arr))
   136  		for k, a := range arr {
   137  			ss[k] = string(a)
   138  		}
   139  		return [][]string{ss}
   140  	} else if v != nil {
   141  		return [][]string{{fmt.Sprintf("%v", v)}}
   142  	} else {
   143  		return [][]string{}
   144  	}
   145  }
   146  
   147  func (f FieldDisplay) AddLimit(limit int) DisplayProcessFnChains {
   148  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   149  		if limit > len(value.Value) {
   150  			return value.Value
   151  		} else if limit < 0 {
   152  			return ""
   153  		} else {
   154  			return value.Value[:limit]
   155  		}
   156  	})
   157  }
   158  
   159  func (f FieldDisplay) AddTrimSpace() DisplayProcessFnChains {
   160  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   161  		return strings.TrimSpace(value.Value)
   162  	})
   163  }
   164  
   165  func (f FieldDisplay) AddSubstr(start int, end int) DisplayProcessFnChains {
   166  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   167  		if start > end || start > len(value.Value) || end < 0 {
   168  			return ""
   169  		}
   170  		if start < 0 {
   171  			start = 0
   172  		}
   173  		if end > len(value.Value) {
   174  			end = len(value.Value)
   175  		}
   176  		return value.Value[start:end]
   177  	})
   178  }
   179  
   180  func (f FieldDisplay) AddToTitle() DisplayProcessFnChains {
   181  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   182  		return strings.Title(value.Value)
   183  	})
   184  }
   185  
   186  func (f FieldDisplay) AddToUpper() DisplayProcessFnChains {
   187  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   188  		return strings.ToUpper(value.Value)
   189  	})
   190  }
   191  
   192  func (f FieldDisplay) AddToLower() DisplayProcessFnChains {
   193  	return f.DisplayProcessChains.Add(func(value FieldModel) interface{} {
   194  		return strings.ToLower(value.Value)
   195  	})
   196  }
   197  
   198  type DisplayProcessFnChains []FieldFilterFn
   199  
   200  func (d DisplayProcessFnChains) Valid() bool {
   201  	return len(d) > 0
   202  }
   203  
   204  func (d DisplayProcessFnChains) Add(f FieldFilterFn) DisplayProcessFnChains {
   205  	return append(d, f)
   206  }
   207  
   208  func (d DisplayProcessFnChains) Append(f DisplayProcessFnChains) DisplayProcessFnChains {
   209  	return append(d, f...)
   210  }
   211  
   212  func (d DisplayProcessFnChains) Copy() DisplayProcessFnChains {
   213  	if len(d) == 0 {
   214  		return make(DisplayProcessFnChains, 0)
   215  	} else {
   216  		var newDisplayProcessFnChains = make(DisplayProcessFnChains, len(d))
   217  		copy(newDisplayProcessFnChains, d)
   218  		return newDisplayProcessFnChains
   219  	}
   220  }
   221  
   222  func chooseDisplayProcessChains(internal DisplayProcessFnChains) DisplayProcessFnChains {
   223  	if len(internal) > 0 {
   224  		return internal
   225  	}
   226  	return globalDisplayProcessChains.Copy()
   227  }
   228  
   229  var globalDisplayProcessChains = make(DisplayProcessFnChains, 0)
   230  
   231  func AddGlobalDisplayProcessFn(f FieldFilterFn) {
   232  	globalDisplayProcessChains = globalDisplayProcessChains.Add(f)
   233  }
   234  
   235  func AddLimit(limit int) DisplayProcessFnChains {
   236  	return addLimit(limit, globalDisplayProcessChains)
   237  }
   238  
   239  func AddTrimSpace() DisplayProcessFnChains {
   240  	return addTrimSpace(globalDisplayProcessChains)
   241  }
   242  
   243  func AddSubstr(start int, end int) DisplayProcessFnChains {
   244  	return addSubstr(start, end, globalDisplayProcessChains)
   245  }
   246  
   247  func AddToTitle() DisplayProcessFnChains {
   248  	return addToTitle(globalDisplayProcessChains)
   249  }
   250  
   251  func AddToUpper() DisplayProcessFnChains {
   252  	return addToUpper(globalDisplayProcessChains)
   253  }
   254  
   255  func AddToLower() DisplayProcessFnChains {
   256  	return addToLower(globalDisplayProcessChains)
   257  }
   258  
   259  func AddXssFilter() DisplayProcessFnChains {
   260  	return addXssFilter(globalDisplayProcessChains)
   261  }
   262  
   263  func AddXssJsFilter() DisplayProcessFnChains {
   264  	return addXssJsFilter(globalDisplayProcessChains)
   265  }
   266  
   267  func addLimit(limit int, chains DisplayProcessFnChains) DisplayProcessFnChains {
   268  	chains = chains.Add(func(value FieldModel) interface{} {
   269  		if limit > len(value.Value) {
   270  			return value
   271  		} else if limit < 0 {
   272  			return ""
   273  		} else {
   274  			return value.Value[:limit]
   275  		}
   276  	})
   277  	return chains
   278  }
   279  
   280  func addTrimSpace(chains DisplayProcessFnChains) DisplayProcessFnChains {
   281  	chains = chains.Add(func(value FieldModel) interface{} {
   282  		return strings.TrimSpace(value.Value)
   283  	})
   284  	return chains
   285  }
   286  
   287  func addSubstr(start int, end int, chains DisplayProcessFnChains) DisplayProcessFnChains {
   288  	chains = chains.Add(func(value FieldModel) interface{} {
   289  		if start > end || start > len(value.Value) || end < 0 {
   290  			return ""
   291  		}
   292  		if start < 0 {
   293  			start = 0
   294  		}
   295  		if end > len(value.Value) {
   296  			end = len(value.Value)
   297  		}
   298  		return value.Value[start:end]
   299  	})
   300  	return chains
   301  }
   302  
   303  func addToTitle(chains DisplayProcessFnChains) DisplayProcessFnChains {
   304  	chains = chains.Add(func(value FieldModel) interface{} {
   305  		return strings.Title(value.Value)
   306  	})
   307  	return chains
   308  }
   309  
   310  func addToUpper(chains DisplayProcessFnChains) DisplayProcessFnChains {
   311  	chains = chains.Add(func(value FieldModel) interface{} {
   312  		return strings.ToUpper(value.Value)
   313  	})
   314  	return chains
   315  }
   316  
   317  func addToLower(chains DisplayProcessFnChains) DisplayProcessFnChains {
   318  	chains = chains.Add(func(value FieldModel) interface{} {
   319  		return strings.ToLower(value.Value)
   320  	})
   321  	return chains
   322  }
   323  
   324  func addXssFilter(chains DisplayProcessFnChains) DisplayProcessFnChains {
   325  	chains = chains.Add(func(value FieldModel) interface{} {
   326  		return html.EscapeString(value.Value)
   327  	})
   328  	return chains
   329  }
   330  
   331  func addXssJsFilter(chains DisplayProcessFnChains) DisplayProcessFnChains {
   332  	chains = chains.Add(func(value FieldModel) interface{} {
   333  		replacer := strings.NewReplacer("<script>", "&lt;script&gt;", "</script>", "&lt;/script&gt;")
   334  		return replacer.Replace(value.Value)
   335  	})
   336  	return chains
   337  }
   338  
   339  func setDefaultDisplayFnOfFormType(f *FormPanel, typ form.Type) {
   340  	if typ.IsMultiFile() {
   341  		f.FieldList[f.curFieldListIndex].Display = func(value FieldModel) interface{} {
   342  			if value.Value == "" {
   343  				return ""
   344  			}
   345  			arr := strings.Split(value.Value, ",")
   346  			res := "["
   347  			for i, item := range arr {
   348  				if i == len(arr)-1 {
   349  					res += "'" + config.GetStore().URL(item) + "']"
   350  				} else {
   351  					res += "'" + config.GetStore().URL(item) + "',"
   352  				}
   353  			}
   354  			return res
   355  		}
   356  	}
   357  	if typ.IsSelect() {
   358  		f.FieldList[f.curFieldListIndex].Display = func(value FieldModel) interface{} {
   359  			return strings.Split(value.Value, ",")
   360  		}
   361  	}
   362  }