示例#1
0
class DirBrowsePage(PublicBasePage):
    body = StreamField(DefaultBodyFields(), blank=True, null=True)
    dir_browse_script_url = CharField(max_length=255, blank=False)

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

    subpage_types = []

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
        FieldPanel('dir_browse_script_url')
    ] + PublicBasePage.content_panels
示例#2
0
class ExhibitChildPage(PublicBasePage):
    """
    Pages for web exhibit child pages.
    """

    body = StreamField(DefaultBodyFields(), blank=True)

    subpage_types = ['lib_collections.ExhibitChildPage']

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

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

    def get_context(self, request):
        context = super(ExhibitChildPage, self).get_context(request)
        exhibit = self.get_parent_of_type('exhibit page')
        footer_img = exhibit.get_web_exhibit_footer_img(
            self.location_and_hours['page_location'].id)

        font = DEFAULT_WEB_EXHIBIT_FONT
        if exhibit.font_family:
            font = exhibit.font_family

        context['branding_color'] = exhibit.branding_color
        context['font_family'] = font
        context['google_font_link'] = exhibit.google_font_link
        context['footer_img'] = footer_img
        context['has_exhibit_footer'] = not (not footer_img)
        context['is_web_exhibit'] = True
        context['related_collections'] = exhibit.get_related_collections(
            request)
        context['exhibit_open_date'] = exhibit.exhibit_open_date
        context['exhibit_close_date'] = exhibit.exhibit_close_date
        context['exhibit_close_date'] = exhibit.exhibit_location
        return context
示例#3
0
class AskPage(PublicBasePage, ContactFields):
    """
    Page type for Ask A Librarian pages.
    """

    ask_widget_name = models.CharField(max_length=100, blank=True)
    reference_resources = RichTextField(blank=True)
    body = StreamField(DefaultBodyFields())
    phone_regex = RegexValidator(regex=PHONE_FORMAT, message=PHONE_ERROR_MSG)
    secondary_phone_number = models.CharField(validators=[phone_regex],
                                              max_length=12,
                                              blank=True)
    schedule_appointment_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        related_name='+',
        on_delete=models.SET_NULL,
        help_text='Link to a contact form')
    visit_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        related_name='+',
        on_delete=models.SET_NULL,
        help_text='Link to a location or hours page')

    subpage_types = ['public.StandardPage', 'public.PublicRawHTMLPage']

    content_panels = Page.content_panels + [
        FieldPanel('ask_widget_name'),
        FieldPanel('reference_resources'),
        MultiFieldPanel([
            PageChooserPanel('link_page'),
            FieldPanel('link_external'),
        ],
                        heading='Contact Form'),
        MultiFieldPanel([
            FieldPanel('email'),
            FieldPanel('phone_number'),
            FieldPanel('secondary_phone_number'),
            PageChooserPanel('visit_page'),
            PageChooserPanel('schedule_appointment_page'),
        ],
                        heading='General Contact'),
        StreamFieldPanel('body'),
    ] + PublicBasePage.content_panels

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('ask_widget_name'),
        index.SearchField('reference_resources'),
        index.SearchField('body'),
        index.SearchField('email'),
        index.SearchField('email_label'),
        index.SearchField('phone_number'),
        index.SearchField('body'),
    ]

    @property
    def ask_form_name(self):
        """
        Get the name of the chat widget.

        Returns:
            String, name of the ask widget.
        """
        return self.ask_widget_name

    @property
    def contact_link(self):
        """
        Return an html link for contacting 
        a librarian by email.
        """
        text = '<i class="fa fa-envelope-o fa-2x"></i> Email'
        if self.link_page:
            return '<a href="%s">%s</a>' % (self.link_page.url, text)
        elif self.email:
            return '<a href="mailto:%s">%s</a>' % (self.email, text)
        else:
            return False

    @property
    def has_right_sidebar(self):
        """
        Determine if a right sidebar should
        be displayed on AskPages.

        Returns:
            boolean
        """
        fields = [
            self.contact_link, self.phone_number, self.secondary_phone_number,
            self.schedule_appointment_page, self.visit_page
        ]
        if self.base_has_right_sidebar():
            return True
        else:
            for field in fields:
                if field:
                    return True
        return False

    def get_context(self, request):
        context = super(AskPage, self).get_context(request)
        context['ask_pages'] = AskPage.objects.live()

        return context
class AskPage(PublicBasePage, ContactFields):
    """
    Page type for Ask A Librarian pages.
    """

    intro = StreamField(
        [
            ('paragraph', RichTextBlock()),
            ('reusable_content_block', ReusableContentBlock()),
            ('html', RawHTMLBlock()),
        ],
        null=True,
        blank=True,
    )
    ask_widget_name = models.CharField(max_length=100, blank=True)
    body = StreamField(DefaultBodyFields(
        null=True,
        blank=True,
    ))
    reference_resources = RichTextField(
        blank=True,
        help_text='Links to guide links and other \
        Ask pages. Make new sections with Header 3'
    )
    phone_regex = RegexValidator(regex=PHONE_FORMAT, message=PHONE_ERROR_MSG)
    secondary_phone_number = models.CharField(
        validators=[phone_regex],
        max_length=12,
        blank=True,
        verbose_name="SMS Number"
    )
    schedule_appointment_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        related_name='+',
        on_delete=models.SET_NULL,
        help_text='Shows up as Schedule icon link. Link to a contact form'
    )
    visit_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        related_name='+',
        on_delete=models.SET_NULL,
        help_text='Link to a location or hours page'
    )

    subpage_types = ['public.StandardPage', 'public.PublicRawHTMLPage']

    content_panels = Page.content_panels + [
        StreamFieldPanel('intro'),
        FieldPanel('ask_widget_name'),
        StreamFieldPanel('body'),
        MultiFieldPanel(
            [
                FieldPanel('phone_number'),
                FieldPanel('secondary_phone_number'),
                PageChooserPanel('visit_page'),
                PageChooserPanel('schedule_appointment_page'),
            ],
            heading='Other Ways to Ask: General Contact'
        ),
        MultiFieldPanel(
            [
                PageChooserPanel('link_page'),
                FieldPanel('link_external'),
                FieldPanel('email'),
            ],
            heading='Other Ways to Ask: Email Icon Link',
            help_text='Shows up as Email icon link. Can only have one.'
        ),
        FieldPanel('reference_resources'),
    ] + PublicBasePage.content_panels

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('ask_widget_name'),
        index.SearchField('reference_resources'),
        index.SearchField('body'),
        index.SearchField('email'),
        index.SearchField('email_label'),
        index.SearchField('phone_number'),
        index.SearchField('body'),
    ]

    @property
    def ask_form_name(self):
        """
        Get the name of the chat widget.

        Returns:
            String, name of the ask widget.
        """
        return self.ask_widget_name

    @property
    def contact_link(self):
        """
        Return an html link for contacting
        a librarian by email.
        """
        text = '<span class="material-icons ask-icons" aria-hidden="true">mail_outline</span> Email'
        if self.link_page:
            return '<a href="%s">%s</a>' % (self.link_page.url, text)
        elif self.email:
            return '<a href="mailto:%s">%s</a>' % (self.email, text)
        else:
            return False

    @property
    def has_right_sidebar(self):
        """
        Determine if a right sidebar should
        be displayed on AskPages.

        Returns:
            boolean
        """
        fields = [
            self.contact_link, self.phone_number, self.secondary_phone_number,
            self.schedule_appointment_page, self.visit_page
        ]
        if self.base_has_right_sidebar():
            return True
        else:
            for field in fields:
                if field:
                    return True
        return False

    def get_context(self, request):
        context = super(AskPage, self).get_context(request)
        context['ask_pages'] = AskPage.objects.live()

        return context
