Ejemplo n.º 1
0
class HeroSection(SectionBase, SectionTitleBlock, ButtonAction, Page):

    hero_layout = models.CharField(
        blank=True,
        max_length=100,
        verbose_name='Layout',
        choices=[('simple_centered', 'Simple centered'),
                 ('image_right', 'Image on right')],
        default='simple_centered',
    )
    hero_first_button_text = models.CharField(
        blank=True,
        max_length=100,
        verbose_name='Hero button text',
        default='Subscribe',
        help_text="Leave field empty to hide.",
    )
    hero_second_button_text = models.CharField(
        blank=True,
        max_length=100,
        verbose_name='Hero button text',
        default='Subscribe',
        help_text="Leave field empty to hide.",
    )
    hero_image = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        verbose_name='Image',
        related_name='+',
    )
    hero_image_size = models.CharField(
        max_length=50,
        choices=cr_settings['HERO_IMAGE_SIZE_CHOICES'],
        default=cr_settings['HERO_IMAGE_SIZE_CHOICES_DEFAULT'],
        verbose_name=('Image size'),
    )
    hero_action_type_1 = models.CharField(
        max_length=50,
        choices=cr_settings['HERO_ACTION_TYPE_CHOICES'],
        default=cr_settings['HERO_ACTION_TYPE_CHOICES_DEFAULT'],
        verbose_name=('Action type (First)'),
    )
    hero_action_type_2 = models.CharField(
        max_length=50,
        choices=cr_settings['HERO_ACTION_TYPE_CHOICES'],
        default=cr_settings['HERO_ACTION_TYPE_CHOICES_DEFAULT'],
        verbose_name=('Action type (Second)'),
    )
    hero_buttons = StreamField([('action_button', ActionButton()),
                                ('primary_button', PrimaryButton())],
                               null=True,
                               verbose_name="Buttons",
                               help_text="Please choose Buttons")

    # basic tab panels
    basic_panels = Page.content_panels + [
        FieldPanel('hero_layout', heading='Layout', classname="title full"),
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel('hero_layout', classname="col6"),
                    FieldPanel('hero_image_size', classname="col6"),
                ]),
                FieldRowPanel([
                    FieldPanel('section_heading',
                               heading='Heading',
                               classname="col6"),
                    FieldPanel('section_subheading',
                               heading='Subheading',
                               classname="col6"),
                ]),
                FieldRowPanel([
                    FieldPanel('section_description',
                               heading='Description',
                               classname="col6"),
                ]),
                FieldPanel('hero_first_button_text'),
                FieldPanel('hero_second_button_text'),
                ImageChooserPanel('hero_image'),
            ],
            heading='Content',
        ),
        SectionBase.section_layout_panels,
        SectionBase.section_design_panels,
    ]

    # advanced tab panels
    advanced_panels = (SectionTitleBlock.title_basic_panels,
                       ) + ButtonAction.button_action_panels

    # Register Tabs
    edit_handler = TabbedInterface([
        ObjectList(basic_panels, heading="Basic"),
        ObjectList(advanced_panels, heading="Plus+"),
    ])

    # Page settings
    template = 'sections/hero_section_preview.html'
    parent_page_types = ['home.HomePage']
    subpage_types = []

    # Overring methods
    def set_url_path(self, parent):
        """
        Populate the url_path field based on this page's slug and the specified parent page.
        (We pass a parent in here, rather than retrieving it via get_parent, so that we can give
        new unsaved pages a meaningful URL when previewing them; at that point the page has not
        been assigned a position in the tree, as far as treebeard is concerned.
        """
        if parent:
            self.url_path = ''
        else:
            # a page without a parent is the tree root, which always has a url_path of '/'
            self.url_path = '/'

        return self.url_path
Ejemplo n.º 2
0
class FlatPage(Page):
    headers = StreamField([
        ('h_hero', _H_HeroBlock(icon='image')),
        # ('code', blocks.RawHTMLBlock(null=True, blank=True, classname="full", icon='code'))
    ])

    price = models.DecimalField(verbose_name="Preis",
                                max_digits=11,
                                decimal_places=2,
                                null=True,
                                blank=False)

    br_choices = (
        ('RE', 'Miete'),
        ('BU', 'Kauf'),
    )

    buy_or_rent = models.CharField(verbose_name="Mieten oder Kaufen?",
                                   max_length=4,
                                   choices=br_choices,
                                   default='RE')
    lead = models.CharField(null=True, blank=True, max_length=512)
    available = models.BooleanField(verbose_name="Verfügbar")
    # ground_plan = ImageChooserBlock(
    #     required=True, blank=False, help_text="Raumplan")

    sections = StreamField(
        [('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)

    gallery = StreamField([('g_gallery', _G_GalleryBlock(icon='fa-info'))],
                          null=True,
                          blank=True)

    ground_plan = StreamField(
        [('p_groundplan', _P_GroundPlanBlock(icon='fa-info'))],
        null=True,
        blank=True,
        verbose_name="Grundrissplan")

    main_content_panels = [
        StreamFieldPanel('headers'),
        FieldPanel('price'),
        FieldPanel('buy_or_rent'),
        FieldPanel('lead'),
        FieldPanel('available'),
        # FieldPanel('ground_plan'),
        StreamFieldPanel('ground_plan'),
        StreamFieldPanel('sections'),
        StreamFieldPanel('gallery'),
        # StreamFieldPanel('footers')
    ]

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

    preview_modes = []
Ejemplo n.º 3
0
    FieldPanel('title', classname="full title"),
    FieldPanel('seo_title'),
    FieldPanel('slug'),
    InlinePanel('advert_placements', label="Adverts"),
]
StandardIndex.promote_panels = []


class StandardChild(Page):
    pass


# Test overriding edit_handler with a custom one
StandardChild.edit_handler = TabbedInterface([
    ObjectList(StandardChild.content_panels, heading='Content'),
    ObjectList(StandardChild.promote_panels, heading='Promote'),
    ObjectList(StandardChild.settings_panels, heading='Settings', classname='settings'),
    ObjectList([], heading='Dinosaurs'),
], base_form_class=WagtailAdminPageForm)


class BusinessIndex(Page):
    """ Can be placed anywhere, can only have Business children """
    subpage_types = ['tests.BusinessChild', 'tests.BusinessSubIndex']


class BusinessSubIndex(Page):
    """ Can be placed under BusinessIndex, and have BusinessChild children """

    # BusinessNowherePage is 'incorrectly' added here as a possible child.
    # The rules on BusinessNowherePage prevent it from being a child here though.
    subpage_types = ['tests.BusinessChild', 'tests.BusinessNowherePage']
Ejemplo n.º 4
0
class EnforcementActionPage(AbstractFilterPage):
    public_enforcement_action = models.CharField(max_length=150, blank=True)
    initial_filing_date = models.DateField(null=True, blank=True)
    settled_or_contested_at_filing = models.CharField(max_length=10,
                                                      choices=[('Settled',
                                                                'Settled'),
                                                               ('Contested',
                                                                'Contested')],
                                                      blank=True)
    court = models.CharField(default='', max_length=150, blank=True)

    content = StreamField([
        ('full_width_text', organisms.FullWidthText()),
        ('expandable', organisms.Expandable()),
        ('expandable_group', organisms.ExpandableGroup()),
        ('notification', molecules.Notification()),
        ('table_block',
         organisms.AtomicTableBlock(table_options={'renderer': 'html'})),
        ('feedback', v1_blocks.Feedback()),
    ],
                          blank=True)

    content_panels = [StreamFieldPanel('header'), StreamFieldPanel('content')]

    metadata_panels = [
        FieldPanel('public_enforcement_action'),
        FieldPanel('initial_filing_date'),
        InlinePanel('defendant_types', label='Defendant/Respondent Type'),
        InlinePanel('categories', label="Forum", min_num=1, max_num=2),
        FieldPanel('court'),
        InlinePanel('docket_numbers', label="Docket Number", min_num=1),
        FieldPanel('settled_or_contested_at_filing'),
        InlinePanel('statuses', label="Status", min_num=1),
        InlinePanel('products', label="Products"),
        InlinePanel('at_risk_groups', label="At Risk Groups"),
        InlinePanel('statutes', label="Statutes/Regulations"),
        InlinePanel('enforcement_dispositions', label='Final Disposition'),
    ]

    settings_panels = [
        MultiFieldPanel(CFGOVPage.promote_panels, 'Settings'),
        MultiFieldPanel([
            FieldPanel('preview_title'),
            FieldPanel('preview_subheading'),
            FieldPanel('preview_description'),
            FieldPanel('secondary_link_url'),
            FieldPanel('secondary_link_text'),
            ImageChooserPanel('preview_image'),
        ],
                        heading='Page Preview Fields',
                        classname='collapsible'),
        FieldPanel('authors', 'Authors'),
        MultiFieldPanel([
            FieldPanel('date_published'),
            FieldPanel('comments_close_by'),
        ],
                        'Relevant Dates',
                        classname='collapsible'),
        MultiFieldPanel(Page.settings_panels, 'Scheduled Publishing'),
        FieldPanel('language', 'Language'),
        MultiFieldPanel(CFGOVPage.archive_panels, 'Archive'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(AbstractFilterPage.content_panels + content_panels,
                   heading='General Content'),
        ObjectList(metadata_panels, heading='Metadata'),
        ObjectList(CFGOVPage.sidefoot_panels, heading='Sidebar'),
        ObjectList(settings_panels, heading='Configuration')
    ])

    template = 'enforcement-action/index.html'

    objects = PageManager()

    search_fields = AbstractFilterPage.search_fields + [
        index.SearchField('content')
    ]

    @classmethod
    def all_actions(cls):
        # Return the collection of all Enforcement Action Pages.
        # Exclude any pages in the Trash or otherwise not a child of the
        # EnforcementActionsFilterPage.
        try:
            # TODO: find a less hacky way to get only the pages in the
            # correct part of the page tree
            pg_id = 1327
            parent_page = Page.objects.get(id=pg_id)
            query = cls.objects.child_of(parent_page)
        except (Page.DoesNotExist):
            query = cls.objects

        query = query.filter(initial_filing_date__isnull=False)
        query = query.live().order_by('-initial_filing_date')
        return query

    def get_context(self, request):
        context = super(EnforcementActionPage, self).get_context(request)
        dispositions = self.enforcement_dispositions.all()

        context.update({
            'total_consumer_relief':
            sum(disp.final_order_consumer_redress +
                disp.final_order_other_consumer_relief
                for disp in dispositions),
            'total_cmp':
            sum(disp.final_order_civil_money_penalty for disp in dispositions),
            'defendant_types': [
                d.get_defendant_type_display()
                for d in self.defendant_types.all()
            ],
            'statutes': [s.statute for s in self.statutes.all()],
            'products': [p.product for p in self.products.all()],
            'at_risk_groups':
            [g.at_risk_group for g in self.at_risk_groups.all()]
        })

        return context
Ejemplo n.º 5
0
class UseCaseIndexPage(Page):
    subtitle_de = models.CharField(max_length=250,
                                   blank=True,
                                   verbose_name="Title")
    subtitle_en = models.CharField(max_length=250,
                                   blank=True,
                                   verbose_name="Title")

    demo_link = models.URLField(blank=True, verbose_name='Demo site')

    subtitle = TranslatedField('subtitle_de', 'subtitle_en')

    form_page = models.ForeignKey(
        'a4_candy_cms_contacts.FormPage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    @property
    def form(self):
        return self.form_page.get_form()

    @property
    def use_cases(self):
        use_cases = UseCasePage.objects.live()
        return use_cases

    def get_context(self, request):
        use_cases = self.use_cases

        category = request.GET.get('category')

        if category:
            try:
                use_cases = use_cases.filter(category=category)
            except ValueError:
                use_cases = []

        context = super().get_context(request)
        context['use_cases'] = use_cases
        context['categories'] = CATEGORY_CHOICES
        if category:
            context['current_category'] = category
            for category_choice in CATEGORY_CHOICES:
                if category_choice[0] == category:
                    context['get_current_category_display'] = (
                        category_choice[1])
        return context

    de_content_panels = [
        FieldPanel('subtitle_de'),
    ]

    en_content_panels = [
        FieldPanel('subtitle_en'),
    ]

    common_panels = [
        FieldPanel('title'),
        FieldPanel('slug'),
        FieldPanel('demo_link'),
        PageChooserPanel('form_page'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(common_panels, heading='Common'),
        ObjectList(en_content_panels, heading='English'),
        ObjectList(de_content_panels, heading='German')
    ])

    subpage_types = ['a4_candy_cms_use_cases.UseCasePage']
Ejemplo n.º 6
0
class CybergatewayHomePage(Page):
    """
    The Cybergateway themed template Page
    """

    # Hero section of HomePage
    site_logo = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Site Logo Image'
    )

    site_link = models.CharField(
        max_length=255,
        default="#",
        help_text='Give a site redirect link',
    )

    site_text = models.CharField(
        max_length=50,
        default="#",
        help_text='Give a Site Name',
    )

    site_header = models.CharField(
        max_length=70,
        default="#",
        help_text='Give a Site Header Name',
    )

    site_link1 = models.CharField(
        max_length=70,
        default="#",
        help_text='Give a Site Nav Link [1]',
    )

    site_link_text1 = models.CharField(
        max_length=70,
        help_text='Give a Site Nav Link Text [1]',
    )

    site_link2 = models.CharField(
        max_length=70,
        default='#',
        help_text='Give a Site Nav Link [2]',
    )

    site_link_text2 = models.CharField(
        max_length=70,
        help_text='Give a Site Nav Link Text [2]',
    )

    site_link3 = models.CharField(
        max_length=70,
        default="#",
        help_text='Give a Site Nav Link [3]',
    )

    site_link_text3 = models.CharField(
        max_length=70,
        help_text='Give a Site Nav Link Text [3]',
    )

    contact = StreamField(
        BaseStreamBlock(),
        verbose_name="Contact Info Block",
        blank=True,
        null=True)

    footer = StreamField(
        BaseStreamBlock(),
        verbose_name="Footer Content Block",
        blank=True,
        null=True)

    boolean_choices = (
        ("yes", "Yes"),
        ("no", "No")
    )

    show_navbar = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want to display the navbar on home page and no if you don't want to.",
        default="yes")

    show_nav_extra = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want the secondary navbar to show on home page or no if you don't want to",
        default="yes")

    show_footer = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want the Footer to show on home page or no if you don't want to",
        default="yes")

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('site_logo'),
            FieldPanel('site_link'),
            FieldPanel('site_text'),
            FieldPanel('site_header'),
            FieldPanel('site_link1'),
            FieldPanel('site_link_text1'),
            FieldPanel('site_link2'),
            FieldPanel('site_link_text2'),
            FieldPanel('site_link3'),
            FieldPanel('site_link_text3'),
        ], heading="Navbar Section"),
        InlinePanel("row", label="row"),
        StreamFieldPanel('contact'),
        StreamFieldPanel('footer'),
    ]

    customization_panels = [
        FieldPanel('show_navbar'),
        FieldPanel('show_nav_extra'),
        FieldPanel('show_footer'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(customization_panels, heading='Customization'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels, heading='Settings',
                   classname="settings"),
    ])

    def __str__(self):
        return self.title
