Skip to content

Commit

Permalink
Warn when user cannot create events (indico#5572)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasr8 authored Nov 24, 2022
1 parent f0f318c commit fa2db1e
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion indico/modules/categories/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
38 changes: 31 additions & 7 deletions indico/modules/events/client/js/creation.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ import {camelizeKeys} from 'indico/utils/case';
const messages = $($.parseHTML($('#event-creation-protection-messages').html()));
const protectionMessage = $('<div>', {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');
Expand All @@ -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('');
Expand All @@ -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) => {
Expand All @@ -90,6 +113,8 @@ import {camelizeKeys} from 'indico/utils/case';
}
currentCategory = cat;
updateProtectionMessage();
updateEventCreationMessage();
updateSubmitBtn();
});

$listingField.on('change', evt => {
Expand All @@ -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() {
Expand Down
3 changes: 3 additions & 0 deletions indico/modules/events/controllers/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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))


Expand Down
20 changes: 17 additions & 3 deletions indico/modules/events/templates/forms/event_creation_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -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 %}
Expand All @@ -16,8 +17,7 @@
{% endcall %}
{% endif %}
{% call form_footer(form) %}
<input class="i-button big highlight" type="submit" value="{% trans %}Create event{% endtrans %}"
data-disabled-until-change>
<input class="i-button big highlight" type="submit" value="{% trans %}Create event{% endtrans %}">
<button type="button" class="i-button big" data-button-back>{% trans %}Cancel{% endtrans %}</button>
{% endcall %}

Expand Down Expand Up @@ -110,11 +110,25 @@
</div>
</script>

<script type="text/html" id="event-creation-message">
<div class="action-box mid-form for-form danger hidden">
<div class="section">
<div class="icon icon-warning"></div>
<div class="text">
<div>
{% trans %}You are not allowed to create events in this category.{% endtrans %}
</div>
</div>
</div>
</div>
</script>

<script>
setupEventCreationDialog({
categoryField: $('#{{ form.category.id }}'),
protectionModeFields: $('input[name="{{ form.protection_mode.name }}"][id^="{{ form.protection_mode.id }}"]'),
initialCategory: {{ category | tojson }},
canCreateEvents: {{ can_create_events | tojson }},
checkAvailability: {{ check_room_availability | tojson }},
rbExcludedCategories: {{ rb_excluded_categories | tojson }},
serverDefaultTimezone: {{ indico_config.DEFAULT_TIMEZONE | tojson }}
Expand Down
43 changes: 27 additions & 16 deletions indico/web/client/js/jquery/widgets/jinja/category_picker_widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,23 @@
$field.val(JSON.stringify(hiddenData));
}

$.ajax({
url: build_url(Indico.Urls.Categories.info, {category_id: navigatorCategory}),
dataType: 'json',
error: handleAjaxError,
success(data) {
navigatorCategory = data;
const {category} = navigatorCategory;
$categoryWarning.toggleClass(
'hidden',
!category.has_children ||
category.has_events ||
// match the emptying of category field when root category has no events (done in RHCreateEvent)
(!category.has_events && category.id === 0)
);
},
// null when we are in the root category and the root only has subcategories
// See RHCreateEvent._default_category
if (navigatorCategory !== null) {
$.ajax({
url: build_url(Indico.Urls.Categories.info, {category_id: navigatorCategory}),
dataType: 'json',
error: handleAjaxError,
success(data) {
navigatorCategory = data;
const {category} = navigatorCategory;
updateWarningVisibility(category);
},
});
}

$field.on('indico:categorySelected', (evt, category) => {
updateWarningVisibility(category);
});

$dialogTrigger.on('click', function(evt) {
Expand All @@ -63,7 +65,7 @@
onAction(category) {
const event = $.Event('indico:categorySelected');
const dfd = $.Deferred();
$categoryWarning.toggleClass('hidden', !category.has_children || category.has_events);
updateWarningVisibility(category);
$categoryTitle.text(category.title);
hiddenData = {id: category.id, title: category.title};
navigatorCategory = category.id;
Expand All @@ -77,5 +79,14 @@
},
});
});

function updateWarningVisibility(category) {
$categoryWarning.toggleClass(
'hidden',
!category || // unlisted event or no category selected
!category.has_children ||
category.has_events
);
}
};
})(window);
19 changes: 13 additions & 6 deletions indico/web/templates/forms/category_picker_widget.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@
<div>
<div id="category-title-{{ field.id }}" class="text-holder-box flexrow f-a-center" data-tooltip-anchor></div>
<div id="category-warning-{{ field.id }}" class="hidden">
{% call message_box('warning') %}
{% trans %}
The selected category does not contain any events, only subcategories.
Please make sure that you really want to create an event there.
{% endtrans %}
{% endcall %}
<div class="action-box mid-form for-form warning">
<div class="section">
<div class="icon icon-warning"></div>
<div class="text">
<div>
{% trans %}
The selected category does not contain any events, only subcategories.
Please make sure that you really want to create an event there.
{% endtrans %}
</div>
</div>
</div>
</div>
</div>
<button type="button"
class="i-button"
Expand Down

0 comments on commit fa2db1e

Please sign in to comment.