示例#5
0
class StaffPage(BasePageWithoutStaffPageForeignKeys):
    """
    Staff profile content type.
    """

    subpage_types = ['base.IntranetPlainPage']
    # editable by HR.
    cnetid = CharField(
        blank=False,
        help_text=
        'Campus-wide unique identifier which links this record to the campus directory.',
        max_length=255)
    chicago_id = CharField(blank=True,
                           help_text='Campus-wide unique identifier',
                           max_length=9)
    display_name = CharField(
        blank=True,
        help_text='Version of this staff person\'s name to display.',
        max_length=255,
        null=True)
    official_name = CharField(
        blank=True,
        help_text='Official version of this staff person\'s name.',
        max_length=255,
        null=True)
    first_name = CharField(blank=True,
                           help_text='First name, for sorting.',
                           max_length=255,
                           null=True)
    middle_name = CharField(blank=True,
                            help_text='Middle name, for sorting.',
                            max_length=255,
                            null=True)
    last_name = CharField(blank=True,
                          help_text='Last name, for sorting.',
                          max_length=255,
                          null=True)
    position_title = CharField(blank=True,
                               help_text='Position title.',
                               max_length=255,
                               null=True)
    employee_type = IntegerField(
        choices=EMPLOYEE_TYPES,
        default=1,
        help_text='Clerical, exempt, non-exempt, IT or Librarian.')
    position_eliminated = BooleanField(
        default=False, help_text='Position will not be refilled.')
    supervisor_override = models.ForeignKey(
        'staff.StaffPage',
        blank=True,
        help_text=
        'If supervisor cannot be determined by the staff person\'s unit, specify supervisor here.',
        null=True,
        on_delete=models.SET_NULL,
        related_name='supervisor_override_for')
    supervises_students = BooleanField(default=False,
                                       help_text='For HR reporting.')
    profile_picture = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        help_text=
        'Profile pictures should be frontal headshots, preferrably on a gray background.',
        null=True,
        on_delete=models.SET_NULL,
        related_name='+')
    pronouns = CharField(
        blank=True,
        help_text='Your pronouns, example: (they/them/theirs)',
        max_length=255,
        null=True)
    libguide_url = models.URLField(
        blank=True,
        help_text='Your profile page on guides.lib.uchicago.edu.',
        max_length=255,
        null=True)
    bio = StreamField(
        DefaultBodyFields(),
        blank=True,
        help_text='A brief bio highlighting what you offer to Library users.',
        null=True)
    cv = models.ForeignKey('wagtaildocs.Document',
                           blank=True,
                           help_text='Your CV or resume.',
                           null=True,
                           on_delete=models.SET_NULL,
                           related_name='+')
    is_public_persona = BooleanField(
        default=False, help_text='(display changes not yet implemented)')
    orcid_regex = RegexValidator(regex=ORCID_FORMAT, message=ORCID_ERROR_MSG)
    orcid = CharField(blank=True,
                      help_text='See https://orcid.org for more information.',
                      max_length=255,
                      null=True,
                      validators=[orcid_regex])

    objects = StaffPageManager()

    def get_employee_type(self):
        """
        Get the serialized employee type for display
        in the api. Converts the integer representation
        from the database to a human readable string.

        Returns:
            String
        """
        try:
            return EMPLOYEE_TYPES[0][self.employee_type]
        except (IndexError):
            return ''

    def get_serialized_units(self):
        """
        Return a serialized list of library units assigned to
        the staff member.

        Returns:
            List
        """
        return [
            str(Page.objects.get(id=u['library_unit_id']))
            for u in self.staff_page_units.values()
        ]

    api_fields = [
        APIField('cnetid'),
        APIField('employee_type',
                 serializer=serializers.CharField(source='get_employee_type')),
        APIField('position_title'),
        APIField('position_eliminated'),
        APIField('supervises_students'),
        APIField(
            'library_units',
            serializer=serializers.ListField(source='get_serialized_units')),
    ]

    @property
    def get_staff_subjects(self):
        """
        Get the subjects beloning to the staff member - UNTESTED
        """
        # MT note: get_public_profile is an undefined value; this
        # should be fixed
        pass
        # return get_public_profile('elong')

    @property
    def is_subject_specialist(self):
        """
        See if the staff member is a subject
        specialist - PLACEHOLDER
        """
        return self.get_subjects() != ''

    @property
    def public_page(self):
        """
        Get a public staff profile page for the
        library expert if one exists.
        """
        from public.models import StaffPublicPage  # Should try to do better
        try:
            return StaffPublicPage.objects.get(cnetid=self.cnetid)
        except (IndexError):
            return None

    @property
    def get_supervisors(self):
        if self.supervisor_override:
            return [self.supervisor_override]
        else:
            supervisors = []
            for u in self.staff_page_units.all():
                try:
                    if u.library_unit.department_head.cnetid == self.cnetid:
                        p = u.library_unit.get_parent().specific
                        if p.department_head:
                            supervisors.append(p.department_head)
                    else:
                        supervisors.append(u.library_unit.department_head)
                except AttributeError:
                    continue
            return supervisors

    def get_subjects(self):
        """
        Get all the subjects for a staff member.
        Must return a string for elasticsearch.

        Returns:
            String, concatenated list of subjects.
        """
        subject_list = self.staff_subject_placements.values_list('subject',
                                                                 flat=True)
        return '\n'.join(
            Subject.objects.get(id=subject).name for subject in subject_list)

    def get_subject_objects(self):
        """
        Get all the subject objects for a staff member.

        Returns:
            Set of subjects for a staff member.
        """
        subject_ids = (Subject.objects.get(id=sid)
                       for sid in self.staff_subject_placements.values_list(
                           'subject_id', flat=True))
        return set(subject_ids)

    def get_staff(self):
        """
        Get a queryset of the staff members this
        person supervises.

        TO DO: include a parameter that controls whether this is
        recursive or not. If it's recursive it should look into the
        heirarchy of UnitPages to get sub-staff.

        Returns:
            a queryset of StaffPage objects.
        """

        cnetids = set()
        for s in StaffPage.objects.all():
            if not s == self:
                if s.supervisor_override:
                    cnetids.add(s.cnetid)
                else:
                    for u in s.staff_page_units.filter(
                            library_unit__department_head=self):
                        try:
                            cnetids.add(u.page.cnetid)
                        except:
                            continue

        return StaffPage.objects.filter(cnetid__in=list(cnetids))

    @staticmethod
    def get_staff_by_building(building_str):
        building = 0
        for b in BUILDINGS:
            if b[1] == building_str:
                building = b[0]
        if building > 0:
            return StaffPage.objects.live().filter(
                staff_page_units__library_unit__building=building).distinct()
        else:
            return StaffPage.objects.none()

    content_panels = Page.content_panels + [
        ImageChooserPanel('profile_picture'),
        FieldPanel('pronouns'),
        StreamFieldPanel('bio'),
        DocumentChooserPanel('cv'),
        FieldPanel('libguide_url'),
        FieldPanel('is_public_persona'),
        InlinePanel('staff_subject_placements', label='Subject Specialties'),
        InlinePanel('expertise_placements', label='Expertise'),
        FieldPanel('orcid')
    ] + BasePageWithoutStaffPageForeignKeys.content_panels

    # for a thread about upcoming support for read-only fields,
    # see: https://github.com/wagtail/wagtail/issues/2893
    human_resources_panels = [
        FieldPanel('cnetid'),
        MultiFieldPanel(
            [
                FieldPanel('display_name'),
                FieldPanel('official_name'),
                FieldPanel('first_name'),
                FieldPanel('middle_name'),
                FieldPanel('last_name'),
                FieldPanel('position_title'),
                InlinePanel('staff_page_email', label='Email Addresses'),
                InlinePanel('staff_page_phone_faculty_exchange',
                            label='Phone Number and Faculty Exchange'),
                InlinePanel('staff_page_units', label='Library Units'),
                FieldPanel('employee_type'),
                FieldPanel('position_eliminated'),
                FieldPanel('supervises_students'),
                PageChooserPanel('supervisor_override'),
            ],
            heading=
            'Human-resources editable fields. These fields will push to the campus directory (where appropriate).'
        ),
        MultiFieldPanel(
            [
                FieldPanel('chicago_id'),
            ],
            heading=
            'Read-only fields. These values are pulled from the campus directory.'
        )
    ]

    search_fields = BasePageWithoutStaffPageForeignKeys.search_fields + [
        index.SearchField('profile_picture'),
        index.SearchField('cv'),
        index.SearchField('libguide_url'),
        index.SearchField('orcid'),
        index.SearchField('position_title')
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(Page.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels,
                   heading='Settings',
                   classname="settings"),
        ObjectList(human_resources_panels, heading='Human Resources Info'),
    ])

    class Meta:
        ordering = ['last_name', 'first_name']

    def get_context(self, request):
        position_title = self.position_title
        emails = self.staff_page_email.all().values_list('email', flat=True)

        units = set()
        for staff_page_unit in self.staff_page_units.all():
            try:
                unit_title = staff_page_unit.library_unit.get_full_name()
            except:
                unit_title = None
            try:
                unit_url = staff_page_unit.library_unit.intranet_unit_page.first(
                ).url
            except:
                unit_url = None
            units.add(json.dumps({'title': unit_title, 'url': unit_url}))
        units = list(map(json.loads, list(units)))

        subjects = []
        for subject in self.staff_subject_placements.all():
            subjects.append({'name': subject.subject.name, 'url': ''})

        group_memberships = []
        for group_membership in self.member.all():
            if group_membership.parent.is_active:
                group_memberships.append({
                    'group': {
                        'title': group_membership.parent.title,
                        'url': group_membership.parent.url
                    },
                    'role': group_membership.role
                })

        context = super(StaffPage, self).get_context(request)
        context['position_title'] = position_title
        context['emails'] = emails
        context['units'] = units
        context['subjects'] = subjects
        context['group_memberships'] = group_memberships
        return context
示例#6
0
class ConferencePage(PublicBasePage, SocialMediaFields):
    """
    Main page for creating conferences.
    """
    # Generic variables
    hex_regex = RegexValidator(regex='^#[a-zA-Z0-9]{6}$', \
        message='Please enter a hex color, e.g. #012043')

    # Field definitions
    primary_branding_color= models.CharField(validators=[hex_regex], \
        max_length=7, blank=True)
    secondary_branding_color= models.CharField(validators=[hex_regex], \
        max_length=7, blank=True)
    location = models.ForeignKey(
        'public.LocationPage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='%(app_label)s_%(class)s_related')
    start_date = models.DateTimeField(blank=True, null=True)
    end_date = models.DateTimeField(blank=True, null=True)
    current = models.BooleanField(default=True, \
        help_text="Uncheck this when the conference has transpired")
    conference_logo = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    secondary_registration_heading = models.CharField(max_length=40,
                                                      blank=True)
    secondary_registration_description = models.TextField(blank=True)
    body = StreamField(DefaultBodyFields())

    # Panels and subpage types
    content_panels = Page.content_panels + [
        MultiFieldPanel([
            ImageChooserPanel('banner_image'),
            FieldPanel('banner_title'),
            FieldPanel('banner_subtitle'),
        ],
                        heading='Banner'),
        MultiFieldPanel(
            [
                FieldPanel('primary_branding_color'),
                FieldPanel('secondary_branding_color'),
                ImageChooserPanel('conference_logo'),
            ],
            heading='Branding',
        ),
        MultiFieldPanel(
            [
                FieldPanel('start_date'),
                FieldPanel('end_date'),
            ],
            heading='Dates and Times',
        ),
        FieldPanel('location'),
        FieldPanel('current'),
        InlinePanel('main_registration', label='Main Registration Link'),
        MultiFieldPanel(
            [
                FieldPanel('secondary_registration_heading'),
                FieldPanel('secondary_registration_description'),
                InlinePanel('sub_registration',
                            label='Secondary Registration Link'),
            ],
            heading='Secondary Registration Links',
        ),
        InlinePanel('sponsors', label='Sponsors'),
        InlinePanel('organizers', label='Organizers'),
        StreamFieldPanel('body'),
    ] + SocialMediaFields.panels + PublicBasePage.content_panels

    subpage_types = ['conferences.ConferenceSubPage', 'redirects.RedirectPage']

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('banner_image'),
        index.SearchField('primary_branding_color'),
        index.SearchField('secondary_branding_color'),
        index.SearchField('location'),
        index.SearchField('current'),
        index.SearchField('conference_logo'),
        index.SearchField('body'),
    ]
    api_fields = ('body', )

    @property
    def has_right_sidebar(self):
        """
        Test to see if a right sidebar should be
        displayed.

        Returns:
            Boolean
        """
        fields = [self.sponsors, self.organizers, self.sub_registration, \
            self.secondary_registration_heading, self.secondary_registration_description]
        return self.base_has_right_sidebar() or self.has_field(fields)

    def has_conf_banner(self, current_site):
        """
        Used to override the boolean [0] value for PublicBasePage
        get_banner. 

        Args:
            current_site: object
        """
        return self.get_banner(current_site)[0] or (self.primary_branding_color
                                                    and self.banner_title)

    def get_banner(self, current_site):
        """
        Override the default get_banner method so that
        banners will always display as long as a title
        is present.

        Args:
            current_site: site object.

        Returns:
            See get_banner in PublicBasePage. 
        """
        try:
            # Base case
            if self.banner_title:
                return (True, self.banner_image, self.banner_feature,
                        self.banner_title, self.banner_subtitle,
                        self.relative_url(current_site), self.title)
            # Recursive case
            else:
                return self.get_parent().specific.get_banner(current_site)
        # Reached the top of the tree (could factor this into an if)
        except (AttributeError):
            return (False, None, None, '', '', '', '')

    # Context
    def get_context(self, request):
        context = super(ConferencePage, self).get_context(request)
        current_site = Site.find_for_request(request)
        main_reg = self.main_registration.all()
        has_sidebar = self.has_left_sidebar(context) or bool(main_reg)
        context['has_left_sidebar'] = has_sidebar
        context['content_div_css'] = self.get_conditional_css_classes(
            'content', has_sidebar)
        context['breadcrumb_div_css'] = self.get_conditional_css_classes(
            'breadcrumbs', has_sidebar)
        context['has_banner'] = self.has_conf_banner(current_site)
        context['primary_branding_color'] = self.primary_branding_color
        context['secondary_branding_color'] = self.secondary_branding_color
        context['conference_logo'] = self.conference_logo
        context['conference_title'] = self.title
        context['has_social_media'] = self.has_social_media
        context['main_registration'] = main_reg
        context['sponsors'] = self.sponsors.all()
        context['organizers'] = self.organizers.all()
        context['secondary_registration'] = self.sub_registration.all()
        context[
            'secondary_registration_heading'] = self.secondary_registration_heading
        context[
            'secondary_registration_description'] = self.secondary_registration_description
        context['home'] = self.relative_url(current_site)
        return context