Ejemplo n.º 7
0
class TabbedSettings(TestSetting):
    edit_handler = TabbedInterface([
        ObjectList([FieldPanel('title')], heading='First tab'),
        ObjectList([FieldPanel('email')], heading='Second tab'),
    ])
Ejemplo n.º 8
0
linkpage_panels = [
    MultiFieldPanel([
        FieldPanel('title', classname="title"),
        PageChooserPanel('link_page'),
        FieldPanel('link_url'),
        FieldPanel('url_append'),
        FieldPanel('extra_classes'),
    ])
]

linkpage_tab = ObjectList(
    linkpage_panels, heading=_("Settings"), classname="settings"
)

linkpage_edit_handler = TabbedInterface([linkpage_tab])


# ########################################################
# For MenuPageMixin
# ########################################################

menupage_panel = MultiFieldPanel(
    heading=_("Advanced menu behaviour"),
    classname="collapsible collapsed",
    children=(
        FieldPanel('repeat_in_subnav'),
        FieldPanel('repeated_item_text'),
    )
)
Ejemplo n.º 9
0
class Topic(BasePage):
    resource_type = "topic"
    parent_page_types = ["Topics"]
    subpage_types = ["Topic", "content.ContentPage"]
    template = "topic.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,
    )
    featured = StreamField(
        StreamBlock(
            [
                (
                    "post",
                    PageChooserBlock(target_model=(
                        "articles.Article",
                        "externalcontent.ExternalArticle",
                    )),
                ),
                ("external_page", FeaturedExternalBlock()),
            ],
            max_num=4,
            required=False,
        ),
        null=True,
        blank=True,
        help_text="Optional space for featured posts, max. 4",
    )
    tabbed_panels = StreamField(
        StreamBlock([("panel", TabbedPanelBlock())], max_num=3,
                    required=False),
        null=True,
        blank=True,
        help_text=
        "Optional tabbed panels for linking out to other resources, max. 3",
        verbose_name="Tabbed panels",
    )
    latest_articles_count = IntegerField(
        choices=RESOURCE_COUNT_CHOICES,
        default=3,
        help_text="The number of posts to display for this topic.",
    )

    # 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
    icon = FileField(
        upload_to="topics/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],
    )
    color = CharField(max_length=14, choices=COLOR_CHOICES, default="blue-40")
    keywords = ClusterTaggableManager(through=TopicTag, blank=True)

    # Content panels
    content_panels = BasePage.content_panels + [
        FieldPanel("description"),
        StreamFieldPanel("featured"),
        StreamFieldPanel("tabbed_panels"),
        FieldPanel("latest_articles_count"),
        MultiFieldPanel(
            [InlinePanel("people")],
            heading="People",
            help_text=
            "Optional list of people associated with this topic as experts",
        ),
    ]

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

    # Meta panels
    meta_panels = [
        MultiFieldPanel(
            [
                InlinePanel("parent_topics", label="Parent topic(s)"),
                InlinePanel("child_topics", label="Child topic(s)"),
            ],
            heading="Parent/child topic(s)",
            classname="collapsible collapsed",
            help_text=("Topics with no parent (i.e. top-level topics) will be "
                       "listed on the home page. Child topics are listed "
                       "on the parent topic’s page."),
        ),
        MultiFieldPanel(
            [FieldPanel("icon"), FieldPanel("color")],
            heading="Theme",
            help_text=(
                "Theme settings used on topic page and any tagged content. "
                "For example, a post tagged with this topic "
                "will use the color specified here as its accent color."),
        ),
        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"),
    ])

    @property
    def articles(self):
        return get_combined_articles(self, topics__topic__pk=self.pk)

    @property
    def events(self):
        """Return upcoming events for this topic,
        ignoring events in the past, ordered by start date"""
        return get_combined_events(self,
                                   topics__topic__pk=self.pk,
                                   start_date__gte=get_past_event_cutoff())

    @property
    def experts(self):
        """Return Person instances for topic experts"""
        return [person.person for person in self.people.all()]

    @property
    def videos(self):
        """Return the latest videos and external videos for this topic. """
        return get_combined_videos(self, topics__topic__pk=self.pk)

    @property
    def color_value(self):
        return dict(COLOR_VALUES)[self.color]

    @property
    def subtopics(self):
        return [topic.child for topic in self.child_topics.all()]
Ejemplo n.º 10
0
class RegulationsSearchPage(RoutablePageMixin, CFGOVPage):
    """A page for the custom search interface for regulations."""

    objects = PageManager()

    parent_page_types = ['regulations3k.RegulationLandingPage']
    subpage_types = []
    results = {}
    content_panels = CFGOVPage.content_panels
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(CFGOVPage.settings_panels, heading='Configuration'),
    ])

    def get_template(self, request):
        template = 'regulations3k/search-regulations.html'
        if 'partial' in request.GET:
            template = 'regulations3k/search-regulations-results.html'
        return template

    @route(r'^results/')
    def regulation_results_page(self, request):
        all_regs = Part.objects.order_by('part_number')
        regs = validate_regs_list(request)
        order = validate_order(request)
        search_query = request.GET.get('q', '').strip()
        payload = {
            'search_query': search_query,
            'results': [],
            'total_results': 0,
            'regs': regs,
            'all_regs': [],
        }
        if not search_query or len(urllib.parse.unquote(search_query)) == 1:
            self.results = payload
            return TemplateResponse(request, self.get_template(request),
                                    self.get_context(request))
        search = SectionParagraphDocument.search().query('match',
                                                         text={
                                                             "query":
                                                             search_query,
                                                             "operator": "AND"
                                                         })
        search = search.highlight('text',
                                  pre_tags="<strong>",
                                  post_tags="</strong>")
        total_results = search.count()
        all_regs = [{
            'short_name':
            reg.short_name,
            'id':
            reg.part_number,
            'num_results':
            search.filter('term', part=reg.part_number).count(),
            'selected':
            reg.part_number in regs
        } for reg in all_regs]
        payload.update({'all_regs': all_regs, 'total_count': total_results})
        if regs:
            search = search.filter('terms', part=regs)
        if order == 'regulation':
            search = search.sort('part', 'section_order')
        search = search[0:total_results]
        response = search.execute()
        for hit in response[0:total_results]:
            try:
                snippet = Markup("".join(hit.meta.highlight.text[0]))
            except TypeError as e:
                logger.warning(
                    "Query string {} produced a TypeError: {}".format(
                        search_query, e))
                continue
            hit_payload = {
                'id':
                hit.paragraph_id,
                'part':
                hit.part,
                'reg':
                hit.short_name,
                'label':
                hit.title,
                'snippet':
                snippet,
                'url':
                "{}{}/{}/#{}".format(self.parent().url, hit.part,
                                     hit.section_label, hit.paragraph_id),
            }
            payload['results'].append(hit_payload)

        payload.update({'current_count': search.count()})
        self.results = payload
        context = self.get_context(request)
        num_results = validate_num_results(request)
        paginator = Paginator(payload['results'], num_results)
        page_number = validate_page_number(request, paginator)
        paginated_page = paginator.page(page_number)
        context.update({
            'current_count':
            payload['current_count'],
            'total_count':
            payload['total_count'],
            'paginator':
            paginator,
            'current_page':
            page_number,
            'num_results':
            num_results,
            'order':
            order,
            'results':
            paginated_page,
            'show_filters':
            any(reg['selected'] is True for reg in payload['all_regs'])
        })
        return TemplateResponse(request, self.get_template(request), context)
class HomePage(MetadataPageMixin, TranslatablePage):
    # Register the fields for your personal information
    name = models.CharField(max_length=255,
                            blank=True,
                            null=True,
                            help_text='Your name',
                            default='John Doe')
    heading = models.CharField(max_length=255,
                               blank=True,
                               null=True,
                               help_text='Your title',
                               default='Web Developer')
    email = models.CharField(max_length=255,
                             blank=True,
                             null=True,
                             help_text='Your email',
                             default='*****@*****.**')
    telephone = models.CharField(max_length=255,
                                 blank=True,
                                 null=True,
                                 help_text='Your telephone',
                                 default='06123456789')
    profile_pic = models.ForeignKey('wagtailimages.Image',
                                    null=True,
                                    blank=True,
                                    on_delete=models.SET_NULL,
                                    related_name='+')
    button = models.CharField(max_length=255,
                              blank=True,
                              null=True,
                              default='Portfolio')

    # Add the intro fields to homepage model
    intro_heading = models.CharField(max_length=255,
                                     blank=True,
                                     null=True,
                                     default='More about me.')
    intro_sub_heading = models.CharField(max_length=255,
                                         blank=True,
                                         null=True,
                                         default='A SHORT INTRODUCTION')
    intro_left = RichTextField(blank=True)
    intro_right = RichTextField(blank=True)
    portfolio_heading = models.CharField(max_length=255,
                                         blank=True,
                                         null=True,
                                         default='Finished projects')
    portfolio_sub_heading = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default='A GLIMPSE OF MY PORTFOLIO')

    # Metadata search image
    search_image = models.ForeignKey(
        get_image_model_string(),
        null=True,
        blank=True,
        related_name='+',
        on_delete=models.SET_NULL,
        verbose_name=ugettext_lazy('Search image'))

    # Register the fields in Wagtail admin, we use FieldRowPanel here for better user experience.
    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel('intro_heading'),
                    FieldPanel('intro_sub_heading'),
                ]),
                FieldRowPanel([
                    FieldPanel('portfolio_heading'),
                    FieldPanel('portfolio_sub_heading'),
                ]),
            ],
            heading="Headings",
            classname="collapsible",
        ),
        FieldPanel('intro_left', classname="full"),
        FieldPanel('intro_right', classname="full"),
    ]

    # Information panel in wagtail admin.
    information_content_panels = [
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel('name'),
                    FieldPanel('heading'),
                ]),
                FieldRowPanel([
                    FieldPanel('email'),
                    FieldPanel('telephone'),
                ]),
                FieldRowPanel([
                    ImageChooserPanel('profile_pic'),
                    FieldPanel('button'),
                ]),
            ],
            heading="Details",
            classname="collapsible",
        ),
    ]

    # This has to be defined because we use Wagtailtrans. Otherwise the search image does not get displayed.
    promote_panels = [
        MultiFieldPanel([
            FieldPanel('slug'),
            FieldPanel('seo_title'),
            FieldPanel('show_in_menus'),
            FieldPanel('search_description'),
            ImageChooserPanel('search_image'),
        ], ugettext_lazy('Common page configuration')),
    ]

    # The edit handler for displaying the tabs we previously defined
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Info'),
        ObjectList(information_content_panels, heading='Personal information'),
        ObjectList(promote_panels, heading='Promote'),
        ObjectList(TranslatablePage.settings_panels,
                   heading='Settings',
                   classname="settings"),
    ])

    subpage_types = []
