Example #1
0
class TimelineSectionBlock(blocks.StructBlock):
    blurbs = blocks.ListBlock(
        blocks.StructBlock([
            ("blurb_header", blocks.CharBlock(required=True)),
            ("blurb_content", blocks.RichTextBlock(required=True)),
        ]))
Example #2
0
class ConferenceRegistrationForm(AbstractFormBlock):
    govdelivery_code = blocks.CharBlock(
        label='GovDelivery code',
        help_text=(
            'Conference registrants will be subscribed to this GovDelivery '
            'topic.'))
    govdelivery_question_id = blocks.RegexBlock(
        required=False,
        regex=r'^\d{5,}$',
        error_messages={
            'invalid': 'GovDelivery question ID must be 5 digits.'
        },
        label='GovDelivery question ID',
        help_text=mark_safe(
            'Enter the ID of the question in GovDelivery that is being used '
            'to track registration for this conference. It is the number in '
            'the question URL, e.g., the <code>12345</code> in '
            '<code>https://admin.govdelivery.com/questions/12345/edit</code>.')
    )
    govdelivery_answer_id = blocks.RegexBlock(
        required=False,
        regex=r'^\d{5,}$',
        error_messages={'invalid': 'GovDelivery answer ID must be 5 digits.'},
        label='GovDelivery answer ID',
        help_text=mark_safe(
            'Enter the ID of the affirmative answer for the above question. '
            'To find it, right-click on the answer in the listing on a page '
            'like <code>https://admin.govdelivery.com/questions/12345/answers'
            '</code>, inspect the element, and look around in the source for '
            'a five-digit ID associated with that answer. <strong>Required '
            'if Govdelivery question ID is set.</strong>'))
    capacity = blocks.IntegerBlock(help_text=(
        'Enter the (physical) conference attendance limit as a number.'))
    success_message = blocks.RichTextBlock(help_text=(
        'Enter a message that will be shown on successful registration.'))
    at_capacity_message = blocks.RichTextBlock(help_text=(
        'Enter a message that will be shown when the event is at capacity.'))
    failure_message = blocks.RichTextBlock(
        help_text=('Enter a message that will be shown if the GovDelivery '
                   'subscription fails.'))

    def clean(self, value):
        cleaned = super(ConferenceRegistrationForm, self).clean(value)
        question = cleaned.get('govdelivery_question_id')
        answer = cleaned.get('govdelivery_answer_id')

        # Question and answer values must both exist or neither exist
        if question and not answer:
            raise ValidationError(
                'Validation error in Conference Registration Form: '
                'GovDelivery question ID requires answer ID, and vice versa.',
                params={
                    'govdelivery_answer_id':
                    ErrorList(
                        ['Required if a GovDelivery question ID is entered.'])
                })
        if answer and not question:
            raise ValidationError(
                'Validation error in Conference Registration Form: '
                'GovDelivery question ID requires answer ID, and vice versa.',
                params={
                    'govdelivery_question_id':
                    ErrorList(
                        ['Required if a GovDelivery answer ID is entered.'])
                })

        return cleaned

    class Meta:
        handler = 'data_research.handlers.ConferenceRegistrationHandler'
        template = 'data_research/conference-registration-form.html'
Example #3
0
class CallToActionSnippet(models.Model):
    title = models.CharField(max_length=255)
    summary = RichTextField(blank=True, max_length=255)
    image = models.ForeignKey(
        "images.CustomImage",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )

    link = StreamField(
        blocks.StreamBlock(
            [
                (
                    "external_link",
                    blocks.StructBlock(
                        [("url", blocks.URLBlock()), ("title", blocks.CharBlock())],
                        icon="link",
                    ),
                ),
                (
                    "internal_link",
                    blocks.StructBlock(
                        [
                            ("page", blocks.PageChooserBlock()),
                            ("title", blocks.CharBlock(required=False)),
                        ],
                        icon="link",
                    ),
                ),
            ],
            max_num=1,
            required=True,
        ),
        blank=True,
    )

    panels = [
        FieldPanel("title"),
        FieldPanel("summary"),
        ImageChooserPanel("image"),
        StreamFieldPanel("link"),
    ]

    def get_link_text(self):
        # Link is required, so we should always have
        # an element with index 0
        block = self.link[0]

        title = block.value["title"]
        if block.block_type == "external_link":
            return title

        # Title is optional for internal_link
        # so fallback to page's title, if it's empty
        return title or block.value["page"].title

    def get_link_url(self):
        # Link is required, so we should always have
        # an element with index 0
        block = self.link[0]

        if block.block_type == "external_link":
            return block.value["url"]

        return block.value["page"].get_url()

    def __str__(self):
        return self.title