示例#7
0
class ConferenceSubPage(PublicBasePage):
    """
    Subpages for conferences. These inherit 
    most of their template "goodness" from 
    parent ConferencePage.
    """
    body = StreamField(DefaultBodyFields())

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

    subpage_types = ['conferences.ConferenceSubPage']

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

    api_fields = ('body', )

    @property
    def has_right_sidebar(self):
        """
        Override default test to see if a right 
        sidebar should be displayed.

        Returns:
            Boolean
        """
        parent = self.get_parent_of_type('conference page')
        return parent.has_right_sidebar

    @property
    def has_social_media(self):
        """
        Override default test for social media.

        Returns:
            Boolean
        """
        parent = self.get_parent_of_type('conference page')
        return parent.has_social_media

    # Context
    def get_context(self, request):
        context = super(ConferenceSubPage, self).get_context(request)
        current_site = Site.find_for_request(request)
        parent = self.get_parent_of_type('conference page')
        main_reg = parent.main_registration.all()
        has_sidebar = parent.has_left_sidebar(context) or bool(main_reg)

        # Set social media fields dynamically and
        # get all the values from the parent page.
        # This doesn't seem like a good practice
        # How else can this be done?
        social_media_fields = [
            f.name for f in SocialMediaFields._meta.get_fields()
        ]
        for field in social_media_fields:
            exec('self.' + field + ' = ' + 'parent.' + field)

        context['primary_branding_color'] = parent.primary_branding_color
        context['secondary_branding_color'] = parent.secondary_branding_color
        context['conference_logo'] = parent.conference_logo
        context['conference_title'] = parent.title
        context['has_social_media'] = parent.has_social_media
        context['main_registration'] = parent.main_registration.all()
        context['sponsors'] = parent.sponsors.all()
        context['organizers'] = parent.organizers.all()
        context['secondary_registration'] = parent.sub_registration.all()
        context[
            'secondary_registration_heading'] = parent.secondary_registration_heading
        context[
            'secondary_registration_description'] = parent.secondary_registration_description
        context['home'] = parent.relative_url(current_site)
        return context
示例#8
0
class LibNewsPage(PublicBasePage):

    def __init__(self, *args, **kwargs):
        super(LibNewsPage, self).__init__(*args, **kwargs)
        self.news_pages = LibNewsPage.objects.live(
        ).prefetch_related('lib_news_categories')

    body = StreamField(DefaultBodyFields())
    thumbnail = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    alt_text = models.CharField(max_length=100, blank=True)
    is_feature_story = models.BooleanField(default=False)
    excerpt = RichTextField(blank=True)
    related_exhibits = StreamField(
        RelatedExhibitBlock(required=False), blank=True, default=[]
    )
    by_staff_or_unit = models.ForeignKey(
        'lib_news.PublicNewsAuthors',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    custom_author_byline = models.CharField(max_length=360, blank=True)
    published_at = models.DateTimeField(default=timezone.now)
    library_kiosk = models.BooleanField(default=False)
    law_kiosk = models.BooleanField(default=False)
    sciences_kiosk = models.BooleanField(default=False)
    scrc_kiosk = models.BooleanField(default=False)
    treat_as_webpage = models.BooleanField(
        default=False,
        help_text='Functionally converts this page to a standard page. \
        If checked, the page will not appear in news feeds'
    )
    exhibit_story_hours_override = RichTextField(blank=True)

    def get_categories(self):
        """
        Get a list of categories assigned to the news page. Categories
        are cached in redis as a dictionary where the keys are page IDs
        and the values are lists of string category names.

        Returns:
            list of strings
        """
        try:
            dcache = caches['default']
            cdict = {}
            pid = self.id
            if 'news_cats' not in dcache:
                dcache.set('news_cats', cdict, NEWS_CACHE_TTL)
            if 'news_cats' in dcache:
                cdict = dcache.get('news_cats')
                if pid in cdict:
                    cats = cdict[pid]
                else:
                    cats = [
                        str(cat)
                        for cat in self.lib_news_categories.get_object_list()
                    ]
                    cdict[pid] = cats
                    dcache.set('news_cats', cdict, NEWS_CACHE_TTL)
            return cats
        # This is a FakeQuerySet and we are probably in preview mode.
        # To handle this, we won't show any categories.
        except (AttributeError):
            return [
                'Can\'t load categories in PREVIEW',
                'Check categories on the LIVE page'
            ]

    @property
    def short_description(self):
        if self.excerpt:
            retval = self.excerpt
        else:
            html = str(self.body).replace('</p>', '</p> ')
            retval = text.Truncator(html).words(100, html=True)
        # return retval
        return bleach.clean(
            retval,
            tags=['a', 'b', 'i'],
            attributes={'a': ['href', 'rel', 'data', 'id', 'linktype']},
            strip=True,
            strip_comments=True,
        )

    @property
    def has_right_sidebar(self):
        """
        Determine if a right sidebar should
        be displayed in the template.

        Returns:
            boolean
        """
        return True

    def get_recent_stories(self, n, field):
        """
        Gets the n most rescent stories sorted by the
        field name passed.

        Args:
            n: int, number of stories to return

            field: string, field to be passed to a
            Django QuerySet filter, e.g. '-published_at'.
        """
        return self.news_pages.order_by(field).exclude(thumbnail=None
                                                       ).exclude(id=self.id)[:n]

    subpage_types = []

    ROW_CLASS = 'col4'

    content_panels = Page.content_panels + [
        MultiFieldPanel(
            [
                ImageChooserPanel('thumbnail'),
                FieldPanel('alt_text'),
            ],
            heading='Thumbnail',
        ),
        FieldPanel('is_feature_story'),
        FieldPanel('excerpt'),
        StreamFieldPanel('body'),
        InlinePanel('lib_news_categories', label='Categories'),
        FieldPanel('published_at'),
        MultiFieldPanel(
            [
                SnippetChooserPanel('by_staff_or_unit'),
                FieldPanel('custom_author_byline'),
            ],
            heading='Author'
        ),
        MultiFieldPanel(
            [
                FieldRowPanel(
                    [
                        FieldPanel('law_kiosk', classname=ROW_CLASS),
                        FieldPanel('sciences_kiosk', classname=ROW_CLASS),
                        FieldPanel('scrc_kiosk', classname=ROW_CLASS),
                        FieldPanel('library_kiosk', classname=ROW_CLASS),
                    ]
                )
            ],
            heading='Publish to'
        ),
    ] + PublicBasePage.content_panels

    widget_content_panels = [
        StreamFieldPanel('related_exhibits'),
        FieldPanel('treat_as_webpage'),
        MultiFieldPanel(
            [
                FieldPanel('quicklinks_title'),
                FieldPanel('quicklinks'),
                FieldPanel('view_more_link_label'),
                FieldPanel('view_more_link'),
                FieldPanel('change_to_callout'),
            ],
            heading='Rich Text'
        ),
        FieldPanel('exhibit_story_hours_override'),
    ]

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

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('body', partial_match=True),
        index.SearchField('alt_text'),
        index.SearchField('excerpt'),
        index.SearchField('related_exhibits'),
        index.SearchField('custom_author_byline'),
        index.SearchField('published_at'),
    ]

    api_fields = [
        APIField('is_feature_story'),
        APIField(
            'categories',
            serializer=serializers.ListField(source='get_categories')
        ),
        APIField(
            'thumbnail', serializer=ImageRenditionField('fill-500x425-c50')
        ),
        APIField(
            'thumbnail_alt_text',
            serializer=serializers.CharField(source='alt_text')
        ),
        APIField('published_at'),
        APIField('treat_as_webpage'),
    ]

    def get_context(self, request):
        """
        Override the page object's get context method.
        """
        context = super(LibNewsPage, self).get_context(request)
        parent = self.get_parent_of_type('lib news index page')
        parent_context = parent.get_context(request)
        self.events_feed_url = parent.events_feed_url
        context['categories'] = parent.get_alpha_cats()
        context['tagged'] = self.get_categories()
        context['category_url_base'] = parent_context['category_url_base']
        context['contacts'] = parent_context['contacts']
        context['display_current_web_exhibits'] = parent_context[
            'display_current_web_exhibits']
        context['current_exhibits'] = parent_context['current_exhibits']
        context['events_feed'] = parent_context['events_feed']
        context['recent_stories'] = self.get_recent_stories(3, '-published_at')
        context['content_div_css'] = parent_context['content_div_css']
        context['right_sidebar_classes'] = parent_context[
            'right_sidebar_classes']
        context['nav'] = parent_context['nav']
        context['libra'] = parent_context['libra']
        return context