Ejemplo n.º 12
0
class RegulationPage(RoutablePageMixin, SecondaryNavigationJSMixin, CFGOVPage):
    """A routable page for serving an eregulations page by Section ID."""

    objects = PageManager()
    parent_page_types = ['regulations3k.RegulationLandingPage']
    subpage_types = []

    template = 'regulations3k/browse-regulation.html'

    header = StreamField([
        ('text_introduction', molecules.TextIntroduction()),
    ],
                         blank=True)

    content = StreamField([
        ('info_unit_group', organisms.InfoUnitGroup()),
        ('full_width_text', organisms.FullWidthText()),
    ],
                          null=True,
                          blank=True)

    regulation = models.ForeignKey(Part,
                                   blank=True,
                                   null=True,
                                   on_delete=models.PROTECT,
                                   related_name='page')

    content_panels = CFGOVPage.content_panels + [
        StreamFieldPanel('header'),
        StreamFieldPanel('content'),
        FieldPanel('regulation', Part),
    ]

    secondary_nav_exclude_sibling_pages = models.BooleanField(default=False)

    sidefoot_panels = CFGOVPage.sidefoot_panels + [
        FieldPanel('secondary_nav_exclude_sibling_pages'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='General Content'),
        ObjectList(sidefoot_panels, heading='Sidebar'),
        ObjectList(CFGOVPage.settings_panels, heading='Configuration'),
    ])

    def can_serve_draft_versions(self, request):
        perms = request.user.get_all_permissions()
        if (request.user.is_superuser
                or getattr(request, 'served_by_wagtail_sharing', False)
                or 'regulations3k.change_section' in perms):
            return True
        return False

    def get_versions_query(self, request):
        versions = self.regulation.versions

        if not self.can_serve_draft_versions(request):
            versions = versions.filter(draft=False)

        return versions

    def get_effective_version(self, request, date_str=None):
        """ Get the requested effective version if the user has permission """
        query_filter = {}

        if date_str is None:
            query_filter['effective_date__lte'] = date.today()
        else:
            query_filter['effective_date'] = date_str

        draft_permission = self.can_serve_draft_versions(request)
        if not draft_permission:
            query_filter['draft'] = False

        effective_version = self.regulation.versions.filter(
            **query_filter).order_by('-effective_date').first()

        if effective_version is None:
            raise Http404

        return effective_version

    def get_section_query(self, request=None, effective_version=None):
        """Query set for Sections in this regulation's effective version."""
        if effective_version is None:
            effective_version = self.get_effective_version(request)
        return Section.objects.filter(subpart__version=effective_version)

    def get_context(self, request, *args, **kwargs):
        context = super(RegulationPage,
                        self).get_context(request, *args, **kwargs)
        context.update({
            'regulation':
            self.regulation,
            'current_version':
            self.get_effective_version(request),
            'breadcrumb_items':
            self.get_breadcrumbs(request, *args, **kwargs),
            'search_url':
            (self.get_parent().url + 'search-regulations/results/?regs=' +
             self.regulation.part_number),
            'num_versions':
            self.get_versions_query(request).count(),
        })
        return context

    def get_breadcrumbs(self, request, section=None, **kwargs):
        crumbs = super(RegulationPage, self).get_breadcrumbs(request)

        if section is not None:
            crumbs = crumbs + [
                {
                    'href':
                    self.url + self.reverse_subpage(
                        'index',
                        kwargs={
                            k: v
                            for k, v in kwargs.items() if k == 'date_str'
                        }),
                    'title':
                    str(section.subpart.version.part),
                },
            ]

        return crumbs

    def get_urls_for_version(self, effective_version, section=None):
        base_url = self.get_full_url()
        versions_url = urljoin(base_url, 'versions') + '/'

        if effective_version.live_version:
            # This is the current version
            version_url = base_url
        else:
            # It's a past or future version, URLs have the date str
            date_str = str(effective_version.effective_date)
            version_url = urljoin(base_url, date_str) + '/'
            yield version_url

        if section is not None:
            yield urljoin(version_url, section.label) + '/'
        else:
            sections = self.get_section_query(
                effective_version=effective_version)
            yield version_url
            yield versions_url
            for section in sections.all():
                yield urljoin(version_url, section.label) + '/'

    def render_interp(self, context, raw_contents, **kwargs):
        template = get_template('regulations3k/inline_interps.html')

        # Extract the title from the raw regdown
        section_title_match = re.search(r'#+\s?(?P<section_title>.*)\s',
                                        raw_contents)
        if section_title_match is not None:
            context.update({'section_title': section_title_match.group(1)})
            span = section_title_match.span()
            raw_contents = raw_contents[:span[0]] + raw_contents[span[1]:]

        context.update({'contents': regdown(raw_contents)})
        context.update(kwargs)

        return template.render(context)

    @route(r'^(?:(?P<date_str>[0-9]{4}-[0-9]{2}-[0-9]{2})/)?$', name="index")
    def index_route(self, request, date_str=None):
        request.is_preview = getattr(request, 'is_preview', False)

        effective_version = self.get_effective_version(request,
                                                       date_str=date_str)
        section_query = self.get_section_query(
            effective_version=effective_version)
        sections = list(section_query.all())

        context = self.get_context(request)
        context.update({
            'requested_version':
            effective_version,
            'sections':
            sections,
            'get_secondary_nav_items':
            partial(get_secondary_nav_items,
                    sections=sections,
                    date_str=date_str),
        })

        if date_str is not None:
            context['date_str'] = date_str

        return TemplateResponse(request, self.get_template(request), context)

    @route(r'^versions/(?:(?P<section_label>' + label_re_str + r')/)?$',
           name="versions")
    def versions_page(self, request, section_label=None):
        section_query = self.get_section_query(request=request)
        sections = list(section_query.all())
        context = self.get_context(request, sections=sections)

        versions = [{
            'effective_date':
            v.effective_date,
            'date_str':
            str(v.effective_date),
            'sections':
            self.get_section_query(effective_version=v).all(),
            'draft':
            v.draft
        } for v in self.get_versions_query(request).order_by('-effective_date')
                    ]

        context.update({
            'versions':
            versions,
            'section_label':
            section_label,
            'get_secondary_nav_items':
            partial(get_secondary_nav_items, sections=sections),
        })

        return TemplateResponse(request, self.template, context)

    @route(r'^(?:(?P<date_str>[0-9]{4}-[0-9]{2}-[0-9]{2})/)?'
           r'(?P<section_label>' + label_re_str + r')/$',
           name="section")
    def section_page(self, request, date_str=None, section_label=None):
        """ Render a section of the currently effective regulation """

        effective_version = self.get_effective_version(request,
                                                       date_str=date_str)
        section_query = self.get_section_query(
            effective_version=effective_version)

        next_version = self.get_versions_query(request).filter(
            effective_date__gt=effective_version.effective_date).first()

        kwargs = {}
        if date_str is not None:
            kwargs['date_str'] = date_str

        try:
            section = section_query.get(label=section_label)
        except Section.DoesNotExist:
            return redirect(self.url +
                            self.reverse_subpage("index", kwargs=kwargs))

        sections = list(section_query.all())
        current_index = sections.index(section)
        context = self.get_context(request,
                                   section,
                                   sections=sections,
                                   **kwargs)

        content = regdown(
            section.contents,
            url_resolver=get_url_resolver(self, date_str=date_str),
            contents_resolver=get_contents_resolver(effective_version),
            render_block_reference=partial(self.render_interp, context))

        next_section = get_next_section(sections, current_index)
        previous_section = get_previous_section(sections, current_index)

        context.update({
            'requested_version':
            effective_version,
            'next_version':
            next_version,
            'section':
            section,
            'content':
            content,
            'get_secondary_nav_items':
            partial(get_secondary_nav_items,
                    sections=sections,
                    date_str=date_str),
            'next_section':
            next_section,
            'next_url':
            get_section_url(self, next_section, date_str=date_str),
            'previous_section':
            previous_section,
            'previous_url':
            get_section_url(self, previous_section, date_str=date_str),
        })

        return TemplateResponse(request, self.template, context)
Ejemplo n.º 13
0
class Person(Page):
    resource_type = 'person'
    parent_page_types = ['People']
    subpage_types = []
    template = 'person.html'

    # Content fields
    job_title = CharField(max_length=250)
    role = CharField(max_length=250, choices=ROLE_CHOICES, default='staff')
    description = RichTextField(default='', blank=True)
    image = ForeignKey(
        'mozimages.MozImage',
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name='+'
    )

    # 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',
    )

    # Meta
    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())
        ], min_num=0, max_num=3, required=False),
        null=True,
        blank=True,
    )
    keywords = ClusterTaggableManager(through=PersonTag, blank=True)

     # Content panels
    content_panels = [
        MultiFieldPanel([
            CustomLabelFieldPanel('title', label='Full name'),
            FieldPanel('job_title'),
            FieldPanel('role'),
        ], heading='About'),
        FieldPanel('description'),
        ImageChooserPanel('image'),
    ]

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

    # Meta panels
    meta_panels = [
        MultiFieldPanel([
            InlinePanel('topics'),
        ], heading='Topics interested in'),
        MultiFieldPanel([
            FieldPanel('twitter'),
            FieldPanel('facebook'),
            FieldPanel('linkedin'),
            FieldPanel('github'),
            FieldPanel('email'),
        ], heading='Profiles'),
        StreamFieldPanel('websites'),
        MultiFieldPanel([
            FieldPanel('seo_title'),
            FieldPanel('search_description'),
            FieldPanel('keywords'),
        ], heading='SEO'),
    ]

    # Settings panels
    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 events(self):
        '''
        Return upcoming events where this person is a speaker,
        ordered by start date
        '''
        from ..events.models import Event

        upcoming_events = (Event
                .objects
                .filter(start_date__gte=datetime.datetime.now())
                .live()
                .public()
        )

        speaker_events = Event.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.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.objects.none()
        external_articles = ExternalArticle.objects.none()

        all_articles = Article.objects.live().public().all()
        all_external_articles = ExternalArticle.objects.live().public().all()

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

        for external_article in all_external_articles:
            if external_article.has_author(self):
                external_articles = external_articles | ExternalArticle.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.objects.none()
        external_videos = ExternalVideo.objects.none()

        all_videos = Video.objects.live().public().all()
        all_external_videos = ExternalVideo.objects.live().public().all()

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

        for external_video in all_external_videos:
            if external_video.has_speaker(self):
                external_videos = external_videos | ExternalVideo.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, ''),
        }
