예제 #1
0
class PageLayoutAdvertisementSnippet(Model):
    name = CharField(max_length=100, unique=True, blank=False)
    page_type = CharField(max_length=100, choices=PAGE_CHOICES, default='none')
    placement = CharField(max_length=100,
                          choices=PLACEMENT_CHOICES,
                          default='none')
    code = CharField(max_length=30, blank=True, default='')
    head = StreamField([
        ('html', RawHTMLBlock()),
    ], blank=True)
    body = StreamField([
        ('advertisement', AdvertisementInline()),
        ('html', RawHTMLBlock()),
    ],
                       blank=True)
    live = BooleanField(default=True)
    panels = [
        FieldPanel('name'),
        FieldPanel('code'),
        FieldPanel('page_type'),
        FieldPanel('placement'),
        FieldPanel('live'),
        StreamFieldPanel('head'),
        StreamFieldPanel('body'),
    ]

    def __str__(self):
        return self.name
예제 #2
0
class HomePage(Page):
    # ---- General Page information ------
    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')
    show_searchbar = models.BooleanField(default=True)
    add_whitespace_bottom = models.BooleanField(default=True)

    body_en = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('news', LatestNewsBlock()),
            ('html', RawHTMLBlock(group="Basic")),
        ],
        blank=True,
    )
    body_sv = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('news', LatestNewsBlock()),
            ('html', RawHTMLBlock(group="Basic")),
        ],
        blank=True,
    )
    body = TranslatedField('body_en', 'body_sv')

    banner_panels = [InlinePanel('banners', label=_('Banner'))]

    content_panels_en = Page.content_panels + [
        StreamFieldPanel('body_en'),
    ]

    content_panels_sv = [
        FieldPanel('title_sv', classname="full title"),
        StreamFieldPanel('body_sv'),
    ]

    custom_settings_panel = Page.settings_panels + [
        MultiFieldPanel(
            [
                FieldPanel('show_searchbar'),
                FieldPanel('add_whitespace_bottom')
            ],
            heading='Banner settings',
            classname='utn-extra-margin'
        )
    ]

    edit_handler = TabbedInterface([
        ObjectList(banner_panels, heading=_('Banners')),
        ObjectList(content_panels_en, heading=_('English')),
        ObjectList(content_panels_sv, heading=_('Swedish')),
        ObjectList(Page.promote_panels, heading=_('Promote')),
        ObjectList(custom_settings_panel, heading=_('Settings')),
    ])

    api_fields = [
        APIField('title_sv'),
        APIField('body_en'),
        APIField('body_sv'),
    ]
예제 #3
0
class LessonPage(Page):
    page_type = CharField(max_length=100, choices=PAGE_CHOICES, default='none')
    show_in_sitemap = BooleanField(default=True)
    menu_title = TextField(blank=True)
    is_nav_root = BooleanField(default=False)
    is_selectable = BooleanField(default=True)
    reference_title = TextField(null=True, blank=True)
    subtitle = TextField(null=True, blank=True)
    lesson_number = SmallIntegerField(blank=True, null=True)
    summary = CharField(max_length=100, null=True, blank=True)
    repetition_material = CharField(max_length=100, null=True, blank=True)
    audio_material = CharField(max_length=100, null=True, blank=True)
    comments_for_lesson = StreamField(
        [('advertisement', AdvertisementInline()),
         ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()),
         ('document', DocumentViewerBlock()), ('html', RawHTMLBlock()),
         ('audio', AudioBlock()), ('video', VideoPlayerBlock()),
         ('post', PostBlock())],
        null=True,
        blank=True)
    body = StreamField([
        ('advertisement', AdvertisementInline()),
        ('paragraph', RichTextBlock()),
        ('image', ImageChooserBlock()),
        ('document', DocumentViewerBlock()),
        ('html', RawHTMLBlock()),
        ('audio', AudioBlock()),
        ('video', VideoPlayerBlock()),
        ('post', PostBlock()),
    ],
                       blank=True)
    dictionary = StreamField(
        [('advertisement', AdvertisementInline()),
         ('paragraph', RichTextBlock()), ('image', ImageChooserBlock()),
         ('document', DocumentViewerBlock()), ('html', RawHTMLBlock()),
         ('audio', AudioBlock()), ('video', VideoPlayerBlock()),
         ('translations',
          ListBlock(StructBlock([('word', RichTextBlock(required=True)),
                                 ('translation', RichTextBlock(required=True))
                                 ]),
                    template="blocks/transcriptions.html")),
         ('post', PostBlock())],
        null=True,
        blank=True)
    other_tabs = StreamField([('tab', TabBlock())], blank=True)

    def get_lesson_number(self):
        return self.slug.split("lecon-", 1)[1]

    has_own_topic = BooleanField(default=False)
    topic = OneToOneField(Topic, on_delete=SET_NULL, null=True, blank=True)

    def get_nav_root(self) -> Page:
        return get_nav_root(self)

    class Meta:
        permissions = (('listen_lesson', 'Can listen lesson'), )
