Beispiel #1
0
class TableBlockStreamPage(Page):
    table = StreamField([('table', TableBlock())])

    content_panels = [StreamFieldPanel('table')]
Beispiel #2
0
class BaseIndexPage(BasePage, InlineHeroMixin):
    class Meta:
        abstract = True

    search_fields = BasePage.search_fields + InlineHeroMixin.extra_search_fields

    content_panels = [
        *Page.content_panels,
        FieldPanel("sub_head"),
        ImageChooserPanel("image"),
        StreamFieldPanel("body"),
    ]

    def _paginator(self, request, page_num=1, tags=None):
        children = self._child_model.objects.exclude(
            id__in=self.featured_ids).live().public().order_by(
                '-first_published_at')

        if tags is not None:
            children = children.filter(tags__slug__in=tags).distinct()

        p = Paginator(children, settings.PAGINATION_ITEMS_PER_PAGE)
        result_set = p.page(page_num)
        return result_set

    def _make_pagination_link(self, tags, page):
        base = f"{self.get_url()}?"
        if tags:
            base += f"tag={tags}&"
        base += f"page={page}"
        return base

    def get_context(self, request):
        ctx = super().get_context(request)
        request_tags = request.GET.get('tag', None)
        tags = None
        page = 1
        if request_tags:
            tags = request_tags.split(',')

        if request.GET.get('page', None):
            page = int(request.GET.get('page', 1))

        children = self._paginator(request, page, tags)

        ctx.update({'children': children})
        if children.has_next():
            ctx.update({
                'next_link':
                self._make_pagination_link(request_tags,
                                           children.next_page_number())
            })
        if children.has_previous():
            ctx.update({
                'previous_link':
                self._make_pagination_link(request_tags,
                                           children.previous_page_number())
            })
        return ctx

    @property
    def featured_ids(self):
        rv = []
        if hasattr(self, 'featured_posts'):
            for item in self.featured_posts:
                rv.append(item.value.id)
        return rv

    @cached_classmethod
    def get_admin_tabs(cls):
        tabs = super().get_admin_tabs()
        return tabs
Beispiel #3
0
class PrimaryPage(FoundationMetadataPageMixin, Page):
    """
    Basically a straight copy of modular page, but with
    restrictions on what can live 'under it'.

    Ideally this is just PrimaryPage(ModularPage) but
    setting that up as a migration seems to be causing
    problems.
    """
    header = models.CharField(
        max_length=250,
        blank=True
    )

    banner = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='primary_banner',
        verbose_name='Hero Image',
        help_text='Choose an image that\'s bigger than 4032px x 1152px with aspect ratio 3.5:1',
    )

    intro = models.CharField(
        max_length=250,
        blank=True,
        help_text='Intro paragraph to show in hero cutout box'
    )

    narrowed_page_content = models.BooleanField(
        default=False,
        help_text='For text-heavy pages, turn this on to reduce the overall width of the content on the page.'
    )

    zen_nav = models.BooleanField(
        default=False,
        help_text='For secondary nav pages, use this to collapse the primary nav under a toggle hamburger.'
    )

    body = StreamField(base_fields)

    settings_panels = Page.settings_panels + [
        MultiFieldPanel([
            FieldPanel('narrowed_page_content'),
        ]),
        MultiFieldPanel([
            FieldPanel('zen_nav'),
        ])
    ]

    content_panels = Page.content_panels + [
        FieldPanel('header'),
        ImageChooserPanel('banner'),
        FieldPanel('intro'),
        StreamFieldPanel('body'),
    ]

    subpage_types = [
        'PrimaryPage',
        'RedirectingPage'
    ]

    show_in_menus_default = True

    def get_context(self, request):
        context = super(PrimaryPage, self).get_context(request)
        return get_page_tree_information(self, context)
Beispiel #4
0
class HomePage(Page):

    body = StreamField(blocks.BodyBlock)

    content_panels = Page.content_panels + [StreamFieldPanel("body")]
Beispiel #5
0
class Event(Page):
    resource_type = 'event'
    parent_page_types = ['events.Events']
    subpage_types = []
    template = 'event.html'

    # Content fields
    description = TextField(
        blank=True,
        default='',
        help_text='Optional short text description, max. 400 characters',
        max_length=400,
    )
    image = ForeignKey(
        'mozimages.MozImage',
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name='+',
    )
    body = CustomStreamField(
        blank=True,
        null=True,
        help_text=
        ('Optional body content. Supports rich text, images, embed via URL, embed via HTML, and inline code snippets'
         ))
    agenda = StreamField(
        StreamBlock([
            ('agenda_item', AgendaItemBlock()),
        ], required=False),
        blank=True,
        null=True,
        help_text='Optional list of agenda items for this event',
    )
    speakers = StreamField(
        StreamBlock([
            ('speaker', PageChooserBlock(target_model='people.Person')),
            ('external_speaker', ExternalSpeakerBlock()),
        ],
                    required=False),
        blank=True,
        null=True,
        help_text='Optional list of speakers for this event',
    )

    # Card fields
    card_title = CharField('Title', max_length=140, blank=True, default='')
    card_description = TextField('Description',
                                 max_length=400,
                                 blank=True,
                                 default='')
    card_image = ForeignKey(
        'mozimages.MozImage',
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name='+',
        verbose_name='Image',
    )

    # Meta fields
    start_date = DateField(default=datetime.date.today)
    end_date = DateField(blank=True, null=True)
    latitude = FloatField(blank=True, null=True)
    longitude = FloatField(blank=True, null=True)
    register_url = URLField('Register URL', blank=True, null=True)
    venue_name = CharField(max_length=100, blank=True, default='')
    venue_url = URLField('Venue URL', max_length=100, blank=True, default='')
    address_line_1 = CharField(max_length=100, blank=True, default='')
    address_line_2 = CharField(max_length=100, blank=True, default='')
    address_line_3 = CharField(max_length=100, blank=True, default='')
    city = CharField(max_length=100, blank=True, default='')
    state = CharField('State/Province/Region',
                      max_length=100,
                      blank=True,
                      default='')
    zip_code = CharField('Zip/Postal code',
                         max_length=100,
                         blank=True,
                         default='')
    country = CountryField(blank=True, default='')
    keywords = ClusterTaggableManager(through=EventTag, blank=True)

    # Content panels
    content_panels = Page.content_panels + [
        FieldPanel('description'),
        MultiFieldPanel(
            [
                ImageChooserPanel('image'),
            ],
            heading='Image',
            help_text=
            ('Optional header image. If not specified a fallback will be used. This image is also shown when sharing '
             'this page via social media')),
        StreamFieldPanel('body'),
        StreamFieldPanel('agenda'),
        StreamFieldPanel('speakers'),
    ]

    # Card panels
    card_panels = [
        FieldPanel('card_title'),
        FieldPanel('card_description'),
        ImageChooserPanel('card_image'),
    ]

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [
                FieldPanel('start_date'),
                FieldPanel('end_date'),
                FieldPanel('latitude'),
                FieldPanel('longitude'),
                FieldPanel('register_url'),
            ],
            heading='Event details',
            classname='collapsible',
            help_text=mark_safe(
                'Optional time and location information for this event. Latitude and longitude are used to show a map '
                'of the event’s location. For more information on finding these values for a given location, '
                '<a href="https://support.google.com/maps/answer/18539">see this article</a>'
            )),
        MultiFieldPanel(
            [
                FieldPanel('venue_name'),
                FieldPanel('venue_url'),
                FieldPanel('address_line_1'),
                FieldPanel('address_line_2'),
                FieldPanel('address_line_3'),
                FieldPanel('city'),
                FieldPanel('state'),
                FieldPanel('zip_code'),
                FieldPanel('country'),
            ],
            heading='Event address',
            classname='collapsible',
            help_text=
            'Optional address fields. The city and country are also shown on event cards'
        ),
        MultiFieldPanel(
            [
                InlinePanel('topics'),
            ],
            heading='Topics',
            help_text=
            ('These are the topic pages the event will appear on. The first topic in the list will be treated as the '
             'primary topic and will be shown in the page’s related content.'
             )),
        MultiFieldPanel(
            [
                FieldPanel('seo_title'),
                FieldPanel('search_description'),
                FieldPanel('keywords'),
            ],
            heading='SEO',
            help_text=
            'Optional fields to override the default title and description for SEO purposes'
        ),
    ]

    # Settings panels
    settings_panels = [
        FieldPanel('slug'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(card_panels, heading='Card'),
        ObjectList(meta_panels, heading='Meta'),
        ObjectList(settings_panels, heading='Settings', classname='settings'),
    ])

    @property
    def is_upcoming(self):
        """Returns whether an event is in the future."""
        return self.start_date > datetime.date.today()

    @property
    def primary_topic(self):
        """Return the first (primary) topic specified for the event."""
        article_topic = self.topics.first()
        return article_topic.topic if article_topic else None

    @property
    def month_group(self):
        return self.start_date.replace(day=1)

    @property
    def event_dates(self):
        """Return a formatted string of the event start and end dates"""
        event_dates = self.start_date.strftime("%b %-d")
        if self.end_date:
            event_dates += " &ndash; "
            start_month = self.start_date.strftime("%m")
            if self.end_date.strftime("%m") == start_month:
                event_dates += self.end_date.strftime("%-d")
            else:
                event_dates += self.end_date.strftime("%b %-d")
        return event_dates

    @property
    def event_dates_full(self):
        """Return a formatted string of the event start and end dates, including the year"""
        return self.event_dates + self.start_date.strftime(", %Y")

    def has_speaker(self, person):
        for speaker in self.speakers:  # pylint: disable=not-an-iterable
            if (speaker.block_type == 'speaker'
                    and str(speaker.value) == str(person.title)):
                return True
        return False
