コード例 #1
0
class ContributionDurationForm(IndicoForm):
    duration = TimeDeltaField(
        _('Duration'),
        [DataRequired(), MaxDuration(timedelta(days=1))],
        default=timedelta(minutes=20),
        units=('minutes', 'hours'))

    def __init__(self, *args, **kwargs):
        self.contrib = kwargs.pop('contrib')
        super(ContributionDurationForm, self).__init__(*args, **kwargs)

    def validate_duration(self, field):
        if field.errors:
            return
        if self.contrib.is_scheduled:
            event = self.contrib.event_new
            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)
コード例 #2
0
class PluginSettingsForm(IndicoForm):
    adams_url = URLField(_('ADaMS URL'), [DataRequired()],
                         description=_('The URL of the ADaMS REST API'))
    username = StringField(_('Username'), [DataRequired()],
                           description=_('The login used to authenticate with ADaMS service'))
    password = IndicoPasswordField(_('Password'), [DataRequired()],
                                   description=_('The password used to authenticate with ADaMS service'))
    secret_key = IndicoPasswordField(_('Secret key'), [DataRequired()],
                                     description=_('Secret key to sign ADaMS requests'))
    authorized_users = PrincipalListField(_('Authorized users'), allow_groups=True,
                                          description=_('List of users/groups who can send requests'))
    excluded_categories = MultipleItemsField('Excluded categories', fields=[{'id': 'id', 'caption': 'Category ID'}])
    access_ticket_template = QuerySelectField(_("Access ticket template"), allow_blank=True,
                                              blank_text=_("No access ticket selected"), get_label='title',
                                              description=_("Ticket template allowing access to CERN"))
    earliest_start_dt = IndicoDateTimeField(_("Earliest start date"), [Optional()], default_time=time(0, 0),
                                            description=_("The earliest date an event can start to qualify for CERN "
                                                          "access badges"))
    delete_personal_data_after = TimeDeltaField(_('Delete personal data'), [DataRequired()], units=('days',),
                                                description=_('Personal data will be deleted once the event has '
                                                              'finished and the duration specified here has been '
                                                              'exceeded. Once the data has been deleted, access badges '
                                                              'will not be accessible anymore.'))
    api_username = StringField(_('Username'), [DataRequired()], description=_('The username to access the API'))
    api_password = IndicoPasswordField(_('Password'), [DataRequired()], toggle=True,
                                       description=_('The password to access the API'))

    def __init__(self, *args, **kwargs):
        super(PluginSettingsForm, self).__init__(*args, **kwargs)
        self.access_ticket_template.query = (DesignerTemplate.query
                                             .filter(DesignerTemplate.category_id == 0,
                                                     DesignerTemplate.type == TemplateType.badge)
                                             .order_by(db.func.lower(DesignerTemplate.title)))
コード例 #3
0
class SubContributionForm(IndicoForm):
    title = StringField(_('Title'), [DataRequired()])
    description = TextAreaField(_('Description'))
    duration = TimeDeltaField(
        _('Duration'),
        [DataRequired(), MaxDuration(timedelta(hours=24))],
        default=timedelta(minutes=20),
        units=('minutes', 'hours'))
    speakers = SubContributionPersonLinkListField(
        _('Speakers'),
        allow_submitters=False,
        description=_('The speakers of the subcontribution'))
    references = ReferencesField(
        _("External IDs"),
        reference_class=SubContributionReference,
        description=_("Manage external resources for this sub-contribution"))

    @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(SubContributionForm, self).__init__(*args, **kwargs)
コード例 #4
0
ファイル: forms.py プロジェクト: vintas/indico
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 = TimeDeltaField(
        _('Default contribution duration'),
        units=('minutes', 'hours'),
        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(SessionForm, self).__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
コード例 #5
0
ファイル: forms.py プロジェクト: ipaste/indico
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 = TimeDeltaField(
        _('Default contribution duration'),
        units=('minutes', 'hours'),
        description=_('Duration that a contribution created within this '
                      'session will have by default.'),
        default=timedelta(minutes=20))
    location_data = IndicoLocationField(
        _("Default location"),
        description=_("Default location for blocks inside the session."))
    colors = IndicoPalettePickerField(_('Colours'), color_list=get_colors())
    is_poster = BooleanField(
        _('Poster session'),
        widget=SwitchWidget(),
        description=
        _('Whether the session is a poster session or contains normal presentations.'
          ))

    def __init__(self, *args, **kwargs):
        event = kwargs.pop('event')
        super(SessionForm, self).__init__(*args, **kwargs)
        if event.type != 'conference':
            del self.is_poster
            del self.code
コード例 #6
0
ファイル: forms.py プロジェクト: tobiashuste/indico
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_')])
コード例 #7
0
class EntryFormMixin:
    _entry_type = None
    _default_duration = None
    _display_fields = None

    time = IndicoTimeField(_("Start time"), [InputRequired()])
    duration = TimeDeltaField(_("Duration"), [DataRequired(), MaxDuration(timedelta(hours=24))],
                              units=('minutes', 'hours'))

    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
コード例 #8
0
class EntryFormMixin(object):
    _entry_type = None
    _default_duration = None
    _display_fields = None

    time = TimeField(_("Start time"), [InputRequired()])
    duration = TimeDeltaField(
        _("Duration"),
        [DataRequired(), MaxDuration(timedelta(hours=24))],
        units=('minutes', 'hours'))

    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:
                defaults.duration = self._default_duration
                kwargs['obj'] = defaults
        super(EntryFormMixin, self).__init__(*args, **kwargs)

    @property
    def data(self):
        data = super(EntryFormMixin, self).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):
        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
