def test_complex_form_fields(self):
        TestBlock = StreamBlock([
            ('h2', CharBlock()),
            ('h3', CharBlock()),
            ('p', RichTextBlock()),
            ('singlelinefield', SingleLineFormFieldBlock()),
            ('multilinefield', MultiLineFormFieldBlock()),
            ('emailfield', EmailFormFieldBlock()),
            ('numberfield', NumberFormFieldBlock()),
            ('urlfield', UrlFormFieldBlock()),
            ('checkboxfield', CheckboxFormFieldBlock()),
            ('dropdownfield', DropdownFormFieldBlock()),
            ('radiofield', RadioFormFieldBlock()),
            ('datefield', DateFormFieldBlock()),
            ('datetimefield', DateTimeFormFieldBlock()),
        ])

        value = TestBlock.to_python(
            json.loads('''\
[{
    "value": {
        "choices": [{
            "description": "Black",
            "key": "black"
        }, {
            "description": "Blue",
            "key": "blue"
        }, {
            "description": "Green",
            "key": "green"
        }, {
            "description": "Orange",
            "key": "orange"
        }, {
            "description": "Red",
            "key": "red"
        }, {
            "description": "White",
            "key": "white"
        }, {
            "description": "Yellow",
            "key": "yellow"
        }],
        "label": "What is your favorite color?",
        "required": true,
        "allow_multiple_selections": false,
        "help_text": "Choose your favorite color from the list below."
    },
    "type": "dropdownfield"
}, {
    "value": {
        "label": "What animal comes to mind when you think of your favorite color?",
        "default_value": "",
        "required": true,
        "help_text": "Don't think really hard. First animal that comes to mind."
    },
    "type": "singlelinefield"
}, {
    "value": {
        "label": "Why is this your favorite color?",
        "default_value": "",
        "required": false,
        "help_text": "Give us two to three sentences that describe why you like this color."
    },
    "type": "multilinefield"
}, {
    "value": {
        "choices": [{
            "description": "Female",
            "key": "female"
        }, {
            "description": "Male",
            "key": "male"
        }],
        "label": "Gender",
        "required": false,
        "help_text": "Are you male or female?"
    },
    "type": "radiofield"
}, {
    "value": {
        "label": "When is your birthday.",
        "required": false,
        "help_text": "This helps us correlate favorite colors by birth month."
    },
    "type": "datefield"
}, {
    "value": {
        "label": "Can we share your answers?",
        "default_checked": true,
        "required": false,
        "help_text": "If you check this box we will share your responses anonymously with everyone that comes to our website."
    },
    "type": "checkboxfield"
}]'''))

        finder = FormFieldFinder()

        fields = finder.find_form_fields(TestBlock, value)

        self.assertEqual(len(fields), 6)
        self.assertIsInstance(fields[0].block, DropdownFormFieldBlock)
        self.assertIsInstance(fields[1].block, SingleLineFormFieldBlock)
        self.assertIsInstance(fields[2].block, MultiLineFormFieldBlock)
        self.assertIsInstance(fields[3].block, RadioFormFieldBlock)
        self.assertIsInstance(fields[4].block, DateFormFieldBlock)
        self.assertIsInstance(fields[5].block, CheckboxFormFieldBlock)

        self.assertEqual(fields[0].value["label"],
                         'What is your favorite color?')
        self.assertEqual(
            fields[1].value["label"],
            'What animal comes to mind when you think of your favorite color?')
        self.assertEqual(fields[2].value["label"],
                         'Why is this your favorite color?')
        self.assertEqual(fields[3].value["label"], 'Gender')
        self.assertEqual(fields[4].value["label"], 'When is your birthday.')
        self.assertEqual(fields[5].value["label"],
                         'Can we share your answers?')