Ejemplo n.º 14
0
class HomePage(ThemeablePage):
    subpage_types = [
        article_models.ArticleListPage,
        article_models.SeriesListPage,
        article_models.TopicListPage,
        people_models.ContributorListPage,
        project_models.ProjectListPage,
        newsletter_models.NewsletterListPage,
        event_models.EventListPage,
        article_models.ExternalArticleListPage,
        jobs_models.JobPostingListPage,
        StreamPage,
    ]

    featured_item = models.ForeignKey('wagtailcore.Page',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL,
                                      related_name='+')

    number_of_rows_of_articles = models.IntegerField(default=12,
                                                     verbose_name="Rows")
    number_of_columns_of_articles = models.IntegerField(default=3,
                                                        verbose_name="Columns")
    number_of_rows_of_series = models.IntegerField(default=1,
                                                   verbose_name="Rows")
    number_of_rows_of_external_articles = models.IntegerField(
        default=2, verbose_name="Rows")
    number_of_columns_of_external_articles = models.IntegerField(
        default=2, verbose_name="Columns")
    number_of_rows_of_visualizations = models.IntegerField(default=2,
                                                           verbose_name="Rows")
    number_of_columns_of_visualizations = models.IntegerField(
        default=2, verbose_name="Columns")
    full_bleed_image_size = models.PositiveSmallIntegerField(
        default=90,
        help_text=
        "Enter a value from 0 - 100, indicating the percentage of the screen to use for the featured image layout."
    )

    _articles = None
    _most_popular_article = None

    def __str__(self):
        return self.title

    def get_article_set(self, columns, rows, article_list, used):
        if columns == 0 and rows == 0 or not article_list:
            return []

        current_set = []
        while rows > 0:
            row, height = self._fill_row(columns, article_list, used, rows)
            if height == 0:
                break
            current_set.append(row)
            rows = rows - height

        return current_set

    def _fill_row(self, columns, article_list, used, max_height):
        if columns == 0 or not article_list:
            return [], 0

        for article in article_list:
            typed_article = article.content_type.get_object_for_this_type(
                id=article.id)
            if typed_article.feature_style.number_of_columns <= columns \
                    and typed_article.id not in used\
                    and typed_article.feature_style.number_of_rows <= max_height:

                columns = columns - typed_article.feature_style.number_of_columns
                used.append(typed_article.id)
                row = [typed_article]
                max_height = min(max_height,
                                 typed_article.feature_style.number_of_rows)

                if max_height > 1 and columns > 0:
                    subset = self.get_article_set(columns, max_height,
                                                  article_list, used)
                    row.append(subset)
                else:
                    recursive_row, height = self._fill_row(
                        columns, article_list, used, max_height)
                    row.extend(recursive_row)
                return row, max_height

        return [], 0

    @property
    def articles(self):
        if self._articles is not None:
            return self._articles

        article_content_type = ContentType.objects.get_for_model(
            article_models.ArticlePage)
        series_content_type = ContentType.objects.get_for_model(
            article_models.SeriesPage)

        articles = Page.objects.live().filter(
            models.Q(content_type=article_content_type)
            | models.Q(content_type=series_content_type)).annotate(
                sticky=models.Case(
                    models.When(models.Q(seriespage__sticky=True)
                                | (models.Q(articlepage__sticky=True)),
                                then=models.Value(1)),
                    default=models.Value(0),
                    output_field=models.IntegerField())).exclude(
                        models.Q(seriespage__slippery=True)
                        | models.Q(articlepage__slippery=True)).order_by(
                            "-sticky", "-first_published_at")

        articles = list(articles[:42])

        used = []
        if self.featured_item:
            used.append(self.featured_item.id)
        self._articles = self.get_article_set(
            self.number_of_columns_of_articles,
            self.number_of_rows_of_articles, articles, used)

        return self._articles

    @property
    def most_popular_article(self):
        if self._most_popular_article is not None:
            return self._most_popular_article

        def get_views(article):
            try:
                if article.analytics:
                    return article.analytics.last_period_views
            except:
                return 0

        # flatten the list of lists with generator
        articles = itertools.chain.from_iterable(self.articles)
        articles_by_popularity = sorted(articles, key=get_views)

        self._most_popular_article = articles_by_popularity[-1]
        return self._most_popular_article

    @property
    def typed_featured_item(self):
        if self.featured_item:
            featured_item = self.featured_item.content_type.get_object_for_this_type(
                id=self.featured_item.id)
            return featured_item

    def get_rows(self, number_of_rows, number_of_columns, items):
        rows = []

        for row_index in range(0, number_of_rows):
            row = items[(row_index *
                         number_of_columns):(row_index * number_of_columns) +
                        number_of_columns]
            rows.append(row)

        return rows

    @property
    def external_articles(self):
        number_of_external_articles = self.number_of_rows_of_external_articles * self.number_of_columns_of_external_articles
        external_article_list = article_models.ExternalArticlePage.objects.live(
        ).order_by("-first_published_at")[:number_of_external_articles]

        return self.get_rows(self.number_of_rows_of_external_articles,
                             self.number_of_columns_of_external_articles,
                             external_article_list)

    @property
    def graphics(self):
        number_of_graphics = self.number_of_rows_of_visualizations * self.number_of_columns_of_visualizations
        graphics_list = article_models.ArticlePage.objects.live().filter(
            visualization=True).annotate(sticky_value=models.Case(
                models.When(models.Q(sticky_for_type_section=True),
                            then=models.Value(1)),
                default=models.Value(0),
                output_field=models.IntegerField())).exclude(
                    slippery_for_type_section=True).order_by(
                        "-sticky_value",
                        "-first_published_at")[:number_of_graphics]

        return self.get_rows(self.number_of_rows_of_visualizations,
                             self.number_of_columns_of_visualizations,
                             graphics_list)

    @property
    def series(self):
        number_of_series = self.number_of_rows_of_series
        series_list = article_models.SeriesPage.objects.live().annotate(
            sticky_value=models.Case(models.When(
                models.Q(sticky_for_type_section=True), then=models.Value(1)),
                                     default=models.Value(0),
                                     output_field=models.IntegerField())
        ).exclude(slippery_for_type_section=True).order_by(
            "-sticky_value", "-first_published_at")[:number_of_series]

        return self.get_rows(self.number_of_rows_of_series, 1, series_list)

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            PageChooserPanel("featured_item", "wagtailcore.Page"),
            FieldPanel("full_bleed_image_size"),
        ],
                        heading="Main Feature"),
        MultiFieldPanel([
            FieldPanel("number_of_rows_of_articles"),
            FieldPanel("number_of_columns_of_articles"),
        ],
                        heading="Main Feed Settings"),
        MultiFieldPanel([
            FieldPanel("number_of_rows_of_series"),
        ],
                        heading="Series Section Settings"),
        MultiFieldPanel([
            FieldPanel("number_of_rows_of_external_articles"),
            FieldPanel("number_of_columns_of_external_articles"),
        ],
                        heading="External Articles Section Settings"),
        MultiFieldPanel([
            FieldPanel("number_of_rows_of_visualizations"),
            FieldPanel("number_of_columns_of_visualizations"),
        ],
                        heading="Visualization Section Settings"),
    ]

    style_panels = ThemeablePage.style_panels

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(style_panels, heading='Page Style Options'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels,
                   heading='Settings',
                   classname="settings"),
    ])
Ejemplo n.º 15
0
class HomePage(Page):
    subpage_types = [
        'articles.Articles',
        'content.ContentPage',
        'events.Events',
        'people.People',
        'topics.Topics',
        'videos.Videos',
    ]
    template = 'home.html'

    # Content fields
    subtitle = TextField(max_length=250, blank=True, default='')
    button_text = CharField(max_length=30, blank=True, default='')
    button_url = CharField(max_length=2048, blank=True, default='')
    image = ForeignKey('mozimages.MozImage',
                       null=True,
                       blank=True,
                       on_delete=SET_NULL,
                       related_name='+')
    external_promos = StreamField(
        StreamBlock([
            ('external_promo', FeaturedExternalBlock()),
        ],
                    max_num=2,
                    required=False),
        null=True,
        blank=True,
        help_text=
        'Optional promo space under the header for linking to external sites, max. 2',
    )
    featured = StreamField(
        StreamBlock([
            ('article',
             PageChooserBlock(target_model=(
                 'articles.Article',
                 'externalcontent.ExternalArticle',
             ))),
            ('external_page', FeaturedExternalBlock()),
        ],
                    max_num=4,
                    required=False),
        null=True,
        blank=True,
        help_text='Optional space for featured articles, max. 4',
    )
    about_title = TextField(max_length=250, blank=True, default='')
    about_subtitle = TextField(max_length=250, blank=True, default='')
    about_button_text = CharField(max_length=30, blank=True, default='')
    about_button_url = URLField(max_length=140, blank=True, default='')

    # 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
    keywords = ClusterTaggableManager(through=HomePageTag, blank=True)

    # Editor panel configuration
    content_panels = Page.content_panels + [
        MultiFieldPanel([
            FieldPanel('subtitle'),
            FieldPanel('button_text'),
            FieldPanel('button_url'),
        ],
                        heading='Header section',
                        help_text='Optional fields for the header section'),
        MultiFieldPanel(
            [
                ImageChooserPanel('image'),
            ],
            heading='Image',
            help_text=
            'Optional image shown when sharing this page through social media'
        ),
        StreamFieldPanel('external_promos'),
        StreamFieldPanel('featured'),
        MultiFieldPanel(
            [
                FieldPanel('about_title'),
                FieldPanel('about_subtitle'),
                FieldPanel('about_button_text'),
                FieldPanel('about_button_url'),
            ],
            heading='About section',
            help_text='Optional section to explain more about Mozilla'),
    ]

    # Card panels
    card_panels = [
        MultiFieldPanel(
            [
                FieldPanel('card_title'),
                FieldPanel('card_description'),
                ImageChooserPanel('card_image'),
            ],
            heading='Card overrides',
            help_text=
            ('Optional fields to override the default title, description and image when this page is shown as a card'
             )),
    ]

    # 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'),
    ]

    # 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'),
    ])

    @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()

    @property
    def primary_topics(self):
        """The site’s top-level topics, i.e. topics without a parent topic."""
        from ..topics.models import Topic
        return Topic.objects.filter(
            parent_topics__isnull=True).live().public().order_by('title')