Beispiel #6
0
class HomePage(RoutablePageMixin, Page):
    banner_title = models.CharField(max_length=100, blank=False, null=True)
    banner_subtitle = RichTextField(features=['bold', 'italic'])
    banner_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    banner_cta = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    content = StreamField([
        ('cta', blocks.CTABlock()),
    ],
                          null=True,
                          blank=True)

    # only one on site
    max_count = 1
    # parent_page_type = ['wagtailcore.Page']
    subpage_types = [
        'blog.BlogListingPage', 'contact.ContactPage', 'flex.FlexPage',
        'behance.BehanceProjectListingPage'
    ]

    # search_fields = Page.search_fields + [

    # ]

    api_fields = [
        APIField('banner_title'),
        APIField('banner_subtitle'),
        APIField('banner_image'),
        APIField('banner_cta'),
        APIField('carousel_images'),
        APIField('content'),
    ]

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

    # promote_panels = []
    # settings_panels = []

    banner_panels = [
        MultiFieldPanel([
            FieldPanel('banner_title'),
            FieldPanel('banner_subtitle'),
            ImageChooserPanel('banner_image'),
            PageChooserPanel('banner_cta'),
        ],
                        heading='Banners Options'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(banner_panels, heading='Banner'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels, heading='Settings'),
    ])

    class Meta:
        verbose_name = 'Home Page'
        verbose_name_plural = 'Home Pages'

    @route(r'^subscribe/$')
    def the_subscribe_page(self, request, *args, **kwargs):
        context = self.get_context(request, *args, **kwargs)
        context['a_special_text'] = 'Hello world 123123'
        return render(request, 'home/subscribe.html', context)
Beispiel #7
0
class PublicationPage(BasePage, CanonicalMixin):
    # standard approach appears to be
    # (via https://docs.wagtail.io/en/latest/topics/streamfield.html)
    # author = models.Charfield(max_length=255)
    # which also gives subcategories for StreamField

    # next two lines would make the post less available but by commenting out
    # instead we make it available anywhere that doesn't exclude it
    # parent_page_types = ["PublicationIndexPage"]
    # subpage_types = []

    updated_at = models.DateTimeField(
        editable=True,
        null=True,
        blank=True,
        verbose_name="Updated at (leave blank for initial publication)",
    )
    history = RichTextField(
        blank=True,
        verbose_name="Version history (leave blank for initial publication)")

    content_panels = [
        *Page.content_panels,
        FieldPanel("first_published_at"),
        FieldPanel("updated_at"),
        StreamFieldPanel("body"),
        FieldPanel("history"),
    ]

    settings_panels = CanonicalMixin.panels + BasePage.settings_panels

    def replace_headers(self, html):
        """Given a html string, return a html string where the header tags
        have id attributes so they can be used as anchors, and list the ids
        and text of those tags so we can make a table of contents."""
        header_tags = ["h2"]
        toc = []
        root = lxml.html.fromstring(html)
        for tag_name in header_tags:
            for tag in root.xpath(f"//{tag_name}"):
                # create a slugged name for the tag of the form tag-text-3
                header_name = tag.text
                bare_slug = slugify(header_name, allow_unicode=True)
                self.slug_count[bare_slug] += 1
                slug = bare_slug + slug_count_text(self.slug_count[bare_slug])
                # modify the tag and record the details
                tag.set("id", slug)
                toc.append((header_name, slug))
        return lxml.html.tostring(root).decode("utf-8"), toc

    def get_context(self, request):
        """Pass the html of each richtext node within the streamfield to
        replace_headers, creating a page-wide table of contents. We use
        self.slug_count to preserve the list of slugs seen so far across
        multiple rich_text blocks."""
        context = super().get_context(request)
        context["toc"] = []  # table of contents
        self.slug_count = Counter({"contents": 1})
        for i, block in enumerate(self.body._raw_data):
            if block["type"] == "rich_text":
                replacement_html, new_toc = self.replace_headers(
                    block["value"])
                context["toc"].extend(new_toc)
                self.body._raw_data[i]["value"] = replacement_html
        return context
Beispiel #8
0
class MovePageTag(TaggedItemBase):
    content_object = ParentalKey(
        'moves.MovePage', related_name='tagged_items'
    )

