class TestFieldRowPanelWithChooser(TestCase):
    def setUp(self):
        self.request = RequestFactory().get('/')
        user = AnonymousUser()  # technically, Anonymous users cannot access the admin
        self.request.user = user

        self.EventPageForm = get_form_for_model(
            EventPage, form_class=WagtailAdminPageForm, formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 19), date_to=date(2014, 7, 21))

        self.dates_panel = FieldRowPanel([
            FieldPanel('date_from'),
            ImageChooserPanel('feed_image'),
        ]).bind_to(model=EventPage, request=self.request)

    def test_render_as_object(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-22'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )
        result = field_panel.render_as_object()

        # check that the populated form field is included
        self.assertIn('value="2014-07-20"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)
    def setUp(self):
        self.request = RequestFactory().get('/')
        user = AnonymousUser()  # technically, Anonymous users cannot access the admin
        self.request.user = user

        self.EventPageForm = get_form_for_model(
            EventPage, form_class=WagtailAdminPageForm, formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 19), date_to=date(2014, 7, 21))

        self.dates_panel = FieldRowPanel([
            FieldPanel('date_from'),
            ImageChooserPanel('feed_image'),
        ]).bind_to(model=EventPage, request=self.request)
Exemple #3
0
class _RUBIONUserModelDefinition(MoveMixin, UserGeneratedPage2):
    class Meta:
        abstract = True

    # This class is just to get more readable code

    # named dosemeters

    NOT_YET_DECIDED = '0'
    NO_DOSEMETER = '1'
    OFFICIAL_DOSEMETER = '2'
    ELECTRONIC_DOSEMETER = '3'
    EXTERNAL_DOSEMETER = '4'

    DOSEMETER_CHOICES = (
        (NOT_YET_DECIDED, _('Not yet decided')),
        (NO_DOSEMETER, _('No dosemeter')),
        (OFFICIAL_DOSEMETER, _('Official dosemeter')),
        (ELECTRONIC_DOSEMETER, _('Electronic dosemeter')),
        (EXTERNAL_DOSEMETER, _('External dosemeter')),
    )
    DOSEMETER_SHORT_NAMES = {
        NOT_YET_DECIDED: _('not decided'),
        NO_DOSEMETER: _('not required'),
        OFFICIAL_DOSEMETER: _('official'),
        ELECTRONIC_DOSEMETER: _('electronic'),
        EXTERNAL_DOSEMETER: _('external'),
    }

    FIELDS_TO_SYNC_WITH_STAFF = ['key_number', 'dosemeter']
    # --- Fields

    # This is a bit annoying, since it repeats the definitions of the
    # normal wagtail user fields. These fields might be not necessary,
    # but I introduced them for some reasons (maybe for course users?)

    name_db = models.CharField(max_length=32,
                               blank=True,
                               null=True,
                               verbose_name=_('name'))
    name_db.context_description = 'Nachname'

    first_name_db = models.CharField(max_length=32,
                                     blank=True,
                                     null=True,
                                     verbose_name=_('first name'))
    first_name_db.context_description = 'Vorname'

    email_db = models.CharField(max_length=128,
                                blank=True,
                                null=True,
                                verbose_name=_('email address'))
    email_db.context_description = 'E-Mail-Adresse'

    # --- Fields for additional personal data

    # I don't like the question in the form "What is your gender?"

    MALE = 'm'
    FEMALE = 'f'

    SEXES = (
        (MALE, _('male')),
        (FEMALE, _('female')),
    )

    sex = models.CharField(
        max_length=1,
        choices=SEXES,
        blank=True,
        null=True,
        verbose_name=_('What is your gender?'),
        help_text=
        _('We ask this question to correctly address you in emails and letters send to you.'
          ))
    sex.context_description = 'Geschlecht'

    BSC = 'b'
    MSC = 'm'
    PHD = 'd'
    MD = 'n'
    PROF = 'p'
    NON = ''

    ACADEMIC_TITLES = (
        (NON, _('None')),
        (BSC, _('BSc')),
        (MSC, _('MSc')),
        (PHD, _('PhD')),
        (MD, _('MD')),
        (PROF, _('Prof.')),
    )

    academic_title = models.CharField(max_length=1,
                                      choices=ACADEMIC_TITLES,
                                      blank=True,
                                      null=True,
                                      verbose_name=_('academic title'))
    academic_title.context_description = 'Akademischer Titel'

    phone = models.CharField(max_length=24,
                             verbose_name=_('Phone number'),
                             blank=True,
                             null=True)
    phone.context_description = 'Telefonnummer'

    linked_user = models.ForeignKey(settings.AUTH_USER_MODEL,
                                    blank=True,
                                    null=True,
                                    verbose_name=_('linked website user'),
                                    on_delete=models.SET_NULL)

    preferred_language = models.CharField(
        max_length=2,
        choices=settings.LANGUAGES,
        null=True,
        blank=True,
        verbose_name=_('Preferred language for communication'))
    preferred_language.context_description = 'Bevorzugte Sprache'

    # --- Fields required by radiation safety

    date_of_birth = models.DateField(null=True,
                                     blank=True,
                                     verbose_name=_('Date of birth'),
                                     help_text=_('Format: YYYY-MM-DD'))
    date_of_birth.context_description = 'Geburtsdatum'

    place_of_birth = models.CharField(
        max_length=256,
        null=True,
        blank=True,
        verbose_name=_('Place of birth'),
        help_text=_('Add the country, if not Germany'))
    place_of_birth.context_description = 'Geburtsort'

    previous_names = models.CharField(
        max_length=512,
        null=True,
        blank=True,
        verbose_name=_('Previous names.'),
        help_text=_(
            'Please list your previous name (in case of marriage, for example)'
        ))
    previous_names.context_description = 'Vorheriger Name'

    previous_exposure = models.BooleanField(
        default=False,
        verbose_name=_('Previous exposure'),
        help_text=
        _('Has there been work-related previous exposure to ionizing radiation?'
          ))
    previous_exposure.context_description = 'Vorherige Expositionen'
    # --- Fields for RUBION-internal use

    is_validated = models.BooleanField(default=False,
                                       verbose_name=_('is the user validated'))
    is_validated.context_description = 'Status der Validierung'

    has_agreed = models.BooleanField(default=False,
                                     verbose_name=_('has agreed'))
    has_agreed.context_description = 'Nutzungsbedingungen zugestimmt?'

    is_rub = models.BooleanField(default=False,
                                 verbose_name=_('is a member of the RUB'))
    is_rub.context_description = 'RUB-Mitglied?'

    # Safety-instructions are not yet implemented

    #    last_safety_instructions = models.DateField(
    #        null = True,
    #        blank = True
    #    )
    needs_safety_instructions = ParentalManyToManyField(
        'userdata.SafetyInstructionsSnippet',
        verbose_name=_('user needs safety instruction'),
        help_text=_('Which safety instructions are required for the user?'),
        blank=True)

    key_number = models.CharField(max_length=64,
                                  blank=True,
                                  default='',
                                  verbose_name=_('Key number'))
    key_number.context_description = 'Schlüsselnummer'

    labcoat_size = models.CharField(max_length=6,
                                    blank=True,
                                    default='',
                                    choices=(
                                        ('S', 'S'),
                                        ('M', 'M'),
                                        ('L', 'L'),
                                        ('XL', 'XL'),
                                        ('2XL', '2XL'),
                                        ('3XL', '3XL'),
                                        ('4XL', '4XL'),
                                        ('5XL', '5XL'),
                                    ),
                                    verbose_name=_('lab coat size'),
                                    help_text=_('The size of your lab coat.'))
    labcoat_size.context_description = 'Kittelgröße'

    overshoe_size = models.CharField(
        max_length=6,
        blank=True,
        default='',
        choices=(
            ('2', 'S-M'),
            ('3', 'L-XL'),
            ('4', 'XXL or above'),
        ),
        verbose_name=_('shoe size'),
        help_text=_('The size your protecting shoes should have.'))
    overshoe_size.context_description = 'Größe der Überschuhe'

    entrance = models.CharField(
        max_length=6,
        blank=True,
        default='',
        choices=(
            ('0', 'NB'),
            ('1', 'NC'),
            ('2', 'ND'),
            ('3', 'NI 06'),
        ),
        verbose_name=_('Preferred entrance in the lab.'))
    entrance.context_description = 'Eingang ins Labor'

    initially_seen = ParentalManyToManyField(
        'userdata.StaffUser',
        #        default = False,
        verbose_name=_('User seen by RUBION staff members'),
        blank=True)

    # --- Some simple permissions

    is_leader = models.BooleanField(default=False,
                                    verbose_name=_('leader of the group'))
    is_leader.context_description = 'Gruppenleiter?'

    # Can be set by the group leader

    may_create_projects = models.BooleanField(
        default=False, verbose_name=_('may create projects'))
    may_create_projects.context_description = 'Darf Projekte anlegen?'

    may_add_members = models.BooleanField(default=False,
                                          verbose_name=_('May add members'))
    may_add_members.context_description = 'Darf Mitglieder hinzufügen?'

    needs_key = models.BooleanField(
        default=False,
        verbose_name=_('Does this user permanently need a key?'))
    needs_key.context_description = 'Benötigt einen Schlüssel?'

    dosemeter = models.CharField(max_length=1,
                                 choices=DOSEMETER_CHOICES,
                                 default=NOT_YET_DECIDED,
                                 verbose_name=_('Type of dosemeter'))
    dosemeter.context_description = 'Benötigtes Dosimeter'

    admin_fields = [
        'key_number', 'is_group_leader', 'linked_user', 'title', 'title_de',
        'is_validated', 'has_agreed', 'key_number', 'last_safety_instructions',
        'needs_safety_instructions', 'is_rub', 'dosemeter'
    ]
    group_head_fields = ['needs_key', 'may_add_members', 'may_create_projects']
    personal_fields = ['academic_title', 'phone', 'sex']

    # Admin content panels.
    # @TODO might require some clean-up
    content_panels = [
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('name_db'),
                FieldPanel('first_name_db'),
            ]),
            FieldPanel('email_db'),
            FieldPanel('preferred_language'),
            FieldPanel('academic_title'),
            FieldPanel('sex'),
        ],
                        heading=_('personal information')),
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel('date_of_birth'),
                    FieldPanel('place_of_birth')
                ]),
                FieldRowPanel([
                    FieldPanel('previous_names'),
                    FieldPanel('previous_exposure')
                ]),
            ],
            heading=_('Additional personal data for radiation safety')),
    ]
    settings_panel = [
        MultiFieldPanel([
            FieldPanel('linked_user'),
            FieldRowPanel([
                FieldPanel('has_agreed'),
                FieldPanel('is_validated'),
            ]),
            FieldRowPanel([
                FieldPanel('is_rub'),
                FieldPanel('is_leader'),
            ]),
        ],
                        heading=_('internal information')),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('may_create_projects'),
                FieldPanel('may_add_members'),
            ])
        ],
                        heading=_('user permissions')),
    ]
    rubion_panel = [
        MultiFieldPanel([
            FieldPanel('dosemeter'),
            FieldRowPanel([
                FieldPanel('labcoat_size'),
                FieldPanel('overshoe_size'),
            ]),
            FieldPanel('entrance'),
        ],
                        heading=_('Safety')),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('needs_key', classname="col4"),
                FieldPanel('key_number', classname="col8"),
            ])
        ],
                        heading=_('Key')),
        MultiFieldPanel([
            InlinePanel('may_book', label=_('User may book')),
        ],
                        heading='User permissions'),
    ]

    comment_panel = [FieldPanel('internal_rubion_comment')]

    si_panel = [
        FieldPanel('needs_safety_instructions',
                   widget=forms.CheckboxSelectMultiple),
        InlinePanel('rubion_user_si',
                    panels=[
                        FieldRowPanel(
                            [FieldPanel('instruction'),
                             FieldPanel('date')])
                    ])
    ]
    edit_handler = TabbedInterface([
        ObjectList(rubion_panel, heading=_('Settings set by RUBION')),
        ObjectList(si_panel, heading=_('Safety instructions')),
        ObjectList(comment_panel, heading=_('internal comments')),
        ObjectList(settings_panel, heading=_('internal settings')),
        ObjectList(content_panels, heading=_('User Data')),
    ])
Exemple #4
0
class Event(models.Model):
    FREE = 'FREE'
    PAID = 'PAID'
    NA = 'NA'
    COST_CHOICES = (
        (FREE, 'Free'),
        (PAID, 'Paid'),
        (NA, 'n/a'),
    )

    NATIVE = 'NT'
    MSL = 'MSL'
    TICKET_TYPE_CHOICES = (
        (NA, 'n/a'),
        (NATIVE, 'Native'),
        (MSL, 'MSL'),
    )

    SOFT_DRINKS_ALCOHOL = 'AV'
    NO_ALCOHOL = 'NO'
    NOT_ALCOHOL_FOCUSED = 'NF'

    ALCOHOL_CHOICES = (
        (SOFT_DRINKS_ALCOHOL, 'Soft drinks & alcohol available'),
        (NO_ALCOHOL, 'No alcohol'),
        (NOT_ALCOHOL_FOCUSED, 'Not alcohol focused'),
    )

    LIMITED_AVAILABILITY = 'LA'
    SOLD_OUT = 'SO'
    TICKET_LEVEL_CHOICES = (
        (NA, 'Not applicable'),
        (LIMITED_AVAILABILITY, 'Limited availability'),
        (SOLD_OUT, 'Sold out'),
    )

    parent = models.ForeignKey('self',
                               default=None,
                               null=True,
                               blank=True,
                               related_name='children',
                               on_delete=models.SET_NULL)

    title = models.TextField()
    slug = AutoSlugField(populate_from='title', unique=False)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

    featured_image = models.ForeignKey(MatteImage,
                                       null=True,
                                       blank=True,
                                       on_delete=models.SET_NULL)
    url = models.URLField(blank=True, default='')
    social_facebook = models.URLField(blank=True, default='')
    kicker = models.CharField(max_length=255, default='', blank=True)
    location_display = models.CharField(max_length=255, default='', blank=True)
    embargo_until = models.DateTimeField(null=True, blank=True)

    venue = models.ForeignKey(Venue,
                              blank=True,
                              null=True,
                              on_delete=models.SET_NULL)
    short_description = models.TextField(default='')
    body = RichTextField(default='', blank=True)
    student_group = models.ForeignKey(StudentGroup,
                                      null=True,
                                      blank=True,
                                      default=None,
                                      on_delete=models.SET_NULL)

    is_over_18_only = models.BooleanField(default=False)
    ticket_level = models.CharField(max_length=2,
                                    choices=TICKET_LEVEL_CHOICES,
                                    default=NA)
    cost = models.CharField(max_length=10, choices=COST_CHOICES, default=NA)
    alcohol = models.CharField(max_length=2,
                               choices=ALCOHOL_CHOICES,
                               default=NOT_ALCOHOL_FOCUSED)

    ticket_type = models.CharField(max_length=3,
                                   choices=TICKET_TYPE_CHOICES,
                                   default=NA)
    ticket_data = models.TextField(default='', blank=True)

    suitable_kids_families = models.BooleanField(default=False)
    just_for_pgs = models.BooleanField(default=False)

    bundle = models.ForeignKey(Bundle,
                               null=True,
                               blank=True,
                               on_delete=models.SET_NULL)
    brand = models.ForeignKey(BrandingPeriod,
                              null=True,
                              blank=True,
                              on_delete=models.SET_NULL)
    category = models.ForeignKey(Category,
                                 null=True,
                                 blank=True,
                                 on_delete=models.SET_NULL)
    type = models.ForeignKey(Type,
                             null=True,
                             blank=True,
                             on_delete=models.SET_NULL)

    custom_panels = [
        MultiFieldPanel([
            FieldPanel('title', classname='title'),
            FieldRowPanel([
                FieldPanel('start_time'),
                FieldPanel('end_time'),
            ]),
            FieldPanel('embargo_until'),
            ImageChooserPanel('featured_image')
        ],
                        heading='The basics'),
        MultiFieldPanel([
            FieldPanel('kicker'),
            FieldPanel('short_description'),
            FieldPanel('body'),
            FieldPanel('location_display'),
            FieldPanel('venue'),
        ],
                        heading='More details'),
        MultiFieldPanel([
            FieldPanel('social_facebook'),
            FieldPanel('url'),
        ],
                        heading='Social'),
        MultiFieldPanel([
            FieldPanel('is_over_18_only'),
            FieldPanel('ticket_level'),
            FieldPanel('cost'),
            FieldPanel('alcohol'),
            FieldPanel('suitable_kids_families'),
            FieldPanel('just_for_pgs'),
        ],
                        heading='About the event itself'),
        MultiFieldPanel([
            FieldPanel('ticket_type'),
            FieldPanel('ticket_data'),
        ],
                        heading='Ticketing'),
        MultiFieldPanel([
            FieldPanel('bundle'),
            FieldPanel('brand'),
            FieldPanel('category'),
            FieldPanel('type'),
            FieldPanel('parent')
        ],
                        heading='Organisation'),
    ]

    edit_handler = ObjectList(custom_panels)

    def get_msl_event_id(self):
        try:
            return MSLEvent.objects.get(event=self).msl_event_id
        except MSLEvent.DoesNotExist:
            return None

    def get_linked_meta(self):
        return LinkedMetadata(title='{} | What\'s on'.format(self.title),
                              description=self.short_description,
                              path='/whats-on/{}-{}'.format(
                                  self.slug, self.pk),
                              image_resource=self.featured_image)

    def move_under(self, parent, user):
        if not user.has_perm('events.change_event'):
            return False

        if parent.pk == self.pk:
            return False

        if parent.is_top_level() and not self.has_child_events():
            self.parent = parent
            return True
        else:
            return False

    def is_top_level(self):
        return self.parent is None

    def has_child_events(self):
        return self.children.count() > 0

    def __str__(self):
        return self.title