예제 #4
0
class WebPage(Page):
    # ---- General Page information ------

    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')

    body_en = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('google_calendar', GoogleCalendarBlock()),
            ('google_drive', GoogleDriveBlock()),
            ('google_form', GoogleFormBlock()),
            ('news', LatestNewsBlock()),
            ('html', RawHTMLBlock(group="Basic")),
            ('eventbrite', EventbriteBlock()),
        ],
        blank=True,
    )
    body_sv = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES +
        [('google_calendar', GoogleCalendarBlock()),
         ('google_drive', GoogleDriveBlock()),
         ('google_form', GoogleFormBlock()), ('news', LatestNewsBlock()),
         ('html', RawHTMLBlock(group="Basic")),
         ('eventbrite', EventbriteBlock())],
        blank=True,
    )
    body = TranslatedField('body_en', 'body_sv')

    content_panels_en = Page.content_panels + [
        StreamFieldPanel('body_en'),
    ]

    content_panels_sv = [
        FieldPanel('title_sv', classname="full title"),
        StreamFieldPanel('body_sv'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels_en, heading=_('English')),
        ObjectList(content_panels_sv, heading=_('Swedish')),
        ObjectList(Page.promote_panels, heading=_('Promote')),
        ObjectList(Page.settings_panels, heading=_('Settings')),
    ])

    api_fields = [
        APIField('title_sv'),
        APIField('body_en'),
        APIField('body_sv'),
    ]
예제 #5
0
class PageWithSidebar(Page):
    page_type = CharField(max_length=100, choices=PAGE_CHOICES, default='none')
    show_in_sitemap = BooleanField(default=True)
    reference_title = TextField(null=True, blank=True)
    subtitle = TextField(null=True, blank=True)
    menu_title = TextField(blank=True)
    is_nav_root = BooleanField(default=False)
    is_selectable = BooleanField(default=True)
    body = StreamField([('advertisement', AdvertisementInline()),
                        ('paragraph', RichTextBlock()),
                        ('image', ImageChooserBlock()),
                        ('document', DocumentViewerBlock()),
                        ('html', RawHTMLBlock()), ('audio', AudioBlock()),
                        ('video', VideoPlayerBlock()), ('tabs', TabsBlock()),
                        ('translations',
                         ListBlock(StructBlock(
                             [('word', RichTextBlock(required=True)),
                              ('translation', RichTextBlock(required=True))]),
                                   template="blocks/transcriptions.html")),
                        ('post', PostBlock()),
                        ('choosen_reviews', ChoosenReviews())],
                       blank=True)

    def get_nav_root(self) -> Page:
        return get_nav_root(self)
예제 #6
0
class BlogPage(Page):
    date = models.DateField('Post date')
    intro = models.CharField(max_length=250)

    content = StreamField([
        ("rich_text", RichTextBlock(template="home/blocks/rich_text.html")),
        ("image", ImageChooserBlock()),
        ("embed", EmbedBlock()),
        ("raw_html", RawHTMLBlock()),
        ("columns", ColumnBlock()),
        ("mathjax", MathjaxBlock()),
        ('code', CodeBlock())
    ])

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('content')
    ]

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        MultiFieldPanel([InlinePanel("authors", min_num=1)], heading="Auteurs"),
        FieldPanel('intro'),
        StreamFieldPanel('content')
    ]
예제 #7
0
class FooterText(models.Model):
    """
    This provides editable text for the site footer. Again it uses the decorator
    `register_snippet` to allow it to be accessible via the admin. It is made
    accessible on the template via a template tag defined in base/templatetags/
    navigation_tags.py
    """
    text = StreamField([
        (
            'html',
            RawHTMLBlock(),
        ),
    ],
                       verbose_name="Add Snippet",
                       null=True)

    panels = [
        StreamFieldPanel('text'),
    ]

    def __str__(self):
        return "Footer"

    class Meta:
        verbose_name = 'Footer'
