Example #1
0
class EventPage(Page):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    AUDIENCE_CHOICES = (
        ("public", "Public"),
        ("private", "Private"),
    )

    date_from = models.DateField("Start date")
    date_to = models.DateField(
        "End date",
        null=True,
        blank=True,
        help_text="Not required if event is on a single day",
    )
    time_from = models.TimeField("Start time", null=True, blank=True)
    time_to = models.TimeField("End time", null=True, blank=True)
    audience = models.CharField(max_length=255, choices=AUDIENCE_CHOICES)
    location = models.CharField(max_length=255)
    body = RichTextField(blank=True)
    cost = models.CharField(max_length=255)
    signup_link = models.URLField(blank=True)
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    api_fields = (
        "date_from",
        "date_to",
        "time_from",
        "time_to",
        "audience",
        "location",
        "body",
        "cost",
        "signup_link",
        "feed_image",
        "carousel_items",
        "related_links",
        "speakers",
    )

    search_fields = Page.search_fields + [
        index.SearchField("get_audience_display"),
        index.SearchField("location"),
        index.SearchField("body"),
    ]

    def get_event_index(self):
        # Find closest ancestor which is an event index
        return EventIndexPage.objects.ancester_of(self).last()
Example #2
0
class RichTextSection(models.Model):
    snippet = ParentalKey("MultiSectionRichTextSnippet",
                          related_name="sections",
                          on_delete=models.CASCADE)
    body = RichTextField()

    panels = [
        FieldPanel("body"),
    ]
Example #3
0
class EventPage(Page):
    date_from = models.DateField("Start date", null=True)
    date_to = models.DateField(
        "End date",
        null=True,
        blank=True,
        help_text="Not required if event is on a single day",
    )
    time_from = models.TimeField("Start time", null=True, blank=True)
    time_to = models.TimeField("End time", null=True, blank=True)
    audience = models.CharField(max_length=255, choices=EVENT_AUDIENCE_CHOICES)
    location = models.CharField(max_length=255)
    body = RichTextField(blank=True)
    cost = models.CharField(max_length=255)
    signup_link = models.URLField(blank=True)
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    categories = ParentalManyToManyField(EventCategory, blank=True)

    search_fields = [
        index.SearchField("get_audience_display"),
        index.SearchField("location"),
        index.SearchField("body"),
        index.FilterField("url_path"),
    ]

    password_required_template = "tests/event_page_password_required.html"
    base_form_class = EventPageForm

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("date_from"),
        FieldPanel("date_to"),
        FieldPanel("time_from"),
        FieldPanel("time_to"),
        FieldPanel("location"),
        FieldPanel("audience"),
        FieldPanel("cost"),
        FieldPanel("signup_link"),
        InlinePanel("carousel_items", label="Carousel items"),
        FieldPanel("body", classname="full"),
        InlinePanel("speakers", label="Speakers", heading="Speaker lineup"),
        InlinePanel("related_links", label="Related links"),
        FieldPanel("categories"),
        # InlinePanel related model uses `pk` not `id`
        InlinePanel("head_counts", label="Head Counts"),
    ]

    promote_panels = [
        MultiFieldPanel(COMMON_PANELS, "Common page configuration"),
        FieldPanel("feed_image"),
    ]
Example #4
0
class CustomDocument(AbstractDocument):
    description = models.TextField(blank=True)
    fancy_description = RichTextField(blank=True)
    admin_form_fields = Document.admin_form_fields + (
        "description",
        "fancy_description",
    )

    class Meta:
        unique_together = [("title", "collection")]
Example #5
0
class CustomImage(AbstractImage):
    caption = models.CharField(max_length=255, blank=True)
    fancy_caption = RichTextField(blank=True)
    not_editable_field = models.CharField(max_length=255, blank=True)

    admin_form_fields = Image.admin_form_fields + (
        "caption",
        "fancy_caption",
    )

    class Meta:
        unique_together = [("title", "collection")]
Example #6
0
class FormClassAdditionalFieldPage(Page):
    location = models.CharField(max_length=255)
    body = RichTextField(blank=True)

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("location"),
        FieldPanel("body"),
        FieldPanel("code"),  # not in model, see set base_form_class
    ]

    base_form_class = FormClassAdditionalFieldPageForm