Exemple #5
0
class PlanetaryBodyMixin(OrbitalMechanicsMixin):
    """
    A mixin for planetary bodies, with properties like density and gravity.

    Note: moons are a form of planetary body too!
    """

    mass = MultiQuantityField(units=(ureg.earth_mass, ureg.jovian_mass, ureg.kilogram))
    radius = MultiQuantityField(units=(ureg.earth_radius, ureg.jovian_radius, ureg.km, ureg.mile, ureg.m))

    @property
    def mass_is_jovian(self):
        return self.mass.to("jovian_mass").magnitude > 0.1

    @property
    def mass_is_terran(self):
        return self.mass.to("earth_mass").magnitude > 0.001

    @property
    def radius_is_jovian(self):
        return self.radius.to("jovian_radius").magnitude > 0.1

    @property
    def radius_is_terran(self):
        return self.radius.to("earth_radius").magnitude > 0.001

    @property
    def surface_gravity(self):
        return GRAVITATIONAL_CONSTANT * self.mass / self.radius**2

    @property
    def density(self):
        return self.mass / ((4/3) * math.pi * self.radius**3)

    @property
    def escape_velocity(self):
        return (2 * GRAVITATIONAL_CONSTANT * self.mass / self.radius)**0.5

    @property
    def mean_surface_temperature(self):
        a_c = math.pi * self.radius**2
        a_e = 4 * math.pi * self.radius**2
        return ((self.solar_constant * a_c)/(STEFAN_CONSTANT * a_e))**0.25
        # return self.orbited_object.luminosity**0.25 / self.semi_major_axis**2

    @property
    def solar_constant(self):
        return self.orbited_object.luminosity / (4 * math.pi * self.semi_major_axis ** 2)

    @property
    def seasonal_insolation(self):
        return {
            'equator': {
                'vernal_equinox': self.surface_insolation(Q_(0, ureg.degree), Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(Q_(0, ureg.degree), Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(Q_(0, ureg.degree), Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(Q_(0, ureg.degree), Q_(270, ureg.degree))
            },
            'north_tropic': {
                'vernal_equinox': self.surface_insolation(self.tropics, Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(self.tropics, Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(self.tropics, Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(self.tropics, Q_(270, ureg.degree))
            },
            'north_polar_circle': {
                'vernal_equinox': self.surface_insolation(self.polar_circles, Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(self.polar_circles, Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(self.polar_circles, Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(self.polar_circles, Q_(270, ureg.degree))
            },
            'north_pole': {
                'vernal_equinox': self.surface_insolation(Q_(90, ureg.degree), Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(Q_(90, ureg.degree), Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(Q_(90, ureg.degree), Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(Q_(90, ureg.degree), Q_(270, ureg.degree))
            },
            'south_tropic': {
                'vernal_equinox': self.surface_insolation(-self.tropics, Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(-self.tropics, Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(-self.tropics, Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(-self.tropics, Q_(270, ureg.degree))
            },
            'south_polar_circle': {
                'vernal_equinox': self.surface_insolation(-self.polar_circles, Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(-self.polar_circles, Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(-self.polar_circles, Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(-self.polar_circles, Q_(270, ureg.degree))
            },
            'south_pole': {
                'vernal_equinox': self.surface_insolation(Q_(-90, ureg.degree), Q_(0, ureg.degree)),
                'summer_solstice': self.surface_insolation(Q_(-90, ureg.degree), Q_(90, ureg.degree)),
                'autumnal_equinox': self.surface_insolation(Q_(-90, ureg.degree), Q_(180, ureg.degree)),
                'winter_solstice': self.surface_insolation(Q_(-90, ureg.degree), Q_(270, ureg.degree))
            }
        }

    def declination(self, true_anomaly):
        """
        Calculates the declination at a given point in the orbit.

        We assume that the vernal equinox is at 0.
        """
        return self.obliquity * math.sin(true_anomaly)

    def sunrise_hour_angle(self, latitude, true_anomaly):
        """
        Calculate the hour angle at which the sun rises for this body at this latitude
        and orbital_position.

        If the sun never rises here (for example at the poles in winter), then
        returns None.
        """
        cos_h0 = -1 * math.tan(latitude) * math.tan(self.declination(Q_(180, ureg.degree)- true_anomaly))
        if cos_h0 > 1:
            return math.pi * ureg.radian
        elif cos_h0 < -1:
            return None
        else:
            return math.acos(cos_h0) * ureg.radian

    def surface_insolation(self, latitude, true_anomaly):
        """
        Calculate the amount of radiation received at a given point on the
        surface of this planet, assuming no atmosphere.
        """
        distance_ratio = 1 + float(self.eccentricity) * math.cos(true_anomaly - self.longitude_of_periapsis)
        hour_angle_0 = self.sunrise_hour_angle(latitude, true_anomaly)
        if hour_angle_0 is None:
            return Q_(0, ureg.watt / ureg.meter**2)
        else:
            return self.solar_constant/math.pi * distance_ratio**2 * (
                hour_angle_0 * math.sin(latitude) * math.sin(self.declination(true_anomaly)) +
                math.cos(latitude) * math.cos(self.declination(true_anomaly)) * math.sin(hour_angle_0)
            )

    content_panels = [ MultiFieldPanel([
        FieldRowPanel([
            FieldPanel('mass'),
            FieldPanel('radius'),
        ]),

    ], 'Physical properties')] + OrbitalMechanicsMixin.content_panels

    class Meta:
        abstract = True
class HighPotentialOpportunityDetailPage(BaseInvestPage):
    subpage_types = ['invest.HighPotentialOpportunityDetailPage']
    view_path = 'high-potential-opportunities/'

    breadcrumbs_label = models.CharField(max_length=50)
    heading = models.CharField(max_length=255)
    hero_image = models.ForeignKey('wagtailimages.Image',
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    featured = models.BooleanField(default=True)
    description = models.TextField(
        blank=True,
        help_text="This is the description shown when the HPO "
        "is featured on another page i.e. the Invest Home Page")

    contact_proposition = MarkdownField(
        blank=False,
        verbose_name='Body text',
    )
    contact_button = models.CharField(max_length=500)
    proposition_one = MarkdownField(blank=False)
    proposition_one_image = models.ForeignKey('wagtailimages.Image',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    proposition_one_video = models.ForeignKey('wagtailmedia.Media',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    opportunity_list_title = models.CharField(max_length=300)
    opportunity_list_item_one = MarkdownField()
    opportunity_list_item_two = MarkdownField()
    opportunity_list_item_three = MarkdownField(blank=True)
    opportunity_list_image = models.ForeignKey('wagtailimages.Image',
                                               null=True,
                                               blank=True,
                                               on_delete=models.SET_NULL,
                                               related_name='+')
    proposition_two = MarkdownField(blank=False)
    proposition_two_list_item_one = MarkdownField()
    proposition_two_list_item_two = MarkdownField()
    proposition_two_list_item_three = MarkdownField()
    proposition_two_image = models.ForeignKey('wagtailimages.Image',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    proposition_two_video = models.ForeignKey('wagtailmedia.Media',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    competitive_advantages_title = models.CharField(
        max_length=300,
        verbose_name='Body text',
    )
    competitive_advantages_list_item_one = MarkdownField()
    competitive_advantages_list_item_one_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    competitive_advantages_list_item_two = MarkdownField()
    competitive_advantages_list_item_two_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    competitive_advantages_list_item_three = MarkdownField()
    competitive_advantages_list_item_three_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    testimonial = MarkdownField(blank=True)
    testimonial_background = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Background image',
    )
    companies_list_text = MarkdownField()
    companies_list_item_image_one = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_two = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_three = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_four = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_five = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_six = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_seven = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    companies_list_item_image_eight = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')
    case_study_list_title = models.CharField(max_length=300)
    case_study_one_text = MarkdownField(blank=True)
    case_study_one_image = models.ForeignKey('wagtailimages.Image',
                                             null=True,
                                             blank=True,
                                             on_delete=models.SET_NULL,
                                             related_name='+')
    case_study_two_text = MarkdownField(blank=True)
    case_study_two_image = models.ForeignKey('wagtailimages.Image',
                                             null=True,
                                             blank=True,
                                             on_delete=models.SET_NULL,
                                             related_name='+')
    case_study_three_text = MarkdownField(blank=True)
    case_study_three_image = models.ForeignKey('wagtailimages.Image',
                                               null=True,
                                               blank=True,
                                               on_delete=models.SET_NULL,
                                               related_name='+')
    case_study_four_text = MarkdownField(blank=True)
    case_study_four_image = models.ForeignKey('wagtailimages.Image',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    other_opportunities_title = models.CharField(max_length=300,
                                                 verbose_name='Title')
    pdf_document = models.ForeignKey('wagtaildocs.Document',
                                     null=True,
                                     on_delete=models.SET_NULL,
                                     related_name='+')
    summary_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        help_text=(
            'Image used on the opportunity listing page for this opportunity'),
        verbose_name='Image',
    )

    content_panels = [
        MultiFieldPanel(heading='Hero',
                        children=[
                            FieldPanel('breadcrumbs_label'),
                            FieldPanel('heading'),
                            ImageChooserPanel('hero_image'),
                        ]),
        MultiFieldPanel(heading='Featured Description',
                        children=[FieldPanel('description')]),
        MultiFieldPanel(heading='Contact us',
                        children=[
                            FieldRowPanel(children=[
                                FieldPanel('contact_proposition'),
                                FieldPanel('contact_button'),
                            ])
                        ]),
        MultiFieldPanel(heading='Proposition one',
                        children=[
                            FieldRowPanel(children=[
                                FieldPanel('proposition_one'),
                                MultiFieldPanel(children=[
                                    ImageChooserPanel('proposition_one_image'),
                                    FieldPanel('proposition_one_video',
                                               widget=AdminMediaChooser),
                                ])
                            ])
                        ]),
        MultiFieldPanel(heading='Opportunity list',
                        children=[
                            FieldPanel('opportunity_list_title'),
                            FieldRowPanel(children=[
                                MultiFieldPanel(children=[
                                    FieldPanel('opportunity_list_item_one'),
                                    FieldPanel('opportunity_list_item_two'),
                                    FieldPanel('opportunity_list_item_three'),
                                ]),
                                ImageChooserPanel('opportunity_list_image'),
                            ])
                        ]),
        MultiFieldPanel(
            heading='Opportunity list',
            children=[
                FieldRowPanel(children=[
                    MultiFieldPanel(children=[
                        FieldPanel('proposition_two'),
                        FieldPanel('proposition_two_list_item_one'),
                        FieldPanel('proposition_two_list_item_two'),
                        FieldPanel('proposition_two_list_item_three'),
                    ]),
                    MultiFieldPanel(children=[
                        ImageChooserPanel('proposition_two_image'),
                        FieldPanel('proposition_two_video',
                                   widget=AdminMediaChooser),
                    ])
                ])
            ]),
        MultiFieldPanel(
            heading='Key facts',
            children=[
                FieldPanel('competitive_advantages_title'),
                FieldRowPanel(children=[
                    FieldPanel('competitive_advantages_list_item_one'),
                    FieldPanel('competitive_advantages_list_item_two'),
                    FieldPanel('competitive_advantages_list_item_three'),
                ]),
                FieldRowPanel(children=[
                    ImageChooserPanel(
                        'competitive_advantages_list_item_one_icon'),
                    ImageChooserPanel(
                        'competitive_advantages_list_item_two_icon'),
                    ImageChooserPanel(
                        'competitive_advantages_list_item_three_icon'),
                ])
            ]),
        MultiFieldPanel(heading='Testimonial',
                        children=[
                            FieldPanel('testimonial'),
                            ImageChooserPanel('testimonial_background'),
                        ]),
        MultiFieldPanel(
            heading='Company list',
            children=[
                FieldPanel('companies_list_text'),
                FieldRowPanel(children=[
                    ImageChooserPanel('companies_list_item_image_one'),
                    ImageChooserPanel('companies_list_item_image_two'),
                    ImageChooserPanel('companies_list_item_image_three'),
                    ImageChooserPanel('companies_list_item_image_four'),
                ]),
                FieldRowPanel(children=[
                    ImageChooserPanel('companies_list_item_image_five'),
                    ImageChooserPanel('companies_list_item_image_six'),
                    ImageChooserPanel('companies_list_item_image_seven'),
                    ImageChooserPanel('companies_list_item_image_eight'),
                ])
            ]),
        MultiFieldPanel(heading='Case studies',
                        children=[
                            FieldPanel('case_study_list_title'),
                            FieldRowPanel(children=[
                                FieldPanel('case_study_one_text'),
                                ImageChooserPanel('case_study_one_image'),
                            ]),
                            FieldRowPanel(children=[
                                FieldPanel('case_study_two_text'),
                                ImageChooserPanel('case_study_two_image'),
                            ]),
                            FieldRowPanel(children=[
                                FieldPanel('case_study_three_text'),
                                ImageChooserPanel('case_study_three_image'),
                            ]),
                            FieldRowPanel(children=[
                                FieldPanel('case_study_four_text'),
                                ImageChooserPanel('case_study_four_image'),
                            ])
                        ]),
        MultiFieldPanel(heading='Other opportunities',
                        children=[
                            FieldPanel('other_opportunities_title'),
                        ]),
        MultiFieldPanel(
            heading='Summary',
            children=[ImageChooserPanel('summary_image')],
        ),
        SearchEngineOptimisationPanel(),
    ]
    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
        FieldPanel('featured'),
        DocumentChooserPanel('pdf_document'),
    ]

    edit_handler = make_translated_interface(content_panels=content_panels,
                                             settings_panels=settings_panels)
Exemple #7
0
class Position(models.Model):
    """Position represents the execution of a role within UTN"""
    class Meta:
        verbose_name = _('Position')
        verbose_name_plural = _('Positions')
        default_permissions = ()
        ordering = ['role']

    role = models.ForeignKey(
        'Role',
        related_name='positions',
        on_delete=models.PROTECT,
        blank=False,
    )

    recruitment_start = models.DateField(
        verbose_name=_('Start of recruitment'),
        default=date.today,
    )
    recruitment_end = models.DateField(verbose_name=_('Recruitment deadline'))

    # ---- Appointment Information ------
    appointments = models.IntegerField(
        verbose_name=_('Number of appointments'),
        help_text=_('Enter the number of concurrent appointments to the '
                    'position'),
        default=1,
    )

    term_from = models.DateField(verbose_name=_('Date of appointment'))

    term_to = models.DateField(verbose_name=_('End date of appointment'))

    comment_en = models.TextField(
        verbose_name=_('English extra comments'),
        help_text=_('Enter extra comments specific to the position this '
                    'year.'),
        blank=True,
    )

    comment_sv = models.TextField(
        verbose_name=_('Swedish extra comments'),
        help_text=_('Enter extra comments specific to the position this '
                    'year.'),
        blank=True,
    )

    comment = TranslatedField('comment_en', 'comment_sv')

    def __str__(self) -> str:
        if self.term_from.year != self.term_to.year:
            return "%s %s-%s" \
                   % (self.role.name, self.term_from.year, self.term_to.year)
        else:
            return "%s %s" % (self.role.name, self.term_from.year)

    @property
    def appointed_applications(self):
        Application = apps.get_model('involvement', 'Application')
        return Application.objects.filter(
            status='appointed',
            position=self,
        )

    @property
    def is_past_due(self):
        return date.today() > self.recruitment_end

    def current_action(self) -> str:
        if self.is_past_due:
            applications = self.applications.exclude(status='draft')
            if applications.all().filter(status='submitted').exists():
                return 'approve'
            elif applications.all().filter(status='appointed') \
                    .count() >= self.appointments:
                return 'done'
            else:
                return 'appoint'
        else:
            return 'recruit'

    # ------ Administrator settings ------
    panels = [
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('role'),
                FieldPanel('appointments'),
            ]),
            FieldRowPanel([
                FieldPanel('term_from'),
                FieldPanel('term_to'),
            ]),
            FieldRowPanel([
                FieldPanel('recruitment_start'),
                FieldPanel('recruitment_end'),
            ]),
            FieldPanel('comment_en'),
            FieldPanel('comment_sv'),
        ])
    ]
Exemple #8
0
                                related_name='+')

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

    class Meta:
        verbose_name = 'Algemene informatie'


WebsiteSettings.panels = [
    MultiFieldPanel([
        FieldRowPanel([
            FieldPanel('email', classname='col6'),
            FieldPanel('telefoon', classname='col6')
        ]),
        FieldRowPanel([FieldPanel('locatie', classname='col6')]),
        FieldRowPanel([
            FieldPanel('btw_nummer', classname='col6'),
        ]),
        FieldPanel('tagline')
    ],
                    heading='Algemene informatie'),
    MultiFieldPanel([ImageChooserPanel('error_image')],
                    heading='Error pages (404 / 500)',
                    classname='collapsible')
]


class HomePage(AbstractEmailForm):
Exemple #9
0
class RegistrationFormPage(AbstractEmailForm):
    # When creating a new Form page in Wagtail
    registration_head = models.CharField(null=True,
                                         blank=False,
                                         max_length=255)
    registration_newsletter_text = models.CharField(null=True,
                                                    blank=False,
                                                    max_length=255)
    registration_privacy_text = RichTextField(
        null=True,
        blank=False,
        features=[
            'bold', 'italic', 'underline', 'strikethrough', 'h1', 'h2', 'h3',
            'h4', 'h5', 'h6', 'blockquote', 'ol', 'ul', 'hr', 'embed', 'link',
            'superscript', 'subscript', 'document-link', 'image', 'code'
        ])
    registration_info_text = RichTextField(
        null=True,
        blank=False,
        features=[
            'bold', 'italic', 'underline', 'strikethrough', 'h1', 'h2', 'h3',
            'h4', 'h5', 'h6', 'blockquote', 'ol', 'ul', 'hr', 'embed', 'link',
            'superscript', 'subscript', 'document-link', 'image', 'code'
        ])
    registration_button = models.ForeignKey('home.Button',
                                            null=True,
                                            blank=False,
                                            on_delete=models.SET_NULL,
                                            related_name='+')

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

    supported_gitlabs = StreamField([
        ('gitlab_server', Gitlab_Server(null=True, blank=False, icon='home')),
    ],
                                    null=True,
                                    blank=False)

    content_panels = AbstractEmailForm.content_panels + [
        MultiFieldPanel(
            [
                FieldPanel('registration_head', classname="full title"),
                FieldPanel('registration_newsletter_text', classname="full"),
                FieldPanel('registration_privacy_text', classname="full"),
                FieldPanel('registration_info_text', classname="full"),
                FieldPanel('registration_step_text', classname="full"),
                SnippetChooserPanel('registration_button', classname="full"),
                FieldPanel('thank_you_text', classname="full"),
                StreamFieldPanel('supported_gitlabs'),
            ],
            heading="content",
        ),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel("subject"),
        ],
                        heading="Email Settings"),
        MultiFieldPanel(
            [InlinePanel('form_fields', label="Form fields")],
            heading="data",
        )
    ]

    def get_submission_class(self):
        return RegistrationFormSubmission

    # Create a new user
    def create_user(self, username, customer_id, telephone, address, city,
                    postal_code, email, country, newsletter, platform_data,
                    sources, verified, first_name, last_name, password,
                    registration_data, gift_code):
        # enter the data here
        user = get_user_model()(
            username=username,
            is_customer=True,
            is_active=False,
            customer_id=customer_id,
            registration_data=registration_data,
        )

        user.set_password(password)

        parent_page = Page.objects.get(url_path="/home/registration/").specific

        profile_page = ProfilePage(title=f"{user.username}",
                                   slug=f"{user.username}",
                                   username=f"{user.username}",
                                   telephone=telephone,
                                   address=address,
                                   city=city,
                                   postal_code=postal_code,
                                   email=email,
                                   country=country,
                                   newsletter=newsletter,
                                   platform_data=platform_data,
                                   sources=sources,
                                   verified=verified,
                                   available_for_hire=verified,
                                   first_name=first_name,
                                   last_name=last_name,
                                   website=f"https://erebos.xyz",
                                   company=f"f")

        if gift_code:
            gift = GiftCode.objects.get(pk=f'{gift_code}')
            if gift.is_active:
                profile_page = ProfilePage(
                    title=f"{user.username}",
                    slug=f"{user.username}",
                    username=f"{user.username}",
                    telephone=telephone,
                    address=address,
                    city=city,
                    postal_code=postal_code,
                    email=email,
                    country=country,
                    newsletter=newsletter,
                    platform_data=platform_data,
                    sources=sources,
                    verified=True,
                    available_for_hire=verified,
                    first_name=first_name,
                    last_name=last_name,
                    website=f"https://erebos.xyz",
                    company=f"f",
                    bids='{' + '"bids":[' + f'"{gift.bid}"' + ']}',
                    tids='{' + '"tids":[' + f'"{gift.tid}"' + ']}',
                )

                gift.is_active = False

            gift.save()

        else:
            profile_page = ProfilePage(title=f"{user.username}",
                                       slug=f"{user.username}",
                                       username=f"{user.username}",
                                       telephone=telephone,
                                       address=address,
                                       city=city,
                                       postal_code=postal_code,
                                       email=email,
                                       country=country,
                                       newsletter=newsletter,
                                       platform_data=platform_data,
                                       sources=sources,
                                       verified=verified,
                                       available_for_hire=verified,
                                       first_name=first_name,
                                       last_name=last_name,
                                       website=f"https://erebos.xyz",
                                       company=f"f")

        user.save()

        parent_page.add_child(instance=profile_page)
        profile_page.save_revision().publish()

        return user

    # Called when a user registers
    def send_mail(self, form):
        addresses = [x.strip() for x in self.to_address.split(',')]

        emailheader = "New registration via Pharmaziegasse Website"

        content = []
        for field in form:
            value = field.value()
            if isinstance(value, list):
                value = ', '.join(value)
            content.append('{}: {}'.format(field.label, value))
        content = '\n'.join(content)

        content += '\n\nMade with ❤ by a tiny SNEK'

        #emailfooter = '<style>@keyframes pulse { 10% { color: red; } }</style><p>Made with <span style="width: 20px; height: 1em; color:#dd0000; animation: pulse 1s infinite;">&#x2764;</span> by <a style="color: lightgrey" href="https://www.aichner-christian.com" target="_blank">Werbeagentur Christian Aichner</a></p>'

        #html_message = f"{emailheader}\n\n{content}\n\n{emailfooter}"

        send_mail(self.subject, f"{emailheader}\n\n{content}", addresses,
                  self.from_address)

    def process_form_submission(self, form):

        user = self.create_user(
            username=form.cleaned_data['username'],
            customer_id=form.cleaned_data['customer_id'],
            telephone=form.cleaned_data['telephone'],
            address=form.cleaned_data['address'],
            city=form.cleaned_data['city'],
            postal_code=form.cleaned_data['postal_code'],
            email=form.cleaned_data['email'],
            country=form.cleaned_data['country'],
            newsletter=form.cleaned_data['newsletter'],
            platform_data=form.cleaned_data['platform_data'],
            sources=form.cleaned_data['sources'],
            verified=form.cleaned_data['verified'],
            first_name=form.cleaned_data['first_name'],
            last_name=form.cleaned_data['last_name'],
            password=form.cleaned_data['password'],
            gift_code=form.cleaned_data['gift_code'],
            registration_data=json.dumps(form.cleaned_data,
                                         cls=DjangoJSONEncoder),
        )

        self.get_submission_class().objects.create(
            form_data=json.dumps(form.cleaned_data, cls=DjangoJSONEncoder),
            page=self,
            user=user,
        )

        if self.to_address:
            self.send_mail(form)
class Form(CollectionMember, index.Indexed, ClusterableModel):
    form_builder = CustomFormBuilder
    base_form_class = CustomWagtailAdminFormPageForm
    template = 'customform/customform.html'


    title = models.CharField(
        max_length=255
    )

    display_title = models.BooleanField(
        default=False,
        help_text=_("If you wish to display the title above the form fields tick this.")
    )

    to_address = models.CharField(
        verbose_name=_('to address'),
        max_length=255,
        blank=True,
        help_text=_("Optional - form submissions will be emailed to these addresses. Separate multiple addresses by commas.")
    )

    from_address = models.CharField(
        verbose_name=_('from address'),
        max_length=255,
        blank=True
    )

    subject = models.CharField(
        verbose_name=_('subject'),
        max_length=255,
        blank=True
    )

    uploaded_by_user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name=_('uploaded by user'),
        null=True,
        blank=True,
        editable=False,
        on_delete=models.SET_NULL
    )

    form_template = models.CharField(
        choices=FORM_TEMPLATE_CHOICES,
        null=True,
        blank=True,
        max_length=255
    )

    button_alignment = models.CharField(
        choices=(
            ('left', 'Left'),
            ('right', 'Right'),
            ('center', 'Center'),
        ),
        null=True,
        blank=True,
        max_length=255
    )

    created_at = models.DateTimeField(verbose_name=_('created at'), auto_now_add=True)

    panels = [
        FieldPanel('title', classname="full"),
        FieldPanel('display_title'),
        FieldPanel('form_template'),
        FieldPanel('button_alignment'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('from_address', classname="col6"),
                FieldPanel('to_address', classname="col6"),
            ]),
            FieldPanel('subject'),
        ], "Email"),
        InlinePanel('form_fields', label="Form fields"),
    ]

    search_fields = CollectionMember.search_fields + [
        index.SearchField('title', partial_match=True, boost=10),
        index.FilterField('title'),
        index.FilterField('to_address', partial_match=True),
        index.FilterField('from_address', partial_match=True),
        index.FilterField('subject', partial_match=True),
    ]

    admin_form_fields = (
        'title',
        'to_address',
        'from_address',
        'subject',
        'collection',
        # 'form_fields'
    )

    objects = FormQuerySet.as_manager()

    def __str__(self):
        return self.title

    def __init__(self, *args, **kwargs):
        super(Form, self).__init__(*args, **kwargs)
        if not hasattr(self, 'landing_page_template'):
            name, ext = os.path.splitext(self.template)
            self.landing_page_template = name + '_landing' + ext

    def process_form_submission(self, form):
        submission = self.get_submission_class().objects.create(
            form_data=json.dumps(form.cleaned_data, cls=DjangoJSONEncoder),
            form=self,
        )
        if self.to_address:
            self.send_mail(form)
        return submission

    def send_mail(self, form):
        addresses = [x.strip() for x in self.to_address.split(',')]
        content = []
        for field in form:
            if not isinstance(field.field, CaptchaField):
                value = field.value()
                if isinstance(value, list):
                    value = ', '.join(value)
                content.append('{}: {}'.format(field.label, value))
        content = '\n'.join(content)
        send_mail(self.subject, content, addresses, self.from_address,)

    def get_form_fields(self):
        """
        Form page expects `form_fields` to be declared.
        If you want to change backwards relation name,
        you need to override this method.
        """

        return self.form_fields.all()

    def get_data_fields(self):
        """
        Returns a list of tuples with (field_name, field_label).
        """

        data_fields = [
            ('submit_time', _('Submission date')),
        ]
        data_fields += [
            (field.clean_name, field.label)
            for field in self.get_form_fields()
        ]

        return data_fields

    def get_form_class(self):
        fb = self.form_builder(self.get_form_fields())
        return fb.get_form_class()

    def get_form_parameters(self):
        return {}

    def get_form(self, *args, **kwargs):
        form_class = self.get_form_class()
        form_params = self.get_form_parameters()
        form_params.update(kwargs)

        return form_class(*args, **form_params)

    def get_submission_class(self):
        return FormSubmission
Exemple #11
0
class InternationalCampaignPage(BasePage):
    service_name_value = cms.GREAT_INTERNATIONAL
    parent_page_types = [
        'great_international.InternationalArticleListingPage',
        'great_international.InternationalTopicLandingPage',
        'great_international.InternationalLocalisedFolderPage'
    ]
    subpage_types = [
        'great_international.InternationalArticlePage'
    ]
    view_path = 'campaigns/'

    campaign_teaser = models.CharField(max_length=255, null=True, blank=True)
    campaign_heading = models.CharField(max_length=255)
    campaign_hero_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    section_one_heading = models.CharField(max_length=255)
    section_one_intro = MarkdownField()
    section_one_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    selling_point_one_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    selling_point_one_heading = models.CharField(max_length=255)
    selling_point_one_content = MarkdownField()

    selling_point_two_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    selling_point_two_heading = models.CharField(
        max_length=255,
        null=True,
        blank=True,
    )
    selling_point_two_content = MarkdownField(null=True, blank=True)

    selling_point_three_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    selling_point_three_heading = models.CharField(
        max_length=255,
        null=True,
        blank=True
    )
    selling_point_three_content = MarkdownField(null=True, blank=True)

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

    section_two_heading = models.CharField(max_length=255)
    section_two_intro = MarkdownField()

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

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

    related_content_heading = models.CharField(max_length=255)
    related_content_intro = MarkdownField()

    related_page_one = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_two = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_three = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    cta_box_message = models.CharField(max_length=255)
    cta_box_button_url = models.CharField(max_length=255)
    cta_box_button_text = models.CharField(max_length=255)

    tags = ParentalManyToManyField(Tag, blank=True)

    content_panels = [
        MultiFieldPanel(
            heading='Hero section',
            children=[
                FieldPanel('campaign_heading'),
                FieldPanel('campaign_teaser'),
                ImageChooserPanel('campaign_hero_image'),
            ]
        ),
        MultiFieldPanel(
            heading='Section one',
            children=[
                FieldPanel('section_one_heading'),
                FieldPanel('section_one_intro'),
                ImageChooserPanel('section_one_image'),
                FieldRowPanel([
                    MultiFieldPanel(
                        children=[
                            ImageChooserPanel('selling_point_one_icon'),
                            FieldPanel('selling_point_one_heading'),
                            FieldPanel('selling_point_one_content'),
                        ]
                    ),
                    MultiFieldPanel(
                        children=[
                            ImageChooserPanel('selling_point_two_icon'),
                            FieldPanel('selling_point_two_heading'),
                            FieldPanel('selling_point_two_content'),
                        ]
                    ),
                    MultiFieldPanel(
                        children=[
                            ImageChooserPanel('selling_point_three_icon'),
                            FieldPanel('selling_point_three_heading'),
                            FieldPanel('selling_point_three_content'),
                        ]
                    ),
                ]),
                FieldRowPanel([
                    FieldPanel('section_one_contact_button_text'),
                    FieldPanel('section_one_contact_button_url'),
                ])
            ]
        ),
        MultiFieldPanel(
            heading='Section two',
            children=[
                FieldPanel('section_two_heading'),
                FieldPanel('section_two_intro'),
                ImageChooserPanel('section_two_image'),
                FieldRowPanel([
                    FieldPanel('section_two_contact_button_text'),
                    FieldPanel('section_two_contact_button_url'),
                ])
            ]
        ),
        MultiFieldPanel(
            heading='Related content section',
            children=[
                FieldPanel('related_content_heading'),
                FieldPanel('related_content_intro'),
                FieldRowPanel([
                    PageChooserPanel(
                        'related_page_one',
                        'great_international.InternationalArticlePage'),
                    PageChooserPanel(
                        'related_page_two',
                        'great_international.InternationalArticlePage'),
                    PageChooserPanel(
                        'related_page_three',
                        'great_international.InternationalArticlePage'),
                ])
            ]
        ),
        MultiFieldPanel(
            heading='Contact box',
            children=[
                FieldRowPanel([
                    FieldPanel('cta_box_message', widget=Textarea),
                    MultiFieldPanel([
                        FieldPanel('cta_box_button_url'),
                        FieldPanel('cta_box_button_text'),
                    ])
                ])
            ]
        ),
        SearchEngineOptimisationPanel(),
    ]

    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
        FieldPanel('tags', widget=CheckboxSelectMultiple)
    ]
Exemple #12
0
class InternationalArticlePage(BasePage):
    service_name_value = cms.GREAT_INTERNATIONAL
    parent_page_types = [
        'great_international.InternationalArticleListingPage',
        'great_international.InternationalCampaignPage',
        'great_international.InternationalLocalisedFolderPage'
    ]
    subpage_types = []

    article_title = models.CharField(max_length=255)

    article_teaser = models.CharField(max_length=255)
    article_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    article_body_text = MarkdownField()

    related_page_one = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_two = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_three = models.ForeignKey(
        'great_international.InternationalArticlePage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    tags = ParentalManyToManyField(Tag, blank=True)

    content_panels = [
        FieldPanel('article_title'),
        MultiFieldPanel(
            heading='Article content',
            children=[
                FieldPanel('article_teaser'),
                ImageChooserPanel('article_image'),
                FieldPanel('article_body_text')
            ]
        ),
        MultiFieldPanel(
            heading='Related articles',
            children=[
                FieldRowPanel([
                    PageChooserPanel(
                        'related_page_one',
                        'great_international.InternationalArticlePage'),
                    PageChooserPanel(
                        'related_page_two',
                        'great_international.InternationalArticlePage'),
                    PageChooserPanel(
                        'related_page_three',
                        'great_international.InternationalArticlePage'),
                ]),
            ]
        ),
        SearchEngineOptimisationPanel(),
    ]

    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
        FieldPanel('tags', widget=CheckboxSelectMultiple)
    ]
Exemple #13
0
class InternationalHomePage(ExclusivePageMixin, BasePage):
    service_name_value = cms.GREAT_INTERNATIONAL
    slug_identity = cms.GREAT_HOME_INTERNATIONAL_SLUG
    subpage_types = []

    tariffs_title = models.CharField(max_length=255)
    tariffs_description = MarkdownField()
    tariffs_link = models.URLField()
    tariffs_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    news_title = models.CharField(max_length=255)
    related_page_one = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_two = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    related_page_three = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    content_panels = [
        MultiFieldPanel(
            heading='Tariffs',
            children=[
                FieldPanel('tariffs_title'),
                FieldPanel('tariffs_description'),
                FieldPanel('tariffs_link'),
                ImageChooserPanel('tariffs_image')
            ]
        ),
        MultiFieldPanel(
            heading='News section',
            children=[
                FieldPanel('news_title'),
                FieldRowPanel([
                    PageChooserPanel(
                        'related_page_one',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                    PageChooserPanel(
                        'related_page_two',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                    PageChooserPanel(
                        'related_page_three',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                ])
            ]
        ),
        SearchEngineOptimisationPanel(),
    ]

    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
    ]
Exemple #14
0
class InternationalSectorPage(BasePage):
    service_name_value = cms.GREAT_INTERNATIONAL
    parent_page_types = ['great_international.InternationalTopicLandingPage']
    subpage_types = []

    tags = ParentalManyToManyField(Tag, blank=True)

    heading = models.CharField(max_length=255)
    sub_heading = models.CharField(max_length=255)
    hero_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    heading_teaser = models.TextField(blank=True)

    section_one_body = MarkdownField(
        null=True,
        verbose_name='Bullets markdown'
    )
    section_one_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Bullets image'
    )
    section_one_image_caption = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Bullets image caption')
    section_one_image_caption_company = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Bullets image caption — company name')

    statistic_1_number = models.CharField(max_length=255)
    statistic_1_heading = models.CharField(max_length=255)
    statistic_1_smallprint = models.CharField(max_length=255, blank=True)

    statistic_2_number = models.CharField(max_length=255)
    statistic_2_heading = models.CharField(max_length=255)
    statistic_2_smallprint = models.CharField(max_length=255, blank=True)

    statistic_3_number = models.CharField(max_length=255, blank=True)
    statistic_3_heading = models.CharField(max_length=255, blank=True)
    statistic_3_smallprint = models.CharField(max_length=255, blank=True)

    statistic_4_number = models.CharField(max_length=255, blank=True)
    statistic_4_heading = models.CharField(max_length=255, blank=True)
    statistic_4_smallprint = models.CharField(max_length=255, blank=True)

    statistic_5_number = models.CharField(max_length=255, blank=True)
    statistic_5_heading = models.CharField(max_length=255, blank=True)
    statistic_5_smallprint = models.CharField(max_length=255, blank=True)

    statistic_6_number = models.CharField(max_length=255, blank=True)
    statistic_6_heading = models.CharField(max_length=255, blank=True)
    statistic_6_smallprint = models.CharField(max_length=255, blank=True)

    section_two_heading = models.CharField(
        max_length=255,
        verbose_name='Highlights heading'
    )
    section_two_teaser = models.TextField(
        verbose_name='Highlights teaser'
    )

    section_two_subsection_one_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Highlight 1 icon'
    )
    section_two_subsection_one_heading = models.CharField(
        max_length=255,
        verbose_name='Highlight 1 heading'
    )
    section_two_subsection_one_body = models.TextField(
        verbose_name='Highlight 1 body'
    )

    section_two_subsection_two_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Highlight 2 icon'
    )
    section_two_subsection_two_heading = models.CharField(
        max_length=255,
        verbose_name='Highlight 2 heading'
    )
    section_two_subsection_two_body = models.TextField(
        verbose_name='Highlight 2 body'
    )

    section_two_subsection_three_icon = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Highlight 3 icon'
    )
    section_two_subsection_three_heading = models.CharField(
        max_length=255,
        verbose_name='Highlight 3 heading'
    )
    section_two_subsection_three_body = models.TextField(
        verbose_name='Highlight 3 body'
    )

    case_study_title = models.CharField(max_length=255, blank=True)
    case_study_description = models.CharField(max_length=255, blank=True)
    case_study_cta_text = models.TextField(blank=True)
    case_study_cta_page = models.ForeignKey(
        'wagtailcore.Page',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    case_study_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    section_three_heading = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Fact sheets heading'
    )
    section_three_teaser = models.TextField(
        blank=True,
        verbose_name='Fact sheets teaser'
    )

    section_three_subsection_one_heading = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Fact sheet 1 heading'
    )
    section_three_subsection_one_teaser = models.TextField(
        blank=True,
        verbose_name='Fact sheet 1 teaser'
    )
    section_three_subsection_one_body = MarkdownField(
        blank=True,
        null=True,
        verbose_name='Fact sheet 1 body'
    )

    section_three_subsection_two_heading = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Fact sheet 2 heading'
    )
    section_three_subsection_two_teaser = models.TextField(
        blank=True,
        verbose_name='Fact sheet 2 teaser'
    )
    section_three_subsection_two_body = MarkdownField(
        blank=True,
        null=True,
        verbose_name='Fact sheet 2 body'
    )

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

    content_panels = [
        MultiFieldPanel(
            heading='Heading',
            children=[
                FieldPanel('heading'),
                FieldPanel('sub_heading'),
                ImageChooserPanel('hero_image'),
                FieldPanel('heading_teaser')
            ]

        ),
        MultiFieldPanel(
            heading='Bullets',
            children=[
                HelpPanel(
                    'For accessibility reasons, use only "## [Your text here]"'
                    ' for headings in this markdown field'),
                FieldRowPanel(
                    [
                        FieldPanel('section_one_body'),
                        MultiFieldPanel(
                            [
                                ImageChooserPanel('section_one_image'),
                                FieldPanel('section_one_image_caption'),
                                FieldPanel('section_one_image_caption_company')
                            ]
                        )
                    ]
                )
            ]
        ),
        MultiFieldPanel(
            heading='Statistics',
            children=[
                FieldRowPanel(
                    [
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_1_number'),
                                FieldPanel('statistic_1_heading'),
                                FieldPanel('statistic_1_smallprint')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_2_number'),
                                FieldPanel('statistic_2_heading'),
                                FieldPanel('statistic_2_smallprint')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_3_number'),
                                FieldPanel('statistic_3_heading'),
                                FieldPanel('statistic_3_smallprint')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_4_number'),
                                FieldPanel('statistic_4_heading'),
                                FieldPanel('statistic_4_smallprint')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_5_number'),
                                FieldPanel('statistic_5_heading'),
                                FieldPanel('statistic_5_smallprint')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel('statistic_6_number'),
                                FieldPanel('statistic_6_heading'),
                                FieldPanel('statistic_6_smallprint')
                            ]
                        ),
                    ]
                )
            ]
        ),
        MultiFieldPanel(
            heading='Highlights',
            children=[
                FieldPanel('section_two_heading'),
                FieldPanel('section_two_teaser'),
                FieldRowPanel(
                    [
                        MultiFieldPanel(
                            [
                                ImageChooserPanel(
                                    'section_two_subsection_one_icon'),
                                FieldPanel(
                                    'section_two_subsection_one_heading'),
                                FieldPanel(
                                    'section_two_subsection_one_body')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                ImageChooserPanel(
                                    'section_two_subsection_two_icon'),
                                FieldPanel(
                                    'section_two_subsection_two_heading'),
                                FieldPanel(
                                    'section_two_subsection_two_body')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                ImageChooserPanel(
                                    'section_two_subsection_three_icon'),
                                FieldPanel(
                                    'section_two_subsection_three_heading'),
                                FieldPanel(
                                    'section_two_subsection_three_body')
                            ]
                        )
                    ]
                )
            ]
        ),
        MultiFieldPanel(
            heading='Case Study',
            classname='collapsible',
            children=[
                FieldPanel('case_study_title'),
                FieldPanel('case_study_description'),
                FieldPanel('case_study_cta_text'),
                PageChooserPanel(
                    'case_study_cta_page',
                    [
                        'great_international.InternationalArticlePage',
                        'great_international.InternationalCampaignPage',
                    ]),
                ImageChooserPanel('case_study_image')
            ]
        ),
        MultiFieldPanel(
            heading='Fact Sheets',
            classname='collapsible collapsed',
            children=[
                FieldPanel('section_three_heading'),
                FieldPanel('section_three_teaser'),
                FieldRowPanel(
                    [
                        MultiFieldPanel(
                            [
                                FieldPanel(
                                    'section_three_subsection_one_heading'),
                                FieldPanel(
                                    'section_three_subsection_one_teaser'),
                                HelpPanel(
                                    'For accessibility reasons, use only '
                                    '"#### [Your text here]" for subheadings '
                                    'in this markdown field'),
                                FieldPanel(
                                    'section_three_subsection_one_body')
                            ]
                        ),
                        MultiFieldPanel(
                            [
                                FieldPanel(
                                    'section_three_subsection_two_heading'),
                                FieldPanel(
                                    'section_three_subsection_two_teaser'),
                                HelpPanel(
                                    'For accessibility reasons, use only '
                                    '"#### [Your text here]" for subheadings '
                                    'in this markdown field'),
                                FieldPanel(
                                    'section_three_subsection_two_body')
                            ]
                        )
                    ]
                )
            ]
        ),
        MultiFieldPanel(
            heading='Related articles',
            children=[
                FieldRowPanel([
                    PageChooserPanel(
                        'related_page_one',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                    PageChooserPanel(
                        'related_page_two',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                    PageChooserPanel(
                        'related_page_three',
                        [
                            'great_international.InternationalArticlePage',
                            'great_international.InternationalCampaignPage',
                        ]),
                ])
            ]
        ),
        SearchEngineOptimisationPanel()
    ]

    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
        FieldPanel('tags', widget=CheckboxSelectMultiple)
    ]
Exemple #15
0
class Competition(RoutablePageMixin, Page):
    rules = RichTextField()
    voting = RichTextField(blank=True, null=True)
    allowed_points = models.CharField(max_length=128,
                                      default="0,1,2,3,4,5,6,7,8,9,10")
    allow_same_points = models.BooleanField(default=False)

    entries_per_person = models.PositiveIntegerField(default=2)
    entries_in_rating = models.PositiveIntegerField(default=1)

    submission_start = models.DateTimeField(blank=True, null=True)
    submission_end = models.DateTimeField(blank=True, null=True)

    voting_start = models.DateTimeField(blank=True, null=True)
    voting_end = models.DateTimeField(blank=True, null=True)

    content_panels = Page.content_panels + [
        FieldPanel('rules'),
        FieldPanel('votinghelp'),
        FieldRowPanel(
            [FieldPanel('allowed_points'),
             FieldPanel('allow_same_points')]),
        FieldRowPanel([
            FieldPanel('entries_per_person'),
            FieldPanel('entries_in_rating')
        ]),
        FieldRowPanel(
            [FieldPanel('submission_start'),
             FieldPanel('submission_end')]),
        FieldRowPanel([FieldPanel('voting_start'),
                       FieldPanel('voting_end')]),
    ]

    def voting_group_id(self):
        group, _ = Group.objects.get_or_create(
            name="competition-{}-{}".format(self.id, self.slug))
        return group.id

    def user_has_vote_access(self, user):
        if user is None or isinstance(user, AnonymousUser):
            return False
        try:
            x = user.groups.get(id=self.voting_group_id())
            return True
        except:
            return False

    @route(r'^vote/v/(\d+)/comment/$')
    @method_decorator(login_required)
    def make_comment(self, request, entry_id=None):
        if not self.user_has_vote_access(request.user):
            return logout_then_login(request)

        votes = get_object_or_404(Votes, entry_id=entry_id)
        comments = request.POST.get('comments')
        votes.comments = comments
        votes.save()

        print(votes, comments)

        return JsonResponse({'comment': votes.comments})

    @route(r'^vote/v/(\d+)/$')
    @route(r'^vote/v/$')
    @method_decorator(login_required)
    def my_votes_for(self, request, entry_id=None):
        if not self.user_has_vote_access(request.user):
            return logout_then_login(request)

        if entry_id is None:
            votes = Votes.objects.filter(entry__competition=self,
                                         user=request.user)
            res = []
            for x in votes:
                res.append({
                    'id': x.entry.id,
                    'points': x.points,
                    'name': x.entry.title,
                    'comments': x.comments
                })
            return JsonResponse(res, safe=False)
        else:
            entry = get_object_or_404(EntryImage, id=entry_id)

            votes, _ = Votes.objects.get_or_create(entry=entry,
                                                   user=request.user)
            if request.method == 'POST':
                now = timezone.now()
                between, _ = check_dates(entry.competition.voting_start,
                                         entry.competition.voting_end)
                if not between:
                    return HttpResponseForbidden()

                points = request.POST.get('points')

                # See if voted points are allowed
                if int(points) > 0 and not entry.competition.allow_same_points:
                    v = Votes.objects.filter(entry__competition=self,
                                             user=request.user,
                                             points=points)
                    if v.count() > 0:
                        return HttpResponseForbidden()

                votes.points = points
                votes.save()
            return JsonResponse({'id': entry_id, 'points': votes.points})

    @route(r'^vote/$', name='vote')
    @method_decorator(login_required)
    def show_vote_form(self, request):
        if not self.user_has_vote_access(request.user):
            messages.error(request,
                           'You lack permissions for this Competition')

            return logout_then_login(request,
                                     login_url="{}vote".format(self.url))

        context = {}
        between, future = check_dates(self.voting_start, self.voting_end)
        if not between:
            if future:
                messages.error(request,
                               'Voting starts {}'.format(self.voting_start))
            else:
                messages.error(request,
                               'Voting ended {}'.format(self.voting_end))
        else:
            context['entries'] = self.entries.all()
            context['points'] = self.allowed_points.split(",")

        context['page'] = self
        return render(request, 'wagtailphotovoter/vote.html', context)

    @route(r'^choice/$', name='choice')
    @method_decorator(login_required)
    def show_choice_form(self, request):
        if not self.user_has_vote_access(request.user):
            messages.error(request,
                           'You lack permissions for this Competition')

            return logout_then_login(request,
                                     login_url="{}vote".format(self.url))

        context = {}
        context['page'] = self

        between, future = check_dates(self.voting_start, self.voting_end)

        if not between:
            if future:
                messages.error(request,
                               'Voting starts {}'.format(self.voting_start))
            else:
                messages.error(request,
                               'Voting ended {}'.format(self.voting_end))

        elif request.method == 'POST':
            for user_id in request.POST:
                if user_id.startswith("user_"):
                    u_id = user_id.split("_")[1]
                    i_id = request.POST.get(user_id)
                    entry = EntryImage.objects.get(pk=i_id)
                    iv, created = ImageVote.objects.get_or_create(
                        user=request.user, entry=entry)
                    # Find and delete other
                    ImageVote.objects.filter(entry__user=entry.user).exclude(
                        entry=entry).delete()
            return JsonResponse({"OK": "fo"})
        else:
            votes = {}
            for e in ImageVote.objects.filter(user=request.user).all():
                votes[e.entry.user.id] = e.entry.id

            context['users'] = EntryUser.objects.filter(
                entries__competition=self).distinct()
            context['votes'] = votes
            print(votes)

        return render(request, 'wagtailphotovoter/image_choice.html', context)

    @route(r'^result/$')
    @method_decorator(login_required)
    def show_result(self, request):
        if not self.user_has_vote_access(request.user):
            return logout_then_login(request,
                                     login_url="{}result".format(self.url))

        context = {}
        q = self.entries.annotate(total_points=Sum('votes__points')).order_by(
            F('total_points').desc(nulls_last=True)).all()
        context['entries'] = q
        #print(context['entries'])
        context['page'] = self
        return render(request, 'wagtailphotovoter/result.html', context)

    @route(r'^result/csv/$')
    @method_decorator(login_required)
    def some_view(self, request):
        if not self.user_has_vote_access(request.user):
            return logout_then_login(request,
                                     login_url="{}result/csv".format(self.url))

        response = HttpResponse(content_type='text/csv')
        response[
            'Content-Disposition'] = 'attachment; filename="{}-{}.csv"'.format(
                self.id, self.slug)
        writer = csv.writer(response)
        writer.writerow([
            'link', 'points', 'title', 'author', 'email', 'location', 'gear',
            'comments'
        ])
        q = self.entries.annotate(total_points=Sum('votes__points')).order_by(
            F('total_points').desc(nulls_last=True)).all()
        for e in q:
            comments = ""
            for v in e.votes.all():
                if v.comments is not None:
                    comments += "{}: {}\n".format(v.user, v.comments)
            writer.writerow([
                "{}{}".format(settings.BASE_URL, e.link), e.points, e.title,
                e.user.name, e.user.email, e.location, e.gear, comments
            ])

        return response

    @route(r'^$')
    def show_add_form(self, request):
        context = {'page': self}

        between, future = check_dates(self.submission_start,
                                      self.submission_end)

        if not between:
            if future:
                messages.error(
                    request,
                    'Submissions opens {}'.format(self.submission_start))
            else:
                messages.error(
                    request,
                    'Sumbissions closed {}'.format(self.submission_end))
            return render(request, 'wagtailphotovoter/add.html', context)

        imageFormSet = formset_factory(ImageForm,
                                       extra=self.entries_per_person,
                                       max_num=self.entries_per_person,
                                       min_num=1)

        if request.method == 'POST':
            iform = imageFormSet(request.POST, request.FILES)
            aform = AuthorForm(request.POST, request.FILES)
            if iform.is_valid() and aform.is_valid():
                name = aform.cleaned_data.get('name')
                email = aform.cleaned_data.get('email')
                user, created = EntryUser.objects.get_or_create(email=email)
                user.name = name
                user.save()
                # get collection
                c = Collection.objects.filter(name=self.title).first()

                for i in iform:
                    gear = i.cleaned_data.get('gear')
                    title = i.cleaned_data.get('title')
                    location = i.cleaned_data.get('location')
                    # Skip if not
                    if gear is None and title is None and location is None:
                        continue
                    img = EntryImage.objects.create(
                        file=i.cleaned_data.get('photo'),
                        title=title,
                        competition=self,
                        gear=gear,
                        location=location,
                        user=user,
                        collection=c,
                    )
                    messages.success(
                        request,
                        "Your entry '{}' has been submitted".format(title))
                # Both forms valid, so redirect to avoid multiple submissions of same
                return HttpResponseRedirect(self.get_url())

        else:
            iform = imageFormSet()
            aform = AuthorForm()

        context['author'] = aform
        context['images'] = iform
        return render(request, 'wagtailphotovoter/add.html', context)
Exemple #16
0
class Logo(models.Model):
    class Meta:
        verbose_name = _('logo')
        verbose_name_plural = _('logos')

    CATEGORY_CHOICES = (
        ('committee', _('Committee')),
        ('section', _('Section')),
    )

    category = models.CharField(
        max_length=20,
        choices=CATEGORY_CHOICES,
        verbose_name=_('category'),
        blank=False,
        null=False,
    )

    link = models.URLField(
        verbose_name=_('links to'),
        null=False,
        blank=False,
    )

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

    logo_white = models.ForeignKey('wagtailimages.Image',
                                   verbose_name=_('white logo'),
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    logo_black = models.ForeignKey('wagtailimages.Image',
                                   verbose_name=_('black logo'),
                                   null=True,
                                   blank=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    belongs_to = models.ForeignKey(
        'wagtailcore.Site',
        verbose_name=_('belongs to'),
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )

    # ------ Administrator settings ------
    panels = [
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('category'),
                FieldPanel('link'),
            ]),
            ImageChooserPanel('logo'),
            ImageChooserPanel('logo_white'),
            ImageChooserPanel('logo_black'),
            FieldPanel('belongs_to'),
        ])
    ]
Exemple #17
0
class EventPage(AbstractFilterPage):
    # General content fields
    body = RichTextField('Subheading', blank=True)
    archive_body = RichTextField(blank=True)
    live_body = RichTextField(blank=True)
    future_body = RichTextField(blank=True)
    persistent_body = StreamField([
        ('content', blocks.RichTextBlock(icon='edit')),
        ('content_with_anchor', molecules.ContentWithAnchor()),
        ('heading', v1_blocks.HeadingBlock(required=False)),
        ('image', molecules.ContentImage()),
        ('table_block', organisms.AtomicTableBlock(
            table_options={'renderer': 'html'}
        )),
        ('reusable_text', v1_blocks.ReusableTextChooserBlock(
            'v1.ReusableText'
        )),
    ], blank=True)
    start_dt = models.DateTimeField("Start")
    end_dt = models.DateTimeField("End", blank=True, null=True)
    future_body = RichTextField(blank=True)
    archive_image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    video_transcript = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    speech_transcript = models.ForeignKey(
        'wagtaildocs.Document',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    flickr_url = models.URLField("Flickr URL", blank=True)
    archive_video_id = models.CharField(
        'YouTube video ID (archive)',
        null=True,
        blank=True,
        max_length=11,
        # This is a reasonable but not official regex for YouTube video IDs.
        # https://webapps.stackexchange.com/a/54448
        validators=[RegexValidator(regex=r'^[\w-]{11}$')],
        help_text=organisms.VideoPlayer.YOUTUBE_ID_HELP_TEXT
    )
    live_stream_availability = models.BooleanField(
        "Streaming?",
        default=False,
        blank=True,
        help_text='Check if this event will be streamed live. This causes the '
                  'event page to show the parts necessary for live streaming.'
    )
    live_video_id = models.CharField(
        'YouTube video ID (live)',
        null=True,
        blank=True,
        max_length=11,
        # This is a reasonable but not official regex for YouTube video IDs.
        # https://webapps.stackexchange.com/a/54448
        validators=[RegexValidator(regex=r'^[\w-]{11}$')],
        help_text=organisms.VideoPlayer.YOUTUBE_ID_HELP_TEXT
    )
    live_stream_date = models.DateTimeField(
        "Go Live Date",
        blank=True,
        null=True,
        help_text='Enter the date and time that the page should switch from '
                  'showing the venue image to showing the live video feed. '
                  'This is typically 15 minutes prior to the event start time.'
    )

    # Venue content fields
    venue_coords = models.CharField(max_length=100, blank=True)
    venue_name = models.CharField(max_length=100, blank=True)
    venue_street = models.CharField(max_length=100, blank=True)
    venue_suite = models.CharField(max_length=100, blank=True)
    venue_city = models.CharField(max_length=100, blank=True)
    venue_state = USStateField(blank=True)
    venue_zipcode = models.CharField(max_length=12, blank=True)
    venue_image_type = models.CharField(
        max_length=8,
        choices=(
            ('map', 'Map'),
            ('image', 'Image (selected below)'),
            ('none', 'No map or image'),
        ),
        default='map',
        help_text='If "Image" is chosen here, you must select the image you '
                  'want below. It should be sized to 1416x796.',
    )
    venue_image = models.ForeignKey(
        'v1.CFGOVImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )
    post_event_image_type = models.CharField(
        max_length=16,
        choices=(
            ('placeholder', 'Placeholder image'),
            ('image', 'Unique image (selected below)'),
        ),
        default='placeholder',
        verbose_name='Post-event image type',
        help_text='Choose what to display after an event concludes. This will '
                  'be overridden by embedded video if the "YouTube video ID '
                  '(archive)" field on the previous tab is populated. If '
                  '"Unique image" is chosen here, you must select the image '
                  'you want below. It should be sized to 1416x796.',
    )
    post_event_image = models.ForeignKey(
        'v1.CFGOVImage',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    # Agenda content fields
    agenda_items = StreamField([('item', AgendaItemBlock())], blank=True)

    objects = CFGOVPageManager()

    search_fields = AbstractFilterPage.search_fields + [
        index.SearchField('body'),
        index.SearchField('archive_body'),
        index.SearchField('live_video_id'),
        index.SearchField('flickr_url'),
        index.SearchField('archive_video_id'),
        index.SearchField('future_body'),
        index.SearchField('agenda_items')
    ]

    # General content tab
    content_panels = CFGOVPage.content_panels + [
        FieldPanel('body'),
        FieldRowPanel([
            FieldPanel('start_dt', classname="col6"),
            FieldPanel('end_dt', classname="col6"),
        ]),
        MultiFieldPanel([
            FieldPanel('archive_body'),
            ImageChooserPanel('archive_image'),
            DocumentChooserPanel('video_transcript'),
            DocumentChooserPanel('speech_transcript'),
            FieldPanel('flickr_url'),
            FieldPanel('archive_video_id'),
        ], heading='Archive Information'),
        FieldPanel('live_body'),
        FieldPanel('future_body'),
        StreamFieldPanel('persistent_body'),
        MultiFieldPanel([
            FieldPanel('live_stream_availability'),
            FieldPanel('live_video_id'),
            FieldPanel('live_stream_date'),
        ], heading='Live Stream Information'),
    ]
    # Venue content tab
    venue_panels = [
        FieldPanel('venue_name'),
        MultiFieldPanel([
            FieldPanel('venue_street'),
            FieldPanel('venue_suite'),
            FieldPanel('venue_city'),
            FieldPanel('venue_state'),
            FieldPanel('venue_zipcode'),
        ], heading='Venue Address'),
        MultiFieldPanel([
            FieldPanel('venue_image_type'),
            ImageChooserPanel('venue_image'),
        ], heading='Venue Image'),
        MultiFieldPanel([
            FieldPanel('post_event_image_type'),
            ImageChooserPanel('post_event_image'),
        ], heading='Post-event Image')
    ]
    # Agenda content tab
    agenda_panels = [
        StreamFieldPanel('agenda_items'),
    ]
    # Promotion panels
    promote_panels = [
        MultiFieldPanel(AbstractFilterPage.promote_panels,
                        "Page configuration"),
    ]
    # Tab handler interface
    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='General Content'),
        ObjectList(venue_panels, heading='Venue Information'),
        ObjectList(agenda_panels, heading='Agenda Information'),
        ObjectList(AbstractFilterPage.sidefoot_panels,
                   heading='Sidebar'),
        ObjectList(AbstractFilterPage.settings_panels,
                   heading='Configuration'),
    ])

    template = 'events/event.html'

    @property
    def event_state(self):
        if self.end_dt:
            end = convert_date(self.end_dt, 'America/New_York')
            if end < datetime.now(timezone('America/New_York')):
                return 'past'

        if self.live_stream_date:
            start = convert_date(
                self.live_stream_date,
                'America/New_York'
            )
        else:
            start = convert_date(self.start_dt, 'America/New_York')

        if datetime.now(timezone('America/New_York')) > start:
            return 'present'

        return 'future'

    @property
    def page_js(self):
        if (
            (self.live_stream_date and self.event_state == 'present')
            or (self.archive_video_id and self.event_state == 'past')
        ):
            return super(EventPage, self).page_js + ['video-player.js']

        return super(EventPage, self).page_js

    def location_image_url(self, scale='2', size='276x155', zoom='12'):
        if not self.venue_coords:
            self.venue_coords = get_venue_coords(
                self.venue_city, self.venue_state
            )
        api_url = 'https://api.mapbox.com/styles/v1/mapbox/streets-v11/static'
        static_map_image_url = '{}/{},{}/{}?access_token={}'.format(
            api_url,
            self.venue_coords,
            zoom,
            size,
            settings.MAPBOX_ACCESS_TOKEN
        )

        return static_map_image_url

    def clean(self):
        super(EventPage, self).clean()
        if self.venue_image_type == 'image' and not self.venue_image:
            raise ValidationError({
                'venue_image': 'Required if "Venue image type" is "Image".'
            })
        if self.post_event_image_type == 'image' and not self.post_event_image:
            raise ValidationError({
                'post_event_image': 'Required if "Post-event image type" is '
                                    '"Image".'
            })

    def save(self, *args, **kwargs):
        self.venue_coords = get_venue_coords(self.venue_city, self.venue_state)
        return super(EventPage, self).save(*args, **kwargs)

    def get_context(self, request):
        context = super(EventPage, self).get_context(request)
        context['event_state'] = self.event_state
        return context
    FieldPanel('title', classname='full title'),
    FieldPanel('description'),
    ImageChooserPanel('image'),
    StreamFieldPanel('content'),
    MultiFieldPanel(
        [
            FieldPanel('start_date'),
            FieldPanel('end_date'),
        ],
        heading="Your Words Competition Settings",
    )
]

YourWordsCompetition.settings_panels = [
    MultiFieldPanel([
        FieldRowPanel([FieldPanel('extra_style_hints')],
                      classname="label-above")
    ], "Meta")
]


class YourWordsCompetitionEntry(models.Model):
    competition = models.ForeignKey(YourWordsCompetition)
    submission_date = models.DateField(null=True,
                                       blank=True,
                                       auto_now_add=True)
    user = models.ForeignKey('auth.User')
    story_name = models.CharField(max_length=128)
    story_text = models.TextField()
    terms_or_conditions_approved = models.BooleanField()
    hide_real_name = models.BooleanField()
    is_read = models.BooleanField(default=False)
Exemple #19
0
class LeagueBadgeRoundEntry(models.Model):
    page = ParentalKey('BadgesPage',
                       related_name='rounds',
                       on_delete=models.CASCADE)
    round_name = models.CharField(max_length=50)

    # Recurve
    rc_white_score = models.IntegerField("RC White")
    rc_black_score = models.IntegerField("RC Black")
    rc_blue_score = models.IntegerField("RC Blue")
    rc_red_score = models.IntegerField("RC Red")
    rc_gold_score = models.IntegerField("RC Gold")
    # Barebow
    bb_white_score = models.IntegerField("BB White")
    bb_black_score = models.IntegerField("BB Black")
    bb_blue_score = models.IntegerField("BB Blue")
    bb_red_score = models.IntegerField("BB Red")
    bb_gold_score = models.IntegerField("BB Gold")
    # Compound
    cb_white_score = models.IntegerField("CP White")
    cb_black_score = models.IntegerField("CP Black")
    cb_blue_score = models.IntegerField("CP Blue")
    cb_red_score = models.IntegerField("CP Red")
    cb_gold_score = models.IntegerField("CP Gold")
    # Longbow
    lb_white_score = models.IntegerField("LB White")
    lb_black_score = models.IntegerField("LB Black")
    lb_blue_score = models.IntegerField("LB Blue")
    lb_red_score = models.IntegerField("LB Red")
    lb_gold_score = models.IntegerField("LB Gold")

    @property
    def recurve_scores(self):
        return self.rc_white_score, self.rc_black_score, self.rc_blue_score, self.rc_red_score, self.rc_gold_score

    @property
    def barebow_scores(self):
        return self.bb_white_score, self.bb_black_score, self.bb_blue_score, self.bb_red_score, self.bb_gold_score

    @property
    def compound_scores(self):
        return self.cb_white_score, self.cb_black_score, self.cb_blue_score, self.cb_red_score, self.cb_gold_score

    @property
    def longbow_scores(self):
        return self.lb_white_score, self.lb_black_score, self.lb_blue_score, self.lb_red_score, self.lb_gold_score

    @property
    def table_order(self):
        return ("Recurve", self.recurve_scores), ("Barebow", self.barebow_scores), ("Compound", self.compound_scores), \
               ("Longbow", self.longbow_scores)

    panels = [
        FieldPanel('round_name', classname='title'),
        FieldRowPanel([
            FieldPanel('rc_white_score', classname='col4'),
            FieldPanel('rc_black_score', classname='col4'),
            FieldPanel('rc_blue_score', classname='col4'),
            FieldPanel('rc_red_score', classname='col4'),
            FieldPanel('rc_gold_score', classname='col4')
        ]),
        FieldRowPanel([
            FieldPanel('bb_white_score', classname='col4'),
            FieldPanel('bb_black_score', classname='col4'),
            FieldPanel('bb_blue_score', classname='col4'),
            FieldPanel('bb_red_score', classname='col4'),
            FieldPanel('bb_gold_score', classname='col4')
        ]),
        FieldRowPanel([
            FieldPanel('cb_white_score', classname='col4'),
            FieldPanel('cb_black_score', classname='col4'),
            FieldPanel('cb_blue_score', classname='col4'),
            FieldPanel('cb_red_score', classname='col4'),
            FieldPanel('cb_gold_score', classname='col4')
        ]),
        FieldRowPanel([
            FieldPanel('lb_white_score', classname='col4'),
            FieldPanel('lb_black_score', classname='col4'),
            FieldPanel('lb_blue_score', classname='col4'),
            FieldPanel('lb_red_score', classname='col4'),
            FieldPanel('lb_gold_score', classname='col4')
        ]),
    ]
Exemple #20
0
class RoundBase(WorkflowStreamForm, SubmittableStreamForm):  # type: ignore
    is_creatable = False
    submission_class = ApplicationSubmission

    objects = PageManager.from_queryset(RoundBaseManager)()

    subpage_types = []  # type: ignore

    lead = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        limit_choices_to=LIMIT_TO_STAFF,
        related_name='%(class)s_lead',
        on_delete=models.PROTECT,
    )
    reviewers = ParentalManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='%(class)s_reviewer',
        limit_choices_to=LIMIT_TO_REVIEWERS,
        blank=True,
    )
    start_date = models.DateField(default=date.today)
    end_date = models.DateField(
        blank=True,
        null=True,
        default=date.today,
        help_text=
        'When no end date is provided the round will remain open indefinitely.'
    )
    sealed = models.BooleanField(default=False)

    content_panels = SubmittableStreamForm.content_panels + [
        FieldPanel('lead'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('start_date'),
                FieldPanel('end_date'),
            ]),
        ],
                        heading="Dates"),
        FieldPanel('reviewers'),
        ReadOnlyPanel('get_workflow_name_display', heading="Workflow"),
        # Forms comes from parental key in models/forms.py
        ReadOnlyInlinePanel('forms', help_text="Copied from the fund."),
        ReadOnlyInlinePanel('review_forms', help_text="Copied from the fund."),
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading='Content'),
        ObjectList(SubmittableStreamForm.promote_panels, heading='Promote'),
    ])

    def get_template(self, request, *args, **kwargs):
        # Make sure all children use the shared template
        return 'funds/round.html'

    def get_landing_page_template(self, request, *args, **kwargs):
        # Make sure all children use the shared template
        return 'funds/round_landing.html'

    @property
    def is_sealed(self):
        return self.sealed and self.is_open

    @property
    def is_open(self):
        return self.start_date <= date.today() <= self.end_date

    def save(self, *args, **kwargs):
        is_new = not self.id
        if is_new and hasattr(self, 'parent_page'):
            parent_page = self.parent_page[self.__class__][self.title]
            self.workflow_name = parent_page.workflow_name
            self.reviewers = parent_page.reviewers.all()

        super().save(*args, **kwargs)

        if is_new and hasattr(self, 'parent_page'):
            # Would be nice to do this using model clusters as part of the __init__
            self._copy_forms('forms')
            self._copy_forms('review_forms')

    def _copy_forms(self, field):
        for form in getattr(self.get_parent().specific, field).all():
            new_form = self._meta.get_field(field).related_model
            self._copy_form(form, new_form)

    def _copy_form(self, form, new_class):
        # Create a copy of the existing form object
        new_form = form.form
        new_form.id = None
        new_form.name = '{} for {} ({})'.format(new_form.name, self.title,
                                                self.get_parent().title)
        new_form.save()
        new_class.objects.create(round=self, form=new_form)

    def get_submit_meta_data(self, **kwargs):
        return super().get_submit_meta_data(
            page=self.get_parent(),
            round=self,
            **kwargs,
        )

    def clean(self):
        super().clean()

        if self.end_date and self.start_date > self.end_date:
            raise ValidationError({
                'end_date':
                'End date must come after the start date',
            })

        if self.end_date:
            conflict_query = (
                Q(start_date__range=[self.start_date, self.end_date])
                | Q(end_date__range=[self.start_date, self.end_date])
                | Q(start_date__lte=self.start_date,
                    end_date__gte=self.end_date))
        else:
            conflict_query = (Q(start_date__lte=self.start_date,
                                end_date__isnull=True)
                              | Q(end_date__gte=self.start_date))

        if not self.id and hasattr(self, 'parent_page'):
            # Check if the create hook has added the parent page, we aren't an object yet.
            # Ensures we can access related objects during the clean phase instead of save.
            base_query = RoundBase.objects.child_of(
                self.parent_page[self.__class__][self.title])
        else:
            # don't need parent page, we are an actual object now.
            base_query = RoundBase.objects.sibling_of(self)

        conflicting_rounds = base_query.filter(conflict_query).exclude(
            id=self.id)

        if conflicting_rounds.exists():
            error_message = mark_safe(
                'Overlaps with the following rounds:<br> {}'.
                format('<br>'.join([
                    f'<a href="{admin_url(round)}">{round.title}</a>: {round.start_date} - {round.end_date}'
                    for round in conflicting_rounds
                ])))
            error = {
                'start_date': error_message,
            }
            if self.end_date:
                error['end_date'] = error_message

            raise ValidationError(error)

    def serve(self, request):
        if hasattr(request, 'is_preview') or hasattr(request, 'show_round'):
            return super().serve(request)

        # We hide the round as only the open round is used which is displayed through the
        # fund page
        raise Http404()