예제 #8
0
class StreamPage(Page):
    body = StreamField([
        ("text", CharBlock()),
        ("rich_text", RichTextBlock()),
        ("image", ExtendedImageChooserBlock()),
        (
            "product",
            StructBlock([
                ("name", CharBlock()),
                ("price", CharBlock()),
            ]),
        ),
        ("raw_html", RawHTMLBlock()),
        (
            "books",
            StreamBlock([
                ("title", CharBlock()),
                ("author", CharBlock()),
            ]),
        ),
    ])

    api_fields = ("body", )

    content_panels = [
        FieldPanel("title"),
        FieldPanel("body"),
    ]

    preview_modes = []
예제 #9
0
class HomePage(Page):
    content = StreamField([
        ('Image', ImageChooserBlock()),
        ('raw_html', RawHTMLBlock()),
        ('paragraph', RichTextBlock()),
        ('block_quote', WagQuoteBlock()),
        ('two_column_block', TwoColumnBlock()),
        ('four_column_block', FourColumnBlock()),
    ],
                          blank=True,
                          null=True)

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                InlinePanel(
                    'carousel_images', max_num=5, min_num=1, label='Image'),
            ],
            heading='Carousel Image',
        ),
        StreamFieldPanel('content'),
    ]

    class Meta:  # noqa

        verbose_name = 'Home Page'
예제 #10
0
파일: models.py 프로젝트: sfikrakow/www
class StaticPage(SFIPage):
    content = StreamField([
        ('agenda', AgendaBlock()),
        ('paragraph', blocks.RichTextBlock()),
        ('image', ImageChooserBlock()),
        ('post_index', PostIndexBlock()),
        ('event_index', EventIndexBlock()),
        ('event_schedule', EventScheduleBlock()),
        ('header', HeadingBlock()),
        ('section_title', SectionTitleBlock()),
        ('section_subtitle', SectionSubtitleBlock()),
        ('section_divider', SectionDividerBlock()),
        ('dropdown', DropdownBlock()),
        ('photo_gallery', PhotoGallery()),
        ('photo_slider', PhotoSlider()),
        ('map', MapBlock()),
        ('raw_html', RawHTMLBlock()),
    ],
                          null=True,
                          blank=True,
                          verbose_name=_('content'))

    content_panels = SFIPage.content_panels + [
        StreamFieldPanel('content'),
    ]

    class Meta:
        verbose_name = _('page')
        verbose_name_plural = _('pages')
예제 #11
0
class HomePage(Page, MeetupMixin, SponsorMixin):
    subpage_types = [
        "HomePage",
        "SimplePage",
        "speakers.SpeakersPage",
        "speakers.TalksPage",
    ]

    body = StreamField([
        ("heading", blocks.CharBlock(icon="home", classname="full title")),
        ("paragraph", blocks.RichTextBlock(icon="edit")),
        ("video", EmbedBlock(icon="media")),
        ("image", ImageChooserBlock(icon="image")),
        ("slide", EmbedBlock(icon="media")),
        ("html", RawHTMLBlock(icon="code")),
    ])

    sponsors = models.ManyToManyField(Sponsor,
                                      through=HomePageSponsorRelationship,
                                      blank=True)

    def __str__(self):
        return self.title

    content_panels = Page.content_panels + [
        StreamFieldPanel("body"),
    ]

    settings_panels = (
        Page.settings_panels + MeetupMixin.settings_panels +
        SponsorMixin.settings_panels +
        [InlinePanel("homepage_segments", label="Homepage Segment")])