Beispiel #2
0
class ProjectPage(
    ArchiveablePageAbstract,
    BasicPageAbstract,
    ContentPage,
    FeatureablePageAbstract,
    ShareablePageAbstract,
    ThemeablePageAbstract,
):
    body = StreamField(
        BasicPageAbstract.body_default_blocks + [
            BasicPageAbstract.body_poster_block,
            BasicPageAbstract.body_recommended_block,
            BasicPageAbstract.body_text_border_block,
        ],
        blank=True,
    )
    image_banner = models.ForeignKey(
        'images.CigionlineImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Banner Image',
    )
    project_contacts = StreamField(
        [
            ('contact', PageChooserBlock(required=True, page_type='people.PersonPage')),
        ],
        blank=True,
    )
    project_leads = StreamField(
        [
            ('project_lead', PageChooserBlock(required=True, page_type='people.PersonPage')),
            ('external_project_lead', CharBlock(required=True)),
        ],
        blank=True,
    )
    project_members = StreamField(
        [
            ('project_member', PageChooserBlock(required=True, page_type='people.PersonPage')),
            ('external_project_member', CharBlock(required=True)),
        ],
        blank=True,
    )
    project_types = ParentalManyToManyField('research.ProjectType', blank=True)
    related_files = StreamField(
        [
            ('file', DocumentChooserBlock()),
        ],
        blank=True,
    )

    # Reference field for the Drupal-Wagtail migrator. Can be removed after.
    drupal_node_id = models.IntegerField(blank=True, null=True)

    content_panels = [
        BasicPageAbstract.title_panel,
        BasicPageAbstract.body_panel,
        MultiFieldPanel(
            [
                FieldPanel('publishing_date'),
                FieldPanel('project_types'),
            ],
            heading='General Information',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                StreamFieldPanel('project_leads'),
                StreamFieldPanel('project_members'),
                StreamFieldPanel('project_contacts'),
            ],
            heading='People',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                ImageChooserPanel('image_hero'),
                ImageChooserPanel('image_banner'),
            ],
            heading='Images',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                FieldPanel('topics'),
                StreamFieldPanel('related_files'),
            ],
            heading='Related',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                InlinePanel(
                    'featured_pages',
                    max_num=9,
                    min_num=0,
                    label='Page',
                ),
            ],
            heading='Featured Content',
            classname='collapsible collapsed',
        ),
    ]

    promote_panels = Page.promote_panels + [
        FeatureablePageAbstract.feature_panel,
        ShareablePageAbstract.social_panel,
        SearchablePageAbstract.search_panel,
    ]

    settings_panels = Page.settings_panels + [
        ArchiveablePageAbstract.archive_panel,
        BasicPageAbstract.submenu_panel,
        ThemeablePageAbstract.theme_panel,
    ]

    search_fields = ArchiveablePageAbstract.search_fields \
        + BasicPageAbstract.search_fields \
        + ContentPage.search_fields

    parent_page_types = ['core.BasicPage', 'research.ProjectListPage']
    subpage_types = []
    templates = 'research/project_page.html'

    def get_featured_pages(self):
        featured_page_ids = self.featured_pages.order_by('sort_order').values_list('featured_page', flat=True)
        pages = Page.objects.specific().prefetch_related(
            'authors__author',
            'topics',
        ).in_bulk(featured_page_ids)
        return [pages[x] for x in featured_page_ids]

    def get_template(self, request, *args, **kwargs):
        standard_template = super(ProjectPage, self).get_template(request, *args, **kwargs)
        if self.theme:
            return f'themes/{self.get_theme_dir()}/project_page.html'
        return standard_template

    def get_context(self, request):
        context = super().get_context(request)

        context['featured_pages'] = self.get_featured_pages()
        return context

    class Meta:
        verbose_name = 'Activity'
        verbose_name_plural = 'Activities'
Beispiel #3
0
class PullQuoteBlock(StructBlock):
    quote = TextBlock("quote title")
    attribution = CharBlock()

    class Meta:
        icon = "openquote"