Exemple #21
0
class ThreeLegStandingsEntry(models.Model):
    page = ParentalKey('ThreeLegStandingsPage',
                       related_name='results',
                       on_delete=models.CASCADE)

    team_name = models.CharField(max_length=50)
    team_is_novice = models.BooleanField(default=False)

    leg_1_score = models.IntegerField(blank=True, default=0)
    leg_1_hits = models.IntegerField(blank=True, default=0)
    leg_1_golds = models.IntegerField(blank=True, default=0)

    leg_2_score = models.IntegerField(blank=True, default=0)
    leg_2_hits = models.IntegerField(blank=True, default=0)
    leg_2_golds = models.IntegerField(blank=True, default=0)

    leg_3_score = models.IntegerField(blank=True, default=0)
    leg_3_hits = models.IntegerField(blank=True, default=0)
    leg_3_golds = models.IntegerField(blank=True, default=0)

    champs_score = models.IntegerField(blank=True, default=0)
    champs_hits = models.IntegerField(blank=True, default=0)
    champs_golds = models.IntegerField(blank=True, default=0)

    @property
    def leg_1(self):
        return self.leg_1_score, self.leg_1_hits, self.leg_1_golds

    @property
    def leg_2(self):
        return self.leg_2_score, self.leg_2_hits, self.leg_2_golds

    @property
    def leg_3(self):
        return self.leg_3_score, self.leg_3_hits, self.leg_3_golds

    @property
    def champs(self):
        return self.champs_score, self.champs_hits, self.champs_golds

    @property
    def results(self):
        return [self.leg_1, self.leg_2, self.leg_3, self.champs]

    @property
    def is_empty(self):
        return not bool(list(filter(lambda x: x != (0, 0, 0), self.results)))

    @property
    def aggregate(self):
        return functools.reduce(
            lambda acc, new:
            (acc[0] + new[0], acc[1] + new[1], acc[2] + new[2]), self.results)

    panels = [
        FieldPanel('team_name', classname='title'),
        FieldPanel('team_is_novice'),
        FieldRowPanel([
            FieldPanel('leg_1_score'),
            FieldPanel('leg_1_hits'),
            FieldPanel('leg_1_golds'),
        ]),
        FieldRowPanel([
            FieldPanel('leg_2_score'),
            FieldPanel('leg_2_hits'),
            FieldPanel('leg_2_golds'),
        ]),
        FieldRowPanel([
            FieldPanel('leg_3_score'),
            FieldPanel('leg_3_hits'),
            FieldPanel('leg_3_golds'),
        ]),
        FieldRowPanel([
            FieldPanel('champs_score'),
            FieldPanel('champs_hits'),
            FieldPanel('champs_golds'),
        ]),
    ]