Example #4
0
class Migration(migrations.Migration):

    dependencies = [
        ('v1', '0205_bureau_structure_multiple_leads'),
    ]

    operations = [
        migrations.CreateModel(
            name='EnforcementActionPage',
            fields=[
                ('abstractfilterpage_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='v1.AbstractFilterPage')),
                ('sidebar_header', models.CharField(default='Action details', max_length=100)),
                ('court', models.CharField(blank=True, default='', max_length=150)),
                ('institution_type', models.CharField(choices=[('Nonbank', 'Nonbank'), ('Bank', 'Bank')], max_length=50)),
                ('docket_number', models.CharField(max_length=100)),
                ('content', core_fields.StreamField((('full_width_text', core_blocks.StreamBlock((('content', core_blocks.RichTextBlock(icon='edit')), ('content_with_anchor', core_blocks.StructBlock((('content_block', core_blocks.RichTextBlock()), ('anchor_link', core_blocks.StructBlock((('link_id', core_blocks.CharBlock(help_text='\n            ID will be auto-generated on save.\n            However, you may enter some human-friendly text that\n            will be incorporated to make it easier to read.\n        ', label='ID for this content block', required=False)),)))))), ('heading', core_blocks.StructBlock((('text', v1.blocks.HeadingTextBlock(required=False)), ('level', core_blocks.ChoiceBlock(choices=[('h2', 'H2'), ('h3', 'H3'), ('h4', 'H4')])), ('icon', v1.blocks.HeadingIconBlock(help_text='Input the name of an icon to appear to the left of the heading. E.g., approved, help-round, etc. <a href="https://cfpb.github.io/capital-framework/components/cf-icons/#the-icons">See full list of icons</a>', required=False))), required=False)), ('image', core_blocks.StructBlock((('image', core_blocks.StructBlock((('upload', images_blocks.ImageChooserBlock(required=False)), ('alt', core_blocks.CharBlock(help_text="If the image is decorative (i.e., if a screenreader wouldn't have anything useful to say about it), leave the Alt field blank.", required=False))))), ('image_width', core_blocks.ChoiceBlock(choices=[('full', 'full'), (470, '470px'), (270, '270px'), (170, '170px')])), ('image_position', core_blocks.ChoiceBlock(choices=[('right', 'right'), ('left', 'left')], help_text='Does not apply if the image is full-width')), ('text', core_blocks.RichTextBlock(label='Caption', required=False)), ('is_bottom_rule', core_blocks.BooleanBlock(default=True, help_text='Check to add a horizontal rule line to bottom of inset.', label='Has bottom rule line', required=False))))), ('table_block', v1.atomic_elements.organisms.AtomicTableBlock(table_options={'renderer': 'html'})), ('quote', core_blocks.StructBlock((('body', core_blocks.TextBlock()), ('citation', core_blocks.TextBlock(required=False)), ('is_large', core_blocks.BooleanBlock(required=False))))), ('cta', core_blocks.StructBlock((('slug_text', core_blocks.CharBlock(required=False)), ('paragraph_text', core_blocks.RichTextBlock(required=False)), ('button', core_blocks.StructBlock((('text', core_blocks.CharBlock(required=False)), ('url', core_blocks.CharBlock(default='/', required=False)), ('size', core_blocks.ChoiceBlock(choices=[('regular', 'Regular'), ('large', 'Large Primary')])))))))), ('related_links', core_blocks.StructBlock((('heading', core_blocks.CharBlock(required=False)), ('paragraph', core_blocks.RichTextBlock(required=False)), ('links', core_blocks.ListBlock(core_blocks.StructBlock((('text', core_blocks.CharBlock(required=False)), ('url', core_blocks.CharBlock(default='/', required=False))))))))), ('reusable_text', v1.blocks.ReusableTextChooserBlock('v1.ReusableText')), ('email_signup', core_blocks.StructBlock((('heading', core_blocks.CharBlock(default='Stay informed', required=False)), ('default_heading', core_blocks.BooleanBlock(default=True, help_text='If selected, heading will be styled as an H5 with green top rule. Deselect to style header as H3.', label='Default heading style', required=False)), ('text', core_blocks.CharBlock(help_text='Write a sentence or two about what kinds of emails the user is signing up for, how frequently they will be sent, etc.', required=False)), ('gd_code', core_blocks.CharBlock(help_text='Code for the topic (i.e., mailing list) you want people who submit this form to subscribe to. Format: USCFPB_###', label='GovDelivery code', required=False)), ('disclaimer_page', core_blocks.PageChooserBlock(help_text='Choose the page that the "See Privacy Act statement" link should go to. If in doubt, use "Generic Email Sign-Up Privacy Act Statement".', label='Privacy Act statement', required=False))))), ('well', core_blocks.StructBlock((('content', core_blocks.RichTextBlock(label='Well', required=False)),))), ('well_with_ask_search', core_blocks.StructBlock((('content', core_blocks.RichTextBlock(label='Well', required=False)), ('ask_search', core_blocks.StructBlock((('show_label', core_blocks.BooleanBlock(default=True, help_text='Whether to show form label.', required=False)), ('placeholder', core_blocks.TextBlock(help_text='Text to show for the input placeholder text.', required=False))))))))))), ('expandable', core_blocks.StructBlock((('label', core_blocks.CharBlock(required=False)), ('is_bordered', core_blocks.BooleanBlock(required=False)), ('is_midtone', core_blocks.BooleanBlock(required=False)), ('is_expanded', core_blocks.BooleanBlock(required=False)), ('content', core_blocks.StreamBlock((('paragraph', core_blocks.RichTextBlock(required=False)), ('well', core_blocks.StructBlock((('content', core_blocks.RichTextBlock(label='Well', required=False)),))), ('links', core_blocks.StructBlock((('text', core_blocks.CharBlock(required=False)), ('url', core_blocks.CharBlock(default='/', required=False))))), ('email', core_blocks.StructBlock((('emails', core_blocks.ListBlock(core_blocks.StructBlock((('url', core_blocks.EmailBlock(label='Email address')), ('text', core_blocks.CharBlock(label='Link text (optional)', required=False)))))),))), ('phone', core_blocks.StructBlock((('fax', core_blocks.BooleanBlock(default=False, label='Is this number a fax?', required=False)), ('phones', core_blocks.ListBlock(core_blocks.StructBlock((('number', core_blocks.CharBlock(help_text='Do not include spaces or dashes. Ex. 8554112372', max_length=15, validators=[django.core.validators.RegexValidator(message='Enter a numeric phone number, without punctuation.', regex='^\\d*$')])), ('extension', core_blocks.CharBlock(max_length=4, required=False)), ('vanity', core_blocks.CharBlock(help_text='A phoneword version of the above number. Include any formatting. Ex. (555) 222-CFPB', max_length=15, required=False)), ('tty', core_blocks.CharBlock(help_text='Do not include spaces or dashes. Ex. 8554112372', label='TTY', max_length=15, required=False, validators=[django.core.validators.RegexValidator(message='Enter a numeric phone number, without punctuation.', regex='^\\d*$')])), ('tty_ext', core_blocks.CharBlock(label='TTY Extension', max_length=4, required=False))))))))), ('address', core_blocks.StructBlock((('label', core_blocks.CharBlock(required=False)), ('title', core_blocks.CharBlock(required=False)), ('street', core_blocks.CharBlock(required=False)), ('city', core_blocks.CharBlock(max_length=50, required=False)), ('state', core_blocks.CharBlock(max_length=25, required=False)), ('zip_code', core_blocks.CharBlock(max_length=15, required=False)))))), blank=True))))), ('expandable_group', core_blocks.StructBlock((('heading', core_blocks.CharBlock(help_text='Added as an <code>&lt;h3&gt;</code> at the top of this block. Also adds a wrapping <code>&lt;div&gt;</code> whose <code>id</code> attribute comes from a slugified version of this heading, creating an anchor that can be used when linking to this part of the page.', required=False)), ('body', core_blocks.RichTextBlock(required=False)), ('is_accordion', core_blocks.BooleanBlock(required=False)), ('has_top_rule_line', core_blocks.BooleanBlock(default=False, help_text='Check this to add a horizontal rule line to top of expandable group.', required=False)), ('expandables', core_blocks.ListBlock(core_blocks.StructBlock((('label', core_blocks.CharBlock(required=False)), ('is_bordered', core_blocks.BooleanBlock(required=False)), ('is_midtone', core_blocks.BooleanBlock(required=False)), ('is_expanded', core_blocks.BooleanBlock(required=False)), ('content', core_blocks.StreamBlock((('paragraph', core_blocks.RichTextBlock(required=False)), ('well', core_blocks.StructBlock((('content', core_blocks.RichTextBlock(label='Well', required=False)),))), ('links', core_blocks.StructBlock((('text', core_blocks.CharBlock(required=False)), ('url', core_blocks.CharBlock(default='/', required=False))))), ('email', core_blocks.StructBlock((('emails', core_blocks.ListBlock(core_blocks.StructBlock((('url', core_blocks.EmailBlock(label='Email address')), ('text', core_blocks.CharBlock(label='Link text (optional)', required=False)))))),))), ('phone', core_blocks.StructBlock((('fax', core_blocks.BooleanBlock(default=False, label='Is this number a fax?', required=False)), ('phones', core_blocks.ListBlock(core_blocks.StructBlock((('number', core_blocks.CharBlock(help_text='Do not include spaces or dashes. Ex. 8554112372', max_length=15, validators=[django.core.validators.RegexValidator(message='Enter a numeric phone number, without punctuation.', regex='^\\d*$')])), ('extension', core_blocks.CharBlock(max_length=4, required=False)), ('vanity', core_blocks.CharBlock(help_text='A phoneword version of the above number. Include any formatting. Ex. (555) 222-CFPB', max_length=15, required=False)), ('tty', core_blocks.CharBlock(help_text='Do not include spaces or dashes. Ex. 8554112372', label='TTY', max_length=15, required=False, validators=[django.core.validators.RegexValidator(message='Enter a numeric phone number, without punctuation.', regex='^\\d*$')])), ('tty_ext', core_blocks.CharBlock(label='TTY Extension', max_length=4, required=False))))))))), ('address', core_blocks.StructBlock((('label', core_blocks.CharBlock(required=False)), ('title', core_blocks.CharBlock(required=False)), ('street', core_blocks.CharBlock(required=False)), ('city', core_blocks.CharBlock(max_length=50, required=False)), ('state', core_blocks.CharBlock(max_length=25, required=False)), ('zip_code', core_blocks.CharBlock(max_length=15, required=False)))))), blank=True))))))))), ('notification', core_blocks.StructBlock((('message', core_blocks.CharBlock(help_text='The main notification message to display.', required=True)), ('explanation', core_blocks.TextBlock(help_text='Explanation text appears below the message in smaller type.', required=False)), ('links', core_blocks.ListBlock(core_blocks.StructBlock((('text', core_blocks.CharBlock(required=False)), ('url', core_blocks.CharBlock(default='/', required=False)))), help_text='Links appear on their own lines below the explanation.', required=False))))), ('table_block', v1.atomic_elements.organisms.AtomicTableBlock(table_options={'renderer': 'html'})), ('feedback', core_blocks.StructBlock((('was_it_helpful_text', core_blocks.CharBlock(default='Was this page helpful to you?', help_text='Use this field only for feedback forms that use "Was this helpful?" radio buttons.', required=False)), ('intro_text', core_blocks.CharBlock(help_text='Optional feedback intro', required=False)), ('question_text', core_blocks.CharBlock(help_text='Optional expansion on intro', required=False)), ('radio_intro', core_blocks.CharBlock(help_text='Leave blank unless you are building a feedback form with extra radio-button prompts, as in /owning-a-home/help-us-improve/.', required=False)), ('radio_text', core_blocks.CharBlock(default='This information helps us understand your question better.', required=False)), ('radio_question_1', core_blocks.CharBlock(default='How soon do you expect to buy a home?', required=False)), ('radio_question_2', core_blocks.CharBlock(default='Do you currently own a home?', required=False)), ('button_text', core_blocks.CharBlock(default='Submit')), ('contact_advisory', core_blocks.RichTextBlock(help_text='Use only for feedback forms that ask for a contact email', required=False)))))), blank=True)),
            ],
            options={
                'abstract': False,
            },
            bases=('v1.abstractfilterpage',),
        ),
        migrations.CreateModel(
            name='EnforcementActionStatus',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('institution', models.CharField(blank=True, max_length=200)),
                ('status', models.CharField(choices=[('Post Order/Post Judgment', 'Post Order/Post Judgment'), ('Expired/Terminated/Dismissed', 'Expired/Terminated/Dismissed'), ('Pending Litigation', 'Pending Litigation')], max_length=50)),
                ('action', modelcluster.fields.ParentalKey(on_delete=django.db.models.deletion.CASCADE, related_name='statuses', to='v1.EnforcementActionPage')),
            ],
        ),
    ]