Beispiel #4
0
class HomePage(HomePageMetaData, SectionBodyMixin, Page):
    def __str__(self):
        return self.title

    class Meta():
        verbose_name = 'Home Page'

    parent_page_types = []  # prevent from being a child page

    featured_publication = models.ForeignKey(
        Page,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='The page to showcase in the page hero',
        verbose_name='Featured page'
    )
    hero_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Overwrites the hero image of the featured publication'
    )
    hero_link_caption = models.CharField(
        max_length=255,
        blank=True,
        help_text='Text to display on the link button',
        default='View full page'
    )
    featured_content = StreamField([
        ('content', StructBlock([
            ('title', CharBlock()),
            ('body', RichTextBlock(features=RICHTEXT_FEATURES_NO_FOOTNOTES)),
            ('related_page', PageChooserBlock(required=False)),
            ('button_caption', CharBlock(required=False, help_text='Overwrite title text from the related page'))
        ], template='home/blocks/featured_content.html'))
    ], null=True, blank=True)
    featured_work_heading = models.CharField(
        blank=True,
        null=True,
        default='Featured work',
        max_length=200,
        verbose_name='Section heading'
    )

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            PageChooserPanel('featured_publication', [
                'publications.PublicationPage',
                'publications.ShortPublicationPage',
                'publications.LegacyPublicationPage',
                'publications.AudioVisualMedia',
                'news.NewsStoryPage',
                'blog.BlogArticlePage',
                'events.EventPage',
                'project.ProjectPage'
            ]),
            ImageChooserPanel('hero_image'),
            FieldPanel('hero_link_caption')
        ], heading='Hero Section'),
        StreamFieldPanel('featured_content'),
        MultiFieldPanel([
            FieldPanel('featured_work_heading'),
            InlinePanel('featured_pages', label='Featured Pages')
        ], heading='Featured Work'),
        StreamFieldPanel('sections'),
        InlinePanel('page_notifications', label='Notifications')
    ]

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context['featured_pages'] = [link.other_page for link in self.featured_pages.all().order_by('sort_order') if link.other_page.live]

        return context
Beispiel #5
0
class AddedStreamFieldWithEmptyListDefaultPage(Page):
    body = StreamField([('title', CharBlock())], default=[])
Beispiel #6
0
class LinkBlock(StructBlock):
    link = URLBlock(required=True)
    link_text = CharBlock(required=True)
Beispiel #7
0
 def __init__(self):
     super().__init__(StructBlock([
         ('image', ImageChooserBlock()),
         ('caption', CharBlock(max_length=255, required=False)),
     ]))
Beispiel #8
0
class SupporterBlock(StructBlock):
    name = CharBlock()
    image = ImageBlock(required=False)
    content = RichTextBlock()
Beispiel #9
0
class Migration(migrations.Migration):

    dependencies = [
        ('wagtailcore', '0040_page_draft_title'),
    ]

    operations = [
        migrations.CreateModel(
            name='AlbumPage',
            fields=[
                ('page_ptr',
                 models.OneToOneField(auto_created=True,
                                      on_delete=models.deletion.CASCADE,
                                      parent_link=True,
                                      primary_key=True,
                                      serialize=False,
                                      to='wagtailcore.Page')),
                ('jumbotron',
                 StreamField(
                     (('jumbotron_block',
                       StructBlock(
                           (('heading_text', CharBlock(required=True)),
                            ('paragraph_text', CharBlock(required=True)),
                            ('text_color',
                             ChoiceBlock(
                                 blank=True,
                                 choices=[('', 'Select the text color'),
                                          ('text-primary', 'Primary Text'),
                                          ('text-secondary', 'Secondary Text'),
                                          ('text-success', 'Success Text'),
                                          ('text-danger', 'Danger Text'),
                                          ('text-warning', 'Warning Text'),
                                          ('text-info', 'Info Text'),
                                          ('text-light', 'Light Text'),
                                          ('text-dark', 'Dark Text'),
                                          ('text-muted', 'Muted Text'),
                                          ('text-white', 'White Text')])),
                            ('bg_color',
                             ChoiceBlock(
                                 blank=True,
                                 choices=[
                                     ('', 'Select the background color'),
                                     ('bg-primary', 'Primary Background'),
                                     ('bg-secondary', 'Secondary Backgorund'),
                                     ('bg-success', 'Success Backgorund'),
                                     ('bg-danger', 'Danger Backgorund'),
                                     ('bg-warning', 'Warning Backgorund'),
                                     ('bg-info', 'Info Backgorund'),
                                     ('bg-light', 'Light Backgorund'),
                                     ('bg-dark', 'Dark Backgorund'),
                                     ('bg-white', 'White Backgorund')
                                 ]))))), ),
                     blank=True,
                     verbose_name='Jumbotron')),
                ('card',
                 StreamField((('card_block',
                               StructBlock(
                                   (('card_image', ImageChooserBlock()),
                                    ('card_text', CharBlock())))), ),
                             blank=True,
                             verbose_name='Card')),
                ('language_link',
                 models.ForeignKey(blank=True,
                                   null=True,
                                   on_delete=models.deletion.SET_NULL,
                                   related_name='+',
                                   to='wagtailcore.Page')),
            ],
            options={
                'abstract': False,
            },
            bases=('wagtailcore.page', models.Model),
        ),
    ]
