list_content.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package containers
  2. import (
  3. "database/sql/driver"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/qor5/ui/vuetify"
  8. "github.com/iancoleman/strcase"
  9. "github.com/jinzhu/inflection"
  10. "github.com/qor5/admin/pagebuilder"
  11. "github.com/qor5/admin/presets"
  12. "github.com/qor5/web"
  13. . "github.com/theplant/htmlgo"
  14. "gorm.io/gorm"
  15. )
  16. type ListContent struct {
  17. ID uint
  18. AddTopSpace bool
  19. AddBottomSpace bool
  20. AnchorID string
  21. Items ListItems `sql:"type:text;"`
  22. BackgroundColor string
  23. Link string
  24. LinkText string
  25. LinkDisplayOption string
  26. }
  27. type ListItem struct {
  28. HeadingIcon string
  29. Heading string
  30. Text string
  31. Link string
  32. LinkText string
  33. }
  34. func (*ListContent) TableName() string {
  35. return "container_list_content"
  36. }
  37. type ListItems []*ListItem
  38. func (this ListItems) Value() (driver.Value, error) {
  39. return json.Marshal(this)
  40. }
  41. func (this *ListItems) Scan(value interface{}) error {
  42. switch v := value.(type) {
  43. case string:
  44. return json.Unmarshal([]byte(v), this)
  45. case []byte:
  46. return json.Unmarshal(v, this)
  47. default:
  48. return errors.New("not supported")
  49. }
  50. }
  51. func RegisterListContentContainer(pb *pagebuilder.Builder, db *gorm.DB) {
  52. vb := pb.RegisterContainer("ListContent").
  53. RenderFunc(func(obj interface{}, input *pagebuilder.RenderInput, ctx *web.EventContext) HTMLComponent {
  54. v := obj.(*ListContent)
  55. return ListContentBody(v, input)
  56. })
  57. mb := vb.Model(&ListContent{})
  58. eb := mb.Editing("AddTopSpace", "AddBottomSpace", "AnchorID", "BackgroundColor", "Items", "Link", "LinkText", "LinkDisplayOption")
  59. eb.Field("BackgroundColor").ComponentFunc(func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) HTMLComponent {
  60. return vuetify.VSelect().
  61. Items([]string{"white", "grey"}).
  62. Value(field.Value(obj)).
  63. Label(field.Label).
  64. FieldName(field.FormKey)
  65. })
  66. eb.Field("LinkDisplayOption").ComponentFunc(func(obj interface{}, field *presets.FieldContext, ctx *web.EventContext) HTMLComponent {
  67. return vuetify.VSelect().
  68. Items([]string{"desktop", "mobile", "all"}).
  69. Value(field.Value(obj)).
  70. Label(field.Label).
  71. FieldName(field.FormKey)
  72. })
  73. fb := pb.GetPresetsBuilder().NewFieldsBuilder(presets.WRITE).Model(&ListItem{}).Only("HeadingIcon", "Heading", "Text", "Link", "LinkText")
  74. eb.Field("Items").Nested(fb, &presets.DisplayFieldInSorter{Field: "Heading"})
  75. }
  76. func ListContentBody(data *ListContent, input *pagebuilder.RenderInput) (body HTMLComponent) {
  77. body = ContainerWrapper(
  78. fmt.Sprintf(inflection.Plural(strcase.ToKebab("ListContent"))+"_%v", data.ID), data.AnchorID, "container-list_content container-lottie",
  79. data.BackgroundColor, "", "",
  80. "", data.AddTopSpace, data.AddBottomSpace, input.IsEditor, input.IsReadonly, "",
  81. Div(
  82. ListItemsBody(data.Items, input),
  83. If(data.LinkText != "" && data.Link != "",
  84. Div(
  85. LinkTextWithArrow(data.LinkText, data.Link),
  86. ).Class("container-list_content-link").Attr("data-display", data.LinkDisplayOption),
  87. ),
  88. ).Class("container-wrapper"),
  89. )
  90. return
  91. }
  92. func ListItemsBody(items []*ListItem, input *pagebuilder.RenderInput) HTMLComponent {
  93. itemsDiv := Div().Class("container-list_content-grid")
  94. for _, i := range items {
  95. itemsDiv.AppendChildren(
  96. Div(
  97. Div(
  98. If(i.Link != "", A(
  99. If(i.HeadingIcon != "", Div(RawHTML(i.HeadingIcon)).Class("container-list_content-icon")),
  100. H3(i.Heading),
  101. ).Class("container-list_content-heading").AttrIf("href", i.Link, i.Link != "")),
  102. If(i.Link == "", Div(
  103. If(i.HeadingIcon != "", Div(RawHTML(i.HeadingIcon)).Class("container-list_content-icon")),
  104. H3(i.Heading),
  105. ).Class("container-list_content-heading")),
  106. Div(
  107. P(Text(i.Text)),
  108. LinkTextWithArrow(i.LinkText, i.Link),
  109. ).Class("container-list_content-content"),
  110. ).Class("container-list_content-inner"),
  111. ).Class("container-list_content-item").AttrIf("data-has-icon", "true", i.HeadingIcon != ""),
  112. )
  113. }
  114. return itemsDiv
  115. }