Example #5
0
class HomePage(Page):
    advert = models.ForeignKey('home.Advert',
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL,
                               related_name='+')

    navigation = StreamField([
        ('NavigationImageBlock', NavigationImageBlock()),
    ])

    footer = StreamField([
        ('FooterImageBlock', FooterImageBlock()),
    ])

    body = StreamField([
        ('Paragraph', blocks.RichTextBlock()),
        ('Image', ImageChooserBlock()),
        ('OtherImgBlock', OtherImgBlock()),
        ('Text', blocks.TextBlock()),
        ('Heading', blocks.CharBlock()),
        ('BlockQuote', blocks.BlockQuoteBlock()),
        ('Email', blocks.EmailBlock()),
        ('URL', blocks.URLBlock()),
        ('Boolean', blocks.BooleanBlock()),
        ('Integer', blocks.IntegerBlock()),
        ('Float', blocks.FloatBlock()),
        ('Decimal', blocks.DecimalBlock()),
        ('Date', blocks.DateBlock()),
        ('Time', blocks.TimeBlock()),
        ('DateTime', blocks.DateTimeBlock()),
        ('RawHTML', blocks.RawHTMLBlock()),
        ('Choice', blocks.ChoiceBlock()),
        ('PageChooser', blocks.PageChooserBlock()),
        ('DocumentChooser', DocumentChooserBlock()),
        ('Banner', BannerBlock()),
        ('Embed', EmbedBlock()),
        ('RecommendCourse',
         blocks.StructBlock([('title', blocks.CharBlock()),
                             ('courses', blocks.ListBlock(CourseBlock()))],
                            template='home/blocks/recommend_courses.html')),
        ('SeriesCourse',
         blocks.StructBlock([('title', blocks.CharBlock()),
                             ('series', blocks.ListBlock(SeriesBlock()))],
                            template='home/blocks/series_list.html')),
        ('StoryBlock', StoryBlock()),
        ('ProfessorBlock', ProfessorBlock()),
        ('CategoriesListBlock', CategoriesListBlock()),
        ('SubjectCourse',
         blocks.StructBlock(
             [('required_course', blocks.ListBlock(SeriesBlock())),
              ('optional_course', blocks.ListBlock(SeriesBlock()))],
             template='home/blocks/subject_course.html')),
        ('VipBlock', VipBlock()),
        ('SeriesProcessBlock', SeriesProcessBlock()),
        ('IntroductionBlock', IntroductionBlock()),
    ])

    content_panels = Page.content_panels + [
        StreamFieldPanel('navigation'),
        StreamFieldPanel('body'),
        SnippetChooserPanel('advert'),
        StreamFieldPanel('footer'),
    ]

    api_fields = [
        APIField('body'),
    ]