Beispiel #10
0
class ContactBlock(StructBlock):
    name = CharBlock()
    website = URLBlock()
    email = EmailBlock()
Beispiel #11
0
class SectorBlock(StructBlock):
    name = CharBlock()
    image = ImageBlock(required=False)
    contacts = ListBlock(ContactBlock)
Beispiel #12
0
class FAQBlock(StructBlock):
    question = CharBlock()
    answer = RichTextBlock()
 class TestStructBlock(StructBlock):
     title = CharBlock()
     description = CharBlock()
     field = SingleLineFormFieldBlock()
 class TestBlock(StreamBlock):
     field = SingleLineFormFieldBlock(icon='placeholder')
     p = CharBlock()
Beispiel #15
0
class QuestionAnswerBlock(StructBlock):
    question = CharBlock()
    answer = RichTextBlock()

    class Meta:
        template = 'cms_home/blocks/question_answer_block.html'
Beispiel #16
0
class CategoryQuestionBlock(OptionalFormFieldBlock):
    class Meta:
        template = 'stream_forms/render_list_field.html'

    # Overwrite field label and help text so we can defer to the category
    # as required
    field_label = CharBlock(
        label=_('Label'),
        required=False,
        help_text=_('Leave blank to use the default Category label'),
    )
    help_text = TextBlock(
        required=False,
        label=_('Leave blank to use the default Category help text'),
    )
    category = ModelChooserBlock('categories.Category')
    multi = BooleanBlock(label='Multi select', required=False)

    def get_field_class(self, struct_value):
        if struct_value['multi']:
            return forms.MultipleChoiceField
        else:
            return forms.ChoiceField

    def use_defaults_from_category(self, kwargs, category):
        category_fields = {'label': 'name', 'help_text': 'help_text'}

        for field in category_fields.keys():
            if not kwargs.get(field):
                kwargs[field] = getattr(category, category_fields[field])

        return kwargs

    def get_field_kwargs(self, struct_value):
        kwargs = super().get_field_kwargs(struct_value)
        category = struct_value['category']
        kwargs = self.use_defaults_from_category(kwargs, category)
        choices = category.options.values_list('id', 'value')
        kwargs.update({'choices': choices})
        return kwargs

    def get_widget(self, struct_value):
        if struct_value['multi']:
            category = struct_value['category']
            category_size = category.options.count()
            # Pick widget according to number of options to maintain good usability.
            if category_size < 32:
                return forms.CheckboxSelectMultiple
            else:
                return Select2MultipleWidget
        else:
            return forms.RadioSelect

    def prepare_data(self, value, data, serialize):
        category = value['category']
        if data:
            data = category.options.filter(id__in=data).values_list('value',
                                                                    flat=True)
        return data

    def get_searchable_content(self, value, data):
        return None

    def no_response(self):
        return ['No Response']
Beispiel #17
0
class FAQBlock(StructBlock):
    title = CharBlock(required=False)
    faqs = ListBlock(QuestionAnswerBlock)

    class Meta:
        template = 'cms_home/blocks/faq_block.html'
Beispiel #18
0
class NamedLinkGroupBlock(StructBlock):
    title = CharBlock()
    link_group = LinkGroupBlock()