コード例 #9
0
class SettingsForm(IndicoForm):
    debug = BooleanField(
        _('Debug mode'),
        widget=SwitchWidget(),
        description=_(
            "If enabled, requests are not sent to the API but logged instead"))
    service_url = URLField(
        _('Service URL'), [URL(require_tld=False)],
        description=_("The URL of the CERN calendar service"))
    username = StringField(
        _('Username'), [DataRequired()],
        description=_(
            "The username used to authenticate with the CERN calendar service")
    )
    password = IndicoPasswordField(
        _('Password'), [DataRequired()],
        toggle=True,
        description=_(
            "The password used to authenticate with the CERN calendar service")
    )
    status = SelectField(
        _('Status'), [DataRequired()],
        choices=_status_choices,
        description=_("The default status of the event in the calendar"))
    reminder = BooleanField(_('Reminder'),
                            description=_("Enable calendar reminder"))
    reminder_minutes = IntegerField(
        _('Reminder time'), [NumberRange(min=0)],
        description=_("Remind users X minutes before the event"))
    id_prefix = StringField(
        _('Prefix'),
        description=_(
            "Prefix for calendar item IDs. If you change this, existing calendar entries "
            "cannot be deleted/updated anymore!"))
    timeout = FloatField(_('Request timeout'), [NumberRange(min=0.25)],
                         description=_("Request timeout in seconds"))
    max_event_duration = TimeDeltaField(
        _('Maximum Duration'), [DataRequired()],
        units=('days', ),
        description=_('Events lasting longer will not be sent to Exchange'))
コード例 #10
0
ファイル: forms.py プロジェクト: tobiashuste/indico
class ContributionDefaultDurationForm(IndicoForm):
    duration = TimeDeltaField(_('Duration'), [DataRequired(), MaxDuration(timedelta(days=1))],
                              units=('minutes', 'hours'))
コード例 #11
0
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
コード例 #12
0
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 = DateField(
        _('Date'), [HiddenUnless('schedule_type', 'absolute'),
                    DataRequired()],
        parse_kwargs={'dayfirst': True})
    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."
        ))

    def __init__(self, *args, **kwargs):
        self.event = kwargs.pop('event')
        super(ReminderForm, self).__init__(*args, **kwargs)
        self.absolute_time.description = _(
            'Your active timezone is {tz}.').format(tz=self.timezone)
        self._set_email_choices()
        if self.event.getType() == 'simple_event':
            del self.include_summary

    def _set_email_choices(self):
        # User
        emails = {session.user.email: session.user.full_name}
        # Creator
        emails[self.event.as_event.creator.
               email] = self.event.as_event.creator.full_name
        # Support
        support = self.event.getSupportInfo()
        emails[support.getEmail()] = support.getCaption() or support.getEmail()
        # Chairs
        emails.update((pl.email, pl.full_name)
                      for pl in self.event.as_event.person_links if pl.email)
        # Current email to avoid destructive modifications
        emails.setdefault(self.reply_to_address.object_data,
                          self.reply_to_address.object_data)
        # Sanitize and format emails
        emails = {
            to_unicode(email.strip().lower()):
            '{} <{}>'.format(to_unicode(name), to_unicode(email))
            for email, name in emails.iteritems() if email and email.strip()
        }
        self.reply_to_address.choices = sorted(
            emails.items(),
            key=lambda x: (x[0] != session.user.email, x[1].lower()))

    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'))

    @property
    def timezone(self):
        return DisplayTZ(conf=self.event).getDisplayTZ()

    @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 get_timezone(self.timezone).localize(dt).astimezone(
                pytz.utc)
        elif self.schedule_type.data == 'relative':
            if self.relative_delta.data is None:
                return None
            return self.event.getStartDate() - 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