Example #7
0
class PersonPage(Page, ContactFieldsMixin):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    intro = RichTextField(blank=True)
    biography = RichTextField(blank=True)
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    api_fields = (
        "first_name",
        "last_name",
        "intro",
        "biography",
        "image",
        "feed_image",
        "related_links",
    ) + ContactFieldsMixin.api_fields

    search_fields = Page.search_fields + [
        index.SearchField("first_name"),
        index.SearchField("last_name"),
        index.SearchField("intro"),
        index.SearchField("biography"),
    ]
Example #8
0
class CommitteesPage(MenuPage):
    subpage_types = ["CommitteePage"]
    description = RichTextField(null=True, blank=True)

    content_panels = Page.content_panels + [
        FieldPanel("description"),
    ]

    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        committees = CommitteePage.objects.all().order_by("title")
        context["committees"] = committees

        return context
Example #9
0
class FormPageWithCustomSubmissionListView(AbstractEmailForm):
    """Form Page with customised submissions listing view"""

    intro = RichTextField(blank=True)
    thank_you_text = RichTextField(blank=True)

    def get_submissions_list_view_class(self):
        from .views import CustomSubmissionsListView

        return CustomSubmissionsListView

    def get_submission_class(self):
        return CustomFormPageSubmission

    def get_data_fields(self):
        data_fields = [
            ("useremail", "User email"),
        ]
        data_fields += super().get_data_fields()

        return data_fields

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("intro", classname="full"),
        InlinePanel("form_fields", label="Form fields"),
        FieldPanel("thank_you_text", classname="full"),
        MultiFieldPanel(
            [
                FieldPanel("to_address", classname="full"),
                FieldPanel("from_address", classname="full"),
                FieldPanel("subject", classname="full"),
            ],
            "Email",
        ),
    ]
Example #10
0
class InfoPage(Page):
    body = RichTextField(blank=True)
    additional_content = StreamField(
        [("embed", blocks.RawHTMLBlock())],
        null=True,
        blank=True,
        use_json_field=True,
    )

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

    content_panels = Page.content_panels + [
        FieldPanel("body", classname="full"),
        FieldPanel("additional_content"),
    ]
Example #11
0
class ManyToManyBlogPage(Page):
    """
    A page type with two different kinds of M2M relation.
    We don't formally support these, but we don't want them to cause
    hard breakages either.
    """

    body = RichTextField(blank=True)
    adverts = models.ManyToManyField(Advert, blank=True)
    blog_categories = models.ManyToManyField(BlogCategory,
                                             through=BlogCategoryBlogPage,
                                             blank=True)

    # make first_published_at editable on this page model
    settings_panels = Page.settings_panels + [
        FieldPanel("first_published_at"),
    ]
Example #12
0
class HomePage(Page):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    body = RichTextField(blank=True)

    api_fields = (
        "body",
        "carousel_items",
        "related_links",
    )

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

    class Meta:
        verbose_name = "homepage"
Example #13
0
class BlogIndexPage(Page):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    intro = RichTextField(blank=True)

    api_fields = (
        "intro",
        "related_links",
    )

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

    def get_blog_entries(self):
        # Get list of live blog pages that are descendants of this page
        entries = BlogEntryPage.objects.descendant_of(self).live()

        # Order by most recent date first
        entries = entries.order_by("-date")

        return entries

    def get_context(self, request):
        # Get blog entries
        entries = self.get_blog_entries()

        # Filter by tag
        tag = request.GET.get("tag")
        if tag:
            entries = entries.filter(tags__name=tag)

        paginator = Paginator(entries, per_page=10)
        entries = paginator.get_page(request.GET.get("page"))

        # Update template context
        context = super().get_context(request)
        context["entries"] = entries
        return context
Example #14
0
class ContactPage(Page, ContactFieldsMixin):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    body = RichTextField(blank=True)
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    api_fields = (
        "body",
        "feed_image",
    ) + ContactFieldsMixin.api_fields

    search_fields = Page.search_fields + [
        index.SearchField("body"),
    ]
Example #15
0
class StandardIndexPage(Page):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    intro = RichTextField(blank=True)
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    api_fields = (
        "intro",
        "feed_image",
        "related_links",
    )

    search_fields = Page.search_fields + [
        index.SearchField("intro"),
    ]
Example #16
0
class BlogEntryPage(Page):
    page_ptr = models.OneToOneField(Page,
                                    parent_link=True,
                                    related_name="+",
                                    on_delete=models.CASCADE)
    body = RichTextField()
    tags = ClusterTaggableManager(through="BlogEntryPageTag", blank=True)
    date = models.DateField("Post date")
    feed_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    api_fields = (
        APIField("body"),
        APIField("tags"),
        APIField("date"),
        APIField("feed_image"),
        APIField(
            "feed_image_thumbnail",
            serializer=ImageRenditionField("fill-300x300",
                                           source="feed_image"),
        ),
        APIField("carousel_items"),
        APIField("related_links"),
    )

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

    def get_blog_index(self):
        # Find closest ancestor which is a blog index
        return BlogIndexPage.ancestor_of(self).last()
