html_blocks.py 7.9 KB

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