diff --git a/AKModel/forms.py b/AKModel/forms.py index 9ec3d24ec5f73148be7f135b8aa9f97965b3a4cc..4f0e399380a8f6a2a62fec8be60116a8dd11b89b 100644 --- a/AKModel/forms.py +++ b/AKModel/forms.py @@ -6,6 +6,7 @@ import csv import io from django import forms +from django.core.exceptions import ValidationError from django.forms.utils import ErrorList from django.utils.translation import gettext_lazy as _ @@ -286,8 +287,25 @@ class RoomFormWithAvailabilities(AvailabilitiesFormMixin, RoomForm): class JSONScheduleImportForm(AdminIntermediateForm): """Form to import an AK schedule from a json file.""" json_data = forms.CharField( - required=True, + required=False, widget=forms.Textarea, label=_("JSON data"), help_text=_("JSON data from the scheduling solver"), ) + + json_file = forms.FileField( + required=False, + label=_("File with JSON data"), + help_text=_("File with JSON data from the scheduling solver"), + ) + + def clean(self): + cleaned_data = super().clean() + if cleaned_data.get("json_file") and cleaned_data.get("json_data"): + raise ValidationError("Please enter data as a file OR via text, not both.") + if not (cleaned_data.get("json_file") or cleaned_data.get("json_data")): + raise ValidationError("No data entered.") + + # TODO Check input data if it is a valid JSON + + return cleaned_data diff --git a/AKModel/models.py b/AKModel/models.py index 15da9170ff93ecb97144710203c2dfba8cf506a5..bae1cdd31b944b8ad6d7070b7bb0b5ab146db760 100644 --- a/AKModel/models.py +++ b/AKModel/models.py @@ -434,8 +434,11 @@ class Event(models.Model): schedule = json.loads(schedule) export_dict = self.as_json_dict() + if "input" not in schedule or "scheduled_aks" not in schedule: + raise ValueError(_("Cannot parse malformed JSON input.")) + if check_for_data_inconsistency and schedule["input"] != export_dict: - raise ValueError("Data has changed since the export. Reexport and run the solver again.") + raise ValueError(_("Data has changed since the export. Reexport and run the solver again.")) slots_in_an_hour = schedule["input"]["timeslots"]["info"]["duration"] diff --git a/AKModel/templates/admin/AKModel/import_json.html b/AKModel/templates/admin/AKModel/import_json.html new file mode 100644 index 0000000000000000000000000000000000000000..737331e89f5614b9ef22fd68cea2f669fc79f91b --- /dev/null +++ b/AKModel/templates/admin/AKModel/import_json.html @@ -0,0 +1,30 @@ +{% extends "admin/base_site.html" %} +{% load tags_AKModel %} + +{% load i18n %} +{% load django_bootstrap5 %} +{% load fontawesome_6 %} + + +{% block title %}{{event}}: {{ title }}{% endblock %} + +{% block content %} + {% block action_preview %} + <p> + {{ preview|linebreaksbr }} + </p> + {% endblock %} + + <form enctype="multipart/form-data" method="post">{% csrf_token %} + {% bootstrap_form form %} + + <div class="float-end"> + <button type="submit" class="save btn btn-success" value="Submit"> + {% fa6_icon "check" 'fas' %} {% trans "Confirm" %} + </button> + </div> + <a href="javascript:history.back()" class="btn btn-info"> + {% fa6_icon "times" 'fas' %} {% trans "Cancel" %} + </a> + </form> +{% endblock %} diff --git a/AKModel/views/manage.py b/AKModel/views/manage.py index 3acb05fd29a6e91cd17f45e9ed43d889a67da22c..5ca9dfcbd7b16b76edf8005f961401288c82765d 100644 --- a/AKModel/views/manage.py +++ b/AKModel/views/manage.py @@ -253,12 +253,21 @@ class AKScheduleJSONImportView(EventSlugMixin, IntermediateAdminView): """ View: Import an AK schedule from a json file that can be pasted into this view. """ + template_name = "admin/AKModel/import_json.html" form_class = JSONScheduleImportForm title = _("AK Schedule JSON Import") def form_valid(self, form): try: - number_of_slots_changed = self.event.schedule_from_json(form.data["json_data"]) + if form.cleaned_data.get("json_data"): + data = form.cleaned_data["json_data"] + elif form.cleaned_data.get("json_file"): + with form.cleaned_data["json_file"].open() as ff: + data = ff.read() + else: + raise ValueError("No data entered!") + + number_of_slots_changed = self.event.schedule_from_json(data) messages.add_message( self.request, messages.SUCCESS,