Example #6
0
class ColumnWithTitleIconTextBlock(HeadingContentBaseBlock):
    icon = ImageChooserBlock(required=False)
    image_alt = blocks.CharBlock(required=False)
Example #7
0
class LinkWithImageAndContentBlock(LinkBlock):
    image = ImageChooserBlock(required=False)
    image_alt = blocks.CharBlock(required=False)
    content = blocks.RichTextBlock()
Example #8
0
class LogoGroupBlock(blocks.StructBlock):
    group_title = blocks.CharBlock()
    logo_sequences = blocks.StreamBlock([('logo_sequence', LogoSequenceBlock())
                                         ])
Example #9
0
class AccordionItemBlock(blocks.StructBlock):
    title = blocks.CharBlock()
    content = RichTextBlock()
Example #10
0
class LogoBlock(blocks.StructBlock):
    title = blocks.CharBlock(required=False)
    image = ImageChooserBlock()
Example #11
0
class LogoSequenceBlock(blocks.StructBlock):
    sequence_title = blocks.CharBlock()
    logos = blocks.StreamBlock([('logo', LogoBlock())])

    class Meta:
        icon = "fa-apple"
Example #12
0
class MuseumMapBlock(blocks.StructBlock):
    title = blocks.CharBlock()
    map_button = ButtonBlock()

    class Meta:
        icon = "fa-map"