class InvestHomePage(ExclusivePageMixin, ServiceHomepageMixin, BaseInvestPage):
    slug_identity = slugs.INVEST_HOME_PAGE
    view_path = ''

    breadcrumbs_label = models.CharField(max_length=50)
    heading = models.CharField(max_length=255)
    sub_heading = models.CharField(max_length=255)
    hero_call_to_action_text = models.CharField(max_length=255, blank=True)
    hero_call_to_action_url = models.CharField(max_length=255, blank=True)
    hero_image = models.ForeignKey('wagtailimages.Image',
                                   blank=True,
                                   null=True,
                                   on_delete=models.SET_NULL,
                                   related_name='+')

    benefits_section_title = models.CharField(max_length=255, blank=True)
    benefits_section_intro = models.TextField(max_length=255, blank=True)
    benefits_section_content = MarkdownField(blank=True)
    benefits_section_img = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name="Benefits section image")

    eu_exit_section_title = models.CharField(
        max_length=255, blank=True, verbose_name="EU exit section title")

    eu_exit_section_content = MarkdownField(
        blank=True, verbose_name="EU exit section content")

    eu_exit_section_call_to_action_text = models.CharField(
        max_length=255, blank=True, verbose_name="EU exit section button text")

    eu_exit_section_call_to_action_url = models.CharField(
        max_length=255, blank=True, verbose_name="EU exit section button url")

    eu_exit_section_img = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name="EU exit section image")

    sector_title = models.TextField(default="Discover UK Industries",
                                    max_length=255,
                                    blank=True)

    sector_button_text = models.TextField(default="See more industries",
                                          max_length=255,
                                          blank=True)

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

    sector_intro = models.TextField(max_length=255, blank=True)

    hpo_title = models.CharField(
        max_length=255,
        verbose_name="High potential opportunity section title",
        blank=True)
    hpo_intro = models.TextField(
        max_length=255,
        blank=True,
        verbose_name="High potential opportunity section intro")

    capital_invest_section_title = models.CharField(max_length=255, blank=True)
    capital_invest_section_content = MarkdownField(blank=True)
    capital_invest_section_image = models.ForeignKey('wagtailimages.Image',
                                                     blank=True,
                                                     null=True,
                                                     on_delete=models.SET_NULL,
                                                     related_name='+')

    setup_guide_title = models.CharField(
        default='Set up an overseas business in the UK',
        max_length=255,
        blank=True)

    setup_guide_lead_in = models.TextField(blank=True, null=True)

    setup_guide_content = MarkdownField(blank=True)
    setup_guide_img = models.ForeignKey('wagtailimages.Image',
                                        blank=True,
                                        null=True,
                                        on_delete=models.SET_NULL,
                                        related_name='+',
                                        verbose_name="Setup guide image")
    setup_guide_call_to_action_url = models.CharField(max_length=255,
                                                      blank=True)

    isd_section_image = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name='Investment Support Directory section image')
    isd_section_title = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Investment Support Directory section title')
    isd_section_text = MarkdownField(
        max_length=255,
        blank=True,
        verbose_name='Investment Support Directory section text')

    featured_card_one_image = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    featured_card_one_title = models.CharField(blank=True, max_length=255)
    featured_card_one_summary = MarkdownField(blank=True)
    featured_card_one_cta_link = models.CharField(max_length=255, blank=True)

    featured_card_two_image = models.ForeignKey(
        'wagtailimages.Image',
        blank=True,
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )
    featured_card_two_title = models.CharField(
        max_length=255,
        blank=True,
    )
    featured_card_two_summary = MarkdownField(
        max_length=255,
        blank=True,
    )
    featured_card_two_cta_link = models.CharField(max_length=255, blank=True)

    featured_card_three_image = models.ForeignKey('wagtailimages.Image',
                                                  blank=True,
                                                  null=True,
                                                  on_delete=models.SET_NULL,
                                                  related_name='+')
    featured_card_three_title = models.CharField(max_length=255, blank=True)
    featured_card_three_summary = MarkdownField(blank=True)
    featured_card_three_cta_link = models.CharField(max_length=255, blank=True)

    how_we_help_title = models.CharField(default='How we help',
                                         max_length=255,
                                         blank=True)
    how_we_help_lead_in = models.TextField(blank=True, null=True)
    # how we help
    how_we_help_text_one = models.CharField(max_length=255, blank=True)
    how_we_help_icon_one = models.ForeignKey('wagtailimages.Image',
                                             null=True,
                                             blank=True,
                                             on_delete=models.SET_NULL,
                                             related_name='+')
    how_we_help_text_two = models.CharField(max_length=255, blank=True)
    how_we_help_icon_two = models.ForeignKey('wagtailimages.Image',
                                             null=True,
                                             blank=True,
                                             on_delete=models.SET_NULL,
                                             related_name='+')
    how_we_help_text_three = models.CharField(max_length=255, blank=True)
    how_we_help_icon_three = models.ForeignKey('wagtailimages.Image',
                                               null=True,
                                               blank=True,
                                               on_delete=models.SET_NULL,
                                               related_name='+')
    how_we_help_text_four = models.CharField(max_length=255, blank=True)
    how_we_help_icon_four = models.ForeignKey('wagtailimages.Image',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    how_we_help_text_five = models.CharField(max_length=255, blank=True)
    how_we_help_icon_five = models.ForeignKey('wagtailimages.Image',
                                              null=True,
                                              blank=True,
                                              on_delete=models.SET_NULL,
                                              related_name='+')
    how_we_help_text_six = models.CharField(max_length=255, blank=True)

    contact_section_title = models.CharField(max_length=255, blank=True)
    contact_section_content = models.TextField(max_length=255, blank=True)
    contact_section_call_to_action_text = models.CharField(max_length=255,
                                                           blank=True)
    contact_section_call_to_action_url = models.CharField(max_length=255,
                                                          blank=True)

    image_panels = [
        ImageChooserPanel('hero_image'),
    ]

    content_panels = [
        MultiFieldPanel(
            heading='Hero',
            classname='collapsible',
            children=[
                FieldPanel('breadcrumbs_label'),
                FieldPanel('heading'),
                FieldPanel('sub_heading'),
                FieldPanel('hero_call_to_action_text'),
                FieldPanel('hero_call_to_action_url'),
            ],
        ),
        MultiFieldPanel(
            heading='Benefits section',
            classname='collapsible',
            children=[
                HelpPanel('Required fields for section to show: '
                          'Benefits Section Title, Benefits Section Content'),
                FieldPanel('benefits_section_title'),
                FieldPanel('benefits_section_intro'),
                FieldPanel('benefits_section_content'),
                ImageChooserPanel('benefits_section_img'),
            ],
        ),
        MultiFieldPanel(
            heading='EU Exit section',
            classname='collapsible collapsed',
            children=[
                FieldPanel('eu_exit_section_title'),
                FieldPanel('eu_exit_section_content'),
                FieldPanel('eu_exit_section_call_to_action_text'),
                FieldPanel('eu_exit_section_call_to_action_url'),
                ImageChooserPanel('eu_exit_section_img'),
            ],
        ),
        MultiFieldPanel(
            heading='Old featured card links',
            classname='collapsible collapsed',
            children=[
                FieldRowPanel([
                    MultiFieldPanel([
                        ImageChooserPanel('setup_guide_img'),
                        FieldPanel('setup_guide_title'),
                        FieldPanel('setup_guide_content'),
                        FieldPanel('setup_guide_call_to_action_url'),
                    ], ),
                    MultiFieldPanel([
                        ImageChooserPanel('isd_section_image'),
                        FieldPanel('isd_section_title'),
                        FieldPanel('isd_section_text')
                    ], ),
                    MultiFieldPanel([
                        ImageChooserPanel('capital_invest_section_image'),
                        FieldPanel('capital_invest_section_title'),
                        FieldPanel('capital_invest_section_content'),
                    ]),
                ]),
            ],
        ),
        MultiFieldPanel(
            heading='Featured card links ',
            classname='collapsible',
            children=[
                HelpPanel('Required fields for section to show: '
                          'All images, titles and summaries'),
                FieldRowPanel([
                    MultiFieldPanel([
                        ImageChooserPanel('featured_card_one_image'),
                        FieldPanel('featured_card_one_title'),
                        FieldPanel('featured_card_one_summary'),
                        FieldPanel('featured_card_one_cta_link'),
                    ], ),
                    MultiFieldPanel([
                        ImageChooserPanel('featured_card_two_image'),
                        FieldPanel('featured_card_two_title'),
                        FieldPanel('featured_card_two_summary'),
                        FieldPanel('featured_card_two_cta_link'),
                    ], ),
                    MultiFieldPanel([
                        ImageChooserPanel('featured_card_three_image'),
                        FieldPanel('featured_card_three_title'),
                        FieldPanel('featured_card_three_summary'),
                        FieldPanel('featured_card_three_cta_link'),
                    ]),
                ]),
            ],
        ),
        MultiFieldPanel(
            heading='Industries section',
            children=[
                HelpPanel('Required fields for section to show: '
                          'Sector Title, Sector Content'),
                FieldPanel('sector_title'),
                FieldPanel('sector_intro'),
                FieldPanel('sector_button_text'),
                FieldPanel('sector_button_url'),
            ],
        ),
        MultiFieldPanel(
            heading='High Potential Opportunities',
            children=[
                HelpPanel('Required fields for section to show: '
                          'HPO title, 1 HPO in active language'),
                FieldPanel('hpo_title'),
                FieldPanel('hpo_intro')
            ],
        ),
        MultiFieldPanel(
            heading='How we help section',
            classname='collapsible',
            children=[
                HelpPanel('Required fields for section to show: '
                          'How We Help Title, How We Help Lead In'),
                FieldPanel('how_we_help_title'),
                FieldPanel('how_we_help_lead_in'),
                HelpPanel('Each icon requires the corresponding text to '
                          'show on the page'),
                FieldRowPanel([
                    MultiFieldPanel([
                        FieldPanel('how_we_help_text_one'),
                        ImageChooserPanel('how_we_help_icon_one')
                    ], ),
                    MultiFieldPanel([
                        FieldPanel('how_we_help_text_two'),
                        ImageChooserPanel('how_we_help_icon_two')
                    ], ),
                    MultiFieldPanel([
                        FieldPanel('how_we_help_text_three'),
                        ImageChooserPanel('how_we_help_icon_three')
                    ], ),
                ], ),
                FieldRowPanel([
                    MultiFieldPanel([
                        FieldPanel('how_we_help_text_four'),
                        ImageChooserPanel('how_we_help_icon_four')
                    ], ),
                    MultiFieldPanel([
                        FieldPanel('how_we_help_text_five'),
                        ImageChooserPanel('how_we_help_icon_five')
                    ], )
                ], ),
            ],
        ),
        MultiFieldPanel(
            heading='Contact Section',
            classname='collapsible',
            children=[
                HelpPanel('Required fields for section to show: '
                          'Contact Title, Contact Content'),
                FieldPanel('contact_section_title'),
                FieldPanel('contact_section_content'),
                HelpPanel('Cta\'s require both text and a link to show '
                          'on page. '),
                FieldPanel('contact_section_call_to_action_text'),
                FieldPanel('contact_section_call_to_action_url'),
            ],
        ),
        SearchEngineOptimisationPanel()
    ]

    settings_panels = [
        FieldPanel('title_en_gb'),
        FieldPanel('slug'),
    ]

    edit_handler = make_translated_interface(content_panels=content_panels,
                                             settings_panels=settings_panels,
                                             other_panels=[
                                                 ObjectList(image_panels,
                                                            heading='Images'),
                                             ])
Exemple #23
0
class Team(models.Model):
    """This class represents a working group within UTN"""
    class Meta:
        verbose_name = _('Team')
        verbose_name_plural = _('Teams')
        default_permissions = ()

    # ---- General Information ------
    name_en = models.CharField(
        max_length=255,
        verbose_name=_('English team name'),
        help_text=_('Enter the name of the team'),
        blank=False,
    )

    name_sv = models.CharField(
        max_length=255,
        verbose_name=_('Swedish team name'),
        help_text=_('Enter the name of the team'),
        blank=False,
    )

    name = TranslatedField('name_en', 'name_sv')

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

    description_en = models.TextField(
        verbose_name=_('English team description'),
        help_text=_('Enter a description of the team'),
        blank=True,
    )

    description_sv = models.TextField(
        verbose_name=_('Swedish team description'),
        help_text=_('Enter a description of the team'),
        blank=True,
    )

    description = TranslatedField('description_en', 'description_sv')

    def __str__(self) -> str:
        return '{}'.format(self.name)

    @property
    def members(self):
        return get_user_model().objects.filter(
            application__position__role__teams__pk=self.pk,
            application__position__term_from__lte=date.today(),
            application__position__term_to__gte=date.today(),
            application__status='appointed',
        )

    @property
    def manual_members(self):
        members = self.members.values('pk')
        return get_user_model().objects.filter(groups=self.group).exclude(
            pk__in=members)

    # ------ Administrator settings ------
    panels = [
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('name_en'),
                FieldPanel('name_sv'),
            ]),
            ImageChooserPanel('logo'),
            FieldPanel('description_en'),
            FieldPanel('description_sv'),
        ])
    ]