Ejemplo n.º 16
0
class ProjectPage(ContactFieldsMixin, BasePage):
    template = "patterns/pages/project/project_detail.html"

    hero_image = models.ForeignKey(
        "images.CustomImage",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    introduction = models.CharField(max_length=500, blank=True)
    introduction_image = models.ForeignKey(
        get_image_model_string(),
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    video_caption = models.CharField(
        blank=True,
        max_length=80,
        help_text=_("The text displayed next to the video play button"),
    )
    video = models.URLField(blank=True)
    body = StreamField(
        [
            ("quote_block", QuoteBlock()),
            (
                "rich_text_block",
                RichTextBlock(features=[
                    "h2", "h3", "bold", "italic", "image", "ul", "ol", "link"
                ]),
            ),
            ("link_block", LinkBlock()),
        ],
        blank=True,
        verbose_name=_("Body copy"),
    )
    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)
    funding = models.CharField(max_length=250, blank=True)
    specification_document = models.ForeignKey(
        "documents.CustomDocument",
        null=True,
        blank=True,
        related_name="+",
        on_delete=models.SET_NULL,
        verbose_name=_("Project PDF"),
    )
    specification_document_link_text = models.CharField(
        max_length=80,
        blank=True,
        null=True,
        verbose_name=_("Project PDF link text"),
        help_text=
        _("You must enter link text if you add a Project PDF, e.g. 'Download project PDF'"
          ),
    )

    gallery = StreamField([("slide", GalleryBlock())],
                          blank=True,
                          verbose_name=_("Gallery"))
    more_information_title = models.CharField(max_length=80,
                                              default="More information")
    more_information = StreamField(
        [("accordion_block", AccordionBlockWithTitle())],
        blank=True,
        verbose_name=_("More information"),
    )
    partners = StreamField([("link", LinkBlock())],
                           blank=True,
                           verbose_name=_("Links to partners"))
    funders = StreamField([("link", LinkBlock())],
                          blank=True,
                          verbose_name=_("Links to funders"))
    quote_carousel = StreamField([("quote", QuoteBlock())],
                                 blank=True,
                                 verbose_name=_("Quote carousel"))
    external_links = StreamField([("link", LinkBlock())],
                                 blank=True,
                                 verbose_name="External Links")
    content_panels = BasePage.content_panels + [
        MultiFieldPanel(
            [ImageChooserPanel("hero_image")],
            heading=_("Hero"),
        ),
        MultiFieldPanel(
            [
                FieldPanel("introduction"),
                ImageChooserPanel("introduction_image"),
                FieldPanel("video"),
                FieldPanel("video_caption"),
            ],
            heading=_("Introduction"),
        ),
        StreamFieldPanel("body"),
        StreamFieldPanel("gallery"),
        MultiFieldPanel(
            [
                FieldPanel("more_information_title"),
                StreamFieldPanel("more_information"),
            ],
            heading=_("More information"),
        ),
        MultiFieldPanel(
            [
                InlinePanel(
                    "project_lead", label="Project team lead", max_num=1),
                InlinePanel("related_staff", label="Project team"),
            ],
            "Project team and staff",
        ),
        InlinePanel("related_student_pages", label="Project students"),
        StreamFieldPanel("partners"),
        StreamFieldPanel("funders"),
        StreamFieldPanel("quote_carousel"),
        StreamFieldPanel("external_links"),
        MultiFieldPanel([*ContactFieldsMixin.panels],
                        heading="Contact information"),
    ]

    key_details_panels = [
        InlinePanel("related_sectors", label=_("Innovation RCA sectors")),
        InlinePanel("related_research_themes", label=_("Research themes")),
        InlinePanel("expertise", label=_("RCA Expertise")),
        InlinePanel("related_school_pages", label=_("Related schools")),
        InlinePanel("related_research_pages",
                    label=_("Related research centres")),
        InlinePanel("research_types", label=_("Research types")),
        FieldPanel("start_date"),
        FieldPanel("end_date"),
        FieldPanel("funding"),
        MultiFieldPanel(
            [
                DocumentChooserPanel("specification_document"),
                FieldPanel("specification_document_link_text"),
            ],
            heading="PDF download",
        ),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(key_details_panels, heading="Key details"),
        ObjectList(BasePage.promote_panels, heading="Promote"),
        ObjectList(BasePage.settings_panels, heading="Settings"),
    ])

    def get_related_projects(self):
        """
        Displays latest projects from the parent School/Centre  the project belongs to.
        IF there are no projects with the same theme School/Centre latest projects with a
        matching research_type will be displayed.
        IF there are no projects with a matching research_type, the latest projects with
        matching expertise tags will be displayed.

        Returns:
            List -- of filtered and formatted ProjectPages
        """

        all_projects = ProjectPage.objects.live().public().not_page(self)

        schools = self.related_school_pages.values_list("page_id")
        projects = all_projects.filter(
            related_school_pages__page_id__in=schools).distinct()
        if projects:
            return format_projects_for_gallery(projects)

        research_centres = self.related_research_pages.values_list("page_id")
        projects = all_projects.filter(
            related_research_pages__page_id__in=research_centres).distinct()
        if projects:
            return format_projects_for_gallery(projects)

        research_types = self.research_types.values_list("research_type_id")
        projects = all_projects.filter(
            research_types__research_type_id__in=research_types).distinct()
        if projects:
            return format_projects_for_gallery(projects)

        expertise = self.expertise.values_list("area_of_expertise_id")
        projects = all_projects.filter(
            expertise__area_of_expertise_id__in=expertise).distinct()

        if projects:
            return format_projects_for_gallery(projects)

    def clean(self):
        super().clean()
        errors = defaultdict(list)

        if self.end_date and self.end_date < self.start_date:
            errors["end_date"].append(
                _("Events involving time travel are not supported"))
        if self.specification_document and not self.specification_document_link_text:
            errors["specification_document_link_text"].append(
                "You must provide link text for the document")

        if errors:
            raise ValidationError(errors)

    def get_related_school_or_centre(self):
        # returns the first related schools page, if none, return the related research
        # centre page
        related_school = self.related_school_pages.first()
        related_research_page = self.related_research_pages.first()
        if related_school:
            return related_school.page
        elif related_research_page:
            return related_research_page.page

    def get_expertise_linked_filters(self):
        """ For the expertise taxonomy thats listed out in key details,
        they need to link to the parent project picker page with a filter pre
        selected"""
        # Get parent page
        parent_picker = ProjectPickerPage.objects.parent_of(
            self).live().first()
        expertise = []
        for i in self.expertise.all().select_related("area_of_expertise"):
            if parent_picker:
                expertise.append({
                    "title":
                    i.area_of_expertise.title,
                    "link":
                    f"{parent_picker.url}?expertise={i.area_of_expertise.slug}",
                })
            else:
                expertise.append({"title": i.area_of_expertise.title})
        return expertise

    def get_sector_linked_filters(self):
        """ For the sector taxonomy thats listed out in key details,
        they need to link to the parent project picker page with a filter pre
        selected"""

        parent_picker = ProjectPickerPage.objects.parent_of(
            self).live().first()
        sectors = []
        for i in self.related_sectors.all().select_related("sector"):
            if parent_picker:
                sectors.append({
                    "title":
                    i.sector.title,
                    "link":
                    f"{parent_picker.url}?sector={i.sector.slug}",
                })
            else:
                sectors.append({"title": i.sector.title})
        return sectors

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        taxonomy_tags = []
        if self.related_school_pages:
            for i in self.related_school_pages.all():
                taxonomy_tags.append({"title": i.page.title})
        if self.related_research_pages:
            for i in self.related_research_pages.all():
                taxonomy_tags.append({"title": i.page.title})
        if self.research_types:
            for i in self.research_types.all():
                taxonomy_tags.append({"title": i.research_type.title})

        context["expertise"] = self.get_expertise_linked_filters()
        context["sectors"] = self.get_sector_linked_filters()
        context["project_lead"] = self.project_lead.select_related("image")
        context["related_staff"] = self.related_staff.select_related("image")
        context["taxonomy_tags"] = taxonomy_tags
        context["related_projects"] = self.get_related_projects()

        return context

    @cached_property
    def is_startup_project(self):
        return len(
            self.research_types.filter(research_type__title="Start-up")) > 0
Ejemplo n.º 17
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',
        null=True,
        blank=True,
    )
    hero_cta = models.CharField(
        verbose_name='Hero CTA',
        max_length=255,
        help_text='Text to display on Call to Action',
        null=True,
        blank=True,
    )
    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,
        null=True)

    # Promo section of the HomePage
    site_logo = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Site Logo'
    )

    features_text = RichTextField(
        null=True,
        blank=True,
        help_text='Write some feature description'
    )

    feature_logo_1 = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Feature Logo 1'
    )

    feature_1_title = models.CharField(
        max_length=255,
        help_text='Feature Title 1'
    )

    feature_1_text = RichTextField(
        null=True,
        blank=True,
        help_text='Write some feature 1 text description'
    )

    feature_logo_2 = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Feature Logo 2'
    )

    feature_2_title = models.CharField(
        max_length=255,
        help_text='Feature Title 2'
    )

    feature_2_text = RichTextField(
        null=True,
        blank=True,
        help_text='Write some feature 2 text description'
    )

    feature_logo_3 = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Feature Logo 3'
    )

    feature_3_title = models.CharField(
        max_length=255,
        help_text='Feature Title 3'
    )

    feature_3_text = RichTextField(
        null=True,
        blank=True,
        help_text='Write some feature 3 text description'
    )

    feature_logo_4 = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Feature Logo 4'
    )

    feature_4_title = models.CharField(
        max_length=255,
        help_text='Feature Title 4'
    )

    feature_4_text = RichTextField(
        null=True,
        blank=True,
        help_text='Write some feature 4 text description'
    )

    custom_body_message = RichTextField(
        null=True,
        blank=True,
        help_text='Write some custom body message!'
    )

    banner_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='Choose Banner Image'
    )

    boolean_choices = (
        ("yes", "Yes"),
        ("no", "No")
    )

    show_navbar = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want to display the navbar on home page and no if you don't want to.",
        default=True)

    show_nav_extra = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want the secondary navbar to show on home page or no if you don't want to",
        default=True)

    show_footer = models.CharField(
        choices=boolean_choices,
        max_length=5,
        help_text="Choose yes if you want the Footer to show on home page or no if you don't want to",
        default="yes")

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('image'),
            FieldPanel('hero_text', classname="full"),
            MultiFieldPanel([
                FieldPanel('hero_cta'),
                PageChooserPanel('hero_cta_link'),
            ])
        ], heading="Hero section"),
        StreamFieldPanel('body'),
        MultiFieldPanel([
            ImageChooserPanel('site_logo'),
            FieldPanel('features_text'),
            MultiFieldPanel([
                ImageChooserPanel('feature_logo_1'),
                FieldPanel('feature_1_title'),
                FieldPanel('feature_1_text'),
            ]),
            MultiFieldPanel([
                ImageChooserPanel('feature_logo_2'),
                FieldPanel('feature_2_title'),
                FieldPanel('feature_2_text'),
            ]),
            MultiFieldPanel([
                ImageChooserPanel('feature_logo_3'),
                FieldPanel('feature_3_title'),
                FieldPanel('feature_3_text'),
            ]),
            MultiFieldPanel([
                ImageChooserPanel('feature_logo_4'),
                FieldPanel('feature_4_title'),
                FieldPanel('feature_4_text'),
            ])
        ], heading="Feature section", classname="collapsible"),
        FieldPanel('custom_body_message'),
        ImageChooserPanel('banner_image')
    ]

    customization_panels = [
        FieldPanel('show_navbar'),
        FieldPanel('show_nav_extra'),
        FieldPanel('show_footer')
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(customization_panels, heading='Customization'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels, heading='Settings',
                   classname="settings"),
    ])

    def __str__(self):
        return self.title
Ejemplo n.º 18
0
class HomePage(BasePage):
    subpage_types = [
        "articles.Articles",
        "content.ContentPage",
        "events.Events",
        "people.People",
        "topics.Topics",
        "videos.Videos",
    ]
    template = "home.html"

    # Content fields
    subtitle = TextField(max_length=250, blank=True, default="")
    button_text = CharField(max_length=30, blank=True, default="")
    button_url = CharField(max_length=2048, blank=True, default="")
    image = ForeignKey(
        "mozimages.MozImage",
        null=True,
        blank=True,
        on_delete=SET_NULL,
        related_name="+",
    )
    featured = StreamField(
        StreamBlock(
            [
                (
                    "post",
                    PageChooserBlock(target_model=(
                        "articles.Article",
                        "externalcontent.ExternalArticle",
                    )),
                ),
                (
                    "content_page",
                    PageChooserBlock(target_model=("content.ContentPage", )),
                ),
                ("external_page", FeaturedExternalBlock()),
                (
                    "video",
                    PageChooserBlock(target_model=(
                        "videos.Video",
                        # NB: ExternalVideo is NOT allowed on the homepage
                        # "externalcontent.ExternalVideo"
                    )),
                ),
            ],
            min_num=2,
            max_num=5,
            required=False,
        ),
        null=True,
        blank=True,
        help_text=
        ("Optional space for featured posts, videos or links, min. 2, max. 5. "
         "Note that External Video is NOT allowed here."),
    )

    featured_people = StreamField(
        StreamBlock(
            [("person", PageChooserBlock(target_model="people.Person"))],
            max_num=3,
            required=False,
        ),
        null=True,
        blank=True,
        help_text="Optional featured people, max. 3",
    )

    about_title = TextField(max_length=250, blank=True, default="")
    about_subtitle = TextField(max_length=250, blank=True, default="")
    about_button_text = CharField(max_length=30, blank=True, default="")
    about_button_url = URLField(max_length=140, blank=True, default="")

    # 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
    keywords = ClusterTaggableManager(through=HomePageTag, blank=True)

    # Editor panel configuration
    content_panels = BasePage.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel("subtitle"),
                FieldPanel("button_text"),
                FieldPanel("button_url"),
            ],
            heading="Header section",
            help_text="Optional fields for the header section",
        ),
        MultiFieldPanel(
            [ImageChooserPanel("image")],
            heading="Image",
            help_text=
            ("Optional image shown when sharing this page through social media"
             ),
        ),
        StreamFieldPanel("featured"),
        StreamFieldPanel("featured_people"),
        MultiFieldPanel(
            [
                FieldPanel("about_title"),
                FieldPanel("about_subtitle"),
                FieldPanel("about_button_text"),
                FieldPanel("about_button_url"),
            ],
            heading="About section",
            help_text="Optional section to explain more about Mozilla",
        ),
    ]

    # Card panels
    card_panels = [
        MultiFieldPanel(
            [
                FieldPanel("card_title"),
                FieldPanel("card_description"),
                ImageChooserPanel("card_image"),
            ],
            heading="Card overrides",
            help_text=((
                "Optional fields to override the default title, "
                "description and image when this page is shown as a card")),
        )
    ]

    # Meta panels
    meta_panels = [
        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 = [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"),
    ])

    @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()

    @property
    def primary_topics(self):
        """The site’s top-level topics, i.e. topics without a parent topic."""
        from ..topics.models import Topic

        return Topic.published_objects.filter(parent_topics__isnull=True)
