diff --git a/src/backoffice/locale/de/LC_MESSAGES/django.po b/src/backoffice/locale/de/LC_MESSAGES/django.po index cbe5fdbb32759f1883961f6aa1c60db3e1f41672..67f12b5e089629e86c64a8985c5285d280ba798d 100644 --- a/src/backoffice/locale/de/LC_MESSAGES/django.po +++ b/src/backoffice/locale/de/LC_MESSAGES/django.po @@ -1874,6 +1874,9 @@ msgstr "Konferenz" msgid "Conference__Publication" msgstr "Veröffentlichung" +msgid "Conference__Registration" +msgstr "Assembly Registrierung" + msgid "Conference__publish__success" msgstr "Die Konferenz wurde erfolgreich veröffentlicht! Viel Spaß!" @@ -1892,6 +1895,9 @@ msgstr "Beim veröffentlichen der Konferenz ist ein Fehler aufgetreten" msgid "Conference__form__invalid" msgstr "Die angegebenen Daten zur Konferenz sind fehlerhaft!" +msgid "Conference__registration_update__success" +msgstr "Die Registrierungsinformationen der Konferenz wurden angepasst." + #, python-format msgid "Event__publish__failed %(event_type)s" msgstr "Fehler beim veröffentlichen der %(event_type)s!" diff --git a/src/backoffice/locale/en/LC_MESSAGES/django.po b/src/backoffice/locale/en/LC_MESSAGES/django.po index 9b36b74b224e47ac947cb0bd56aac286e5dec2ac..f55f82ac8283574887740a9c5c873128dd7a5aa9 100644 --- a/src/backoffice/locale/en/LC_MESSAGES/django.po +++ b/src/backoffice/locale/en/LC_MESSAGES/django.po @@ -1881,6 +1881,9 @@ msgstr "Conference" msgid "Conference__Publication" msgstr "Publication Settings" +msgid "Conference__Registration" +msgstr "Assembly Registration" + msgid "Conference__publish__success" msgstr "Conference was successfully published! Have fun!" @@ -1899,6 +1902,9 @@ msgstr "Failed to publish the conference!" msgid "Conference__form__invalid" msgstr "Conference data you entered is invalid!" +msgid "Conference__registration_update__success" +msgstr "Conference registration information was successfully updated." + #, python-format msgid "Event__publish__failed %(event_type)s" msgstr "Error while publishing the %(event_type)s" diff --git a/src/backoffice/templates/backoffice/base.html b/src/backoffice/templates/backoffice/base.html index 922d681b962e8661184e9a5941f6582bc34c342d..f66127feed4d9cc53a145fe2b3cf80f7bd5e4d15 100644 --- a/src/backoffice/templates/backoffice/base.html +++ b/src/backoffice/templates/backoffice/base.html @@ -54,7 +54,7 @@ <a class="nav-link{% if active_page == 'moderation' %} active{% endif %}" href="{% url 'backoffice:moderation' %}">{% trans "nav_moderation" %}{% if active_page == 'moderation' %} <span class="visually-hidden">{{ activetab_srmarker }}</span>{% endif %}</a> </li> {% endif %} - {% if has_conference_admin %} + {% if has_conference_admin or has_assembly_registration_admin %} <li class="nav-item"> <a class="nav-link{% if active_page == 'conference_admin' %} active{% endif %}" href="{% url 'backoffice:conference-publication' conference.id %}">{% trans "nav_conference_admin" %}{% if active_page == 'conference_admin' %} <span class="visually-hidden">{{ activetab_srmarker }}</span>{% endif %}</a> </li> diff --git a/src/backoffice/templates/backoffice/conferences/registration_edit.html b/src/backoffice/templates/backoffice/conferences/registration_edit.html new file mode 100644 index 0000000000000000000000000000000000000000..1e43b6e6f72452936a676f288b16503f18e10140 --- /dev/null +++ b/src/backoffice/templates/backoffice/conferences/registration_edit.html @@ -0,0 +1,87 @@ +{% extends 'backoffice/base.html' %} +{% load django_bootstrap5 %} +{% load i18n %} +{% load static %} +{% block title %} + {% if form.create %} + {% trans 'create' %} + {% else %} + {{ form.instance.name }} + {% endif %} +{% endblock title %} +{% block scripts %} + <script src="{% static "backoffice/modal.js" %}"></script> + <script> + $(document).ready(() => { + showModal = registerModal() + publishConference = document.getElementById('publishConference'); + if(publishConference){ + document.getElementById('publishConference').addEventListener('click', (e) => { + e.preventDefault(); + if (document.getElementById('id_is_public').value === "True"){ + showModal( + () => { + form = document.getElementById('ConferenceForm'); + form.action = publishConference.formAction + form.submit() + }, + 'warning', + '{% trans "Conference__recall__warning__header" %}', + '{% trans "Conference__recall__warning__text" %}', + '{% trans "Conference__recall__submit" %}') + } else { + showModal( + () => { + form = document.getElementById('ConferenceForm'); + form.action = publishConference.formAction + form.submit() + }, + 'warning', + '{% trans "Conference__publish__warning__header" %}', + '{% trans "Conference__publish__warning__text" %}', + '{% trans "Conference__publish__submit" %}') + } + }) + }; + }); + </script> +{% endblock scripts %} +{% block content %} + <form method="POST" enctype="multipart/form-data" id="ConferenceForm"> + {% csrf_token %} + <div class="card border-default"> + <div class="card-header bg-default"> + {% if form.create %} + {% blocktrans %}create conference{% endblocktrans %} + {% else %} + {% blocktrans %}edit conference{% endblocktrans %} + {% endif %} + </div> + <div class="card-body"> + + {% if form.errors %}<div class="alert alert-danger">{{ form.errors }}</div>{% endif %} + + <p class="fw-bold border-bottom mb-3">{% trans "Conference__edit-metadata" %}</p> + <div class="row mb-3"> + <div class="col-md-4">{% bootstrap_field form.name %}</div> + <div class="col-md-4">{% bootstrap_field form.slug %}</div> + <div class="col-md-4">{% bootstrap_field form.publication_date %}</div> + </div> + <div class="row mb-3"> + <div class="col-md-6">{% bootstrap_field form.registration_start %}</div> + <div class="col-md-6">{% bootstrap_field form.registration_deadline %}</div> + </div> + <div class="row mb-3"> + <div class="col-md-12">{% bootstrap_field form.additional_fields_schema %}</div> + </div> + + </div> + {% if has_form_perms %} + {% trans 'Conference__submit' as button_text %} + <div class="card-footer"> + {% bootstrap_button button_text button_type="submit" button_class="btn-primary float-end" %} + </div> + {% endif %} + </div> + </form> +{% endblock content %} diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index 02d825e119847531a65d9cb3b2d911e3e24ec0da..cffa5382b5918a2114109e5e3d74822bc37bc509 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -3,6 +3,7 @@ from django.views.generic import RedirectView from backoffice.views.conferences import ( ConferencePublicationView, + ConferenceRegistrationView, ConferenceSelectionView, ) from backoffice.views.map import ( @@ -53,6 +54,7 @@ urlpatterns = [ path('auth_debug', auth.AuthDebugView.as_view()), path('conferences', ConferenceSelectionView.as_view(), name='conferences'), path('conference/<uuid:pk>', ConferencePublicationView.as_view(), name='conference-publication'), + path('conference/<uuid:pk>/registration', ConferenceRegistrationView.as_view(), name='conference-registration'), path('wiki', wiki.WikiOverviewView.as_view(), name='wiki'), path('wiki/namespaces', wiki.NamespaceListView.as_view(), name='wiki-namespaces'), path('wiki/locks', wiki.LockListView.as_view(), name='wiki-locks'), diff --git a/src/backoffice/views/conferences.py b/src/backoffice/views/conferences.py index 8a1c7c2ff2e4020f6bd84b4792b6c4f6e057f4db..66515ce995aae3295dbf5504333b2989b32992b9 100644 --- a/src/backoffice/views/conferences.py +++ b/src/backoffice/views/conferences.py @@ -10,7 +10,7 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.views.generic.edit import FormView, UpdateView -from core.forms import ConferencePublicationForm +from core.forms import ConferencePublicationForm, ConferenceRegistrationForm from core.models import Conference, ConferenceMember from backoffice.forms import ConferenceSelectionForm @@ -88,6 +88,13 @@ class ConferenceFormMixin(ConferenceRequiredMixin, FormView): kwargs={'pk': self.conference.pk}, ), }, + { + 'caption': _('Conference__Registration'), + 'link': reverse( + 'backoffice:conference-registration', + kwargs={'pk': self.conference.pk}, + ), + }, ], }, } @@ -161,3 +168,31 @@ class ConferencePublicationView(ConferenceFormMixin, UpdateView): def get_success_url(self): return reverse('backoffice:conference-publication', kwargs={'pk': self.object.pk}) + + +class ConferenceRegistrationView(ConferenceFormMixin, UpdateView): + """ + An UpdateView to change to current :model:`core.conference` settings. + """ + + template_name = 'backoffice/conferences/registration_edit.html' + form_class = ConferenceRegistrationForm + active_page = 'conference' + form_permissions_required = ['core.assembly_registration_admin'] + + def form_valid(self, form: ConferencePublicationForm): + # Try to safe the form before creating logs and messages + self.object = form.save() + logger.info( + 'changed publication info of "%(conference)s" by %(user)s', + { + 'conference': form.instance, + 'user': self.request.user, + }, + ) + messages.success(self.request, _('Conference__registration_update__success')) + + return HttpResponseRedirect(self.get_success_url()) + + def get_success_url(self): + return reverse('backoffice:conference-registration', kwargs={'pk': self.object.pk}) diff --git a/src/backoffice/views/mixins.py b/src/backoffice/views/mixins.py index c7adadf123b6dbbe08337f70682fc1c615779d43..2856a5c7e48dc29eb20f097f55ecaa9acb02070d 100644 --- a/src/backoffice/views/mixins.py +++ b/src/backoffice/views/mixins.py @@ -111,6 +111,7 @@ class ConferenceRequiredMixin(PermissionRequiredMixin): 'has_channel': self.is_channel_team, 'has_pages': self.conferencemember.has_perms('core.static_pages', require_staff=True), 'has_map': self.conferencemember.has_perms('core.map_edit', require_staff=True), + 'has_assembly_registration_admin': self.conferencemember.has_perms('core.assembly_registration_admin', require_staff=True), 'has_conference_admin': self.conferencemember.has_perms('core.conference_admin', require_staff=True), 'has_moderation': self.conferencemember.has_perms('core.moderation', require_staff=True), 'has_schedules': self.conferencemember.has_perms('core.scheduleadmin', require_staff=True), @@ -125,6 +126,7 @@ class ConferenceRequiredMixin(PermissionRequiredMixin): 'has_channel': False, 'has_pages': False, 'has_map': False, + 'has_assembly_registration_admin': False, 'has_conference_admin': False, 'has_moderation': False, 'has_schedules': False, diff --git a/src/core/fixtures/bootstrap_auth_groups.json b/src/core/fixtures/bootstrap_auth_groups.json index 2b7b8cf1f54b25020b8b3f530da955d4c7525e58..bc1cb07757307f89ee5d61bfb430cb74cc1add67 100644 --- a/src/core/fixtures/bootstrap_auth_groups.json +++ b/src/core/fixtures/bootstrap_auth_groups.json @@ -12,6 +12,19 @@ ] } }, + { + "model": "auth.group", + "fields": { + "name": "Registration Admin", + "permissions": [ + [ + "assembly_registration_admin", + "core", + "conferencemember" + ] + ] + } + }, { "model": "auth.group", "fields": { diff --git a/src/core/forms.py b/src/core/forms.py index c4cb99550cad7b7819ace3a2a2110fb56ed1b775..dbcdef83e49c8ab6afed247170c543693a620a4d 100644 --- a/src/core/forms.py +++ b/src/core/forms.py @@ -285,6 +285,35 @@ class ConferencePublicationForm(TranslatedFieldsForm): return super().clean() +class ConferenceRegistrationForm(TranslatedFieldsForm): + class Meta: + model = Conference + fields = [ + 'name', + 'slug', + 'publication_date', + 'registration_start', + 'registration_deadline', + 'additional_fields_schema', + ] + + widgets = { + 'publication_date': DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M:%S%z'), + 'registration_start': DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M:%S%z'), + 'registration_deadline': DateTimeInput(attrs={'type': 'datetime-local'}, format='%Y-%m-%dT%H:%M:%S%z'), + } + + def __init__( + self, + *args, + instance: Conference | None = None, + **kwargs, + ): + super().__init__(*args, instance=instance, **kwargs) + self.fields['name'].disabled = True + self.fields['slug'].disabled = True + + class ProjectForm(TranslatedFieldsForm): class Meta: model = Project diff --git a/src/core/locale/de/LC_MESSAGES/django.po b/src/core/locale/de/LC_MESSAGES/django.po index c74d549de681e78a25281c4f0ebcdcbbbb6b5525..e6c5b80d802fa77913b6b866aa787794ff0386cf 100644 --- a/src/core/locale/de/LC_MESSAGES/django.po +++ b/src/core/locale/de/LC_MESSAGES/django.po @@ -637,6 +637,9 @@ msgstr "Konferenz-Admin: Kann die Veröffentlichungszeitpunkte der Konferenz ver msgid "ConferenceMember__permission-assembly_team" msgstr "Assembly-Team: alle Assemblies verwaltbar, auch noch nicht fertig angelegte und abgelehnte sind sichtbar" +msgid "ConferenceMember__permission-assembly_registration_admin" +msgstr "Registrierungs-Admin: Verwalten der Registrierungsinformationen für Assemblies" + msgid "ConferenceMember__permission-channel_team" msgstr "Channel-Team: alle Assemblies verwaltbar, auch noch nicht fertig angelegte und abgelehnte sind sichtbar" diff --git a/src/core/locale/en/LC_MESSAGES/django.po b/src/core/locale/en/LC_MESSAGES/django.po index b12d8610642fb8053bc9b4261be1403950905472..26eb8f1f6919652af3f08e088eee352ad55baed0 100644 --- a/src/core/locale/en/LC_MESSAGES/django.po +++ b/src/core/locale/en/LC_MESSAGES/django.po @@ -637,6 +637,9 @@ msgstr "Conference admin: can manage the conference's publication times" msgid "ConferenceMember__permission-assembly_team" msgstr "assemblies team: manage all assemblies, see also incomplete and rejected registrations" +msgid "ConferenceMember__permission-assembly_registration_admin" +msgstr "Registration-Admin: Manage registration information for assemblies" + msgid "ConferenceMember__permission-channel_team" msgstr "channel team: manage all assemblies, see also incomplete and rejected registrations" diff --git a/src/core/migrations/0153_alter_conferencemember_options.py b/src/core/migrations/0153_alter_conferencemember_options.py new file mode 100644 index 0000000000000000000000000000000000000000..ce1ce96d856de70f82574daab462446b00243018 --- /dev/null +++ b/src/core/migrations/0153_alter_conferencemember_options.py @@ -0,0 +1,39 @@ +# Generated by Django 5.1.2 on 2024-10-27 13:10 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("core", "0152_alter_conferencemember_options"), + ] + + operations = [ + migrations.AlterModelOptions( + name="conferencemember", + options={ + "permissions": [ + ( + "conference_admin", + "ConferenceMember__permission-confernece_admin", + ), + ("assembly_team", "ConferenceMember__permission-assembly_team"), + ( + "assembly_registration_admin", + "ConferenceMember__permission-assembly_registration_admin", + ), + ("channel_team", "ConferenceMember__permission-channel_team"), + ("static_pages", "ConferenceMember__permission-static_pages"), + ("map_edit", "ConferenceMember__permission-map_edit"), + ("moderation", "Orga: Moderation"), + ("voucher_admin", "ConferenceMember__permission-voucher_admin"), + ("scheduleadmin", "ConferenceMember__permission-scheduleadmin"), + ( + "workadventure_admin", + "ConferenceMember__permission-workadventure_admin", + ), + ] + }, + ), + ] diff --git a/src/core/models/conference.py b/src/core/models/conference.py index cb2a9a8106cee6aa43add4f234ab00b5625cb38d..501d6ecb1afcf23a470f24af417fca60b924c832 100644 --- a/src/core/models/conference.py +++ b/src/core/models/conference.py @@ -82,6 +82,8 @@ class ConferenceMember(models.Model): # Change conference settings (e.g., dates, ), update venue json. ('assembly_team', _('ConferenceMember__permission-assembly_team')), # See all assemblies, not only the accepted ones. + ('assembly_registration_admin', _('ConferenceMember__permission-assembly_registration_admin')), + # See all assemblies, not only the accepted ones. ('channel_team', _('ConferenceMember__permission-channel_team')), # Channelteam, Assemblyteam for Channel-Type Assemblies (Assemblies that provide their own content) ('static_pages', _('ConferenceMember__permission-static_pages')),