diff --git a/CHANGES.rst b/CHANGES.rst index a63019993a2..d15a123c704 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -24,6 +24,8 @@ Improvements - Allow specifying a default session for a track which will then be used by default when accepting an abstract in that track (:issue:`3069`) +- Allow marking contribution types as private so they cannot be selected + by users submitting an abstract (:issue:`3138`) Internal Changes ^^^^^^^^^^^^^^^^ diff --git a/indico/migrations/versions/20171101_1149_566d5de4e0e5_add_is_private_column_to_contribution_types.py b/indico/migrations/versions/20171101_1149_566d5de4e0e5_add_is_private_column_to_contribution_types.py new file mode 100644 index 00000000000..ee990c017a1 --- /dev/null +++ b/indico/migrations/versions/20171101_1149_566d5de4e0e5_add_is_private_column_to_contribution_types.py @@ -0,0 +1,29 @@ +"""Add is_private column to contribution types table + +Revision ID: 566d5de4e0e5 +Revises: 1d512a9ebb30 +Create Date: 2017-11-01 11:49:47.532339 +""" + +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision = '566d5de4e0e5' +down_revision = '1d512a9ebb30' +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + 'contribution_types', + sa.Column('is_private', sa.Boolean(), nullable=False, server_default='false'), + schema='events' + ) + op.alter_column('contribution_types', 'is_private', server_default=None, schema='events') + + +def downgrade(): + op.drop_column('contribution_types', 'is_private', schema='events') diff --git a/indico/modules/events/abstracts/controllers/abstract.py b/indico/modules/events/abstracts/controllers/abstract.py index 7cb89376c6d..e7546ba58cf 100644 --- a/indico/modules/events/abstracts/controllers/abstract.py +++ b/indico/modules/events/abstracts/controllers/abstract.py @@ -52,7 +52,7 @@ def _process(self): abstract_form_class = make_abstract_form(self.event, management=self.management) custom_field_values = {'custom_{}'.format(x.contribution_field_id): x.data for x in self.abstract.field_values} defaults = FormDefaults(self.abstract, attachments=self.abstract.files, **custom_field_values) - form = abstract_form_class(obj=defaults, abstract=self.abstract, event=self.event) + form = abstract_form_class(obj=defaults, abstract=self.abstract, event=self.event, management=self.management) if form.validate_on_submit(): update_abstract(self.abstract, *get_field_values(form.data)) flash(_("Abstract modified successfully"), 'success') diff --git a/indico/modules/events/abstracts/controllers/abstract_list.py b/indico/modules/events/abstracts/controllers/abstract_list.py index cdfa48d9efe..6cb8145e2ac 100644 --- a/indico/modules/events/abstracts/controllers/abstract_list.py +++ b/indico/modules/events/abstracts/controllers/abstract_list.py @@ -117,7 +117,7 @@ def _process(self): class RHCreateAbstract(RHAbstractListBase): def _process(self): abstract_form_class = make_abstract_form(self.event, notification_option=True, management=self.management) - form = abstract_form_class(event=self.event) + form = abstract_form_class(event=self.event, management=self.management) if form.validate_on_submit(): data = form.data send_notifications = data.pop('send_notifications') diff --git a/indico/modules/events/abstracts/controllers/display.py b/indico/modules/events/abstracts/controllers/display.py index 7a46775f846..205481e561c 100644 --- a/indico/modules/events/abstracts/controllers/display.py +++ b/indico/modules/events/abstracts/controllers/display.py @@ -69,7 +69,7 @@ def _check_access(self): def _process(self): abstract_form_class = make_abstract_form(self.event, management=self.management) - form = abstract_form_class(event=self.event) + form = abstract_form_class(event=self.event, management=self.management) if form.validate_on_submit(): abstract = create_abstract(self.event, *get_field_values(form.data), send_notifications=True) flash(_("Your abstract '{}' has been successfully submitted. It is registered with the number " diff --git a/indico/modules/events/abstracts/forms.py b/indico/modules/events/abstracts/forms.py index efedc099c63..791b3b63f11 100644 --- a/indico/modules/events/abstracts/forms.py +++ b/indico/modules/events/abstracts/forms.py @@ -467,6 +467,7 @@ class AbstractForm(IndicoForm): def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.abstract = kwargs.pop('abstract', None) + management = kwargs.pop('management', False) description_settings = abstracts_settings.get(self.event, 'description_settings') description_validators = self._get_description_validators(description_settings) if description_validators: @@ -474,7 +475,13 @@ def __init__(self, *args, **kwargs): if abstracts_settings.get(self.event, 'contrib_type_required'): inject_validators(self, 'submitted_contrib_type', [DataRequired()]) super(AbstractForm, self).__init__(*args, **kwargs) - self.submitted_contrib_type.query = self.event.contribution_types + if management: + self.submitted_contrib_type.query = self.event.contribution_types + else: + criteria = [~ContributionType.is_private] + if self.abstract and self.abstract.submitted_contrib_type: + criteria.append(ContributionType.id == self.abstract.submitted_contrib_type.id) + self.submitted_contrib_type.query = self.event.contribution_types.filter(db.or_(*criteria)) if not self.submitted_contrib_type.query.count(): del self.submitted_contrib_type if not self.event.cfa.allow_attachments: diff --git a/indico/modules/events/contributions/forms.py b/indico/modules/events/contributions/forms.py index 6a4e5170097..6cd11ff38fc 100644 --- a/indico/modules/events/contributions/forms.py +++ b/indico/modules/events/contributions/forms.py @@ -19,7 +19,7 @@ from datetime import timedelta from wtforms.ext.sqlalchemy.fields import QuerySelectField -from wtforms.fields import StringField, TextAreaField +from wtforms.fields import BooleanField, StringField, TextAreaField from wtforms.validators import DataRequired, ValidationError from indico.core.db import db @@ -36,6 +36,7 @@ from indico.web.forms.fields import (AccessControlListField, IndicoDateTimeField, IndicoLocationField, IndicoProtectionField, IndicoTagListField, PrincipalListField, TimeDeltaField) from indico.web.forms.validators import DateTimeRange, MaxDuration, UsedIf +from indico.web.forms.widgets import SwitchWidget class ContributionForm(IndicoForm): @@ -187,6 +188,9 @@ class ContributionTypeForm(IndicoForm): """Form to create or edit a ContributionType""" name = StringField(_("Name"), [DataRequired()]) + is_private = BooleanField(_("Private"), widget=SwitchWidget(), + description=_("If selected, this contribution type cannot be chosen by users " + "submitting an abstract.")) description = TextAreaField(_("Description")) def __init__(self, *args, **kwargs): diff --git a/indico/modules/events/contributions/models/types.py b/indico/modules/events/contributions/models/types.py index 5612ca9b9bd..030acbe16a9 100644 --- a/indico/modules/events/contributions/models/types.py +++ b/indico/modules/events/contributions/models/types.py @@ -51,6 +51,11 @@ def __table_args__(cls): nullable=False, default='' ) + is_private = db.Column( + db.Boolean, + nullable=False, + default=False + ) event = db.relationship( 'Event', diff --git a/indico/modules/events/contributions/templates/management/_types_table.html b/indico/modules/events/contributions/templates/management/_types_table.html index bd679a0ad8a..6572406fc3d 100644 --- a/indico/modules/events/contributions/templates/management/_types_table.html +++ b/indico/modules/events/contributions/templates/management/_types_table.html @@ -2,6 +2,7 @@ {{ contrib_type.name }} {{ contrib_type.description }} + {{ _('Yes') if contrib_type.is_private else _('No') }} {% trans %}Description{% endtrans %} + + {% trans %}Private{% endtrans %} +