Beispiel #19
0
class NewsletterPage(Page):
    class CallToActionChoices(models.TextChoices):
        EXPLORE = ('explore', 'Explore')
        LEARN_MORE = ('learn_more', 'Learn More')
        LISTEN = ('listen', 'Listen')
        NO_CTA = ('no_cta', 'No CTA')
        PDF = ('pdf', 'PDF')
        READ = ('read', 'Read')
        RSVP = ('rsvp', 'RSVP')
        SHARE_FACEBOOK = ('share_facebook', 'Share (Facebook)')
        SHARE_LINKEDIN = ('share_linkedin', 'Share (LinkedIn)')
        SHARE_TWITTER = ('share_twitter', 'Share (Twitter)')
        SUBSCRIBE = ('subscribe', 'Subscribe')
        WATCH = ('watch', 'Watch')

    body = StreamField(
        [
            ('advertisement_block',
             StructBlock([
                 ('title', CharBlock(required=False)),
                 ('text', RichTextBlock(required=False)),
                 ('url', URLBlock(required=True)),
                 ('image', ImageChooserBlock(required=False)),
                 ('cta',
                  ChoiceBlock(
                      choices=CallToActionChoices.choices,
                      verbose_name='CTA',
                      required=True,
                  )),
             ])),
            ('content_block',
             StructBlock([
                 ('content', PageChooserBlock(required=False)),
                 ('url', URLBlock(required=False)),
                 ('title_override', CharBlock(required=False)),
                 ('text_override', RichTextBlock(required=False)),
                 ('cta',
                  ChoiceBlock(
                      choices=CallToActionChoices.choices,
                      verbose_name='CTA',
                      required=True,
                  )),
                 ('line_separator_above',
                  BooleanBlock(
                      verbose_name='Add line separator above block', )),
             ])),
            ('featured_content_block',
             StructBlock([
                 ('content', PageChooserBlock(required=False)),
                 ('url', URLBlock(required=False)),
                 ('title_override', CharBlock(required=False)),
                 ('text_override', RichTextBlock(required=False)),
                 ('image_override', ImageChooserBlock(required=False)),
                 ('cta',
                  ChoiceBlock(
                      choices=CallToActionChoices.choices,
                      verbose_name='CTA',
                      required=True,
                  )),
             ])),
            ('social_block',
             StructBlock([
                 ('title', CharBlock(required=False)),
                 ('text', RichTextBlock(required=False)),
             ])),
            ('text_block',
             StructBlock([
                 ('title', CharBlock(required=False)),
                 ('text', RichTextBlock(required=False)),
             ])),
        ],
        blank=True,
    )
    html_file = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    # Reference field for the Drupal-Wagtail migrator. Can be removed after.
    drupal_node_id = models.IntegerField(blank=True, null=True)

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                StreamFieldPanel('body'),
            ],
            heading='Body',
            classname='collapsible',
        ),
        MultiFieldPanel(
            [
                DocumentChooserPanel('html_file'),
            ],
            heading='HTML File',
            classname='collapsible collapsed',
        ),
    ]

    parent_page_types = ['newsletters.NewsletterListPage']
    subpage_types = []
    templates = 'newsletters/newsletter_page.html'

    class Meta:
        verbose_name = 'Newsletter'
        verbose_name_plural = 'Newsletters'
Beispiel #20
0
class SponsorCategoryBlock(StructBlock):
    category_title = CharBlock()
    sponsor_group = SponsorGroupBlock()