class MovePage(Page):
    description = models.CharField(max_length=255)
    content = RichTextField(blank=True)
    tags = ClusterTaggableManager(through=MovePageTag, blank=True)
    image = models.ForeignKey(
        Image,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    indexed_fields = ('info', 'description', 'content', 'tags')

MovePage.content_panels = Page.content_panels + [
    StreamFieldPanel('info'),
    FieldPanel('description'),
    FieldPanel('content'),
    ImageChooserPanel('image'),
    FieldPanel('tags'),
    InlinePanel('credits', label="Credits")
]


Beispiel #9
0
class FooterPage(Page):
    footer_image = models.ForeignKey('wagtailimages.Image',
                                     null=True,
                                     blank=True,
                                     on_delete=models.SET_NULL)
    column_1 = StreamField([
        ('image', ImageChooserBlock()),
        ('externalLink',
         LinkBlock(label="External Link", template="cms/external_link.html")),
        ('internalLink',
         InternalLinkBlock(label="Internal Link",
                           template="cms/internal_link.html")),
        ('google_form',
         LinkBlock(
             label="Google Form Link",
             template="cms/google_form_footer.html",
             help_text=
             "The URL for the Google form. This will be loaded into a popup when clicked."
         )),
        ('text',
         RichTextBlock(features=[
             'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol', 'ul', 'hr',
             'superscript', 'subscript', 'strikethrough', 'blockquote',
             'image', 'embed'
         ])),
    ])
    column_2 = StreamField([
        ('image', ImageChooserBlock()),
        ('externalLink',
         LinkBlock(label="External Link", template="cms/external_link.html")),
        ('internalLink',
         InternalLinkBlock(label="Internal Link",
                           template="cms/internal_link.html")),
        ('google_form',
         LinkBlock(
             label="Google Form Link",
             template="cms/google_form_footer.html",
             help_text=
             "The URL for the Google form. This will be loaded into a popup when clicked."
         )),
        ('text',
         RichTextBlock(features=[
             'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol', 'ul', 'hr',
             'superscript', 'subscript', 'strikethrough', 'blockquote',
             'image', 'embed'
         ])),
    ])
    column_3 = StreamField([
        ('image', ImageChooserBlock()),
        ('externalLink',
         LinkBlock(label="External Link", template="cms/external_link.html")),
        ('internalLink',
         InternalLinkBlock(label="Internal Link",
                           template="cms/internal_link.html")),
        ('google_form',
         LinkBlock(
             label="Google Form Link",
             template="cms/google_form_footer.html",
             help_text=
             "The URL for the Google form. This will be loaded into a popup when clicked."
         )),
        ('text',
         RichTextBlock(features=[
             'h2', 'h3', 'h4', 'bold', 'italic', 'link', 'ol', 'ul', 'hr',
             'superscript', 'subscript', 'strikethrough', 'blockquote',
             'image', 'embed'
         ])),
    ])

    content_panels = Page.content_panels + [
        ImageChooserPanel('footer_image'),
        StreamFieldPanel('column_1'),
        StreamFieldPanel('column_2'),
        StreamFieldPanel('column_3'),
    ]
Beispiel #10
0
class WebPage(Page):

    # Values that help Streamfield Blocks.
    _rich_text_features = [
        'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'bold', 'italic', 'ol', 'ul',
        'link', 'document-link', 'image', 'embed'
    ]
    _block_list = [
        (
            'CardLinks',
            ListBlock(
                CardLinkBlock(
                    label=_BlockNames.cardlink,
                    help_text=_StreamfieldHelpTexts.cardlink,
                ),
                template='home/list_block_card_link.html',
            ),
        ),
        (
            'Postcard',
            PostcardBlock(
                label=_BlockNames.postcard,
                help_text=_StreamfieldHelpTexts.postcard,
            ),
        ),
        (
            'Quote',
            QuoteWithAttributionBlock(
                label=_BlockNames.quote,
                help_text=_StreamfieldHelpTexts.quote,
            ),
        ),
        (
            'RichText',
            RichTextBlock(
                features=_rich_text_features,
                label=_BlockNames.rich_text,
                help_text=_StreamfieldHelpTexts.rich_text,
            ),
        ),
        (
            'Title',
            TitleBlock(
                label=_BlockNames.title,
                help_text=_StreamfieldHelpTexts.title_block,
            ),
        ),
        (
            'SectionTitle',
            SectionTitleBlock(
                label=_BlockNames.section_title,
                help_text=_StreamfieldHelpTexts.section_title_block,
            ),
        ),
        (
            'Line',
            LineBlock(
                label=_BlockNames.line,
                help_text=_StreamfieldHelpTexts.line_block,
            ),
        ),
        (
            'Chart',
            ChartBlock(
                label=_BlockNames.chart,
                help_text=_StreamfieldHelpTexts.chart_block,
            ),
        ),
    ]

    # Model Fields
    title_my = models.CharField(
        max_length=255,
        blank=True,
        verbose_name=_ModelVerboseNames.title,
        help_text=_ModelHelpTexts.title,
    )
    hero_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name=_ModelVerboseNames.hero_image,
        help_text=_ModelHelpTexts.hero_image,
    )
    description_en = models.TextField(
        blank=True,
        verbose_name=_ModelVerboseNames.description,
        help_text=_ModelHelpTexts.description,
    )
    description_my = models.TextField(
        blank=True,
        verbose_name=_ModelVerboseNames.description,
        help_text=_ModelHelpTexts.description,
    )

    body_en = StreamField(
        _block_list,
        blank=True,
        help_text=_ModelHelpTexts.body,
        verbose_name=_ModelVerboseNames.body,
    )
    body_my = StreamField(
        _block_list,
        blank=True,
        help_text=_ModelHelpTexts.body,
        verbose_name=_ModelVerboseNames.body,
    )

    # Translatable fields.
    translated_title = TranslatedField(
        'title',
        'title_my',
    )
    description = TranslatedField(
        'description_en',
        'description_my',
    )
    body = TranslatedField(
        'body_en',
        'body_my',
    )

    # Add fields to the search index.
    search_fields = Page.search_fields + [
        index.SearchField('title'),
        index.SearchField('title_my'),
        index.SearchField('body_en'),
        index.SearchField('body_my'),
        index.SearchField('description_en'),
        index.SearchField('description_my')
    ]

    # Which fields the English and Myanmar admin tabs display.
    en_content_panels = Page.content_panels + [
        FieldPanel('description_en'),
        StreamFieldPanel('body_en'),
    ]
    my_content_panels = [
        FieldPanel('title_my'),
        FieldPanel('description_my'),
        StreamFieldPanel('body_my'),
    ]
    promote_panels = Page.promote_panels + [
        ImageChooserPanel('hero_image'),
    ]

    # Sets the Wagtail Admin Interface's tabs.
    edit_handler = TabbedInterface([
        ObjectList(en_content_panels, heading=_english_panel),
        ObjectList(my_content_panels, heading=_myanmar_panel),
        ObjectList(promote_panels, heading=_promote_panel),
        ObjectList(Page.settings_panels,
                   heading=_settings_panel,
                   classname="settings"),
    ])
Beispiel #11
0
class AssignmentTypes(index.Indexed, models.Model):

    category_type = models.CharField(max_length=100,
                                     blank=True,
                                     null=True,
                                     help_text="Select the category type.",
                                     choices=CATEGORY_LIST)

    title = models.CharField(max_length=100,
                             blank=True,
                             null=True,
                             help_text="Select the type of feat.",
                             choices=TITLE_LIST)

    verb = models.CharField(max_length=100,
                            blank=True,
                            null=True,
                            help_text="Select the verb you for this feat.",
                            choices=VERB_LIST)

    description = models.TextField(
        blank=True,
        null=True,
        help_text="Enter the description of the assignment type.")

    feat = models.CharField(max_length=255,
                            blank=True,
                            null=True,
                            help_text="Enter the assignment feat.")

    topics = StreamField([
        ("Topics", Topics()),
    ],
                         null=True,
                         blank=True,
                         help_text="Enter any topics to explore")

    # add image carousel to panels
    panels = [
        MultiFieldPanel(
            [
                # FieldPanel("performance_type", classname="col12 line"),
                FieldPanel("category_type", classname="col6 line"),
                FieldPanel("title", classname="col6 line"),
                FieldPanel("feat", classname="col6 line"),
                FieldPanel("verb", classname="col6 line"),
                FieldPanel("description", classname="col12 line"),
                StreamFieldPanel("topics", classname="col12 line"),

                # DocumentChooserPanel("resource_link", classname="col6"),
                # DocumentChooserPanel("student_sample", classname="col6"),
                # FieldPanel("video_link", classname="col12 line-top"),
            ],
            heading="Assignment Info",
        ),

        # FieldPanel("category_type"),
        # FieldPanel("title"),
        # FieldPanel("verb"),
        # FieldPanel("description"),
        # FieldPanel("feat"),
        #
        # StreamFieldPanel("topics"),
    ]

    def __str__(self):
        return self.title or ''

    class Meta:
        verbose_name = "Assignment Type"
        verbose_name_plural = "Assignment Types"


#
# widgets
# __all__ = (
#     'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'NumberInput',
#     'EmailInput', 'URLInput', 'PasswordInput', 'HiddenInput',
#     'MultipleHiddenInput', 'FileInput', 'ClearableFileInput', 'Textarea',
#     'DateInput', 'DateTimeInput', 'TimeInput', 'CheckboxInput', 'Select',
#     'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
#     'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget',
#     'SplitHiddenDateTimeWidget', 'SelectDateWidget',
# )
class ContactPage(Page):
    # ---- General Page information ------
    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')

    contact_point = StreamField([('person', ContactCardBlock())], )

    other_contacts = StreamField(
        [('contact',
          blocks.StructBlock([
              ('person', ContactCardBlock()),
              ('english_groups',
               blocks.CharBlock(
                   help_text=_('Comma separated list of English group names.'),
                   required=False,
               )),
              ('swedish_groups',
               blocks.CharBlock(
                   help_text=_('Comma separated list of Swedish group names.'),
                   required=False,
               )),
          ],
                             icon='user'))], )

    map_location = models.CharField(
        max_length=255,
        verbose_name=_('Map Location'),
        help_text=_('Enter comma separated coordinates'),
        blank=True,
    )

    location_description = RichTextField(
        verbose_name=_('Location Description'),
        help_text=_('Enter the text to show on the map'),
        blank=True,
    )

    def get_context(self, request, *args, **kwargs):
        contacts = {}
        for contact in self.other_contacts:
            if request.LANGUAGE_CODE == 'sv':
                groups = contact.value.get('swedish_groups', '')
            else:
                groups = contact.value.get('english_groups', '')
            groups = groups.split(',')

            for group in groups:
                group = group.strip()
                list = contacts.get(group, [])
                list.append(contact.value['person'])
                contacts[group] = list

        context = super(ContactPage, self).get_context(request, *args,
                                                       **kwargs)
        context['contacts'] = contacts
        return context

    content_panels = Page.content_panels + [
        FieldPanel('title_sv', classname="full title"),
        FieldPanel('map_location'),
        FieldPanel('location_description'),
        StreamFieldPanel('contact_point'),
        StreamFieldPanel('other_contacts'),
    ]
