diff --git a/CHANGES.rst b/CHANGES.rst
index e1a8451e14d..0b4b8d644a0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -11,6 +11,7 @@ Improvements
^^^^^^^^^^^^
- Display program codes in 'My contributions' (:pr:`5573`)
+- Warn when a user cannot create an event in the current category (:pr:`5572`)
Bugfixes
^^^^^^^^
diff --git a/indico/modules/categories/fields.py b/indico/modules/categories/fields.py
index 7ab5f265f2c..51924dd05d3 100644
--- a/indico/modules/categories/fields.py
+++ b/indico/modules/categories/fields.py
@@ -25,7 +25,7 @@ class CategoryField(HiddenField):
widget = JinjaWidget('forms/category_picker_widget.html')
def __init__(self, *args, **kwargs):
- self.navigator_category_id = 0
+ self.navigator_category_id = None
self.require_event_creation_rights = kwargs.pop('require_event_creation_rights', False)
super().__init__(*args, **kwargs)
diff --git a/indico/modules/events/client/js/creation.js b/indico/modules/events/client/js/creation.js
index d527d9d5896..58fc0187489 100644
--- a/indico/modules/events/client/js/creation.js
+++ b/indico/modules/events/client/js/creation.js
@@ -33,7 +33,10 @@ import {camelizeKeys} from 'indico/utils/case';
const messages = $($.parseHTML($('#event-creation-protection-messages').html()));
const protectionMessage = $('
', {class: 'form-group', css: {marginTop: '5px'}});
const listingMessage = $($.parseHTML($('#event-listing-message').html()));
+ const eventCreationMessage = $($.parseHTML($('#event-creation-message').html()));
+ const $form = options.categoryField.closest('form');
+ const $submitBtn = $form.find('input[type="submit"]').first();
const $createBooking = $('#event-creation-create_booking');
const $availableMessage = $('#room-available');
const $availablePrebookMessage = $('#room-available-prebook');
@@ -55,8 +58,30 @@ import {camelizeKeys} from 'indico/utils/case';
let multipleOccurrences = false;
protectionMessage.appendTo(options.protectionModeFields.closest('.form-field'));
+ eventCreationMessage.insertAfter($('#category-warning-event-creation-category'));
listingMessage.appendTo($listingField.closest('.form-field'));
+ $submitBtn.prop('disabled', true);
+ $form.on('change input', updateSubmitBtn);
+
+ function canCreateInSelectedCategory() {
+ return (
+ options.canCreateEvents ||
+ // unlisted events or no default category
+ !currentCategory ||
+ // categories other than the initial one cannot be selected unless the user can create events in them
+ currentCategory?.id !== options.initialCategory?.id
+ );
+ }
+
+ // like disabled-until-change but also disables submit when the user
+ // does not have the rights to create events in the selected category
+ function updateSubmitBtn() {
+ const untouched = $.param($form.serializeArray(), true) === $form.data('initialData');
+ const disabled = untouched || !canCreateInSelectedCategory();
+ $submitBtn.prop('disabled', disabled);
+ }
+
function updateProtectionMessage() {
if (!currentCategory) {
protectionMessage.html('');
@@ -71,11 +96,9 @@ import {camelizeKeys} from 'indico/utils/case';
protectionMessage.html(elem);
}
- function updateWarningMessage() {
- $(`#category-warning-event-creation-category`).toggleClass(
- 'hidden',
- (currentCategory && currentCategory.has_events) || !currentCategory
- );
+ // Display a warning if the user does not have the rights to create events in the selected category
+ function updateEventCreationMessage() {
+ eventCreationMessage.toggleClass('hidden', canCreateInSelectedCategory());
}
options.categoryField.on('indico:categorySelected', (evt, cat) => {
@@ -90,6 +113,8 @@ import {camelizeKeys} from 'indico/utils/case';
}
currentCategory = cat;
updateProtectionMessage();
+ updateEventCreationMessage();
+ updateSubmitBtn();
});
$listingField.on('change', evt => {
@@ -108,9 +133,8 @@ import {camelizeKeys} from 'indico/utils/case';
options.categoryField.trigger('indico:categorySelected', []);
}
- // update listing and warning message boxes
+ // update listing
listingMessage.toggleClass('hidden', JSON.parse($listingField.val()));
- updateWarningMessage();
});
options.protectionModeFields.on('change', function() {
diff --git a/indico/modules/events/controllers/creation.py b/indico/modules/events/controllers/creation.py
index e631551d9a0..29c26f98a77 100644
--- a/indico/modules/events/controllers/creation.py
+++ b/indico/modules/events/controllers/creation.py
@@ -156,10 +156,13 @@ def _process(self):
return jsonify_data(flash=False, redirect=url_for('event_management.settings', event))
check_room_availability = rb_check_user_access(session.user) and config.ENABLE_ROOMBOOKING
rb_excluded_categories = [c.id for c in rb_settings.get('excluded_categories')]
+ category = self._default_category
+ can_create_events = category.can_create_events(session.user) if category else True
return jsonify_template('events/forms/event_creation_form.html', form=form, fields=form._field_order,
event_type=self.event_type.name, single_category=(not self.root_category.has_children),
check_room_availability=check_room_availability,
rb_excluded_categories=rb_excluded_categories,
+ can_create_events=can_create_events,
can_create_unlisted_events=can_create_unlisted_events(session.user))
diff --git a/indico/modules/events/templates/forms/event_creation_form.html b/indico/modules/events/templates/forms/event_creation_form.html
index c47f4f741fc..848e148d68a 100644
--- a/indico/modules/events/templates/forms/event_creation_form.html
+++ b/indico/modules/events/templates/forms/event_creation_form.html
@@ -2,7 +2,8 @@
{% set category = {'id': form.category.data.id,
'is_protected': form.category.data.is_protected,
'title': form.category.data.title,
- 'has_events': form.category.data.has_events} if form.category.data else none %}
+ 'has_events': form.category.data.has_events,
+ 'has_children': form.category.data.has_children} if form.category.data else none %}
{{ form_header(form, action=url_for('events.create', event_type=event_type)) }}
{% if can_create_unlisted_events %}
@@ -16,8 +17,7 @@
{% endcall %}
{% endif %}
{% call form_footer(form) %}
-
+
{% endcall %}
@@ -110,11 +110,25 @@
+
+