class Homepage(FoundationMetadataPageMixin, Page):
    hero_headline = models.CharField(
        max_length=140,
        help_text='Hero story headline',
        blank=True,
    )

    hero_story_description = RichTextField(features=[
        'bold',
        'italic',
        'link',
    ])

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

    hero_button_text = models.CharField(max_length=50, blank=True)

    hero_button_url = models.URLField(blank=True)

    content_panels = Page.content_panels + [
        MultiFieldPanel([
            FieldPanel('hero_headline'),
            FieldPanel('hero_story_description'),
            FieldRowPanel([
                FieldPanel('hero_button_text'),
                FieldPanel('hero_button_url'),
            ], ),
            ImageChooserPanel('hero_image'),
        ],
                        heading='hero',
                        classname='collapsible'),
        InlinePanel('featured_blogs', label='Blogs', max_num=4),
        InlinePanel('featured_highlights', label='Highlights', max_num=5),
    ]

    subpage_types = [
        'BanneredCampaignPage',
        'IndexPage',
        'InitiativesPage',
        'MiniSiteNameSpace',
        'NewsPage',
        'OpportunityPage',
        'ParticipatePage',
        'ParticipatePage2',
        'PeoplePage',
        'PrimaryPage',
        'RedirectingPage',
        'Styleguide',
    ]

    def get_context(self, request):
        # We need to expose MEDIA_URL so that the s3 images will show up properly
        # due to our custom image upload approach pre-wagtail
        context = super().get_context(request)
        context['MEDIA_URL'] = settings.MEDIA_URL
        context['menu_root'] = self
        context['menu_items'] = self.get_children().live().in_menu()
        return context
