class ContributionDurationForm(IndicoForm): duration = IndicoDurationField( _('Duration'), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20)) def __init__(self, *args, **kwargs): self.contrib = kwargs.pop('contrib') super().__init__(*args, **kwargs) def validate_duration(self, field): if field.errors: return if self.contrib.is_scheduled: 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 duration, the contribution would exceed the event end time.' ) else: latest_dt = get_day_end(day, tzinfo=event.tzinfo) error_msg = _( 'With this duration, the contribution would exceed the current day.' ) if self.contrib.start_dt + field.data > latest_dt: raise ValidationError(error_msg)
class SubContributionForm(IndicoForm): title = StringField(_('Title'), [DataRequired()]) description = TextAreaField(_('Description')) duration = IndicoDurationField( _('Duration'), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20)) speakers = SubContributionPersonLinkListField( _('Speakers'), allow_submitters=False, allow_authors=False, description=_('The speakers of the subcontribution')) references = ReferencesField( _('External IDs'), reference_class=SubContributionReference, description=_('Manage external resources for this sub-contribution')) code = StringField(_('Program code')) @generated_data def render_mode(self): return RenderMode.markdown def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.subcontrib = kwargs.pop('subcontrib', None) super().__init__(*args, **kwargs)
class SessionForm(IndicoForm): title = StringField(_('Title'), [DataRequired()]) code = StringField( _('Session code'), description=_('The code that will identify the session in the Book of ' 'Abstracts.')) description = TextAreaField(_('Description')) default_contribution_duration = IndicoDurationField( _('Default contribution duration'), description=_('Duration that a contribution created within ' 'this session will have by default.'), default=timedelta(minutes=20)) type = QuerySelectField(_("Type"), get_label='name', allow_blank=True, blank_text=_("No type selected")) location_data = IndicoLocationField( _("Default location"), description=_("Default location for blocks inside the session.")) colors = IndicoPalettePickerField(_('Colours'), color_list=get_colors()) def __init__(self, *args, **kwargs): event = kwargs.pop('event') super().__init__(*args, **kwargs) if event.type != 'conference': del self.code del self.type else: self.type.query = SessionType.query.with_parent(event) if not self.type.query.has_rows(): del self.type
class EntryFormMixin: _entry_type = None _default_duration = None _display_fields = None time = IndicoTimeField(_("Start time"), [InputRequired()]) duration = IndicoDurationField(_('Duration'), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20)) def __init__(self, *args, **kwargs): self.event = kwargs['event'] self.session_block = kwargs.get('session_block') self.day = kwargs.pop('day') if self._default_duration is not None: kwargs.setdefault('time', self._get_default_time()) defaults = kwargs.get('obj') or FormDefaults() if 'duration' not in defaults: if self._entry_type == TimetableEntryType.CONTRIBUTION and self.session_block: defaults.duration = self.session_block.session.default_contribution_duration else: defaults.duration = self._default_duration kwargs['obj'] = defaults super().__init__(*args, **kwargs) @property def data(self): data = super().data del data['time'] return data @generated_data def start_dt(self): if self.time.data is not None: dt = datetime.combine(self.day, self.time.data) return self.event.tzinfo.localize(dt).astimezone(utc) def validate_duration(self, field): if not self.start_dt.data: return end_dt = self.start_dt.data + field.data if end_dt.astimezone(self.event.tzinfo).date() > self.event.end_dt_local.date(): raise ValidationError(_("{} exceeds current day. Adjust start time or duration.") .format(self._entry_type.title.capitalize())) def _get_default_time(self): if self.session_block: # inside a block we suggest right after the latest contribution # or fall back to the block start time if it's empty entry = self.session_block.timetable_entry start_dt = max(x.end_dt for x in entry.children) if entry.children else entry.start_dt else: # outside a block we find the first slot where a contribution would fit start_dt = find_next_start_dt(self._default_duration, obj=self.session_block or self.event, day=None if self.session_block else self.day) return start_dt.astimezone(self.event.tzinfo).time() if start_dt else None
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 = IndicoDurationField( _('Duration'), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20)) 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(_('Program 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().__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 ContributionDefaultDurationForm(IndicoForm): duration = IndicoDurationField( _('Duration'), [DataRequired(), MaxDuration(timedelta(hours=24))], default=timedelta(minutes=20))