예제 #12
0
class CoreBlocks(StreamBlock):
    action_link = ActionLinkBlock(group='Base')
    care_card = CareCardBlock(group='Base')
    details = DetailsBlock(group='Base')
    do_list = DoBlock(group='Base')
    dont_list = DontBlock(group='Base')
    expander = ExpanderBlock(group='Base')
    expander_group = ExpanderGroupBlock(group='Base')
    inset_text = InsetTextBlock(group='Base')
    image = ImageBlock(group='Base')
    panel = PanelBlock(group='Base')
    panel_list = PanelListBlock(group='Base')
    # panel_with_image = PanelBlockWithImage(group='Base')
    grey_panel = GreyPanelBlock(group='Base')
    warning_callout = WarningCalloutBlock(group='Base')
    summary_list = SummaryListBlock(group='Base')
    promo = PromoBlock(group='Base')
    promo_group = PromoGroupBlock(group='Base')

    recent_posts = RecentPostsBlock(group='Custom')
    text = RichTextBlock(group='Custom',
                         help_text="""
            Use this block to add formatted text into a page e.g. 
            paragraph with heading and/or links and images
        """,
                         template='blocks/text_block.html',
                         features=RICHTEXT_FEATURES_ALL)
    html = RawHTMLBlock(
        group='custom',
        help_text="""
            Use this block to add raw html
        """,
        template='blocks/html_block.html',
    )
예제 #13
0
class StreamPage(Page):
    body = StreamField([
        ('text', CharBlock()),
        ('rich_text', RichTextBlock()),
        ('image', ExtendedImageChooserBlock()),
        ('product',
         StructBlock([
             ('name', CharBlock()),
             ('price', CharBlock()),
         ])),
        ('raw_html', RawHTMLBlock()),
        ('books',
         StreamBlock([
             ('title', CharBlock()),
             ('author', CharBlock()),
         ])),
    ])

    api_fields = ('body', )

    content_panels = [
        FieldPanel('title'),
        StreamFieldPanel('body'),
    ]

    preview_modes = []
예제 #14
0
파일: models.py 프로젝트: al-bezd/pdf2tiff
class SimplePage(Page):
    keywords = models.TextField(
        blank=True,
        null=True,
        verbose_name=_('keywords'),
        help_text=_("Ключевые слова для индексации поисковыми роботами"))

    class Meta:
        verbose_name = 'Обычная страница'
        verbose_name_plural = 'Обычная страница'

    body = StreamField([
        ('Heading', blocks.CharBlock(form_classname="full title")),
        ('Text', RichTextBlock()),
        ('img', ImageChooserBlock()),
        ('HTML', RawHTMLBlock()),
        ('docs', DocumentChooserBlock()),
    ])

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
    ]

    PAGE_TEMPLATE_VAR = 'page'

    #promote_panels = set_promote_panels()

    def save(self, *args, **kwargs):
        #self.slug = slugify(self.title)
        super().save(*args, **kwargs)
예제 #15
0
class ArticlePage(Page):
    page_type = CharField(max_length=100,
                          choices=PAGE_CHOICES,
                          default='article_page')
    show_in_sitemap = BooleanField(default=True)
    allow_comments = BooleanField('allow comments', default=True)
    menu_title = TextField(blank=True)
    is_nav_root = BooleanField(default=False)
    is_selectable = BooleanField(default=True)
    reference_title = TextField(null=True, blank=True)
    subtitle = TextField(null=True, blank=True)
    body = StreamField([
        ('advertisement', AdvertisementInline()),
        ('paragraph', RichTextBlock()),
        ('image', ImageChooserBlock()),
        ('document', DocumentViewerBlock()),
        ('html', RawHTMLBlock()),
        ('audio', AudioBlock()),
        ('video', VideoPlayerBlock()),
    ],
                       blank=True)

    def get_absolute_url(self):
        return self.full_url

    def get_nav_root(self) -> Page:
        return get_nav_root(self)
예제 #16
0
class ContentRawHTML(StructBlock):
    html = RawHTMLBlock()

    class Meta:
        label = 'Raw HTML'
        icon = 'fa-code'
        template = 'core/blocks/raw_html_block.html'
예제 #17
0
class ResponsiveVideoIframeBlock(StructBlock):
    iframe_embed = RawHTMLBlock(
        help_text=_('Currently only youtube/vimeo embeds can be responsive'))

    class Meta:
        icon = "media"
        template = 'pages/blocks/responsive_video_iframe_block.html'
        label = _('Responsive Video iFrame')
예제 #18
0
class EmbedHTML(RawHTMLBlock):
    html = RawHTMLBlock(
        "Embed code or raw HTML",
        help_text='Use this sparingly, if possible.',
    )

    class Meta:
        template = "categories/blocks/embed.html"