Beispiel #13
0
class ExternalArticle(ExternalContent):
    class Meta:
        verbose_name = "External Post"
        verbose_name_plural = "External Posts"

    resource_type = "article"  #  if you change this, amend the related CSS, too

    date = DateField(
        "External Post date",
        default=datetime.date.today,
        help_text="The date the external post was published",
    )
    authors = StreamField(
        StreamBlock(
            [
                ("author", PageChooserBlock(target_model="people.Person")),
                ("external_author", ExternalAuthorBlock()),
            ],
            required=False,
        ),
        blank=True,
        null=True,
        help_text=(
            "Optional list of the external post's authors. "
            "Use ‘External author’ to add "
            "guest authors without creating a profile on the system"
        ),
    )
    read_time = CharField(
        max_length=30,
        blank=True,
        help_text=(
            "Optional, approximate read-time for this external post, "
            "e.g. “2 mins”. This is shown as a small hint when the "
            "external post is displayed as a card."
        ),
    )

    meta_panels = [
        FieldPanel("date"),
        StreamFieldPanel("authors"),
        MultiFieldPanel(
            [InlinePanel("topics")],
            heading="Topics",
            help_text="The topic pages this external post will appear on",
        ),
        FieldPanel("read_time"),
    ]

    settings_panels = BasePage.settings_panels + [FieldPanel("slug")]

    edit_handler = TabbedInterface(
        [
            ObjectList(ExternalContent.card_panels, heading="Card"),
            ObjectList(meta_panels, heading="Meta"),
            ObjectList(settings_panels, heading="Settings", classname="settings"),
        ]
    )

    @property
    def article(self):
        return self

    @property
    def month_group(self):
        return self.date.replace(day=1)

    def has_author(self, person):
        for author in self.authors:  # pylint: disable=not-an-iterable
            if author.block_type == "author" and str(author.value) == str(person.title):
                return True
        return False
Beispiel #14
0
class HomePage(RoutablePageMixin, Page):
  """Home page model"""

  template = "home/home_page.html"
  max_count =1 # Only one homepage instance
  # parent_page_type = [
  #   'wagtailcore.Page'
  # ]

  banner_title = models.CharField(max_length=100, blank=False, null=True)
  banner_subtitle = RichTextField(features=["bold", "italic"])
  banner_image = models.ForeignKey(
    "wagtailimages.Image",
    null=True,
    blank=False,
    on_delete=models.SET_NULL,
    related_name="+"
  )
  banner_cta = models.ForeignKey(
    "wagtailcore.Page",
    null=True,
    blank=True,
    on_delete=models.SET_NULL,
    related_name="+"
  )

  content = StreamField(
    [
      ("cta", blocks.CTABlock()),
    ],
    null=True,
    blank=True
  )

  content_panels = Page.content_panels + [
    MultiFieldPanel([
      FieldPanel("banner_title"),
      FieldPanel("banner_subtitle"),
      ImageChooserPanel("banner_image"),
      PageChooserPanel("banner_cta"),
    ], heading="Banner Options"),
    InlinePanel("carousel_images", max_num=5, min_num=1, label="Carousel Images"),
    StreamFieldPanel("content"),
  ]


  # # # def get_context_data(self, **kwargs):
  # # #   context = super().get_context_data(**kwargs) 
  # # def get_context(self, request):
  # #   context = super(HomePage, self).get_context(request)
  def get_context(self, request, *args, **kwargs):
    context = super().get_context(request, *args, **kwargs)
    context['subscription_form'] = SubscriberCreateForm()
    return context

  class Meta:

    verbose_name = "Home Page"
    verbose_name_plural = "Home Pages"

  @route(r'^subscribe-route/$')
  def the_subscribe_page(self, request, *args, **kwargs):
    context = self.get_context(request, *args, **kwargs)
    context['subscription_form'] = SubscriberCreateForm()
    return render(request, "home/subscribe.html", context)
Beispiel #15
0
    reference_title = TextField(null=True, blank=True)
    subtitle = TextField(null=True, blank=True)
    body = StreamField([
        ('paragraph', RichTextBlock()),
        ('image', ImageChooserBlock()),
        ('html', RawHTMLBlock()),
        ('audio', AudioBlock()),
        ('video', VideoPlayerBlock()),
    ],
                       blank=True)


DefaultPage.content_panels = Page.content_panels + [
    FieldPanel('reference_title'),
    FieldPanel('subtitle'),
    StreamFieldPanel('body'),
]
DefaultPage.promote_panels = DefaultPage.promote_panels + [
    FieldPanel('show_in_sitemap')
]


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()),
Beispiel #16
0
class CoursePage(Page):

    parent_page_type = ["CourseIndexPage"]
    intro = models.CharField('one line summary', max_length=250)
    summary = RichTextField('full summary')
    # start_date = models.DateTimeField(blank=False)
    address_details = models.CharField('address details',
                                       max_length=250,
                                       blank=True)
    formatted_address = models.CharField(max_length=255)
    # latlng_address = models.CharField(max_length=255)

    course_image = models.ForeignKey('wagtailimages.Image',
                                     null=True,
                                     blank=True,
                                     on_delete=models.SET_NULL,
                                     related_name='+')

    course_flyer = StreamField([
        ('course_flyer', DocumentChooserBlock()),
    ],
                               blank=True)

    organiser_name = models.CharField('name', max_length=250, blank=True)
    organiser_email = models.EmailField('email', blank=True)
    organiser_number = models.CharField('number', max_length=250, blank=True)

    course_programme = StreamField([
        ('table', TableBlock()),
    ], blank=True)

    class Meta:
        verbose_name = "Courses & Conferences Page"

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

    content_panels = Page.content_panels + [
        FieldPanel('intro', classname="full"),
        FieldPanel('summary', classname="full"),
        ImageChooserPanel('course_image'),
        InlinePanel('related_links', label="Course Links"),
        InlinePanel('related_dates', label="Course Dates"),
        StreamFieldPanel('course_programme'),
        StreamFieldPanel('course_flyer'),
        MultiFieldPanel(
            [
                FieldPanel('address_details', classname="full"),
                MapFieldPanel('formatted_address'),
            ],
            heading="Location",
            # classname="collapsible collapsed"
        ),
        MultiFieldPanel(
            [
                FieldPanel('organiser_name', classname="full"),
                FieldPanel('organiser_email', classname="full"),
                FieldPanel('organiser_number', classname="full"),
            ],
            heading="Organiser Details",
            # classname="collapsible collapsed"
        ),

        # MapFieldPanel('latlng_address', latlng=True),
    ]

    # parent_page_types = ['CourseIndexPage']

    def get_context(self, request):
        context = super().get_context(request)
        relateddates = self.related_dates.order_by('date')
        #the [:1] returns the first result from the list e.g. the start date.
        context['relateddates'] = relateddates
        return context