Example #13
0
class LinkBlock(blocks.StructBlock):
    label = blocks.CharBlock()
    link = blocks.URLBlock()

    class Meta:
        icon = "fa-link"
Example #14
0
class LogoSequenceBlock(blocks.StructBlock):
    section_title = blocks.CharBlock()
    logo_groups = blocks.StreamBlock([('logo_group', LogoGroupBlock())])

    class Meta:
        icon = "fa-apple"
Example #15
0
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel, MultiFieldPanel, FieldRowPanel
from wagtail.snippets.edit_handlers import SnippetChooserPanel
from wagtail.images.blocks import ImageChooserBlock
from wagtail.snippets.models import register_snippet
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.core.models import Orderable as WagtailOrderable
from modelcluster.fields import ParentalKey
from wagtail.admin.edit_handlers import InlinePanel
from wagtailmetadata.models import MetadataPageMixin
"""
We'll need to figure out which components are truly "base" and
which are bits that should be used in subclassing template-based
page types.
"""
base_fields = [
    ('heading', blocks.CharBlock()),
    ('paragraph',
     blocks.RichTextBlock(features=[
         'bold',
         'italic',
         'h2',
         'h3',
         'h4',
         'h5',
         'ol',
         'ul',
         'link',
         'image',
         'hr',
     ])),
    ('image_text', customblocks.ImageTextBlock()),
Example #16
0
class CollectionItemBlock(blocks.StructBlock):
    image = ImageChooserBlock()
    title = blocks.CharBlock()
    description = blocks.CharBlock()
    artist = SnippetChooserBlock(People)
    year = blocks.IntegerBlock(min_value=0)
Example #17
0
class HeadingContentBaseBlock(blocks.StructBlock):
    heading = blocks.CharBlock()
    content = blocks.RichTextBlock()
Example #18
0
class EventItemBlock(blocks.StructBlock):
    schedule = blocks.DateTimeBlock()
    event = blocks.CharBlock()
    description = blocks.CharBlock()
Example #19
0
class LinkBlock(blocks.StructBlock):
    source = blocks.CharBlock(
        help_text='The source or the type of the link, e.g. GOV.UK/Advice')
    text = blocks.CharBlock()
    url = blocks.CharBlock()  # not a URL block to allow relative links
Example #20
0
class ButtonBlock(blocks.StructBlock):
    label = blocks.CharBlock()
    link = blocks.URLBlock()

    class Meta:
        icon = "fa-play-circle"
Example #21
0
class Faq(blocks.StreamBlock):
    question = blocks.CharBlock(classname="question")
    answer = blocks.RichTextBlock(classname="answer")

    class Meta:
        template = 'universal_page/blocks/faq.html'
Example #22
0
class TraineePage(Page):
    CATEGORY_CHOICES = (
        ('story', '蜕变故事'),
        ('picture', '瑜伽图片'),
        ('video', '光影瑜伽'),
    )
    date = models.DateField('发表日期')
    category = models.CharField('类别',
                                choices=CATEGORY_CHOICES,
                                max_length=16,
                                default='picture')
    name = models.CharField('姓名', max_length=32, blank=True)
    age = models.CharField('年龄', max_length=8, default='保密')
    occupation = models.CharField('职业', max_length=16, default='自由职业者')
    intro = RichTextField('简介', max_length=128, blank=True)
    body = StreamField([
        ('标题', blocks.CharBlock(classname="full title")),
        ('段落', blocks.RichTextBlock()),
        ('图片', ImageChooserBlock()),
    ])
    tags = ClusterTaggableManager(through=TraineePageTag, blank=True)

    class Meta:
        verbose_name = '学员详情页'
        verbose_name_plural = verbose_name

    def thumbnail_image(self):
        gallery_item = self.gallery_images.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

    def main_doc(self):
        gallery_item = self.gallery_docs.first()
        if gallery_item:
            return gallery_item.doc
        else:
            return None

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

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            FieldPanel('date'),
            FieldPanel('tags'),
        ],
                        heading="内容属性"),
        MultiFieldPanel([
            FieldPanel('name'),
            FieldPanel('age'),
            FieldPanel('occupation'),
            FieldPanel('intro'),
            FieldPanel('category'),
        ],
                        heading='学员简介'),
        StreamFieldPanel('body'),
        InlinePanel('gallery_images', label='Gallery images'),
        InlinePanel('gallery_docs', label='Gallery documents')
    ]

    def get_context(self, request):
        wallpaper = Image.objects.filter(
            tags__name="学员壁纸").order_by('-created_at')[0]
        # Update template context
        context = super().get_context(request)
        context['wallpaper'] = wallpaper
        return context