示例#9
0
class IntranetUnitsPage(BasePage, Email, PhoneNumber):
    """
    Content type for department pages on the intranet. 
    """

    unit = models.ForeignKey('directory_unit.DirectoryUnit',
                             related_name='intranet_unit_page',
                             null=True,
                             blank=True,
                             on_delete=models.SET_NULL)

    intro = StreamField(DefaultBodyFields(), blank=True)

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

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

    internal_email = models.EmailField(max_length=255, blank=True)

    staff_only_email = models.EmailField(max_length=254, blank=True)

    body = StreamField(DefaultBodyFields(), null=True, blank=True)

    show_staff = models.BooleanField(default=False)

    show_departments = models.BooleanField(default=False)

    subpage_types = ['base.IntranetIndexPage', 'base.IntranetPlainPage', 'intranetforms.IntranetFormPage', \
    'intranettocs.TOCPage', 'intranetunits.IntranetUnitsPage', 'intranetunits.IntranetUnitsReportsIndexPage']

    search_fields = BasePage.search_fields + [
        index.SearchField('intro'),
        index.SearchField('internal_location'),
        index.SearchField('internal_phone_number'),
        index.SearchField('internal_email'),
        index.SearchField('staff_only_email'),
        index.SearchField('body'),
    ]

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

        context['phone'] = ''
        if self.specific.internal_phone_number:
            context['phone'] = self.specific.internal_phone_number

        context['location'] = ''
        if self.specific.internal_location:
            context['location'] = self.specific.internal_location

        context['email'] = ''
        if self.specific.internal_email:
            context['email'] = self.specific.internal_email

        context['show_staff'] = self.show_staff

        context['show_departments'] = self.show_departments

        department_members = []
        if self.specific.unit:
            units = self.specific.unit.get_descendants(True)

            staff_pages = []
            for v in StaffPagePageVCards.objects.filter(page__live=True,
                                                        unit__in=units):
                staff_page = v.staffpagepagevcards.page
                if staff_page not in staff_pages:
                    staff_pages.append(staff_page)

            # sorting: supervisors first, alphabetically; then non-supervisors, alphabetically.
            supervisors = list(
                map(lambda u: u.supervisor,
                    UnitSupervisor.objects.filter(unit=self.specific.unit)))
            supervisor_staff = sorted(list(
                set(staff_pages).intersection(supervisors)),
                                      key=lambda s: s.title)
            non_supervisor_staff = sorted(list(
                set(staff_pages).difference(supervisors)),
                                          key=lambda s: s.title)
            staff_pages = supervisor_staff + non_supervisor_staff

            for staff_page in staff_pages:
                titles = []
                emails = []
                phone_numbers = []
                for v in StaffPagePageVCards.objects.filter(page=staff_page,
                                                            unit__in=units):
                    if not v.title in titles:
                        titles.append(v.title)
                    if not v.email in emails:
                        emails.append(v.email)
                    if not v.phone_number in phone_numbers:
                        phone_numbers.append(v.phone_number)

                if len(emails) > 0:
                    email = emails[0]
                else:
                    email = ''

                department_members.append({
                    'title': staff_page.title,
                    'url': staff_page.url,
                    'jobtitle': "<br/>".join(titles),
                    'email': email,
                    'phone': "<br/>".join(phone_numbers),
                })

        context['department_members'] = department_members

        department_units = []
        if self.unit:
            for directory_unit in DirectoryUnit.objects.filter(
                    parentUnit=self.unit):
                intranet_unit_pages = directory_unit.intranet_unit_page.all(
                ).filter(live=True, show_in_menus=True)
                if intranet_unit_pages:
                    unit = {
                        'title': intranet_unit_pages[0].title,
                        'url': intranet_unit_pages[0].url,
                        'location': intranet_unit_pages[0].internal_location,
                        'phone_number':
                        intranet_unit_pages[0].internal_phone_number,
                        'email': intranet_unit_pages[0].internal_email
                    }

                    supervisors = []
                    for s in UnitSupervisor.objects.filter(
                            unit=directory_unit):
                        if s.supervisor != None:
                            supervisors.append({
                                'title':
                                s.supervisor.title,
                                'url':
                                s.supervisor.url,
                                'phone_number':
                                s.supervisor.vcards.all()[0].phone_number,
                                'email':
                                s.supervisor.vcards.all()[0].email,
                            })
                    unit['supervisors'] = supervisors
                    department_units.append(unit)

        # split the department units into lists of lists, each inner list containing 4 or less items.
        context['department_unit_rows'] = [
            department_units[i:i + 4]
            for i in range(0, len(department_units), 4)
        ]

        #reports
        tmp = []
        unit_reports_pages = IntranetUnitsReportsPage.objects.descendant_of(
            self)
        for unit_reports_page in unit_reports_pages:
            for r in unit_reports_page.intranet_units_reports.all():
                if not r.link and not r.document.url:
                    continue
                report = {
                    'summary': r.summary,
                    'date': r.date.strftime("%b. %-d, %Y"),
                    'sortdate': r.date.strftime("%Y%m%d")
                }
                if r.link:
                    report['url'] = r.link
                elif r.document.url:
                    report['url'] = r.document.url
                tmp.append(report)
        reports = sorted(tmp, key=lambda r: r['sortdate'], reverse=True)[:3]

        context['reports'] = reports

        return context
示例#10
0
class NewsPage(BasePage):
    """
    News story content type used on intranet pages.
    """
    excerpt = RichTextField(
        blank=True,
        null=True,
        help_text=
        'Shown on the News feed. Populated automatically from “Body” if left empty.'
    )
    author = models.ForeignKey('staff.StaffPage',
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL,
                               related_name='news_stories')
    story_date = models.DateField(
        default=timezone.now,
        help_text=
        'If you use Settings to publish a future post, put the publish date here. Otherwise, leave today as the story date.'
    )
    sticky_until = models.DateField(
        blank=True, null=True, help_text='To be used by Admin and HR only.')
    thumbnail = models.ForeignKey('wagtailimages.Image',
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    alt_text = models.CharField(max_length=100, blank=True)
    body = StreamField(DefaultBodyFields(), blank=False, null=False)

    subpage_types = []

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
        FieldPanel('author'),
        FieldPanel('story_date'),
        MultiFieldPanel(
            [
                ImageChooserPanel('thumbnail'),
                FieldPanel('alt_text'),
            ],
            heading='Thumbnail',
        ),
        FieldPanel('excerpt'),
    ] + BasePage.content_panels

    promote_panels = BasePage.promote_panels + [
        FieldPanel('sticky_until'),
    ]

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('excerpt'),
        index.SearchField('author'),
        index.SearchField('thumbnail'),
        index.SearchField('body'),
    ]

    @classmethod
    def get_stories(cls, sticky=False, now=None):
        """
	A handy function to efficiently get a list of news stories to display
        on Loop.

        Parameters:
	sticky -- A boolean. If this is set to True, the method will return
		  sticky stories only. Setting this to False returns non-sticky
                  stories only.
	now    -- A datetime.date(), or None. If None, the method will set now
		  to the current date. This parameter is present to make this
                  function easier to test.
 
        Returns:
        A django.core.paginator.Paginator object for Loop news stories. 
        """

        if now == None:
            now = datetime.date(datetime.now())

        stories = cls.objects.filter(
            live=True,
            story_date__lte=now,
        ).order_by('-story_date', '-latest_revision_created_at')
        if sticky:
            stories = stories.filter(sticky_until__gte=now)
        else:
            stories = stories.exclude(sticky_until__gte=now)

        return Paginator(stories, 10)
