html_blocks.py 7.8 KB

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