Beispiel #17
0
class ContentPage(BasePage):
    parent_page_types = [
        "home.HomePage", "content.ContentPage", "topics.Topic"
    ]
    subpage_types = ["people.People", "content.ContentPage"]
    template = "content.html"

    # Content fields
    description = RichTextField(
        blank=True,
        default="",
        features=RICH_TEXT_FEATURES_SIMPLE,
        help_text="Optional short text description, max. 400 characters",
        max_length=400,
    )
    body = CustomStreamField(help_text=(
        "Main page body content. Supports rich text, images, embed via URL, "
        "embed via HTML, and inline code snippets"))

    sidebar = CustomStreamField(
        null=True,
        blank=True,
        help_text=
        ("Sidebar page body content (narrower than main body). Rendered to the "
         "right of the main body content in desktop and below it in mobile."
         "Supports rich text, images, embed via URL, "
         "embed via HTML, and inline code snippets"),
    )

    # Card fields
    card_title = CharField("Title", max_length=140, blank=True, default="")
    card_description = TextField("Description",
                                 max_length=140,
                                 blank=True,
                                 default="")
    card_image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
        help_text="An image in 16:9 aspect ratio",
    )
    card_image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
        help_text="An image in 16:9 aspect ratio",
    )
    card_image_3_2 = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
        help_text="An image in 3:2 aspect ratio",
    )

    # Meta fields
    nav_description = TextField("Navigation description",
                                max_length=400,
                                blank=True,
                                default="")
    icon = FileField(
        upload_to="contentpage/icons",
        blank=True,
        default="",
        help_text=("MUST be a black-on-transparent SVG icon ONLY, "
                   "with no bitmap embedded in it."),
        validators=[check_for_svg_file],
    )
    keywords = ClusterTaggableManager(through=ContentPageTag, blank=True)

    # Editor panel configuration
    content_panels = BasePage.content_panels + [
        FieldPanel("description"),
        StreamFieldPanel("body"),
        StreamFieldPanel("sidebar"),
    ]

    # Card panels
    card_panels = [
        FieldPanel(
            "card_title",
            help_text=("Title displayed when this page is "
                       "represented by a card in a list of items. "
                       "If blank, the page's title is used."),
        ),
        FieldPanel(
            "card_description",
            help_text=("Summary text displayed when this page is "
                       "represented by a card in a list of items. "
                       "If blank, the page's description is used."),
        ),
        MultiFieldPanel(
            [ImageChooserPanel("card_image")],
            heading="16:9 Image",
            help_text=(
                "Image used for representing this page as a Card. "
                "Should be 16:9 aspect ratio. "
                "If not specified a fallback will be used. "
                "This image is also shown when sharing this page via social "
                "media unless a social image is specified."),
        ),
        MultiFieldPanel(
            [ImageChooserPanel("card_image_3_2")],
            heading="3:2 Image",
            help_text=("Image used for representing this page as a Card. "
                       "Should be 3:2 aspect ratio. "
                       "If not specified a fallback will be used. "),
        ),
    ]

    # Meta panels
    meta_panels = [
        FieldPanel(
            "nav_description",
            help_text=
            "Text to display in the navigation with the title for this page.",
        ),
        MultiFieldPanel(
            [FieldPanel("icon")],
            heading="Theme",
            help_text=
            ("This icon will be used if, for example, this page is shown in a Menu"
             ),
        ),
        MultiFieldPanel(
            [
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                ImageChooserPanel("social_image"),
                FieldPanel("keywords"),
            ],
            heading="SEO",
            help_text=("Optional fields to override the default title and "
                       "description for SEO purposes"),
        ),
    ]

    # Settings panels
    settings_panels = BasePage.settings_panels + [
        FieldPanel("slug"),
        FieldPanel("show_in_menus"),
    ]

    # Tabs
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(card_panels, heading="Card"),
        ObjectList(meta_panels, heading="Meta"),
        ObjectList(settings_panels, heading="Settings", classname="settings"),
    ])
class Navbar(models.Model):
    class Meta:
        abstract = True

    TITLE_POSITION = [
        ('', 'Inherit'),
        ('left', 'Left'),
        ('center', 'Center'),
        ('right', 'Right'),
    ]
    title_position = models.CharField(max_length=6,
                                      choices=TITLE_POSITION,
                                      default=TITLE_POSITION[0][0],
                                      blank=True,
                                      help_text='Title position')

    navbar_color = models.CharField(
        max_length=25,
        default='',
        blank=True,
        help_text='Navbar Color (Uses Parent Page if blank)')
    navbar_links = StreamField(
        [('links', LinkBlock())],
        blank=True,
        help_text='Navbar navigation links (Uses Parent Page if blank)')
    sidebar_links = StreamField(
        [('links', LinkBlock())],
        blank=True,
        help_text="Sidebar navigation links (Uses Navbar links if blank).")

    promote_panels = [
        MultiFieldPanel([
            FieldRowPanel(
                [FieldPanel('title_position'),
                 FieldPanel('navbar_color')]),
            StreamFieldPanel('navbar_links'),
        ],
                        heading='Navbar Fields',
                        classname='collapsible collapsed'),
        MultiFieldPanel([
            StreamFieldPanel('sidebar_links'),
        ],
                        heading='Sidebar (Mobile) Links',
                        classname='collapsible collapsed'),
    ]

    def title_pos(self):
        if self.title_position:
            return self.title_position
        try:
            return self.get_parent().specific.title_pos()
        except:
            return self.title_position or 'center'

    def color(self):
        color = self.navbar_color
        if not color:
            try:
                color = self.get_parent().specific.color()
            except:
                color = self.navbar_color

        # Make the color be the last element for -text (Ex: 'cyan lighten-4' changed to 'lighten-4 cyan' for cyan-text
        cs = color.split(' ')
        if len(cs) >= 2:
            color = ' '.join((*cs[1:], cs[0]))

        return color

    def nav_links(self):
        if self.navbar_links:
            return self.navbar_links
        try:
            return self.get_parent().specific.nav_links()
        except AttributeError:
            return []

    def sidenav_links(self):
        if self.sidebar_links:
            return self.sidebar_links
        try:
            parent = self.get_parent().specific
            if parent.sidebar_links:
                return parent.sidebar_links
        except AttributeError:
            pass
        return self.nav_links()
Beispiel #19
0
class HomePage(Page):
    city = models.CharField(null=True, blank=False, max_length=255)
    zip_code = models.CharField(null=True, blank=False, max_length=255)
    address = models.CharField(null=True, blank=False, max_length=255)
    telephone = models.CharField(null=True, blank=False, max_length=255)
    telefax = models.CharField(null=True, blank=False, max_length=255)
    vat_number = models.CharField(null=True, blank=False, max_length=255)
    whatsapp_telephone = models.CharField(null=True, blank=True, max_length=255)
    whatsapp_contactline = models.CharField(null=True, blank=True, max_length=255)
    tax_id = models.CharField(null=True, blank=False, max_length=255)
    trade_register_number = models.CharField(null=True, blank=False, max_length=255)
    court_of_registry = models.CharField(null=True, blank=False, max_length=255)
    place_of_registry = models.CharField(null=True, blank=False, max_length=255)
    trade_register_number = models.CharField(null=True, blank=False, max_length=255)
    ownership = models.CharField(null=True, blank=False, max_length=255)
    email = models.CharField(null=True, blank=False, max_length=255)

    copyrightholder = models.CharField(null=True, blank=False, max_length=255)

    about = RichTextField(null=True, blank=False)
    privacy = RichTextField(null=True, blank=False)

    sociallinks = StreamField([
        ('link', blocks.URLBlock(help_text="Important! Format https://www.domain.tld/xyz"))
    ])

    array = []
    def sociallink_company(self):
        for link in self.sociallinks:
            self.array.append(str(link).split(".")[1])
        return self.array


    headers = StreamField([
        ('h_hero', _H_HeroBlock(null=True, blank=False, icon='image')),
        ('code', blocks.RawHTMLBlock(null=True, blank=True, classname="full", icon='code'))
    ], null=True, blank=False)

    sections = StreamField([
        ('s_why', _S_WhyBlock(null=True, blank=False, icon='group')),
        ('s_about', _S_AboutBlock(null=True, blank=False, icon='fa-quote-left')),
        ('s_instagram', _S_InstagramBlock(null=True, blank=False, icon='fa-instagram')),
        ('s_steps', _S_StepsBlock(null=True, blank=False, icon='fa-list-ul')),
        ('s_shop', _S_ShopBlock(null=True, blank=False, icon='home')),
        ('s_trusted', _S_TrustedBlock(null=True, blank=False, icon='fa-list-ul')),
        ('s_wolf', _S_WolfBlock(null=True, blank=False, icon='fa-list-ul')),
        ('s_faq', _S_FAQBlock(null=True, blank=False, icon='home')),
        ('code', blocks.RawHTMLBlock(null=True, blank=True, classname="full", icon='code'))
    ], null=True, blank=False)

    token = models.CharField(null=True, blank=True, max_length=255)

    #graphql_fields = [
    #    GraphQLStreamfield("headers"),
    #    GraphQLStreamfield("sections"),
    #]

    main_content_panels = [
        StreamFieldPanel('headers'),
        StreamFieldPanel('sections')
    ]

    imprint_panels = [
        MultiFieldPanel(
            [
            FieldPanel('city'),
            FieldPanel('zip_code'),
            FieldPanel('address'),
            FieldPanel('telephone'),
            FieldPanel('telefax'),
            FieldPanel('whatsapp_telephone'),
            FieldPanel('whatsapp_contactline'),
            FieldPanel('email'),
            FieldPanel('copyrightholder')
            ],
            heading="contact",
        ),
        MultiFieldPanel(
            [
            FieldPanel('vat_number'),
            FieldPanel('tax_id'),
            FieldPanel('trade_register_number'),
            FieldPanel('court_of_registry'),
            FieldPanel('place_of_registry'),
            FieldPanel('trade_register_number'),
            FieldPanel('ownership')
            ],
            heading="legal",
        ),
        StreamFieldPanel('sociallinks'),
        MultiFieldPanel(
            [
            FieldPanel('about'),
            FieldPanel('privacy')
            ],
            heading="privacy",
        )
    ]

    token_panel = [
        FieldPanel('token')
    ]

    edit_handler = TabbedInterface([
        ObjectList(Page.content_panels + main_content_panels, heading='Main'),
        ObjectList(imprint_panels, heading='Imprint'),
        ObjectList(Page.promote_panels + token_panel + Page.settings_panels, heading='Settings', classname="settings")
    ])