Example #17
0
class NewsIndexPage(Page):
    message = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel("message", classname="full")
    ]
    subpage_types = [
        "news.NewsPage",  # appname.ModelName
    ]

    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        blogpages = self.get_children().live().order_by("-last_published_at")
        paginator = Paginator(blogpages, 5)
        page = request.GET.get("page")
        try:
            resources = paginator.page(page)
        except PageNotAnInteger:
            resources = paginator.page(1)
        except EmptyPage:
            resources = paginator.page(paginator.num_pages)
        context["blogpages"] = resources
        return context
Example #18
0
class FormPageWithCustomSubmission(AbstractEmailForm):
    """
    This Form page:
        * Have custom submission model
        * Have custom related_name (see `FormFieldWithCustomSubmission.page`)
        * Saves reference to a user
        * Doesn't render html form, if submission for current user is present
    """

    intro = RichTextField(blank=True)
    thank_you_text = RichTextField(blank=True)

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request)
        context["greeting"] = "hello world"
        return context

    def get_form_fields(self):
        return self.custom_form_fields.all()

    def get_data_fields(self):
        data_fields = [
            ("useremail", "User email"),
        ]
        data_fields += super().get_data_fields()

        return data_fields

    def get_submission_class(self):
        return CustomFormPageSubmission

    def process_form_submission(self, form):
        form_submission = self.get_submission_class().objects.create(
            form_data=form.cleaned_data,
            page=self,
            user=form.user,
        )

        if self.to_address:
            addresses = [x.strip() for x in self.to_address.split(",")]
            content = "\n".join([
                x[1].label + ": " + str(form.data.get(x[0]))
                for x in form.fields.items()
            ])
            send_mail(
                self.subject,
                content,
                addresses,
                self.from_address,
            )

        # process_form_submission should now return the created form_submission
        return form_submission

    def serve(self, request, *args, **kwargs):
        if (self.get_submission_class().objects.filter(
                page=self, user__pk=request.user.pk).exists()):
            return TemplateResponse(request, self.template,
                                    self.get_context(request))

        return super().serve(request, *args, **kwargs)

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("intro", classname="full"),
        InlinePanel("custom_form_fields", label="Form fields"),
        FieldPanel("thank_you_text", classname="full"),
        MultiFieldPanel(
            [
                FieldPanel("to_address", classname="full"),
                FieldPanel("from_address", classname="full"),
                FieldPanel("subject", classname="full"),
            ],
            "Email",
        ),
    ]
Example #19
0
class EventIndex(Page):
    intro = RichTextField(blank=True)
    ajax_template = "tests/includes/event_listing.html"

    def get_events(self):
        return self.get_children().live().type(EventPage)

    def get_paginator(self):
        return Paginator(self.get_events(), 4)

    def get_context(self, request, page=1):
        # Pagination
        paginator = self.get_paginator()
        try:
            events = paginator.page(page)
        except PageNotAnInteger:
            events = paginator.page(1)
        except EmptyPage:
            events = paginator.page(paginator.num_pages)

        # Update context
        context = super().get_context(request)
        context["events"] = events
        return context

    def route(self, request, path_components):
        if self.live and len(path_components) == 1:
            try:
                return self.serve(request, page=int(path_components[0]))
            except (TypeError, ValueError):
                pass

        return super().route(request, path_components)

    def get_static_site_paths(self):
        # Get page count
        page_count = self.get_paginator().num_pages

        # Yield a path for each page
        for page in range(page_count):
            yield "/%d/" % (page + 1)

        # Yield from superclass
        for path in super().get_static_site_paths():
            yield path

    def get_sitemap_urls(self, request=None):
        # Add past events url to sitemap
        return super().get_sitemap_urls(
            request=request) + [{
                "location": self.full_url + "past/",
                "lastmod": self.latest_revision_created_at,
            }]

    def get_cached_paths(self):
        return super().get_cached_paths() + ["/past/"]

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("intro", classname="full"),
    ]
