list_content_with_image.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package containers
  2. import (
  3. "database/sql/driver"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "github.com/iancoleman/strcase"
  8. "github.com/jinzhu/inflection"
  9. "github.com/qor5/admin/media/media_library"
  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 ListContentWithImage struct {
  17. ID uint
  18. AddTopSpace bool
  19. AddBottomSpace bool
  20. AnchorID string
  21. Items ImageListItems
  22. }
  23. type ImageListItems []*ImageListItem
  24. type ImageListItem struct {
  25. Image media_library.MediaBox `sql:"type:text;"`
  26. Link string
  27. Heading string
  28. Subheading string
  29. Text string
  30. }
  31. func (*ListContentWithImage) TableName() string {
  32. return "container_list_content_with_image"
  33. }
  34. func (this ImageListItems) Value() (driver.Value, error) {
  35. return json.Marshal(this)
  36. }
  37. func (this *ImageListItems) Scan(value interface{}) error {
  38. switch v := value.(type) {
  39. case string:
  40. return json.Unmarshal([]byte(v), this)
  41. case []byte:
  42. return json.Unmarshal(v, this)
  43. default:
  44. return errors.New("not supported")
  45. }
  46. }
  47. func RegisterListContentWithImageContainer(pb *pagebuilder.Builder, db *gorm.DB) {
  48. vb := pb.RegisterContainer("ListContentWithImage").
  49. RenderFunc(func(obj interface{}, input *pagebuilder.RenderInput, ctx *web.EventContext) HTMLComponent {
  50. v := obj.(*ListContentWithImage)
  51. return ListContentWithImageBody(v, input)
  52. })
  53. mb := vb.Model(&ListContentWithImage{})
  54. eb := mb.Editing("AddTopSpace", "AddBottomSpace", "AnchorID", "Items")
  55. fb := pb.GetPresetsBuilder().NewFieldsBuilder(presets.WRITE).Model(&ImageListItem{}).
  56. Only("Image", "Link", "Heading", "Subheading", "Text")
  57. eb.Field("Items").Nested(fb)
  58. }
  59. func ListContentWithImageBody(data *ListContentWithImage, input *pagebuilder.RenderInput) (body HTMLComponent) {
  60. body = ContainerWrapper(
  61. fmt.Sprintf(inflection.Plural(strcase.ToKebab("ListContentWithImage"))+"_%v", data.ID), data.AnchorID, "container-list_content_with_image",
  62. "", "", "",
  63. "", data.AddTopSpace, data.AddBottomSpace, input.IsEditor, input.IsReadonly, "",
  64. Div(
  65. ImageListItemsBody(data.Items),
  66. ).Class("container-wrapper"),
  67. )
  68. return
  69. }
  70. func ImageListItemsBody(items []*ImageListItem) HTMLComponent {
  71. listItemsDiv := Div().Class("container-list_content_with_image-inner")
  72. for _, i := range items {
  73. listItemsDiv.AppendChildren(
  74. Div(
  75. If(i.Link != "", A().Class("container-list_content_with_image-link").Href(i.Link)),
  76. Div().Class("container-list_content_with_image-image").Style(fmt.Sprintf("background-image: url(%s)", i.Image.URL())),
  77. If(i.Heading != "" || i.Subheading != "" || i.Text != "",
  78. Div(
  79. If(i.Heading != "", H3(i.Heading).Class("container-list_content_with_image-heading")),
  80. If(i.Subheading != "", Div(Text(i.Subheading)).Class("container-list_content_with_image-subheading h5")),
  81. If(i.Text != "", P(Text(i.Text)).Class("container-list_content_with_image-text")),
  82. ).Class("container-list_content_with_image-content"),
  83. ),
  84. ).Class("container-list_content_with_image-item"),
  85. )
  86. }
  87. return listItemsDiv
  88. }