class D3Block(StructBlock):
    html = RawHTMLBlock(required=False)
    css = RawHTMLBlock(required=False)
    js = RawHTMLBlock(required=False)
    additional_files = RawHTMLBlock(required=False,
                                    verbose_name="Additional JS\
                                    files to load.")

    class Meta:
        help_text = '''
        Enter the relevent sections.
        You don't need to add script or style tags.
        IMPORTANT: Please verify with KDL before publishing.
        Additional files should be added one file per line.
        Note: Do not include d3
        itself.'''
        template = 'cms/blocks/d3_block.html'
예제 #20
0
class DocumentEmbedBlock(StructBlock):
    title = RichTextBlock(required=False)
    html = RawHTMLBlock()

    class Meta:
        icon = 'doc'
        template = 'blocks/document_embed_block.html'
        help_text = 'Choose or upload a document'
예제 #21
0
class StandardBlock(StreamBlock):
    heading = CharBlock(icon="title")
    paragraph = RichTextBlock(icon="pilcrow")
    image = ImageChooserBlock(icon="image",
                              template='includes/imageblock.html')
    embed = EmbedBlock(icon="code")
    raw_html = RawHTMLBlock(icon="placeholder")
    table = TableBlock(table_options={'renderer': 'html'})
예제 #22
0
class ProducerPage(RoutablePageMixin, PortalPage):
    subtitle = models.CharField(max_length=255,
                                default='Producer Profile',
                                help_text="Page header subtitle")
    bottom_blurb = StreamField([
        ('image', ImageChooserBlock()),
        ('text',
         RichTextBlock(blank=True,
                       features=[
                           'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol',
                           'ul', 'hr', 'superscript', 'subscript',
                           'strikethrough', 'blockquote', 'image', 'embed'
                       ])),
        ('google_form',
         LinkBlock(
             label="Google Form Link",
             template="cms/google_form.html",
             help_text=
             "The URL for the Google form. This will be loaded into a popup when clicked."
         )),
        ('HTML',
         RawHTMLBlock(
             label="Custom HTML",
             help_text="For fine-tuning very specific/custom blocks.")),
        ('Embedded_Media', EmbedBlock(label="Embedded Media"))
    ],
                               min_num=0,
                               blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('subtitle', classname="full"),
        FieldPanel('bottom_blurb', classname="full"),
    ]

    @route(r'^$')  # will override the default Page serving mechanism
    @route(r'^(\d+)/$')
    def producer(self, request, id=None):
        """
        View function for the producer page
        """
        if id:
            try:
                provider = Provider.objects.get(pk=id)
            except Exception as e:
                pass
        if not id:
            provider = Provider.objects.all()[0]

        # NOTE: We can use the RoutablePageMixin.render() method to render
        # the page as normal, but with some of the context values overridden
        return self.render(request, context_overrides={
            'provider': provider,
        })

    def get_context(self, request):
        context = super().get_context(request)
        return context
예제 #23
0
class AlignedHTMLBlock(StructBlock):
    """A block which allows for raw HTML entry and alignment."""

    html = RawHTMLBlock()
    alignment = HTMLAlignmentChoiceBlock()

    class Meta(object):
        """Meta data for the class."""

        icon = "code"
예제 #24
0
class TeamPage(Page):
    body = StreamField([
        ('team', TeamBlock()),
        ('raw_html', RawHTMLBlock()),
    ],
                       default='')

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
    ]
예제 #25
0
class ContentPage(PortalPage):
    back_button = models.BooleanField(
        default=False,
        verbose_name="Show back button",
        help_text="Check to show a 'Back' button at the top of the page")
    back_button_text = models.CharField(max_length=255, default='Back')
    subtitle = models.CharField(
        max_length=255,
        null=True,
        blank=True,
        default=None,
        help_text="[Optional] White label under site header")
    header_blurb = RichTextField(
        null=True,
        blank=True,
        default=None,
        help_text="[Optional] Additional content in header")

    content_title = RichTextField(null=True, blank=True, default='Page Title')
    content = StreamField([
        ('image', ImageChooserBlock()),
        ('text',
         RichTextBlock(null=True,
                       blank=True,
                       features=[
                           'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol',
                           'ul', 'hr', 'superscript', 'subscript',
                           'strikethrough', 'blockquote', 'image', 'embed'
                       ])),
        ('google_form',
         LinkBlock(
             label="Google Form Link",
             template="cms/google_form.html",
             help_text=
             "The URL for the Google form. This will be loaded into a popup when clicked."
         )),
        ('HTML',
         RawHTMLBlock(
             label="Custom HTML",
             help_text="For fine-tuning very specific/custom blocks.")),
        ('Embedded_Media', EmbedBlock(label="Embedded Media"))
    ])

    content_panels = Page.content_panels + [
        FieldPanel('back_button'),
        FieldPanel('back_button_text', classname="full"),
        FieldPanel('subtitle', classname="full"),
        FieldPanel('header_blurb', classname="full"),
        FieldPanel('content_title', classname="full"),
        FieldPanel('content', classname="full"),
    ]

    def get_context(self, request):
        context = super().get_context(request)
        return context
