html_blocks.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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 ugettext_lazy as _
  10. from wagtail.contrib.table_block.blocks import TableBlock as WagtailTableBlock
  11. from wagtail.core 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 = 'fa-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 = 'coderedcms/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. place_id = blocks.CharBlock(
  61. required=False,
  62. max_length=255,
  63. label=_('Google place ID'),
  64. help_text=_('Requires API key to use place ID.')
  65. )
  66. map_zoom_level = blocks.IntegerBlock(
  67. required=False,
  68. default=14,
  69. label=_('Map zoom level'),
  70. help_text=_(
  71. '''
  72. Requires API key to use zoom. 1: World, 5: Landmass/continent,
  73. 10: City, 15: Streets, 20: Buildings
  74. '''
  75. )
  76. )
  77. class Meta:
  78. template = 'coderedcms/blocks/google_map.html'
  79. icon = 'fa-map'
  80. label = _('Google Map')
  81. class EmbedVideoBlock(BaseBlock):
  82. """
  83. Emedded media using stock wagtail functionality.
  84. """
  85. url = EmbedBlock(
  86. required=True,
  87. label=_('URL'),
  88. help_text=_('Link to a YouTube/Vimeo video, tweet, facebook post, etc.')
  89. )
  90. class Meta:
  91. template = 'coderedcms/blocks/embed_video_block.html'
  92. icon = 'media'
  93. label = _('Embed Media')
  94. class H1Block(BaseBlock):
  95. """
  96. An <h1> heading.
  97. """
  98. text = blocks.CharBlock(
  99. max_length=255,
  100. label=_('Text'),
  101. )
  102. class Meta:
  103. template = 'coderedcms/blocks/h1_block.html'
  104. icon = 'fa-header'
  105. label = _('Heading 1')
  106. class H2Block(BaseBlock):
  107. """
  108. An <h2> heading.
  109. """
  110. text = blocks.CharBlock(
  111. max_length=255,
  112. label=_('Text'),
  113. )
  114. class Meta:
  115. template = 'coderedcms/blocks/h2_block.html'
  116. icon = 'fa-header'
  117. label = _('Heading 2')
  118. class H3Block(BaseBlock):
  119. """
  120. An <h3> heading.
  121. """
  122. text = blocks.CharBlock(
  123. max_length=255,
  124. label=_('Text'),
  125. )
  126. class Meta:
  127. template = 'coderedcms/blocks/h3_block.html'
  128. icon = 'fa-header'
  129. label = _('Heading 3')
  130. class TableBlock(BaseBlock):
  131. table = WagtailTableBlock()
  132. class Meta:
  133. template = 'coderedcms/blocks/table_block.html'
  134. icon = 'fa-table'
  135. label = 'Table'
  136. class ImageBlock(BaseBlock):
  137. """
  138. An <img>, by default styled responsively to fill its container.
  139. """
  140. image = ImageChooserBlock(
  141. label=_('Image'),
  142. )
  143. class Meta:
  144. template = 'coderedcms/blocks/image_block.html'
  145. icon = 'image'
  146. label = _('Image')
  147. class ImageLinkBlock(BaseLinkBlock):
  148. """
  149. An <a> with an image inside it, instead of text.
  150. """
  151. image = ImageChooserBlock(
  152. label=_('Image'),
  153. )
  154. alt_text = blocks.CharBlock(
  155. max_length=255,
  156. required=True,
  157. help_text=_('Alternate text to show if the image doesn’t load'),
  158. )
  159. class Meta:
  160. template = 'coderedcms/blocks/image_link_block.html'
  161. icon = 'image'
  162. label = _('Image Link')
  163. value_class = LinkStructValue
  164. class PageListBlock(BaseBlock):
  165. """
  166. Renders a preview of selected pages.
  167. """
  168. indexed_by = blocks.PageChooserBlock(
  169. required=True,
  170. label=_('Parent page'),
  171. help_text=_(
  172. '''
  173. Show a preview of pages that are children of the selected page.
  174. Uses ordering specified in the page’s LAYOUT tab.
  175. '''
  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 = 'coderedcms/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:
  207. # `pages` is not a queryset, or is not a queryset of CoderedPage.
  208. logger.warning(
  209. '''
  210. Tried to filter by ClassifierTerm in PageListBlock, but <%s.%s ('%s')>.get_index_children()
  211. did not return a queryset or is not a queryset of CoderedPage models.
  212. ''',
  213. indexer._meta.app_label, indexer.__class__.__name__, indexer.title
  214. )
  215. else:
  216. pages = indexer.get_children().live()
  217. context['pages'] = pages[:value['num_posts']]
  218. return context
  219. class PagePreviewBlock(BaseBlock):
  220. """
  221. Renders a preview of a specific page.
  222. """
  223. page = blocks.PageChooserBlock(
  224. required=True,
  225. label=_('Page to preview'),
  226. help_text=_('Show a mini preview of the selected page.'),
  227. )
  228. class Meta:
  229. template = 'coderedcms/blocks/pagepreview_block.html'
  230. icon = 'doc-empty-inverse'
  231. label = _('Page Preview')
  232. class QuoteBlock(BaseBlock):
  233. """
  234. A <blockquote>.
  235. """
  236. text = blocks.TextBlock(
  237. required=True,
  238. rows=4,
  239. label=_('Quote Text'),
  240. )
  241. author = blocks.CharBlock(
  242. required=False,
  243. max_length=255,
  244. label=_('Author'),
  245. )
  246. class Meta:
  247. template = 'coderedcms/blocks/quote_block.html'
  248. icon = 'openquote'
  249. label = _('Quote')
  250. class RichTextBlock(blocks.RichTextBlock):
  251. class Meta:
  252. template = 'coderedcms/blocks/rich_text_block.html'