Beispiel #20
0
class HomePage(Page):
    city = models.CharField(null=True, blank=False, max_length=255)
    zip_code = models.CharField(null=True, blank=False, max_length=255)
    address = models.CharField(null=True, blank=False, max_length=255)
    telephone = models.CharField(blank=True, max_length=255)
    vat_number = models.CharField(blank=True, max_length=255)
    email = models.CharField(blank=True, max_length=255)

    copyrightholder = models.CharField(blank=True, max_length=255)

    about = RichTextField(blank=True)
    privacy = RichTextField(blank=True)
    shipping = RichTextField(blank=True)
    gtc = RichTextField(blank=True)
    cancellation_policy = RichTextField(blank=True)

    sociallinks = StreamField([
        ('link',
         blocks.URLBlock(
             help_text="Important! Format https://www.domain.tld/xyz"))
    ])

    array = []

    def sociallink_company(self):
        for link in self.sociallinks:
            self.array.append(str(link).split(".")[1])
        return self.array

    headers = StreamField([
        ('h_hero', _H_HeroBlock(icon='image')),
        # ('code', blocks.RawHTMLBlock(null=True, blank=True, classname="full", icon='code'))
    ])

    sections = StreamField(
        [('s_feature', _S_FeatureBlock(icon='fa-info')),
         ('s_maps', _S_MapsBlock(icon='fa-info')),
         ('s_partners', _S_PartnersBlock(icon='fa-info')),
         ('s_references', _S_ReferencesBlock(icon='fa-info')),
         ('s_about', _S_AboutBlock(icon='fa-info')),
         ('s_news', _S_NewsBlock(icon='fa-info')),
         ('s_projects', _S_ProjectsBlock(icon='fa-info')),
         ('s_contentcenter', _S_ContentCenter(icon='fa-info')),
         ('s_contentright', _S_ContentRight(icon='fa-info')),
         ('s_contentleft', _S_ContentLeft(icon='fa-info'))],
        null=True,
        blank=True)

    # footers = StreamField([
    # ], null=True, blank=False)

    token = models.CharField(null=True, blank=True, max_length=255)

    #graphql_fields = [
    #    GraphQLStreamfield("headers"),
    #    GraphQLStreamfield("sections"),
    #]

    main_content_panels = [
        StreamFieldPanel('headers'),
        StreamFieldPanel('sections'),
        # StreamFieldPanel('footers')
    ]

    imprint_panels = [
        MultiFieldPanel(
            [
                FieldPanel('city'),
                FieldPanel('zip_code'),
                FieldPanel('address'),
                FieldPanel('telephone'),
                FieldPanel('email'),
                FieldPanel('copyrightholder')
            ],
            heading="contact",
        ),
        MultiFieldPanel(
            [FieldPanel('vat_number')],
            heading="legal",
        ),
        StreamFieldPanel('sociallinks'),
        MultiFieldPanel(
            [
                FieldPanel('about'),
                FieldPanel('privacy'),
                FieldPanel('shipping'),
                FieldPanel('gtc'),
                FieldPanel('cancellation_policy'),
            ],
            heading="terms",
        )
    ]

    token_panel = [FieldPanel('token')]

    edit_handler = TabbedInterface([
        ObjectList(Page.content_panels + main_content_panels, heading='Main'),
        ObjectList(imprint_panels, heading='Imprint'),
        ObjectList(Page.promote_panels + token_panel + Page.settings_panels,
                   heading='Settings',
                   classname="settings")
    ])

    preview_modes = []
Beispiel #21
0
class FlexPage(Page):
    body = StreamField(get_all_fields(), null=True)

    content_panels = Page.content_panels + [StreamFieldPanel('body')]
Beispiel #22
0
class Person(BasePage):
    resource_type = "person"
    parent_page_types = ["People"]
    subpage_types = []
    template = "person.html"

    # Content fields
    nickname = CharField(max_length=250, null=True, blank=True)
    job_title = CharField(max_length=250)
    role = CharField(max_length=250, choices=ROLE_CHOICES, default="staff")
    description = RichTextField(
        "About",
        blank=True,
        default="",
        features=RICH_TEXT_FEATURES_SIMPLE,
        help_text="Optional ‘About me’ section content, supports rich text",
    )

    # Card fields
    card_title = CharField("Title", max_length=140, blank=True, default="")
    card_description = TextField("Description",
                                 max_length=400,
                                 blank=True,
                                 default="")
    card_image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
        verbose_name="Image",
        help_text="An image in 16:9 aspect ratio",
    )

    # Meta
    city = CharField(max_length=250, blank=True, default="")
    country = CountryField(verbose_name="Country or Region",
                           blank=True,
                           default="")
    twitter = CharField(max_length=250, blank=True, default="")
    facebook = CharField(max_length=250, blank=True, default="")
    linkedin = CharField(max_length=250, blank=True, default="")
    github = CharField(max_length=250, blank=True, default="")
    email = CharField(max_length=250, blank=True, default="")
    websites = StreamField(
        StreamBlock([("website", PersonalWebsiteBlock())],
                    max_num=3,
                    required=False),
        null=True,
        blank=True,
        help_text="Optional links to any other personal websites",
    )
    keywords = ClusterTaggableManager(through=PersonTag, blank=True)

    # Content panels
    content_panels = [
        MultiFieldPanel(
            [
                CustomLabelFieldPanel("title", label="Full name"),
                FieldPanel("nickname"),
                FieldPanel("job_title"),
                FieldPanel("role"),
            ],
            heading="Details",
        ),
        FieldPanel("description"),
    ]

    # Card panels
    card_panels = [
        FieldPanel("card_title"),
        FieldPanel("card_description"),
        MultiFieldPanel(
            [ImageChooserPanel("card_image")],
            heading="16:9 Image",
            help_text=(
                "Image used for representing this page as a Card. "
                "Should be 16:9 aspect ratio. "
                "If not specified a fallback will be used. "
                "This image is also shown when sharing this page via social "
                "media unless a social image is specified."),
        ),
    ]

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [FieldPanel("city"), FieldPanel("country")],
            heading="Location",
            help_text=("Location fields. The country field is also filterable "
                       "via the people directory page."),
        ),
        MultiFieldPanel([InlinePanel("topics")],
                        heading="Topics this person specializes in"),
        MultiFieldPanel(
            [
                FieldPanel("twitter"),
                FieldPanel("facebook"),
                FieldPanel("linkedin"),
                FieldPanel("github"),
                FieldPanel("email"),
            ],
            heading="Profiles",
            help_text="",
        ),
        StreamFieldPanel("websites"),
        MultiFieldPanel(
            [
                FieldPanel("seo_title"),
                FieldPanel("search_description"),
                ImageChooserPanel("social_image"),
                FieldPanel("keywords"),
            ],
            heading="SEO",
            help_text=(
                "Optional fields to override the default title and description "
                "for SEO purposes"),
        ),
    ]

    # Settings panels
    settings_panels = BasePage.settings_panels + [FieldPanel("slug")]

    # Tabs
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(card_panels, heading="Card"),
        ObjectList(meta_panels, heading="Meta"),
        ObjectList(settings_panels, heading="Settings", classname="settings"),
    ])

    @property
    def display_title(self):
        """
        Return the display title for profile pages. Adds a nickname to the
        person's full name when one is provided.
        """
        return f'{self.title} aka "{self.nickname}"' if self.nickname else self.title

    @property
    def events(self):
        """
        Return upcoming events where this person is a speaker,
        ordered by start date
        """
        from ..events.models import Event

        upcoming_events = Event.published_objects.filter(
            start_date__gte=get_past_event_cutoff())

        speaker_events = Event.published_objects.none()

        for event in upcoming_events.all():
            # add the event to the list if the current person is a speaker
            if event.has_speaker(self):
                speaker_events = speaker_events | Event.published_objects.page(
                    event)

        return speaker_events.order_by("start_date")

    @property
    def articles(self):
        """
        Return articles and external articles where this person is (one of) the authors,
        ordered by article date, most recent first
        """
        from ..articles.models import Article
        from ..externalcontent.models import ExternalArticle

        articles = Article.published_objects.none()
        external_articles = ExternalArticle.published_objects.none()

        all_articles = Article.published_objects.all()
        all_external_articles = ExternalArticle.published_objects.all()

        for article in all_articles:
            if article.has_author(self):
                articles = articles | Article.published_objects.page(article)

        for external_article in all_external_articles:
            if external_article.has_author(self):
                external_articles = external_articles | (
                    ExternalArticle.published_objects.page(external_article))

        return sorted(chain(articles, external_articles),
                      key=attrgetter("date"),
                      reverse=True)

    @property
    def videos(self):
        """
        Return the most recent videos and external videos where this person is (one of)
        the speakers.
        """
        from ..videos.models import Video
        from ..externalcontent.models import ExternalVideo

        videos = Video.published_objects.none()
        external_videos = ExternalVideo.published_objects.none()

        all_videos = Video.published_objects.all()
        all_external_videos = ExternalVideo.published_objects.all()

        for video in all_videos:
            if video.has_speaker(self):
                videos = videos | Video.published_objects.page(video)

        for external_video in all_external_videos:
            if external_video.has_speaker(self):
                external_videos = external_videos | (
                    ExternalVideo.published_objects.page(external_video))

        return sorted(chain(videos, external_videos),
                      key=attrgetter("date"),
                      reverse=True)

    @property
    def role_group(self):
        return {
            "slug": self.role,
            "title": dict(ROLE_CHOICES).get(self.role, "")
        }

    @property
    def country_group(self):
        return ({
            "slug": self.country.code.lower(),
            "title": self.country.name
        } if self.country else {
            "slug": ""
        })

    def get_topics(self) -> List:
        """Return the live/published Topic pages associated with this Person"""

        # Note that we do this in Python because django-modelcluster won't support
        # `filter(topic__live=True)` when _previewing_ pages (even tho it'll work
        # on saved ones)
        topics = [pt.topic for pt in self.topics.all()]
        return [t for t in topics if t.live]