Beispiel #21
0
class EventPage(
        BasicPageAbstract,
        ContentPage,
        FeatureablePageAbstract,
        ShareablePageAbstract,
):
    class EventAccessOptions(models.IntegerChoices):
        PRIVATE = (0, 'Private')
        PUBLIC = (1, 'Public')

    class InvitationTypes(models.IntegerChoices):
        RSVP_REQUIRED = (0, 'RSVP Required')
        INVITATION_ONLY = (1, 'Invitation Only')
        NO_RSVP = (2, 'No RSVP Required')

    embed_youtube = models.URLField(blank=True)
    event_access = models.IntegerField(choices=EventAccessOptions.choices,
                                       default=EventAccessOptions.PUBLIC,
                                       null=True,
                                       blank=False)
    event_end = models.DateTimeField(blank=True, null=True)
    flickr_album_url = models.URLField(blank=True)
    invitation_type = models.IntegerField(
        choices=InvitationTypes.choices, default=InvitationTypes.RSVP_REQUIRED)
    location_address1 = models.CharField(blank=True,
                                         max_length=255,
                                         verbose_name='Address (Line 1)')
    location_address2 = models.CharField(blank=True,
                                         max_length=255,
                                         verbose_name='Address (Line 2)')
    location_city = models.CharField(blank=True,
                                     max_length=255,
                                     verbose_name='City')
    location_country = models.CharField(blank=True,
                                        max_length=255,
                                        verbose_name='Country')
    location_name = models.CharField(blank=True, max_length=255)
    location_postal_code = models.CharField(blank=True,
                                            max_length=32,
                                            verbose_name='Postal Code')
    location_province = models.CharField(blank=True,
                                         max_length=255,
                                         verbose_name='Province/State')
    projects = ParentalManyToManyField('research.ProjectPage', blank=True)
    registration_url = models.URLField(blank=True, max_length=512)
    related_files = StreamField(
        [
            ('file', DocumentChooserBlock()),
        ],
        blank=True,
    )
    speakers = StreamField(
        [
            ('speaker',
             PageChooserBlock(required=True, page_type='people.PersonPage')),
            ('external_speaker', CharBlock(required=True)),
        ],
        blank=True,
    )
    twitter_hashtag = models.CharField(blank=True, max_length=64)
    website_button_text = models.CharField(
        blank=True,
        max_length=64,
        help_text=
        'Override the button text for the event website. If empty, the button will read "Event Website".'
    )
    website_url = models.URLField(blank=True, max_length=512)

    # Reference field for the Drupal-Wagtail migrator. Can be removed after.
    drupal_node_id = models.IntegerField(blank=True, null=True)

    content_panels = [
        BasicPageAbstract.title_panel,
        BasicPageAbstract.body_panel,
        BasicPageAbstract.images_panel,
        FieldPanel('publishing_date', heading='Event start'),
        FieldPanel('event_end'),
        MultiFieldPanel(
            [
                FieldPanel('event_access'),
                FieldPanel('invitation_type'),
                FieldPanel('website_url'),
                FieldPanel('website_button_text'),
                FieldPanel('registration_url'),
            ],
            heading='Event Details',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                StreamFieldPanel('speakers'),
            ],
            heading='Speakers',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                FieldPanel('location_name'),
                FieldPanel('location_address1'),
                FieldPanel('location_address2'),
                FieldPanel('location_city'),
                FieldPanel('location_province'),
                FieldPanel('location_postal_code'),
                FieldPanel('location_country'),
            ],
            heading='Location',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                FieldPanel('embed_youtube'),
                StreamFieldPanel('related_files'),
            ],
            heading='Media',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                FieldPanel('twitter_hashtag'),
                FieldPanel('flickr_album_url'),
            ],
            heading='Event Social Media',
            classname='collapsible collapsed',
        ),
        MultiFieldPanel(
            [
                FieldPanel('topics'),
                FieldPanel('projects'),
            ],
            heading='Related',
            classname='collapsible collapsed',
        ),
    ]
    promote_panels = Page.promote_panels + [
        FeatureablePageAbstract.feature_panel,
        ShareablePageAbstract.social_panel,
    ]

    parent_page_types = ['events.EventListPage']
    subpage_types = []
    templates = 'events/event_page.html'

    class Meta:
        verbose_name = 'Event'
        verbose_name_plural = 'Events'
Beispiel #22
0
class MultiInputCharFieldBlock(CharFieldBlock):
    number_of_inputs = IntegerBlock(default=2, label=_('Max number of inputs'))
    add_button_text = CharBlock(required=False, default=_('Add new item'))

    class Meta:
        label = _('Text field (single line) (multiple inputs)')
Beispiel #23
0
class AddedStreamFieldWithoutDefaultPage(Page):
    body = StreamField([('title', CharBlock())])
Beispiel #24
0
class FormFieldBlock(StructBlock):
    field_label = CharBlock(label=_('Label'))
    help_text = TextBlock(required=False, label=_('Help text'))
    help_link = URLBlock(required=False, label=_('Help link'))

    field_class = forms.CharField
    widget = None

    class Meta:
        template = 'stream_forms/render_field.html'

    def get_slug(self, struct_value):
        return force_str(slugify(anyascii(struct_value['field_label'])))

    def get_field_class(self, struct_value):
        return self.field_class

    def get_widget(self, struct_value):
        return self.widget

    def get_field_kwargs(self, struct_value):
        kwargs = {
            'label': struct_value['field_label'],
            'help_text': conditional_escape(struct_value['help_text']),
            'required': struct_value.get('required', False)
        }
        if 'default_value' in struct_value:
            kwargs['initial'] = struct_value['default_value']
        form_widget = self.get_widget(struct_value)
        if form_widget is not None:
            kwargs['widget'] = form_widget
        return kwargs

    def get_field(self, struct_value):
        field_kwargs = self.get_field_kwargs(struct_value)
        return self.get_field_class(struct_value)(**field_kwargs)

    def decode(self, value):
        """Convert JSON representation into actual python objects"""
        return value

    def serialize(self, value, context):
        field_kwargs = self.get_field_kwargs(value)
        return {
            'question': field_kwargs['label'],
            'answer': context.get('data'),
            'type': self.name,
        }

    def serialize_no_response(self, value, context):
        return {
            'question': value['field_label'],
            'answer': 'No Response',
            'type': 'no_response',
        }

    def prepare_data(self, value, data, serialize=False):
        return bleach_value(str(data))

    def render(self, value, context):
        data = context.get('data')
        data = self.prepare_data(value, data, context.get('serialize', False))

        context.update(data=data or self.no_response())

        if context.get('serialize'):
            if not data:
                return self.serialize_no_response(value, context)
            return self.serialize(value, context)

        return super().render(value, context)

    def get_searchable_content(self, value, data):
        return str(data)

    def no_response(self):
        return "No response"
