class _DateTimePair(IndicoForm): class Meta: csrf = False start_date = IndicoDateField( _(u'from'), [UsedIf(lambda form, field: form.end_date.data)]) start_time = TimeField(None, [Optional()]) end_date = IndicoDateField( _(u'to'), [UsedIf(lambda form, field: form.start_date.data)]) end_time = TimeField(None, [Optional()]) @property def start_dt(self): if self.start_date.data: return datetime.combine(self.start_date.data, self.start_time.data) else: return None @property def end_dt(self): if self.end_date.data: return datetime.combine(self.end_date.data, self.end_time.data) else: return None def validate_start(self, field): if self.start_dt and self.end_dt and self.start_dt >= self.end_dt: raise ValidationError( 'The start date must be earlier than the end date.') validate_end = validate_start
class VCRoomListFilterForm(IndicoForm): direction = SelectField(_('Sort direction'), [DataRequired()], choices=[('asc', _('Ascending')), ('desc', _('Descending'))]) abs_start_date = IndicoDateField( _('Start Date'), [Optional(), Exclusive('rel_start_date')]) abs_end_date = IndicoDateField( _('End Date'), [Optional(), Exclusive('rel_end_date')]) rel_start_date = IntegerField( _('Days in the past'), [Optional(), Exclusive('abs_start_date'), NumberRange(min=0)], default=0) rel_end_date = IntegerField( _('Days in the future'), [Optional(), Exclusive('abs_end_date'), NumberRange(min=0)], default=7) @generated_data def start_date(self): if self.abs_start_date.data is None and self.rel_start_date.data is None: return None return self.abs_start_date.data or ( date.today() - timedelta(days=self.rel_start_date.data)) @generated_data def end_date(self): if self.abs_end_date.data is None and self.rel_end_date.data is None: return None return self.abs_end_date.data or ( date.today() + timedelta(days=self.rel_end_date.data))
class BookingSearchForm(IndicoForm): room_ids = SelectMultipleField('Rooms', [DataRequired()], coerce=int) start_date = IndicoDateField('Start Date', [InputRequired()]) start_time = TimeField('Start Time', [InputRequired()]) end_date = IndicoDateField('End Date', [InputRequired()]) end_time = TimeField('End Time', [InputRequired()]) booked_for_name = StringField('Booked For Name') reason = StringField('Reason') is_only_mine = BooleanField('Only Mine') is_only_my_rooms = BooleanField('Only My Rooms') is_only_confirmed_bookings = BooleanField('Only Confirmed Bookings') is_only_pending_bookings = BooleanField('Only Prebookings') is_rejected = BooleanField('Is Rejected') is_cancelled = BooleanField('Is Cancelled') is_archived = BooleanField('Is Archived') uses_vc = BooleanField(_('Uses Videoconference')) needs_vc_assistance = BooleanField(_('Videoconference Setup Assistance')) needs_assistance = BooleanField('General Assistance') @generated_data def start_dt(self): return datetime.combine(self.start_date.data, self.start_time.data) @generated_data def end_dt(self): return datetime.combine(self.end_date.data, self.end_time.data)
class SearchForm(IndicoForm): phrase = StringField(_('Phrase')) field = SelectField(_('Search in'), choices=FIELD_CHOICES, default='') start_date = IndicoDateField('Start Date', [Optional()]) end_date = IndicoDateField('End Date', [Optional()]) def is_submitted(self): return 'search-phrase' in request.args
class CreateBlockingForm(BlockingForm): start_date = IndicoDateField(_(u'Start date'), [DataRequired()]) end_date = IndicoDateField(_(u'End date'), [DataRequired()]) def validate_start_date(self, field): if self.start_date.data > self.end_date.data: raise ValidationError('Blocking may not end before it starts!') validate_end_date = validate_start_date
class AccessIdentityDataForm(IndicoForm): birth_date = IndicoDateField(_('Birth date'), [DataRequired()]) nationality = SelectField(_('Country of birth'), [DataRequired()]) birth_place = StringField(_('Place of birth'), [DataRequired()]) by_car = BooleanField(_('Are you bringing your own car?'), [Optional()], widget=SwitchWidget()) license_plate = StringField( _('License plate'), [ HiddenUnless('by_car'), Length(min=3), IndicoRegexp(r'^[0-9A-Za-z]+([- ][ ]*[0-9A-Za-z]+)*$', message=_('Wrong format. Only letters and numbers separated by dashes (-) or spaces allowed')) ] ) def __init__(self, *args, **kwargs): super(AccessIdentityDataForm, self).__init__(*args, **kwargs) self.nationality.choices = [('', '')] + sorted(get_countries().iteritems(), key=itemgetter(1)) def validate_birth_date(self, field): if field.data > datetime.now().date(): raise ValidationError(_('The specified date is in the future')) def validate_license_plate(self, field): if self.by_car.data and not sanitize_license_plate(field.data): raise ValidationError(_('Please insert a valid license plate number!'))
class AttachmentPackageForm(IndicoForm): added_since = IndicoDateField( _('Added Since'), [Optional()], description=_('Include only attachments uploaded after this date')) filter_type = IndicoRadioField(_('Include'), [DataRequired()]) sessions = IndicoSelectMultipleCheckboxField( _('Sessions'), [ UsedIf(lambda form, _: form.filter_type.data == 'sessions'), DataRequired() ], description=_('Include materials from selected sessions'), coerce=int) contributions = IndicoSelectMultipleCheckboxField( _('Contributions'), [ UsedIf(lambda form, _: form.filter_type.data == 'contributions'), DataRequired() ], description=_('Include materials from selected contributions'), coerce=int) dates = IndicoSelectMultipleCheckboxField( _('Events scheduled on'), [ UsedIf(lambda form, _: form.filter_type.data == 'dates'), DataRequired() ], description=_( 'Include materials from sessions/contributions scheduled ' 'on the selected dates'))
class AccessIdentityDataForm(IndicoForm): birth_date = IndicoDateField(_('Birth date'), [DataRequired()]) nationality = SelectField(_('Country of birth'), [DataRequired()]) birth_place = StringField(_('Place of birth'), [DataRequired()]) def __init__(self, *args, **kwargs): super(AccessIdentityDataForm, self).__init__(*args, **kwargs) self.nationality.choices = [('', '')] + sorted(get_countries().iteritems(), key=itemgetter(1)) def validate_birth_date(self, field): if field.data > datetime.now().date(): raise ValidationError(_('The specified date is in the future'))
class CloneRepeatUntilFormBase(CloneRepeatOnceForm): stop_criterion = IndicoRadioField(_('Clone'), [DataRequired()], default='num_times', choices=(('day', _('Until a given day (inclusive)')), ('num_times', _('A number of times')))) until_dt = IndicoDateField(_('Day'), [HiddenUnless('stop_criterion', 'day'), DataRequired()]) num_times = IntegerField(_('Number of times'), [HiddenUnless('stop_criterion', 'num_times'), DataRequired(), NumberRange(1, 100, message=_("You can clone a maximum of 100 times"))], default=2) def __init__(self, event, **kwargs): kwargs.setdefault('until_dt', (self._calc_start_dt(event) + timedelta(days=14)).date()) super().__init__(event, **kwargs)
class RequestListFilterForm(IndicoForm): direction = SelectField(_('Sort direction'), [DataRequired()], choices=[('asc', _('Ascending')), ('desc', _('Descending'))]) granularity = SelectField(_('Granularity'), [DataRequired()], choices=[('events', _('Events')), ('talks', _('Talks'))]) state = IndicoEnumSelectField(_('Request state'), enum=RequestState, skip={RequestState.withdrawn}, none=_('Any state')) abs_start_date = IndicoDateField( _('Start Date'), [Optional(), Exclusive('rel_start_date')]) abs_end_date = IndicoDateField( _('End Date'), [Optional(), Exclusive('rel_end_date')]) rel_start_date = IntegerField( _('Days in the past'), [Optional(), Exclusive('abs_start_date'), NumberRange(min=0)]) rel_end_date = IntegerField( _('Days in the future'), [Optional(), Exclusive('abs_end_date'), NumberRange(min=0)]) @generated_data def start_date(self): if self.abs_start_date.data is None and self.rel_start_date.data is None: return None return self.abs_start_date.data or ( date.today() - timedelta(days=self.rel_start_date.data)) @generated_data def end_date(self): if self.abs_end_date.data is None and self.rel_end_date.data is None: return None return self.abs_end_date.data or ( date.today() + timedelta(days=self.rel_end_date.data))
class ReminderForm(IndicoForm): default_widget_attrs = {'absolute_time': {'placeholder': 'HH:MM'}} recipient_fields = {'recipients', 'send_to_participants'} schedule_fields = { 'schedule_type', 'absolute_date', 'absolute_time', '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_date = IndicoDateField( _('Date'), [HiddenUnless('schedule_type', 'absolute'), DataRequired()]) absolute_time = TimeField( _('Time'), [HiddenUnless('schedule_type', 'absolute'), InputRequired()]) # 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') super(ReminderForm, self).__init__(*args, **kwargs) self.absolute_time.description = _( "The event's timezone is {tz}.").format(tz=self.event.tzinfo) self.reply_to_address.choices = (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')) def validate_absolute_date(self, field): if self.schedule_type.data == 'absolute' and field.data < date.today(): raise ValidationError(_('The specified date is in the past')) @generated_data def scheduled_dt(self): if self.schedule_type.data == 'absolute': if self.absolute_date.data is None or self.absolute_time.data is None: return None dt = datetime.combine(self.absolute_date.data, self.absolute_time.data) return self.event.tzinfo.localize(dt).astimezone(pytz.utc) 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