Beispiel #23
0
class BlogDetailPage(BannerPage):
    template = "blog/post.html"
    subpage_types = []
    parent_page_type = [
        "blog.BlogListingPage",
    ]

    author = models.ForeignKey(
        BlogAuthor,
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
    )

    notify_newsletter_subscribers = models.BooleanField(
        default=False,
        verbose_name="Newsletter",
    )

    notify_telegram_subscribers = models.BooleanField(
        default=False,
        verbose_name="Telegram",
    )

    content = StreamField(
        [
            ("richtext", blocks.RichTextBlock()),
            ("image", blocks.FigureBlock()),
            ("code", blocks.CodeFragmentBlock()),
            ("HTML", RawHTMLBlock(icon="fa-html5")),
            ("Terminal", TerminalBlock()),
            ("latex", blocks.MathBlock()),
            ("blockquote", blocks.BlockQuoteBlock()),
            ("youtube", blocks.YouTubeBlock()),
        ],
        blank=True,
    )

    content_panels = BannerPage.content_panels + [
        SnippetChooserPanel("author"),
        StreamFieldPanel("content"),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(BannerPage.promote_panels, heading="Promote"),
        ObjectList(
            BannerPage.settings_panels + [
                MultiFieldPanel(
                    [
                        FieldPanel("notify_newsletter_subscribers"),
                        FieldPanel("notify_telegram_subscribers"),
                    ],
                    heading="Notification Channels",
                    help_text=
                    "Choose which channels to notifiy about this blog post.",
                )
            ],
            heading="Settings",
        ),
    ])
Beispiel #24
0
class HomePage(Page):
    """
    The Home Page. This looks slightly more complicated than it is. You can
    see if you visit your site and edit the homepage that it is split between
    a:
    - Hero area
    - Body area
    - A promotional area
    - Moveable featured site sections
    """

    # Hero section of HomePage
    image = models.ForeignKey('wagtailimages.Image',
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL,
                              related_name='+',
                              help_text='Homepage image')
    hero_text = models.CharField(
        max_length=255, help_text='Write an introduction for the bakery')
    hero_cta = models.CharField(verbose_name='Hero CTA',
                                max_length=255,
                                help_text='Text to display on Call to Action')
    hero_cta_link = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Hero CTA link',
        help_text='Choose a page to link to for the Call to Action')

    # Body section of the HomePage
    body = StreamField(BaseStreamBlock(),
                       verbose_name="Home content block",
                       blank=True)

    # Promo section of the HomePage
    promo_image = models.ForeignKey('wagtailimages.Image',
                                    null=True,
                                    blank=True,
                                    on_delete=models.SET_NULL,
                                    related_name='+',
                                    help_text='Promo image')
    promo_title = models.CharField(
        null=True,
        blank=True,
        max_length=255,
        help_text='Title to display above the promo copy')
    promo_text = RichTextField(null=True,
                               blank=True,
                               help_text='Write some promotional copy')

    # Featured sections on the HomePage
    # You will see on templates/base/home_page.html that these are treated
    # in different ways, and displayed in different areas of the page.
    # Each list their children items that we access via the children function
    # that we define on the individual Page models e.g. BlogIndexPage
    featured_section_1_title = models.CharField(
        null=True,
        blank=True,
        max_length=255,
        help_text='Title to display above the promo copy')
    featured_section_1 = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='First featured section for the homepage. Will display up to '
        'three child items.',
        verbose_name='Featured section 1')

    featured_section_2_title = models.CharField(
        null=True,
        blank=True,
        max_length=255,
        help_text='Title to display above the promo copy')
    featured_section_2 = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Second featured section for the homepage. Will display up to '
        'three child items.',
        verbose_name='Featured section 2')

    featured_section_3_title = models.CharField(
        null=True,
        blank=True,
        max_length=255,
        help_text='Title to display above the promo copy')
    featured_section_3 = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Third featured section for the homepage. Will display up to '
        'six child items.',
        verbose_name='Featured section 3')

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('image'),
            FieldPanel('hero_text', classname="full"),
            MultiFieldPanel([
                FieldPanel('hero_cta'),
                PageChooserPanel('hero_cta_link'),
            ]),
        ],
                        heading="Hero section"),
        MultiFieldPanel([
            ImageChooserPanel('promo_image'),
            FieldPanel('promo_title'),
            FieldPanel('promo_text'),
        ],
                        heading="Promo section"),
        StreamFieldPanel('body'),
        MultiFieldPanel([
            MultiFieldPanel([
                FieldPanel('featured_section_1_title'),
                PageChooserPanel('featured_section_1'),
            ]),
            MultiFieldPanel([
                FieldPanel('featured_section_2_title'),
                PageChooserPanel('featured_section_2'),
            ]),
            MultiFieldPanel([
                FieldPanel('featured_section_3_title'),
                PageChooserPanel('featured_section_3'),
            ]),
        ],
                        heading="Featured homepage sections",
                        classname="collapsible")
    ]

    api_fields = [
        APIField('image'),
        APIField('body'),
    ]

    def __str__(self):
        return self.title
Beispiel #25
0
class Events(Page):
    parent_page_types = ['home.HomePage']
    subpage_types = ['events.Event']
    template = 'events.html'

    # Content fields
    featured = StreamField(
        StreamBlock([
            ('event',
             PageChooserBlock(target_model=(
                 'events.Event',
                 'externalcontent.ExternalEvent',
             ))),
            ('external_page', FeaturedExternalBlock()),
        ],
                    max_num=1,
                    required=False),
        null=True,
        blank=True,
        help_text='Optional space to show a featured event',
    )

    # Meta fields
    keywords = ClusterTaggableManager(through=EventsTag, blank=True)

    # Content panels
    content_panels = Page.content_panels + [StreamFieldPanel('featured')]

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [
                FieldPanel('seo_title'),
                FieldPanel('search_description'),
                FieldPanel('keywords'),
            ],
            heading='SEO',
            help_text=
            'Optional fields to override the default title and description for SEO purposes'
        ),
    ]

    # Settings panels
    settings_panels = [
        FieldPanel('slug'),
        FieldPanel('show_in_menus'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(meta_panels, heading='Meta'),
        ObjectList(settings_panels, heading='Settings', classname='settings'),
    ])

    class Meta:
        verbose_name_plural = 'Events'

    @classmethod
    def can_create_at(cls, parent):
        # Allow only one instance of this page type
        return super().can_create_at(parent) and not cls.objects.exists()

    def get_context(self, request):
        context = super().get_context(request)
        context['filters'] = self.get_filters()
        return context

    @property
    def events(self):
        """Return events in chronological order"""
        return get_combined_events(self)

    def get_filters(self):
        from ..topics.models import Topic
        return {
            'months': True,
            'topics': Topic.objects.live().public().order_by('title'),
        }