Exemple #25
0
class AbstractAttendeeRelation(Orderable):
    class Meta:
        abstract = True

    attendee_name_en = models.CharField(
        max_length=512,
        verbose_name=_('name of the attendee type (english)'),
        blank=True,
        null=True)
    attendee_name_de = models.CharField(
        max_length=512,
        verbose_name=_('name of the attendee type (german)'),
        blank=True,
        null=True)

    attendee_name = TranslatedField('attendee_name')

    description_en = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'ol', 'ul'],
        verbose_name=_('description of the attendee type (english)'))
    description_de = RichTextField(
        blank=True,
        features=['bold', 'italic', 'link', 'ol', 'ul'],
        verbose_name=_('description of the attendee type (german)'))

    description = TranslatedField('description')

    attendee = models.CharField(max_length=16,
                                verbose_name=_('required form data'))

    waitlist = models.BooleanField(default=False, verbose_name=_('waitlist'))

    price = models.DecimalField(max_digits=7,
                                decimal_places=2,
                                default=0,
                                blank=True,
                                null=True,
                                verbose_name=_('price'))

    max_attendees = models.IntegerField(blank=True,
                                        null=True,
                                        verbose_name=_('max attendees'))

    panels = [
        FieldPanel('attendee_name_en'),
        FieldPanel('attendee_name_de'),
        FieldPanel('attendee', widget=AttendeeSelectWidget()),
        FieldPanel('description_en'),
        FieldPanel('description_de'),
        FieldPanel('price'),
        FieldRowPanel([
            FieldPanel('max_attendees'),
            FieldPanel('waitlist'),
        ])
    ]

    def get_attendee_class(self):
        if not self.attendee:
            return None
        return get_attendee_class(self.attendee)