Example #23
0
class DALMEPage(Page):
    header_image = models.ForeignKey(
        'dalme_public.DALMEImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text='The image that will display in the header.')
    short_title = models.CharField(
        max_length=63,
        null=True,
        blank=True,
        help_text=
        'An optional short title that will be displayed in certain space constrained contexts.'  # noqa
    )

    body = StreamField([
        ('main_image', MainImageBlock()),
        ('carousel', CarouselBlock(ImageChooserBlock())),
        ('inline_image', ImageChooserBlock()),
        ('text', blocks.RichTextBlock()),
        ('heading', blocks.CharBlock()),
        ('pullquote', blocks.RichTextBlock(icon='openquote')),
        ('page', blocks.PageChooserBlock()),
        ('document', DocumentBlock()),
        ('person', PersonBlock()),
        ('external_resource', ExternalResourceBlock()),
        ('embed', EmbedBlock(icon='media')),
        ('html', blocks.RawHTMLBlock()),
        ('subsection', SubsectionBlock()),
    ],
                       null=True)

    class Meta:
        abstract = True

    def get_context(self, request):
        context = super().get_context(request)
        context.update({
            'api_endpoint': settings.API_ENDPOINT,
            'db_endpoint': settings.DB_ENDPOINT
        })
        return context

    @property
    def main_image(self):
        try:
            field = next(field for field in self.body
                         if field.block.name in ['carousel', 'main_image'])
        except StopIteration:
            return None
        if field.block.name == 'main_image':
            return field.value
        try:
            return field.value[0]
        except IndexError:
            return None

    @property
    def title_switch(self):
        """Utility to reduce OR coalescing in templates.
        Prefer the short_title if a Page has one, if not fallback to title.
        """
        try:
            return self.short_title or self.title
        except AttributeError:
            return self.title
Example #24
0
class AbstractProduct(ClusterableModel, OscarAbstractProduct):
    priority = models.IntegerField(default='0')
    active = models.BooleanField(default=True)
    description = RichTextField(blank=True)
    price = models.DecimalField(default=None, max_digits=18, decimal_places=2, blank=True, help_text="Price including VAT")
    sku = models.CharField(max_length = 255, blank=True )
    default_attributes = StreamField([
        ('attribute', blocks.StructBlock([
            ('key', blocks.CharBlock()),
            ('value', blocks.CharBlock()),
        ], icon='table'))
    ], blank=True)

    product_class = models.ForeignKey(
        'catalogue.ProductClass',
        null=True,
        blank=True,
        on_delete=models.PROTECT,
        verbose_name=_('Product type'), related_name="products",
        help_text=_("Choose what type of product this is"),
        default=1)
    general_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('description', classname="full"),
        FieldPanel('price', classname="full"),
    ]
    images_panels = [
        MultiFieldPanel(
            [
                InlinePanel('images', label="Image"),                
            ],
            heading="Images",
            classname=None
        )
    ]

    attributes_panels = [
        StreamFieldPanel('default_attributes'),
    ]

    categories_panels = [
        MultiFieldPanel(
            [
                InlinePanel('product_category', label="Category"),
            ],
            heading="Categories",
            classname=None
        )
    ]

    settings_panels = [
        FieldPanel('active'),
        FieldPanel('sku'),
        FieldPanel('priority'),
        FieldPanel('product_class'),
    ]
    edit_handler = TabbedInterface([
        ObjectList(general_panels, heading='General'),
        ObjectList(attributes_panels, heading='Attributes'),
        ObjectList(images_panels, heading='Images'),
        ObjectList(categories_panels, heading='Categories'),
        ObjectList(settings_panels, heading='Settings'),
    ])

    # base_form_class = ProductForm
    @property
    def get_absolute_url(self):
        return ""
    
    def avatar_property(self):
        return self.images.first().image
    avatar_property.short_description = "Full name of the person"
    avatar = property(avatar_property)

    def primary_image(self):
        if self.images.first():

            image = self.images.first().image

            return image
        else:
            return None

    def save(self, *args, **kwargs):

        if not self.pk:
            super().save(*args, **kwargs)
            if not self.sku :
                self.sku = self.pk
            partner = Partner.objects.first()
            exc_vat = Decimal(self.price)/(Decimal('1') + Decimal(str(Selector.strategy(self).rate)))
            stock = StockRecord(partner=partner, product=self, partner_sku=self.sku, price_excl_tax=exc_vat)
            stock.save()


        else:
            stockrecord = self.stockrecords.first()
            exc_vat = Decimal(self.price)/(Decimal('1') + Decimal(str(Selector.strategy(self).rate)))
            stockrecord.price_excl_tax=exc_vat
            if not self.sku or self.sku == '':
                self.sku = self.pk
            stockrecord.partner_sku=self.sku
            stockrecord.save()


        super().save(*args, **kwargs)  # Call the "real" save() method.

    class Meta:
        abstract = True
        app_label = 'catalogue'
        verbose_name = _('Product')
        verbose_name_plural = _('Products')
        ordering = ["-active", "-priority", "-date_created"]
Example #25
0
class PersonBlock(blocks.StructBlock):
    name = blocks.CharBlock()
    bio = blocks.RichTextBlock()
    body = blocks.StreamBlock([("heading", blocks.CharBlock()),
                               ("paragraph", blocks.RichTextBlock()),
                               ("image", ImageChooserBlock())])