Beispiel #25
0
class StreamModel(models.Model):
    body = StreamField([
        ('text', CharBlock()),
        ('rich_text', RichTextBlock()),
        ('image', ImageChooserBlock()),
    ])
Beispiel #26
0
class ComplexPage(Page):
    footer_colour = models.CharField("Hover colour",
                                     max_length=255,
                                     blank=True,
                                     null=True)
    story = StreamField([
        ('new_line_break', BooleanBlock(required=False, default=False)),
        ('title',
         CharBlock(blank=True,
                   classname="full title",
                   template='home/blocks/inner_title.html',
                   icon='title')),
        ('text_block',
         StructBlock([
             ('text', RichTextBlock(blank=True)),
             ('size',
              ChoiceBlock(required=False,
                          max_length=20,
                          choices=(
                              (u'6', u'Half'),
                              (u'9', u'Full'),
                          ))),
         ],
                     template='home/blocks/text.html',
                     icon='pilcrow')),
        ('image',
         StructBlock([
             ('new_line_break', BooleanBlock(required=False, default=False)),
             ('image', ImageChooserBlock(blank=True, required=False)),
             ('caption', CharBlock(required=False)),
             ('size',
              ChoiceBlock(required=False,
                          max_length=20,
                          choices=(
                              (u'4', u'Small'),
                              (u'6', u'Medium'),
                              (u'8', u'Large'),
                          ))),
         ],
                     template='home/blocks/image.html',
                     icon='image')),
        ('slideshow',
         StreamBlock(
             [('slide',
               StructBlock([
                   ('image', ImageChooserBlock(blank=True, required=False)),
                   ('caption', CharBlock(required=False)),
               ],
                           icon='image'))],
             template='home/blocks/slideshow.html',
             icon='code')),
        ('visual_link',
         StructBlock(
             [('new_line_break', BooleanBlock(required=False, default=False)),
              ('image', ImageChooserBlock(blank=True, required=False)),
              ('title', CharBlock(required=False)),
              ('size',
               ChoiceBlock(required=False,
                           max_length=20,
                           choices=(
                               (u'4', u'Small'),
                               (u'6', u'Medium'),
                               (u'8', u'Large'),
                           ))), ('page_link', PageChooserBlock(blank=True))],
             template='home/blocks/visual_link.html',
             icon='image')),
    ],
                        blank=True)

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

    promote_panels = [
        FieldPanel('footer_colour'),
    ] + Page.promote_panels
Beispiel #27
0
class HomePage(Page):

    body = StreamField([("title", CharBlock()), ("paragraph", RichTextBlock())])

    content_panels = Page.content_panels + [StreamFieldPanel("body")]