Exemple #26
0
class OrbitalMechanicsMixin(models.Model):
    """
    A mixin for anything that orbits something else (e.g. a planet or a moon).

    This mixin assumes its direct parent has mass.
    """

    semi_major_axis = MultiQuantityField(units=(ureg.au, ureg.km))
    eccentricity = models.DecimalField(max_digits=5, decimal_places=5)
    inclination = MultiQuantityField(units=(ureg.degree, ureg.radian))
    longitude_of_the_ascending_node = MultiQuantityField(units=(ureg.degree, ureg.radian))
    argument_of_periapsis = MultiQuantityField(units=(ureg.degree, ureg.radian))

    # Local motion
    rotational_period = MultiQuantityField(units=(ureg.hour, ureg.day))
    obliquity = MultiQuantityField(units=(ureg.degree, ureg.radian))
    precessional_period = MultiQuantityField(units=(ureg.year,))

    @property
    def orbited_object(self):
        return self.get_parent().specific

    @property
    def periapsis(self):
        return self.semi_major_axis * (1 - float(self.eccentricity))

    @property
    def apoapsis(self):
        return self.semi_major_axis * (1+ float(self.eccentricity))

    @property
    def orbital_period(self):
        return (((4 * math.pi**2) / (GRAVITATIONAL_CONSTANT * self.orbited_object.mass)) * self.semi_major_axis**3)**0.5

    @property
    def longitude_of_periapsis(self):
        return self.longitude_of_the_ascending_node + self.argument_of_periapsis


    @property
    def day_length(self):
        return self.rotational_period

    @property
    def local_days_in_year(self):
        return self.orbital_period / self.rotational_period

    @property
    def tropics(self):
        return self.obliquity

    @property
    def polar_circles(self):
        return Q_('90 degree') - self.obliquity

    content_panels = [MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('semi_major_axis'),
                FieldPanel('eccentricity'),
            ]),
            FieldRowPanel([
                FieldPanel('inclination'),
                FieldPanel('longitude_of_the_ascending_node'),
                FieldPanel('argument_of_periapsis'),
            ]),
            FieldRowPanel([
                FieldPanel('rotational_period'),
                FieldPanel('obliquity'),
                FieldPanel('precessional_period'),
            ]),
        ], 'Orbital properties')]

    class Meta:
        abstract = True
Exemple #27
0
class Course(RoutablePageMixin, TranslatedPage, BodyMixin):
    class Meta:
        verbose_name = _('Course date')

    parent_page_types = [CourseInformationPage]

    start = models.DateField(verbose_name=_('start date'))
    end = models.DateField(blank=True,
                           null=True,
                           verbose_name=_('end date'),
                           help_text=_('leave empty for a one-day course'))

    overrule_parent = models.BooleanField(
        default=False, verbose_name=_('Overrule standard settings'))
    register_via_website = models.BooleanField(
        default=False, verbose_name=_('Registration via website'))

    share_data_via_website = models.BooleanField(
        default=False, verbose_name=_('Share data via website'))

    max_attendees = models.IntegerField(blank=True,
                                        null=True,
                                        default=None,
                                        verbose_name=_('Max attendees'))

    script = StreamField(
        [
            ('chapter',
             blocks.CharBlock(
                 classname="full title", required=True, label='Kapitel')),
            ('section', blocks.CharBlock(required=True, label='Unterkapitel')),
            ('file', DocumentChooserBlock(label="Datei mit Folien")),
        ],
        verbose_name=_('Script for the course'),
        help_text=_('This allows to combine several PDFs to a single one'),
        null=True,
        blank=True)

    script_title = models.CharField(max_length=512, blank=True)
    script_subtitle1 = models.CharField(max_length=512, blank=True)
    script_subtitle2 = models.CharField(max_length=512, blank=True)
    script_date = models.CharField(max_length=2,
                                   choices=(
                                       ('d', 'german'),
                                       ('e', 'english'),
                                       ('n', 'no date'),
                                   ),
                                   default='n')

    fill_automatically = models.BooleanField(
        default=False,
        help_text=_('Fill with attendees from waitlist automatically?'))

    content_panels = [
        FieldRowPanel([FieldPanel('start'),
                       FieldPanel('end')]),
        StreamFieldPanel('body_en'),
        StreamFieldPanel('body_de'),
    ]

    settings_panels = [
        FieldPanel('overrule_parent'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('register_via_website'),
                FieldPanel('share_data_via_website'),
            ]),
        ],
                        heading=_('Registration options')),
        FieldPanel('max_attendees'),
        InlinePanel('attendee_types', label=_('allowed attendees'))
    ]

    script_panel = [
        FieldPanel('script_title'),
        FieldPanel('script_subtitle1'),
        FieldPanel('script_subtitle2'),
        FieldPanel('script_date'),
        StreamFieldPanel('script')
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels, heading=_('Date and info')),
        ObjectList(settings_panels, heading=_('Overrule parent settings')),
        ObjectList(script_panel, heading=_('Script')),
    ])

    def clean(self):
        self.title = '{}–{}'.format(self.start, self.end)
        self.title_de = self.title
        if not self.slug:
            self.slug = self._get_autogenerated_slug(slugify(self.title))

    def _get_me_or_parent(self):
        if self.overrule_parent:
            return self
        else:
            return self.get_parent().specific

    @property
    def is_bookable(self):
        return self._get_me_or_parent().register_via_website

    def started_in_past(self):
        return self.start <= datetime.date.today()

    def get_attendee_types(self):
        return self._get_me_or_parent().attendee_types

    def get_max_attendees(self):
        return self._get_me_or_parent().max_attendees

    @property
    def has_data_sharing(self):
        return self._get_me_or_parent().share_data_via_website

    def get_price(self, attendee):

        for at_rel in self.get_attendee_types().all():
            if at_rel.get_attendee_class() == attendee:
                return at_rel.price
        return 0

    def has_waitlist_for(self, attendee):
        return self.get_attendee_types().filter(attendee=attendee.identifier,
                                                waitlist=True).count() > 0

    @property
    def registered_attendees_stats(self):
        '''
        Returns an overview of the the registered attendees
        '''
        attendees = {}

        for atype in self.get_attendee_types().all():
            Klass = atype.get_attendee_class()
            if not Klass:
                continue
            try:
                disp = Klass.display_name_plural
            except AttributeError:
                disp = Klass.display_name

            # The total number of attendees for one attendee-type
            # is the sum of
            #
            # a) those who are validated

            qs = Klass.objects.filter(related_course=self)
            num = qs.filter(is_validated=True).count()

            # b) those who are not yet validated, but the
            # mail asking for validation has been sent within the last week

            minus_one_week = datetime.date.today() - relativedelta(weeks=1)

            num = num + qs.filter(
                is_validated=False,
                validation_mail_sent=True,
                validation_mail_sent_at__gte=minus_one_week).count()

            # c) People from the waitlist that have been asked to
            # attend this course, but have not yet answered and the
            # mail was sent within the last week

            num = num + Klass.objects.filter(
                waitlist_course=self,
                add2course_mail_sent=True,
                add2course_mail_sent_at__gte=minus_one_week).count()

            # This is just in case that two or more attendee types have the
            # same display name. Should not happen! It might be better
            # to solve this by something like:
            # { 'unique' : ('display', num) }
            #
            # (see method get_free_slots below)
            c = 0
            while disp in attendees:
                c += 1
                disp = "{}_{}".format(disp, c)

            attendees[disp] = num
        return attendees

    def get_free_slots(self, Attendee):

        print('Attendee is: {}'.format(Attendee))
        stats = self.registered_attendees_stats

        # we need idx to be a unique index.
        try:
            idx = Attendee.display_name_plural
        except AttributeError:
            idx = Attendee.display_name

        try:
            n_attendees = stats[idx]
        except KeyError:
            # if idx is not in stats, this Attendee type is not allowed
            # for this course. Thus, free slots is 0
            return 0

        # get max_attendees for this attendee-type, if exists

        limit_type = (self.get_attendee_types().get(
            attendee=Attendee.identifier).max_attendees)
        if limit_type is not None:
            attendee_free = limit_type - n_attendees
            if attendee_free < 0:
                # might happen during testing or if someone adds an attendee
                # manually
                attendee_free = 0
        else:
            attendee_free = None

        limit_total = self.get_max_attendees()

        # compute total number of attendees
        total_attendees = 0
        for k, v in stats.items():
            total_attendees = total_attendees + v

        total_free = limit_total - total_attendees
        if total_free < 0:
            # see above...
            total_free = 0

        # Very import to test for None, since 0 is interpreted as False...
        if attendee_free is not None:
            return min(total_free, attendee_free)
        else:
            return total_free

    def get_n_attendees(self):
        c = 0
        for k, v in self.registered_attendees_stats.items():
            c = c + v

        return c

    @property
    def is_fully_booked(self):
        try:
            return self.get_n_attendees() >= self.get_max_attendees()
        except TypeError:
            return False

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

        # test whether there are any free slots in this course

        n_attendees = 0

        for k, v in self.registered_attendees_stats.items():
            n_attendees = n_attendees + v

        # is there any attendee_type with a waitlist?

        waitlist = self.get_attendee_types().all().filter(
            waitlist=True).count() > 0

        if self.get_max_attendees():
            if not waitlist and self.get_max_attendees() <= n_attendees:
                context['fully_booked'] = True
            else:
                context['fully_booked'] = False
        # test if we have a waitlist for any allowed attendee type
        # and no slots left for the type...
        free_courses = {}
        for a2c_rel in self.get_attendee_types().all().filter(waitlist=True):
            if self.get_free_slots(a2c_rel.get_attendee_class()) == 0:

                # Do we have another course, not fully booked, for that attendee type?

                upcoming_courses = self.get_parent(
                ).specific.get_upcoming_courses().exclude(id=self.id)
                for uc in upcoming_courses:
                    if uc.specific.get_free_slots(
                            a2c_rel.get_attendee_class()) > 0:
                        if not a2c_rel.get_attendee_class(
                        ).display_name_plural in free_courses.keys():
                            free_courses[a2c_rel.get_attendee_class().
                                         display_name_plural] = []
                        free_courses[a2c_rel.get_attendee_class().
                                     display_name_plural].append(uc)

        if free_courses:
            context['show_waitlist_info'] = True
            context['free_courses'] = free_courses

        return context

    @route(r'^register/(\w+)/$', name="register")
    @route(r'^register/(\w+)/(\d+)/$', name="register")
    def register_for_course(self, request, attendee, form_count=0):
        # implements a multi-step form for registration.
        # The forms are provided by `forms` list of the corresponding attendee class.

        # get the form count
        form_count = int(form_count)

        # if a form has been filled is stored in request.session.form<number>
        # Avoid that a form is shown before the previous has been filled:
        if form_count > 0:
            if not request.session.get('form{}_filled'.format(form_count - 1)):
                return redirect(self.url + self.reverse_subpage(
                    'register', args=[attendee, form_count - 1]))

        # get the attende by the "register_attendee" mechanism and raise a 404 if not known
        Attendee = get_attendee_class(attendee)

        if not Attendee:
            raise Http404

        # IF THE COURSE IS IN THE PAST, RAISE A 404

        if self.start <= datetime.date.today():
            raise Http404

        # @TODO: Test if attendee is allowed for this course

        # collect all form classes...
        forms = []
        for f in Attendee.forms:
            module_name, class_name = f.rsplit(".", 1)
            module = importlib.import_module(module_name)
            FormKlass = getattr(module, class_name)
            forms.append(FormKlass)

        # Check if there are earlier courses that have a waitlist for this Attendee class

        waitlist_available = False
        previous_courses = self.get_parent().specific.get_upcoming_courses(
        ).filter(start__lt=self.start).order_by('-start')
        for pc in previous_courses.all():
            if pc.get_free_slots(Attendee) == 0 and pc.get_attendee_types(
            ).filter(waitlist=True, attendee=Attendee.identifier).count() > 0:
                waitlist_available = True
                waitlist_course = pc
                break

        # and if there is one, add the respective form class in the second last position
        # but only, if this regsitration is for the course, and not for the waitlist of this course
        has_waitlist = self.has_waitlist_for(Attendee)
        free_slots = self.get_free_slots(Attendee)
        uses_waitlist = has_waitlist and free_slots < 1
        if uses_waitlist:
            waitlist_available = False
        if waitlist_available:
            from .forms import WaitlistForm
            last_form = forms[-1]
            forms[-1] = WaitlistForm
            forms.append(last_form)

        # ... and get the current one
        try:
            CurrentFormKlass = forms[form_count]
        except KeyError:
            raise Http404

        kwargs = {}

        # there might be some values passed from the previous form
        provided_values = request.session.get(
            'provided_values{}'.format(form_count - 1), None)

        if provided_values:
            kwargs['provided_values'] = provided_values

        print('Form count is: {}'.format(form_count))
        if waitlist_available and form_count == len(forms) - 2:
            kwargs['course'] = pc

        # now the usual stuff
        if request.method == 'GET':

            # @TODO.
            # This code might be executed if someone clicks on the "step indicator"
            # try to fill it with the already collected data...
            if request.session.get('form{}_filled'.format(form_count), None):
                data_json = request.session.get('cleaned_data', None)
                if data_json:
                    data = json.loads(data_json)
                else:
                    data = {}
                kwargs['initial'] = data
            else:
                if provided_values:
                    kwargs['initial'] = provided_values

            form = CurrentFormKlass(**kwargs)

        if request.method == 'POST':
            form = CurrentFormKlass(request.POST, **kwargs)

            if form.is_valid():
                if hasattr(form, 'is_validated'):
                    cleaned_data = {'is_validated': True}
                else:
                    cleaned_data = {}

                # Get the json for the data from the session
                data_json = request.session.get('cleaned_data', None)
                if data_json:
                    cleaned_data.update(json.loads(data_json))

                if issubclass(CurrentFormKlass,
                              ModelForm) or (waitlist_available
                                             and form_count == len(forms) - 2):
                    for key, value in form.cleaned_data.items():
                        cleaned_data[key] = value

                else:
                    try:
                        request.session['provided_values{}'.format(
                            form_count)] = form.provided_values
                    except AttributeError:
                        request.session['provided_values{}'.format(
                            form_count)] = {}

                request.session['form{}_filled'.format(form_count)] = True
                request.session['cleaned_data'] = json.dumps(cleaned_data,
                                                             cls=PHJsonEncoder)
                request.session.modified = True

                if form_count < len(forms) - 1:
                    messages.info(
                        request,
                        format_lazy(
                            'Your data for step {} has been saved. Please proceed with step {}.',
                            form_count + 1, form_count + 2))
                    return redirect(self.url + self.reverse_subpage(
                        'register', args=[attendee, form_count + 1]))
                else:
                    instance = form.save(commit=False)
                    for key, value in cleaned_data.items():
                        if key == 'waitlist' and waitlist_available:
                            setattr(instance, 'waitlist_course', pc)
                        else:
                            setattr(instance, key, value)

                    # Attendees that have to pay have the amount of the fee and the
                    # amount already payed in the database. We need to provide values here...
                    if hasattr(instance, 'amount'):
                        instance.amount = self.get_price(Attendee)
                    if hasattr(instance, 'payed'):
                        instance.payed = False

                    instance.related_course = self
                    if self.get_free_slots(Attendee) > 0:
                        instance.save()
                        if not instance.is_validated:
                            return redirect(self.url + self.reverse_subpage(
                                'validation_mail',
                                args=[instance.courseattendee_ptr_id]))
                        else:
                            return redirect(self.url + self.reverse_subpage(
                                'success',
                                args=[instance.courseattendee_ptr_id]))
                    elif has_waitlist:
                        instance.waitlist_course = self
                        instance.related_course = None
                        instance.save()
                        messages.info(request,
                                      _('You were put on the waiting list.'))
                        if not instance.is_validated:
                            return redirect(self.url + self.reverse_subpage(
                                'validation_mail',
                                args=[instance.courseattendee_ptr_id]))
                        else:
                            return redirect(self.url + self.reverse_subpage(
                                'success',
                                args=[instance.courseattendee_ptr_id]))
                    else:
                        messages.error(
                            request,
                            _('The course is fully booked. You have not been registered.'
                              ))
                        messages.info(request,
                                      _('We have not stored your data.'))
                        try:
                            del request.session['cleaned_data']
                        except KeyError:
                            pass
                        return redirect(self.url)

        price = self.get_price(Attendee)
        show_price_hint = price > 0 and form_count == len(forms) - 1

        return TemplateResponse(
            request, 'courses/register.html', {
                'attendee': attendee,
                'attendee_name': Attendee.display_name,
                'forms': forms,
                'current_form': form_count,
                'form': form,
                'page': self,
                'price': price,
                'show_price_hint': show_price_hint,
                'free_slots': free_slots,
                'has_waitlist': has_waitlist
            })

    @route(r'^success/(\d+)/$', name="success")
    def success(self, request, attendee_id):

        attendee = get_object_or_404(CourseAttendee, id=attendee_id)
        if attendee.confirmation_mail_sent:
            raise Http404

        mailtext = EMailText.objects.get(
            identifier='courses.registration.confirmation')
        mailtext.send(
            attendee.email, {
                'attendee': attendee,
                'course': self,
                'waitlist': attendee.waitlist_course == self
            })
        self.send_invoice(attendee)
        try:
            del request.session['cleaned_data']
        except KeyError:
            pass
        return TemplateResponse(request, 'courses/success.html',
                                {'page': self})

    @route(r'^validation_required/(\d+)/$', name="validation_mail")
    def validation_mail(self, request, attendee_id):
        attendee = get_object_or_404(CourseAttendee, id=attendee_id)

        validation = CourseParticipationValidation()
        validation.attendee = attendee
        validation.save()

        now = datetime.datetime.now()

        attendee.validation_mail_sent = True
        attendee.validation_mail_sent_at = now
        attendee.save()

        valid_until = now + relativedelta(weeks=+1)

        if valid_until.date() >= self.start:
            valid_until = self.start + relativedelta(days=-2)

        mailtext = EMailText.objects.get(
            identifier='courses.registration.validation')
        mailtext.send(
            attendee.email, {
                'attendee':
                attendee,
                'course':
                self,
                'validation_url':
                request.build_absolute_uri(
                    reverse('manage-courses:validate_course_registration',
                            kwargs={'uuid': validation.uuid})),
                'validation':
                validation,
                'valid_until':
                valid_until
            })
        try:
            del request.session['cleaned_data']
        except KeyError:
            pass
        return TemplateResponse(request, 'courses/validation_mail.html', {
            'page': self,
            'valid_until': valid_until,
            'attendee': attendee
        })

    def send_invoice(self, attendee):

        # get the specific course attendee object
        for Kls in ATTENDEE_TYPES:
            try:
                s_att = Kls.objects.get(courseattendee_ptr_id=attendee.id)
                break
            except Kls.DoesNotExist:
                pass

        attendee = s_att
        try:
            if attendee.amount == 0:
                return
        except AttributeError:
            return

        parent = self.get_parent().specific
        staff_mails = [
            staff.person.mail for staff in parent.contact_persons.all()
        ]

        pdffile = RUBIONCourseInvoice(
            attendee,
            parent.contact_persons.first().person,
        )
        pdffilename = pdffile.write2file()

        mailtext = EMailText.objects.get(
            identifier='courses.staff.invoice_copy')
        mailtext.send(staff_mails, {
            'course': self,
            'attendee': attendee,
            'invoice_was_sent': False
        },
                      attachements=[pdffilename],
                      lang='de')

        # Should mails be sent automatically or manually?
        # I guess we said manually, at least in the beginning.

        #MAILTEXT = EMailText.objects.get(identifier = 'courses.attendee.invoice' )
        #mailtext.send(
        #    attendee.email,
        #    {
        #        'attendee': attendee,
        #        'course' : self
        #    }
        #)

    def get_data_sharing_page(self):
        if DataSharingPage.objects.child_of(self).exists():
            return DataSharingPage.objects.child_of(self).first()
        else:
            return None

    def save(self, *args, **kwargs):
        super(Course, self).save(*args, **kwargs)

        if self.has_data_sharing:
            if not self.get_data_sharing_page():
                dsp = DataSharingPage()
                dsp.clean()
                self.add_child(dsp)
                characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_*?!$&"
                pvr = PageViewRestriction(
                    page=dsp,
                    restriction_type=PageViewRestriction.PASSWORD,
                    password="".join(
                        random.choice(characters) for __ in range(10)))
                pvr.save()