Example #26
0
class PulseProjectList(blocks.StructBlock):
    search_terms = blocks.CharBlock(
        help_text='Test your search at mozillapulse.org/search',
        label='Search',
        required=False,
    )

    max_number_of_results = blocks.IntegerBlock(
        min_value=0,
        max_value=12,
        default=6,
        required=True,
        help_text=
        'Choose 1-12. If you want visitors to see more, link to a search or tag on Pulse.',
    )

    only_featured_entries = blocks.BooleanBlock(
        default=False,
        label='Display only featured entries',
        help_text='Featured items are selected by Pulse moderators.',
        required=False,
    )

    newest_first = blocks.ChoiceBlock(
        choices=[
            ('True', 'Show newer entries first'),
            ('False', 'Show older entries first'),
        ],
        required=True,
        label='Sort',
        default='True',
    )

    advanced_filter_header = blocks.StaticBlock(
        label=' ',
        admin_text=
        '-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------',
    )

    issues = blocks.ChoiceBlock(choices=[
        ('all', 'All'),
        ('Decentralization', 'Decentralization'),
        ('Digital Inclusion', 'Digital Inclusion'),
        ('Online Privacy & Security', 'Online Privacy & Security'),
        ('Open Innovation', 'Open Innovation'),
        ('Web Literacy', 'Web Literacy'),
    ],
                                required=True,
                                default='all')

    help = blocks.ChoiceBlock(
        choices=[
            ('all', 'All'),
            ('Attend', 'Attend'),
            ('Create content', 'Create content'),
            ('Code', 'Code'),
            ('Design', 'Design'),
            ('Fundraise', 'Fundraise'),
            ('Join community', 'Join community'),
            ('Localize & translate', 'Localize & translate'),
            ('Mentor', 'Mentor'),
            ('Plan & organize', 'Plan & organize'),
            ('Promote', 'Promote'),
            ('Take action', 'Take action'),
            ('Test & feedback', 'Test & feedback'),
            ('Write documentation', 'Write documentation'),
        ],
        required=True,
        default='all',
        label='Type of help needed',
    )

    class Meta:
        template = 'wagtailpages/blocks/pulse_project_list.html'
        icon = 'site'
        value_class = PulseProjectQueryValue
Example #27
0
class ArticlePage(CFGOVPage):
    """
    General article page type.
    """
    category = models.CharField(
        choices=[
            ('basics', 'Basics'),
            ('common_issues', 'Common issues'),
            ('howto', 'How to'),
            ('know_your_rights', 'Know your rights'),
        ],
        max_length=255,
    )
    heading = models.CharField(
        max_length=255,
        blank=False,
    )
    intro = models.TextField(blank=False)
    inset_heading = models.CharField(max_length=255,
                                     blank=True,
                                     verbose_name="Heading")
    sections = StreamField([
        ('section',
         blocks.StructBlock([
             ('heading',
              blocks.CharBlock(max_length=255,
                               required=True,
                               label='Section heading')),
             ('summary',
              blocks.TextBlock(required=False,
                               blank=True,
                               label='Section summary')),
             ('link_text',
              blocks.CharBlock(required=False,
                               blank=True,
                               label="Section link text")),
             ('url',
              blocks.CharBlock(
                  required=False,
                  blank=True,
                  label='Section link URL',
                  max_length=255,
              )),
             ('subsections',
              blocks.ListBlock(
                  blocks.StructBlock([
                      ('heading',
                       blocks.CharBlock(max_length=255,
                                        required=False,
                                        blank=True,
                                        label='Subsection heading')),
                      ('summary',
                       blocks.TextBlock(required=False,
                                        blank=True,
                                        label='Subsection summary')),
                      ('link_text',
                       blocks.CharBlock(required=True,
                                        label='Subsection link text')),
                      ('url',
                       blocks.CharBlock(required=True,
                                        label='Subsection link URL'))
                  ])))
         ]))
    ])
    content_panels = CFGOVPage.content_panels + [
        MultiFieldPanel([
            FieldPanel('category'),
            FieldPanel('heading'),
            FieldPanel('intro')
        ],
                        heading="Heading",
                        classname="collapsible"),
        MultiFieldPanel([
            FieldPanel('inset_heading'),
            InlinePanel('article_links', label='Inset link', max_num=2),
        ],
                        heading="Inset links",
                        classname="collapsible"),
        StreamFieldPanel('sections'),
    ]

    sidebar = StreamField([
        ('call_to_action', molecules.CallToAction()),
        ('related_links', molecules.RelatedLinks()),
        ('related_metadata', molecules.RelatedMetadata()),
        ('email_signup', organisms.EmailSignUp()),
        ('reusable_text', v1_blocks.ReusableTextChooserBlock(ReusableText)),
    ],
                          blank=True)

    sidebar_panels = [
        StreamFieldPanel('sidebar'),
    ]

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

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

    template = 'ask-cfpb/article-page.html'

    objects = CFGOVPageManager()

    def get_context(self, request, *args, **kwargs):
        context = super(ArticlePage, self).get_context(request)
        context['about_us'] = get_standard_text(self.language, 'about_us')
        return context

    def __str__(self):
        return self.title