Beispiel #28
0
class ServicesPage(TypesetBodyMixin, HeroMixin, Page):
    """
    http://development-initiatives.surge.sh/page-templates/09-consultancy-services
    """
    def get_context(self, request):
        context = super(ServicesPage, self).get_context(request)
        topic_filter = request.GET.get('topic', None)
        if topic_filter:
            examples = ServicesPageRelatedExample.objects.filter(
                topics__slug=topic_filter)
        else:
            examples = ServicesPageRelatedExample.objects.all()

        context['topics'] = ExampleTopic.objects.all()
        context['selected_topic'] = topic_filter
        context['examples'] = examples
        context['related_news'] = get_related_pages(
            self,
            self.services_related_news.all(),
            NewsStoryPage.objects,
            min_len=0)

        return context

    contact_text = models.CharField(
        blank=True,
        null=True,
        max_length=250,
        default=
        'Find out more about our consultancy services and what we can do for you'
    )
    contact_button_text = models.CharField(blank=True,
                                           null=True,
                                           max_length=100,
                                           default='Get in touch')
    contact_email = models.EmailField(blank=True, null=True)

    specialities = StreamField([
        ('speciality',
         StructBlock([('image', ImageChooserBlock(required=False)),
                      ('heading', CharBlock(required=False)),
                      ('body',
                       RichTextBlock(required=False,
                                     features=RICHTEXT_FEATURES_NO_FOOTNOTES))
                      ]))
    ])

    skills = StreamField([
        ('skill',
         StructBlock([('heading', CharBlock(required=False)),
                      ('body',
                       RichTextBlock(required=False,
                                     features=RICHTEXT_FEATURES_NO_FOOTNOTES))
                      ]))
    ])

    richtext_columns = StreamField(
        [('column',
          StructBlock([('heading', TextBlock(required=False, icon='title')),
                       ('content',
                        RichTextBlock(features=RICHTEXT_FEATURES_NO_FOOTNOTES,
                                      icon='fa-paragraph'))],
                      template='blocks/richtext_column.html'))],
        null=True,
        blank=True)

    sections = StreamField(SectionStreamBlock(),
                           verbose_name="Sections",
                           null=True,
                           blank=True)

    class Meta:
        verbose_name = 'Services Page'

    content_panels = Page.content_panels + [
        hero_panels(),
        MultiFieldPanel([
            FieldPanel('contact_text'),
            FieldPanel('contact_button_text'),
            FieldPanel('contact_email')
        ],
                        heading='Contact aside'),
        StreamFieldPanel('body'),
        StreamFieldPanel('specialities'),
        StreamFieldPanel('skills'),
        InlinePanel('services_related_news', label="Related news"),
        InlinePanel('services_related_example', label="Project examples"),
        StreamFieldPanel('richtext_columns'),
        StreamFieldPanel('sections'),
        InlinePanel('page_notifications', label='Notifications')
    ]

    subpage_types = ['general.General']
    parent_page_types = [WhatWeDoPage]
Beispiel #29
0
class NamedBackerBlock(StructBlock):
    name = CharBlock()

    class Meta:
        template = 'blog/blocks/named_backer.html'
Beispiel #30
0
class LinkBlock(StructBlock):
    """
        A Link which can either be to a (off-site) URL, to a page in the site,
        or to a document. Use this instead of URLBlock.
    """

    link_to = ChoiceBlock(
        choices=[("page", "Page"), ("file", "File"), ("custom_url", "Custom URL")],
        required=False,
        classname="link_choice_type_selector",
    )
    page = PageChooserBlock(required=False, classname="page_link")
    file = DocumentChooserBlock(required=False, classname="file_link")
    custom_url = CharBlock(
        max_length=300,
        required=False,
        classname="custom_url_link url_field",
        validators=[URLOrAbsolutePathValidator()],
    )
    new_window = BooleanBlock(
        label="Open in new window", required=False, classname="new_window_toggle"
    )

    class Meta:
        label = None
        value_class = URLValue
        icon = "fa-share-square"
        form_classname = "link_block"
        form_template = "wagtailadmin/block_forms/link_block.html"
        template = "blocks/link_block.html"

    def set_name(self, name):
        """
        Over ride StructBlock set_name so label can remain empty in streamblocks
        """
        self.name = name

    def clean(self, value):
        clean_values = super().clean(value)
        errors = {}

        url_default_values = {
            "page": None,
            "file": None,
            "custom_url": "",
        }
        url_type = clean_values.get("link_to")

        # Check that a value has been uploaded for the chosen link type
        if url_type != "" and clean_values.get(url_type) in [None, ""]:
            errors[url_type] = ErrorList(
                ["You need to add a {} link".format(url_type.replace("_", " "))]
            )
        else:
            try:
                # Remove values added for link types not selected
                url_default_values.pop(url_type, None)
                for field in url_default_values:
                    clean_values[field] = url_default_values[field]
            except KeyError:
                errors[url_type] = ErrorList(["Enter a valid link type"])

        if errors:
            raise StreamBlockValidationError(block_errors=errors)

        return clean_values