Ejemplo n.º 19
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, "
            f"max. {DESCRIPTION_MAX_LENGTH} characters"
        ),
        max_length=DESCRIPTION_MAX_LENGTH,
    )
    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=DESCRIPTION_MAX_LENGTH,
        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"),
        ]
    )

    # Search config
    search_fields = BasePage.search_fields + [  # Inherit search_fields from Page
        # "title" is already specced in BasePage
        index.SearchField("description"),
        index.SearchField("body"),
        index.SearchField("sidebar"),
        # Add FilterFields for things we may be filtering on (eg topics)
        index.FilterField("slug"),
    ]
Ejemplo n.º 20
0
class ResearchCentrePage(LegacyNewsAndEventsMixin, BasePage):
    template = "patterns/pages/researchcentre/research_centre.html"
    hero_image = models.ForeignKey(
        "images.CustomImage",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    introduction = models.TextField(max_length=500, blank=True)
    about_page_url = models.URLField(blank=True)
    about_page = models.ForeignKey(
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    about_page_link_text = models.CharField(blank=True, max_length=120)

    introduction_image = models.ForeignKey(
        get_image_model_string(),
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    video_caption = models.CharField(
        blank=True,
        max_length=80,
        help_text=_("The text dipsplayed next to the video play button"),
    )
    video = models.URLField(blank=True)

    primary_staff_url = models.URLField(
        blank=True,
        help_text=_("The external URL to the staff member page"),
        verbose_name=_("Head of centre URL"),
    )
    primary_staff_name = models.CharField(
        blank=True,
        max_length=250,
        help_text=_("The name of the staff member"),
        verbose_name=_("Head of centre full name"),
    )
    primary_staff_role = models.CharField(
        blank=True,
        max_length=120,
        help_text=_("The role of the staff member, E.G 'Head of Programme'"),
        verbose_name=_("Head of centre role"),
    )
    centre_address = RichTextField(blank=True, features=["link"])
    centre_tel = PhoneNumberField(blank=True)
    centre_tel_display_text = models.CharField(
        max_length=120,
        help_text=(
            "Specify specific text or numbers to display for the linked tel "
            "number, e.g. +44 (0)20 7590 1234 or +44 (0)7749 183783"),
        blank=True,
    )
    twitter_username = models.CharField(
        blank=True,
        max_length=15,
        help_text=_("The Research Centres Twitter username"))
    centre_email = models.EmailField(blank=True)
    more_research_centre_content_title = models.CharField(
        blank=True,
        max_length=250,
        help_text=_(
            "The title value displayed above the Research centre news carousel"
        ),
    )

    highlights_title = models.CharField(
        max_length=120,
        blank=True,
        help_text=
        _("The title value displayed above the Research highlights gallery showing project pages"
          ),
    )
    related_programmes_title = models.CharField(
        max_length=250,
        help_text=
        _("The title value displayed above the Research centre related_programmes"
          ),
    )
    staff_title = models.CharField(
        blank=True,
        max_length=250,
        help_text=_("The title value displayed above the related staff grid"),
    )
    staff_link = models.URLField(blank=True,
                                 help_text=_("Add a link to see all staff"))
    staff_link_text = models.CharField(
        blank=True,
        help_text=_("The text to display on the link to all staff"),
        max_length=80,
    )
    related_links = StreamField([("link", LinkBlock())],
                                blank=True,
                                verbose_name="Related Links")
    research_projects_link = models.URLField(
        blank=True,
        help_text=_(
            "Add a link to a pre-filtered project listing, "
            "E.G https://rca.ac.uk/research/projects/?school-or-centre=helen-hamlyn-centre#results"
        ),
    )

    content_panels = BasePage.content_panels + [
        MultiFieldPanel(
            [ImageChooserPanel("hero_image")],
            heading="Hero",
        ),
        MultiFieldPanel(
            [
                FieldPanel("introduction"),
                ImageChooserPanel("introduction_image"),
                FieldPanel("about_page_url"),
                PageChooserPanel("about_page"),
                FieldPanel("about_page_link_text"),
                FieldPanel("video"),
                FieldPanel("video_caption"),
            ],
            heading=_("Introduction"),
        ),
        MultiFieldPanel(
            [InlinePanel("research_spaces", label="Research spaces")],
            heading="Research spaces",
        ),
        MultiFieldPanel(
            [
                FieldPanel("highlights_title"),
                InlinePanel(
                    "research_projects", label=_("Project pages"), max_num=8),
                FieldPanel("research_projects_link"),
            ],
            heading=_("Research centre highlights"),
        ),
        MultiFieldPanel(
            [
                InlinePanel("research_opportunities",
                            label="Research opportunities")
            ],
            heading="Research opportunities",
        ),
        MultiFieldPanel(
            [
                FieldPanel("more_research_centre_content_title"),
                InlinePanel("research_news", label="Research guides"),
            ],
            heading="More research centre content",
        ),
        MultiFieldPanel(
            [
                FieldPanel("staff_title"),
                InlinePanel("related_staff", label="staff"),
                FieldPanel("staff_link"),
                FieldPanel("staff_link_text"),
            ],
            heading="Research Centre Staff",
        ),
        FieldPanel("related_programmes_title"),
        StreamFieldPanel("related_links"),
        FieldPanel("legacy_news_and_event_tags"),
    ]
    key_details_panels = [
        MultiFieldPanel(
            [
                FieldPanel("primary_staff_name"),
                FieldPanel("primary_staff_url"),
                FieldPanel("primary_staff_role"),
            ],
            heading="Primary staff member",
        ),
        MultiFieldPanel(
            [
                FieldPanel("centre_address"),
                FieldPanel("centre_tel"),
                FieldPanel("centre_tel_display_text"),
                FieldPanel("centre_email"),
            ],
            heading="Centre contact information",
        ),
        FieldPanel("twitter_username"),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading="Content"),
        ObjectList(key_details_panels, heading="Key details"),
        ObjectList(BasePage.promote_panels, heading="Promote"),
        ObjectList(BasePage.settings_panels, heading="Settings"),
    ])

    def get_related_projects(self):
        child_projects = []
        for value in self.research_projects.select_related("page"):
            if value.page and value.page.live:
                page = value.page.specific
                child_projects.append({
                    "title": page.title,
                    "link": page.url,
                    "image": page.hero_image,
                    "description": page.introduction,
                })
        return child_projects

    def get_research_spaces(self):
        research_spaces = []
        for value in self.research_spaces.select_related("page"):
            if value.page and value.page.live:
                page = value.page.specific
                research_spaces.append({
                    "title":
                    page.title,
                    "link":
                    page.url,
                    "image":
                    page.listing_image,
                    "description":
                    page.introduction
                    if hasattr(page, "introduction") else None,
                })
        return research_spaces

    def get_research_opportunities(self):
        research_opportunities = []
        for value in self.research_opportunities.select_related("page"):
            if value.page.live:
                page = value.page.specific
                research_opportunities.append({
                    "title": page.title,
                    "link": page.url,
                    "image": page.listing_image,
                    "description": page.introduction,
                })
        return research_opportunities

    def get_research_news(self):
        research_news = {
            "title": self.more_research_centre_content_title,
            "slides": []
        }
        for value in self.research_news.select_related("page"):
            if value.page.live:
                page = value.page.specific
                project_type = "PROJECT"
                if hasattr(page,
                           "research_types") and page.research_types.first():
                    project_type = page.research_types.first(
                    ).research_type.title
                page_type_mapping = {
                    "GuidePage": "GUIDE",
                    "ProjectPage": project_type,
                    "ResearchCentrePage": "RESEARCH CENTRE",
                    "ShortCoursePage": "SHORT COURSE",
                    "ProgrammePage": "PROGRAMME",
                }
                page_type = page_type_mapping.get(page.__class__.__name__,
                                                  None)
                research_news["slides"].append({
                    "value": {
                        "title":
                        page.title,
                        "link":
                        page.url,
                        "image":
                        page.hero_image
                        if hasattr(page, "hero_image") else page.listing_image,
                        "summary":
                        page.introduction if hasattr(page, "introduction") else
                        page.listing_summary,
                        "type":
                        page_type,
                    }
                })
        return research_news

    def get_related_programme_pages(self):
        from rca.programmes.models import ProgrammePage
        from rca.shortcourses.models import ShortCoursePage

        programme_pages_qs = ProgrammePage.objects.filter(
            related_schools_and_research_pages__page_id=self.id).live()
        short_course_pages_qs = ShortCoursePage.objects.filter(
            related_schools_and_research_pages__page_id=self.id).live()
        qs = list(chain(programme_pages_qs, short_course_pages_qs))

        programme_pages = [{
            "title": self.related_programmes_title,
            "related_items": qs
        }]
        return programme_pages

    def clean(self):
        errors = defaultdict(list)

        if self.twitter_username.startswith("@"):
            self.twitter_username = self.twitter_username[1:]

        if self.about_page and self.about_page_url:
            errors["about_page"].append(
                "Please choose between an internal page, or an external link")
        if (self.about_page and not self.about_page_link_text
                or self.about_page_url and not self.about_page_link_text):
            errors["about_page"].append(
                "Please add some link text for the about page")
        if self.staff_link and not self.staff_link_text:
            errors["staff_link_text"].append(
                "Please add some text for the link to all staff")

        if errors:
            raise ValidationError(errors)

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context["about_page"] = (self.about_page.url
                                 if self.about_page else self.about_page_url)

        context["projects"] = self.get_related_projects()
        context["research_spaces"] = self.get_research_spaces()
        context["research_opportunities"] = self.get_research_opportunities()
        context["research_news"] = self.get_research_news()
        context["related_staff"] = self.related_staff.all
        context["related_programmes"] = self.get_related_programme_pages()
        context[
            "staff_title"] = self.staff_title if self.staff_title else "Staff"

        return context
Ejemplo n.º 21
0
class ProjectPage(Page):

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

    subtitle = models.CharField(max_length=255, blank=True)
    subtitle_de = models.CharField(max_length=255, blank=True)

    teaser = RichTextField(blank=True)
    teaser_de = RichTextField(blank=True)

    BODY_BLOCKS = [
        ('richtext', RichTextBlock()),
        ('html', RawHTMLBlock()),
        ('image', ImageChooserBlock()),
    ]

    body = StreamField(BODY_BLOCKS, blank=True)
    body_de = StreamField(BODY_BLOCKS, blank=True)

    collaboration = RichTextField(blank=True)
    collaboration_de = RichTextField(blank=True)

    publications = RichTextField(blank=True)
    publications_de = RichTextField(blank=True)

    references = RichTextField(blank=True)
    references_de = RichTextField(blank=True)

    start_date = models.DateField(blank=True, null=True)
    end_date = models.DateField(blank=True, null=True)

    STATUS_IN_PROGRESS = 'IN_PROGRESS'
    STATUS_COMPLETED = 'COMPLETED'
    STATUS_CHOICES = ((STATUS_IN_PROGRESS, _('in progress')),
                      (STATUS_COMPLETED, _('completed')))

    status = models.CharField(max_length=32,
                              choices=STATUS_CHOICES,
                              default=STATUS_IN_PROGRESS)

    trans_title = TranslatedTextField('title')
    trans_subtitle = TranslatedTextField('subtitle')
    trans_teaser = TranslatedTextField('teaser')
    trans_body = TranslatedStreamField('body')
    trans_collaboration = TranslatedTextField('collaboration')
    trans_publications = TranslatedTextField('publications')
    trans_references = TranslatedTextField('references')

    search_fields = Page.search_fields + [
        index.SearchField('title_de'),
        index.SearchField('subtitle'),
        index.SearchField('subtitle_de'),
        index.SearchField('teaser'),
        index.SearchField('teaser_de'),
        index.SearchField('body'),
        index.SearchField('body_de'),
    ]

    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('subtitle', classname="full title"),
        FieldPanel('teaser', classname='full'),
        StreamFieldPanel('body', classname='full'),
        FieldPanel('collaboration', classname='full'),
        FieldPanel('publications', classname='full'),
        FieldPanel('references', classname='full'),
    ]
    content_de_panels = [
        FieldPanel('title_de', classname="full title"),
        FieldPanel('subtitle_de', classname="full title"),
        FieldPanel('teaser_de', classname='full'),
        StreamFieldPanel('body_de', classname='full'),
        FieldPanel('collaboration_de', classname='full'),
        FieldPanel('publications_de', classname='full'),
        FieldPanel('references_de', classname='full'),
    ]
    misc_panels = [
        FieldPanel('status'),
        FieldPanel('start_date'),
        FieldPanel('end_date'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(content_de_panels, heading='Content DE'),
        ObjectList(misc_panels, heading='Misc'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels,
                   heading='Settings',
                   classname='settings'),
    ])

    parent_page_types = ['projects.ProjectIndexPage']

    @property
    def color(self):
        return self.get_parent().specific.color