class BlogDetailPage(Page):
    """Blog Detail Page"""

    template = "blog/blog-detail.html"
    parent_page_types = ["blog.BlogIndexPage"]
    """
        - upvotes *
        - times read *
        - read time *
    """
    author = models.ForeignKey("blog.BlogAuthor",
                               on_delete=models.PROTECT,
                               related_name="+",
                               help_text="Select the author of this blog post")
    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        blank=False,
        related_name="+",
        on_delete=models.SET_NULL,
        help_text="Select an image to use on the post's page")
    date_published = models.DateTimeField(auto_now_add=True)
    quote = models.TextField(_("A Programming Quote"),
                             help_text="Enter some programming quote",
                             blank=False,
                             null=False)
    category = models.ForeignKey(
        "blog.BlogCategory",
        on_delete=models.PROTECT,
        related_name="+",
        help_text="Select the category of this blog post")
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
    content = StreamField([
        ("heading", blocks.CharBlock()),
        ("text", blocks.TextBlock()),
        ("paragraph",
         blocks.RichTextBlock(template="blocks/rich-text-block.html",
                              features=[
                                  'h1', 'h2', 'h3', 'h4', 'h5', 'bold',
                                  'italic', 'ol', 'ul', 'hr', 'link', 'image',
                                  'code', 'blockquote'
                              ])),
        ("code", CodeBlock()),
        ("image", ImageChooserBlock()),
    ])

    def get_context(self, request, *args, **kwargs):
        context = super().get_context(request, *args, **kwargs)
        context["posts_from_author"] = BlogDetailPage.objects.live().filter(
            author__full_name=self.author.full_name).exclude(
                title=self.title)[:5]
        return context

    content_panels = Page.content_panels + [
        ImageChooserPanel("image"),
        MultiFieldPanel([
            FieldRowPanel([
                SnippetChooserPanel("author"),
                SnippetChooserPanel("category")
            ]),
        ],
                        heading="Author and Category"),
        FieldPanel("tags"),
        FieldPanel("quote"),
        MultiFieldPanel([
            StreamFieldPanel("content"),
        ],
                        heading="Blog Content",
                        classname="collapse collapsed"),
        MultiFieldPanel([
            InlinePanel(
                "related_posts", max_num=10, min_num=1, heading="Related Post")
        ],
                        heading="Related Blog Posts")
    ]
Exemple #29
0
class CourseInformationPage(TranslatedPage, MandatoryIntroductionMixin,
                            BodyMixin, ChildMixin):
    '''
    A general model for a course.
    '''

    subpage_types = ['courses.Course']
    parent_page_types = ['courses.ListOfCoursesPage']

    class Meta:
        verbose_name = _('Definition of a course')

    # ID in the courses register
    course_id = models.CharField(max_length=64, blank=True)

    register_via_website = models.BooleanField(default=False)

    share_data_via_website = models.BooleanField(default=False)

    max_attendees = models.IntegerField(blank=True, null=True, default=None)

    information_list = models.BooleanField(
        default=False,
        help_text=
        _('Is there a list that stores people intereted in this course if no course date is available?'
          ))

    content_panels_de = [
        FieldPanel('title_de'),
        StreamFieldPanel('introduction_de'),
        StreamFieldPanel('body_de'),
    ]
    content_panels_en = [
        FieldPanel('title'),
        StreamFieldPanel('introduction_en'),
        StreamFieldPanel('body_en'),
    ]
    additional_information_panel = [
        FieldPanel('course_id'),
        InlinePanel('contact_persons', label=_('Contact persons'))
    ]
    settings_panel = [
        FieldPanel('information_list'),
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('register_via_website'),
                FieldPanel('share_data_via_website'),
            ]),
        ],
                        heading=_('Registration options')),
        FieldPanel('max_attendees'),
        InlinePanel('attendee_types', label=_('allowed attendees'))
    ]

    edit_handler = TabbedInterface([
        ObjectList(content_panels_de, heading=_('Content (de)')),
        ObjectList(content_panels_en, heading=_('Content (en)')),
        ObjectList(additional_information_panel,
                   heading=_('Additional information')),
        ObjectList(settings_panel, heading=_('Settings')),
    ])

    def get_upcoming_courses(self):
        children = Course.objects.live().child_of(self).filter(
            start__gt=datetime.date.today()).order_by('start')
        return children

    def get_admin_display_title(self):
        return self.title_trans
class TestFieldRowPanel(TestCase):
    def setUp(self):
        self.request = RequestFactory().get('/')
        user = AnonymousUser()  # technically, Anonymous users cannot access the admin
        self.request.user = user

        self.EventPageForm = get_form_for_model(
            EventPage, form_class=WagtailAdminPageForm, formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 20), date_to=date(2014, 7, 21))

        self.dates_panel = FieldRowPanel([
            FieldPanel('date_from', classname='col4'),
            FieldPanel('date_to', classname='coltwo'),
        ]).bind_to(model=EventPage, request=self.request)

    def test_render_as_object(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-22'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )
        result = field_panel.render_as_object()

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_render_as_field(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-22'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )
        result = field_panel.render_as_field()

        # check that label is output in the 'field' style
        self.assertIn('<label for="id_date_to">End date:</label>', result)
        self.assertNotIn('<legend>End date</legend>', result)

        # check that help text is included
        self.assertIn('Not required if event is on a single day', result)

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_error_message_is_rendered(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )
        result = field_panel.render_as_field()

        self.assertIn('<p class="error-message">', result)
        self.assertIn('<span>Enter a valid date.</span>', result)

    def test_add_col_when_wrong_in_panel_def(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )

        result = field_panel.render_as_field()

        self.assertIn('<li class="field-col coltwo col6', result)

    def test_added_col_doesnt_change_siblings(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to(
            instance=self.event,
            form=form,
        )

        result = field_panel.render_as_field()

        self.assertIn('<li class="field-col col4', result)
Exemple #31
0
class Appearance(BaseSetting, NavbarSection, Footer, ButtonAction, Colors):

    # Navbar settings
    header_logo = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+',
        verbose_name=('Logo Image'),
    )

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

    # Body settings
    body_background_color_solid = ColorField(
        blank=True,
        null=True,
        help_text="Choose background color",
        verbose_name=('Background color'),
    )

    # components tab panels
    components_panels = ButtonAction.button_action_panels + NavbarSection.navbar_panels

    # branding tab panels
    branding_panels = [
        MultiFieldPanel(
            [
                FieldRowPanel([
                    NativeColorPanel(
                        'color_primary', heading='Color 1', classname="col6"),
                    NativeColorPanel('color_secondary',
                                     heading='Color 2',
                                     classname="col6"),
                ]),
            ],
            heading='Colors',
        ),
        MultiFieldPanel(
            [
                FieldRowPanel([
                    ImageChooserPanel(
                        'header_logo', heading='Logo', classname="col12"),
                    ImageChooserPanel(
                        'favicon_image', heading='Favicon', classname="col12"),
                ]),
            ],
            heading='Logo and Favicon',
        ),
    ]
    # Register Tabs
    edit_handler = TabbedInterface([
        ObjectList(branding_panels, heading="Branding"),
        ObjectList(components_panels, heading="Components"),
    ])
class TestFieldRowPanel(TestCase):
    def setUp(self):
        self.request = RequestFactory().get('/')
        user = AnonymousUser()  # technically, Anonymous users cannot access the admin
        self.request.user = user

        self.EventPageForm = get_form_for_model(
            EventPage, form_class=WagtailAdminPageForm, formsets=[])
        self.event = EventPage(title='Abergavenny sheepdog trials',
                               date_from=date(2014, 7, 20), date_to=date(2014, 7, 21))

        self.dates_panel = FieldRowPanel([
            FieldPanel('date_from', classname='col4'),
            FieldPanel('date_to', classname='coltwo'),
        ]).bind_to_model(EventPage)

    def test_render_as_object(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-22'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to_instance(
            instance=self.event,
            form=form,
            request=self.request
        )
        result = field_panel.render_as_object()

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_render_as_field(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-22'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to_instance(
            instance=self.event,
            form=form,
            request=self.request
        )
        result = field_panel.render_as_field()

        # check that label is output in the 'field' style
        self.assertIn('<label for="id_date_to">End date:</label>', result)
        self.assertNotIn('<legend>End date</legend>', result)

        # check that help text is included
        self.assertIn('Not required if event is on a single day', result)

        # check that the populated form field is included
        self.assertIn('value="2014-07-22"', result)

        # there should be no errors on this field
        self.assertNotIn('<p class="error-message">', result)

    def test_error_message_is_rendered(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to_instance(
            instance=self.event,
            form=form,
            request=self.request
        )
        result = field_panel.render_as_field()

        self.assertIn('<p class="error-message">', result)
        self.assertIn('<span>Enter a valid date.</span>', result)

    def test_add_col_when_wrong_in_panel_def(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to_instance(
            instance=self.event,
            form=form,
            request=self.request
        )

        result = field_panel.render_as_field()

        self.assertIn('<li class="field-col coltwo col6', result)

    def test_added_col_doesnt_change_siblings(self):
        form = self.EventPageForm(
            {'title': 'Pontypridd sheepdog trials', 'date_from': '2014-07-20', 'date_to': '2014-07-33'},
            instance=self.event)

        form.is_valid()

        field_panel = self.dates_panel.bind_to_instance(
            instance=self.event,
            form=form,
            request=self.request
        )

        result = field_panel.render_as_field()

        self.assertIn('<li class="field-col col4', result)
Exemple #33
0
class Contact(AbstractBaseModel):
    INFO = 'info'
    BUSINESS = 'business'
    VISIT = 'visit'
    MESSAGE_CATEGORY_CHOICES = (('visit', 'Visit brewery'), ('info',
                                                             'Info on beers'),
                                ('business', 'Business occasion'))
    sender_full_name = models.CharField(max_length=255,
                                        verbose_name='Sender full name')
    sender_email = models.EmailField(max_length=255,
                                     verbose_name='Sender email')
    sender_telephone = models.CharField(max_length=255,
                                        verbose_name='Sender phone number',
                                        null=True,
                                        blank=True)
    message_type = models.CharField(max_length=20,
                                    choices=MESSAGE_CATEGORY_CHOICES,
                                    default=INFO)
    subject = models.CharField(max_length=255, verbose_name='Message subject')
    body = models.TextField(verbose_name='Message body')

    panels = [
        FieldRowPanel([
            FieldPanel('sender_full_name', classname='col6'),
            FieldPanel('sender_email', classname='col6')
        ]),
        FieldRowPanel([
            FieldPanel('sender_telephone', classname='col6'),
            FieldPanel('message_type', classname='col6')
        ]),
        FieldPanel('subject', classname='full'),
        FieldPanel('body', classname='full')
    ] + AbstractBaseModel.panels

    search_fields = [
        index.SearchField('sender_full_name', partial_match=True),
        index.SearchField('sender_email', partial_match=True),
        index.SearchField('subject', partial_match=True),
        index.SearchField('body', partial_match=True)
    ]

    class Meta:
        app_label = 'contact'
        ordering = ['-created', 'sender_email']
        verbose_name = 'Contact message'
        verbose_name_plural = 'Contact messages'

    def __str__(self):
        return 'From %s on %s' % (self.sender_email,
                                  self.created.strftime('%d/%M/%Y'))

    def get_formatted_message(self):
        from_email = settings.DEFAULT_FROM_EMAIL
        subject = settings.EMAIL_SUBJECT_PREFIX + self.subject

        text_body = self.sender_email + ' ha mandato un messaggio con il contenuto: \n'\
            + self.body + '.\n Dati del messaggio:\n -Mittente: '\
            + self.sender_full_name + '\n -Telefono: ' + self.sender_telephone\
            + '\n -Tipo di messaggio: ' + self.message_type + '\n -Data invio: '\
            + self.created.strftime('%d/%m/%Y') + '.'

        html_content = '<h4>' + self.sender_email + ' ha mandato un messaggio con il contenuto: </h4>'\
            + '<p> + ' + self.body + '</p><br/><h4>Dati del messaggio:</h4><ul><li>Mittente: '\
            + self.sender_full_name + '</li><li>Telefono: ' + self.sender_telephone + '</li>'\
            + '<li>Tipo di messaggio: ' + self.message_type + '</li><li>Data invio: '\
            + self.created.strftime('%d/%m/%Y') + '</li></ul>'

        message = EmailMultiAlternatives(subject, text_body, from_email,
                                         settings.RECIPIENTS)

        message.attach_alternative(html_content, 'text/html')
        return message

    def send_itself(self):
        message = self.get_formatted_message()
        message.send()