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>", "<script>", "</script>", "</script>") 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 }