Beispiel #26
0
class ServicePage(Page, ContentPageMixin):
    date = models.DateField("Service date")
    description = wtfields.RichTextField(
        blank=True,
        default=
        "Please join us for our Sunday service as we worship and listen to God's word.",
    )
    stream_link = models.URLField(default="", blank=True)
    public_stream_link = models.URLField(default="", blank=True)
    chat_enabled = models.BooleanField(default=True)
    weekly_theme = models.CharField(max_length=128, default="", blank=True)

    bulletin = wtfields.StreamField(
        [
            ("bulletin_section",
             BulletinSectionBlock(name="Bulletin Section")),
        ],
        blank=True,
    )

    # service = wtfields.StreamField([
    #     ('worship_section', WorshipSectionBlock(name="Worship Section")),
    #     ('announcements_section', AnnouncementsSectionBlock(name="Announcement Section")),
    #     ('sermon_section', SermonSectionBlock(name="Sermon Section")),
    #     ('discussion_section', DiscussionSectionBlock(name="Discussion Section")),
    #     # TODO
    #     # - polls/voting?
    #     # - feedback
    #     # - discussion
    # ])

    @property
    def getdescription(self):
        return self.description

    content_panels = Page.content_panels + [
        FieldPanel("date"),
        FieldPanel("stream_link"),
        FieldPanel("public_stream_link"),
        FieldPanel("description"),
        InlinePanel("documents", label="Documents"),
        FieldPanel("chat_enabled"),
        StreamFieldPanel("bulletin"),
        FieldPanel("weekly_theme"),
    ]

    prayer_requests = models.ManyToManyField(pr_models.PrayerRequest,
                                             related_name="services_pages")

    def child_pages(self):
        pages = DailyReadingPage.objects.live().descendant_of(self).order_by(
            "-date")
        return pages

    @classmethod
    def current_service_page(cls):
        return cls.objects.all().order_by("date").last()

    def add_prayer_request(self, pr):
        self.prayer_requests.add(pr)

    @property
    def email_attachments(self):
        return [
            doclink.document.file.file for doclink in self.documents.all()
            if doclink.include_in_email
        ]

    def get_context(self, request):
        context = super().get_context(request)
        context["self"] = self
        context["docs"] = self.documents.all()
        return context
Beispiel #27
0
            query_string=query_string,
            # TODO blog_feed_title=feed_settings.blog_feed_title
        )
        return context

    def serve_preview(self, request, mode_name):
        """ This is another hack to overcome the MRO issue we were seeing """
        return BibliographyMixin.serve_preview(self, request, mode_name)

    class Meta:
        verbose_name = "IESG Statement Page"

IESGStatementPage.content_panels = Page.content_panels + [
    FieldPanel('date_published'),
    FieldPanel('introduction'),
    StreamFieldPanel('body'),
    InlinePanel('topics', label="Topics"),
]

IESGStatementPage.promote_panels = Page.promote_panels + PromoteMixin.panels


class IESGStatementIndexPage(RoutablePageMixin, Page):

    def get_context(self, request):
        context = super().get_context(request)
        context['statements'] = IESGStatementPage.objects.child_of(self).live().annotate(
            d=Coalesce('date_published', 'first_published_at')
        ).order_by('-d')
        return context
Beispiel #28
0
class BlogPage(RoutablePageMixin, Page):
    subtitle = models.CharField(max_length=255, null=True, blank=True)
    main_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')
    date = models.DateField("Post date", null=True, blank=True)
    intro = models.CharField(max_length=250, null=True, blank=True)
    body = StreamField([
        ('heading', CharBlock(classname="full title", icon='title')),
        ('paragraph', RichTextBlock(icon='pilcrow')),
        ('image', ImageChooserBlock(icon='image')),
        ('codeblock', TextBlock(icon='cogs')),
        ('markdown', MarkDownBlock()),
        ('real_codeblock', CodeBlock()),
    ],
                       blank=True,
                       null=True)
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
    listing_intro = RichTextField(null=True, blank=True)
    listing_image = models.ForeignKey('wagtailimages.Image',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL,
                                      related_name='+')

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

    content_panels = Page.content_panels + [
        FieldPanel('subtitle'),
        ImageChooserPanel('main_image'),
        FieldPanel('date'),
        FieldPanel('intro'),
        StreamFieldPanel('body'),
        FieldPanel('tags'),
    ]

    promote_panels = Page.promote_panels + [
        FieldPanel('listing_intro'),
        ImageChooserPanel('listing_image'),
    ]

    @property
    def home_page(self):
        return self.get_parent()

    @property
    def next_blog(self):
        blogs = BlogPage.objects.filter(live=True).order_by('-date')
        current_index = blogs.index(self)

    def get_absolute_url(self):
        return self.full_url

    @route(r'^$', name='normal_blog')
    def normal_blog(self, request):
        site_root = self.get_parent()

        return render(request, self.template, {
            'self': self,
        })

    @route(r'^amp/$', name='amp_blog')
    def amp_blog(self, request):
        context = self.get_context(request)
        context['is_amp'] = True
        context['base_template'] = 'base_amp.html'
        response = TemplateResponse(request, self.template, context)
        return response
Beispiel #29
0
class LocationPage(Page):
    """
    Detail for a specific bakery location.
    """
    introduction = models.TextField(
        help_text='Text to describe the page',
        blank=True)
    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Landscape mode only; horizontal width between 1000px and 3000px.'
    )
    body = StreamField(
        BaseStreamBlock(), verbose_name="Page body", blank=True
    )
    address = models.TextField()
    lat_long = models.CharField(
        max_length=36,
        help_text="Comma separated lat/long. (Ex. 64.144367, -21.939182) \
                   Right click Google Maps and select 'What\'s Here'",
        validators=[
            RegexValidator(
                regex=r'^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$',
                message='Lat Long must be a comma-separated numeric lat and long',
                code='invalid_lat_long'
            ),
        ]
    )

    # Search index configuration
    search_fields = Page.search_fields + [
        index.SearchField('address'),
        index.SearchField('body'),
    ]

    # Fields to show to the editor in the admin view
    content_panels = [
        FieldPanel('title', classname="full"),
        FieldPanel('introduction', classname="full"),
        ImageChooserPanel('image'),
        StreamFieldPanel('body'),
        FieldPanel('address', classname="full"),
        FieldPanel('lat_long'),
        InlinePanel('hours_of_operation', label="Hours of Operation"),
    ]

    def __str__(self):
        return self.title

    @property
    def operating_hours(self):
        hours = self.hours_of_operation.all()
        return hours

    # Determines if the location is currently open. It is timezone naive
    def is_open(self):
        now = datetime.now()
        current_time = now.time()
        current_day = now.strftime('%a').upper()
        try:
            self.operating_hours.get(
                day=current_day,
                opening_time__lte=current_time,
                closing_time__gte=current_time
            )
            return True
        except LocationOperatingHours.DoesNotExist:
            return False

    # Makes additional context available to the template so that we can access
    # the latitude, longitude and map API key to render the map
    def get_context(self, request):
        context = super(LocationPage, self).get_context(request)
        context['lat'] = self.lat_long.split(",")[0]
        context['long'] = self.lat_long.split(",")[1]
        context['google_map_api_key'] = settings.GOOGLE_MAP_API_KEY
        return context

    # Can only be placed under a LocationsIndexPage object
    parent_page_types = ['LocationsIndexPage']
Beispiel #30
0
class DefaultRichBlockFieldPage(Page):
    body = StreamField([
        ('rich_text', RichTextBlock()),
    ])

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