diff --git a/AKDashboard/locale/de_DE/LC_MESSAGES/django.po b/AKDashboard/locale/de_DE/LC_MESSAGES/django.po index 16106ec28c235db1e0c5863c3cae67d919f334f4..0e9393ffc125f57b0aa770fd134a8b884858c5ed 100644 --- a/AKDashboard/locale/de_DE/LC_MESSAGES/django.po +++ b/AKDashboard/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/AKModel/admin.py b/AKModel/admin.py index 6f9b752b90e8b70079a484be99e24c8093ed687e..bf8cd7ccac53747a4a419b839738eb88023ddf1b 100644 --- a/AKModel/admin.py +++ b/AKModel/admin.py @@ -3,7 +3,7 @@ from django.contrib import admin from django.contrib.admin import SimpleListFilter from django.db.models import Count, F from django import forms -from django.shortcuts import render +from django.shortcuts import render, redirect from django.urls import path, reverse_lazy from django.utils import timezone from django.utils.html import format_html @@ -16,7 +16,9 @@ from AKModel.availability.forms import AvailabilitiesFormMixin from AKModel.availability.models import Availability from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequirement, AK, AKSlot, Room, AKOrgaMessage, \ ConstraintViolation -from AKModel.views import EventStatusView, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, AKRequirementOverview +from AKModel.views import EventStatusView, AKCSVExportView, AKWikiExportView, AKMessageDeleteView, AKRequirementOverview, \ + NewEventWizardStartView, NewEventWizardSettingsView, NewEventWizardPrepareImportView, NewEventWizardFinishView, \ + NewEventWizardImportView, NewEventWizardActivateView @admin.register(Event) @@ -27,9 +29,29 @@ class EventAdmin(admin.ModelAdmin): list_editable = ['active'] ordering = ['-start'] + def add_view(self, request, form_url='', extra_context=None): + # Always use wizard to create new events + # (the built-in form wouldn't work anyways since the timezone cannot be specified before starting to fill the form) + return redirect("admin:new_event_wizard_start") + def get_urls(self): urls = super().get_urls() custom_urls = [ + path('add/wizard/start/', self.admin_site.admin_view(NewEventWizardStartView.as_view()), + name="new_event_wizard_start"), + path('add/wizard/settings/', self.admin_site.admin_view(NewEventWizardSettingsView.as_view()), + name="new_event_wizard_settings"), + path('add/wizard/created/<slug:event_slug>/', self.admin_site.admin_view(NewEventWizardPrepareImportView.as_view()), + name="new_event_wizard_prepare_import"), + path('add/wizard/import/<slug:event_slug>/from/<slug:import_slug>/', + self.admin_site.admin_view(NewEventWizardImportView.as_view()), + name="new_event_wizard_import"), + path('add/wizard/activate/<slug:slug>/', + self.admin_site.admin_view(NewEventWizardActivateView.as_view()), + name="new_event_wizard_activate"), + path('add/wizard/finish/<slug:slug>/', + self.admin_site.admin_view(NewEventWizardFinishView.as_view()), + name="new_event_wizard_finish"), path('<slug:slug>/status/', self.admin_site.admin_view(EventStatusView.as_view()), name="event_status"), path('<slug:event_slug>/requirements/', self.admin_site.admin_view(AKRequirementOverview.as_view()), name="event_requirement_overview"), path('<slug:event_slug>/ak-csv-export/', self.admin_site.admin_view(AKCSVExportView.as_view()), name="ak_csv_export"), @@ -46,11 +68,7 @@ class EventAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, change=False, **kwargs): # Use timezone of event - if obj is not None and obj.timezone: - timezone.activate(obj.timezone) - # No timezone available? Use UTC - else: - timezone.activate("UTC") + timezone.activate(obj.timezone) return super().get_form(request, obj, change, **kwargs) diff --git a/AKModel/forms.py b/AKModel/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..bdb4e8dd6d5514d68ca40187739e1c95f51a6203 --- /dev/null +++ b/AKModel/forms.py @@ -0,0 +1,68 @@ +from bootstrap_datepicker_plus import DateTimePickerInput +from django import forms +from django.forms.utils import ErrorList +from django.utils.translation import ugettext_lazy as _ + +from AKModel.models import Event, AKCategory, AKRequirement + + +class NewEventWizardStartForm(forms.ModelForm): + class Meta: + model = Event + fields = ['name', 'slug', 'timezone'] + + is_init = forms.BooleanField(initial=True, widget=forms.HiddenInput) + + +class NewEventWizardSettingsForm(forms.ModelForm): + class Meta: + model = Event + exclude = [] + widgets = { + 'name': forms.HiddenInput(), + 'slug': forms.HiddenInput(), + 'timezone': forms.HiddenInput(), + 'active': forms.HiddenInput(), + 'plan_hidden': forms.HiddenInput(), + 'start': DateTimePickerInput(options={"format": "YYYY-MM-DD HH:mm"}), + 'end': DateTimePickerInput(options={"format": "YYYY-MM-DD HH:mm"}), + 'reso_deadline': DateTimePickerInput(options={"format": "YYYY-MM-DD HH:mm"}), + } + + +class NewEventWizardPrepareImportForm(forms.Form): + import_event = forms.ModelChoiceField( + queryset=Event.objects.all(), + label=_("Copy ak requirements and ak categories of existing event"), + help_text=_("You can choose what to copy in the next step") + ) + + +class NewEventWizardImportForm(forms.Form): + import_categories = forms.ModelMultipleChoiceField( + queryset=AKCategory.objects.all(), + widget=forms.CheckboxSelectMultiple, + label=_("Copy ak categories"), + required=False, + ) + + import_requirements = forms.ModelMultipleChoiceField( + queryset=AKRequirement.objects.all(), + widget=forms.CheckboxSelectMultiple, + label=_("Copy ak requirements"), + required=False, + ) + + def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, initial=None, error_class=ErrorList, + label_suffix=None, empty_permitted=False, field_order=None, use_required_attribute=None, + renderer=None): + super().__init__(data, files, auto_id, prefix, initial, error_class, label_suffix, empty_permitted, field_order, + use_required_attribute, renderer) + self.fields["import_categories"].queryset = self.fields["import_categories"].queryset.filter(event=self.initial["import_event"]) + self.fields["import_requirements"].queryset = self.fields["import_requirements"].queryset.filter(event=self.initial["import_event"]) + + +class NewEventWizardActivateForm(forms.ModelForm): + class Meta: + fields = ["active"] + model = Event diff --git a/AKModel/locale/de_DE/LC_MESSAGES/django.po b/AKModel/locale/de_DE/LC_MESSAGES/django.po index 3f02a022ea6849db7d62ee55ceb44bdb29f4ff02..0f5209a90da627faff8fb5580cca31585a64b972 100644 --- a/AKModel/locale/de_DE/LC_MESSAGES/django.po +++ b/AKModel/locale/de_DE/LC_MESSAGES/django.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -11,30 +11,33 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: AKModel/admin.py:44 AKModel/admin.py:45 +#: AKModel/admin.py:66 AKModel/admin.py:67 +#: AKModel/templates/admin/AKModel/event_wizard/activate.html:32 +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:48 +#: AKModel/templates/admin/AKModel/event_wizard/finish.html:21 #: AKModel/templates/admin/AKModel/requirements_overview.html:8 #: AKModel/templates/admin/AKModel/status.html:7 #: AKModel/templates/admin/ak_index.html:15 msgid "Status" msgstr "Status" -#: AKModel/admin.py:135 +#: AKModel/admin.py:153 msgid "Wish" msgstr "AK-Wunsch" -#: AKModel/admin.py:141 +#: AKModel/admin.py:159 msgid "Is wish" msgstr "Ist ein Wunsch" -#: AKModel/admin.py:142 +#: AKModel/admin.py:160 msgid "Is not a wish" msgstr "Ist kein Wunsch" -#: AKModel/admin.py:169 +#: AKModel/admin.py:187 msgid "Export to wiki syntax" msgstr "In Wiki-Syntax exportieren" -#: AKModel/admin.py:265 +#: AKModel/admin.py:283 msgid "AK Details" msgstr "AK-Details" @@ -114,6 +117,23 @@ msgstr "AK-Kategorie, deren Verfügbarkeit hier abgebildet wird" msgid "Availabilities" msgstr "Verfügbarkeiten" +#: AKModel/forms.py:36 +msgid "Copy ak requirements and ak categories of existing event" +msgstr "AK-Anforderungen und AK-Kategorien eines existierenden Events kopieren" + +#: AKModel/forms.py:37 +msgid "You can choose what to copy in the next step" +msgstr "" +"Im nächsten Schritt kann ausgewählt werden, was genau kopiert werden soll" + +#: AKModel/forms.py:45 +msgid "Copy ak categories" +msgstr "AK-Kategorien kopieren" + +#: AKModel/forms.py:52 +msgid "Copy ak requirements" +msgstr "AK-Anforderungen kopieren" + #: AKModel/models.py:16 AKModel/models.py:123 AKModel/models.py:144 #: AKModel/models.py:163 AKModel/models.py:177 AKModel/models.py:195 #: AKModel/models.py:291 @@ -150,7 +170,7 @@ msgstr "Zeitzone" msgid "Time Zone where this event takes place in" msgstr "Zeitzone in der das Event stattfindet" -#: AKModel/models.py:25 +#: AKModel/models.py:25 AKModel/views.py:206 msgid "Start" msgstr "Start" @@ -543,7 +563,7 @@ msgstr "AK-Slot" #: AKModel/models.py:337 AKModel/models.py:442 msgid "AK Slots" -msgstr "AK-Slots" +msgstr "AK-Slot" #: AKModel/models.py:359 AKModel/models.py:368 msgid "Not scheduled yet" @@ -726,6 +746,71 @@ msgstr "" msgid "Logout" msgstr "Ausloggen" +#: AKModel/templates/admin/AKModel/event_wizard/activate.html:9 +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:9 +#: AKModel/templates/admin/AKModel/event_wizard/finish.html:9 +#: AKModel/templates/admin/AKModel/event_wizard/import.html:9 +#: AKModel/templates/admin/AKModel/event_wizard/settings.html:9 +#: AKModel/templates/admin/AKModel/event_wizard/start.html:8 +#: AKModel/templates/admin/AKModel/event_wizard/wizard_steps.html:3 +msgid "New event wizard" +msgstr "Assistent zum Anlegen eines neuen Events" + +#: AKModel/templates/admin/AKModel/event_wizard/activate.html:18 +msgid "Successfully imported.<br><br>Do you want to activate your event now?" +msgstr "Erfolgreich importiert.<br><br>Soll das Event jetzt aktiviert werden?" + +#: AKModel/templates/admin/AKModel/event_wizard/activate.html:27 +#: AKModel/views.py:211 +msgid "Finish" +msgstr "Abschluss" + +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:16 +msgid "New event:" +msgstr "Neues Event:" + +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:30 +msgid "Your event was created and can now be further configured." +msgstr "Das Event wurde angelegt und kann nun weiter konfiguriert werden." + +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:39 +msgid "Skip Import" +msgstr "Import überspringen" + +#: AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html:43 +#: AKModel/templates/admin/AKModel/event_wizard/import.html:20 +#: AKModel/templates/admin/AKModel/event_wizard/settings.html:22 +#: AKModel/templates/admin/AKModel/event_wizard/start.html:19 +msgid "Continue" +msgstr "Fortfahren" + +#: AKModel/templates/admin/AKModel/event_wizard/finish.html:18 +msgid "Congratulations. Everything is set up!" +msgstr "Herzlichen Glückwunsch. Alles ist eingerichtet!" + +#: AKModel/templates/admin/AKModel/event_wizard/import.html:24 +#: AKModel/templates/admin/AKModel/event_wizard/settings.html:29 +#: AKModel/templates/admin/AKModel/event_wizard/start.html:23 +#: AKModel/templates/admin/AKModel/message_delete.html:21 +msgid "Cancel" +msgstr "Abbrechen" + +#: AKModel/templates/admin/AKModel/event_wizard/settings.html:26 +msgid "Back" +msgstr "Zurück" + +#: AKModel/templates/admin/AKModel/event_wizard/start.html:13 +msgid "" +"Add a new event. Please start by filling these basic properties. You can " +"specify more settings later." +msgstr "" +"Neues Event anlegen. Bitte zunächst diese Grundeinstellungen ausfüllen, " +"weitere Einstellungen können später gesetzt werden." + +#: AKModel/templates/admin/AKModel/event_wizard/wizard_steps.html:15 +msgid "Step" +msgstr "Schritt" + #: AKModel/templates/admin/AKModel/message_delete.html:7 msgid "Delete Orga-Messages" msgstr "Organachrichten löschen" @@ -747,10 +832,6 @@ msgstr "" msgid "Delete" msgstr "Löschen" -#: AKModel/templates/admin/AKModel/message_delete.html:21 -msgid "Cancel" -msgstr "Abbrechen" - #: AKModel/templates/admin/AKModel/requirements_overview.html:12 msgid "Requirements Overview" msgstr "Übersicht Anforderungen" @@ -837,26 +918,54 @@ msgstr "Alle Nachrichten löschen" msgid "Active Events" msgstr "Aktive Events" -#: AKModel/views.py:135 +#: AKModel/views.py:136 msgid "Event Status" msgstr "Eventstatus" -#: AKModel/views.py:148 +#: AKModel/views.py:149 msgid "Requirements for Event" msgstr "Anforderungen für das Event" -#: AKModel/views.py:162 +#: AKModel/views.py:163 msgid "AK CSV Export" msgstr "AK-CSV-Export" -#: AKModel/views.py:176 +#: AKModel/views.py:177 msgid "AK Wiki Export" msgstr "AK-Wiki-Export" -#: AKModel/views.py:196 +#: AKModel/views.py:197 msgid "AK Orga Messages successfully deleted" msgstr "AK-Organachrichten erfolgreich gelöscht" +#: AKModel/views.py:207 +msgid "Settings" +msgstr "Einstellungen" + +#: AKModel/views.py:208 +msgid "Event created, Prepare Import" +msgstr "Event angelegt, Import vorbereiten" + +#: AKModel/views.py:209 +msgid "Import categories & requirements" +msgstr "Kategorien & Anforderungen kopieren" + +#: AKModel/views.py:210 +#, fuzzy +#| msgid "Active State" +msgid "Activate?" +msgstr "Aktivieren?" + +#: AKModel/views.py:270 +#, python-format +msgid "Copied '%(obj)s'" +msgstr "'%(obj)s' kopiert" + +#: AKModel/views.py:272 +#, python-format +msgid "Could not copy '%(obj)s' (%(error)s)" +msgstr "'%(obj)s' konnte nicht kopiert werden (%(error)s)" + #~ msgid "Confirm" #~ msgstr "Bestätigen" diff --git a/AKModel/templates/admin/AKModel/event_wizard/activate.html b/AKModel/templates/admin/AKModel/event_wizard/activate.html new file mode 100644 index 0000000000000000000000000000000000000000..eb460420a410be7ff3b2ac08f761c21c6bd17c5c --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/activate.html @@ -0,0 +1,36 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} +{% load tz %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + <div class="text-center btn-success disabled mt-3 mb-3" style="font-size: 8em;"> + {% fa5_icon "copy" "fas" %} + </div> + + <h5 class="mb-3">{% trans "Successfully imported.<br><br>Do you want to activate your event now?" %}</h5> + + {{ form.media }} + + <form method="post">{% csrf_token %} + {% bootstrap_form form %} + + <div class="float-right"> + <button type="submit" class="save btn btn-success" value="Submit"> + {% fa5_icon "check" 'fas' %} {% trans "Finish" %} + </button> + </div> + + <a href="{% url 'admin:event_status' event.slug %}" class="btn btn-info"> + {% fa5_icon "info" 'fas' %} {% trans "Status" %} + </a> + </form> + +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html b/AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html new file mode 100644 index 0000000000000000000000000000000000000000..e1fc7165a13e039801a70c294ce77049b87b9ba8 --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/created_prepare_import.html @@ -0,0 +1,52 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} +{% load tz %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + {% timezone event.timezone %} + <div class="card border-success mt-3 mb-3" style="max-width: 100%;"> + <div class="card-header">{% trans "New event:" %}</div> + <div class="card-body"> + <h4 class="card-title">{{event}}</h4> + <p class="card-text">{{ event.start }} - {{ event.end }}</p> + </div> + </div> + {% endtimezone %} + + <div class="text-center btn-success disabled mb-3" style="font-size: 8em;"> + {% fa5_icon "calendar-plus" "fas" %} + </div> + + + + <h5 class="mb-3">{% trans "Your event was created and can now be further configured." %}</h5> + + {{ form.media }} + + <form method="post">{% csrf_token %} + {% bootstrap_form form %} + + <div class="float-right"> + <a href="{% url 'admin:new_event_wizard_activate' event.slug %}" class="btn btn-info"> + {% fa5_icon "forward" 'fas' %} {% trans "Skip Import" %} + </a> + + <button type="submit" class="save btn btn-success" value="Submit"> + {% fa5_icon "check" 'fas' %} {% trans "Continue" %} + </button> + </div> + + <a href="{% url 'admin:event_status' event.slug %}" class="btn btn-info"> + {% fa5_icon "info" 'fas' %} {% trans "Status" %} + </a> + </form> + +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/finish.html b/AKModel/templates/admin/AKModel/event_wizard/finish.html new file mode 100644 index 0000000000000000000000000000000000000000..16d3090b0f3d690f3859740b4c9b3cb057f7a1e1 --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/finish.html @@ -0,0 +1,24 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} +{% load tz %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + <div class="text-center btn-success disabled mt-3 mb-3" style="font-size: 8em;"> + {% fa5_icon "check-circle" "fas" %} + </div> + + <h5>{% trans "Congratulations. Everything is set up!" %}</h5> + + <a href="{% url 'admin:event_status' event.slug %}" class="btn btn-info float-right"> + {% fa5_icon "info" 'fas' %} {% trans "Status" %} + </a> + +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/import.html b/AKModel/templates/admin/AKModel/event_wizard/import.html new file mode 100644 index 0000000000000000000000000000000000000000..d899a2d02c4a4aad6efb1da1ef73e8ebbc6b1173 --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/import.html @@ -0,0 +1,28 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} +{% load tz %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + {{ form.media }} + + <form method="post">{% csrf_token %} + {% bootstrap_form form %} + + <button type="submit" class="save btn btn-success float-right" value="Submit"> + {% fa5_icon "check" 'fas' %} {% trans "Continue" %} + </button> + + <a href="{% url 'admin:index' %}" class="btn btn-info"> + {% fa5_icon "times" 'fas' %} {% trans "Cancel" %} + </a> + </form> + +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/settings.html b/AKModel/templates/admin/AKModel/event_wizard/settings.html new file mode 100644 index 0000000000000000000000000000000000000000..0b306d7bb6e93f330e01454ea2690332e12e6d8a --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/settings.html @@ -0,0 +1,34 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} +{% load tz %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + {{ form.media }} + + {% timezone timezone %} + + <form method="post">{% csrf_token %} + {% bootstrap_form form %} + + <button type="submit" class="save btn btn-success float-right" value="Submit"> + {% fa5_icon "check" 'fas' %} {% trans "Continue" %} + </button> + + <a href="{% url 'admin:new_event_wizard_start' %}" class="btn btn-info"> + {% fa5_icon "chevron-left" 'fas' %} {% trans "Back" %} + </a> + <a href="{% url 'admin:index' %}" class="btn btn-warning"> + {% fa5_icon "times" 'fas' %} {% trans "Cancel" %} + </a> + </form> + + {% endtimezone %} +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/start.html b/AKModel/templates/admin/AKModel/event_wizard/start.html new file mode 100644 index 0000000000000000000000000000000000000000..762cadb5932d9b7f65cfaa69ed022572d305a423 --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/start.html @@ -0,0 +1,26 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load bootstrap4 %} +{% load fontawesome_5 %} + +{% block title %}{% trans "New event wizard" %}: {{ wizard_step_text }}{% endblock %} + +{% block content %} + {% include "admin/AKModel/event_wizard/wizard_steps.html" %} + + {% trans "Add a new event. Please start by filling these basic properties. You can specify more settings later." %} + + <form method="post" action="{% url 'admin:new_event_wizard_settings' %}">{% csrf_token %} + {% bootstrap_form form %} + + <button type="submit" class="save btn btn-success float-right" value="Submit"> + {% fa5_icon "check" 'fas' %} {% trans "Continue" %} + </button> + + <a href="{% url 'admin:index' %}" class="btn btn-info"> + {% fa5_icon "times" 'fas' %} {% trans "Cancel" %} + </a> + </form> +{% endblock %} diff --git a/AKModel/templates/admin/AKModel/event_wizard/wizard_steps.html b/AKModel/templates/admin/AKModel/event_wizard/wizard_steps.html new file mode 100644 index 0000000000000000000000000000000000000000..a006f3d3bb0a573e052de3dfaf41b5137958990d --- /dev/null +++ b/AKModel/templates/admin/AKModel/event_wizard/wizard_steps.html @@ -0,0 +1,15 @@ +{% load i18n %} + +<h2>{% trans "New event wizard" %}</h2> + +<div> + <ul class="pagination pagination-sm"> + {% for step in wizard_steps %} + <li class="page-item {% if forloop.counter == wizard_step %}active{% else %}disabled{% endif %}"> + <a class="page-link" href="#">{{ step }}</a> + </li> + {% endfor %} + </ul> +</div> + +<h3>{% trans "Step" %} {{ wizard_step }}: {{ wizard_step_text }}</h3> diff --git a/AKModel/views.py b/AKModel/views.py index 72be1c0a0d66a2226525d7506649e9a60cd184c5..cc78a0c5a2bece33be49d4c495746722b112ed49 100644 --- a/AKModel/views.py +++ b/AKModel/views.py @@ -1,12 +1,13 @@ from django.contrib import admin, messages from django.http import HttpResponseRedirect -from django.shortcuts import get_object_or_404 +from django.shortcuts import get_object_or_404, redirect from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ - -from django.views.generic import TemplateView, DetailView, ListView, DeleteView +from django.views.generic import TemplateView, DetailView, ListView, DeleteView, CreateView, FormView, UpdateView from rest_framework import viewsets, permissions, mixins +from AKModel.forms import NewEventWizardStartForm, NewEventWizardSettingsForm, NewEventWizardPrepareImportForm, \ + NewEventWizardImportForm, NewEventWizardActivateForm from AKModel.models import Event, AK, AKSlot, Room, AKTrack, AKCategory, AKOwner, AKOrgaMessage, AKRequirement from AKModel.serializers import AKSerializer, AKSlotSerializer, RoomSerializer, AKTrackSerializer, AKCategorySerializer, \ AKOwnerSerializer @@ -38,10 +39,10 @@ class EventSlugMixin: self._load_event() return super().create(request, *args, **kwargs) - def initial(self, request, *args, **kwargs): + def dispatch(self, request, *args, **kwargs): if self.event is None: self._load_event() - super().initial(request, *args, **kwargs) + return super().dispatch(request, *args, **kwargs) def get_context_data(self, *, object_list=None, **kwargs): context = super().get_context_data(object_list=object_list, **kwargs) @@ -195,3 +196,94 @@ class AKMessageDeleteView(AdminViewMixin, DeleteView): self.get_orga_messages_for_event(self.get_object()).delete() messages.add_message(self.request, messages.SUCCESS, _("AK Orga Messages successfully deleted")) return HttpResponseRedirect(reverse_lazy('admin:event_status', kwargs={'slug': self.get_object().slug})) + + +class WizardViewMixin: + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["wizard_step"] = self.wizard_step + context["wizard_steps"] = [ + _("Start"), + _("Settings"), + _("Event created, Prepare Import"), + _("Import categories & requirements"), + _("Activate?"), + _("Finish") + ] + context["wizard_step_text"] = context["wizard_steps"][self.wizard_step - 1] + context["wizard_steps_total"] = len(context["wizard_steps"]) + return context + + +class NewEventWizardStartView(AdminViewMixin, WizardViewMixin, CreateView): + model = Event + form_class = NewEventWizardStartForm + template_name = "admin/AKModel/event_wizard/start.html" + wizard_step = 1 + + +class NewEventWizardSettingsView(AdminViewMixin, WizardViewMixin, CreateView): + model = Event + form_class = NewEventWizardSettingsForm + template_name = "admin/AKModel/event_wizard/settings.html" + wizard_step = 2 + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["timezone"] = context["form"].cleaned_data["timezone"] + return context + + def get_success_url(self): + return reverse_lazy("admin:new_event_wizard_prepare_import", kwargs={"event_slug": self.object.slug}) + + +class NewEventWizardPrepareImportView(WizardViewMixin, EventSlugMixin, FormView): + form_class = NewEventWizardPrepareImportForm + template_name = "admin/AKModel/event_wizard/created_prepare_import.html" + wizard_step = 3 + + + + def form_valid(self, form): + # Selected a valid event to import from? Use this to go to next step of wizard + return redirect("admin:new_event_wizard_import", event_slug=self.event.slug, import_slug=form.cleaned_data["import_event"].slug) + + +class NewEventWizardImportView(EventSlugMixin, WizardViewMixin, FormView): + form_class = NewEventWizardImportForm + template_name = "admin/AKModel/event_wizard/import.html" + wizard_step = 4 + + def get_initial(self): + initial = super().get_initial() + initial["import_event"] = Event.objects.get(slug=self.kwargs["import_slug"]) + return initial + + def form_valid(self, form): + for import_type in ["import_categories", "import_requirements"]: + for import_obj in form.cleaned_data.get(import_type): + # clone existing entry + try: + import_obj.event = self.event + import_obj.pk = None + import_obj.save() + messages.add_message(self.request, messages.SUCCESS, _("Copied '%(obj)s'" % {'obj': import_obj})) + except BaseException as e: + messages.add_message(self.request, messages.ERROR, _("Could not copy '%(obj)s' (%(error)s)" % {'obj': import_obj, "error": str(e)})) + return redirect("admin:new_event_wizard_activate", slug=self.event.slug) + + +class NewEventWizardActivateView(WizardViewMixin, UpdateView): + model = Event + template_name = "admin/AKModel/event_wizard/activate.html" + form_class = NewEventWizardActivateForm + wizard_step = 5 + + def get_success_url(self): + return reverse_lazy("admin:new_event_wizard_finish", kwargs={"slug": self.object.slug}) + + +class NewEventWizardFinishView(WizardViewMixin, DetailView): + model = Event + template_name = "admin/AKModel/event_wizard/finish.html" + wizard_step = 6 diff --git a/AKPlan/locale/de_DE/LC_MESSAGES/django.po b/AKPlan/locale/de_DE/LC_MESSAGES/django.po index d4db40908d725efba16a34b4fca135f533d8e8db..120f98ec3aa53d92c9834c799ef26b1312363b1c 100644 --- a/AKPlan/locale/de_DE/LC_MESSAGES/django.po +++ b/AKPlan/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/AKPlanning/locale/de_DE/LC_MESSAGES/django.po b/AKPlanning/locale/de_DE/LC_MESSAGES/django.po index 6830c35c8072ed059a0e244f82cc709e1c002838..7338ca7ceea654920d0e2d499bbd9828fe27a6f1 100644 --- a/AKPlanning/locale/de_DE/LC_MESSAGES/django.po +++ b/AKPlanning/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,10 +17,10 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: AKPlanning/settings.py:133 +#: AKPlanning/settings.py:134 msgid "German" msgstr "Deutsch" -#: AKPlanning/settings.py:134 +#: AKPlanning/settings.py:135 msgid "English" msgstr "Englisch" diff --git a/AKPlanning/settings.py b/AKPlanning/settings.py index 0dbfeb5c69e6e8d902aaa0179dbdde356786ff14..b6745ea1be102cacacffd7463f9762890e50c909 100644 --- a/AKPlanning/settings.py +++ b/AKPlanning/settings.py @@ -51,6 +51,7 @@ INSTALLED_APPS = [ 'rest_framework', 'simple_history', 'registration', + 'bootstrap_datepicker_plus', ] MIDDLEWARE = [ diff --git a/AKScheduling/locale/de_DE/LC_MESSAGES/django.po b/AKScheduling/locale/de_DE/LC_MESSAGES/django.po index 2cb2de0eb02fc16cc37a45508a136e99669a7929..f25c002dbd9be02bcac1bd45292140a48688de0d 100644 --- a/AKScheduling/locale/de_DE/LC_MESSAGES/django.po +++ b/AKScheduling/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/AKSubmission/locale/de_DE/LC_MESSAGES/django.po b/AKSubmission/locale/de_DE/LC_MESSAGES/django.po index 4ec5841a70543ca60fd2c586f228ca2efeb2a428..103059be8dc1225a6de8a80b01ac91ff437f0022 100644 --- a/AKSubmission/locale/de_DE/LC_MESSAGES/django.po +++ b/AKSubmission/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index a23d11fd5b2273b57f3e96c9a40760d8c6e385c2..08f762b7b7501a236d78898cf696363ebac7c924 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-04-29 21:09+0000\n" +"POT-Creation-Date: 2021-04-29 22:48+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -50,9 +50,6 @@ msgstr "Diese Software ist Open Source" #~ msgid "Scheduling for" #~ msgstr "Scheduling für" -#~ msgid "Event Status" -#~ msgstr "Event-Status" - #~ msgid "Day (Horizontal)" #~ msgstr "Tag (horizontal)" @@ -68,6 +65,9 @@ msgstr "Diese Software ist Open Source" #~ msgid "Room" #~ msgstr "Raum" +#~ msgid "Event Status" +#~ msgstr "Event-Status" + #~ msgid "Unscheduled AK Slots" #~ msgstr "Noch nicht geschedulte AK-Slots" diff --git a/requirements.txt b/requirements.txt index a32a4ed15c9e82e7c6a1cffb871fe3a4b518cd0a..176ecddcb86a08622ed74567a87ff7fc64f0cc3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,12 @@ -Django==3.1.5 -django-bootstrap4==2.3.1 +Django==3.1.8 +django-bootstrap4==3.0.1 django-fontawesome-5==1.0.18 django-split-settings==1.0.1 django-timezone-field==4.1.2 -djangorestframework==3.12.2 -django-simple-history==2.12.0 +djangorestframework==3.12.4 +django-simple-history==3.0.0 django-registration-redux==2.9 -django-debug-toolbar==3.2 +django-debug-toolbar==3.2.1 +django-bootstrap-datepicker-plus==3.0.5 mysqlclient==2.0.3 # for production deployment pytz==2021.1