示例#11
0
class ExhibitPage(PublicBasePage):
    """
    Pages for individual exhibits.
    """
    acknowledgments = models.TextField(null=False, blank=True, default='')
    short_abstract = models.TextField(null=False, blank=False, default='')
    full_description = StreamField(DefaultBodyFields(), blank=True, null=True)
    thumbnail = models.ForeignKey('wagtailimages.Image',
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    thumbnail_caption = models.TextField(null=False, blank=True, default='')
    staff_contact = models.ForeignKey('staff.StaffPage',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL)
    unit_contact = models.BooleanField(default=False)
    student_exhibit = models.BooleanField(default=False)

    exhibit_open_date = models.DateField(blank=True, null=True)
    exhibit_close_date = models.DateField(blank=True, null=True)
    exhibit_location = models.ForeignKey('public.LocationPage',
                                         null=True,
                                         blank=True,
                                         on_delete=models.SET_NULL)
    exhibit_daily_hours = models.CharField(blank=True,
                                           null=False,
                                           default='',
                                           max_length=255)
    exhibit_cost = models.CharField(blank=True,
                                    null=False,
                                    default='',
                                    max_length=255)
    space_type = models.CharField(null=False,
                                  blank=True,
                                  choices=(('Case', 'Case'), ('Gallery',
                                                              'Gallery')),
                                  max_length=255)
    web_exhibit_url = models.URLField("Web Exhibit URL", blank=True)
    publication_description = models.CharField(null=False,
                                               blank=True,
                                               default='',
                                               max_length=255)
    publication_price = models.CharField(null=False,
                                         blank=True,
                                         default='',
                                         max_length=255)
    publication_url = models.URLField("Publication URL", blank=True)
    ordering_information = models.BooleanField(default=False)

    exhibit_text_link_external = models.URLField("Exhibit text external link",
                                                 blank=True)
    exhibit_text_link_page = models.ForeignKey('wagtailcore.Page',
                                               null=True,
                                               blank=True,
                                               related_name='+',
                                               on_delete=models.SET_NULL)
    exhibit_text_document = models.ForeignKey('wagtaildocs.Document',
                                              null=True,
                                              blank=True,
                                              related_name='+',
                                              on_delete=models.SET_NULL)

    exhibit_checklist_link_external = models.URLField(
        "Exhibit checklist external link", blank=True)
    exhibit_checklist_link_page = models.ForeignKey('wagtailcore.Page',
                                                    null=True,
                                                    blank=True,
                                                    related_name='+',
                                                    on_delete=models.SET_NULL)
    exhibit_checklist_document = models.ForeignKey('wagtaildocs.Document',
                                                   null=True,
                                                   blank=True,
                                                   related_name='+',
                                                   on_delete=models.SET_NULL)

    # Web exhibit fields
    web_exhibit = models.BooleanField(default=False,
                                      help_text='Display as web exhibit')
    hex_regex = RegexValidator(regex='^#[a-zA-Z0-9]{6}$', \
        message='Please enter a hex color, e.g. #012043')
    branding_color = models.CharField(validators=[hex_regex],
                                      max_length=7,
                                      blank=True)
    google_font_link = models.URLField(
        blank=True, help_text='Google fonts link to embedd in the header')
    font_family = models.CharField(
        max_length=100,
        blank=True,
        help_text='CSS font-family value, e.g. \'Roboto\', sans-serif')

    subpage_types = ['lib_collections.ExhibitChildPage']

    web_exhibit_panels = [
        FieldPanel('web_exhibit'),
        MultiFieldPanel([
            ImageChooserPanel('banner_image'),
            ImageChooserPanel('banner_feature'),
            FieldPanel('banner_title'),
            FieldPanel('banner_subtitle'),
        ],
                        heading='Banner'),
        MultiFieldPanel([
            FieldPanel('branding_color'),
            FieldPanel('google_font_link'),
            FieldPanel('font_family'),
        ],
                        heading='Branding'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('acknowledgments'),
        FieldPanel('short_abstract'),
        StreamFieldPanel('full_description'),
        MultiFieldPanel(
            [ImageChooserPanel('thumbnail'),
             FieldPanel('thumbnail_caption')],
            heading='Thumbnail'),
        InlinePanel('exhibit_subject_placements', label='Subjects'),
        InlinePanel('exhibit_page_related_collection_placement',
                    label='Related Collection'),
        InlinePanel('exhibit_page_donor_page_list_placement', label='Donor'),
        FieldPanel('student_exhibit'),
        MultiFieldPanel([
            FieldPanel('exhibit_open_date'),
            FieldPanel('exhibit_close_date'),
        ],
                        heading='Dates'),
        MultiFieldPanel([
            FieldPanel('exhibit_location'),
            FieldPanel('exhibit_daily_hours'),
            FieldPanel('exhibit_cost'),
            FieldPanel('space_type'),
        ],
                        heading='Visiting information'),
        MultiFieldPanel([
            FieldPanel('web_exhibit_url'),
            FieldPanel('publication_description'),
            FieldPanel('publication_price'),
            FieldPanel('publication_url'),
            FieldPanel('ordering_information'),
        ],
                        heading='Publication information'),
        MultiFieldPanel([
            FieldPanel('exhibit_text_link_external'),
            PageChooserPanel('exhibit_text_link_page'),
            DocumentChooserPanel('exhibit_text_document')
        ],
                        heading='Exhibit Text (Choose One or None)'),
        MultiFieldPanel([
            FieldPanel('exhibit_checklist_link_external'),
            PageChooserPanel('exhibit_checklist_link_page'),
            DocumentChooserPanel('exhibit_checklist_document')
        ],
                        heading='Exhibit Checklist (Choose One or None)'),
        MultiFieldPanel(
            [FieldPanel('staff_contact'),
             FieldPanel('unit_contact')],
            heading='Staff or Unit Contact')
    ] + PublicBasePage.content_panels

    search_fields = PublicBasePage.search_fields + [
        index.FilterField('exhibit_open_date'),
        index.FilterField('exhibit_close_date'),
        index.FilterField('title'),
        index.FilterField('web_exhibit_url'),
        index.SearchField('short_abstract'),
        index.SearchField('full_description'),
        index.SearchField('thumbnail'),
        index.SearchField('thumbnail_caption'),
        index.SearchField('exhibit_location'),
        index.SearchField('exhibit_daily_hours'),
        index.SearchField('exhibit_cost'),
        index.SearchField('space_type'),
        index.SearchField('web_exhibit_url'),
        index.SearchField('publication_description'),
        index.SearchField('publication_price'),
        index.SearchField('publication_url'),
        index.SearchField('staff_contact'),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(PublicBasePage.promote_panels, heading='Promote'),
        ObjectList(Page.settings_panels,
                   heading='Settings',
                   classname="settings"),
        ObjectList(web_exhibit_panels, heading='Web Exhibit'),
    ])

    def is_web_exhibit(self):
        """
        Determine if an ExhibitPage is a 
        web exhibit.
        """
        return self.web_exhibit

    def has_right_sidebar(self):
        """
        Always has a right sidebar?
        """
        return True

    def get_web_exhibit_footer_img(self, building):
        """
        Get the web exhibit footer image
        for a specific building.

        Returns:
            Image object or None
        """
        #building = self.location_and_hours['page_location'].id
        img = {
            SCRC_BUILDING_ID: SCRC_EXHIBIT_FOOTER_IMG,
            CRERAR_BUILDING_ID: CRERAR_EXHIBIT_FOOTER_IMG
        }
        if building in img:
            return Image.objects.get(id=img[building])
        return None

    def get_related_collections(self, request):
        """
        Get the related collections for a web exhibit.
    
        Args:
            request: object

        Returns:
            A list of tuples where the first item in 
            the tuple is a collection title and the
            second item is a url. If no related 
            collections are found, returns None.
        """
        current_site = Site.find_for_request(request)
        collections = self.exhibit_page_related_collection_placement.all()
        related_collections = '<ul>'
        if collections:
            for collection in collections:
                if collection.related_collection:
                    related_collections += '<li><a href="' + collection.related_collection.relative_url(
                        current_site
                    ) + '">' + collection.related_collection.title + '</a></li>'
            return related_collections + '</ul>'
        return None

    def get_context(self, request):
        staff_url = ''
        try:
            staff_url = StaffPublicPage.objects.get(
                cnetid=self.staff_contact.cnetid).url
        except:
            pass
        default_image = None
        default_image = Image.objects.get(title="Default Placeholder Photo")

        font = DEFAULT_WEB_EXHIBIT_FONT
        if self.font_family:
            font = self.font_family

        context = super(ExhibitPage, self).get_context(request)
        footer_img = self.get_web_exhibit_footer_img(
            self.location_and_hours['page_location'].id
        )  # must be set after context
        context['default_image'] = default_image
        context['staff_url'] = staff_url
        context['branding_color'] = self.branding_color
        context['font_family'] = font
        context['google_font_link'] = self.google_font_link
        context['footer_img'] = footer_img
        context['has_exhibit_footer'] = not (not footer_img)
        context['is_web_exhibit'] = self.is_web_exhibit()
        context['related_collections'] = self.get_related_collections(request)
        context['exhibit_open_date'] = self.exhibit_open_date
        context['exhibit_close_date'] = self.exhibit_close_date
        context['exhibit_close_date'] = self.exhibit_location

        return context
示例#12
0
class CollectionPage(PublicBasePage):
    """
    Pages for individual collections.
    """
    acknowledgments = models.TextField(null=False, blank=True, default='')
    short_abstract = models.TextField(null=False, blank=False, default='')
    full_description = StreamField(DefaultBodyFields(), blank=True, null=True)
    access_instructions = models.TextField(null=False, blank=True, default='')
    thumbnail = models.ForeignKey('wagtailimages.Image',
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    thumbnail_caption = models.TextField(null=False, blank=True)
    primary_online_access_link_label = models.CharField(max_length=255,
                                                        blank=True)
    primary_online_access_link_url = models.URLField(
        "Primary online access link URL", blank=True)
    collection_location = models.ForeignKey('public.LocationPage',
                                            null=True,
                                            blank=True,
                                            on_delete=models.SET_NULL)
    staff_contact = models.ForeignKey('staff.StaffPage',
                                      null=True,
                                      blank=True,
                                      on_delete=models.SET_NULL)
    unit_contact = models.BooleanField(default=False)

    subpage_types = ['public.StandardPage']

    content_panels = Page.content_panels + [
        FieldPanel('acknowledgments'),
        InlinePanel('alternate_name', label='Alternate Names'),
        FieldPanel('short_abstract'),
        StreamFieldPanel('full_description'),
        MultiFieldPanel([
            ImageChooserPanel('thumbnail'),
            FieldPanel('thumbnail_caption'),
        ],
                        heading='Thumbnail'),
        InlinePanel('collection_subject_placements', label='Subjects'),
        InlinePanel('collection_placements', label='Formats'),
        FieldPanel('access_instructions'),
        MultiFieldPanel([
            FieldPanel('primary_online_access_link_label'),
            FieldPanel('primary_online_access_link_url'),
        ],
                        heading='Primary Online Access Link'),
        InlinePanel('supplementary_access_links',
                    label='Supplementary Access Links'),
        InlinePanel('related_collection_placement',
                    label='Related Collection'),
        FieldPanel('collection_location'),
        InlinePanel('donor_page_list_placement', label='Donor'),
        MultiFieldPanel(
            [FieldPanel('staff_contact'),
             FieldPanel('unit_contact')],
            heading='Staff or Unit Contact')
    ] + PublicBasePage.content_panels

    search_fields = PublicBasePage.search_fields + [
        index.FilterField('title'),
        index.SearchField('short_abstract'),
        index.SearchField('full_description'),
        index.SearchField('thumbnail'),
        index.SearchField('thumbnail_caption'),
        index.SearchField('access_instructions'),
        index.SearchField('collection_location'),
        index.SearchField('staff_contact'),
    ]

    def get_context(self, request):
        staff_title = ''
        staff_vcard_title = ''
        staff_vcard_email = ''
        staff_vcard_phone_number = ''
        staff_vcard_faculty_exchange = ''
        try:
            staff_title = self.staff_contact.title
            staff_vcard_title = self.staff_contact.vcards.first().title
            staff_vcard_email = self.staff_contact.vcards.first().email
            staff_vcard_phone_number = self.staff_contact.vcards.first(
            ).phone_number
            staff_vcard_faculty_exchange = self.staff_contact.vcards.first(
            ).faculty_exchange
        except:
            pass

        staff_url = ''
        try:
            staff_url = StaffPublicPage.objects.get(
                cnetid=self.staff_contact.cnetid).url
        except:
            pass

        unit_title = ''
        unit_url = ''
        unit_email_label = ''
        unit_email = ''
        unit_phone_label = ''
        unit_phone_number = ''
        unit_fax_number = ''
        unit_link_text = ''
        unit_link_external = ''
        unit_link_page = ''
        unit_link_document = ''
        if self.unit_contact:
            try:
                unit_title = self.unit.title
            except:
                pass

            try:
                unit_url = self.unit.public_web_page.url
            except:
                pass

            try:
                unit_email_label = self.unit.email_label
            except:
                pass
            try:
                unit_email = self.unit.email
            except:
                pass

            try:
                unit_phone_label = self.unit.phone_label
            except:
                pass
            try:
                unit_phone_number = self.unit.phone_number
            except:
                pass

            try:
                unit_fax_number = self.unit.fax_number
            except:
                pass

            try:
                unit_link_text = self.unit.link_text
            except:
                pass

            try:
                unit_link_external = self.unit.link_external
            except:
                pass

            try:
                unit_link_page = self.unit.link_page.url
            except:
                pass

            try:
                unit_link_document = self.unit.link_document.file.url
            except:
                pass

        default_image = None
        default_image = Image.objects.get(title="Default Placeholder Photo")

        context = super(CollectionPage, self).get_context(request)
        context['default_image'] = default_image
        context['staff_title'] = staff_title
        context['staff_url'] = staff_url
        context['staff_vcard_title'] = staff_vcard_title
        context['staff_vcard_email'] = staff_vcard_email
        context['staff_vcard_phone_number'] = staff_vcard_phone_number
        context['staff_vcard_faculty_exchange'] = staff_vcard_faculty_exchange
        context['unit_title'] = unit_title
        context['unit_url'] = unit_url
        context['unit_email_label'] = unit_email_label
        context['unit_email'] = unit_email
        context['unit_phone_label'] = unit_phone_label
        context['unit_phone_number'] = unit_phone_number
        context['unit_fax_number'] = unit_fax_number
        context['unit_link_text'] = unit_link_text
        context['unit_link_external'] = unit_link_external
        context['unit_link_page'] = unit_link_page
        context['unit_link_document'] = unit_link_document
        context[
            'supplementary_access_links'] = self.supplementary_access_links.get_object_list(
            )
        return context

    def has_right_sidebar(self):
        return True
示例#13
0
class IntranetUnitsPage(BasePage, Email, PhoneNumber):
    """
    Content type for department pages on the intranet.
    """

    unit_page = models.ForeignKey('units.UnitPage',
                                  related_name='loop_page',
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL)

    intro = StreamField(DefaultBodyFields(), blank=True)
    internal_location = models.CharField(max_length=255, blank=True)
    internal_phone_number = models.CharField(max_length=255, blank=True)
    internal_email = models.EmailField(max_length=255, blank=True)
    staff_only_email = models.EmailField(max_length=254, blank=True)
    body = StreamField(DefaultBodyFields(), null=True, blank=True)
    show_staff = models.BooleanField(default=False)
    show_departments = models.BooleanField(default=False)

    subpage_types = [
        'base.IntranetIndexPage', 'base.IntranetPlainPage',
        'intranetforms.IntranetFormPage', 'intranettocs.TOCPage',
        'intranetunits.IntranetUnitsPage',
        'intranetunits.IntranetUnitsReportsIndexPage'
    ]

    search_fields = BasePage.search_fields + [
        index.SearchField('intro'),
        index.SearchField('internal_location'),
        index.SearchField('internal_phone_number'),
        index.SearchField('internal_email'),
        index.SearchField('staff_only_email'),
        index.SearchField('body'),
    ]

    def _get_full_name_list(self):
        """
        Helper function for get_full_name() and
        get_campus_directory_full_name(). This returns a list of page titles
        that can be processed by those two functions.
        """
        return list(
            self.get_ancestors(True).live().type(
                IntranetUnitsPage).values_list('title', flat=True))

    def get_full_name(self):
        """
        Get an IntranetUnitsPage's full name according to Wagtail.

        The full name of an IntranetUnitsPage includes a breadcrumb trail of
        the titles its ancestor IntranetUnitsPages.

        Example:
        Wagtail contains an IntranetUnitsPage for "Collections & Access". That
        page contains "Access Services". The full name for Access Services is
        "Collections & Access - Access Services".

        Compare this method's output with get_campus_directory_full_name().
        """
        return ' - '.join(self._get_full_name_list())

    def get_campus_directory_full_name(self):
        """
        Get an IntranetUnitsPage's campus directory name.

        The campus directory describes a university department in a three level
        heirarchy: division, department, and sub-department. For library
        departments division is always "Library".

        The library's own view of its org chart has more levels than what we
        can represent in the campus directory, so we skip some levels to make
        room for the departments below it. Those levels are hardcoded below.

        Example:
        Wagail contains an IntranetUnitsPage for "Collections & Access - Access
        Services". The campus directory full name for Access Services should be
        "Access Services".
        """
        titles = self._get_full_name_list()

        # Remove "container units". These are top-level units in the library's
        # system that aren't present in the campus directory.
        skip_containing_units = ['Collections & Access', 'Research & Learning']
        for v in skip_containing_units:
            try:
                titles.remove(v)
            except ValueError:
                continue

        # Our system includes more than two levels of heiarchy, but the campus
        # directory only includes two.
        titles = titles[:2]

        return ' - '.join(titles)

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

        context['phone'] = ''
        if self.specific.internal_phone_number:
            context['phone'] = self.specific.internal_phone_number

        context['location'] = ''
        if self.specific.internal_location:
            context['location'] = self.specific.internal_location

        context['email'] = ''
        if self.specific.internal_email:
            context['email'] = self.specific.internal_email

        context['show_staff'] = self.show_staff

        context['show_departments'] = self.show_departments

        department_members = []
        if self.specific.unit_page:
            unit_pages = self.specific.unit_page.get_descendants(True)
            staff_pages = StaffPage.objects.live().filter(
                staff_page_units__library_unit__in=unit_pages).distinct()

            # sorting: supervisors first, alphabetically; then non-supervisors, alphabetically.
            supervisor = self.specific.unit_page.department_head
            if supervisor:
                staff_pages = [supervisor] + list(
                    staff_pages.exclude(
                        pk=supervisor.pk).order_by('last_name'))
            else:
                staff_pages = list(staff_pages.order_by('last_name'))

            for staff_page in staff_pages:
                try:
                    email = staff_page.staff_page_email.first().email
                except AttributeError:
                    email = None
                phone_numbers = staff_page.staff_page_phone_faculty_exchange.all(
                ).values_list('phone_number', flat=True)
                titles = []
                if staff_page.position_title:
                    titles = [staff_page.position_title]

                department_members.append({
                    'title': staff_page.title,
                    'url': staff_page.url,
                    'jobtitle': "<br/>".join(titles),
                    'email': email,
                    'phone': "<br/>".join(phone_numbers),
                })

        context['department_members'] = department_members

        department_units = []
        try:
            for unit_page in self.unit_page.get_descendants():
                intranet_unit_page = unit_page.specific.loop_page.live(
                ).filter(show_in_menus=True).first()
                if intranet_unit_page:
                    unit = {
                        'title': intranet_unit_page.title,
                        'url': intranet_unit_page.url,
                        'location': intranet_unit_page.internal_location,
                        'phone_number':
                        intranet_unit_page.internal_phone_number,
                        'email': intranet_unit_page.internal_email
                    }

                    supervisors = []
                    if unit_page.specific.department_head:
                        try:
                            email = unit_page.specific.department_head.staff_page_email.first(
                            ).email
                        except AttributeError:
                            email = ''
                        try:
                            phone_number = unit_page.specific.department_head.staff_page_phone_faculty_exchange.first(
                            ).phone_number
                        except AttributeError:
                            phone_number = ''

                        supervisors.append({
                            'title':
                            unit_page.specific.department_head.title,
                            'url':
                            unit_page.specific.department_head.url,
                            'phone_number':
                            phone_number,
                            'email':
                            email
                        })
                    unit['supervisors'] = supervisors
                    department_units.append(unit)
        except (AttributeError):
            pass

        # split the department units into lists of lists, each inner list containing 4 or less items.
        context['department_unit_rows'] = [
            department_units[i:i + 4]
            for i in range(0, len(department_units), 4)
        ]

        # reports
        tmp = []
        unit_reports_pages = IntranetUnitsReportsPage.objects.descendant_of(
            self)
        for unit_reports_page in unit_reports_pages:
            for r in unit_reports_page.intranet_units_reports.all():
                try:
                    if not r.link and not r.document.url:
                        continue
                except AttributeError:
                    continue
                report = {
                    'summary': r.summary,
                    'date': r.date.strftime("%b. %-d, %Y"),
                    'sortdate': r.date.strftime("%Y%m%d")
                }
                if r.link:
                    report['url'] = r.link
                elif r.document.url:
                    report['url'] = r.document.url
                tmp.append(report)
        reports = sorted(tmp, key=lambda r: r['sortdate'], reverse=True)[:3]

        context['reports'] = reports

        return context
示例#14
0
class StandardPage(PublicBasePage, SocialMediaFields):
    """
    A standard basic page.
    """
    # Page content
    body = StreamField(DefaultBodyFields(), blank=True)

    # Search widget
    enable_search_widget = models.BooleanField(default=False)

    # Find spaces fields
    enable_find_spaces = models.BooleanField(default=False)
    book_a_room_link = models.URLField(max_length=255, blank=True, default='')

    # Custom icons fields
    widget_title = models.CharField(max_length=100, blank=True)
    more_icons_link = models.URLField(max_length=255,
                                      blank=True,
                                      default='',
                                      verbose_name='View More Link')
    more_icons_link_label = models.CharField(
        max_length=100, blank=True, verbose_name='View More Link Label')

    # Featured collections
    collection_page = models.ForeignKey('lib_collections.CollectionPage',
                                        null=True,
                                        blank=True,
                                        related_name='+',
                                        on_delete=models.SET_NULL)

    # Featured Library Expert
    featured_library_expert_fallback = StreamField(
        FeaturedLibraryExpertBaseFields(required=False),
        blank=True,
        default=[])

    expert_link = models.CharField(max_length=400,
                                   default="/about/directory/?view=staff",
                                   verbose_name="Featured Expert Link")

    featured_library_experts = StreamField(
        FeaturedLibraryExpertFields(required=False), blank=True, default=[])

    subpage_types = [
        'alerts.AlertIndexPage',
        'public.StandardPage',
        'public.LocationPage',
        'public.DonorPage',
        'lib_collections.CollectingAreaPage',
        'lib_collections.CollectionPage',
        'lib_collections.ExhibitPage',
        'lib_news.LibNewsIndexPage',
        'redirects.RedirectPage',
        'units.UnitPage',
        'ask_a_librarian.AskPage',
        'units.UnitIndexPage',
        'conferences.ConferenceIndexPage',
        'base.IntranetPlainPage',
        'dirbrowse.DirBrowsePage',
        'public.StaffPublicPage',
    ]

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

    widget_content_panels = [
        MultiFieldPanel([FieldPanel('enable_search_widget')],
                        heading='Search Widget'),
        MultiFieldPanel([
            FieldPanel('quicklinks_title'),
            FieldPanel('quicklinks'),
            FieldPanel('view_more_link_label'),
            FieldPanel('view_more_link'),
            FieldPanel('change_to_callout'),
        ],
                        heading='Quicklinks'),
        MultiFieldPanel([
            FieldPanel('enable_index'),
            FieldPanel('display_hierarchical_listing'),
        ],
                        heading='Auto-generated Sitemap'),
        MultiFieldPanel([
            FieldPanel('display_hours_in_right_sidebar'),
        ],
                        heading='Granular hours'),
        MultiFieldPanel([
            ImageChooserPanel('banner_image'),
            FieldPanel('banner_title'),
        ],
                        heading='Banner'),
        MultiFieldPanel([
            FieldPanel('events_feed_url'),
        ],
                        heading='Workshops and Events'),
        MultiFieldPanel([
            FieldPanel('news_feed_source'),
            FieldPanel('external_news_page'),
            PageChooserPanel('internal_news_page'),
        ],
                        heading='News'),
        MultiFieldPanel([
            FieldPanel('enable_find_spaces'),
            FieldPanel('book_a_room_link'),
        ],
                        heading='Find Spaces'),
        MultiFieldPanel([
            PageChooserPanel('collection_page',
                             'lib_collections.CollectionPage'),
        ],
                        heading='Featured Collection'),
        MultiFieldPanel([
            FieldPanel('rich_text_heading'),
            FieldPanel('rich_text'),
            PageChooserPanel('rich_text_link'),
            FieldPanel('rich_text_external_link'),
            FieldPanel('rich_text_link_text'),
        ],
                        heading='Rich Text'),
        InlinePanel('carousel_items', label='Carousel items'),
        MultiFieldPanel([
            FieldPanel('widget_title'),
            InlinePanel('icon_link_items', max_num=3, label='Icon Link items'),
            FieldPanel('more_icons_link'),
            FieldPanel('more_icons_link_label'),
        ],
                        heading='Custom Icon Links'),
        InlinePanel('reusable_content', label='Reusable Content Blocks'),
        FieldPanel('expert_link'),
        StreamFieldPanel('featured_library_expert_fallback'),
        StreamFieldPanel('featured_library_experts'),
        MultiFieldPanel([
            FieldPanel('cgi_mail_form_thank_you_text'),
            FieldPanel('cgi_mail_form'),
        ],
                        heading='CGIMail Form'),
    ] + SocialMediaFields.panels

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('body', partial_match=True),
    ]

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

    def streamblock_has_link(self, streamblock, field):
        """
        Check that a streamfield block object has a
        either an internal or external link when
        base.models.LinkBlock is in use.

        Args:
            streamblock: streamfield block object,
            wagtail.core.blocks.stream_block.StreamValue.StreamChild.

            field: string field name that contains
            a ListBlock of LinkBlocks.
        """
        block_list = streamblock.value.get(field)
        for block in block_list:
            val1 = block.get('link_text')
            val2 = block.get('link_external')
            val3 = block.get('link_page')
            if not (val1 and val2) and not (val1 and val3):
                return False
        return True

    def streamblock_has_all_fields(self, streamblock, field_list):
        """
        Test to see if a streamfield block has a value for all
        fields in a given list.

        Args:
            streamblock: streamfield block object,
            wagtail.core.blocks.stream_block.StreamValue.StreamChild.

            field_names: list of strings, field names.

        Returns:
            Boolean
        """
        for field in field_list:
            value = streamblock.value.get(field)
            if not value:
                return False
        return True

    def has_featured_lib_expert_fallback(self):
        """
        Test to see if a page has a "Featured
        Library Expert" fallback set.

        Returns:
            Boolean
        """
        try:
            return self.streamblock_has_all_fields(
                self.featured_library_expert_fallback[0],
                ['library_expert']) and self.streamblock_has_link(
                    self.featured_library_expert_fallback[0], 'libguides')
        except (IndexError):
            return False

    def get_featured_lib_expert(self):
        """
        Test to see if a page has a "Featured Library Expert".
        Return a boolean and the featured library expert for
        today's date. Return False and None if there is no
        Featured Library Expert for today. The fallback is
        used if nothing is available for today's date. In
        order to return True a proper fallback must always
        be set.

        Returns:
            A mixed tuple where the first value is a boolean
            and the second value is a streamfield block or
            None when the first value is False.
        """
        fallback = self.has_featured_lib_expert_fallback()
        # print(self.featured_library_expert_fallback[0].value.get('library_expert'))
        today = date.today()
        for block in self.featured_library_experts:
            # print(block.value.get('library_expert'))
            has_fields = self.streamblock_has_all_fields(
                block, ['library_expert', 'start_date', 'end_date'])
            # Could misfire, just an estimation
            has_links = self.streamblock_has_link(block, 'libguides')
            in_range = block.value.get(
                'start_date') <= today and block.value.get('end_date') >= today
            if (fallback and (has_fields and has_links)) and in_range:
                return (True, block)
        if (fallback):
            return (True, self.featured_library_expert_fallback[0])
        return (False, None)

    def unpack_lib_expert_block(self, block, current_site):
        """
        Unpack the values from a "Featured Library Expert"
        streamfield block and return a data structure for
        display in the templates. This method wouldn't be
        needed, however, at the moment Wagtail doesn't allow
        for getting the page context from a block. This is
        discussed in Wagtail github issue #s 1743 and 2469.
        When a solution is implemented in the Wagtail base
        we could get rid of this.

        Args:
            block: Featured Library Expert or fallback
            streamfield block.

            current_site: Wagtail site object for the
            request.

        Returns:
            Mixed dictionary with the following values:
            person (StaffPage object), image (object),
            profile (string url), links (list of html strings).
        """
        person = block.value.get('library_expert')
        libguides = block.value.get('libguides')
        image = person.specific.profile_picture
        email = person.specific.staff_page_email.first().email
        try:
            public_person = StaffPublicPage.objects.get(title=str(person))
        except:
            public_person = None
        profile = public_person.relative_url(
            current_site) if public_person else None

        links = []
        for guide in libguides:
            link_text = guide['link_text']
            url = guide['link_external'] if guide['link_external'] else guide[
                'link_page'].relative_url(current_site)
            html = '<a href="%s">%s</a>' % (url, link_text)
            links.append(html)

        return {
            'person': person,
            'image': image,
            'profile': profile,
            'links': links,
            'email': email
        }

    @property
    def has_find_spaces(self):
        """
        Determine if there is a "Find Spaces"
        widget on the page.

        Returns:
            Boolean
        """
        return self.has_field([self.enable_find_spaces])

    @property
    def has_icon_link_items(self):
        """
        Determine if there is a "Link Items"
        widget on the page.
        Returns:
            Boolean
        """
        if self.has_field([self.icon_link_items]):
            return self.icon_link_items.all().count() > 0
        return False

    @property
    def has_right_sidebar(self):
        """
        Determine if a right sidebar should
        be displayed in the template.

        Returns:
            boolean
        """
        fields = [self.collection_page]
        if self.base_has_right_sidebar():
            return True
        elif self.has_social_media:
            return True
        elif self.has_find_spaces:
            return True
        else:
            return self.has_field(fields)

    def get_context(self, request):
        """
        Override the page object's get context method.
        """
        context = super(StandardPage, self).get_context(request)
        current_site = Site.find_for_request(request)
        has_featured_lib_expert = self.get_featured_lib_expert()[0]

        if has_featured_lib_expert:
            lib_expert_block = self.unpack_lib_expert_block(
                self.get_featured_lib_expert()[1], current_site)
            has_libcal_schedule = libcal_id_by_email(
                lib_expert_block['email']) != ''
            context['has_featured_lib_expert'] = has_featured_lib_expert
            context['has_libcal_schedule'] = has_libcal_schedule
            context['featured_lib_expert'] = self.get_featured_lib_expert()[1]
            context['featured_lib_expert_name'] = lib_expert_block['person']
            context['featured_lib_expert_image'] = lib_expert_block['image']
            context['featured_lib_expert_profile'] = lib_expert_block[
                'profile']
            context['featured_lib_expert_links'] = lib_expert_block['links']
            context['email'] = lib_expert_block['email']

        context['has_search_widget'] = self.enable_search_widget

        return context
示例#15
0
class NewsPage(BasePage):
    """
    News story content type used on intranet pages.
    """
    excerpt = RichTextField(
        blank=True,
        null=True,
        help_text=
        'Shown on the News feed. Populated automatically from “Body” if left empty.'
    )
    author = models.ForeignKey('staff.StaffPage',
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL,
                               related_name='news_stories')
    story_date = models.DateField(
        default=timezone.now,
        help_text=
        'If you use Settings to publish a future post, put the publish date here. Otherwise, leave today as the story date.'
    )
    sticky_until = models.DateField(
        blank=True, null=True, help_text='To be used by Admin and HR only.')
    thumbnail = models.ForeignKey('wagtailimages.Image',
                                  null=True,
                                  blank=True,
                                  on_delete=models.SET_NULL,
                                  related_name='+')
    alt_text = models.CharField(max_length=100, blank=True)
    body = StreamField(DefaultBodyFields(), blank=False, null=False)

    subpage_types = []

    content_panels = Page.content_panels + [
        StreamFieldPanel('body'),
        FieldPanel('author'),
        FieldPanel('story_date'),
        FieldPanel('sticky_until'),
        MultiFieldPanel(
            [
                ImageChooserPanel('thumbnail'),
                FieldPanel('alt_text'),
            ],
            heading='Thumbnail',
        ),
        FieldPanel('excerpt'),
    ] + BasePage.content_panels

    search_fields = PublicBasePage.search_fields + [
        index.SearchField('excerpt'),
        index.SearchField('author'),
        index.SearchField('thumbnail'),
        index.SearchField('body'),
    ]

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

        details = get_story_summary(self)
        context['story_date'] = details['story_date']
        try:
            context['author_title'] = details['author_title']
        except:
            context['author_title'] = ''
        context['author_url'] = details['author_url']
        context['thumbnail'] = details['thumbnail']

        return context
示例#16
0
class GroupPage(BasePage, Email):
    """
    Content type for group and committee pages.
    """
    subpage_types = [
        'base.IntranetIndexPage', 'base.IntranetPlainPage', 'group.GroupPage',
        'group.GroupMeetingMinutesIndexPage', 'group.GroupReportsIndexPage',
        'intranetforms.IntranetFormPage', 'projects.ProjectPage'
    ]
    meeting_location = CharField(blank=True, max_length=255)
    meeting_start_time = models.TimeField(auto_now=False,
                                          auto_now_add=False,
                                          default=timezone.now,
                                          blank=True,
                                          null=True)
    meeting_end_time = models.TimeField(auto_now=False,
                                        auto_now_add=False,
                                        default=default_end_time,
                                        blank=True,
                                        null=True)
    meeting_frequency = CharField(blank=True, max_length=255)
    intro = StreamField(DefaultBodyFields(), blank=True)
    is_active = models.BooleanField(default=True)
    body = StreamField(DefaultBodyFields())

    content_panels = Page.content_panels + Email.content_panels + [
        MultiFieldPanel([
            FieldPanel('meeting_start_time'),
            FieldPanel('meeting_end_time'),
            FieldPanel('meeting_location'),
            FieldPanel('meeting_frequency'),
        ],
                        heading='Meeting Information'),
        StreamFieldPanel('intro'),
        InlinePanel('group_members', label='Group Members'),
        FieldPanel('is_active'),
        StreamFieldPanel('body'),
    ] + BasePage.content_panels

    search_fields = BasePage.search_fields + [
        index.SearchField('meeting_location'),
        index.SearchField('meeting_frequency'),
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    def get_context(self, request):

        context = super(GroupPage, self).get_context(request)
        group_members = self.group_members.all()

        # sorting: chairs or co-chairs first, alphabetically; then others, alphabetically.
        group_member_chairs = []
        non_group_member_chairs = []
        for g in group_members:
            if g.group_member == None:
                continue
            if g.group_member.live == False:
                continue
            if g.role and g.role.text in ['Chair', 'Co-Chair']:
                group_member_chairs.append(g)
            else:
                non_group_member_chairs.append(g)

        group_member_chairs = sorted(group_member_chairs,
                                     key=lambda g: g.group_member.title)
        non_group_member_chairs = sorted(non_group_member_chairs,
                                         key=lambda g: g.group_member.title)
        group_members = group_member_chairs + non_group_member_chairs

        # minutes
        tmp = []
        group_meeting_min_pages = GroupMeetingMinutesPage.objects.descendant_of(
            self)
        for group_meeting_min_page in group_meeting_min_pages:
            for m in group_meeting_min_page.meeting_minutes.all():
                try:
                    if not m.link and not m.document.url:
                        continue
                except AttributeError:
                    continue
                minute = {
                    'summary': m.summary,
                    'date': m.date.strftime("%b. %-d, %Y"),
                    'sortdate': m.date.strftime("%Y%m%d")
                }
                if m.link:
                    minute['url'] = m.link
                elif m.document.url:
                    minute['url'] = m.document.url
                tmp.append(minute)
        minutes = sorted(tmp, key=lambda m: m['sortdate'], reverse=True)[:3]

        # reports
        tmp = []
        group_reports_pages = GroupReportsPage.objects.descendant_of(self)
        for group_reports_page in group_reports_pages:
            for r in group_reports_page.group_reports.all():
                try:
                    if not r.link and not r.document.url:
                        continue
                except AttributeError:
                    continue
                report = {
                    'summary': r.summary,
                    'date': r.date.strftime("%b. %-d, %Y"),
                    'sortdate': r.date.strftime("%Y%m%d")
                }
                if r.link:
                    report['url'] = r.link
                elif r.document.url:
                    report['url'] = r.document.url
                tmp.append(report)
        reports = sorted(tmp, key=lambda r: r['sortdate'], reverse=True)[:3]

        context['minutes'] = minutes
        context['reports'] = reports
        context['group_members'] = list(
            map(
                lambda m: {
                    'title':
                    m.group_member.title,
                    'unit':
                    '<br/>'.join(
                        sorted(
                            map(lambda u: u.library_unit.get_full_name(),
                                m.group_member.staff_page_units.all()))),
                    'url':
                    m.group_member.url,
                    'role':
                    m.role
                }, group_members))
        return context
示例#17
0
class StaffPage(BasePageWithoutStaffPageForeignKeys):
    """
    Staff profile content type.
    """
    cnetid = CharField(
        max_length=255,
        blank=False)
    display_name = CharField(
        max_length=255,
        null=True,
        blank=True)
    official_name = CharField(
        max_length=255,
        null=True,
        blank=True)
    first_name = CharField(
        max_length=255,
        null=True,
        blank=True)
    middle_name = CharField(
        max_length=255,
        null=True,
        blank=True)
    last_name = CharField(
        max_length=255,
        null=True,
        blank=True)
    supervisor = models.ForeignKey(
        'staff.StaffPage',
        null=True, blank=True, on_delete=models.SET_NULL)
    profile_picture = models.ForeignKey(
                'wagtailimages.Image',
                null=True,
                blank=True,
                on_delete=models.SET_NULL,
                related_name='+')
    libguide_url = models.URLField(
        max_length=255, 
        null=True, 
        blank=True)
    bio = StreamField(DefaultBodyFields(), blank=True, null=True)
    cv = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    is_public_persona = BooleanField(default=False)
    orcid_regex = RegexValidator(regex=ORCID_FORMAT, message=ORCID_ERROR_MSG)
    orcid = CharField(
        max_length=255,
        null=True,
        blank=True,
        validators=[orcid_regex]
    )

    objects = StaffPageManager()

    @property
    def get_staff_subjects(self):
        """
        Get the subjects beloning to the 
        staff member - UNTESTED 
        """
        return get_public_profile('elong')

    @property
    def is_subject_specialist(self):
        """
        See if the staff member is a subject
        specialist - PLACEHOLDER
        """
        subjects = self.get_subjects()
        return None

    @property
    def public_page(self):
        """
        Get a public staff profile page for the
        library expert if one exists.
        """
        from public.models import StaffPublicPage # Should try to do better
        try:
            return StaffPublicPage.objects.live().filter(title=self.cnetid)[0]
        except(IndexError):
            return None

    def get_subjects(self):
        """
        Get all the subjects for a staff member. 
        Must return a string for elasticsearch.

        Returns:
            String, concatenated list of subjects.
        """
        subject_list = self.staff_subject_placements.values_list('subject', flat=True)
        return '\n'.join(Subject.objects.get(id=subject).name for subject in subject_list)

    content_panels = Page.content_panels + [
        ImageChooserPanel('profile_picture'),
        StreamFieldPanel('bio'),
        DocumentChooserPanel('cv'),
        FieldPanel('libguide_url'),
        FieldPanel('is_public_persona'),
        InlinePanel('staff_subject_placements', label='Subject Specialties'),
        InlinePanel('expertise_placements', label='Expertise'),
        FieldPanel('orcid')
    ] + BasePageWithoutStaffPageForeignKeys.content_panels

    search_fields = BasePageWithoutStaffPageForeignKeys.search_fields + [
        index.SearchField('profile_picture'),
        index.SearchField('cv'),
        index.SearchField('libguide_url'),
        index.SearchField('orcid'),
        index.SearchField('get_subjects')
    ]

    subpage_types = ['base.IntranetIndexPage', 'base.IntranetPlainPage', 'intranetforms.IntranetFormPage', 'intranettocs.TOCPage']

    class Meta:
        ordering = ['last_name', 'first_name']

    def get_context(self, request):
        vcard_titles = set()
        faculty_exchanges = set()
        emails = set()
        phones = set()
        units = set()
    
        for vcard in self.vcards.all():
            vcard_titles.add(re.sub('\s+', ' ', vcard.title).strip())
            faculty_exchanges.add(re.sub('\s+', ' ', vcard.faculty_exchange).strip())
            emails.add(vcard.email)
            phones.add(vcard.phone_number)

            try:
                unit_title = vcard.unit.fullName
            except:
                unit_title = None
            try:
                unit_url = vcard.unit.intranet_unit_page.first().url
            except:
                unit_url = None
            units.add(json.dumps({
                'title': unit_title,
                'url': unit_url
            }))

        vcard_titles = list(vcard_titles)
        faculty_exchanges = list(faculty_exchanges)
        emails = list(emails)
        phones = list(phones)
        units = list(map(json.loads, list(units)))

        subjects = []
        for subject in self.staff_subject_placements.all():
            subjects.append({
                'name': subject.subject.name,
                'url': ''
            })

        group_memberships = []
        for group_membership in self.member.all():
            if group_membership.parent.is_active:
                group_memberships.append({
                    'group': {
                        'title': group_membership.parent.title,
                        'url': group_membership.parent.url
                    },
                    'role': group_membership.role
                })
            
        context = super(StaffPage, self).get_context(request)
        context['vcard_titles'] = vcard_titles
        context['faculty_exchanges'] = faculty_exchanges
        context['emails'] = emails
        context['phones'] = phones
        context['units'] = units
        context['subjects'] = subjects
        context['group_memberships'] = group_memberships
        return context