github.com/kotovmak/go-admin@v1.1.1/template/types/form.go (about) 1 package types 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "html" 8 "html/template" 9 "net/http" 10 "reflect" 11 "strconv" 12 "strings" 13 "time" 14 15 "github.com/kotovmak/go-admin/context" 16 "github.com/kotovmak/go-admin/modules/config" 17 "github.com/kotovmak/go-admin/modules/constant" 18 "github.com/kotovmak/go-admin/modules/db" 19 "github.com/kotovmak/go-admin/modules/errors" 20 "github.com/kotovmak/go-admin/modules/file" 21 "github.com/kotovmak/go-admin/modules/language" 22 "github.com/kotovmak/go-admin/modules/logger" 23 "github.com/kotovmak/go-admin/modules/utils" 24 "github.com/kotovmak/go-admin/plugins/admin/modules" 25 "github.com/kotovmak/go-admin/plugins/admin/modules/form" 26 form2 "github.com/kotovmak/go-admin/template/types/form" 27 ) 28 29 type FieldOption struct { 30 Text string `json:"text"` 31 Value string `json:"value"` 32 TextHTML template.HTML `json:"-"` 33 Selected bool `json:"-"` 34 SelectedLabel template.HTML `json:"-"` 35 Extra map[string]string `json:"-"` 36 } 37 38 type FieldOptions []FieldOption 39 40 func (fo FieldOptions) Copy() FieldOptions { 41 newOptions := make(FieldOptions, len(fo)) 42 copy(newOptions, fo) 43 return newOptions 44 } 45 46 func (fo FieldOptions) SetSelected(val interface{}, labels []template.HTML) FieldOptions { 47 48 if valArr, ok := val.([]string); ok { 49 for k := range fo { 50 text := fo[k].Text 51 if text == "" { 52 text = string(fo[k].TextHTML) 53 } 54 fo[k].Selected = utils.InArray(valArr, fo[k].Value) || utils.InArray(valArr, text) 55 if fo[k].Selected { 56 fo[k].SelectedLabel = labels[0] 57 } else { 58 fo[k].SelectedLabel = labels[1] 59 } 60 } 61 } else { 62 for k := range fo { 63 text := fo[k].Text 64 if text == "" { 65 text = string(fo[k].TextHTML) 66 } 67 fo[k].Selected = fo[k].Value == val || text == val 68 if fo[k].Selected { 69 fo[k].SelectedLabel = labels[0] 70 } else { 71 fo[k].SelectedLabel = labels[1] 72 } 73 } 74 } 75 76 return fo 77 } 78 79 func (fo FieldOptions) SetSelectedLabel(labels []template.HTML) FieldOptions { 80 for k := range fo { 81 if fo[k].Selected { 82 fo[k].SelectedLabel = labels[0] 83 } else { 84 fo[k].SelectedLabel = labels[1] 85 } 86 } 87 return fo 88 } 89 90 func (fo FieldOptions) Marshal() string { 91 if len(fo) == 0 { 92 return "" 93 } 94 eo, err := json.Marshal(fo) 95 96 if err != nil { 97 return "" 98 } 99 100 return string(eo) 101 } 102 103 type ( 104 OptionInitFn func(val FieldModel) FieldOptions 105 OptionArrInitFn func(val FieldModel) []FieldOptions 106 OptionTableQueryProcessFn func(sql *db.SQL) *db.SQL 107 OptionProcessFn func(options FieldOptions) FieldOptions 108 109 OptionTable struct { 110 Table string 111 TextField string 112 ValueField string 113 QueryProcessFn OptionTableQueryProcessFn 114 ProcessFn OptionProcessFn 115 } 116 ) 117 118 // FormField is the form field with different options. 119 type FormField struct { 120 Field string `json:"field"` 121 FieldClass string `json:"field_class"` 122 TypeName db.DatabaseType `json:"type_name"` 123 Head string `json:"head"` 124 Foot template.HTML `json:"foot"` 125 FormType form2.Type `json:"form_type"` 126 FatherFormType form2.Type `json:"father_form_type"` 127 FatherField string `json:"father_field"` 128 129 RowWidth int 130 RowFlag uint8 131 132 Default template.HTML `json:"default"` 133 DefaultArr interface{} `json:"default_arr"` 134 Value template.HTML `json:"value"` 135 Value2 string `json:"value_2"` 136 ValueArr []string `json:"value_arr"` 137 Value2Arr []string `json:"value_2_arr"` 138 Options FieldOptions `json:"options"` 139 OptionsArr []FieldOptions `json:"options_arr"` 140 DefaultOptionDelimiter string `json:"default_option_delimiter"` 141 Label template.HTML `json:"label"` 142 HideLabel bool `json:"hide_label"` 143 144 Placeholder string `json:"placeholder"` 145 146 CustomContent template.HTML `json:"custom_content"` 147 CustomJs template.JS `json:"custom_js"` 148 CustomCss template.CSS `json:"custom_css"` 149 150 Editable bool `json:"editable"` 151 NotAllowEdit bool `json:"not_allow_edit"` 152 NotAllowAdd bool `json:"not_allow_add"` 153 DisplayButNotAdd bool `json:"display_but_not_add"` 154 Must bool `json:"must"` 155 Hide bool `json:"hide"` 156 CreateHide bool `json:"create_hide"` 157 EditHide bool `json:"edit_hide"` 158 159 Width int `json:"width"` 160 161 InputWidth int `json:"input_width"` 162 HeadWidth int `json:"head_width"` 163 164 Joins Joins `json:"-"` 165 166 Divider bool `json:"divider"` 167 DividerTitle string `json:"divider_title"` 168 169 HelpMsg template.HTML `json:"help_msg"` 170 171 TableFields FormFields 172 173 Style template.HTMLAttr `json:"style"` 174 NoIcon bool `json:"no_icon"` 175 176 OptionExt template.JS `json:"option_ext"` 177 OptionExt2 template.JS `json:"option_ext_2"` 178 OptionInitFn OptionInitFn `json:"-"` 179 OptionArrInitFn OptionArrInitFn `json:"-"` 180 OptionTable OptionTable `json:"-"` 181 182 FieldDisplay `json:"-"` 183 PostFilterFn PostFieldFilterFn `json:"-"` 184 } 185 186 func (f *FormField) GetRawValue(columns []string, v interface{}) string { 187 isJSON := len(columns) == 0 188 return modules.AorB(isJSON || modules.InArray(columns, f.Field), 189 db.GetValueFromDatabaseType(f.TypeName, v, isJSON).String(), "") 190 } 191 192 func (f *FormField) UpdateValue(id, val string, res map[string]interface{}, sql *db.SQL) *FormField { 193 return f.updateValue(id, val, res, PostTypeUpdate, sql) 194 } 195 196 func (f *FormField) UpdateDefaultValue(sql *db.SQL) *FormField { 197 f.Value = f.Default 198 return f.updateValue("", string(f.Value), make(map[string]interface{}), PostTypeCreate, sql) 199 } 200 201 func (f *FormField) setOptionsFromSQL(sql *db.SQL) { 202 if sql != nil && f.OptionTable.Table != "" && len(f.Options) == 0 { 203 204 sql.Table(f.OptionTable.Table).Select(f.OptionTable.ValueField, f.OptionTable.TextField) 205 206 if f.OptionTable.QueryProcessFn != nil { 207 f.OptionTable.QueryProcessFn(sql) 208 } 209 210 queryRes, err := sql.All() 211 if err == nil { 212 for _, item := range queryRes { 213 value := item[f.OptionTable.ValueField] 214 typeStr := reflect.TypeOf(value).String() 215 if typeStr == "[]uint8" { 216 f.Options = append(f.Options, FieldOption{ 217 Value: fmt.Sprintf("%v", string(value.([]uint8))), 218 Text: fmt.Sprintf("%v", item[f.OptionTable.TextField]), 219 }) 220 } else { 221 f.Options = append(f.Options, FieldOption{ 222 Value: fmt.Sprintf("%v", value), 223 Text: fmt.Sprintf("%v", item[f.OptionTable.TextField]), 224 }) 225 } 226 } 227 } 228 229 if f.OptionTable.ProcessFn != nil { 230 f.Options = f.OptionTable.ProcessFn(f.Options) 231 } 232 } 233 } 234 235 func (f *FormField) isBelongToATable() bool { 236 return f.FatherField != "" && f.FatherFormType.IsTable() 237 } 238 239 func (f *FormField) isNotBelongToATable() bool { 240 return f.FatherField == "" && !f.FatherFormType.IsTable() 241 } 242 243 func (f *FormField) allowAdd() bool { 244 return !f.NotAllowAdd 245 } 246 247 func (f *FormField) updateValue(id, val string, res map[string]interface{}, typ PostType, sql *db.SQL) *FormField { 248 249 m := FieldModel{ 250 ID: id, 251 Value: val, 252 Row: res, 253 PostType: typ, 254 } 255 256 if f.isBelongToATable() { 257 if f.FormType.IsSelect() { 258 if len(f.OptionsArr) == 0 && f.OptionArrInitFn != nil { 259 f.OptionsArr = f.OptionArrInitFn(m) 260 for i := 0; i < len(f.OptionsArr); i++ { 261 f.OptionsArr[i] = f.OptionsArr[i].SetSelectedLabel(f.FormType.SelectedLabel()) 262 } 263 } else { 264 265 f.setOptionsFromSQL(sql) 266 267 if f.FormType.IsSingleSelect() { 268 values := f.ToDisplayStringArray(m) 269 f.OptionsArr = make([]FieldOptions, len(values)) 270 for k, value := range values { 271 f.OptionsArr[k] = f.Options.Copy().SetSelected(value, f.FormType.SelectedLabel()) 272 } 273 } else { 274 values := f.ToDisplayStringArrayArray(m) 275 f.OptionsArr = make([]FieldOptions, len(values)) 276 for k, value := range values { 277 f.OptionsArr[k] = f.Options.Copy().SetSelected(value, f.FormType.SelectedLabel()) 278 } 279 } 280 } 281 } else { 282 f.ValueArr = f.ToDisplayStringArray(m) 283 } 284 } else { 285 if f.FormType.IsSelect() { 286 if len(f.Options) == 0 && f.OptionInitFn != nil { 287 f.Options = f.OptionInitFn(m).SetSelectedLabel(f.FormType.SelectedLabel()) 288 } else { 289 f.setOptionsFromSQL(sql) 290 f.Options.SetSelected(f.ToDisplay(m), f.FormType.SelectedLabel()) 291 } 292 } else if f.FormType.IsArray() { 293 f.ValueArr = f.ToDisplayStringArray(m) 294 } else { 295 f.Value = f.ToDisplayHTML(m) 296 if f.FormType.IsFile() { 297 if f.Value != template.HTML("") { 298 f.Value2 = config.GetStore().URL(string(f.Value)) 299 } 300 } 301 } 302 } 303 304 return f 305 } 306 307 func (f *FormField) FillCustomContent() *FormField { 308 // TODO: optimize 309 if f.CustomContent != "" { 310 f.CustomContent = template.HTML(f.fillCustom(string(f.CustomContent))) 311 } 312 if f.CustomJs != "" { 313 f.CustomJs = template.JS(f.fillCustom(string(f.CustomJs))) 314 } 315 if f.CustomCss != "" { 316 f.CustomCss = template.CSS(f.fillCustom(string(f.CustomCss))) 317 } 318 return f 319 } 320 321 func (f *FormField) fillCustom(src string) string { 322 t := template.New("custom") 323 t, err := t.Parse(src) 324 if err != nil { 325 logger.Error(err) 326 return "" 327 } 328 buf := new(bytes.Buffer) 329 err = t.Execute(buf, f) 330 if err != nil { 331 logger.Error(err) 332 return "" 333 } 334 return buf.String() 335 } 336 337 // FormPanel 338 type FormPanel struct { 339 FieldList FormFields `json:"field_list"` 340 curFieldListIndex int 341 342 // Warn: may be deprecated in the future. `json:"" 343 TabGroups TabGroups `json:"tab_groups"` 344 TabHeaders TabHeaders `json:"tab_headers"` 345 346 Table string `json:"table"` 347 Title string `json:"title"` 348 Description string `json:"description"` 349 350 Validator FormPostFn `json:"validator"` 351 PostHook FormPostFn `json:"post_hook"` 352 PreProcessFn FormPreProcessFn `json:"pre_process_fn"` 353 354 Callbacks Callbacks `json:"callbacks"` 355 356 primaryKey primaryKey 357 358 UpdateFn FormPostFn `json:"update_fn"` 359 InsertFn FormPostFn `json:"insert_fn"` 360 361 IsHideContinueEditCheckBox bool `json:"is_hide_continue_edit_check_box"` 362 IsHideContinueNewCheckBox bool `json:"is_hide_continue_new_check_box"` 363 IsHideResetButton bool `json:"is_hide_reset_button"` 364 IsHideBackButton bool `json:"is_hide_back_button"` 365 366 Layout form2.Layout `json:"layout"` 367 368 HTMLContent template.HTML `json:"html_content"` 369 370 Header template.HTML `json:"header"` 371 372 InputWidth int `json:"input_width"` 373 HeadWidth int `json:"head_width"` 374 375 FormNewTitle template.HTML `json:"form_new_title"` 376 FormNewBtnWord template.HTML `json:"form_new_btn_word"` 377 FormEditTitle template.HTML `json:"form_edit_title"` 378 FormEditBtnWord template.HTML `json:"form_edit_btn_word"` 379 380 Ajax bool `json:"ajax"` 381 AjaxSuccessJS template.JS `json:"ajax_success_js"` 382 AjaxErrorJS template.JS `json:"ajax_error_js"` 383 384 Responder Responder `json:"responder"` 385 386 Wrapper ContentWrapper `json:"wrapper"` 387 388 HideSideBar bool `json:"hide_side_bar"` 389 390 processChains DisplayProcessFnChains 391 392 HeaderHtml template.HTML `json:"header_html"` 393 FooterHtml template.HTML `json:"footer_html"` 394 395 PageError errors.PageError `json:"page_error"` 396 PageErrorHTML template.HTML `json:"page_error_html"` 397 398 NoCompress bool `json:"no_compress"` 399 } 400 401 type Responder func(ctx *context.Context) 402 403 func NewFormPanel() *FormPanel { 404 return &FormPanel{ 405 curFieldListIndex: -1, 406 Callbacks: make(Callbacks, 0), 407 Layout: form2.LayoutDefault, 408 FormNewTitle: "New", 409 FormEditTitle: "Edit", 410 FormNewBtnWord: language.GetFromHtml("Save"), 411 FormEditBtnWord: language.GetFromHtml("Save"), 412 } 413 } 414 415 func (f *FormPanel) AddLimitFilter(limit int) *FormPanel { 416 f.processChains = addLimit(limit, f.processChains) 417 return f 418 } 419 420 func (f *FormPanel) AddTrimSpaceFilter() *FormPanel { 421 f.processChains = addTrimSpace(f.processChains) 422 return f 423 } 424 425 func (f *FormPanel) AddSubstrFilter(start int, end int) *FormPanel { 426 f.processChains = addSubstr(start, end, f.processChains) 427 return f 428 } 429 430 func (f *FormPanel) AddToTitleFilter() *FormPanel { 431 f.processChains = addToTitle(f.processChains) 432 return f 433 } 434 435 func (f *FormPanel) AddToUpperFilter() *FormPanel { 436 f.processChains = addToUpper(f.processChains) 437 return f 438 } 439 440 func (f *FormPanel) AddToLowerFilter() *FormPanel { 441 f.processChains = addToLower(f.processChains) 442 return f 443 } 444 445 func (f *FormPanel) AddXssFilter() *FormPanel { 446 f.processChains = addXssFilter(f.processChains) 447 return f 448 } 449 450 func (f *FormPanel) AddXssJsFilter() *FormPanel { 451 f.processChains = addXssJsFilter(f.processChains) 452 return f 453 } 454 455 func (f *FormPanel) SetPrimaryKey(name string, typ db.DatabaseType) *FormPanel { 456 f.primaryKey = primaryKey{Name: name, Type: typ} 457 return f 458 } 459 460 func (f *FormPanel) HideContinueEditCheckBox() *FormPanel { 461 f.IsHideContinueEditCheckBox = true 462 return f 463 } 464 465 func (f *FormPanel) HideContinueNewCheckBox() *FormPanel { 466 f.IsHideContinueNewCheckBox = true 467 return f 468 } 469 470 func (f *FormPanel) HideResetButton() *FormPanel { 471 f.IsHideResetButton = true 472 return f 473 } 474 475 func (f *FormPanel) HideBackButton() *FormPanel { 476 f.IsHideBackButton = true 477 return f 478 } 479 480 func (f *FormPanel) AddFieldTr(ctx *context.Context, head, field string, filedType db.DatabaseType, formType form2.Type) *FormPanel { 481 return f.AddFieldWithTranslation(ctx, head, field, filedType, formType) 482 } 483 484 func (f *FormPanel) AddFieldWithTranslation(ctx *context.Context, head, field string, filedType db.DatabaseType, 485 formType form2.Type) *FormPanel { 486 return f.AddField(language.GetWithLang(head, ctx.Lang()), field, filedType, formType) 487 } 488 489 func (f *FormPanel) AddField(head, field string, filedType db.DatabaseType, formType form2.Type) *FormPanel { 490 491 f.FieldList = append(f.FieldList, FormField{ 492 Head: head, 493 Field: field, 494 FieldClass: field, 495 TypeName: filedType, 496 Editable: true, 497 Hide: false, 498 TableFields: make(FormFields, 0), 499 Placeholder: language.Get("input") + " " + head, 500 FormType: formType, 501 FieldDisplay: FieldDisplay{ 502 Display: func(value FieldModel) interface{} { 503 return value.Value 504 }, 505 DisplayProcessChains: chooseDisplayProcessChains(f.processChains), 506 }, 507 }) 508 f.curFieldListIndex++ 509 510 // Set default options of different form type 511 op1, op2, js := formType.GetDefaultOptions(field) 512 f.FieldOptionExt(op1) 513 f.FieldOptionExt2(op2) 514 f.FieldOptionExtJS(js) 515 516 // Set default Display Filter Function of different form type 517 setDefaultDisplayFnOfFormType(f, formType) 518 519 if formType.IsEditor() { 520 f.NoCompress = true 521 } 522 523 return f 524 } 525 526 type AddFormFieldFn func(panel *FormPanel) 527 528 func (f *FormPanel) AddTable(head, field string, addFields AddFormFieldFn) *FormPanel { 529 index := f.curFieldListIndex 530 addFields(f) 531 for i := index + 1; i <= f.curFieldListIndex; i++ { 532 f.FieldList[i].FatherFormType = form2.Table 533 f.FieldList[i].FatherField = field 534 } 535 fields := make(FormFields, f.curFieldListIndex-index) 536 copy(fields, f.FieldList[index+1:f.curFieldListIndex+1]) 537 f.FieldList = append(f.FieldList, FormField{ 538 Head: head, 539 Field: field, 540 FieldClass: field, 541 TypeName: db.Varchar, 542 Editable: true, 543 Hide: false, 544 TableFields: fields, 545 FormType: form2.Table, 546 FieldDisplay: FieldDisplay{ 547 Display: func(value FieldModel) interface{} { 548 return value.Value 549 }, 550 DisplayProcessChains: chooseDisplayProcessChains(f.processChains), 551 }, 552 }) 553 f.curFieldListIndex++ 554 return f 555 } 556 557 func (f *FormPanel) AddRow(addFields AddFormFieldFn) *FormPanel { 558 index := f.curFieldListIndex 559 addFields(f) 560 if f.curFieldListIndex != index+1 { 561 for i := index + 1; i <= f.curFieldListIndex; i++ { 562 if i == index+1 { 563 f.FieldList[i].RowFlag = 1 564 } else if i == f.curFieldListIndex { 565 f.FieldList[i].RowFlag = 2 566 } else { 567 f.FieldList[i].RowFlag = 3 568 } 569 } 570 } 571 return f 572 } 573 574 // Field attribute setting functions 575 // ==================================================== 576 577 func (f *FormPanel) FieldDisplay(filter FieldFilterFn) *FormPanel { 578 f.FieldList[f.curFieldListIndex].Display = filter 579 return f 580 } 581 582 func (f *FormPanel) SetTable(table string) *FormPanel { 583 f.Table = table 584 return f 585 } 586 587 func (f *FormPanel) FieldMust() *FormPanel { 588 f.FieldList[f.curFieldListIndex].Must = true 589 return f 590 } 591 592 func (f *FormPanel) FieldHide() *FormPanel { 593 f.FieldList[f.curFieldListIndex].Hide = true 594 return f 595 } 596 597 func (f *FormPanel) FieldPlaceholder(placeholder string) *FormPanel { 598 f.FieldList[f.curFieldListIndex].Placeholder = placeholder 599 return f 600 } 601 602 func (f *FormPanel) FieldWidth(width int) *FormPanel { 603 f.FieldList[f.curFieldListIndex].Width = width 604 return f 605 } 606 607 func (f *FormPanel) FieldInputWidth(width int) *FormPanel { 608 f.FieldList[f.curFieldListIndex].InputWidth = width 609 return f 610 } 611 612 func (f *FormPanel) FieldHeadWidth(width int) *FormPanel { 613 f.FieldList[f.curFieldListIndex].HeadWidth = width 614 return f 615 } 616 617 func (f *FormPanel) FieldRowWidth(width int) *FormPanel { 618 f.FieldList[f.curFieldListIndex].RowWidth = width 619 return f 620 } 621 622 func (f *FormPanel) FieldHideLabel() *FormPanel { 623 f.FieldList[f.curFieldListIndex].HideLabel = true 624 return f 625 } 626 627 func (f *FormPanel) FieldFoot(foot template.HTML) *FormPanel { 628 f.FieldList[f.curFieldListIndex].Foot = foot 629 return f 630 } 631 632 func (f *FormPanel) FieldDivider(title ...string) *FormPanel { 633 f.FieldList[f.curFieldListIndex].Divider = true 634 if len(title) > 0 { 635 f.FieldList[f.curFieldListIndex].DividerTitle = title[0] 636 } 637 return f 638 } 639 640 func (f *FormPanel) FieldHelpMsg(s template.HTML) *FormPanel { 641 f.FieldList[f.curFieldListIndex].HelpMsg = s 642 return f 643 } 644 645 func (f *FormPanel) FieldOptionInitFn(fn OptionInitFn) *FormPanel { 646 f.FieldList[f.curFieldListIndex].OptionInitFn = fn 647 return f 648 } 649 650 func (f *FormPanel) FieldOptionExt(m map[string]interface{}) *FormPanel { 651 652 if m == nil { 653 return f 654 } 655 656 if f.FieldList[f.curFieldListIndex].FormType.IsCode() { 657 f.FieldList[f.curFieldListIndex].OptionExt = template.JS(fmt.Sprintf(` 658 theme = "%s"; 659 font_size = %s; 660 language = "%s"; 661 options = %s; 662 `, m["theme"], m["font_size"], m["language"], m["options"])) 663 return f 664 } 665 666 m = f.FieldList[f.curFieldListIndex].FormType.FixOptions(m) 667 668 s, _ := json.Marshal(m) 669 670 if f.FieldList[f.curFieldListIndex].OptionExt != template.JS("") { 671 ss := string(f.FieldList[f.curFieldListIndex].OptionExt) 672 ss = strings.Replace(ss, "}", "", strings.Count(ss, "}")) 673 ss = strings.TrimRight(ss, " ") 674 ss += "," 675 f.FieldList[f.curFieldListIndex].OptionExt = template.JS(ss) + template.JS(strings.Replace(string(s), "{", "", 1)) 676 } else { 677 f.FieldList[f.curFieldListIndex].OptionExt = template.JS(string(s)) 678 } 679 680 return f 681 } 682 683 func (f *FormPanel) FieldOptionExt2(m map[string]interface{}) *FormPanel { 684 685 if m == nil { 686 return f 687 } 688 689 m = f.FieldList[f.curFieldListIndex].FormType.FixOptions(m) 690 691 s, _ := json.Marshal(m) 692 693 if f.FieldList[f.curFieldListIndex].OptionExt2 != template.JS("") { 694 ss := string(f.FieldList[f.curFieldListIndex].OptionExt2) 695 ss = strings.Replace(ss, "}", "", strings.Count(ss, "}")) 696 ss = strings.TrimRight(ss, " ") 697 ss += "," 698 f.FieldList[f.curFieldListIndex].OptionExt2 = template.JS(ss) + template.JS(strings.Replace(string(s), "{", "", 1)) 699 } else { 700 f.FieldList[f.curFieldListIndex].OptionExt2 = template.JS(string(s)) 701 } 702 703 return f 704 } 705 706 func (f *FormPanel) FieldOptionExtJS(js template.JS) *FormPanel { 707 if js != template.JS("") { 708 f.FieldList[f.curFieldListIndex].OptionExt = js 709 } 710 return f 711 } 712 713 func (f *FormPanel) FieldOptionExtJS2(js template.JS) *FormPanel { 714 f.FieldList[f.curFieldListIndex].OptionExt2 = js 715 return f 716 } 717 718 func (f *FormPanel) FieldEnableFileUpload(data ...interface{}) *FormPanel { 719 720 url := f.OperationURL("/file/upload") 721 722 if len(data) > 0 { 723 url = data[0].(string) 724 } 725 726 field := f.FieldList[f.curFieldListIndex].Field 727 728 f.FieldList[f.curFieldListIndex].OptionExt = template.JS(fmt.Sprintf(` 729 %seditor.customConfig.uploadImgServer = '%s'; 730 %seditor.customConfig.uploadImgMaxSize = 3 * 1024 * 1024; 731 %seditor.customConfig.uploadImgMaxLength = 5; 732 %seditor.customConfig.uploadFileName = 'file'; 733 `, field, url, field, field, field)) 734 735 var fileUploadHandler context.Handler 736 if len(data) > 1 { 737 fileUploadHandler = data[1].(context.Handler) 738 } else { 739 fileUploadHandler = func(ctx *context.Context) { 740 if len(ctx.Request.MultipartForm.File) == 0 { 741 ctx.JSON(http.StatusOK, map[string]interface{}{ 742 "errno": 400, 743 }) 744 return 745 } 746 747 err := file.GetFileEngine(config.GetFileUploadEngine().Name).Upload(ctx.Request.MultipartForm) 748 if err != nil { 749 ctx.JSON(http.StatusOK, map[string]interface{}{ 750 "errno": 500, 751 }) 752 return 753 } 754 755 var imgPath = make([]string, len(ctx.Request.MultipartForm.Value["file"])) 756 for i, path := range ctx.Request.MultipartForm.Value["file"] { 757 imgPath[i] = config.GetStore().URL(path) 758 } 759 760 ctx.JSON(http.StatusOK, map[string]interface{}{ 761 "errno": 0, 762 "data": imgPath, 763 }) 764 } 765 } 766 767 f.Callbacks = f.Callbacks.AddCallback(context.Node{ 768 Path: url, 769 Method: "post", 770 Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, 771 Handlers: []context.Handler{fileUploadHandler}, 772 }) 773 774 return f 775 } 776 777 func (f *FormPanel) FieldDefault(def string) *FormPanel { 778 f.FieldList[f.curFieldListIndex].Default = template.HTML(def) 779 return f 780 } 781 782 // FieldNotAllowEdit means when update record the field can not be edited but will still be displayed and submitted. 783 // Deprecated: Use FieldDisplayButCanNotEditWhenUpdate instead. 784 func (f *FormPanel) FieldNotAllowEdit() *FormPanel { 785 f.FieldList[f.curFieldListIndex].Editable = false 786 return f 787 } 788 789 // FieldDisplayButCanNotEditWhenUpdate means when update record the field can not be edited but will still be displayed and submitted. 790 func (f *FormPanel) FieldDisplayButCanNotEditWhenUpdate() *FormPanel { 791 f.FieldList[f.curFieldListIndex].Editable = false 792 return f 793 } 794 795 // FieldDisableWhenUpdate means when update record the field can not be edited, displayed and submitted. 796 func (f *FormPanel) FieldDisableWhenUpdate() *FormPanel { 797 f.FieldList[f.curFieldListIndex].NotAllowEdit = true 798 return f 799 } 800 801 // FieldNotAllowAdd means when create record the field can not be edited, displayed and submitted. 802 // Deprecated: Use FieldDisableWhenCreate instead. 803 func (f *FormPanel) FieldNotAllowAdd() *FormPanel { 804 f.FieldList[f.curFieldListIndex].NotAllowAdd = true 805 return f 806 } 807 808 // FieldDisableWhenCreate means when create record the field can not be edited, displayed and submitted. 809 func (f *FormPanel) FieldDisableWhenCreate() *FormPanel { 810 f.FieldList[f.curFieldListIndex].NotAllowAdd = true 811 return f 812 } 813 814 // FieldDisplayButCanNotEditWhenCreate means when create record the field can not be edited but will still be displayed and submitted. 815 func (f *FormPanel) FieldDisplayButCanNotEditWhenCreate() *FormPanel { 816 f.FieldList[f.curFieldListIndex].DisplayButNotAdd = true 817 return f 818 } 819 820 // FieldHideWhenCreate means when create record the field can not be edited and displayed, but will be submitted. 821 func (f *FormPanel) FieldHideWhenCreate() *FormPanel { 822 f.FieldList[f.curFieldListIndex].CreateHide = true 823 return f 824 } 825 826 // FieldHideWhenUpdate means when update record the field can not be edited and displayed, but will be submitted. 827 func (f *FormPanel) FieldHideWhenUpdate() *FormPanel { 828 f.FieldList[f.curFieldListIndex].EditHide = true 829 return f 830 } 831 832 func (f *FormPanel) FieldFormType(formType form2.Type) *FormPanel { 833 f.FieldList[f.curFieldListIndex].FormType = formType 834 return f 835 } 836 837 func (f *FormPanel) FieldValue(value string) *FormPanel { 838 f.FieldList[f.curFieldListIndex].Value = template.HTML(value) 839 return f 840 } 841 842 func (f *FormPanel) FieldOptionsFromTable(table, textFieldName, valueFieldName string, process ...OptionTableQueryProcessFn) *FormPanel { 843 var fn OptionTableQueryProcessFn 844 if len(process) > 0 { 845 fn = process[0] 846 } 847 f.FieldList[f.curFieldListIndex].OptionTable = OptionTable{ 848 Table: table, 849 TextField: textFieldName, 850 ValueField: valueFieldName, 851 QueryProcessFn: fn, 852 } 853 return f 854 } 855 856 func (f *FormPanel) FieldOptionsTableProcessFn(fn OptionProcessFn) *FormPanel { 857 f.FieldList[f.curFieldListIndex].OptionTable.ProcessFn = fn 858 return f 859 } 860 861 func (f *FormPanel) FieldOptions(options FieldOptions) *FormPanel { 862 f.FieldList[f.curFieldListIndex].Options = options 863 return f 864 } 865 866 func (f *FormPanel) FieldDefaultOptionDelimiter(delimiter string) *FormPanel { 867 f.FieldList[f.curFieldListIndex].DefaultOptionDelimiter = delimiter 868 return f 869 } 870 871 func (f *FormPanel) FieldPostFilterFn(post PostFieldFilterFn) *FormPanel { 872 f.FieldList[f.curFieldListIndex].PostFilterFn = post 873 return f 874 } 875 876 func (f *FormPanel) FieldNow() *FormPanel { 877 f.FieldList[f.curFieldListIndex].PostFilterFn = func(value PostFieldModel) interface{} { 878 return time.Now().Format("2006-01-02 15:04:05") 879 } 880 return f 881 } 882 883 func (f *FormPanel) FieldNowWhenUpdate() *FormPanel { 884 f.FieldList[f.curFieldListIndex].PostFilterFn = func(value PostFieldModel) interface{} { 885 if value.IsUpdate() { 886 return time.Now().Format("2006-01-02 15:04:05") 887 } 888 return value.Value.Value() 889 } 890 return f 891 } 892 893 func (f *FormPanel) FieldNowWhenInsert() *FormPanel { 894 f.FieldList[f.curFieldListIndex].PostFilterFn = func(value PostFieldModel) interface{} { 895 if value.IsCreate() { 896 return time.Now().Format("2006-01-02 15:04:05") 897 } 898 return value.Value.Value() 899 } 900 return f 901 } 902 903 func (f *FormPanel) FieldLimit(limit int) *FormPanel { 904 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddLimit(limit) 905 return f 906 } 907 908 func (f *FormPanel) FieldTrimSpace() *FormPanel { 909 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddTrimSpace() 910 return f 911 } 912 913 func (f *FormPanel) FieldSubstr(start int, end int) *FormPanel { 914 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddSubstr(start, end) 915 return f 916 } 917 918 func (f *FormPanel) FieldToTitle() *FormPanel { 919 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddToTitle() 920 return f 921 } 922 923 func (f *FormPanel) FieldToUpper() *FormPanel { 924 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddToUpper() 925 return f 926 } 927 928 func (f *FormPanel) FieldToLower() *FormPanel { 929 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].AddToLower() 930 return f 931 } 932 933 func (f *FormPanel) FieldXssFilter() *FormPanel { 934 f.FieldList[f.curFieldListIndex].DisplayProcessChains = f.FieldList[f.curFieldListIndex].DisplayProcessChains. 935 Add(func(value FieldModel) interface{} { 936 return html.EscapeString(value.Value) 937 }) 938 return f 939 } 940 941 func (f *FormPanel) FieldCustomContent(content template.HTML) *FormPanel { 942 f.FieldList[f.curFieldListIndex].CustomContent = content 943 return f 944 } 945 946 func (f *FormPanel) FieldCustomJs(js template.JS) *FormPanel { 947 f.FieldList[f.curFieldListIndex].CustomJs = js 948 return f 949 } 950 951 func (f *FormPanel) FieldCustomCss(css template.CSS) *FormPanel { 952 f.FieldList[f.curFieldListIndex].CustomCss = css 953 return f 954 } 955 956 func (f *FormPanel) FieldOnSearch(url string, handler Handler, delay ...int) *FormPanel { 957 ext, callback := searchJS(f.FieldList[f.curFieldListIndex].OptionExt, f.OperationURL(url), handler, delay...) 958 f.FieldList[f.curFieldListIndex].OptionExt = ext 959 f.Callbacks = f.Callbacks.AddCallback(callback) 960 return f 961 } 962 963 func (f *FormPanel) FieldOnChooseCustom(js template.HTML) *FormPanel { 964 f.FooterHtml += chooseCustomJS(f.FieldList[f.curFieldListIndex].Field, js) 965 return f 966 } 967 968 type LinkField struct { 969 Field string 970 Value template.HTML 971 Hide bool 972 Disable bool 973 } 974 975 func (f *FormPanel) FieldOnChooseMap(m map[string]LinkField) *FormPanel { 976 f.FooterHtml += chooseMapJS(f.FieldList[f.curFieldListIndex].Field, m) 977 return f 978 } 979 980 func (f *FormPanel) FieldOnChoose(val, field string, value template.HTML) *FormPanel { 981 f.FooterHtml += chooseJS(f.FieldList[f.curFieldListIndex].Field, field, val, value) 982 return f 983 } 984 985 func (f *FormPanel) OperationURL(id string) string { 986 return config.Url("/operation/" + utils.WrapURL(id)) 987 } 988 989 func (f *FormPanel) FieldOnChooseAjax(field, url string, handler Handler, custom ...template.HTML) *FormPanel { 990 js, callback := chooseAjax(f.FieldList[f.curFieldListIndex].Field, field, f.OperationURL(url), handler, custom...) 991 f.FooterHtml += js 992 f.Callbacks = f.Callbacks.AddCallback(callback) 993 return f 994 } 995 996 func (f *FormPanel) FieldOnChooseHide(value string, field ...string) *FormPanel { 997 f.FooterHtml += chooseHideJS(f.FieldList[f.curFieldListIndex].Field, []string{value}, field...) 998 return f 999 } 1000 1001 func (f *FormPanel) FieldOnChooseOptionsHide(values []string, field ...string) *FormPanel { 1002 f.FooterHtml += chooseHideJS(f.FieldList[f.curFieldListIndex].Field, values, field...) 1003 return f 1004 } 1005 1006 func (f *FormPanel) FieldOnChooseShow(value string, field ...string) *FormPanel { 1007 f.FooterHtml += chooseShowJS(f.FieldList[f.curFieldListIndex].Field, []string{value}, field...) 1008 return f 1009 } 1010 1011 func (f *FormPanel) FieldOnChooseOptionsShow(values []string, field ...string) *FormPanel { 1012 f.FooterHtml += chooseShowJS(f.FieldList[f.curFieldListIndex].Field, values, field...) 1013 return f 1014 } 1015 1016 func (f *FormPanel) FieldOnChooseDisable(value string, field ...string) *FormPanel { 1017 f.FooterHtml += chooseDisableJS(f.FieldList[f.curFieldListIndex].Field, []string{value}, field...) 1018 return f 1019 } 1020 1021 func (f *FormPanel) addFooterHTML(footer template.HTML) *FormPanel { 1022 f.FooterHtml += template.HTML(ParseTableDataTmpl(footer)) 1023 return f 1024 } 1025 1026 func (f *FormPanel) AddCSS(css template.CSS) *FormPanel { 1027 return f.addFooterHTML(template.HTML("<style>" + css + "</style>")) 1028 } 1029 1030 func (f *FormPanel) AddJS(js template.JS) *FormPanel { 1031 return f.addFooterHTML(template.HTML("<script>" + js + "</script>")) 1032 } 1033 1034 func searchJS(ext template.JS, url string, handler Handler, delay ...int) (template.JS, context.Node) { 1035 delayStr := "500" 1036 if len(delay) > 0 { 1037 delayStr = strconv.Itoa(delay[0]) 1038 } 1039 1040 if ext != template.JS("") { 1041 s := string(ext) 1042 s = strings.Replace(s, "{", "", 1) 1043 s = utils.ReplaceNth(s, "}", "", strings.Count(s, "}")) 1044 s = strings.TrimRight(s, " ") 1045 s += "," 1046 ext = template.JS(s) 1047 } 1048 1049 return template.JS(`{ 1050 `) + ext + template.JS(` 1051 ajax: { 1052 url: "`+url+`", 1053 dataType: 'json', 1054 data: function (params) { 1055 var query = { 1056 search: params.term, 1057 page: params.page || 1 1058 } 1059 return query; 1060 }, 1061 delay: `+delayStr+`, 1062 processResults: function (data, params) { 1063 return data.data; 1064 } 1065 } 1066 }`), context.Node{ 1067 Path: url, 1068 Method: "get", 1069 Handlers: context.Handlers{handler.Wrap()}, 1070 Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, 1071 } 1072 } 1073 1074 func chooseCustomJS(field string, js template.HTML) template.HTML { 1075 return utils.ParseHTML("choose_custom", tmpls["choose_custom"], struct { 1076 Field template.JS 1077 JS template.JS 1078 }{Field: template.JS(field), JS: template.JS(js)}) 1079 } 1080 1081 func chooseMapJS(field string, m map[string]LinkField) template.HTML { 1082 return utils.ParseHTML("choose_map", tmpls["choose_map"], struct { 1083 Field template.JS 1084 Data map[string]LinkField 1085 }{ 1086 Field: template.JS(field), 1087 Data: m, 1088 }) 1089 } 1090 1091 func chooseJS(field, chooseField, val string, value template.HTML) template.HTML { 1092 return utils.ParseHTML("choose", tmpls["choose"], struct { 1093 Field template.JS 1094 ChooseField template.JS 1095 Val template.JS 1096 Value template.JS 1097 }{ 1098 Field: template.JS(field), 1099 ChooseField: template.JS(chooseField), 1100 Value: decorateChooseValue([]string{string(value)}), 1101 Val: decorateChooseValue([]string{string(val)}), 1102 }) 1103 } 1104 1105 func chooseAjax(field, chooseField, url string, handler Handler, js ...template.HTML) (template.HTML, context.Node) { 1106 1107 actionJS := template.HTML("") 1108 passValue := template.JS("") 1109 1110 if len(js) > 0 { 1111 actionJS = js[0] 1112 } 1113 1114 if len(js) > 1 { 1115 passValue = template.JS(js[1]) 1116 } 1117 1118 return utils.ParseHTML("choose_ajax", tmpls["choose_ajax"], struct { 1119 Field template.JS 1120 ChooseField template.JS 1121 PassValue template.JS 1122 ActionJS template.JS 1123 Url template.JS 1124 }{ 1125 Url: template.JS(url), 1126 Field: template.JS(field), 1127 ChooseField: template.JS(chooseField), 1128 PassValue: passValue, 1129 ActionJS: template.JS(actionJS), 1130 }), context.Node{ 1131 Path: url, 1132 Method: "post", 1133 Handlers: context.Handlers{handler.Wrap()}, 1134 Value: map[string]interface{}{constant.ContextNodeNeedAuth: 1}, 1135 } 1136 } 1137 1138 func chooseHideJS(field string, value []string, chooseFields ...string) template.HTML { 1139 if len(chooseFields) == 0 { 1140 return "" 1141 } 1142 1143 return utils.ParseHTML("choose_hide", tmpls["choose_hide"], struct { 1144 Field template.JS 1145 Value template.JS 1146 ChooseFields []string 1147 }{ 1148 Field: template.JS(field), 1149 Value: decorateChooseValue(value), 1150 ChooseFields: chooseFields, 1151 }) 1152 } 1153 1154 func chooseShowJS(field string, value []string, chooseFields ...string) template.HTML { 1155 if len(chooseFields) == 0 { 1156 return "" 1157 } 1158 1159 return utils.ParseHTML("choose_show", tmpls["choose_show"], struct { 1160 Field template.JS 1161 Value template.JS 1162 ChooseFields []string 1163 }{ 1164 Field: template.JS(field), 1165 Value: decorateChooseValue(value), 1166 ChooseFields: chooseFields, 1167 }) 1168 } 1169 1170 func chooseDisableJS(field string, value []string, chooseFields ...string) template.HTML { 1171 if len(chooseFields) == 0 { 1172 return "" 1173 } 1174 1175 return utils.ParseHTML("choose_disable", tmpls["choose_disable"], struct { 1176 Field template.JS 1177 Value template.JS 1178 ChooseFields []string 1179 }{ 1180 Field: template.JS(field), 1181 Value: decorateChooseValue(value), 1182 ChooseFields: chooseFields, 1183 }) 1184 } 1185 1186 func decorateChooseValue(val []string) template.JS { 1187 if len(val) == 0 { 1188 return "" 1189 } 1190 1191 res := make([]string, len(val)) 1192 1193 for k, v := range val { 1194 1195 if v == "" { 1196 v = `""` 1197 } 1198 1199 if v[0] != '"' { 1200 if strings.Contains(v, "$(this)") { 1201 res[k] = v 1202 } 1203 if v == "{{.vue}}" { 1204 res[k] = "$(this).v()" 1205 } 1206 if len(v) > 3 && v[:3] == "js:" { 1207 res[k] = v[3:] 1208 } 1209 res[k] = `"` + v + `"` 1210 } else { 1211 res[k] = v 1212 } 1213 } 1214 1215 return template.JS("[" + strings.Join(res, ",") + "]") 1216 } 1217 1218 // FormPanel attribute setting functions 1219 // ==================================================== 1220 1221 func (f *FormPanel) SetTitle(title string) *FormPanel { 1222 f.Title = title 1223 return f 1224 } 1225 1226 func (f *FormPanel) SetTabGroups(groups TabGroups) *FormPanel { 1227 f.TabGroups = groups 1228 return f 1229 } 1230 1231 func (f *FormPanel) SetTabHeaders(headers ...string) *FormPanel { 1232 f.TabHeaders = headers 1233 return f 1234 } 1235 1236 func (f *FormPanel) SetDescription(desc string) *FormPanel { 1237 f.Description = desc 1238 return f 1239 } 1240 1241 func (f *FormPanel) SetHeaderHtml(header template.HTML) *FormPanel { 1242 f.HeaderHtml += header 1243 return f 1244 } 1245 1246 func (f *FormPanel) SetFooterHtml(footer template.HTML) *FormPanel { 1247 f.FooterHtml += footer 1248 return f 1249 } 1250 1251 func (f *FormPanel) HasError() bool { 1252 return f.PageError != nil 1253 } 1254 1255 func (f *FormPanel) SetError(err errors.PageError, content ...template.HTML) *FormPanel { 1256 f.PageError = err 1257 if len(content) > 0 { 1258 f.PageErrorHTML = content[0] 1259 } 1260 return f 1261 } 1262 1263 func (f *FormPanel) SetNoCompress() *FormPanel { 1264 f.NoCompress = true 1265 return f 1266 } 1267 1268 func (f *FormPanel) Set404Error(content ...template.HTML) *FormPanel { 1269 f.SetError(errors.PageError404, content...) 1270 return f 1271 } 1272 1273 func (f *FormPanel) Set403Error(content ...template.HTML) *FormPanel { 1274 f.SetError(errors.PageError403, content...) 1275 return f 1276 } 1277 1278 func (f *FormPanel) Set400Error(content ...template.HTML) *FormPanel { 1279 f.SetError(errors.PageError401, content...) 1280 return f 1281 } 1282 1283 func (f *FormPanel) Set500Error(content ...template.HTML) *FormPanel { 1284 f.SetError(errors.PageError500, content...) 1285 return f 1286 } 1287 1288 func (f *FormPanel) SetLayout(layout form2.Layout) *FormPanel { 1289 f.Layout = layout 1290 return f 1291 } 1292 1293 func (f *FormPanel) SetPostValidator(va FormPostFn) *FormPanel { 1294 f.Validator = va 1295 return f 1296 } 1297 1298 func (f *FormPanel) SetPreProcessFn(fn FormPreProcessFn) *FormPanel { 1299 f.PreProcessFn = fn 1300 return f 1301 } 1302 1303 func (f *FormPanel) SetHTMLContent(content template.HTML) *FormPanel { 1304 f.HTMLContent = content 1305 return f 1306 } 1307 1308 func (f *FormPanel) SetHeader(content template.HTML) *FormPanel { 1309 f.Header = content 1310 return f 1311 } 1312 1313 func (f *FormPanel) SetInputWidth(width int) *FormPanel { 1314 f.InputWidth = width 1315 return f 1316 } 1317 1318 func (f *FormPanel) SetHeadWidth(width int) *FormPanel { 1319 f.HeadWidth = width 1320 return f 1321 } 1322 1323 func (f *FormPanel) SetWrapper(wrapper ContentWrapper) *FormPanel { 1324 f.Wrapper = wrapper 1325 return f 1326 } 1327 1328 func (f *FormPanel) SetHideSideBar() *FormPanel { 1329 f.HideSideBar = true 1330 return f 1331 } 1332 1333 func (f *FormPanel) SetFormNewTitle(title template.HTML) *FormPanel { 1334 f.FormNewTitle = title 1335 return f 1336 } 1337 1338 func (f *FormPanel) SetFormNewBtnWord(word template.HTML) *FormPanel { 1339 f.FormNewBtnWord = word 1340 return f 1341 } 1342 1343 func (f *FormPanel) SetFormEditTitle(title template.HTML) *FormPanel { 1344 f.FormEditTitle = title 1345 return f 1346 } 1347 1348 func (f *FormPanel) SetFormEditBtnWord(word template.HTML) *FormPanel { 1349 f.FormEditBtnWord = word 1350 return f 1351 } 1352 1353 func (f *FormPanel) SetResponder(responder Responder) *FormPanel { 1354 f.Responder = responder 1355 return f 1356 } 1357 1358 type AjaxData struct { 1359 SuccessTitle string 1360 SuccessText string 1361 ErrorTitle string 1362 ErrorText string 1363 SuccessJumpURL string 1364 DisableJump bool 1365 SuccessJS string 1366 JumpInNewTab string 1367 } 1368 1369 func (f *FormPanel) EnableAjaxData(data AjaxData) *FormPanel { 1370 f.Ajax = true 1371 if f.AjaxSuccessJS == template.JS("") { 1372 successMsg := modules.AorB(data.SuccessTitle != "", `"`+data.SuccessTitle+`"`, "data.msg") 1373 errorMsg := modules.AorB(data.ErrorTitle != "", `"`+data.ErrorTitle+`"`, "data.msg") 1374 jump := modules.AorB(data.SuccessJumpURL != "", `"`+data.SuccessJumpURL+`"`, "data.data.url") 1375 text := modules.AorB(data.SuccessText != "", `text:"`+data.SuccessText+`",`, "") 1376 wrongText := modules.AorB(data.ErrorText != "", `text:"`+data.ErrorText+`",`, "text:data.msg,") 1377 jumpURL := "" 1378 if !data.DisableJump { 1379 if data.JumpInNewTab != "" { 1380 jumpURL = `listenerForAddNavTab(` + jump + `, "` + data.JumpInNewTab + `");` 1381 } 1382 jumpURL += `$.pjax({url: ` + jump + `, container: '#pjax-container'});` 1383 } else { 1384 jumpURL = ` 1385 if (data.data && data.data.token !== "") { 1386 $("input[name='__go_admin_t_']").val(data.data.token) 1387 }` 1388 } 1389 f.AjaxSuccessJS = template.JS(` 1390 if (typeof (data) === "string") { 1391 data = JSON.parse(data); 1392 } 1393 if (data.code === 200) { 1394 swal({ 1395 type: "success", 1396 title: ` + successMsg + `, 1397 ` + text + ` 1398 showCancelButton: false, 1399 confirmButtonColor: "#3c8dbc", 1400 confirmButtonText: '` + language.Get("got it") + `', 1401 }, function() { 1402 $(".modal-backdrop.fade.in").remove(); 1403 ` + jumpURL + ` 1404 ` + data.SuccessJS + ` 1405 }); 1406 } else { 1407 if (data.data && data.data.token !== "") { 1408 $("input[name='__go_admin_t_']").val(data.data.token); 1409 } 1410 swal({ 1411 type: "error", 1412 title: ` + errorMsg + `, 1413 ` + wrongText + ` 1414 showCancelButton: false, 1415 confirmButtonColor: "#3c8dbc", 1416 confirmButtonText: '` + language.Get("got it") + `', 1417 }) 1418 } 1419 `) 1420 } 1421 if f.AjaxErrorJS == template.JS("") { 1422 errorMsg := modules.AorB(data.ErrorTitle != "", `"`+data.ErrorTitle+`"`, "data.responseJSON.msg") 1423 error2Msg := modules.AorB(data.ErrorTitle != "", `"`+data.ErrorTitle+`"`, "'"+language.Get("error")+"'") 1424 wrongText := modules.AorB(data.ErrorText != "", `text:"`+data.ErrorText+`",`, "text:data.msg,") 1425 f.AjaxErrorJS = template.JS(` 1426 if (data.responseText !== "") { 1427 if (data.responseJSON.data && data.responseJSON.data.token !== "") { 1428 $("input[name='__go_admin_t_']").val(data.responseJSON.data.token) 1429 } 1430 swal({ 1431 type: "error", 1432 title: ` + errorMsg + `, 1433 ` + wrongText + ` 1434 showCancelButton: false, 1435 confirmButtonColor: "#3c8dbc", 1436 confirmButtonText: '` + language.Get("got it") + `', 1437 }) 1438 } else { 1439 swal({ 1440 type: "error", 1441 title: ` + error2Msg + `, 1442 ` + wrongText + ` 1443 showCancelButton: false, 1444 confirmButtonColor: "#3c8dbc", 1445 confirmButtonText: '` + language.Get("got it") + `', 1446 }) 1447 } 1448 `) 1449 } 1450 return f 1451 } 1452 1453 func (f *FormPanel) EnableAjax(msgs ...string) *FormPanel { 1454 var data AjaxData 1455 if len(msgs) > 0 && msgs[0] != "" { 1456 data.SuccessTitle = msgs[0] 1457 } 1458 if len(msgs) > 1 && msgs[1] != "" { 1459 data.ErrorTitle = msgs[1] 1460 } 1461 if len(msgs) > 2 && msgs[2] != "" { 1462 data.SuccessJumpURL = msgs[2] 1463 } 1464 if len(msgs) > 3 && msgs[3] != "" { 1465 data.SuccessText = msgs[3] 1466 } 1467 if len(msgs) > 4 && msgs[4] != "" { 1468 data.ErrorText = msgs[4] 1469 } 1470 return f.EnableAjaxData(data) 1471 } 1472 1473 func (f *FormPanel) SetAjaxSuccessJS(js template.JS) *FormPanel { 1474 f.AjaxSuccessJS = js 1475 return f 1476 } 1477 1478 func (f *FormPanel) SetAjaxErrorJS(js template.JS) *FormPanel { 1479 f.AjaxErrorJS = js 1480 return f 1481 } 1482 1483 func (f *FormPanel) SetPostHook(fn FormPostFn) *FormPanel { 1484 f.PostHook = fn 1485 return f 1486 } 1487 1488 func (f *FormPanel) SetUpdateFn(fn FormPostFn) *FormPanel { 1489 f.UpdateFn = fn 1490 return f 1491 } 1492 1493 func (f *FormPanel) SetInsertFn(fn FormPostFn) *FormPanel { 1494 f.InsertFn = fn 1495 return f 1496 } 1497 1498 func (f *FormPanel) GroupFieldWithValue(pk, id string, columns []string, res map[string]interface{}, sql func() *db.SQL) ([]FormFields, []string) { 1499 var ( 1500 groupFormList = make([]FormFields, 0) 1501 groupHeaders = make([]string, 0) 1502 hasPK = false 1503 existField = make([]string, 0) 1504 ) 1505 1506 if len(f.TabGroups) > 0 { 1507 for index, group := range f.TabGroups { 1508 list := make(FormFields, 0) 1509 for index, fieldName := range group { 1510 label := "_ga_group_" + strconv.Itoa(index) 1511 field := f.FieldList.FindByFieldName(fieldName) 1512 if field != nil && field.isNotBelongToATable() && !field.NotAllowEdit { 1513 if !field.Hide { 1514 field.Hide = field.EditHide 1515 } 1516 if field.FormType.IsTable() { 1517 for z := 0; z < len(field.TableFields); z++ { 1518 rowValue := field.TableFields[z].GetRawValue(columns, res[field.TableFields[z].Field]) 1519 if field.TableFields[z].Field == pk { 1520 hasPK = true 1521 } 1522 field.TableFields[z] = *(field.TableFields[z].UpdateValue(id, rowValue, res, sql())) 1523 } 1524 if utils.InArray(existField, field.Field) { 1525 field.Field = field.Field + label 1526 } 1527 list = append(list, *field) 1528 existField = append(existField, field.Field) 1529 } else { 1530 if field.Field == pk { 1531 hasPK = true 1532 } 1533 rowValue := field.GetRawValue(columns, res[field.Field]) 1534 if utils.InArray(existField, field.Field) { 1535 field.Field = field.Field + label 1536 } 1537 list = append(list, *(field.UpdateValue(id, rowValue, res, sql()))) 1538 existField = append(existField, field.Field) 1539 } 1540 } 1541 } 1542 1543 groupFormList = append(groupFormList, list.FillCustomContent()) 1544 groupHeaders = append(groupHeaders, f.TabHeaders[index]) 1545 } 1546 1547 if len(groupFormList) > 0 && !hasPK { 1548 groupFormList[len(groupFormList)-1] = groupFormList[len(groupFormList)-1].Add(&FormField{ 1549 Head: pk, 1550 FieldClass: pk, 1551 Field: pk, 1552 Value: template.HTML(id), 1553 Hide: true, 1554 }) 1555 } 1556 } 1557 1558 return groupFormList, groupHeaders 1559 } 1560 1561 func (f *FormPanel) GroupField(sql ...func() *db.SQL) ([]FormFields, []string) { 1562 var ( 1563 groupFormList = make([]FormFields, 0) 1564 groupHeaders = make([]string, 0) 1565 existField = make([]string, 0) 1566 ) 1567 1568 for index, group := range f.TabGroups { 1569 list := make(FormFields, 0) 1570 for index, fieldName := range group { 1571 field := f.FieldList.FindByFieldName(fieldName) 1572 label := "_ga_group_" + strconv.Itoa(index) 1573 if field != nil && field.isNotBelongToATable() && field.allowAdd() { 1574 field.Editable = !field.DisplayButNotAdd 1575 if !field.Hide { 1576 field.Hide = field.CreateHide 1577 } 1578 if field.FormType.IsTable() { 1579 for z := 0; z < len(field.TableFields); z++ { 1580 if len(sql) > 0 { 1581 field.TableFields[z] = *(field.TableFields[z].UpdateDefaultValue(sql[0]())) 1582 } else { 1583 field.TableFields[z] = *(field.TableFields[z].UpdateDefaultValue(nil)) 1584 } 1585 } 1586 if utils.InArray(existField, field.Field) { 1587 field.Field = field.Field + label 1588 } 1589 list = append(list, *field) 1590 existField = append(existField, field.Field) 1591 } else { 1592 if utils.InArray(existField, field.Field) { 1593 field.Field = field.Field + label 1594 } 1595 if len(sql) > 0 { 1596 list = append(list, *(field.UpdateDefaultValue(sql[0]()))) 1597 } else { 1598 list = append(list, *(field.UpdateDefaultValue(nil))) 1599 } 1600 existField = append(existField, field.Field) 1601 } 1602 } 1603 } 1604 groupFormList = append(groupFormList, list.FillCustomContent()) 1605 groupHeaders = append(groupHeaders, f.TabHeaders[index]) 1606 } 1607 1608 return groupFormList, groupHeaders 1609 } 1610 1611 func (f *FormPanel) FieldsWithValue(pk, id string, columns []string, res map[string]interface{}, sql func() *db.SQL) FormFields { 1612 var ( 1613 list = make(FormFields, 0) 1614 hasPK = false 1615 ) 1616 for i := 0; i < len(f.FieldList); i++ { 1617 if !f.FieldList[i].NotAllowEdit { 1618 if !f.FieldList[i].Hide { 1619 f.FieldList[i].Hide = f.FieldList[i].EditHide 1620 } 1621 rowValue := f.FieldList[i].GetRawValue(columns, res[f.FieldList[i].Field]) 1622 if f.FieldList[i].FatherField != "" { 1623 f.FieldList.FindTableField(f.FieldList[i].Field, f.FieldList[i].FatherField).UpdateValue(id, rowValue, res, sql()) 1624 } else if f.FieldList[i].FormType.IsTable() { 1625 list = append(list, f.FieldList[i]) 1626 } else { 1627 list = append(list, *(f.FieldList[i].UpdateValue(id, rowValue, res, sql()))) 1628 } 1629 1630 if f.FieldList[i].Field == pk { 1631 hasPK = true 1632 } 1633 } 1634 } 1635 if !hasPK { 1636 list = list.Add(&FormField{ 1637 Head: pk, 1638 FieldClass: pk, 1639 Field: pk, 1640 Value: template.HTML(id), 1641 FormType: form2.Default, 1642 Hide: true, 1643 }) 1644 } 1645 return list.FillCustomContent() 1646 } 1647 1648 func (f *FormPanel) FieldsWithDefaultValue(sql ...func() *db.SQL) FormFields { 1649 var list = make(FormFields, 0) 1650 for i := 0; i < len(f.FieldList); i++ { 1651 if f.FieldList[i].allowAdd() { 1652 f.FieldList[i].Editable = !f.FieldList[i].DisplayButNotAdd 1653 if !f.FieldList[i].Hide { 1654 f.FieldList[i].Hide = f.FieldList[i].CreateHide 1655 } 1656 if f.FieldList[i].FatherField != "" { 1657 if len(sql) > 0 { 1658 f.FieldList.FindTableField(f.FieldList[i].Field, f.FieldList[i].FatherField).UpdateDefaultValue(sql[0]()) 1659 } else { 1660 f.FieldList.FindTableField(f.FieldList[i].Field, f.FieldList[i].FatherField).UpdateDefaultValue(nil) 1661 } 1662 } else if f.FieldList[i].FormType.IsTable() { 1663 list = append(list, f.FieldList[i]) 1664 } else { 1665 if len(sql) > 0 { 1666 list = append(list, *(f.FieldList[i].UpdateDefaultValue(sql[0]()))) 1667 } else { 1668 list = append(list, *(f.FieldList[i].UpdateDefaultValue(nil))) 1669 } 1670 } 1671 } 1672 } 1673 return list.FillCustomContent().RemoveNotShow() 1674 } 1675 1676 func (f *FormPanel) GetNewFormFields(sql ...func() *db.SQL) (FormFields, []FormFields, []string) { 1677 if len(f.TabGroups) > 0 { 1678 tabFields, tabHeaders := f.GroupField(sql...) 1679 return make(FormFields, 0), tabFields, tabHeaders 1680 } 1681 return f.FieldsWithDefaultValue(sql...), make([]FormFields, 0), make([]string, 0) 1682 } 1683 1684 type ( 1685 FormPreProcessFn func(values form.Values) form.Values 1686 FormPostFn func(values form.Values) error 1687 FormFields []FormField 1688 GroupFormFields []FormFields 1689 GroupFieldHeaders []string 1690 ) 1691 1692 func (f FormFields) Copy() FormFields { 1693 formList := make(FormFields, len(f)) 1694 copy(formList, f) 1695 for i := 0; i < len(formList); i++ { 1696 formList[i].Options = make(FieldOptions, len(f[i].Options)) 1697 for j := 0; j < len(f[i].Options); j++ { 1698 formList[i].Options[j] = FieldOption{ 1699 Value: f[i].Options[j].Value, 1700 Text: f[i].Options[j].Text, 1701 TextHTML: f[i].Options[j].TextHTML, 1702 Selected: f[i].Options[j].Selected, 1703 } 1704 } 1705 } 1706 return formList 1707 } 1708 1709 func (f FormFields) FindByFieldName(field string) *FormField { 1710 for i := 0; i < len(f); i++ { 1711 if f[i].Field == field { 1712 return &f[i] 1713 } 1714 } 1715 return nil 1716 } 1717 1718 func (f FormFields) FindIndexByFieldName(field string) int { 1719 for i := 0; i < len(f); i++ { 1720 if f[i].Field == field { 1721 return i 1722 } 1723 } 1724 return -1 1725 } 1726 1727 func (f FormFields) FindTableField(field, father string) *FormField { 1728 ff := f.FindByFieldName(father) 1729 return ff.TableFields.FindByFieldName(field) 1730 } 1731 1732 func (f FormFields) FindTableChildren(father string) []*FormField { 1733 list := make([]*FormField, 0) 1734 for i := 0; i < len(f); i++ { 1735 if f[i].FatherField == father { 1736 list = append(list, &f[i]) 1737 } 1738 } 1739 return list 1740 } 1741 1742 func (f FormFields) FillCustomContent() FormFields { 1743 for i := range f { 1744 if f[i].FormType.IsCustom() { 1745 f[i] = *(f[i]).FillCustomContent() 1746 } 1747 } 1748 return f 1749 } 1750 1751 func (f FormFields) Add(field *FormField) FormFields { 1752 return append(f, *field) 1753 } 1754 1755 func (f FormFields) RemoveNotShow() FormFields { 1756 ff := f 1757 for i := 0; i < len(ff); { 1758 if ff[i].FatherFormType == form2.Table { 1759 ff = append(ff[:i], ff[i+1:]...) 1760 } else { 1761 i++ 1762 } 1763 } 1764 return ff 1765 }