Example #28
0
class LatestProfileList(blocks.StructBlock):
    max_number_of_results = blocks.IntegerBlock(
        min_value=1,
        max_value=48,
        default=12,
        required=True,
        help_text='Pick up to 48 profiles.',
    )

    advanced_filter_header = blocks.StaticBlock(
        label=' ',
        admin_text=
        '-------- ADVANCED FILTERS: OPTIONS TO DISPLAY FEWER, MORE TARGETED RESULTS. --------',
    )

    profile_type = blocks.CharBlock(required=False,
                                    default='',
                                    help_text='Example: Fellow.')

    program_type = blocks.CharBlock(required=False,
                                    default='',
                                    help_text='Example: Tech Policy.')

    year = blocks.CharBlock(required=False, default='')

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        query_args = {
            'limit': context['block'].value['max_number_of_results'],
            'profile_type': context['block'].value['profile_type'],
            'program_type': context['block'].value['program_type'],
            'program_year': context['block'].value['year'],
            'ordering': '-id',
            'is_active': 'true',
            'format': 'json',
        }

        # filter out emptish values
        query_args = {k: v for k, v in query_args.items() if v}

        # FIXME: the protocol should be part of the pulse api variable.
        #   see: https://github.com/mozilla/foundation.mozilla.org/issues/1824

        url = "{pulse_api}/api/pulse/v2/profiles/?{query}".format(
            pulse_api=settings.FRONTEND['PULSE_API_DOMAIN'],
            query=parse.urlencode(query_args))

        try:
            response = request.urlopen(url)
            response_data = response.read()
            data = json.loads(response_data)

            for profile in data:
                profile['created_entries'] = False
                profile['published_entries'] = False
                profile['entry_count'] = False
                profile['user_bio_long'] = False

        except (IOError, ValueError) as exception:
            print(str(exception))
            pass

        context['profiles'] = data
        return context

    class Meta:
        template = 'wagtailpages/blocks/profile_blocks.html'
        icon = 'group'
        value_class = LatestProfileQueryValue
class RecentBlogEntries(blocks.StructBlock):
    title = blocks.CharBlock(required=True, )

    tag_filter = blocks.CharBlock(
        label='Filter by Tag',
        required=False,
        help_text='Test this filter at foundation.mozilla.org/blog/tags/',
    )

    category_filter = blocks.ChoiceBlock(
        label='Filter by Category',
        required=False,
        choices=BlogPageCategory.get_categories,
        help_text='Test this filter at foundation.mozilla.org/blog/category/',
    )

    top_divider = blocks.BooleanBlock(
        required=False,
        help_text='Optional divider above content block.',
    )

    bottom_divider = blocks.BooleanBlock(
        required=False,
        help_text='Optional divider below content block.',
    )

    # TODO: add in validation so that if there are no tags or category
    #       filled in we don't allow the page to be saved, with a wagtail
    #       error indication what's wrong.

    def get_context(self, value, parent_context=None):
        context = super().get_context(value, parent_context=parent_context)
        BlogIndexPage = apps.get_model('wagtailpages.BlogIndexPage')
        blogpage = BlogIndexPage.objects.get(title_en__iexact="blog")

        tag = value.get("tag_filter", False)
        category = value.get("category_filter", False)

        # default filter and query
        type = "tags"
        query = "mozilla"
        entries = []

        # If only tag_filter is chosen we want to load entries by tag and update the url accordingly
        if tag and not category:
            tag = slugify(tag)
            query = tag
            blogpage.extract_tag_information(tag)
            entries = blogpage.get_entries(context)
        '''
        If category_filter is chosen at all, we want to load entries by category and
        update the url accordingly. Once we add validation, we'll be able to remove
        the prioritization of category and instead notify the user that they must/can
        only choose one filter option.
        '''
        if category and category != "All":
            type = "category"
            query = slugify(category)
            try:
                # verify this category exists, and set up a filter for it
                category_object = BlogPageCategory.objects.get(name=category)
                blogpage.extract_category_information(category_object.slug)
            except BlogPageCategory.DoesNotExist:
                # do nothing
                pass

        # get the entries based on prefiltering
        entries = blogpage.get_entries(context)

        # Updates the href for the 'More from our blog' button
        url = f"/{blogpage.slug}/{type}/{query}"
        context['more_entries_link'] = url

        # We only want to grab no more than the first 6 entries
        context['entries'] = entries[0:6]

        # We only want to display the 'More from our blog' button if
        # there's more than 6 entries
        context['more_entries'] = len(entries) > 6

        # this data does not belong "on a root document" but is pulled for
        # transclusion in arbitrary pages, so don't try to figure out the
        # page hierarachy.
        context['root'] = None

        # Optional dividers
        divider_styles = []
        if value.get("top_divider"):
            divider_styles.append('div-top-thick pt-4')
        if value.get("bottom_divider"):
            divider_styles.append('div-bottom-thick pb-4')
        context['divider_styles'] = ' '.join(divider_styles)

        return context

    class Meta:
        template = 'wagtailpages/blocks/recent_blog_entries.html'
        icon = 'site'
Example #30
0
class EventListBlock(blocks.StructBlock):
    title = blocks.CharBlock(required=False)
    events = blocks.StreamBlock([("event", EventLinkBlock())])

    class Meta:
        template = "home/blocks/event_list_block.html"