Ejemplo n.º 22
0
class FormPage(WagtailCaptchaEmailForm):

    title_sv = models.CharField(max_length=255)
    translated_title = TranslatedField('title', 'title_sv')
    use_recaptcha = models.BooleanField(
        default=False,
        verbose_name=_("Use Recaptcha"),
    )

    intro_en = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('contact_card', ContactCardBlock()),
        ],
        verbose_name=_('English Introduction'),
        blank=True,
    )
    intro_sv = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('contact_card', ContactCardBlock()),
        ],
        verbose_name=_('Swedish Introduction'),
        blank=True,
    )
    intro = TranslatedField('intro_en', 'intro_sv')

    thank_you_text_en = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('contact_card', ContactCardBlock()),
        ],
        verbose_name=_('English Thank You Text'),
        blank=True,
    )
    thank_you_text_sv = StreamField(
        WAGTAIL_STATIC_BLOCKTYPES + [
            ('contact_card', ContactCardBlock()),
        ],
        verbose_name=_('Swedish Thank You Text'),
        blank=True,
    )
    thank_you_text = TranslatedField('thank_you_text_en', 'thank_you_text_sv')

    form_title_en = models.CharField(verbose_name=_('English Form Title'),
                                     max_length=255,
                                     blank=True)
    form_title_sv = models.CharField(
        verbose_name=_('Swedish Form Title'),
        max_length=255,
        blank=True,
    )
    form_title = TranslatedField('form_title_en', 'form_title_sv')

    general_panels = [
        InlinePanel('form_fields', label="Form fields"),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email"),
    ]

    content_panels_en = AbstractEmailForm.content_panels + [
        StreamFieldPanel('intro_en'),
        FieldPanel('form_title_en', classname="full title"),
        StreamFieldPanel('thank_you_text_en'),
    ]

    content_panels_sv = [
        FieldPanel('title_sv', classname="full title"),
        StreamFieldPanel('intro_sv'),
        FieldPanel('form_title_sv', classname="full title"),
        StreamFieldPanel('thank_you_text_sv'),
    ]

    custom_settings_panel = Page.settings_panels + [
        MultiFieldPanel([
            FieldPanel('use_recaptcha'),
        ], 'Recaptcha')
    ]

    edit_handler = TabbedInterface([
        ObjectList(general_panels, heading=_('General')),
        ObjectList(content_panels_en, heading=_('English')),
        ObjectList(content_panels_sv, heading=_('Swedish')),
        ObjectList(Page.promote_panels, heading=_('Promote')),
        ObjectList(custom_settings_panel, heading=_('Settings')),
    ])
Ejemplo n.º 23
0
class UseCasePage(Page):

    category = models.CharField(max_length=2, choices=CATEGORY_CHOICES)

    image = models.ForeignKey(
        'a4_candy_cms_images.CustomImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name="Use Case Header Image",
        help_text="The Image that is shown on the use case item page " +
        "and the use case index page")

    title_de = models.CharField(max_length=250,
                                blank=True,
                                verbose_name="German Title")
    title_en = models.CharField(max_length=250,
                                blank=True,
                                verbose_name="English Title")

    body_streamfield_de = fields.StreamField(
        [('paragraph', blocks.RichTextBlock()),
         ('html', blocks.RawHTMLBlock()), ('examples', ExampleBlock())],
        blank=True)

    body_streamfield_en = fields.StreamField(
        [('paragraph', blocks.RichTextBlock()),
         ('html', blocks.RawHTMLBlock()), ('examples', ExampleBlock())],
        blank=True)

    subtitle = TranslatedField('title_de', 'title_en')

    teaser = TranslatedField('teaser_de', 'teaser_en')

    body = TranslatedField('body_streamfield_de', 'body_streamfield_en')

    def get_context(self, request):
        category = self.category

        if category:
            try:
                use_cases = UseCasePage.objects\
                    .filter(category=category)\
                    .exclude(id=self.id)
            except ValueError:
                use_cases = []

        context = super().get_context(request)
        context['other_use_cases'] = use_cases
        return context

    en_content_panels = [
        FieldPanel('title_en'),
        StreamFieldPanel('body_streamfield_en')
    ]

    de_content_panels = [
        FieldPanel('title_de'),
        StreamFieldPanel('body_streamfield_de')
    ]

    common_panels = [
        FieldPanel('title'),
        ImageChooserPanel('image'),
        FieldPanel('slug'),
        FieldPanel('category')
    ]

    edit_handler = TabbedInterface([
        ObjectList(common_panels, heading='Common'),
        ObjectList(en_content_panels, heading='English'),
        ObjectList(de_content_panels, heading='German')
    ])

    subpage_types = []
Ejemplo n.º 24
0
class BlogIndexPage(Page):

    featured_page = models.ForeignKey(
        'cms_blog.BlogPage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    subtitle = models.CharField(max_length=200)

    subpage_types = ['cms_blog.BlogPage']

    @property
    def blogs(self):
        blogs = BlogPage.objects.live()
        blogs = blogs.order_by('-last_published_at')
        return blogs

    def get_context(self, request):
        blogs = self.blogs

        category = request.GET.get('category')

        if category:
            try:
                category = int(category)
                blogs = blogs.filter(categories__pk=category)
            except ValueError:
                blogs = []

        page = request.GET.get('page', 1)
        paginator = Paginator(blogs, 5)

        try:
            blogs = paginator.page(page)
        except InvalidPage:
            raise Http404

        context = super(BlogIndexPage, self).get_context(request)
        context['blogs'] = blogs
        context['categories'] = Category.objects.all()
        context['category'] = category
        return context

    content_panels = [
        FieldPanel('title'),
        FieldPanel('subtitle'),
        PageChooserPanel('featured_page'),
    ]

    promote_panels = [
        MultiFieldPanel([
            FieldPanel('slug'),
            FieldPanel('seo_title'),
            FieldPanel('search_description')
        ])
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(promote_panels, heading='Promote')
    ])
Ejemplo n.º 25
0
class ProjectsPage(Page):
    headers = StreamField([
        ('h_hero', _H_HeroBlock(icon='image')),
        # ('code', blocks.RawHTMLBlock(null=True, blank=True, classname="full", icon='code'))
    ])

    price_min = models.IntegerField(
        verbose_name="Preis der billigsten Einheit", null=True, blank=False)
    price_max = models.IntegerField(
        verbose_name=
        "Preis der teuersten Einheit (leer lassen wenn nur eine Einheit vorhanden ist)",
        null=True,
        blank=True)
    buy_available = models.BooleanField(verbose_name="Kaufmöglichkeit")
    rent_available = models.BooleanField(verbose_name="Mietmöglichkeit")
    location_name = models.CharField(
        verbose_name="Ortsname (z.B. Villach-Landskron)",
        null=True,
        blank=True,
        max_length=255)
    coordinates = models.CharField(
        verbose_name=
        "Standpunkt (Koordinaten, z.B. Beispiel: 46.6120061,13.916085)",
        null=True,
        blank=True,
        max_length=255)

    sections = StreamField(
        [
            ('s_info', _S_InfoBlock(icon='fa-info')),
            ('s_contentcenter', _S_ContentCenter(icon='fa-info')),
            ('s_contentright', _S_ContentRight(icon='fa-info')),
            ('s_contentleft', _S_ContentLeft(icon='fa-info')),
            # ('s_imagegallery', _S_ImageGallery(icon='fa-info'))
        ],
        null=True,
        blank=True)

    gallery = StreamField([('g_gallery', _G_GalleryBlock(icon='fa-info'))],
                          null=True,
                          blank=True)

    flats = StreamField([('f_flats', _F_FlatsBlock(icon='fa-info'))],
                        verbose_name="Wohneinheiten-Pages",
                        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'),
        FieldPanel('price_min'),
        FieldPanel('price_max'),
        FieldPanel('buy_available'),
        FieldPanel('rent_available'),
        FieldPanel('location_name'),
        FieldPanel('coordinates'),
        StreamFieldPanel('sections'),
        StreamFieldPanel('gallery'),
        StreamFieldPanel('flats')
        # StreamFieldPanel('footers')
    ]

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

    preview_modes = []
Ejemplo n.º 26
0
class Event(Page):
    resource_type = 'event'
    parent_page_types = ['events.Events']
    subpage_types = []
    template = 'event.html'

    # Content fields
    description = TextField(max_length=250, blank=True, default='')
    image = ForeignKey('mozimages.MozImage',
                       null=True,
                       blank=True,
                       on_delete=SET_NULL,
                       related_name='+')
    body = CustomStreamField(blank=True, null=True)
    agenda = StreamField(StreamBlock([
        ('agenda_item', AgendaItemBlock()),
    ],
                                     required=False),
                         blank=True,
                         null=True)
    speakers = StreamField(StreamBlock([
        ('speaker',
         PageChooserBlock(required=False, target_model='people.Person')),
        ('external_speaker', ExternalSpeakerBlock(required=False)),
    ],
                                       required=False),
                           blank=True,
                           null=True)

    # 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',
    )

    # Meta fields
    start_date = DateField(default=datetime.date.today)
    end_date = DateField(blank=True, null=True)
    venue = TextField(
        max_length=250,
        blank=True,
        default='',
        help_text=
        'Full address of the event venue, displayed on the event detail page')
    location = CharField(
        max_length=100,
        blank=True,
        default='',
        help_text=
        'Location details (city and country), displayed on event cards')
    latitude = FloatField(blank=True, null=True)
    longitude = FloatField(blank=True, null=True)
    register_url = URLField('Register URL', blank=True, null=True)
    keywords = ClusterTaggableManager(through=EventTag, blank=True)

    # Content panels
    content_panels = Page.content_panels + [
        FieldPanel('description'),
        ImageChooserPanel('image'),
        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('venue'),
            FieldPanel('location'),
            FieldPanel('latitude'),
            FieldPanel('longitude'),
            FieldPanel('register_url'),
        ],
                        heading='Event details'),
        MultiFieldPanel(
            [
                InlinePanel('topics'),
            ],
            heading='Topics',
            help_text=
            ('These are the topic pages the article will appear on. The first '
             'topic in the list will be treated as the primary topic.')),
        MultiFieldPanel([
            FieldPanel('seo_title'),
            FieldPanel('search_description'),
            FieldPanel('keywords'),
        ],
                        heading='SEO'),
    ]

    # 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")
