github.com/kotovmak/go-admin@v1.1.1/plugins/admin/modules/table/generators.go (about)

     1  package table
     2  
     3  import (
     4  	"database/sql"
     5  	"errors"
     6  	"fmt"
     7  	tmpl "html/template"
     8  	"net/url"
     9  	"reflect"
    10  	"regexp"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/GoAdminGroup/html"
    16  	"github.com/kotovmak/go-admin/context"
    17  	"github.com/kotovmak/go-admin/modules/collection"
    18  	"github.com/kotovmak/go-admin/modules/config"
    19  	"github.com/kotovmak/go-admin/modules/db"
    20  	"github.com/kotovmak/go-admin/modules/db/dialect"
    21  	errs "github.com/kotovmak/go-admin/modules/errors"
    22  	"github.com/kotovmak/go-admin/modules/language"
    23  	"github.com/kotovmak/go-admin/modules/logger"
    24  	"github.com/kotovmak/go-admin/modules/ui"
    25  	"github.com/kotovmak/go-admin/modules/utils"
    26  	"github.com/kotovmak/go-admin/plugins/admin/models"
    27  	form2 "github.com/kotovmak/go-admin/plugins/admin/modules/form"
    28  	"github.com/kotovmak/go-admin/plugins/admin/modules/parameter"
    29  	"github.com/kotovmak/go-admin/plugins/admin/modules/tools"
    30  	"github.com/kotovmak/go-admin/template"
    31  	"github.com/kotovmak/go-admin/template/types"
    32  	"github.com/kotovmak/go-admin/template/types/action"
    33  	"github.com/kotovmak/go-admin/template/types/form"
    34  	selection "github.com/kotovmak/go-admin/template/types/form/select"
    35  	"golang.org/x/crypto/bcrypt"
    36  )
    37  
    38  type SystemTable struct {
    39  	conn db.Connection
    40  	c    *config.Config
    41  }
    42  
    43  func NewSystemTable(conn db.Connection, c *config.Config) *SystemTable {
    44  	return &SystemTable{conn: conn, c: c}
    45  }
    46  
    47  func (s *SystemTable) GetManagerTable(ctx *context.Context) (managerTable Table) {
    48  	managerTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver))
    49  
    50  	info := managerTable.GetInfo().AddXssJsFilter().HideFilterArea()
    51  
    52  	info.AddField("ID", "id", db.Int).FieldSortable()
    53  	info.AddField(lg("Name"), "username", db.Varchar).FieldFilterable()
    54  	info.AddField(lg("Nickname"), "name", db.Varchar).FieldFilterable()
    55  	info.AddField(lg("role"), "name", db.Varchar).
    56  		FieldJoin(types.Join{
    57  			Table:     "goadmin_role_users",
    58  			JoinField: "user_id",
    59  			Field:     "id",
    60  		}).
    61  		FieldJoin(types.Join{
    62  			Table:     "goadmin_roles",
    63  			JoinField: "id",
    64  			Field:     "role_id",
    65  			BaseTable: "goadmin_role_users",
    66  		}).
    67  		FieldDisplay(func(model types.FieldModel) interface{} {
    68  			labels := template.HTML("")
    69  			labelTpl := label().SetType("success")
    70  
    71  			labelValues := strings.Split(model.Value, types.JoinFieldValueDelimiter)
    72  			for key, label := range labelValues {
    73  				if key == len(labelValues)-1 {
    74  					labels += labelTpl.SetContent(template.HTML(label)).GetContent()
    75  				} else {
    76  					labels += labelTpl.SetContent(template.HTML(label)).GetContent() + "<br><br>"
    77  				}
    78  			}
    79  
    80  			if labels == template.HTML("") {
    81  				return lg("no roles")
    82  			}
    83  
    84  			return labels
    85  		}).FieldFilterable()
    86  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
    87  	info.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
    88  
    89  	info.SetTable("goadmin_users").
    90  		SetTitle(lg("Managers")).
    91  		SetDescription(lg("Managers")).
    92  		SetDeleteFn(func(idArr []string) error {
    93  
    94  			var ids = interfaces(idArr)
    95  
    96  			_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
    97  
    98  				deleteUserRoleErr := s.connection().WithTx(tx).
    99  					Table("goadmin_role_users").
   100  					WhereIn("user_id", ids).
   101  					Delete()
   102  
   103  				if db.CheckError(deleteUserRoleErr, db.DELETE) {
   104  					return deleteUserRoleErr, nil
   105  				}
   106  
   107  				deleteUserPermissionErr := s.connection().WithTx(tx).
   108  					Table("goadmin_user_permissions").
   109  					WhereIn("user_id", ids).
   110  					Delete()
   111  
   112  				if db.CheckError(deleteUserPermissionErr, db.DELETE) {
   113  					return deleteUserPermissionErr, nil
   114  				}
   115  
   116  				deleteUserErr := s.connection().WithTx(tx).
   117  					Table("goadmin_users").
   118  					WhereIn("id", ids).
   119  					Delete()
   120  
   121  				if db.CheckError(deleteUserErr, db.DELETE) {
   122  					return deleteUserErr, nil
   123  				}
   124  
   125  				return nil, nil
   126  			})
   127  
   128  			return txErr
   129  		})
   130  
   131  	formList := managerTable.GetForm().AddXssJsFilter()
   132  
   133  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   134  	formList.AddField(lg("Name"), "username", db.Varchar, form.Text).
   135  		FieldHelpMsg(template.HTML(lg("use for login"))).FieldMust()
   136  	formList.AddField(lg("Nickname"), "name", db.Varchar, form.Text).
   137  		FieldHelpMsg(template.HTML(lg("use to display"))).FieldMust()
   138  	formList.AddField(lg("Avatar"), "avatar", db.Varchar, form.File)
   139  	formList.AddField(lg("role"), "role_id", db.Varchar, form.Select).
   140  		FieldOptionsFromTable("goadmin_roles", "slug", "id").
   141  		FieldDisplay(func(model types.FieldModel) interface{} {
   142  			var roles []string
   143  
   144  			if model.ID == "" {
   145  				return roles
   146  			}
   147  			roleModel, _ := s.table("goadmin_role_users").Select("role_id").
   148  				Where("user_id", "=", model.ID).All()
   149  			for _, v := range roleModel {
   150  				roles = append(roles, strconv.FormatInt(v["role_id"].(int64), 10))
   151  			}
   152  			return roles
   153  		}).FieldHelpMsg(template.HTML(lg("no corresponding options?")) +
   154  		link("/admin/info/roles/new", "Create here."))
   155  
   156  	formList.AddField(lg("permission"), "permission_id", db.Varchar, form.Select).
   157  		FieldOptionsFromTable("goadmin_permissions", "slug", "id").
   158  		FieldDisplay(func(model types.FieldModel) interface{} {
   159  			var permissions []string
   160  
   161  			if model.ID == "" {
   162  				return permissions
   163  			}
   164  			permissionModel, _ := s.table("goadmin_user_permissions").
   165  				Select("permission_id").Where("user_id", "=", model.ID).All()
   166  			for _, v := range permissionModel {
   167  				permissions = append(permissions, strconv.FormatInt(v["permission_id"].(int64), 10))
   168  			}
   169  			return permissions
   170  		}).FieldHelpMsg(template.HTML(lg("no corresponding options?")) +
   171  		link("/admin/info/permission/new", "Create here."))
   172  
   173  	formList.AddField(lg("password"), "password", db.Varchar, form.Password).
   174  		FieldDisplay(func(value types.FieldModel) interface{} {
   175  			return ""
   176  		})
   177  	formList.AddField(lg("confirm password"), "password_again", db.Varchar, form.Password).
   178  		FieldDisplay(func(value types.FieldModel) interface{} {
   179  			return ""
   180  		})
   181  
   182  	formList.SetTable("goadmin_users").SetTitle(lg("Managers")).SetDescription(lg("Managers"))
   183  	formList.SetUpdateFn(func(values form2.Values) error {
   184  
   185  		if values.IsEmpty("name", "username") {
   186  			return errors.New("username and password can not be empty")
   187  		}
   188  
   189  		user := models.UserWithId(values.Get("id")).SetConn(s.conn)
   190  
   191  		password := values.Get("password")
   192  
   193  		if password != "" {
   194  
   195  			if password != values.Get("password_again") {
   196  				return errors.New("password does not match")
   197  			}
   198  
   199  			password = encodePassword([]byte(values.Get("password")))
   200  		}
   201  
   202  		_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   203  
   204  			avatar := values.Get("avatar")
   205  
   206  			if values.Get("avatar__delete_flag") == "1" {
   207  				avatar = ""
   208  			}
   209  
   210  			_, updateUserErr := user.WithTx(tx).Update(values.Get("username"),
   211  				password, values.Get("name"), avatar, values.Get("avatar__change_flag") == "1")
   212  
   213  			if db.CheckError(updateUserErr, db.UPDATE) {
   214  				return updateUserErr, nil
   215  			}
   216  
   217  			delRoleErr := user.WithTx(tx).DeleteRoles()
   218  
   219  			if db.CheckError(delRoleErr, db.DELETE) {
   220  				return delRoleErr, nil
   221  			}
   222  
   223  			for i := 0; i < len(values["role_id[]"]); i++ {
   224  				_, addRoleErr := user.WithTx(tx).AddRole(values["role_id[]"][i])
   225  				if db.CheckError(addRoleErr, db.INSERT) {
   226  					return addRoleErr, nil
   227  				}
   228  			}
   229  
   230  			delPermissionErr := user.WithTx(tx).DeletePermissions()
   231  
   232  			if db.CheckError(delPermissionErr, db.DELETE) {
   233  				return delPermissionErr, nil
   234  			}
   235  
   236  			for i := 0; i < len(values["permission_id[]"]); i++ {
   237  				_, addPermissionErr := user.WithTx(tx).AddPermission(values["permission_id[]"][i])
   238  				if db.CheckError(addPermissionErr, db.INSERT) {
   239  					return addPermissionErr, nil
   240  				}
   241  			}
   242  
   243  			return nil, nil
   244  		})
   245  
   246  		return txErr
   247  	})
   248  	formList.SetInsertFn(func(values form2.Values) error {
   249  		if values.IsEmpty("name", "username", "password") {
   250  			return errors.New("username and password can not be empty")
   251  		}
   252  
   253  		password := values.Get("password")
   254  
   255  		if password != values.Get("password_again") {
   256  			return errors.New("password does not match")
   257  		}
   258  
   259  		_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   260  
   261  			user, createUserErr := models.User().WithTx(tx).SetConn(s.conn).New(values.Get("username"),
   262  				encodePassword([]byte(values.Get("password"))),
   263  				values.Get("name"),
   264  				values.Get("avatar"))
   265  
   266  			if db.CheckError(createUserErr, db.INSERT) {
   267  				return createUserErr, nil
   268  			}
   269  
   270  			for i := 0; i < len(values["role_id[]"]); i++ {
   271  				_, addRoleErr := user.WithTx(tx).AddRole(values["role_id[]"][i])
   272  				if db.CheckError(addRoleErr, db.INSERT) {
   273  					return addRoleErr, nil
   274  				}
   275  			}
   276  
   277  			for i := 0; i < len(values["permission_id[]"]); i++ {
   278  				_, addPermissionErr := user.WithTx(tx).AddPermission(values["permission_id[]"][i])
   279  				if db.CheckError(addPermissionErr, db.INSERT) {
   280  					return addPermissionErr, nil
   281  				}
   282  			}
   283  
   284  			return nil, nil
   285  		})
   286  		return txErr
   287  	})
   288  
   289  	detail := managerTable.GetDetail()
   290  	detail.AddField("ID", "id", db.Int)
   291  	detail.AddField(lg("Name"), "username", db.Varchar)
   292  	detail.AddField(lg("Avatar"), "avatar", db.Varchar).
   293  		FieldDisplay(func(model types.FieldModel) interface{} {
   294  			if model.Value == "" || config.GetStore().Prefix == "" {
   295  				model.Value = config.Url("/assets/dist/img/avatar04.png")
   296  			} else {
   297  				model.Value = config.GetStore().URL(model.Value)
   298  			}
   299  			return template.Default().Image().
   300  				SetSrc(template.HTML(model.Value)).
   301  				SetHeight("120").SetWidth("120").WithModal().GetContent()
   302  		})
   303  	detail.AddField(lg("Nickname"), "name", db.Varchar)
   304  	detail.AddField(lg("role"), "roles", db.Varchar).
   305  		FieldDisplay(func(model types.FieldModel) interface{} {
   306  			labelModels, _ := s.table("goadmin_role_users").
   307  				Select("goadmin_roles.name").
   308  				LeftJoin("goadmin_roles", "goadmin_roles.id", "=", "goadmin_role_users.role_id").
   309  				Where("user_id", "=", model.ID).
   310  				All()
   311  
   312  			labels := template.HTML("")
   313  			labelTpl := label().SetType("success")
   314  
   315  			for key, label := range labelModels {
   316  				if key == len(labelModels)-1 {
   317  					labels += labelTpl.SetContent(template.HTML(label["name"].(string))).GetContent()
   318  				} else {
   319  					labels += labelTpl.SetContent(template.HTML(label["name"].(string))).GetContent() + "<br><br>"
   320  				}
   321  			}
   322  
   323  			if labels == template.HTML("") {
   324  				return lg("no roles")
   325  			}
   326  
   327  			return labels
   328  		})
   329  	detail.AddField(lg("permission"), "roles", db.Varchar).
   330  		FieldDisplay(func(model types.FieldModel) interface{} {
   331  			permissionModel, _ := s.table("goadmin_user_permissions").
   332  				Select("goadmin_permissions.name").
   333  				LeftJoin("goadmin_permissions", "goadmin_permissions.id", "=", "goadmin_user_permissions.permission_id").
   334  				Where("user_id", "=", model.ID).
   335  				All()
   336  
   337  			permissions := template.HTML("")
   338  			permissionTpl := label().SetType("success")
   339  
   340  			for key, label := range permissionModel {
   341  				if key == len(permissionModel)-1 {
   342  					permissions += permissionTpl.SetContent(template.HTML(label["name"].(string))).GetContent()
   343  				} else {
   344  					permissions += permissionTpl.SetContent(template.HTML(label["name"].(string))).GetContent() + "<br><br>"
   345  				}
   346  			}
   347  
   348  			return permissions
   349  		})
   350  	detail.AddField(lg("createdAt"), "created_at", db.Timestamp)
   351  	detail.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
   352  
   353  	return
   354  }
   355  
   356  func (s *SystemTable) GetNormalManagerTable(ctx *context.Context) (managerTable Table) {
   357  	managerTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver))
   358  
   359  	info := managerTable.GetInfo().AddXssJsFilter().HideFilterArea()
   360  
   361  	info.AddField("ID", "id", db.Int).FieldSortable()
   362  	info.AddField(lg("Name"), "username", db.Varchar).FieldFilterable()
   363  	info.AddField(lg("Nickname"), "name", db.Varchar).FieldFilterable()
   364  	info.AddField(lg("role"), "name", db.Varchar).
   365  		FieldJoin(types.Join{
   366  			Table:     "goadmin_role_users",
   367  			JoinField: "user_id",
   368  			Field:     "id",
   369  		}).
   370  		FieldJoin(types.Join{
   371  			Table:     "goadmin_roles",
   372  			JoinField: "id",
   373  			Field:     "role_id",
   374  			BaseTable: "goadmin_role_users",
   375  		}).
   376  		FieldDisplay(func(model types.FieldModel) interface{} {
   377  			labels := template.HTML("")
   378  			labelTpl := label().SetType("success")
   379  
   380  			labelValues := strings.Split(model.Value, types.JoinFieldValueDelimiter)
   381  			for key, label := range labelValues {
   382  				if key == len(labelValues)-1 {
   383  					labels += labelTpl.SetContent(template.HTML(label)).GetContent()
   384  				} else {
   385  					labels += labelTpl.SetContent(template.HTML(label)).GetContent() + "<br><br>"
   386  				}
   387  			}
   388  
   389  			if labels == template.HTML("") {
   390  				return lg("no roles")
   391  			}
   392  
   393  			return labels
   394  		})
   395  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
   396  	info.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
   397  
   398  	info.SetTable("goadmin_users").
   399  		SetTitle(lg("Managers")).
   400  		SetDescription(lg("Managers")).
   401  		SetDeleteFn(func(idArr []string) error {
   402  
   403  			var ids = interfaces(idArr)
   404  
   405  			_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   406  
   407  				deleteUserRoleErr := s.connection().WithTx(tx).
   408  					Table("goadmin_role_users").
   409  					WhereIn("user_id", ids).
   410  					Delete()
   411  
   412  				if db.CheckError(deleteUserRoleErr, db.DELETE) {
   413  					return deleteUserRoleErr, nil
   414  				}
   415  
   416  				deleteUserPermissionErr := s.connection().WithTx(tx).
   417  					Table("goadmin_user_permissions").
   418  					WhereIn("user_id", ids).
   419  					Delete()
   420  
   421  				if db.CheckError(deleteUserPermissionErr, db.DELETE) {
   422  					return deleteUserPermissionErr, nil
   423  				}
   424  
   425  				deleteUserErr := s.connection().WithTx(tx).
   426  					Table("goadmin_users").
   427  					WhereIn("id", ids).
   428  					Delete()
   429  
   430  				if db.CheckError(deleteUserErr, db.DELETE) {
   431  					return deleteUserErr, nil
   432  				}
   433  
   434  				return nil, nil
   435  			})
   436  
   437  			return txErr
   438  		})
   439  
   440  	formList := managerTable.GetForm().AddXssJsFilter()
   441  
   442  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   443  	formList.AddField(lg("Name"), "username", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("use for login"))).FieldMust()
   444  	formList.AddField(lg("Nickname"), "name", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("use to display"))).FieldMust()
   445  	formList.AddField(lg("Avatar"), "avatar", db.Varchar, form.File)
   446  	formList.AddField(lg("password"), "password", db.Varchar, form.Password).
   447  		FieldDisplay(func(value types.FieldModel) interface{} {
   448  			return ""
   449  		})
   450  	formList.AddField(lg("confirm password"), "password_again", db.Varchar, form.Password).
   451  		FieldDisplay(func(value types.FieldModel) interface{} {
   452  			return ""
   453  		})
   454  
   455  	formList.SetTable("goadmin_users").SetTitle(lg("Managers")).SetDescription(lg("Managers"))
   456  	formList.SetUpdateFn(func(values form2.Values) error {
   457  
   458  		if values.IsEmpty("name", "username") {
   459  			return errors.New("username and password can not be empty")
   460  		}
   461  
   462  		user := models.UserWithId(values.Get("id")).SetConn(s.conn)
   463  
   464  		if values.Has("permission", "role") {
   465  			return errors.New(errs.NoPermission)
   466  		}
   467  
   468  		password := values.Get("password")
   469  
   470  		if password != "" {
   471  
   472  			if password != values.Get("password_again") {
   473  				return errors.New("password does not match")
   474  			}
   475  
   476  			password = encodePassword([]byte(values.Get("password")))
   477  		}
   478  
   479  		avatar := values.Get("avatar")
   480  
   481  		if values.Get("avatar__delete_flag") == "1" {
   482  			avatar = ""
   483  		}
   484  
   485  		_, updateUserErr := user.Update(values.Get("username"),
   486  			password, values.Get("name"), avatar, values.Get("avatar__change_flag") == "1")
   487  
   488  		if db.CheckError(updateUserErr, db.UPDATE) {
   489  			return updateUserErr
   490  		}
   491  
   492  		return nil
   493  	})
   494  	formList.SetInsertFn(func(values form2.Values) error {
   495  		if values.IsEmpty("name", "username", "password") {
   496  			return errors.New("username and password can not be empty")
   497  		}
   498  
   499  		password := values.Get("password")
   500  
   501  		if password != values.Get("password_again") {
   502  			return errors.New("password does not match")
   503  		}
   504  
   505  		if values.Has("permission", "role") {
   506  			return errors.New(errs.NoPermission)
   507  		}
   508  
   509  		_, createUserErr := models.User().SetConn(s.conn).New(values.Get("username"),
   510  			encodePassword([]byte(values.Get("password"))),
   511  			values.Get("name"),
   512  			values.Get("avatar"))
   513  
   514  		if db.CheckError(createUserErr, db.INSERT) {
   515  			return createUserErr
   516  		}
   517  
   518  		return nil
   519  	})
   520  
   521  	return
   522  }
   523  
   524  func (s *SystemTable) GetPermissionTable(ctx *context.Context) (permissionTable Table) {
   525  	permissionTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver))
   526  
   527  	info := permissionTable.GetInfo().AddXssJsFilter().HideFilterArea()
   528  
   529  	info.AddField("ID", "id", db.Int).FieldSortable()
   530  	info.AddField(lg("permission"), "name", db.Varchar).FieldFilterable()
   531  	info.AddField(lg("slug"), "slug", db.Varchar).FieldFilterable()
   532  	info.AddField(lg("method"), "http_method", db.Varchar).FieldDisplay(func(value types.FieldModel) interface{} {
   533  		if value.Value == "" {
   534  			return "All methods"
   535  		}
   536  		return value.Value
   537  	})
   538  	info.AddField(lg("path"), "http_path", db.Varchar).
   539  		FieldDisplay(func(model types.FieldModel) interface{} {
   540  			pathArr := strings.Split(model.Value, "\n")
   541  			res := ""
   542  			for i := 0; i < len(pathArr); i++ {
   543  				if i == len(pathArr)-1 {
   544  					res += string(label().SetContent(template.HTML(pathArr[i])).GetContent())
   545  				} else {
   546  					res += string(label().SetContent(template.HTML(pathArr[i])).GetContent()) + "<br><br>"
   547  				}
   548  			}
   549  			return res
   550  		})
   551  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
   552  	info.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
   553  
   554  	info.SetTable("goadmin_permissions").
   555  		SetTitle(lg("Permission Manage")).
   556  		SetDescription(lg("Permission Manage")).
   557  		SetDeleteFn(func(idArr []string) error {
   558  
   559  			var ids = interfaces(idArr)
   560  
   561  			_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   562  
   563  				deleteRolePermissionErr := s.connection().WithTx(tx).
   564  					Table("goadmin_role_permissions").
   565  					WhereIn("permission_id", ids).
   566  					Delete()
   567  
   568  				if db.CheckError(deleteRolePermissionErr, db.DELETE) {
   569  					return deleteRolePermissionErr, nil
   570  				}
   571  
   572  				deleteUserPermissionErr := s.connection().WithTx(tx).
   573  					Table("goadmin_user_permissions").
   574  					WhereIn("permission_id", ids).
   575  					Delete()
   576  
   577  				if db.CheckError(deleteUserPermissionErr, db.DELETE) {
   578  					return deleteUserPermissionErr, nil
   579  				}
   580  
   581  				deletePermissionsErr := s.connection().WithTx(tx).
   582  					Table("goadmin_permissions").
   583  					WhereIn("id", ids).
   584  					Delete()
   585  
   586  				if deletePermissionsErr != nil {
   587  					return deletePermissionsErr, nil
   588  				}
   589  
   590  				return nil, nil
   591  			})
   592  
   593  			return txErr
   594  		})
   595  
   596  	formList := permissionTable.GetForm().AddXssJsFilter()
   597  
   598  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   599  	formList.AddField(lg("permission"), "name", db.Varchar, form.Text).FieldMust()
   600  	formList.AddField(lg("slug"), "slug", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("should be unique"))).FieldMust()
   601  	formList.AddField(lg("method"), "http_method", db.Varchar, form.Select).
   602  		FieldOptions(types.FieldOptions{
   603  			{Value: "GET", Text: "GET"},
   604  			{Value: "PUT", Text: "PUT"},
   605  			{Value: "POST", Text: "POST"},
   606  			{Value: "DELETE", Text: "DELETE"},
   607  			{Value: "PATCH", Text: "PATCH"},
   608  			{Value: "OPTIONS", Text: "OPTIONS"},
   609  			{Value: "HEAD", Text: "HEAD"},
   610  		}).
   611  		FieldDisplay(func(model types.FieldModel) interface{} {
   612  			return strings.Split(model.Value, ",")
   613  		}).
   614  		FieldPostFilterFn(func(model types.PostFieldModel) interface{} {
   615  			return strings.Join(model.Value, ",")
   616  		}).
   617  		FieldHelpMsg(template.HTML(lg("all method if empty")))
   618  
   619  	formList.AddField(lg("path"), "http_path", db.Varchar, form.TextArea).
   620  		FieldPostFilterFn(func(model types.PostFieldModel) interface{} {
   621  			return strings.TrimSpace(model.Value.Value())
   622  		}).
   623  		FieldHelpMsg(template.HTML(lg("a path a line, without global prefix")))
   624  	formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   625  	formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   626  
   627  	formList.SetTable("goadmin_permissions").
   628  		SetTitle(lg("Permission Manage")).
   629  		SetDescription(lg("Permission Manage")).
   630  		SetPostValidator(func(values form2.Values) error {
   631  
   632  			if values.IsEmpty("slug", "http_path", "name") {
   633  				return errors.New("slug or http_path or name should not be empty")
   634  			}
   635  
   636  			if models.Permission().SetConn(s.conn).IsSlugExist(values.Get("slug"), values.Get("id")) {
   637  				return errors.New("slug exists")
   638  			}
   639  			return nil
   640  		}).SetPostHook(func(values form2.Values) error {
   641  
   642  		if values.IsInsertPost() {
   643  			return nil
   644  		}
   645  
   646  		_, err := s.connection().Table("goadmin_permissions").
   647  			Where("id", "=", values.Get("id")).
   648  			Update(dialect.H{
   649  				"updated_at": time.Now().Format("2006-01-02 15:04:05"),
   650  			})
   651  
   652  		if db.CheckError(err, db.UPDATE) {
   653  			return err
   654  		}
   655  
   656  		return nil
   657  	})
   658  
   659  	return
   660  }
   661  
   662  func (s *SystemTable) GetRolesTable(ctx *context.Context) (roleTable Table) {
   663  	roleTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver))
   664  
   665  	info := roleTable.GetInfo().AddXssJsFilter().HideFilterArea()
   666  
   667  	info.AddField("ID", "id", db.Int).FieldSortable()
   668  	info.AddField(lg("role"), "name", db.Varchar).FieldFilterable()
   669  	info.AddField(lg("slug"), "slug", db.Varchar).FieldFilterable()
   670  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
   671  	info.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
   672  
   673  	info.SetTable("goadmin_roles").
   674  		SetTitle(lg("Roles Manage")).
   675  		SetDescription(lg("Roles Manage")).
   676  		SetDeleteFn(func(idArr []string) error {
   677  
   678  			var ids = interfaces(idArr)
   679  
   680  			_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   681  
   682  				deleteRoleUserErr := s.connection().WithTx(tx).
   683  					Table("goadmin_role_users").
   684  					WhereIn("role_id", ids).
   685  					Delete()
   686  
   687  				if db.CheckError(deleteRoleUserErr, db.DELETE) {
   688  					return deleteRoleUserErr, nil
   689  				}
   690  
   691  				deleteRoleMenuErr := s.connection().WithTx(tx).
   692  					Table("goadmin_role_menu").
   693  					WhereIn("role_id", ids).
   694  					Delete()
   695  
   696  				if db.CheckError(deleteRoleMenuErr, db.DELETE) {
   697  					return deleteRoleMenuErr, nil
   698  				}
   699  
   700  				deleteRolePermissionErr := s.connection().WithTx(tx).
   701  					Table("goadmin_role_permissions").
   702  					WhereIn("role_id", ids).
   703  					Delete()
   704  
   705  				if db.CheckError(deleteRolePermissionErr, db.DELETE) {
   706  					return deleteRolePermissionErr, nil
   707  				}
   708  
   709  				deleteRolesErr := s.connection().WithTx(tx).
   710  					Table("goadmin_roles").
   711  					WhereIn("id", ids).
   712  					Delete()
   713  
   714  				if db.CheckError(deleteRolesErr, db.DELETE) {
   715  					return deleteRolesErr, nil
   716  				}
   717  
   718  				return nil, nil
   719  			})
   720  
   721  			return txErr
   722  		})
   723  
   724  	formList := roleTable.GetForm().AddXssJsFilter()
   725  
   726  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   727  	formList.AddField(lg("role"), "name", db.Varchar, form.Text).FieldMust()
   728  	formList.AddField(lg("slug"), "slug", db.Varchar, form.Text).FieldHelpMsg(template.HTML(lg("should be unique"))).FieldMust()
   729  	formList.AddField(lg("permission"), "permission_id", db.Varchar, form.SelectBox).
   730  		FieldOptionsFromTable("goadmin_permissions", "name", "id").
   731  		FieldDisplay(func(model types.FieldModel) interface{} {
   732  			var permissions = make([]string, 0)
   733  
   734  			if model.ID == "" {
   735  				return permissions
   736  			}
   737  			perModel, _ := s.table("goadmin_role_permissions").
   738  				Select("permission_id").
   739  				Where("role_id", "=", model.ID).
   740  				All()
   741  			for _, v := range perModel {
   742  				permissions = append(permissions, strconv.FormatInt(v["permission_id"].(int64), 10))
   743  			}
   744  			return permissions
   745  		}).FieldHelpMsg(template.HTML(lg("no corresponding options?")) +
   746  		link("/admin/info/permission/new", "Create here."))
   747  
   748  	formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   749  	formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   750  
   751  	formList.SetTable("goadmin_roles").
   752  		SetTitle(lg("Roles Manage")).
   753  		SetDescription(lg("Roles Manage"))
   754  
   755  	formList.SetUpdateFn(func(values form2.Values) error {
   756  
   757  		if models.Role().SetConn(s.conn).IsSlugExist(values.Get("slug"), values.Get("id")) {
   758  			return errors.New("slug exists")
   759  		}
   760  
   761  		role := models.RoleWithId(values.Get("id")).SetConn(s.conn)
   762  
   763  		_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   764  
   765  			_, updateRoleErr := role.WithTx(tx).Update(values.Get("name"), values.Get("slug"))
   766  
   767  			if db.CheckError(updateRoleErr, db.UPDATE) {
   768  				return updateRoleErr, nil
   769  			}
   770  
   771  			delPermissionErr := role.WithTx(tx).DeletePermissions()
   772  
   773  			if db.CheckError(delPermissionErr, db.DELETE) {
   774  				return delPermissionErr, nil
   775  			}
   776  
   777  			for i := 0; i < len(values["permission_id[]"]); i++ {
   778  				_, addPermissionErr := role.WithTx(tx).AddPermission(values["permission_id[]"][i])
   779  				if db.CheckError(addPermissionErr, db.INSERT) {
   780  					return addPermissionErr, nil
   781  				}
   782  			}
   783  
   784  			return nil, nil
   785  		})
   786  
   787  		return txErr
   788  	})
   789  
   790  	formList.SetInsertFn(func(values form2.Values) error {
   791  
   792  		if models.Role().SetConn(s.conn).IsSlugExist(values.Get("slug"), "") {
   793  			return errors.New("slug exists")
   794  		}
   795  
   796  		_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   797  			role, createRoleErr := models.Role().WithTx(tx).SetConn(s.conn).New(values.Get("name"), values.Get("slug"))
   798  
   799  			if db.CheckError(createRoleErr, db.INSERT) {
   800  				return createRoleErr, nil
   801  			}
   802  
   803  			for i := 0; i < len(values["permission_id[]"]); i++ {
   804  				_, addPermissionErr := role.WithTx(tx).AddPermission(values["permission_id[]"][i])
   805  				if db.CheckError(addPermissionErr, db.INSERT) {
   806  					return addPermissionErr, nil
   807  				}
   808  			}
   809  
   810  			return nil, nil
   811  		})
   812  
   813  		return txErr
   814  	})
   815  
   816  	return
   817  }
   818  
   819  func (s *SystemTable) GetOpTable(ctx *context.Context) (opTable Table) {
   820  	opTable = NewDefaultTable(Config{
   821  		Driver:     config.GetDatabases().GetDefault().Driver,
   822  		CanAdd:     false,
   823  		Editable:   false,
   824  		Deletable:  config.GetAllowDelOperationLog(),
   825  		Exportable: true,
   826  		Connection: "default",
   827  		PrimaryKey: PrimaryKey{
   828  			Type: db.Int,
   829  			Name: DefaultPrimaryKeyName,
   830  		},
   831  	})
   832  
   833  	info := opTable.GetInfo().AddXssJsFilter().
   834  		HideFilterArea().HideDetailButton().HideEditButton().HideNewButton()
   835  
   836  	if !config.GetAllowDelOperationLog() {
   837  		info = info.HideDeleteButton()
   838  	}
   839  
   840  	info.AddField("ID", "id", db.Int).FieldSortable()
   841  	info.AddField("userID", "user_id", db.Int).FieldHide()
   842  	info.AddField(lg("user"), "name", db.Varchar).FieldJoin(types.Join{
   843  		Table:     config.GetAuthUserTable(),
   844  		JoinField: "id",
   845  		Field:     "user_id",
   846  	}).FieldDisplay(func(value types.FieldModel) interface{} {
   847  		return template.Default().
   848  			Link().
   849  			SetURL(config.Url("/info/manager/detail?__goadmin_detail_pk=") + strconv.Itoa(int(value.Row["user_id"].(int64)))).
   850  			SetContent(template.HTML(value.Value)).
   851  			OpenInNewTab().
   852  			SetTabTitle("Manager Detail").
   853  			GetContent()
   854  	}).FieldFilterable()
   855  	info.AddField(lg("path"), "path", db.Varchar).FieldFilterable()
   856  	info.AddField(lg("method"), "method", db.Varchar).FieldFilterable()
   857  	info.AddField(lg("ip"), "ip", db.Varchar).FieldFilterable()
   858  	info.AddField(lg("content"), "input", db.Text).FieldWidth(230)
   859  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
   860  
   861  	users, _ := s.table(config.GetAuthUserTable()).Select("id", "name").All()
   862  	options := make(types.FieldOptions, len(users))
   863  	for k, user := range users {
   864  		if reflect.TypeOf(user["id"]).String() == "[]uint8" {
   865  			options[k].Value = string(user["id"].([]uint8))
   866  		} else {
   867  			options[k].Value = string(rune(user["id"].(int64)))
   868  		}
   869  		options[k].Text = fmt.Sprintf("%v", user["name"])
   870  	}
   871  	info.AddSelectBox(language.Get("user"), options, action.FieldFilter("user_id"))
   872  	info.AddSelectBox(language.Get("method"), types.FieldOptions{
   873  		{Value: "GET", Text: "GET"},
   874  		{Value: "POST", Text: "POST"},
   875  		{Value: "OPTIONS", Text: "OPTIONS"},
   876  		{Value: "PUT", Text: "PUT"},
   877  		{Value: "HEAD", Text: "HEAD"},
   878  		{Value: "DELETE", Text: "DELETE"},
   879  	}, action.FieldFilter("method"))
   880  
   881  	info.SetTable("goadmin_operation_log").
   882  		SetTitle(lg("operation log")).
   883  		SetDescription(lg("operation log"))
   884  
   885  	formList := opTable.GetForm().AddXssJsFilter()
   886  
   887  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   888  	formList.AddField(lg("userID"), "user_id", db.Int, form.Text)
   889  	formList.AddField(lg("path"), "path", db.Varchar, form.Text)
   890  	formList.AddField(lg("method"), "method", db.Varchar, form.Text)
   891  	formList.AddField(lg("ip"), "ip", db.Varchar, form.Text)
   892  	formList.AddField(lg("content"), "input", db.Varchar, form.Text)
   893  	formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   894  	formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
   895  
   896  	formList.SetTable("goadmin_operation_log").
   897  		SetTitle(lg("operation log")).
   898  		SetDescription(lg("operation log"))
   899  
   900  	return
   901  }
   902  
   903  func (s *SystemTable) GetMenuTable(ctx *context.Context) (menuTable Table) {
   904  	menuTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver))
   905  
   906  	name := ctx.Query("__plugin_name")
   907  
   908  	info := menuTable.GetInfo().AddXssJsFilter().HideFilterArea().Where("plugin_name", "=", name)
   909  
   910  	info.AddField("ID", "id", db.Int).FieldSortable()
   911  	info.AddField(lg("parent"), "parent_id", db.Int)
   912  	info.AddField(lg("menu name"), "title", db.Varchar)
   913  	info.AddField(lg("icon"), "icon", db.Varchar)
   914  	info.AddField(lg("uri"), "uri", db.Varchar)
   915  	info.AddField(lg("role"), "roles", db.Varchar)
   916  	info.AddField(lg("header"), "header", db.Varchar)
   917  	info.AddField(lg("createdAt"), "created_at", db.Timestamp)
   918  	info.AddField(lg("updatedAt"), "updated_at", db.Timestamp)
   919  
   920  	info.SetTable("goadmin_menu").
   921  		SetTitle(lg("Menus Manage")).
   922  		SetDescription(lg("Menus Manage")).
   923  		SetDeleteFn(func(idArr []string) error {
   924  
   925  			var ids = interfaces(idArr)
   926  
   927  			_, txErr := s.connection().WithTransaction(func(tx *sql.Tx) (e error, i map[string]interface{}) {
   928  
   929  				deleteRoleMenuErr := s.connection().WithTx(tx).
   930  					Table("goadmin_role_menu").
   931  					WhereIn("menu_id", ids).
   932  					Delete()
   933  
   934  				if db.CheckError(deleteRoleMenuErr, db.DELETE) {
   935  					return deleteRoleMenuErr, nil
   936  				}
   937  
   938  				deleteMenusErr := s.connection().WithTx(tx).
   939  					Table("goadmin_menu").
   940  					WhereIn("id", ids).
   941  					Delete()
   942  
   943  				if db.CheckError(deleteMenusErr, db.DELETE) {
   944  					return deleteMenusErr, nil
   945  				}
   946  
   947  				return nil, map[string]interface{}{}
   948  			})
   949  
   950  			return txErr
   951  		})
   952  
   953  	var parentIDOptions = types.FieldOptions{
   954  		{
   955  			Text:  "ROOT",
   956  			Value: "0",
   957  		},
   958  	}
   959  
   960  	allMenus, _ := s.connection().Table("goadmin_menu").
   961  		Where("parent_id", "=", 0).
   962  		Where("plugin_name", "=", name).
   963  		Select("id", "title").
   964  		OrderBy("order", "asc").
   965  		All()
   966  	allMenuIDs := make([]interface{}, len(allMenus))
   967  
   968  	if len(allMenuIDs) > 0 {
   969  		for i := 0; i < len(allMenus); i++ {
   970  			allMenuIDs[i] = allMenus[i]["id"]
   971  		}
   972  
   973  		secondLevelMenus, _ := s.connection().Table("goadmin_menu").
   974  			WhereIn("parent_id", allMenuIDs).
   975  			Where("plugin_name", "=", name).
   976  			Select("id", "title", "parent_id").
   977  			All()
   978  
   979  		secondLevelMenusCol := collection.Collection(secondLevelMenus)
   980  
   981  		for i := 0; i < len(allMenus); i++ {
   982  			parentIDOptions = append(parentIDOptions, types.FieldOption{
   983  				TextHTML: "&nbsp;&nbsp;┝  " + language.GetFromHtml(template.HTML(allMenus[i]["title"].(string))),
   984  				Value:    strconv.Itoa(int(allMenus[i]["id"].(int64))),
   985  			})
   986  			col := secondLevelMenusCol.Where("parent_id", "=", allMenus[i]["id"].(int64))
   987  			for i := 0; i < len(col); i++ {
   988  				parentIDOptions = append(parentIDOptions, types.FieldOption{
   989  					TextHTML: "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;┝  " +
   990  						language.GetFromHtml(template.HTML(col[i]["title"].(string))),
   991  					Value: strconv.Itoa(int(col[i]["id"].(int64))),
   992  				})
   993  			}
   994  		}
   995  	}
   996  
   997  	formList := menuTable.GetForm().AddXssJsFilter()
   998  	formList.AddField("ID", "id", db.Int, form.Default).FieldDisplayButCanNotEditWhenUpdate().FieldDisableWhenCreate()
   999  	formList.AddField(lg("parent"), "parent_id", db.Int, form.SelectSingle).
  1000  		FieldOptions(parentIDOptions).
  1001  		FieldDisplay(func(model types.FieldModel) interface{} {
  1002  			var menuItem []string
  1003  
  1004  			if model.ID == "" {
  1005  				return menuItem
  1006  			}
  1007  
  1008  			menuModel, _ := s.table("goadmin_menu").Select("parent_id").Find(model.ID)
  1009  			menuItem = append(menuItem, strconv.FormatInt(menuModel["parent_id"].(int64), 10))
  1010  			return menuItem
  1011  		})
  1012  	formList.AddField(lg("menu name"), "title", db.Varchar, form.Text).FieldMust()
  1013  	formList.AddField(lg("header"), "header", db.Varchar, form.Text)
  1014  	formList.AddField(lg("icon"), "icon", db.Varchar, form.IconPicker)
  1015  	formList.AddField(lg("uri"), "uri", db.Varchar, form.Text)
  1016  	formList.AddField("PluginName", "plugin_name", db.Varchar, form.Text).FieldDefault(name).FieldHide()
  1017  	formList.AddField(lg("role"), "roles", db.Int, form.Select).
  1018  		FieldOptionsFromTable("goadmin_roles", "slug", "id").
  1019  		FieldDisplay(func(model types.FieldModel) interface{} {
  1020  			var roles []string
  1021  
  1022  			if model.ID == "" {
  1023  				return roles
  1024  			}
  1025  
  1026  			roleModel, _ := s.table("goadmin_role_menu").
  1027  				Select("role_id").
  1028  				Where("menu_id", "=", model.ID).
  1029  				All()
  1030  
  1031  			for _, v := range roleModel {
  1032  				roles = append(roles, strconv.FormatInt(v["role_id"].(int64), 10))
  1033  			}
  1034  			return roles
  1035  		})
  1036  
  1037  	formList.AddField(lg("updatedAt"), "updated_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
  1038  	formList.AddField(lg("createdAt"), "created_at", db.Timestamp, form.Default).FieldDisableWhenCreate()
  1039  
  1040  	formList.SetTable("goadmin_menu").
  1041  		SetTitle(lg("Menus Manage")).
  1042  		SetDescription(lg("Menus Manage"))
  1043  
  1044  	return
  1045  }
  1046  
  1047  func (s *SystemTable) GetSiteTable(ctx *context.Context) (siteTable Table) {
  1048  	siteTable = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver).
  1049  		SetOnlyUpdateForm().
  1050  		SetGetDataFun(func(params parameter.Parameters) (i []map[string]interface{}, i2 int) {
  1051  			return []map[string]interface{}{models.Site().SetConn(s.conn).AllToMapInterface()}, 1
  1052  		}))
  1053  
  1054  	trueStr := lgWithConfigScore("true")
  1055  	falseStr := lgWithConfigScore("false")
  1056  
  1057  	formList := siteTable.GetForm().AddXssJsFilter()
  1058  	formList.AddField("ID", "id", db.Varchar, form.Default).FieldDefault("1").FieldHide()
  1059  	formList.AddField(lgWithConfigScore("site off"), "site_off", db.Varchar, form.Switch).
  1060  		FieldOptions(types.FieldOptions{
  1061  			{Text: trueStr, Value: "true"},
  1062  			{Text: falseStr, Value: "false"},
  1063  		})
  1064  	formList.AddField(lgWithConfigScore("debug"), "debug", db.Varchar, form.Switch).
  1065  		FieldOptions(types.FieldOptions{
  1066  			{Text: trueStr, Value: "true"},
  1067  			{Text: falseStr, Value: "false"},
  1068  		})
  1069  	formList.AddField(lgWithConfigScore("env"), "env", db.Varchar, form.Default).
  1070  		FieldDisplay(func(value types.FieldModel) interface{} {
  1071  			return s.c.Env
  1072  		})
  1073  
  1074  	langOps := make(types.FieldOptions, len(language.Langs))
  1075  	for k, t := range language.Langs {
  1076  		langOps[k] = types.FieldOption{Text: lgWithConfigScore(t, "language"), Value: t}
  1077  	}
  1078  	formList.AddField(lgWithConfigScore("language"), "language", db.Varchar, form.SelectSingle).
  1079  		FieldDisplay(func(value types.FieldModel) interface{} {
  1080  			return language.FixedLanguageKey(value.Value)
  1081  		}).
  1082  		FieldOptions(langOps)
  1083  	themes := template.Themes()
  1084  	themesOps := make(types.FieldOptions, len(themes))
  1085  	for k, t := range themes {
  1086  		themesOps[k] = types.FieldOption{Text: t, Value: t}
  1087  	}
  1088  
  1089  	formList.AddField(lgWithConfigScore("theme"), "theme", db.Varchar, form.SelectSingle).
  1090  		FieldOptions(themesOps).
  1091  		FieldOnChooseShow("adminlte",
  1092  			"color_scheme")
  1093  	formList.AddField(lgWithConfigScore("title"), "title", db.Varchar, form.Text).FieldMust()
  1094  	formList.AddField(lgWithConfigScore("color scheme"), "color_scheme", db.Varchar, form.SelectSingle).
  1095  		FieldOptions(types.FieldOptions{
  1096  			{Text: "skin-black", Value: "skin-black"},
  1097  			{Text: "skin-black-light", Value: "skin-black-light"},
  1098  			{Text: "skin-blue", Value: "skin-blue"},
  1099  			{Text: "skin-blue-light", Value: "skin-blue-light"},
  1100  			{Text: "skin-green", Value: "skin-green"},
  1101  			{Text: "skin-green-light", Value: "skin-green-light"},
  1102  			{Text: "skin-purple", Value: "skin-purple"},
  1103  			{Text: "skin-purple-light", Value: "skin-purple-light"},
  1104  			{Text: "skin-red", Value: "skin-red"},
  1105  			{Text: "skin-red-light", Value: "skin-red-light"},
  1106  			{Text: "skin-yellow", Value: "skin-yellow"},
  1107  			{Text: "skin-yellow-light", Value: "skin-yellow-light"},
  1108  		}).FieldHelpMsg(template.HTML(lgWithConfigScore("It will work when theme is adminlte")))
  1109  	formList.AddField(lgWithConfigScore("login title"), "login_title", db.Varchar, form.Text).FieldMust()
  1110  	formList.AddField(lgWithConfigScore("extra"), "extra", db.Varchar, form.TextArea)
  1111  	formList.AddField(lgWithConfigScore("logo"), "logo", db.Varchar, form.Code).FieldMust()
  1112  	formList.AddField(lgWithConfigScore("mini logo"), "mini_logo", db.Varchar, form.Code).FieldMust()
  1113  	if s.c.IsNotProductionEnvironment() {
  1114  		formList.AddField(lgWithConfigScore("bootstrap file path"), "bootstrap_file_path", db.Varchar, form.Text)
  1115  		formList.AddField(lgWithConfigScore("go mod file path"), "go_mod_file_path", db.Varchar, form.Text)
  1116  	}
  1117  	formList.AddField(lgWithConfigScore("session life time"), "session_life_time", db.Varchar, form.Number).
  1118  		FieldMust().
  1119  		FieldHelpMsg(template.HTML(lgWithConfigScore("must bigger than 900 seconds")))
  1120  	formList.AddField(lgWithConfigScore("custom head html"), "custom_head_html", db.Varchar, form.Code)
  1121  	formList.AddField(lgWithConfigScore("custom foot Html"), "custom_foot_html", db.Varchar, form.Code)
  1122  	formList.AddField(lgWithConfigScore("custom 404 html"), "custom_404_html", db.Varchar, form.Code)
  1123  	formList.AddField(lgWithConfigScore("custom 403 html"), "custom_403_html", db.Varchar, form.Code)
  1124  	formList.AddField(lgWithConfigScore("custom 500 Html"), "custom_500_html", db.Varchar, form.Code)
  1125  	formList.AddField(lgWithConfigScore("footer info"), "footer_info", db.Varchar, form.Code)
  1126  	formList.AddField(lgWithConfigScore("login logo"), "login_logo", db.Varchar, form.Code)
  1127  	formList.AddField(lgWithConfigScore("no limit login ip"), "no_limit_login_ip", db.Varchar, form.Switch).
  1128  		FieldOptions(types.FieldOptions{
  1129  			{Text: trueStr, Value: "true"},
  1130  			{Text: falseStr, Value: "false"},
  1131  		})
  1132  	formList.AddField(lgWithConfigScore("operation log off"), "operation_log_off", db.Varchar, form.Switch).
  1133  		FieldOptions(types.FieldOptions{
  1134  			{Text: trueStr, Value: "true"},
  1135  			{Text: falseStr, Value: "false"},
  1136  		})
  1137  	formList.AddField(lgWithConfigScore("allow delete operation log"), "allow_del_operation_log", db.Varchar, form.Switch).
  1138  		FieldOptions(types.FieldOptions{
  1139  			{Text: trueStr, Value: "true"},
  1140  			{Text: falseStr, Value: "false"},
  1141  		})
  1142  	formList.AddField(lgWithConfigScore("hide config center entrance"), "hide_config_center_entrance", db.Varchar, form.Switch).
  1143  		FieldOptions(types.FieldOptions{
  1144  			{Text: trueStr, Value: "true"},
  1145  			{Text: falseStr, Value: "false"},
  1146  		})
  1147  	formList.AddField(lgWithConfigScore("hide app info entrance"), "hide_app_info_entrance", db.Varchar, form.Switch).
  1148  		FieldOptions(types.FieldOptions{
  1149  			{Text: trueStr, Value: "true"},
  1150  			{Text: falseStr, Value: "false"},
  1151  		})
  1152  	formList.AddField(lgWithConfigScore("hide tool entrance"), "hide_tool_entrance", db.Varchar, form.Switch).
  1153  		FieldOptions(types.FieldOptions{
  1154  			{Text: trueStr, Value: "true"},
  1155  			{Text: falseStr, Value: "false"},
  1156  		})
  1157  	formList.AddField(lgWithConfigScore("hide plugin entrance"), "hide_plugin_entrance", db.Varchar, form.Switch).
  1158  		FieldOptions(types.FieldOptions{
  1159  			{Text: trueStr, Value: "true"},
  1160  			{Text: falseStr, Value: "false"},
  1161  		})
  1162  	formList.AddField(lgWithConfigScore("animation type"), "animation_type", db.Varchar, form.SelectSingle).
  1163  		FieldOptions(types.FieldOptions{
  1164  			{Text: "", Value: ""},
  1165  			{Text: "bounce", Value: "bounce"}, {Text: "flash", Value: "flash"}, {Text: "pulse", Value: "pulse"},
  1166  			{Text: "rubberBand", Value: "rubberBand"}, {Text: "shake", Value: "shake"}, {Text: "swing", Value: "swing"},
  1167  			{Text: "tada", Value: "tada"}, {Text: "wobble", Value: "wobble"}, {Text: "jello", Value: "jello"},
  1168  			{Text: "heartBeat", Value: "heartBeat"}, {Text: "bounceIn", Value: "bounceIn"}, {Text: "bounceInDown", Value: "bounceInDown"},
  1169  			{Text: "bounceInLeft", Value: "bounceInLeft"}, {Text: "bounceInRight", Value: "bounceInRight"}, {Text: "bounceInUp", Value: "bounceInUp"},
  1170  			{Text: "fadeIn", Value: "fadeIn"}, {Text: "fadeInDown", Value: "fadeInDown"}, {Text: "fadeInDownBig", Value: "fadeInDownBig"},
  1171  			{Text: "fadeInLeft", Value: "fadeInLeft"}, {Text: "fadeInLeftBig", Value: "fadeInLeftBig"}, {Text: "fadeInRight", Value: "fadeInRight"},
  1172  			{Text: "fadeInRightBig", Value: "fadeInRightBig"}, {Text: "fadeInUp", Value: "fadeInUp"}, {Text: "fadeInUpBig", Value: "fadeInUpBig"},
  1173  			{Text: "flip", Value: "flip"}, {Text: "flipInX", Value: "flipInX"}, {Text: "flipInY", Value: "flipInY"},
  1174  			{Text: "lightSpeedIn", Value: "lightSpeedIn"}, {Text: "rotateIn", Value: "rotateIn"}, {Text: "rotateInDownLeft", Value: "rotateInDownLeft"},
  1175  			{Text: "rotateInDownRight", Value: "rotateInDownRight"}, {Text: "rotateInUpLeft", Value: "rotateInUpLeft"}, {Text: "rotateInUpRight", Value: "rotateInUpRight"},
  1176  			{Text: "slideInUp", Value: "slideInUp"}, {Text: "slideInDown", Value: "slideInDown"}, {Text: "slideInLeft", Value: "slideInLeft"}, {Text: "slideInRight", Value: "slideInRight"},
  1177  			{Text: "slideOutRight", Value: "slideOutRight"}, {Text: "zoomIn", Value: "zoomIn"}, {Text: "zoomInDown", Value: "zoomInDown"},
  1178  			{Text: "zoomInLeft", Value: "zoomInLeft"}, {Text: "zoomInRight", Value: "zoomInRight"}, {Text: "zoomInUp", Value: "zoomInUp"},
  1179  			{Text: "hinge", Value: "hinge"}, {Text: "jackInTheBox", Value: "jackInTheBox"}, {Text: "rollIn", Value: "rollIn"},
  1180  		}).FieldOnChooseHide("", "animation_duration", "animation_delay").
  1181  		FieldOptionExt(map[string]interface{}{"allowClear": true}).
  1182  		FieldHelpMsg(`see more: <a href="https://daneden.github.io/animate.css/">https://daneden.github.io/animate.css/</a>`)
  1183  
  1184  	formList.AddField(lgWithConfigScore("animation duration"), "animation_duration", db.Varchar, form.Number)
  1185  	formList.AddField(lgWithConfigScore("animation delay"), "animation_delay", db.Varchar, form.Number)
  1186  
  1187  	formList.AddField(lgWithConfigScore("file upload engine"), "file_upload_engine", db.Varchar, form.Text)
  1188  
  1189  	formList.AddField(lgWithConfigScore("cdn url"), "asset_url", db.Varchar, form.Text).
  1190  		FieldHelpMsg(template.HTML(lgWithConfigScore("Do not modify when you have not set up all assets")))
  1191  
  1192  	formList.AddField(lgWithConfigScore("info log path"), "info_log_path", db.Varchar, form.Text)
  1193  	formList.AddField(lgWithConfigScore("error log path"), "error_log_path", db.Varchar, form.Text)
  1194  	formList.AddField(lgWithConfigScore("access log path"), "access_log_path", db.Varchar, form.Text)
  1195  	formList.AddField(lgWithConfigScore("info log off"), "info_log_off", db.Varchar, form.Switch).
  1196  		FieldOptions(types.FieldOptions{
  1197  			{Text: trueStr, Value: "true"},
  1198  			{Text: falseStr, Value: "false"},
  1199  		})
  1200  	formList.AddField(lgWithConfigScore("error log off"), "error_log_off", db.Varchar, form.Switch).
  1201  		FieldOptions(types.FieldOptions{
  1202  			{Text: trueStr, Value: "true"},
  1203  			{Text: falseStr, Value: "false"},
  1204  		})
  1205  	formList.AddField(lgWithConfigScore("access log off"), "access_log_off", db.Varchar, form.Switch).
  1206  		FieldOptions(types.FieldOptions{
  1207  			{Text: trueStr, Value: "true"},
  1208  			{Text: falseStr, Value: "false"},
  1209  		})
  1210  	formList.AddField(lgWithConfigScore("access assets log off"), "access_assets_log_off", db.Varchar, form.Switch).
  1211  		FieldOptions(types.FieldOptions{
  1212  			{Text: trueStr, Value: "true"},
  1213  			{Text: falseStr, Value: "false"},
  1214  		})
  1215  	formList.AddField(lgWithConfigScore("sql log on"), "sql_log", db.Varchar, form.Switch).
  1216  		FieldOptions(types.FieldOptions{
  1217  			{Text: trueStr, Value: "true"},
  1218  			{Text: falseStr, Value: "false"},
  1219  		})
  1220  	formList.AddField(lgWithConfigScore("log level"), "logger_level", db.Varchar, form.SelectSingle).
  1221  		FieldOptions(types.FieldOptions{
  1222  			{Text: "Debug", Value: "-1"},
  1223  			{Text: "Info", Value: "0"},
  1224  			{Text: "Warn", Value: "1"},
  1225  			{Text: "Error", Value: "2"},
  1226  		}).FieldDisplay(defaultFilterFn("0"))
  1227  
  1228  	formList.AddField(lgWithConfigScore("logger rotate max size"), "logger_rotate_max_size", db.Varchar, form.Number).
  1229  		FieldDivider(lgWithConfigScore("logger rotate")).FieldDisplay(defaultFilterFn("10", "0"))
  1230  	formList.AddField(lgWithConfigScore("logger rotate max backups"), "logger_rotate_max_backups", db.Varchar, form.Number).
  1231  		FieldDisplay(defaultFilterFn("5", "0"))
  1232  	formList.AddField(lgWithConfigScore("logger rotate max age"), "logger_rotate_max_age", db.Varchar, form.Number).
  1233  		FieldDisplay(defaultFilterFn("30", "0"))
  1234  	formList.AddField(lgWithConfigScore("logger rotate compress"), "logger_rotate_compress", db.Varchar, form.Switch).
  1235  		FieldOptions(types.FieldOptions{
  1236  			{Text: trueStr, Value: "true"},
  1237  			{Text: falseStr, Value: "false"},
  1238  		}).FieldDisplay(defaultFilterFn("false"))
  1239  
  1240  	formList.AddField(lgWithConfigScore("logger rotate encoder encoding"), "logger_encoder_encoding", db.Varchar,
  1241  		form.SelectSingle).
  1242  		FieldDivider(lgWithConfigScore("logger rotate encoder")).
  1243  		FieldOptions(types.FieldOptions{
  1244  			{Text: "JSON", Value: "json"},
  1245  			{Text: "Console", Value: "console"},
  1246  		}).FieldDisplay(defaultFilterFn("console")).
  1247  		FieldOnChooseHide("Console",
  1248  			"logger_encoder_time_key", "logger_encoder_level_key", "logger_encoder_caller_key",
  1249  			"logger_encoder_message_key", "logger_encoder_stacktrace_key", "logger_encoder_name_key")
  1250  
  1251  	formList.AddField(lgWithConfigScore("logger rotate encoder time key"), "logger_encoder_time_key", db.Varchar, form.Text).
  1252  		FieldDisplay(defaultFilterFn("ts"))
  1253  	formList.AddField(lgWithConfigScore("logger rotate encoder level key"), "logger_encoder_level_key", db.Varchar, form.Text).
  1254  		FieldDisplay(defaultFilterFn("level"))
  1255  	formList.AddField(lgWithConfigScore("logger rotate encoder name key"), "logger_encoder_name_key", db.Varchar, form.Text).
  1256  		FieldDisplay(defaultFilterFn("logger"))
  1257  	formList.AddField(lgWithConfigScore("logger rotate encoder caller key"), "logger_encoder_caller_key", db.Varchar, form.Text).
  1258  		FieldDisplay(defaultFilterFn("caller"))
  1259  	formList.AddField(lgWithConfigScore("logger rotate encoder message key"), "logger_encoder_message_key", db.Varchar, form.Text).
  1260  		FieldDisplay(defaultFilterFn("msg"))
  1261  	formList.AddField(lgWithConfigScore("logger rotate encoder stacktrace key"), "logger_encoder_stacktrace_key", db.Varchar, form.Text).
  1262  		FieldDisplay(defaultFilterFn("stacktrace"))
  1263  
  1264  	formList.AddField(lgWithConfigScore("logger rotate encoder level"), "logger_encoder_level", db.Varchar,
  1265  		form.SelectSingle).
  1266  		FieldOptions(types.FieldOptions{
  1267  			{Text: lgWithConfigScore("capital"), Value: "capital"},
  1268  			{Text: lgWithConfigScore("capitalcolor"), Value: "capitalColor"},
  1269  			{Text: lgWithConfigScore("lowercase"), Value: "lowercase"},
  1270  			{Text: lgWithConfigScore("lowercasecolor"), Value: "color"},
  1271  		}).FieldDisplay(defaultFilterFn("capitalColor"))
  1272  	formList.AddField(lgWithConfigScore("logger rotate encoder time"), "logger_encoder_time", db.Varchar,
  1273  		form.SelectSingle).
  1274  		FieldOptions(types.FieldOptions{
  1275  			{Text: "ISO8601(2006-01-02T15:04:05.000Z0700)", Value: "iso8601"},
  1276  			{Text: lgWithConfigScore("millisecond"), Value: "millis"},
  1277  			{Text: lgWithConfigScore("nanosecond"), Value: "nanos"},
  1278  			{Text: "RFC3339(2006-01-02T15:04:05Z07:00)", Value: "rfc3339"},
  1279  			{Text: "RFC3339 Nano(2006-01-02T15:04:05.999999999Z07:00)", Value: "rfc3339nano"},
  1280  		}).FieldDisplay(defaultFilterFn("iso8601"))
  1281  	formList.AddField(lgWithConfigScore("logger rotate encoder duration"), "logger_encoder_duration", db.Varchar,
  1282  		form.SelectSingle).
  1283  		FieldOptions(types.FieldOptions{
  1284  			{Text: lgWithConfigScore("seconds"), Value: "string"},
  1285  			{Text: lgWithConfigScore("nanosecond"), Value: "nanos"},
  1286  			{Text: lgWithConfigScore("microsecond"), Value: "ms"},
  1287  		}).FieldDisplay(defaultFilterFn("string"))
  1288  	formList.AddField(lgWithConfigScore("logger rotate encoder caller"), "logger_encoder_caller", db.Varchar,
  1289  		form.SelectSingle).
  1290  		FieldOptions(types.FieldOptions{
  1291  			{Text: lgWithConfigScore("full path"), Value: "full"},
  1292  			{Text: lgWithConfigScore("short path"), Value: "short"},
  1293  		}).FieldDisplay(defaultFilterFn("full"))
  1294  
  1295  	formList.HideBackButton().HideContinueEditCheckBox().HideContinueNewCheckBox()
  1296  	formList.SetTabGroups(types.NewTabGroups("id", "debug", "env", "language", "theme", "color_scheme",
  1297  		"asset_url", "title", "login_title", "session_life_time", "bootstrap_file_path", "go_mod_file_path", "no_limit_login_ip",
  1298  		"operation_log_off", "allow_del_operation_log", "hide_config_center_entrance", "hide_app_info_entrance", "hide_tool_entrance",
  1299  		"hide_plugin_entrance", "animation_type",
  1300  		"animation_duration", "animation_delay", "file_upload_engine", "extra").
  1301  		AddGroup("access_log_off", "access_assets_log_off", "info_log_off", "error_log_off", "sql_log", "logger_level",
  1302  			"info_log_path", "error_log_path",
  1303  			"access_log_path", "logger_rotate_max_size", "logger_rotate_max_backups",
  1304  			"logger_rotate_max_age", "logger_rotate_compress",
  1305  			"logger_encoder_encoding", "logger_encoder_time_key", "logger_encoder_level_key", "logger_encoder_name_key",
  1306  			"logger_encoder_caller_key", "logger_encoder_message_key", "logger_encoder_stacktrace_key", "logger_encoder_level",
  1307  			"logger_encoder_time", "logger_encoder_duration", "logger_encoder_caller").
  1308  		AddGroup("logo", "mini_logo", "custom_head_html", "custom_foot_html", "footer_info", "login_logo",
  1309  			"custom_404_html", "custom_403_html", "custom_500_html")).
  1310  		SetTabHeaders(lgWithConfigScore("general"), lgWithConfigScore("log"), lgWithConfigScore("custom"))
  1311  
  1312  	formList.SetTable("goadmin_site").
  1313  		SetTitle(lgWithConfigScore("site setting")).
  1314  		SetDescription(lgWithConfigScore("site setting"))
  1315  
  1316  	formList.SetUpdateFn(func(values form2.Values) error {
  1317  
  1318  		ses := values.Get("session_life_time")
  1319  		sesInt, _ := strconv.Atoi(ses)
  1320  		if sesInt < 900 {
  1321  			return errors.New("wrong session life time, must bigger than 900 seconds")
  1322  		}
  1323  		if err := checkJSON(values, "file_upload_engine"); err != nil {
  1324  			return err
  1325  		}
  1326  
  1327  		values["logo"][0] = escape(values.Get("logo"))
  1328  		values["mini_logo"][0] = escape(values.Get("mini_logo"))
  1329  		values["custom_head_html"][0] = escape(values.Get("custom_head_html"))
  1330  		values["custom_foot_html"][0] = escape(values.Get("custom_foot_html"))
  1331  		values["custom_404_html"][0] = escape(values.Get("custom_404_html"))
  1332  		values["custom_403_html"][0] = escape(values.Get("custom_403_html"))
  1333  		values["custom_500_html"][0] = escape(values.Get("custom_500_html"))
  1334  		values["footer_info"][0] = escape(values.Get("footer_info"))
  1335  		values["login_logo"][0] = escape(values.Get("login_logo"))
  1336  
  1337  		var err error
  1338  		if s.c.UpdateProcessFn != nil {
  1339  			values, err = s.c.UpdateProcessFn(values)
  1340  			if err != nil {
  1341  				return err
  1342  			}
  1343  		}
  1344  
  1345  		ui.GetService(services).RemoveOrShowSiteNavButton(values["hide_config_center_entrance"][0] == "true")
  1346  		ui.GetService(services).RemoveOrShowInfoNavButton(values["hide_app_info_entrance"][0] == "true")
  1347  		ui.GetService(services).RemoveOrShowToolNavButton(values["hide_tool_entrance"][0] == "true")
  1348  		ui.GetService(services).RemoveOrShowPlugNavButton(values["hide_plugin_entrance"][0] == "true")
  1349  
  1350  		// TODO: add transaction
  1351  		err = models.Site().SetConn(s.conn).Update(values.RemoveSysRemark())
  1352  		if err != nil {
  1353  			return err
  1354  		}
  1355  		return s.c.Update(values.ToMap())
  1356  	})
  1357  
  1358  	formList.EnableAjax(lgWithConfigScore("modify site config"),
  1359  		lgWithConfigScore("modify site config"),
  1360  		"",
  1361  		lgWithConfigScore("modify site config success"),
  1362  		lgWithConfigScore("modify site config fail"))
  1363  
  1364  	return
  1365  }
  1366  
  1367  func (s *SystemTable) GetGenerateForm(ctx *context.Context) (generateTool Table) {
  1368  	generateTool = NewDefaultTable(DefaultConfigWithDriver(config.GetDatabases().GetDefault().Driver).
  1369  		SetOnlyNewForm())
  1370  
  1371  	formList := generateTool.GetForm().AddXssJsFilter().
  1372  		SetHeadWidth(1).
  1373  		SetInputWidth(4).
  1374  		HideBackButton().
  1375  		HideContinueNewCheckBox()
  1376  
  1377  	formList.AddField("ID", "id", db.Varchar, form.Default).FieldDefault("1").FieldHide()
  1378  
  1379  	connNames := config.GetDatabases().Connections()
  1380  	ops := make(types.FieldOptions, len(connNames))
  1381  	for i, name := range connNames {
  1382  		ops[i] = types.FieldOption{Text: name, Value: name}
  1383  	}
  1384  
  1385  	// General options
  1386  	// ================================
  1387  
  1388  	formList.AddField(lgWithScore("connection", "tool"), "conn", db.Varchar, form.SelectSingle).
  1389  		FieldOptions(ops).
  1390  		FieldOnChooseAjax("table", "/tool/choose/conn",
  1391  			func(ctx *context.Context) (success bool, msg string, data interface{}) {
  1392  				connName := ctx.FormValue("value")
  1393  				if connName == "" {
  1394  					return false, "wrong parameter", nil
  1395  				}
  1396  				cfg := s.c.Databases[connName]
  1397  				conn := db.GetConnectionFromService(services.Get(cfg.Driver))
  1398  				tables, err := db.WithDriverAndConnection(connName, conn).Table(cfg.Name).ShowTables()
  1399  				if err != nil {
  1400  					return false, err.Error(), nil
  1401  				}
  1402  				ops := make(selection.Options, len(tables))
  1403  				for i, table := range tables {
  1404  					ops[i] = selection.Option{Text: table, ID: table}
  1405  				}
  1406  				return true, "ok", ops
  1407  			})
  1408  	formList.AddField(lgWithScore("table", "tool"), "table", db.Varchar, form.SelectSingle).
  1409  		FieldOnChooseAjax("xxxx", "/tool/choose/table",
  1410  			func(ctx *context.Context) (success bool, msg string, data interface{}) {
  1411  
  1412  				var (
  1413  					tableName       = ctx.FormValue("value")
  1414  					connName        = ctx.FormValue("conn")
  1415  					driver          = s.c.Databases[connName].Driver
  1416  					conn            = db.GetConnectionFromService(services.Get(driver))
  1417  					columnsModel, _ = db.WithDriverAndConnection(connName, conn).Table(tableName).ShowColumns()
  1418  
  1419  					fieldField = "Field"
  1420  					typeField  = "Type"
  1421  				)
  1422  
  1423  				if driver == "postgresql" {
  1424  					fieldField = "column_name"
  1425  					typeField = "udt_name"
  1426  				}
  1427  				if driver == "sqlite" {
  1428  					fieldField = "name"
  1429  					typeField = "type"
  1430  				}
  1431  				if driver == "mssql" {
  1432  					fieldField = "column_name"
  1433  					typeField = "data_type"
  1434  				}
  1435  
  1436  				headName := make([]string, len(columnsModel))
  1437  				fieldName := make([]string, len(columnsModel))
  1438  				dbTypeList := make([]string, len(columnsModel))
  1439  				formTypeList := make([]string, len(columnsModel))
  1440  
  1441  				for i, model := range columnsModel {
  1442  					typeName := getType(model[typeField].(string))
  1443  
  1444  					headName[i] = strings.Title(model[fieldField].(string))
  1445  					fieldName[i] = model[fieldField].(string)
  1446  					dbTypeList[i] = typeName
  1447  					formTypeList[i] = form.GetFormTypeFromFieldType(db.DT(strings.ToUpper(typeName)),
  1448  						model[fieldField].(string))
  1449  				}
  1450  
  1451  				return true, "ok", [][]string{headName, fieldName, dbTypeList, formTypeList}
  1452  			}, template.HTML(utils.ParseText("choose_table_ajax", tmpls["choose_table_ajax"], nil)),
  1453  			`"conn":$('.conn').val(),`)
  1454  	formList.AddField(lgWithScore("package", "tool"), "package", db.Varchar, form.Text).FieldDefault("tables")
  1455  	formList.AddField(lgWithScore("primarykey", "tool"), "pk", db.Varchar, form.Text).FieldDefault("id")
  1456  
  1457  	formList.AddField(lgWithScore("table permission", "tool"), "permission", db.Varchar, form.Switch).
  1458  		FieldOptions(types.FieldOptions{
  1459  			{Text: lgWithScore("yes", "tool"), Value: "y"},
  1460  			{Text: lgWithScore("no", "tool"), Value: "n"},
  1461  		}).FieldDefault("n")
  1462  
  1463  	formList.AddField(lgWithScore("extra import package", "tool"), "extra_import_package", db.Varchar, form.Select).
  1464  		FieldOptions(types.FieldOptions{
  1465  			{Text: "time", Value: "time"},
  1466  			{Text: "log", Value: "log"},
  1467  			{Text: "fmt", Value: "fmt"},
  1468  			{Text: "github.com/kotovmak/go-admin/modules/db/dialect", Value: "github.com/kotovmak/go-admin/modules/db/dialect"},
  1469  			{Text: "github.com/kotovmak/go-admin/modules/db", Value: "github.com/kotovmak/go-admin/modules/db"},
  1470  			{Text: "github.com/kotovmak/go-admin/modules/language", Value: "github.com/kotovmak/go-admin/modules/language"},
  1471  			{Text: "github.com/kotovmak/go-admin/modules/logger", Value: "github.com/kotovmak/go-admin/modules/logger"},
  1472  		}).
  1473  		FieldDefault("").
  1474  		FieldOptionExt(map[string]interface{}{
  1475  			"tags": true,
  1476  		})
  1477  
  1478  	formList.AddField(lgWithScore("output", "tool"), "path", db.Varchar, form.Text).
  1479  		FieldDefault("").FieldMust().FieldHelpMsg(template.HTML(lgWithScore("use absolute path", "tool")))
  1480  
  1481  	formList.AddField(lgWithScore("extra code", "tool"), "extra_code", db.Varchar, form.Code).
  1482  		FieldDefault("").FieldInputWidth(11)
  1483  
  1484  	// Info table generate options
  1485  	// ================================
  1486  
  1487  	formList.AddField(lgWithScore("title", "tool"), "table_title", db.Varchar, form.Text)
  1488  	formList.AddField(lgWithScore("description", "tool"), "table_description", db.Varchar, form.Text)
  1489  
  1490  	formList.AddRow(func(panel *types.FormPanel) {
  1491  		addSwitchForTool(panel, "filter area", "hide_filter_area", "n", 2)
  1492  		panel.AddField(lgWithScore("filter form layout", "tool"), "filter_form_layout", db.Varchar, form.SelectSingle).
  1493  			FieldOptions(types.FieldOptions{
  1494  				{Text: form.LayoutDefault.String(), Value: form.LayoutDefault.String()},
  1495  				{Text: form.LayoutTwoCol.String(), Value: form.LayoutTwoCol.String()},
  1496  				{Text: form.LayoutThreeCol.String(), Value: form.LayoutThreeCol.String()},
  1497  				{Text: form.LayoutFourCol.String(), Value: form.LayoutFourCol.String()},
  1498  				{Text: form.LayoutFlow.String(), Value: form.LayoutFlow.String()},
  1499  			}).FieldDefault(form.LayoutDefault.String()).
  1500  			FieldRowWidth(4).FieldHeadWidth(3)
  1501  	})
  1502  
  1503  	formList.AddRow(func(panel *types.FormPanel) {
  1504  		addSwitchForTool(panel, "new button", "hide_new_button", "n", 2)
  1505  		addSwitchForTool(panel, "export button", "hide_export_button", "n", 4, 3)
  1506  		addSwitchForTool(panel, "edit button", "hide_edit_button", "n", 4, 2)
  1507  	})
  1508  
  1509  	formList.AddRow(func(panel *types.FormPanel) {
  1510  		addSwitchForTool(panel, "pagination", "hide_pagination", "n", 2)
  1511  		addSwitchForTool(panel, "delete button", "hide_delete_button", "n", 4, 3)
  1512  		addSwitchForTool(panel, "detail button", "hide_detail_button", "n", 4, 2)
  1513  	})
  1514  
  1515  	formList.AddRow(func(panel *types.FormPanel) {
  1516  		addSwitchForTool(panel, "filter button", "hide_filter_button", "n", 2)
  1517  		addSwitchForTool(panel, "row selector", "hide_row_selector", "n", 4, 3)
  1518  		addSwitchForTool(panel, "query info", "hide_query_info", "n", 4, 2)
  1519  	})
  1520  
  1521  	formList.AddTable(lgWithScore("field", "tool"), "fields", func(pa *types.FormPanel) {
  1522  		pa.AddField(lgWithScore("title", "tool"), "field_head", db.Varchar, form.Text).FieldHideLabel().
  1523  			FieldDisplay(func(value types.FieldModel) interface{} {
  1524  				return []string{""}
  1525  			})
  1526  		pa.AddField(lgWithScore("field name", "tool"), "field_name", db.Varchar, form.Text).FieldHideLabel().
  1527  			FieldDisplay(func(value types.FieldModel) interface{} {
  1528  				return []string{""}
  1529  			})
  1530  		pa.AddField(lgWithScore("field filterable", "tool"), "field_filterable", db.Varchar, form.CheckboxSingle).
  1531  			FieldOptions(types.FieldOptions{
  1532  				{Text: "", Value: "y"},
  1533  				{Text: "", Value: "n"},
  1534  			}).
  1535  			FieldDefault("n").
  1536  			FieldDisplay(func(value types.FieldModel) interface{} {
  1537  				return []string{"n"}
  1538  			})
  1539  		pa.AddField(lgWithScore("field sortable", "tool"), "field_sortable", db.Varchar, form.CheckboxSingle).
  1540  			FieldOptions(types.FieldOptions{
  1541  				{Text: "", Value: "y"},
  1542  				{Text: "", Value: "n"},
  1543  			}).
  1544  			FieldDefault("n").
  1545  			FieldDisplay(func(value types.FieldModel) interface{} {
  1546  				return []string{"n"}
  1547  			})
  1548  		pa.AddField(lgWithScore("field hide", "tool"), "field_hide", db.Varchar, form.CheckboxSingle).
  1549  			FieldOptions(types.FieldOptions{
  1550  				{Text: "", Value: "y"},
  1551  				{Text: "", Value: "n"},
  1552  			}).
  1553  			FieldDefault("n").
  1554  			FieldDisplay(func(value types.FieldModel) interface{} {
  1555  				return []string{"n"}
  1556  			})
  1557  		pa.AddField(lgWithScore("info field editable", "tool"), "info_field_editable", db.Varchar, form.CheckboxSingle).
  1558  			FieldOptions(types.FieldOptions{
  1559  				{Text: "", Value: "y"},
  1560  				{Text: "", Value: "n"},
  1561  			}).
  1562  			FieldDefault("n").
  1563  			FieldDisplay(func(value types.FieldModel) interface{} {
  1564  				return []string{"n"}
  1565  			})
  1566  		//pa.AddField(lgWithScore("db display type", "tool"), "field_display_type", db.Varchar, form.SelectSingle).
  1567  		//	FieldOptions(infoFieldDisplayTypeOptions()).
  1568  		//	FieldDisplay(func(value types.FieldModel) interface{} {
  1569  		//		return []string{""}
  1570  		//	})
  1571  		pa.AddField(lgWithScore("db type", "tool"), "field_db_type", db.Varchar, form.SelectSingle).
  1572  			FieldOptions(databaseTypeOptions()).
  1573  			FieldDisplay(func(value types.FieldModel) interface{} {
  1574  				return []string{"Int"}
  1575  			})
  1576  	}).FieldInputWidth(11)
  1577  
  1578  	// Form generate options
  1579  	// ================================
  1580  
  1581  	formList.AddField(lgWithScore("title", "tool"), "form_title", db.Varchar, form.Text)
  1582  	formList.AddField(lgWithScore("description", "tool"), "form_description", db.Varchar, form.Text)
  1583  
  1584  	formList.AddRow(func(panel *types.FormPanel) {
  1585  		addSwitchForTool(panel, "continue edit checkbox", "hide_continue_edit_check_box", "n", 2)
  1586  		addSwitchForTool(panel, "reset button", "hide_reset_button", "n", 5, 3)
  1587  	})
  1588  
  1589  	formList.AddRow(func(panel *types.FormPanel) {
  1590  		addSwitchForTool(panel, "continue new checkbox", "hide_continue_new_check_box", "n", 2)
  1591  		addSwitchForTool(panel, "back button", "hide_back_button", "n", 5, 3)
  1592  	})
  1593  
  1594  	formList.AddTable(lgWithScore("field", "tool"), "fields_form", func(pa *types.FormPanel) {
  1595  		pa.AddField(lgWithScore("title", "tool"), "field_head_form", db.Varchar, form.Text).FieldHideLabel().
  1596  			FieldDisplay(func(value types.FieldModel) interface{} {
  1597  				return []string{""}
  1598  			})
  1599  		pa.AddField(lgWithScore("field name", "tool"), "field_name_form", db.Varchar, form.Text).FieldHideLabel().
  1600  			FieldDisplay(func(value types.FieldModel) interface{} {
  1601  				return []string{""}
  1602  			})
  1603  		pa.AddField(lgWithScore("field editable", "tool"), "field_canedit", db.Varchar, form.CheckboxSingle).
  1604  			FieldOptions(types.FieldOptions{
  1605  				{Text: "", Value: "y"},
  1606  				{Text: "", Value: "n"},
  1607  			}).
  1608  			FieldDefault("y").
  1609  			FieldDisplay(func(value types.FieldModel) interface{} {
  1610  				return []string{"y"}
  1611  			})
  1612  		pa.AddField(lgWithScore("field can add", "tool"), "field_canadd", db.Varchar, form.CheckboxSingle).
  1613  			FieldOptions(types.FieldOptions{
  1614  				{Text: "", Value: "y"},
  1615  				{Text: "", Value: "n"},
  1616  			}).
  1617  			FieldDefault("y").
  1618  			FieldDisplay(func(value types.FieldModel) interface{} {
  1619  				return []string{"y"}
  1620  			})
  1621  		pa.AddField(lgWithScore("field default", "tool"), "field_default", db.Varchar, form.Text).FieldHideLabel().
  1622  			FieldDisplay(func(value types.FieldModel) interface{} {
  1623  				return []string{""}
  1624  			})
  1625  		pa.AddField(lgWithScore("field display", "tool"), "field_display", db.Varchar, form.SelectSingle).
  1626  			FieldOptions(types.FieldOptions{
  1627  				{Text: lgWithScore("field display normal", "tool"), Value: "0"},
  1628  				{Text: lgWithScore("field diplay hide", "tool"), Value: "1"},
  1629  				{Text: lgWithScore("field diplay edit hide", "tool"), Value: "2"},
  1630  				{Text: lgWithScore("field diplay create hide", "tool"), Value: "3"},
  1631  			}).
  1632  			FieldDisplay(func(value types.FieldModel) interface{} {
  1633  				return []string{"0"}
  1634  			})
  1635  		pa.AddField(lgWithScore("db type", "tool"), "field_db_type_form", db.Varchar, form.SelectSingle).
  1636  			FieldOptions(databaseTypeOptions()).
  1637  			FieldDisplay(func(value types.FieldModel) interface{} {
  1638  				return []string{"Int"}
  1639  			})
  1640  		pa.AddField(lgWithScore("form type", "tool"), "field_form_type_form", db.Varchar, form.SelectSingle).
  1641  			FieldOptions(formTypeOptions()).FieldDisplay(func(value types.FieldModel) interface{} {
  1642  			return []string{"Text"}
  1643  		})
  1644  	}).FieldInputWidth(11)
  1645  
  1646  	// Detail page generate options
  1647  	// ================================
  1648  
  1649  	formList.AddField(lgWithScore("title", "tool"), "detail_title", db.Varchar, form.Text)
  1650  	formList.AddField(lgWithScore("description", "tool"), "detail_description", db.Varchar, form.Text)
  1651  
  1652  	formList.AddField(lgWithScore("detail display", "tool"), "detail_display", db.Varchar, form.SelectSingle).
  1653  		FieldOptions(types.FieldOptions{
  1654  			{Text: lgWithScore("follow list page", "tool"), Value: "0"},
  1655  			{Text: lgWithScore("inherit from list page", "tool"), Value: "1"},
  1656  			{Text: lgWithScore("independent from list page", "tool"), Value: "2"},
  1657  		}).
  1658  		FieldDefault("0").
  1659  		FieldOnChooseHide("0", "detail_title", "detail_description", "fields_detail")
  1660  
  1661  	formList.AddTable(lgWithScore("field", "tool"), "fields_detail", func(pa *types.FormPanel) {
  1662  		pa.AddField(lgWithScore("title", "tool"), "detail_field_head", db.Varchar, form.Text).FieldHideLabel().
  1663  			FieldDisplay(func(value types.FieldModel) interface{} {
  1664  				return []string{""}
  1665  			})
  1666  		pa.AddField(lgWithScore("field name", "tool"), "detail_field_name", db.Varchar, form.Text).FieldHideLabel().
  1667  			FieldDisplay(func(value types.FieldModel) interface{} {
  1668  				return []string{""}
  1669  			})
  1670  		pa.AddField(lgWithScore("db type", "tool"), "detail_field_db_type", db.Varchar, form.SelectSingle).
  1671  			FieldOptions(databaseTypeOptions()).
  1672  			FieldDisplay(func(value types.FieldModel) interface{} {
  1673  				return []string{"Int"}
  1674  			})
  1675  	}).FieldInputWidth(11)
  1676  
  1677  	formList.SetTabGroups(types.
  1678  		NewTabGroups("conn", "table", "package", "pk", "permission", "extra_import_package", "path", "extra_code").
  1679  		AddGroup("table_title", "table_description", "hide_filter_area", "filter_form_layout",
  1680  			"hide_new_button", "hide_export_button", "hide_edit_button",
  1681  			"hide_pagination", "hide_delete_button", "hide_detail_button",
  1682  			"hide_filter_button", "hide_row_selector", "hide_query_info",
  1683  			"fields").
  1684  		AddGroup("form_title", "form_description", "hide_continue_edit_check_box", "hide_reset_button",
  1685  			"hide_continue_new_check_box", "hide_back_button",
  1686  			"fields_form").
  1687  		AddGroup("detail_display", "detail_title", "detail_description", "fields_detail")).
  1688  		SetTabHeaders(lgWithScore("basic info", "tool"), lgWithScore("table info", "tool"),
  1689  			lgWithScore("form info", "tool"), lgWithScore("detail info", "tool"))
  1690  
  1691  	formList.SetTable("tool").
  1692  		SetTitle(lgWithScore("tool", "tool")).
  1693  		SetDescription(lgWithScore("tool", "tool")).
  1694  		SetHeader(template.HTML(`<h3 class="box-title">` +
  1695  			lgWithScore("generate table model", "tool") + `</h3>`))
  1696  
  1697  	formList.SetInsertFn(func(values form2.Values) error {
  1698  
  1699  		table := values.Get("table")
  1700  
  1701  		if table == "" {
  1702  			return errors.New("table is empty")
  1703  		}
  1704  
  1705  		if values.Get("permission") == "y" {
  1706  			tools.InsertPermissionOfTable(s.conn, table)
  1707  		}
  1708  
  1709  		output := values.Get("path")
  1710  
  1711  		if output == "" {
  1712  			return errors.New("output path is empty")
  1713  		}
  1714  
  1715  		connName := values.Get("conn")
  1716  
  1717  		fields := make(tools.Fields, len(values["field_head"]))
  1718  
  1719  		for i := 0; i < len(values["field_head"]); i++ {
  1720  			fields[i] = tools.Field{
  1721  				Head:         values["field_head"][i],
  1722  				Name:         values["field_name"][i],
  1723  				DBType:       values["field_db_type"][i],
  1724  				Filterable:   values["field_filterable"][i] == "y",
  1725  				Sortable:     values["field_sortable"][i] == "y",
  1726  				Hide:         values["field_hide"][i] == "y",
  1727  				InfoEditable: values["info_field_editable"][i] == "y",
  1728  			}
  1729  		}
  1730  
  1731  		extraImport := ""
  1732  		for _, pack := range values["extra_import_package[]"] {
  1733  			if extraImport != "" {
  1734  				extraImport += `
  1735  `
  1736  			}
  1737  			extraImport += `	"` + pack + `"`
  1738  		}
  1739  
  1740  		formFields := make(tools.Fields, len(values["field_head_form"]))
  1741  
  1742  		for i := 0; i < len(values["field_head_form"]); i++ {
  1743  			extraFun := ""
  1744  			if values["field_name_form"][i] == `created_at` {
  1745  				extraFun += `.FieldNowWhenInsert()`
  1746  			} else if values["field_name_form"][i] == `updated_at` {
  1747  				extraFun += `.FieldNowWhenUpdate()`
  1748  			} else if values["field_default"][i] != "" && !strings.Contains(values["field_default"][i], `"`) {
  1749  				values["field_default"][i] = `"` + values["field_default"][i] + `"`
  1750  			}
  1751  			formFields[i] = tools.Field{
  1752  				Head:       values["field_head_form"][i],
  1753  				Name:       values["field_name_form"][i],
  1754  				Default:    values["field_default"][i],
  1755  				FormType:   values["field_form_type_form"][i],
  1756  				DBType:     values["field_db_type_form"][i],
  1757  				CanAdd:     values["field_canadd"][i] == "y",
  1758  				Editable:   values["field_canedit"][i] == "y",
  1759  				FormHide:   values["field_display"][i] == "1",
  1760  				CreateHide: values["field_display"][i] == "2",
  1761  				EditHide:   values["field_display"][i] == "3",
  1762  				ExtraFun:   extraFun,
  1763  			}
  1764  		}
  1765  
  1766  		detailFields := make(tools.Fields, len(values["detail_field_head"]))
  1767  
  1768  		for i := 0; i < len(values["detail_field_head"]); i++ {
  1769  			detailFields[i] = tools.Field{
  1770  				Head:   values["detail_field_head"][i],
  1771  				Name:   values["detail_field_name"][i],
  1772  				DBType: values["detail_field_db_type"][i],
  1773  			}
  1774  		}
  1775  
  1776  		detailDisplay, _ := strconv.ParseUint(values.Get("detail_display"), 10, 64)
  1777  
  1778  		err := tools.Generate(tools.NewParamWithFields(tools.Config{
  1779  			Connection:               connName,
  1780  			Driver:                   s.c.Databases[connName].Driver,
  1781  			Package:                  values.Get("package"),
  1782  			Table:                    table,
  1783  			HideFilterArea:           values.Get("hide_filter_area") == "y",
  1784  			HideNewButton:            values.Get("hide_new_button") == "y",
  1785  			HideExportButton:         values.Get("hide_export_button") == "y",
  1786  			HideEditButton:           values.Get("hide_edit_button") == "y",
  1787  			HideDeleteButton:         values.Get("hide_delete_button") == "y",
  1788  			HideDetailButton:         values.Get("hide_detail_button") == "y",
  1789  			HideFilterButton:         values.Get("hide_filter_button") == "y",
  1790  			HideRowSelector:          values.Get("hide_row_selector") == "y",
  1791  			HidePagination:           values.Get("hide_pagination") == "y",
  1792  			HideQueryInfo:            values.Get("hide_query_info") == "y",
  1793  			HideContinueEditCheckBox: values.Get("hide_continue_edit_check_box") == "y",
  1794  			HideContinueNewCheckBox:  values.Get("hide_continue_new_check_box") == "y",
  1795  			HideResetButton:          values.Get("hide_reset_button") == "y",
  1796  			HideBackButton:           values.Get("hide_back_button") == "y",
  1797  			FilterFormLayout:         form.GetLayoutFromString(values.Get("filter_form_layout")),
  1798  			Schema:                   values.Get("schema"),
  1799  			Output:                   output,
  1800  			DetailDisplay:            uint8(detailDisplay),
  1801  			FormTitle:                values.Get("form_title"),
  1802  			FormDescription:          values.Get("form_description"),
  1803  			DetailTitle:              values.Get("detail_title"),
  1804  			DetailDescription:        values.Get("detail_description"),
  1805  			TableTitle:               values.Get("table_title"),
  1806  			TableDescription:         values.Get("table_description"),
  1807  			ExtraImport:              extraImport,
  1808  			ExtraCode:                escape(values.Get("extra_code")),
  1809  		}, fields, formFields, detailFields))
  1810  
  1811  		if err != nil {
  1812  			return err
  1813  		}
  1814  
  1815  		return tools.GenerateTables(output, values.Get("package"), []string{table}, false)
  1816  	})
  1817  
  1818  	formList.EnableAjaxData(types.AjaxData{
  1819  		SuccessTitle: lgWithScore("generate table model", "tool"),
  1820  		ErrorTitle:   lgWithScore("generate table model", "tool"),
  1821  		SuccessText:  lgWithScore("generate table model success", "tool"),
  1822  		ErrorText:    lgWithScore("generate table model fail", "tool"),
  1823  		DisableJump:  true,
  1824  	})
  1825  
  1826  	formList.SetFooterHtml(utils.ParseHTML("generator", tmpls["generator"], map[string]string{
  1827  		"prefix": "go_admin_" + config.GetAppID() + "_generator_",
  1828  	}))
  1829  
  1830  	formList.SetFormNewBtnWord(template.HTML(lgWithScore("generate", "tool")))
  1831  	formList.SetWrapper(func(content tmpl.HTML) tmpl.HTML {
  1832  		headli := html.LiEl().SetClass("list-group-item", "list-head").
  1833  			SetContent(template.HTML(lgWithScore("generated tables", "tool"))).Get()
  1834  		return html.UlEl().SetClass("save_table_list", "list-group").SetContent(
  1835  			headli).Get() + content
  1836  	})
  1837  
  1838  	formList.SetHideSideBar()
  1839  
  1840  	return generateTool
  1841  }
  1842  
  1843  // -------------------------
  1844  // helper functions
  1845  // -------------------------
  1846  
  1847  func encodePassword(pwd []byte) string {
  1848  	hash, err := bcrypt.GenerateFromPassword(pwd, bcrypt.DefaultCost)
  1849  	if err != nil {
  1850  		return ""
  1851  	}
  1852  	return string(hash)
  1853  }
  1854  
  1855  func label() types.LabelAttribute {
  1856  	return template.Get(config.GetTheme()).Label().SetType("success")
  1857  }
  1858  
  1859  func lg(v string) string {
  1860  	return language.Get(v)
  1861  }
  1862  
  1863  func defaultFilterFn(val string, def ...string) types.FieldFilterFn {
  1864  	return func(value types.FieldModel) interface{} {
  1865  		if len(def) > 0 {
  1866  			if value.Value == def[0] {
  1867  				return val
  1868  			}
  1869  		} else {
  1870  			if value.Value == "" {
  1871  				return val
  1872  			}
  1873  		}
  1874  		return value.Value
  1875  	}
  1876  }
  1877  
  1878  func lgWithScore(v string, score ...string) string {
  1879  	return language.GetWithScope(v, score...)
  1880  }
  1881  
  1882  func lgWithConfigScore(v string, score ...string) string {
  1883  	scores := append([]string{"config"}, score...)
  1884  	return language.GetWithScope(v, scores...)
  1885  }
  1886  
  1887  func link(url, content string) tmpl.HTML {
  1888  	return html.AEl().
  1889  		SetAttr("href", url).
  1890  		SetContent(template.HTML(lg(content))).
  1891  		Get()
  1892  }
  1893  
  1894  func escape(s string) string {
  1895  	if s == "" {
  1896  		return ""
  1897  	}
  1898  	s, err := url.QueryUnescape(s)
  1899  	if err != nil {
  1900  		logger.Error("escape error", err)
  1901  	}
  1902  	return s
  1903  }
  1904  
  1905  func checkJSON(values form2.Values, key string) error {
  1906  	v := values.Get(key)
  1907  	if v != "" && !utils.IsJSON(v) {
  1908  		return errors.New("wrong " + key)
  1909  	}
  1910  	return nil
  1911  }
  1912  
  1913  func (s *SystemTable) table(table string) *db.SQL {
  1914  	return s.connection().Table(table)
  1915  }
  1916  
  1917  func (s *SystemTable) connection() *db.SQL {
  1918  	return db.WithDriver(s.conn)
  1919  }
  1920  
  1921  func interfaces(arr []string) []interface{} {
  1922  	var iarr = make([]interface{}, len(arr))
  1923  
  1924  	for key, v := range arr {
  1925  		iarr[key] = v
  1926  	}
  1927  
  1928  	return iarr
  1929  }
  1930  
  1931  func addSwitchForTool(formList *types.FormPanel, head, field, def string, row ...int) {
  1932  	formList.AddField(lgWithScore(head, "tool"), field, db.Varchar, form.Switch).
  1933  		FieldOptions(types.FieldOptions{
  1934  			{Text: lgWithScore("show", "tool"), Value: "n"},
  1935  			{Text: lgWithScore("hide", "tool"), Value: "y"},
  1936  		}).FieldDefault(def)
  1937  	if len(row) > 0 {
  1938  		formList.FieldRowWidth(row[0])
  1939  	}
  1940  	if len(row) > 1 {
  1941  		formList.FieldHeadWidth(row[1])
  1942  	}
  1943  	if len(row) > 2 {
  1944  		formList.FieldInputWidth(row[2])
  1945  	}
  1946  }
  1947  
  1948  func formTypeOptions() types.FieldOptions {
  1949  	opts := make(types.FieldOptions, len(form.AllType))
  1950  	for i := 0; i < len(form.AllType); i++ {
  1951  		v := form.AllType[i].Name()
  1952  		opts[i] = types.FieldOption{Text: v, Value: v}
  1953  	}
  1954  	return opts
  1955  }
  1956  
  1957  func databaseTypeOptions() types.FieldOptions {
  1958  	opts := make(types.FieldOptions, len(db.IntTypeList)+
  1959  		len(db.StringTypeList)+
  1960  		len(db.FloatTypeList)+
  1961  		len(db.UintTypeList)+
  1962  		len(db.BoolTypeList))
  1963  	z := 0
  1964  	for _, t := range db.IntTypeList {
  1965  		text := string(t)
  1966  		v := strings.Title(strings.ToLower(text))
  1967  		opts[z] = types.FieldOption{Text: text, Value: v}
  1968  		z++
  1969  	}
  1970  	for _, t := range db.StringTypeList {
  1971  		text := string(t)
  1972  		v := strings.Title(strings.ToLower(text))
  1973  		opts[z] = types.FieldOption{Text: text, Value: v}
  1974  		z++
  1975  	}
  1976  	for _, t := range db.FloatTypeList {
  1977  		text := string(t)
  1978  		v := strings.Title(strings.ToLower(text))
  1979  		opts[z] = types.FieldOption{Text: text, Value: v}
  1980  		z++
  1981  	}
  1982  	for _, t := range db.UintTypeList {
  1983  		text := string(t)
  1984  		v := strings.Title(strings.ToLower(text))
  1985  		opts[z] = types.FieldOption{Text: text, Value: v}
  1986  		z++
  1987  	}
  1988  	for _, t := range db.BoolTypeList {
  1989  		text := string(t)
  1990  		v := strings.Title(strings.ToLower(text))
  1991  		opts[z] = types.FieldOption{Text: text, Value: v}
  1992  		z++
  1993  	}
  1994  	return opts
  1995  }
  1996  
  1997  func getType(typeName string) string {
  1998  	r, _ := regexp.Compile(`\(.*?\)`)
  1999  	typeName = r.ReplaceAllString(typeName, "")
  2000  	r2, _ := regexp.Compile(`unsigned(.*)`)
  2001  	return strings.TrimSpace(strings.Title(strings.ToLower(r2.ReplaceAllString(typeName, ""))))
  2002  }