diff --git a/djangorota/rota/views.py b/djangorota/rota/views.py index 0c5c0bd..28ed0a6 100644 --- a/djangorota/rota/views.py +++ b/djangorota/rota/views.py @@ -330,41 +330,49 @@ def rota_options(request, rota_id): is_hx = request.headers.get("HX-Request", "false").lower() == "true" if request.method == "POST": - options_json = request.POST.get("options_json", "") - try: - parsed = json.loads(options_json) if options_json.strip() else {} - except Exception as exc: - if is_hx: + # Support two POST modes: legacy `options_json` textarea, or the typed + # form generated by `RotaScheduleForm` (fields prefixed with `opt__`). + if "options_json" in request.POST: + options_json = request.POST.get("options_json", "") + try: + parsed = json.loads(options_json) if options_json.strip() else {} + except Exception as exc: + if is_hx: + return HttpResponseBadRequest(f"Invalid JSON: {exc}") return HttpResponseBadRequest(f"Invalid JSON: {exc}") - return HttpResponseBadRequest(f"Invalid JSON: {exc}") - rota.options = parsed - rota.save(update_fields=["options"]) + rota.options = parsed + rota.save(update_fields=["options"]) + if is_hx: + return _oob_update_options_display(request, rota) + return redirect(reverse("rota:rota_detail", args=(rota.id,))) + # Typed form submission + from .forms import RotaScheduleForm + + form = RotaScheduleForm(request.POST, instance=rota) + if not form.is_valid(): + if is_hx: + # Re-render modal with errors + modal_html = render_to_string( + "rota/partials/rota_options_modal.html", + {"form_action": reverse("rota:rota_options", args=(rota.id,)), "form": form, "rota": rota}, + request=request, + ) + return HttpResponse(modal_html) + return HttpResponseBadRequest("Invalid form submission") + + form.save() if is_hx: - # render display snippet and send OOB swap to update it and clear modal - options_pretty = json.dumps(rota.options or {}, indent=4) - options_html = render_to_string( - "rota/partials/rota_options_display.html", - {"rota": rota, "options_pretty": options_pretty}, - request=request, - ) - resp = '
' + options_html + '
' + '' - response = HttpResponse(resp) - response["HX-Trigger"] = "closeModal" - return response - + return _oob_update_options_display(request, rota) return redirect(reverse("rota:rota_detail", args=(rota.id,))) - # GET: return modal partial - try: - initial = {"options_json": json.dumps(rota.options or {}, indent=4)} - except Exception: - initial = {"options_json": "{}"} - + # GET: render modal with typed form populated from the rota instance + from .forms import RotaScheduleForm + form = RotaScheduleForm(instance=rota) modal_html = render_to_string( "rota/partials/rota_options_modal.html", - {"form_action": reverse("rota:rota_options", args=(rota.id,)), "initial": initial, "rota": rota}, + {"form_action": reverse("rota:rota_options", args=(rota.id,)), "form": form, "rota": rota}, request=request, ) return HttpResponse(modal_html)