autocomplete_data_source.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package presets
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strconv"
  6. "strings"
  7. "github.com/qor5/web"
  8. "github.com/qor5/ui/vuetifyx"
  9. )
  10. const autocompleteDataSourceEvent = "autocomplete-data-source-event"
  11. type AutocompleteDataResult struct {
  12. Items []OptionItem `json:"items"`
  13. Total int `json:"total"`
  14. Current int `json:"current"`
  15. Pages int `json:"pages"`
  16. }
  17. type OptionItem struct {
  18. Text string `json:"text,omitempty"`
  19. Value string `json:"value,omitempty"`
  20. Icon string `json:"icon,omitempty"`
  21. }
  22. type AutocompleteDataSourceConfig struct {
  23. OptionValue string
  24. OptionText interface{} //func(interface{}) string or string
  25. OptionIcon func(interface{}) string
  26. IsPaging bool
  27. KeywordColumns []string
  28. SQLConditions []*SQLCondition
  29. OrderBy string
  30. PerPage int64
  31. }
  32. func (b *ListingBuilder) ConfigureAutocompleteDataSource(config *AutocompleteDataSourceConfig, name ...string) *vuetifyx.AutocompleteDataSource {
  33. if config == nil {
  34. panic("config is required")
  35. }
  36. if config.OptionValue == "" {
  37. config.OptionValue = "ID"
  38. }
  39. if config.OptionText == nil {
  40. config.OptionText = "ID"
  41. }
  42. if config.KeywordColumns == nil {
  43. config.KeywordColumns = b.searchColumns
  44. }
  45. if config.OrderBy == "" {
  46. config.OrderBy = b.orderBy
  47. }
  48. if config.PerPage == 0 {
  49. config.PerPage = b.perPage
  50. }
  51. if config.PerPage == 0 {
  52. config.PerPage = 20
  53. }
  54. eventName := autocompleteDataSourceEvent
  55. if len(name) > 0 {
  56. eventName = eventName + "-" + strings.ToLower(name[0])
  57. }
  58. b.mb.RegisterEventFunc(eventName, func(ctx *web.EventContext) (r web.EventResponse, err error) {
  59. var (
  60. objs interface{}
  61. totalCount int
  62. page int64
  63. )
  64. if v, err := strconv.ParseInt(ctx.R.FormValue("page"), 10, 64); err == nil {
  65. page = v
  66. }
  67. searchParams := &SearchParams{
  68. KeywordColumns: b.searchColumns,
  69. Keyword: ctx.R.FormValue("keyword"),
  70. PerPage: config.PerPage,
  71. OrderBy: config.OrderBy,
  72. Page: page,
  73. }
  74. if config.SQLConditions != nil {
  75. searchParams.SQLConditions = config.SQLConditions
  76. }
  77. objs, totalCount, err = b.Searcher(b.mb.NewModelSlice(), searchParams, ctx)
  78. if err != nil {
  79. return web.EventResponse{}, err
  80. }
  81. reflectValue := reflect.Indirect(reflect.ValueOf(objs))
  82. var items []OptionItem
  83. for i := 0; i < reflectValue.Len(); i++ {
  84. var value = fmt.Sprintf("%v", reflect.Indirect(reflectValue.Index(i)).FieldByName(config.OptionValue).Interface())
  85. var text string
  86. switch config.OptionText.(type) {
  87. case func(interface{}) string:
  88. text = config.OptionText.(func(interface{}) string)(reflectValue.Index(i).Interface())
  89. case string:
  90. text = fmt.Sprintf("%v", reflect.Indirect(reflectValue.Index(i)).FieldByName(config.OptionText.(string)).Interface())
  91. }
  92. var icon string
  93. if config.OptionIcon != nil {
  94. icon = config.OptionIcon(reflectValue.Index(i).Interface())
  95. }
  96. items = append(items, OptionItem{
  97. Text: text,
  98. Value: value,
  99. Icon: icon,
  100. })
  101. }
  102. current := int((page-1)*config.PerPage) + len(items)
  103. if current > totalCount {
  104. current = totalCount
  105. }
  106. pages := totalCount / int(config.PerPage)
  107. if totalCount%int(config.PerPage) > 0 {
  108. pages++
  109. }
  110. r.Data = AutocompleteDataResult{
  111. Total: totalCount,
  112. Current: current,
  113. Pages: pages,
  114. Items: items,
  115. }
  116. return
  117. })
  118. return &vuetifyx.AutocompleteDataSource{
  119. RemoteURL: b.mb.Info().ListingHref(),
  120. EventName: eventName,
  121. IsPaging: config.IsPaging,
  122. HasIcon: config.OptionIcon != nil,
  123. }
  124. }