Ejemplo n.º 27
0
class CFGOVPage(Page):
    authors = ClusterTaggableManager(through=CFGOVAuthoredPages,
                                     blank=True,
                                     verbose_name='Authors',
                                     help_text='A comma separated list of ' +
                                     'authors.',
                                     related_name='authored_pages')
    tags = ClusterTaggableManager(through=CFGOVTaggedPages,
                                  blank=True,
                                  related_name='tagged_pages')
    language = models.CharField(choices=ref.supported_languagues,
                                default='en',
                                max_length=2)
    social_sharing_image = models.ForeignKey(
        'v1.CFGOVImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text=(
            'Optionally select a custom image to appear when users share this '
            'page on social media websites. Recommended size: 1200w x 630h. '
            'Maximum size: 4096w x 4096h.'))
    schema_json = JSONField(
        null=True,
        blank=True,
        verbose_name='Schema JSON',
        help_text=mark_safe(
            'Enter structured data for this page in JSON-LD format, '
            'for use by search engines in providing rich search results. '
            '<a href="https://developers.google.com/search/docs/guides/'
            'intro-structured-data">Learn more.</a> '
            'JSON entered here will be output in the '
            '<code>&lt;head&gt;</code> of the page between '
            '<code>&lt;script type="application/ld+json"&gt;</code> and '
            '<code>&lt;/script&gt;</code> tags.'),
    )
    force_breadcrumbs = models.BooleanField(
        "Force breadcrumbs on child pages",
        default=False,
        blank=True,
        help_text=(
            "Normally breadcrumbs don't appear on pages one or two levels "
            "below the homepage. Check this option to force breadcrumbs to "
            "appear on all children of this page no matter how many levels "
            "below the homepage they are (for example, if you want "
            "breadcrumbs to appear on all children of a top-level campaign "
            "page)."),
    )

    # This is used solely for subclassing pages we want to make at the CFPB.
    is_creatable = False

    objects = CFGOVPageManager()

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

    # These fields show up in either the sidebar or the footer of the page
    # depending on the page type.
    sidefoot = StreamField([
        ('call_to_action', molecules.CallToAction()),
        ('related_links', molecules.RelatedLinks()),
        ('related_posts', organisms.RelatedPosts()),
        ('related_metadata', molecules.RelatedMetadata()),
        ('email_signup', organisms.EmailSignUp()),
        ('sidebar_contact', organisms.SidebarContactInfo()),
        ('rss_feed', molecules.RSSFeed()),
        ('social_media', molecules.SocialMedia()),
        ('reusable_text', v1_blocks.ReusableTextChooserBlock(ReusableText)),
    ],
                           blank=True)

    # Panels
    promote_panels = Page.promote_panels + [
        ImageChooserPanel('social_sharing_image'),
        FieldPanel('force_breadcrumbs', 'Breadcrumbs'),
    ]

    sidefoot_panels = [
        StreamFieldPanel('sidefoot'),
    ]

    settings_panels = [
        MultiFieldPanel(promote_panels, 'Settings'),
        InlinePanel('categories', label="Categories", max_num=2),
        FieldPanel('tags', 'Tags'),
        FieldPanel('authors', 'Authors'),
        FieldPanel('schema_json', 'Structured Data'),
        MultiFieldPanel(Page.settings_panels, 'Scheduled Publishing'),
        FieldPanel('language', 'language'),
    ]

    # Tab handler interface guide because it must be repeated for each subclass
    edit_handler = TabbedInterface([
        ObjectList(Page.content_panels, heading='General Content'),
        ObjectList(sidefoot_panels, heading='Sidebar/Footer'),
        ObjectList(settings_panels, heading='Configuration'),
    ])

    def clean(self):
        super(CFGOVPage, self).clean()
        validate_social_sharing_image(self.social_sharing_image)

    def get_authors(self):
        """ Returns a sorted list of authors. Default is alphabetical """
        return self.alphabetize_authors()

    def alphabetize_authors(self):
        """
        Alphabetize authors of this page by last name,
        then first name if needed
        """
        # First sort by first name
        author_names = self.authors.order_by('name')
        # Then sort by last name
        return sorted(author_names, key=lambda x: x.name.split()[-1])

    def related_metadata_tags(self):
        # Set the tags to correct data format
        tags = {'links': []}
        filter_page = self.get_filter_data()
        for tag in self.specific.tags.all():
            tag_link = {'text': tag.name, 'url': ''}
            if filter_page:
                relative_url = filter_page.relative_url(filter_page.get_site())
                param = '?topics=' + tag.slug
                tag_link['url'] = relative_url + param
            tags['links'].append(tag_link)
        return tags

    def get_filter_data(self):
        for ancestor in self.get_ancestors().reverse().specific():
            if ancestor.specific_class.__name__ in [
                    'BrowseFilterablePage', 'SublandingFilterablePage',
                    'EventArchivePage', 'NewsroomLandingPage'
            ]:
                return ancestor
        return None

    def get_breadcrumbs(self, request):
        ancestors = self.get_ancestors().specific()
        for i, ancestor in enumerate(ancestors):
            if ancestor.is_child_of(request.site.root_page):
                if ancestor.specific.force_breadcrumbs:
                    return ancestors[i:]
                return ancestors[i + 1:]
        return []

    def get_appropriate_descendants(self, inclusive=True):
        return CFGOVPage.objects.live().descendant_of(self, inclusive)

    def get_appropriate_siblings(self, inclusive=True):
        return CFGOVPage.objects.live().sibling_of(self, inclusive)

    def get_context(self, request, *args, **kwargs):
        context = super(CFGOVPage, self).get_context(request, *args, **kwargs)

        for hook in hooks.get_hooks('cfgovpage_context_handlers'):
            hook(self, request, context, *args, **kwargs)

        # Add any banners that are enabled and match the current request path
        # to a context variable.
        context['banners'] = Banner.objects \
            .filter(enabled=True) \
            .annotate(
                # This annotation creates a path field in the QuerySet
                # that we can use in the filter below to compare with
                # the url_pattern defined on each enabled banner.
                path=Value(request.path, output_field=models.CharField())) \
            .filter(path__regex=F('url_pattern'))

        if self.schema_json:
            context['schema_json'] = self.schema_json

        return context

    def serve(self, request, *args, **kwargs):
        """
        If request is ajax, then return the ajax request handler response, else
        return the super.
        """
        if request.method == 'POST':
            return self.serve_post(request, *args, **kwargs)

        # Force the page's language on the request
        translation.activate(self.language)
        request.LANGUAGE_CODE = translation.get_language()
        return super(CFGOVPage, self).serve(request, *args, **kwargs)

    def _return_bad_post_response(self, request):
        if request.is_ajax():
            return JsonResponse({'result': 'error'}, status=400)

        return HttpResponseBadRequest(self.url)

    def serve_post(self, request, *args, **kwargs):
        """Handle a POST to a specific form on the page.

        Attempts to retrieve form_id from the POST request, which must be
        formatted like "form-name-index" where the "name" part is the name of a
        StreamField on the page and the "index" part refers to the index of the
        form element in the StreamField.

        If form_id is found, it returns the response from the block method
        retrieval.

        If form_id is not found, or if form_id is not a block that implements
        get_result() to process the POST, it returns an error response.
        """
        form_module = None
        form_id = request.POST.get('form_id', None)

        if form_id:
            form_id_parts = form_id.split('-')

            if len(form_id_parts) == 3:
                streamfield_name = form_id_parts[1]
                streamfield = getattr(self, streamfield_name, None)

                if streamfield is not None:
                    try:
                        streamfield_index = int(form_id_parts[2])
                    except ValueError:
                        streamfield_index = None

                    if streamfield_index is not None:
                        try:
                            form_module = streamfield[streamfield_index]
                        except IndexError:
                            form_module = None

        try:
            result = form_module.block.get_result(self, request,
                                                  form_module.value, True)
        except AttributeError:
            return self._return_bad_post_response(request)

        if isinstance(result, HttpResponse):
            return result

        context = self.get_context(request, *args, **kwargs)
        context['form_modules'][streamfield_name].update(
            {streamfield_index: result})

        return TemplateResponse(request,
                                self.get_template(request, *args, **kwargs),
                                context)

    class Meta:
        app_label = 'v1'

    def parent(self):
        parent = self.get_ancestors(inclusive=False).reverse()[0].specific
        return parent

    # To be overriden if page type requires JS files every time
    @property
    def page_js(self):
        return []

    @property
    def streamfield_js(self):
        js = []

        block_cls_names = get_page_blocks(self)
        for block_cls_name in block_cls_names:
            block_cls = import_string(block_cls_name)
            if hasattr(block_cls, 'Media') and hasattr(block_cls.Media, 'js'):
                js.extend(block_cls.Media.js)

        return js

    # Returns the JS files required by this page and its StreamField blocks.
    @property
    def media(self):
        return sorted(set(self.page_js + self.streamfield_js))

    # Returns an image for the page's meta Open Graph tag
    @property
    def meta_image(self):
        return self.social_sharing_image

    @property
    def post_preview_cache_key(self):
        return 'post_preview_{}'.format(self.id)
Ejemplo n.º 28
0
class Events(Page):
    parent_page_types = ['home.HomePage']
    subpage_types = ['events.Event']
    template = 'events.html'

    # Content fields
    featured = StreamField(
        StreamBlock([
            ('event',
             PageChooserBlock(
                 required=False,
                 target_model=[
                     'events.Event',
                     'externalcontent.ExternalEvent',
                 ],
             )),
            ('external_page', FeaturedExternalBlock()),
        ],
                    min_num=0,
                    max_num=1,
                    required=False),
        null=True,
        blank=True,
    )

    # 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'),
    ]

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

    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'

    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'),
        }
Ejemplo n.º 29
0
class ArticleConstants(models.Model):
    select_a_drug = TranslatedField()
    select_a_drug_en, select_a_drug_es = select_a_drug.init(
        models.CharField,
        ('select_a_drug_en', 'select_a_drug_es'),
        max_length=30, blank=True)

    no_drug_selected_text = TranslatedField()
    no_drug_selected_text_en, no_drug_selected_text_es = no_drug_selected_text.init(
        models.CharField,
        ('no_drug_selected_text_en', 'no_drug_selected_text_es'),
        max_length=255, blank=True)

    source = TranslatedField()
    source_en, source_es = source.init(
        models.CharField,
        ('source_en', 'source_es'),
        max_length=15, blank=True)

    campaign_caption = TranslatedField()
    campaign_caption_en, campaign_caption_es = campaign_caption.init(
        RichTextField,
        ('campaign_caption_en', 'campaign_caption_es'),
        blank=True)

    cookie_banner_message = TranslatedField()
    cookie_banner_message_en, cookie_banner_message_es = cookie_banner_message.init(
        models.TextField,
        ('cookie_banner_message_en', 'cookie_banner_message_es'),
        blank=True)

    cookie_banner_button = TranslatedField()
    cookie_banner_button_en, cookie_banner_button_es = cookie_banner_button.init(
        models.TextField,
        ('cookie_banner_button_en', 'cookie_banner_button_es'),
        blank=True)

    cookie_banner_link = TranslatedField()
    cookie_banner_link_en, cookie_banner_link_es = cookie_banner_link.init(
        models.URLField,
        ('cookie_banner_link_en', 'cookie_banner_link_es'),
        blank=True)

    default_share_blurb = TranslatedField()
    default_share_blurb_en, default_share_blurb_es = default_share_blurb.init(
        models.TextField,
        ('default_share_blurb_en', 'default_share_blurb_es'),
        blank=True)

    panels = [
        FieldPanel('select_a_drug_en'),
        FieldPanel('no_drug_selected_text_en'),
        FieldPanel('source_en'),
        FieldPanel('campaign_caption_en'),
        FieldPanel('cookie_banner_message_en'),
        FieldPanel('cookie_banner_button_en'),
        FieldPanel('cookie_banner_link_en')



    ]
    panels_es = [
        FieldPanel('select_a_drug_es'),
        FieldPanel('no_drug_selected_text_es'),
        FieldPanel('source_es'),
        FieldPanel('campaign_caption_es'),
        FieldPanel('cookie_banner_message_es'),
        FieldPanel('cookie_banner_button_es'),
        FieldPanel('cookie_banner_link_es')



    ]
    edit_handler = TabbedInterface([
        ObjectList(panels, heading='EN Content'),
        ObjectList(panels_es, heading='ES content'),
    ])


    def __str__(self):
        return "Article constants"
Ejemplo n.º 30
0
class UniquePage(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)
    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)
    sociallinks = models.CharField(null=True, blank=False, max_length=255)

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

    privacy = RichTextField(null=True,
                            blank=False,
                            features=[
                                'bold', 'italic', 'underline', 'strikethrough',
                                'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
                                'blockquote', 'ol', 'ul', 'hr', 'embed',
                                'link', 'superscript', 'subscript',
                                'document-link', 'image', 'code'
                            ])

    sociallinks = StreamField([('link', blocks.URLBlock())])

    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_individual',
          _S_IndividualBlock(null=True, blank=False, icon='user')),
         ('s_experts', _S_ExpertsBlock(null=True, blank=False, icon='pick')),
         ('s_lab', _S_LabBlock(null=True, blank=False, icon='snippet')),
         ('s_method', _S_MethodBlock(null=True, blank=False, icon='site')),
         ('s_services',
          _S_ServicesBlock(null=True, blank=False, icon='openquote')),
         ('s_reviews', _S_ReviewsBlock(null=True, blank=False, icon='form')),
         ('s_facebook',
          _S_FacebookBlock(null=True, blank=False,
                           icon='fa-facebook-official')),
         ('s_instagram',
          _S_InstagramBlock(null=True, blank=False, icon='fa-instagram')),
         ('s_pricing', _S_PricingBlock(null=True, blank=False, icon='home')),
         ('s_about', _S_AboutBlock(
             null=True, blank=False, icon='fa-quote-left')),
         ('code',
          blocks.RawHTMLBlock(
              null=True, blank=True, classname="full", icon='code'))],
        null=True,
        blank=False)

    footers = StreamField(
        [('f_info', _F_InfoBlock(null=True, blank=False, icon='placeholder')),
         ('code',
          blocks.RawHTMLBlock(
              null=True, blank=True, classname="full", icon='code'))],
        null=True,
        blank=False)

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

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

    imprint_panels = [
        MultiFieldPanel(
            [
                FieldPanel('city'),
                FieldPanel('zip_code'),
                FieldPanel('address'),
                FieldPanel('telephone'),
                FieldPanel('telefax'),
                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('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")
    ])