class ContributionStartDateForm(IndicoForm): start_dt = IndicoDateTimeField(_('Start date'), [ DataRequired(), DateTimeRange(earliest=lambda form, field: form.event.start_dt, latest=lambda form, field: form.event.end_dt) ], allow_clear=False) def __init__(self, *args, **kwargs): self.contrib = kwargs.pop('contrib') self.event = self.contrib.event self.timezone = self.event.timezone super().__init__(*args, **kwargs) def validate_start_dt(self, field): event = self.contrib.event day = self.contrib.start_dt.astimezone(event.tzinfo).date() if day == event.end_dt_local.date(): latest_dt = event.end_dt error_msg = _( 'With this time, the contribution would exceed the event end time.' ) else: latest_dt = get_day_end(day, tzinfo=event.tzinfo) error_msg = _( 'With this time, the contribution would exceed the current day.' ) if field.data + self.contrib.duration > latest_dt: raise ValidationError(error_msg)
class ScheduleSurveyForm(IndicoForm): start_dt = IndicoDateTimeField( _("Start"), [ UsedIf(lambda form, field: form.allow_reschedule_start), Optional(), DateTimeRange(earliest='now') ], default_time=time(0, 0), description=_("Moment when the survey will open for submissions")) end_dt = IndicoDateTimeField( _("End"), [Optional(), LinkedDateTime('start_dt')], default_time=time(23, 59), description=_("Moment when the survey will close")) resend_start_notification = BooleanField( _('Resend start notification'), widget=SwitchWidget(), description=_("Resend the survey start notification.")) def __init__(self, *args, **kwargs): survey = kwargs.pop('survey') self.allow_reschedule_start = kwargs.pop('allow_reschedule_start') self.timezone = survey.event_new.timezone super(IndicoForm, self).__init__(*args, **kwargs) if not survey.start_notification_sent or not self.allow_reschedule_start: del self.resend_start_notification
class ContributionForm(IndicoForm): title = StringField(_("Title"), [DataRequired()]) description = TextAreaField(_("Description")) start_dt = IndicoDateTimeField(_("Start date"), [DataRequired(), DateTimeRange(earliest=lambda form, field: form._get_earliest_start_dt(), latest=lambda form, field: form._get_latest_start_dt())], allow_clear=False, description=_("Start date of the contribution")) duration = TimeDeltaField(_("Duration"), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20), units=('minutes', 'hours')) type = QuerySelectField(_("Type"), get_label='name', allow_blank=True, blank_text=_("No type selected")) person_link_data = ContributionPersonLinkListField(_("People")) location_data = IndicoLocationField(_("Location")) keywords = IndicoTagListField(_('Keywords')) references = ReferencesField(_("External IDs"), reference_class=ContributionReference, description=_("Manage external resources for this contribution")) board_number = StringField(_("Board Number")) code = StringField(_('Programme code')) @generated_data def render_mode(self): return RenderMode.markdown def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.contrib = kwargs.pop('contrib', None) self.session_block = kwargs.get('session_block') self.timezone = self.event.timezone to_schedule = kwargs.pop('to_schedule', False) super(ContributionForm, self).__init__(*args, **kwargs) self.type.query = self.event.contribution_types if self.event.type != 'conference': self.person_link_data.label.text = _("Speakers") if not self.type.query.count(): del self.type if not to_schedule and (self.contrib is None or not self.contrib.is_scheduled): del self.start_dt def _get_earliest_start_dt(self): return self.session_block.start_dt if self.session_block else self.event.start_dt def _get_latest_start_dt(self): return self.session_block.end_dt if self.session_block else self.event.end_dt def validate_duration(self, field): start_dt = self.start_dt.data if self.start_dt else None if start_dt: end_dt = start_dt + field.data if self.session_block and end_dt > self.session_block.end_dt: raise ValidationError(_("With the current duration the contribution exceeds the block end date")) if end_dt > self.event.end_dt: raise ValidationError(_('With the current duration the contribution exceeds the event end date')) @property def custom_field_names(self): return tuple([field_name for field_name in self._fields if field_name.startswith('custom_')])
class RoomAssistanceRequestForm(RequestFormBase): start_dt = IndicoDateTimeField( _('When'), [DataRequired(), DateTimeRange(earliest=now_utc())], description=_('When do you need the assistance?')) reason = TextAreaField(_('Reason'), [DataRequired()], description=_('Why are you requesting assistance?')) def validate_start_dt(self, field): localized_time = field.data.astimezone(session.tzinfo).time() is_in_working_hours = WORKING_TIME_PERIOD[ 0] <= localized_time <= WORKING_TIME_PERIOD[1] if not is_in_working_hours: raise ValidationError( 'Specified datetime is not within the working hours')
class ReminderForm(IndicoForm): recipient_fields = {'recipients', 'send_to_participants'} schedule_fields = {'schedule_type', 'absolute_dt', 'relative_delta'} schedule_recipient_fields = recipient_fields | schedule_fields # Schedule schedule_type = IndicoRadioField( _('Type'), [DataRequired()], choices=[('relative', _("Relative to the event start time")), ('absolute', _("Fixed date/time")), ('now', _('Send immediately'))]) relative_delta = TimeDeltaField( _('Offset'), [HiddenUnless('schedule_type', 'relative'), DataRequired()]) absolute_dt = IndicoDateTimeField(_('Date'), [ HiddenUnless('schedule_type', 'absolute'), DataRequired(), DateTimeRange() ]) # Recipients recipients = EmailListField(_('Email addresses'), description=_('One email address per line.')) send_to_participants = BooleanField( _('Participants'), description=_('Send the reminder to all participants/registrants ' 'of the event.')) # Misc reply_to_address = SelectField( _('Sender'), [DataRequired()], description=_('The email address that will show up as the sender.')) message = TextAreaField( _('Note'), description=_('A custom message to include in the email.')) include_summary = BooleanField( _('Include agenda'), description=_( "Includes a simple text version of the event's agenda in the email." )) include_description = BooleanField( _('Include description'), description=_("Includes the event's description in the email.")) def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.timezone = self.event.timezone super().__init__(*args, **kwargs) self.reply_to_address.choices = (list( self.event.get_allowed_sender_emails( extra=self.reply_to_address.object_data).items())) if self.event.type_ == EventType.lecture: del self.include_summary def validate_recipients(self, field): if not field.data and not self.send_to_participants.data: raise ValidationError( _('If participants are not included you need to specify recipients.' )) def validate_send_to_participants(self, field): if not field.data and not self.recipients.data: raise ValidationError( _('If no recipients are specified you need to include participants.' )) def validate_schedule_type(self, field): # Be graceful and allow a reminder that's in the past but on the same day. # It will be sent immediately but that way we are a little bit more user-friendly if field.data == 'now': return scheduled_dt = self.scheduled_dt.data if scheduled_dt is not None and scheduled_dt.date() < now_utc().date(): raise ValidationError(_('The specified date is in the past')) @generated_data def scheduled_dt(self): if self.schedule_type.data == 'absolute': if self.absolute_dt.data is None: return None return self.absolute_dt.data elif self.schedule_type.data == 'relative': if self.relative_delta.data is None: return None return self.event.start_dt - self.relative_delta.data elif self.schedule_type.data == 'now': return now_utc() @generated_data def event_start_delta(self): return self.relative_delta.data if self.schedule_type.data == 'relative' else None