.
This commit is contained in:
@@ -22,6 +22,9 @@ urlpatterns = [
|
||||
path("rota/<int:rota_id>/export/builder/", views.rota_export_builder, name="rota_export_builder"),
|
||||
path("rota/<int:rota_id>/options/update/", views.rota_options_update, name="rota_options_update"),
|
||||
path("rota/<int:rota_id>/options/", views.rota_options, name="rota_options"),
|
||||
path("rota/<int:rota_id>/option/add/", views.rota_option_add, name="rota_option_add"),
|
||||
path("rota/<int:rota_id>/option/edit/", views.rota_option_edit, name="rota_option_edit"),
|
||||
path("rota/<int:rota_id>/option/delete/", views.rota_option_delete, name="rota_option_delete"),
|
||||
path("rota/<int:rota_id>/runs/clear/", views.rota_runs_clear, name="rota_runs_clear"),
|
||||
path("run/<int:run_id>/export/regenerate/", views.rota_run_export_regenerate, name="rota_run_export_regenerate"),
|
||||
]
|
||||
|
||||
@@ -335,6 +335,147 @@ def rota_options(request, rota_id):
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
def _oob_update_options_display(request, rota):
|
||||
"""Helper: render options display and return HTMX OOB swap response."""
|
||||
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 = '<div id="rota-options-display" hx-swap-oob="true">' + options_html + '</div>' + '<div id="modal" hx-swap-oob="true"></div>'
|
||||
response = HttpResponse(resp)
|
||||
response["HX-Trigger"] = "closeModal"
|
||||
return response
|
||||
|
||||
|
||||
def rota_option_add(request, rota_id):
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
is_hx = request.headers.get("HX-Request", "false").lower() == "true"
|
||||
|
||||
if request.method == "POST":
|
||||
key = request.POST.get("key", "").strip()
|
||||
val = request.POST.get("value", "")
|
||||
vtype = request.POST.get("type", "string")
|
||||
if not key:
|
||||
return HttpResponseBadRequest("Key is required")
|
||||
# parse value according to type
|
||||
try:
|
||||
if vtype == "int":
|
||||
parsed = int(val)
|
||||
elif vtype == "float":
|
||||
parsed = float(val)
|
||||
elif vtype == "bool":
|
||||
parsed = val.lower() in ("1", "true", "yes", "on")
|
||||
elif vtype == "json":
|
||||
parsed = json.loads(val) if val.strip() else None
|
||||
else:
|
||||
parsed = val
|
||||
except Exception as exc:
|
||||
return HttpResponseBadRequest(f"Invalid value: {exc}")
|
||||
|
||||
opts = rota.options or {}
|
||||
opts[key] = parsed
|
||||
rota.options = opts
|
||||
rota.save(update_fields=["options"])
|
||||
|
||||
if is_hx:
|
||||
return _oob_update_options_display(request, rota)
|
||||
|
||||
return redirect("rota:rota_detail", rota_id=rota.id)
|
||||
|
||||
# GET: show modal partial
|
||||
modal_html = render_to_string(
|
||||
"rota/partials/rota_option_modal_single.html",
|
||||
{"form_action": reverse("rota:rota_option_add", args=(rota.id,)), "initial": {"key": "", "value": "", "type": "string"}, "rota": rota},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
def rota_option_edit(request, rota_id):
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
is_hx = request.headers.get("HX-Request", "false").lower() == "true"
|
||||
|
||||
if request.method == "POST":
|
||||
key = request.POST.get("key", "").strip()
|
||||
val = request.POST.get("value", "")
|
||||
vtype = request.POST.get("type", "string")
|
||||
if not key:
|
||||
return HttpResponseBadRequest("Key is required")
|
||||
try:
|
||||
if vtype == "int":
|
||||
parsed = int(val)
|
||||
elif vtype == "float":
|
||||
parsed = float(val)
|
||||
elif vtype == "bool":
|
||||
parsed = val.lower() in ("1", "true", "yes", "on")
|
||||
elif vtype == "json":
|
||||
parsed = json.loads(val) if val.strip() else None
|
||||
else:
|
||||
parsed = val
|
||||
except Exception as exc:
|
||||
return HttpResponseBadRequest(f"Invalid value: {exc}")
|
||||
|
||||
opts = rota.options or {}
|
||||
opts[key] = parsed
|
||||
rota.options = opts
|
||||
rota.save(update_fields=["options"])
|
||||
|
||||
if is_hx:
|
||||
return _oob_update_options_display(request, rota)
|
||||
|
||||
return redirect("rota:rota_detail", rota_id=rota.id)
|
||||
|
||||
# GET: prepare edit modal with existing value
|
||||
key = request.GET.get("key")
|
||||
if not key:
|
||||
return HttpResponseBadRequest("Missing key")
|
||||
current = rota.options or {}
|
||||
cur_val = current.get(key, "")
|
||||
# choose type hint
|
||||
if isinstance(cur_val, bool):
|
||||
vtype = "bool"
|
||||
value = "1" if cur_val else "0"
|
||||
elif isinstance(cur_val, int):
|
||||
vtype = "int"
|
||||
value = str(cur_val)
|
||||
elif isinstance(cur_val, float):
|
||||
vtype = "float"
|
||||
value = str(cur_val)
|
||||
elif isinstance(cur_val, (list, dict)):
|
||||
vtype = "json"
|
||||
value = json.dumps(cur_val)
|
||||
else:
|
||||
vtype = "string"
|
||||
value = str(cur_val)
|
||||
|
||||
modal_html = render_to_string(
|
||||
"rota/partials/rota_option_modal_single.html",
|
||||
{"form_action": reverse("rota:rota_option_edit", args=(rota.id,)), "initial": {"key": key, "value": value, "type": vtype}, "rota": rota},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
@require_POST
|
||||
def rota_option_delete(request, rota_id):
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
key = request.POST.get("key")
|
||||
if not key:
|
||||
return HttpResponseBadRequest("Missing key")
|
||||
opts = rota.options or {}
|
||||
if key in opts:
|
||||
opts.pop(key)
|
||||
rota.options = opts
|
||||
rota.save(update_fields=["options"])
|
||||
|
||||
if request.headers.get("HX-Request", "false").lower() == "true":
|
||||
return _oob_update_options_display(request, rota)
|
||||
|
||||
return redirect("rota:rota_detail", rota_id=rota.id)
|
||||
|
||||
|
||||
def rota_run_export_download(request, run_id):
|
||||
from .models import RotaRun
|
||||
|
||||
|
||||
Reference in New Issue
Block a user