Example #20
0
class CommitteePage(Page):
    parent_page_types = ["CommitteesPage"]
    subpage_types = []

    COMMITTEE = "CT"
    WORKING_GROUP = "WG"
    CAUCUS = "CU"
    PRIORITY = "PR"
    FORMATION_CHOICES = [
        (COMMITTEE, "Committee"),
        (WORKING_GROUP, "Working Group"),
        (CAUCUS, "Caucus"),
        (PRIORITY, "Priority"),
    ]

    description = RichTextField()
    formation_type = models.CharField(
        max_length=2, choices=FORMATION_CHOICES, default=""
    )
    leader = models.ForeignKey(
        Person,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="committee_leader",
    )
    leader_name = models.CharField(max_length=30, null=True)
    email = models.EmailField()
    people = models.ManyToManyField(Person, related_name="committee_member", blank=True)
    sign_up_form_endpoint = models.TextField(null=True, blank=True)

    search_fields = Page.search_fields + [index.SearchField("description")]

    content_panels = Page.content_panels + [
        FieldPanel("formation_type"),
        FieldPanel("description"),
        FieldPanel("leader_name"),
        FieldPanel("email"),
        FieldPanel("sign_up_form_endpoint"),
    ]

    def get_context(self, request):
        context = super().get_context(request)
        context["upcoming_events"] = list(self.events.filter(start__gt=datetime.now()))
        if self.sign_up_form_endpoint:
            print(self.sign_up_form_endpoint)
            print(self.slug)
            print(settings.ACTIONNETWORK_API_KEYS)
            print(settings.ACTIONNETWORK_API_KEYS.get(self.slug))
            embeds = requests.get(
                f"{self.sign_up_form_endpoint}embed",
                headers={
                    "OSDI-API-Token": settings.ACTIONNETWORK_API_KEYS.get(self.slug)
                },
            ).json()
            print(embeds)
            embed_code = embeds["embed_standard_layout_only_styles"]
        else:
            embed_code = None
        context["embed_code"] = embed_code

        return context

    def __str__(self):
        return f"{self.title.title()} {self.get_formation_type_display()}"
Example #21
0
class NewsPage(Page):
    main_story_image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    main_story_heading = models.CharField(max_length=500,
                                          null=True,
                                          blank=True)
    main_story_copy = RichTextField(blank=True)
    action_network_href = models.URLField(blank=True, null=True)
    related_stories = StreamField(
        [("related_story", RelatedStoryBlock())],
        null=True,
        blank=True,
        collapsed=False,
        default=upcoming_events_as_related_stories,
        use_json_field=True,
    )

    parent_page_type = ["news.NewsIndexPage"]  # appname.ModelName
    search_fields = Page.search_fields + [
        index.SearchField("main_story_copy"),
    ]

    content_panels = Page.content_panels + [
        FieldPanel("main_story_image", ),
        FieldPanel("main_story_heading"),
        FieldPanel("main_story_copy", classname="full"),
        FieldPanel("related_stories"),
    ]

    def save(self, *args, **kwargs):
        if self.action_network_href:
            email.edit(
                self.action_network_href,
                {
                    "subject":
                    self.title,
                    "body":
                    render_block_to_string("news/news_page.html",
                                           "content",
                                           context={"page": self}),
                    "from":
                    "STL DSA",
                    "reply_to":
                    "*****@*****.**",
                },
                settings.ACTIONNETWORK_API_KEYS["main"],
            )
        else:
            response = email.create(
                self.title,
                # main_story_html + "".join(related_stories_html),
                render_block_to_string("news/news_page.html",
                                       "content",
                                       context={"page": self}),
                "STL DSA",
                "*****@*****.**",
                settings.ACTIONNETWORK_API_KEYS["main"],
            )
            action_network_href = response.json()["_links"]["self"]["href"]
            self.action_network_href = action_network_href

        if self.go_live_at and self.go_live_at > timezone.now():
            polling.poll(
                lambda: requests.get(
                    self.action_network_href,
                    headers={
                        "OSDI-API-Token": settings.ACTIONNETWORK_API_KEYS[
                            "main"]
                    },
                ).json().get("total_targeted", 0) > 0,
                step=1,
                timeout=10,
                step_function=lambda step: step + 2,
            )
            email.schedule(
                f"{self.action_network_href}/schedule",
                self.go_live_at,
                settings.ACTIONNETWORK_API_KEYS["main"],
            )
        super().save(*args, **kwargs)  # Call the "real" save() method.
Example #22
0
class PageWithRichText(Page):
    body = RichTextField(max_length=255, blank=True, null=True)