예제 #26
0
class WebFeedBlock(blocks.StructBlock):
    """Code block for social media feeds."""

    webfeed_title = blocks.CharBlock(required=False,
                                     help_text="Title for callout section")
    webfeed_code = RawHTMLBlock(required=False)

    class Meta:  # noqa
        template = "streams/webfeed_block.html"
        icon = "code"
        label = "Web Feed Block"
예제 #27
0
class ColumnBlock(StructBlock):
    class Meta:
        icon = "doc-full"
        label = "Columns"
        template = "columns/block.html"

    columns = StreamBlock([
        ("paragraph", RichTextBlock(template="columns/column_rich_text.html")),
        ("image", ImageChooserBlock()), ("embed", EmbedBlock()),
        ("raw_html", RawHTMLBlock())
    ])
예제 #28
0
class ParagraphWithRawEmbedBlock(blocks.StructBlock):
    embed = RawHTMLBlock(help_text="Embed HTML code(an iframe)")
    embed_caption = RichTextMiniBlock(required=False)
    embed_align = blocks.ChoiceBlock(choices=ALIGNMENT_CHOICES,
                                     default=ALIGNMENT_CHOICES[0][0])
    content = PargraphBlockWithOptionalContent(required=False)

    class Meta:
        icon = 'media'
        label = 'Raw embed with text'
        template = 'article/blocks/paragraph_with_raw_embed.html'
예제 #29
0
class SinglePage(Page):
    author = models.CharField(max_length=255)
    date = models.DateField("Post date")
    body = StreamField([
        ('rawHtml', RawHTMLBlock()),
    ])

    content_panels = Page.content_panels + [
        FieldPanel('author'),
        FieldPanel('date'),
        StreamFieldPanel('body'),
    ]
예제 #30
0
class StoryBlock(StreamBlock):
    h2 = CharBlock(
        form_classname="title",
        icon="title",
        template="patterns/molecules/streamfield/blocks/heading2_block.html",
    )
    h3 = CharBlock(
        form_classname="title",
        icon="title",
        template="patterns/molecules/streamfield/blocks/heading3_block.html",
    )
    h4 = CharBlock(
        form_classname="title",
        icon="title",
        template="patterns/molecules/streamfield/blocks/heading4_block.html",
    )
    intro = RichTextBlock(
        icon="pilcrow",
        template="patterns/molecules/streamfield/blocks/intro_block.html",
    )
    paragraph = RichTextBlock(
        icon="pilcrow",
        template="patterns/molecules/streamfield/blocks/paragraph_block.html",
    )
    aligned_image = ImageBlock(
        label="Aligned image",
        template=
        "patterns/molecules/streamfield/blocks/aligned_image_block.html",
    )
    wide_image = WideImage(
        label="Wide image",
        template="patterns/molecules/streamfield/blocks/wide_image_block.html",
    )
    bustout = BustoutBlock(
        template="patterns/molecules/streamfield/blocks/bustout_block.html")
    pullquote = PullQuoteBlock(
        template="patterns/molecules/streamfield/blocks/pullquote_block.html")
    raw_html = RawHTMLBlock(
        label="Raw HTML",
        icon="code",
        template="patterns/molecules/streamfield/blocks/raw_html_block.html",
    )
    embed = EmbedBlock(
        icon="code",
        template="patterns/molecules/streamfield/blocks/embed_block.html",
    )
    markdown = MarkdownBlock(
        icon="code",
        template="patterns/molecules/streamfield/blocks/markdown_block.html",
    )

    class Meta:
        template = "patterns/molecules/streamfield/stream_block.html"