Skip to content
Snippets Groups Projects
Commit 15e6489c authored by Nadja Geisler's avatar Nadja Geisler :sunny:
Browse files

Merge branch 'feature-room-import' into 'main'

Introduce view for room import from CSV

Closes #156

See merge request !139
parents 86c75e95 26226749
No related branches found
No related tags found
1 merge request!139Introduce view for room import from CSV
Pipeline #118809 passed
......@@ -19,7 +19,7 @@ from AKModel.models import Event, AKOwner, AKCategory, AKTrack, AKTag, AKRequire
ConstraintViolation, DefaultSlot
from AKModel.urls import get_admin_urls_event_wizard, get_admin_urls_event
from AKModel.views import CVMarkResolvedView, CVSetLevelViolationView, CVSetLevelWarningView, AKResetInterestView, \
AKResetInterestCounterView, PlanPublishView, PlanUnpublishView, DefaultSlotEditorView
AKResetInterestCounterView, PlanPublishView, PlanUnpublishView, DefaultSlotEditorView, RoomBatchCreationView
class EventRelatedFieldListFilter(RelatedFieldListFilter):
......@@ -56,6 +56,7 @@ class EventAdmin(admin.ModelAdmin):
path('plan/publish/', PlanPublishView.as_view(), name="plan-publish"),
path('plan/unpublish/', PlanUnpublishView.as_view(), name="plan-unpublish"),
path('<slug:event_slug>/defaultSlots/', DefaultSlotEditorView.as_view(), name="default-slots-editor"),
path('<slug:event_slug>/importRooms/', RoomBatchCreationView.as_view(), name="room-import"),
])
urls.extend(super().get_urls())
return urls
......
import csv
import io
from bootstrap_datepicker_plus import DateTimePickerInput
from django import forms
from django.forms.utils import ErrorList
......@@ -61,8 +64,10 @@ class NewEventWizardImportForm(forms.Form):
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"])
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):
......@@ -112,3 +117,22 @@ class DefaultSlotEditorForm(AdminIntermediateForm):
widget=forms.TextInput(attrs={'class': 'availabilities-editor-data'}),
required=True,
)
class RoomBatchCreationForm(AdminIntermediateForm):
rooms = forms.CharField(
label=_('New rooms'),
help_text=_('Enter room details in CSV format. Required colum is "name", optional colums are "location", '
'"capacity", and "url" for online/hybrid rooms. Delimiter: Semicolon'),
widget=forms.Textarea,
required=True,
)
def clean_rooms(self):
rooms_raw_text = self.cleaned_data["rooms"]
rooms_raw_dict = csv.DictReader(io.StringIO(rooms_raw_text), delimiter=";")
if "name" not in rooms_raw_dict.fieldnames:
raise forms.ValidationError(_("CSV must contain a name column"))
return rooms_raw_dict
......@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-29 00:13+0100\n"
"POT-Creation-Date: 2022-11-30 01:57+0100\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,7 +11,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: AKModel/admin.py:63 AKModel/admin.py:66
#: AKModel/admin.py:64 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
......@@ -21,59 +21,59 @@ msgstr ""
msgid "Status"
msgstr "Status"
#: AKModel/admin.py:68
#: AKModel/admin.py:69
msgid "Toggle plan visibility"
msgstr "Plansichtbarkeit ändern"
#: AKModel/admin.py:72 AKModel/admin.py:83 AKModel/views.py:483
#: AKModel/admin.py:73 AKModel/admin.py:84 AKModel/views.py:485
msgid "Publish plan"
msgstr "Plan veröffentlichen"
#: AKModel/admin.py:75 AKModel/admin.py:88 AKModel/views.py:493
#: AKModel/admin.py:76 AKModel/admin.py:89 AKModel/views.py:495
msgid "Unpublish plan"
msgstr "Plan verbergen"
#: AKModel/admin.py:160
#: AKModel/admin.py:161
msgid "Wish"
msgstr "AK-Wunsch"
#: AKModel/admin.py:166
#: AKModel/admin.py:167
msgid "Is wish"
msgstr "Ist ein Wunsch"
#: AKModel/admin.py:167
#: AKModel/admin.py:168
msgid "Is not a wish"
msgstr "Ist kein Wunsch"
#: AKModel/admin.py:211
#: AKModel/admin.py:212
msgid "Export to wiki syntax"
msgstr "In Wiki-Syntax exportieren"
#: AKModel/admin.py:220
#: AKModel/admin.py:221
msgid "Cannot export AKs from more than one event at the same time."
msgstr "Kann nicht AKs von mehreren Events zur selben Zeit exportieren."
#: AKModel/admin.py:235 AKModel/views.py:463
#: AKModel/admin.py:236 AKModel/views.py:465
msgid "Reset interest in AKs"
msgstr "Interesse an AKs zurücksetzen"
#: AKModel/admin.py:240 AKModel/views.py:473
#: AKModel/admin.py:241 AKModel/views.py:475
msgid "Reset AKs' interest counters"
msgstr "Interessenszähler der AKs zurücksetzen"
#: AKModel/admin.py:324 AKModel/admin.py:331
#: AKModel/admin.py:325 AKModel/admin.py:332
msgid "AK Details"
msgstr "AK-Details"
#: AKModel/admin.py:383 AKModel/views.py:433
#: AKModel/admin.py:384 AKModel/views.py:435
msgid "Mark Constraint Violations as manually resolved"
msgstr "Markiere Constraintverletzungen als manuell behoben"
#: AKModel/admin.py:388 AKModel/views.py:443
#: AKModel/admin.py:389 AKModel/views.py:445
msgid "Set Constraint Violations to level \"violation\""
msgstr "Constraintverletzungen auf Level \"Violation\" setzen"
#: AKModel/admin.py:393 AKModel/views.py:453
#: AKModel/admin.py:394 AKModel/views.py:455
msgid "Set Constraint Violations to level \"warning\""
msgstr "Constraintverletzungen auf Level \"Warning\" setzen"
......@@ -81,7 +81,7 @@ msgstr "Constraintverletzungen auf Level \"Warning\" setzen"
msgid "Availability"
msgstr "Verfügbarkeit"
#: AKModel/availability/forms.py:23 AKModel/forms.py:110
#: AKModel/availability/forms.py:23 AKModel/forms.py:115
msgid ""
"Click and drag to mark the availability during the event, double-click to "
"delete."
......@@ -154,52 +154,52 @@ msgstr "AK-Kategorie, deren Verfügbarkeit hier abgebildet wird"
msgid "Availabilities"
msgstr "Verfügbarkeiten"
#: AKModel/forms.py:39
#: AKModel/forms.py:42
msgid "Copy ak requirements and ak categories of existing event"
msgstr "AK-Anforderungen und AK-Kategorien eines existierenden Events kopieren"
#: AKModel/forms.py:40
#: AKModel/forms.py:43
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:48
#: AKModel/forms.py:51
msgid "Copy ak categories"
msgstr "AK-Kategorien kopieren"
#: AKModel/forms.py:55
#: AKModel/forms.py:58
msgid "Copy ak requirements"
msgstr "AK-Anforderungen kopieren"
#: AKModel/forms.py:87
#: AKModel/forms.py:92
msgid "# next AKs"
msgstr "# nächste AKs"
#: AKModel/forms.py:88
#: AKModel/forms.py:93
msgid "How many next AKs should be shown on a slide?"
msgstr "Wie viele nächste AKs sollen auf einer Folie angezeigt werden?"
#: AKModel/forms.py:91
#: AKModel/forms.py:96
msgid "Presentation only?"
msgstr "Nur Vorstellung?"
#: AKModel/forms.py:93 AKModel/forms.py:100
#: AKModel/forms.py:98 AKModel/forms.py:105
msgid "Yes"
msgstr "Ja"
#: AKModel/forms.py:93 AKModel/forms.py:100
#: AKModel/forms.py:98 AKModel/forms.py:105
msgid "No"
msgstr "Nein"
#: AKModel/forms.py:95
#: AKModel/forms.py:100
msgid "Restrict AKs to those that asked for chance to be presented?"
msgstr "AKs auf solche, die um eine Vorstellung gebeten haben, einschränken?"
#: AKModel/forms.py:98
#: AKModel/forms.py:103
msgid "Space for notes in wishes?"
msgstr "Platz für Notizen bei den Wünschen?"
#: AKModel/forms.py:102
#: AKModel/forms.py:107
msgid ""
"Create symbols indicating space to note down owners and timeslots for "
"wishes, e.g., to be filled out on a touch screen while presenting?"
......@@ -208,10 +208,28 @@ msgstr ""
"fürWünsche markieren, z.B. um während der Präsentation auf einem Touchscreen "
"ausgefüllt zu werden?"
#: AKModel/forms.py:108 AKModel/models.py:658
#: AKModel/forms.py:113 AKModel/models.py:658
msgid "Default Slots"
msgstr "Standardslots"
#: AKModel/forms.py:124
msgid "New rooms"
msgstr "Neue Räume"
#: AKModel/forms.py:125
msgid ""
"Enter room details in CSV format. Required colum is \"name\", optional "
"colums are \"location\", \"capacity\", and \"url\" for online/hybrid rooms. "
"Delimiter: Semicolon"
msgstr ""
"Raumdetails im CSV-Format eingeben. Benötigte Spalte ist \"name\", optionale "
"Spalten sind \"location\", \"capacity\", und \"url\" for Online-/Hybridräume"
"Trennzeichen: Semikolon"
#: AKModel/forms.py:136
msgid "CSV must contain a name column"
msgstr "CSV muss eine name-Spalte enthalten"
#: AKModel/models.py:18 AKModel/models.py:175 AKModel/models.py:199
#: AKModel/models.py:218 AKModel/models.py:232 AKModel/models.py:250
#: AKModel/models.py:346
......@@ -248,7 +266,7 @@ msgstr "Zeitzone"
msgid "Time Zone where this event takes place in"
msgstr "Zeitzone in der das Event stattfindet"
#: AKModel/models.py:27 AKModel/views.py:244
#: AKModel/models.py:27 AKModel/views.py:246
msgid "Start"
msgstr "Start"
......@@ -544,7 +562,7 @@ msgstr "AK präsentieren"
msgid "Present results of this AK"
msgstr "Die Ergebnisse dieses AKs vorstellen"
#: AKModel/models.py:273 AKModel/templates/admin/AKModel/status.html:104
#: AKModel/models.py:273 AKModel/templates/admin/AKModel/status.html:105
msgid "Requirements"
msgstr "Anforderungen"
......@@ -600,8 +618,8 @@ msgid "People who have indicated interest online"
msgstr "Anzahl Personen, die online Interesse bekundet haben"
#: AKModel/models.py:295 AKModel/models.py:502
#: AKModel/templates/admin/AKModel/status.html:56
#: AKModel/templates/admin/AKModel/status.html:63 AKModel/views.py:362
#: AKModel/templates/admin/AKModel/status.html:57
#: AKModel/templates/admin/AKModel/status.html:64 AKModel/views.py:364
msgid "AKs"
msgstr "AKs"
......@@ -710,7 +728,7 @@ msgstr "AK-Organachrichten"
msgid "Constraint Violation"
msgstr "Constraintverletzung"
#: AKModel/models.py:473 AKModel/templates/admin/AKModel/status.html:86
#: AKModel/models.py:473 AKModel/templates/admin/AKModel/status.html:87
msgid "Constraint Violations"
msgstr "Constraintverletzungen"
......@@ -906,7 +924,7 @@ 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:249
#: AKModel/views.py:251
msgid "Finish"
msgstr "Abschluss"
......@@ -971,7 +989,7 @@ msgid "No AKs with this requirement"
msgstr "Kein AK mit dieser Anforderung"
#: AKModel/templates/admin/AKModel/requirements_overview.html:45
#: AKModel/templates/admin/AKModel/status.html:120
#: AKModel/templates/admin/AKModel/status.html:121
msgid "Add Requirement"
msgstr "Anforderung hinzufügen"
......@@ -999,64 +1017,68 @@ msgstr "Bisher keine Räume"
msgid "Add Room"
msgstr "Raum hinzufügen"
#: AKModel/templates/admin/AKModel/status.html:58
#: AKModel/templates/admin/AKModel/status.html:55 AKModel/views.py:582
msgid "Import Rooms from CSV"
msgstr "Räume aus CSV importieren"
#: AKModel/templates/admin/AKModel/status.html:59
msgid "No AKs yet"
msgstr "Bisher keine AKs"
#: AKModel/templates/admin/AKModel/status.html:66
#: AKModel/templates/admin/AKModel/status.html:67
msgid "Slots"
msgstr "Slots"
#: AKModel/templates/admin/AKModel/status.html:69
#: AKModel/templates/admin/AKModel/status.html:70
msgid "Unscheduled Slots"
msgstr "Ungeplante Slots"
#: AKModel/templates/admin/AKModel/status.html:83
#: AKModel/templates/admin/AKModel/status.html:84
#: AKModel/templates/admin/ak_index.html:16
msgid "Scheduling"
msgstr "Scheduling"
#: AKModel/templates/admin/AKModel/status.html:88
#: AKModel/templates/admin/AKModel/status.html:89
msgid "AKs requiring special attention"
msgstr "AKs, die besondere Aufmerksamkeit benötigen"
#: AKModel/templates/admin/AKModel/status.html:90
#: AKModel/templates/admin/AKModel/status.html:91
msgid "Enter Interest"
msgstr "Interesse erfassen"
#: AKModel/templates/admin/AKModel/status.html:93 AKModel/views.py:505
#: AKModel/templates/admin/AKModel/status.html:94 AKModel/views.py:507
msgid "Edit Default Slots"
msgstr "Standardslots bearbeiten"
#: AKModel/templates/admin/AKModel/status.html:95
#: AKModel/templates/admin/AKModel/status.html:96
msgid "Manage ak tracks"
msgstr "AK-Tracks verwalten"
#: AKModel/templates/admin/AKModel/status.html:97
#: AKModel/templates/admin/AKModel/status.html:98
msgid "Export AKs as CSV"
msgstr "AKs als CSV exportieren"
#: AKModel/templates/admin/AKModel/status.html:99
#: AKModel/templates/admin/AKModel/status.html:100
msgid "Export AKs for Wiki"
msgstr "AKs im Wiki-Format exportieren"
#: AKModel/templates/admin/AKModel/status.html:101 AKModel/views.py:332
#: AKModel/templates/admin/AKModel/status.html:102 AKModel/views.py:334
msgid "Export AK Slides"
msgstr "AK-Folien exportieren"
#: AKModel/templates/admin/AKModel/status.html:106
#: AKModel/templates/admin/AKModel/status.html:107
msgid "No requirements yet"
msgstr "Bisher keine Anforderungen"
#: AKModel/templates/admin/AKModel/status.html:119
#: AKModel/templates/admin/AKModel/status.html:120
msgid "Show AKs for requirements"
msgstr "Zu Anforderungen gehörige AKs anzeigen"
#: AKModel/templates/admin/AKModel/status.html:123
#: AKModel/templates/admin/AKModel/status.html:124
msgid "Messages"
msgstr "Nachrichten"
#: AKModel/templates/admin/AKModel/status.html:125
#: AKModel/templates/admin/AKModel/status.html:126
msgid "Delete all messages"
msgstr "Alle Nachrichten löschen"
......@@ -1093,148 +1115,162 @@ msgstr "Login"
msgid "Register"
msgstr "Registrieren"
#: AKModel/views.py:150
#: AKModel/views.py:152
msgid "Event Status"
msgstr "Eventstatus"
#: AKModel/views.py:163
#: AKModel/views.py:165
msgid "Requirements for Event"
msgstr "Anforderungen für das Event"
#: AKModel/views.py:177
#: AKModel/views.py:179
msgid "AK CSV Export"
msgstr "AK-CSV-Export"
#: AKModel/views.py:191
#: AKModel/views.py:193
msgid "AK Wiki Export"
msgstr "AK-Wiki-Export"
#: AKModel/views.py:199 AKModel/views.py:348
#: AKModel/views.py:201 AKModel/views.py:350
msgid "Wishes"
msgstr "Wünsche"
#: AKModel/views.py:220
#: AKModel/views.py:222
msgid "Delete AK Orga Messages"
msgstr "AK-Organachrichten löschen"
#: AKModel/views.py:235
#: AKModel/views.py:237
msgid "AK Orga Messages successfully deleted"
msgstr "AK-Organachrichten erfolgreich gelöscht"
#: AKModel/views.py:245
#: AKModel/views.py:247
msgid "Settings"
msgstr "Einstellungen"
#: AKModel/views.py:246
#: AKModel/views.py:248
msgid "Event created, Prepare Import"
msgstr "Event angelegt, Import vorbereiten"
#: AKModel/views.py:247
#: AKModel/views.py:249
msgid "Import categories & requirements"
msgstr "Kategorien & Anforderungen kopieren"
#: AKModel/views.py:248
#: AKModel/views.py:250
msgid "Activate?"
msgstr "Aktivieren?"
#: AKModel/views.py:307
#: AKModel/views.py:309
#, python-format
msgid "Copied '%(obj)s'"
msgstr "'%(obj)s' kopiert"
#: AKModel/views.py:310
#: AKModel/views.py:312
#, python-format
msgid "Could not copy '%(obj)s' (%(error)s)"
msgstr "'%(obj)s' konnte nicht kopiert werden (%(error)s)"
#: AKModel/views.py:343
#: AKModel/views.py:345
msgid "Symbols"
msgstr "Symbole"
#: AKModel/views.py:344
#: AKModel/views.py:346
msgid "Who?"
msgstr "Wer?"
#: AKModel/views.py:345
#: AKModel/views.py:347
msgid "Duration(s)"
msgstr "Dauer(n)"
#: AKModel/views.py:346
#: AKModel/views.py:348
msgid "Reso intention?"
msgstr "Resolutionsabsicht?"
#: AKModel/views.py:347
#: AKModel/views.py:349
msgid "Category (for Wishes)"
msgstr "Kategorie (für Wünsche)"
#: AKModel/views.py:435
#: AKModel/views.py:437
msgid "The following Constraint Violations will be marked as manually resolved"
msgstr ""
"Die folgenden Constraintverletzungen werden als manuell behoben markiert."
#: AKModel/views.py:436
#: AKModel/views.py:438
msgid "Constraint Violations marked as resolved"
msgstr "Constraintverletzungen als manuell behoben markiert"
#: AKModel/views.py:445
#: AKModel/views.py:447
msgid "The following Constraint Violations will be set to level 'violation'"
msgstr ""
"Die folgenden Constraintverletzungen werden auf das Level \"Violation\" "
"gesetzt."
#: AKModel/views.py:446
#: AKModel/views.py:448
msgid "Constraint Violations set to level 'violation'"
msgstr "Constraintverletzungen auf Level \"Violation\" gesetzt"
#: AKModel/views.py:455
#: AKModel/views.py:457
msgid "The following Constraint Violations will be set to level 'warning'"
msgstr ""
"Die folgenden Constraintverletzungen werden auf das Level 'warning' gesetzt."
#: AKModel/views.py:456
#: AKModel/views.py:458
msgid "Constraint Violations set to level 'warning'"
msgstr "Constraintverletzungen auf Level \"Warning\" gesetzt"
#: AKModel/views.py:465
#: AKModel/views.py:467
msgid "Interest of the following AKs will be set to not filled (-1):"
msgstr "Interesse an den folgenden AKs wird auf nicht ausgefüllt (-1) gesetzt:"
#: AKModel/views.py:466
#: AKModel/views.py:468
msgid "Reset of interest in AKs successful."
msgstr "Interesse an AKs erfolgreich zurückgesetzt."
#: AKModel/views.py:475
#: AKModel/views.py:477
msgid "Interest counter of the following AKs will be set to 0:"
msgstr "Interessensbekundungszähler der folgenden AKs wird auf 0 gesetzt:"
#: AKModel/views.py:476
#: AKModel/views.py:478
msgid "AKs' interest counters set back to 0."
msgstr "Interessenszähler der AKs zurückgesetzt"
#: AKModel/views.py:485
#: AKModel/views.py:487
msgid "Publish the plan(s) of:"
msgstr "Den Plan/die Pläne veröffentlichen von:"
#: AKModel/views.py:486
#: AKModel/views.py:488
msgid "Plan published"
msgstr "Plan veröffentlicht"
#: AKModel/views.py:495
#: AKModel/views.py:497
msgid "Unpublish the plan(s) of:"
msgstr "Den Plan/die Pläne verbergen von:"
#: AKModel/views.py:496
#: AKModel/views.py:498
msgid "Plan unpublished"
msgstr "Plan verborgen"
#: AKModel/views.py:542
#: AKModel/views.py:544
#, python-brace-format
msgid "Could not update slot {id} since it does not belong to {event}"
msgstr ""
"Konnte Slot {id} nicht bearbeiten, da er nicht zum Event {event} gehört"
#: AKModel/views.py:572
#: AKModel/views.py:574
#, python-brace-format
msgid "Updated {u} slot(s). created {c} new slot(s) and deleted {d} slot(s)"
msgstr ""
"{u} Slot(s) aktualisiert, {c} Slot(s) hinzugefügt und {d} Slot(s) gelöscht"
#: AKModel/views.py:611
#, python-brace-format
msgid "Could not import room {name}: {e}"
msgstr "Konnte Raum {name} nicht importieren: {e}"
#: AKModel/views.py:615
#, python-brace-format
msgid "Imported {count} room(s)"
msgstr "{count} Raum/Räume importiert"
#: AKModel/views.py:617
msgid "No rooms imported"
msgstr "Keine Räume importiert"
......@@ -52,6 +52,7 @@
</p>
{% endif %}
<a class="btn btn-success" href="{% url 'admin:AKModel_room_add' %}">{% trans "Add Room" %}</a>
<a class="btn btn-success" href="{% url 'admin:room-import' event_slug=event.slug %}">{% trans "Import Rooms from CSV" %}</a>
<h3 class="block-header">{% trans "AKs" %}</h3>
{% if event.ak_set.count == 0 %}
......
import csv
import json
import os
import tempfile
from abc import ABC, abstractmethod
from itertools import zip_longest
import django.db
from django.contrib import admin, messages
from django.db.models.functions import Now
from django.shortcuts import get_object_or_404, redirect
......@@ -17,7 +19,7 @@ from rest_framework import viewsets, permissions, mixins
from AKModel.forms import NewEventWizardStartForm, NewEventWizardSettingsForm, NewEventWizardPrepareImportForm, \
NewEventWizardImportForm, NewEventWizardActivateForm, AdminIntermediateForm, SlideExportForm, \
AdminIntermediateActionForm, DefaultSlotEditorForm
AdminIntermediateActionForm, DefaultSlotEditorForm, RoomBatchCreationForm
from AKModel.models import Event, AK, AKSlot, Room, AKTrack, AKCategory, AKOwner, AKOrgaMessage, AKRequirement, \
ConstraintViolation, DefaultSlot
from AKModel.serializers import AKSerializer, AKSlotSerializer, RoomSerializer, AKTrackSerializer, AKCategorySerializer, \
......@@ -573,3 +575,44 @@ class DefaultSlotEditorView(EventSlugMixin, IntermediateAdminView):
.format(u=str(updated_count), c=str(created_count), d=str(deleted_count))
)
return super().form_valid(form)
class RoomBatchCreationView(EventSlugMixin, IntermediateAdminView):
form_class = RoomBatchCreationForm
title = _("Import Rooms from CSV")
def get_success_url(self):
return reverse_lazy('admin:event_status', kwargs={'slug': self.event.slug})
def form_valid(self, form):
from django.apps import apps
VIRTUAL_ROOMS_SUPPORT = False
if apps.is_installed("AKOnline"):
VIRTUAL_ROOMS_SUPPORT = True
from AKOnline.models import VirtualRoom
created_count = 0
rooms_raw_dict: csv.DictReader = form.cleaned_data["rooms"]
for raw_room in rooms_raw_dict:
name = raw_room["name"]
location = raw_room["location"] if "location" in rooms_raw_dict.fieldnames else ""
capacity = raw_room["capacity"] if "capacity" in rooms_raw_dict.fieldnames else -1
url = raw_room["url"] if "url" in rooms_raw_dict.fieldnames else ""
try:
if VIRTUAL_ROOMS_SUPPORT and url != "":
VirtualRoom.objects.create(name=name, location=location, capacity=capacity, url=url, event=self.event)
else:
Room.objects.create(name=name, location=location, capacity=capacity, event=self.event)
created_count += 1
except django.db.Error as e:
messages.add_message(self.request, messages.WARNING,
_("Could not import room {name}: {e}").format(name=name, e=str(e)))
if created_count > 0:
messages.add_message(self.request, messages.SUCCESS,
_("Imported {count} room(s)").format(count=created_count))
else:
messages.add_message(self.request, messages.WARNING, _("No rooms imported"))
return super().form_valid(form)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment