html_blocks.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. """
  2. HTML blocks are simple blocks used to represent common HTML elements,
  3. with additional styling and attributes.
  4. HTML blocks should NOT contain more sub-blocks or sub-streamfields.
  5. They must be safe to nest within more robust "content blocks" without
  6. creating recursion.
  7. """
  8. import logging
  9. from django.utils.translation import gettext_lazy as _
  10. from wagtail import blocks
  11. from wagtail.contrib.table_block.blocks import TableBlock as WagtailTableBlock
  12. from wagtail.documents.blocks import DocumentChooserBlock
  13. from wagtail.embeds.blocks import EmbedBlock
  14. from wagtail.images.blocks import ImageChooserBlock
  15. from .base_blocks import BaseBlock
  16. from .base_blocks import BaseLinkBlock
  17. from .base_blocks import ButtonMixin
  18. from .base_blocks import ClassifierTermChooserBlock
  19. from .base_blocks import CoderedAdvTrackingSettings
  20. from .base_blocks import LinkStructValue
  21. logger = logging.getLogger("coderedcms")
  22. class ButtonBlock(ButtonMixin, BaseLinkBlock):
  23. """
  24. A link styled as a button.
  25. """
  26. class Meta:
  27. template = "coderedcms/blocks/button_block.html"
  28. icon = "cr-hand-pointer-o"
  29. label = _("Button Link")
  30. value_class = LinkStructValue
  31. class DownloadBlock(ButtonMixin, BaseBlock):
  32. """
  33. Link to a file that can be downloaded.
  34. """
  35. downloadable_file = DocumentChooserBlock(
  36. required=False,
  37. label=_("Document link"),
  38. )
  39. advsettings_class = CoderedAdvTrackingSettings
  40. class Meta:
  41. template = "coderedcms/blocks/download_block.html"
  42. icon = "download"
  43. label = _("Download")
  44. class EmbedGoogleMapBlock(BaseBlock):
  45. """
  46. An embedded Google map in an <iframe>.
  47. """
  48. search = blocks.CharBlock(
  49. required=False,
  50. max_length=255,
  51. label=_("Search query"),
  52. help_text=_(
  53. "Address or search term used to find your location on the map."
  54. ),
  55. )
  56. map_title = blocks.CharBlock(
  57. required=False,
  58. max_length=255,
  59. label=_("Map title"),
  60. help_text=_('Map title for screen readers, ex: "Map to Goodale Park"'),
  61. )
  62. place_id = blocks.CharBlock(
  63. required=False,
  64. max_length=255,
  65. label=_("Google place ID"),
  66. help_text=_("Requires API key to use place ID."),
  67. )
  68. map_zoom_level = blocks.IntegerBlock(
  69. required=False,
  70. default=14,
  71. label=_("Map zoom level"),
  72. help_text=_(
  73. "Requires API key to use zoom. "
  74. "1: World, 5: Landmass/continent, 10: City, 15: Streets, 20: Buildings"
  75. ),
  76. )
  77. class Meta:
  78. template = "coderedcms/blocks/google_map.html"
  79. icon = "cr-map"
  80. label = _("Google Map")
  81. class EmbedVideoBlock(BaseBlock):
  82. """
  83. Embedded media using stock wagtail functionality.
  84. """
  85. url = EmbedBlock(
  86. required=True,
  87. label=_("URL"),
  88. help_text=_(
  89. "Link to a YouTube/Vimeo video, tweet, facebook post, etc."
  90. ),
  91. )
  92. class Meta:
  93. template = "coderedcms/blocks/embed_video_block.html"
  94. icon = "media"
  95. label = _("Embed Media")
  96. class H1Block(BaseBlock):
  97. """
  98. An <h1> heading.
  99. """
  100. text = blocks.CharBlock(
  101. max_length=255,
  102. label=_("Text"),
  103. )
  104. class Meta:
  105. template = "coderedcms/blocks/h1_block.html"
  106. icon = "cr-header"
  107. label = _("Heading 1")
  108. class H2Block(BaseBlock):
  109. """
  110. An <h2> heading.
  111. """
  112. text = blocks.CharBlock(
  113. max_length=255,
  114. label=_("Text"),
  115. )
  116. class Meta:
  117. template = "coderedcms/blocks/h2_block.html"
  118. icon = "cr-header"
  119. label = _("Heading 2")
  120. class H3Block(BaseBlock):
  121. """
  122. An <h3> heading.
  123. """
  124. text = blocks.CharBlock(
  125. max_length=255,
  126. label=_("Text"),
  127. )
  128. class Meta:
  129. template = "coderedcms/blocks/h3_block.html"
  130. icon = "cr-header"
  131. label = _("Heading 3")
  132. class TableBlock(BaseBlock):
  133. table = WagtailTableBlock()
  134. class Meta:
  135. template = "coderedcms/blocks/table_block.html"
  136. icon = "table"
  137. label = "Table"
  138. class ImageBlock(BaseBlock):
  139. """
  140. An <img>, by default styled responsively to fill its container.
  141. """
  142. image = ImageChooserBlock(
  143. label=_("Image"),
  144. )
  145. class Meta:
  146. template = "coderedcms/blocks/image_block.html"
  147. icon = "image"
  148. label = _("Image")
  149. class ImageLinkBlock(BaseLinkBlock):
  150. """
  151. An <a> with an image inside it, instead of text.
  152. """
  153. image = ImageChooserBlock(
  154. label=_("Image"),
  155. )
  156. alt_text = blocks.CharBlock(
  157. max_length=255,
  158. required=True,
  159. help_text=_("Alternate text to show if the image doesn’t load"),
  160. )
  161. class Meta:
  162. template = "coderedcms/blocks/image_link_block.html"
  163. icon = "image"
  164. label = _("Image Link")
  165. value_class = LinkStructValue
  166. class PageListBlock(BaseBlock):
  167. """
  168. Renders a preview of selected pages.
  169. """
  170. indexed_by = blocks.PageChooserBlock(
  171. required=True,
  172. label=_("Parent page"),
  173. help_text=_(
  174. "Show a preview of pages that are children of the selected page. "
  175. "Uses ordering specified in the page’s LAYOUT tab."
  176. ),
  177. )
  178. classified_by = ClassifierTermChooserBlock(
  179. required=False,
  180. label=_("Classified as"),
  181. help_text=_("Only show pages that are classified with this term."),
  182. )
  183. # DEPRECATED: Remove in 3.0
  184. show_preview = blocks.BooleanBlock(
  185. required=False,
  186. default=False,
  187. label=_("Show body preview"),
  188. )
  189. num_posts = blocks.IntegerBlock(
  190. default=3,
  191. label=_("Number of pages to show"),
  192. )
  193. class Meta:
  194. template = "coderedcms/blocks/pagelist_block.html"
  195. icon = "list-ul"
  196. label = _("Latest Pages")
  197. def get_context(self, value, parent_context=None):
  198. context = super().get_context(value, parent_context=parent_context)
  199. indexer = value["indexed_by"].specific
  200. # try to use the CoderedPage `get_index_children()`,
  201. # but fall back to get_children if this is a non-CoderedPage
  202. if hasattr(indexer, "get_index_children"):
  203. pages = indexer.get_index_children()
  204. if value["classified_by"]:
  205. try:
  206. pages = pages.filter(
  207. classifier_terms=value["classified_by"]
  208. )
  209. except AttributeError:
  210. # `pages` is not a queryset, or is not a queryset of CoderedPage.
  211. logger.warning(
  212. (
  213. "Tried to filter by ClassifierTerm in PageListBlock, "
  214. "but <%s.%s ('%s')>.get_index_children() "
  215. "did not return a queryset or is not a queryset of "
  216. "CoderedPage models."
  217. ),
  218. indexer._meta.app_label,
  219. indexer.__class__.__name__,
  220. indexer.title,
  221. )
  222. else:
  223. pages = indexer.get_children().live()
  224. context["pages"] = pages[: value["num_posts"]]
  225. return context
  226. class PagePreviewBlock(BaseBlock):
  227. """
  228. Renders a preview of a specific page.
  229. """
  230. page = blocks.PageChooserBlock(
  231. required=True,
  232. label=_("Page to preview"),
  233. help_text=_("Show a mini preview of the selected page."),
  234. )
  235. class Meta:
  236. template = "coderedcms/blocks/pagepreview_block.html"
  237. icon = "doc-empty-inverse"
  238. label = _("Page Preview")
  239. class QuoteBlock(BaseBlock):
  240. """
  241. A <blockquote>.
  242. """
  243. text = blocks.TextBlock(
  244. required=True,
  245. rows=4,
  246. label=_("Quote Text"),
  247. )
  248. author = blocks.CharBlock(
  249. required=False,
  250. max_length=255,
  251. label=_("Author"),
  252. )
  253. class Meta:
  254. template = "coderedcms/blocks/quote_block.html"
  255. icon = "openquote"
  256. label = _("Quote")
  257. class RichTextBlock(blocks.RichTextBlock):
  258. class Meta:
  259. template = "coderedcms/blocks/rich_text_block.html"