.
This commit is contained in:
@@ -14,6 +14,71 @@ from django.shortcuts import HttpResponseRedirect
|
||||
import traceback
|
||||
|
||||
|
||||
def _get_constraint_description(key: str):
|
||||
"""Return the description for a constraint key from the typed model metadata.
|
||||
|
||||
This is defensive because different pydantic versions expose field metadata
|
||||
to the Python API slightly differently.
|
||||
"""
|
||||
if not key:
|
||||
return None
|
||||
try:
|
||||
import importlib
|
||||
mod = importlib.import_module("rota_generator.shifts")
|
||||
RotaConstraintOptions = getattr(mod, "RotaConstraintOptions", None)
|
||||
meta = {}
|
||||
if RotaConstraintOptions is not None:
|
||||
meta = getattr(RotaConstraintOptions, "model_fields", {}) or {}
|
||||
else:
|
||||
RotaBuilder = getattr(mod, "RotaBuilder", None)
|
||||
if RotaBuilder is not None:
|
||||
try:
|
||||
rb = RotaBuilder()
|
||||
opts_model = getattr(rb, "constraint_options_model", None)
|
||||
meta = getattr(opts_model.__class__, "model_fields", {}) or {}
|
||||
except Exception:
|
||||
meta = {}
|
||||
# meta should be a dict-like mapping of field names -> field info
|
||||
if not isinstance(meta, dict):
|
||||
try:
|
||||
meta = dict(meta)
|
||||
except Exception:
|
||||
meta = {}
|
||||
if key not in meta:
|
||||
return None
|
||||
info = meta[key]
|
||||
# Try several access patterns to extract a description
|
||||
desc = None
|
||||
try:
|
||||
if hasattr(info, "description") and info.description:
|
||||
desc = info.description
|
||||
except Exception:
|
||||
desc = None
|
||||
if not desc:
|
||||
try:
|
||||
# dict-like
|
||||
desc = info.get("description")
|
||||
except Exception:
|
||||
desc = None
|
||||
if not desc:
|
||||
try:
|
||||
fi = getattr(info, "field_info", None)
|
||||
if fi is not None and getattr(fi, "description", None):
|
||||
desc = fi.description
|
||||
except Exception:
|
||||
desc = None
|
||||
if not desc:
|
||||
try:
|
||||
extra = getattr(info, "extra", None)
|
||||
if isinstance(extra, dict) and extra.get("description"):
|
||||
desc = extra.get("description")
|
||||
except Exception:
|
||||
pass
|
||||
return desc
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def index(request):
|
||||
rotas = RotaSchedule.objects.all().order_by("-created_at")
|
||||
return render(request, "rota/index.html", {"rotas": rotas})
|
||||
@@ -93,7 +158,14 @@ def rota_detail(request, rota_id):
|
||||
pretty = json.dumps(v, indent=2, default=str)
|
||||
except Exception:
|
||||
pretty = str(v)
|
||||
configured_constraints[k] = {"value": v, "pretty": pretty, "typed": (k in available_constraints_rich)}
|
||||
# Include description from the typed defaults when available so the
|
||||
# UI can show tooltips and the modal can display helpful text.
|
||||
desc = None
|
||||
try:
|
||||
desc = available_constraints_rich.get(k, {}).get("description")
|
||||
except Exception:
|
||||
desc = None
|
||||
configured_constraints[k] = {"value": v, "pretty": pretty, "typed": (k in available_constraints_rich), "description": desc}
|
||||
except Exception:
|
||||
configured_constraints = {}
|
||||
|
||||
@@ -484,9 +556,12 @@ def rota_option_add(request, rota_id):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Compute description for the suggested key (if any) and pass into modal
|
||||
desc = _get_constraint_description(key_q) if key_q else None
|
||||
|
||||
modal_html = render_to_string(
|
||||
"rota/partials/rota_option_modal_single.html",
|
||||
{"form_action": reverse("rota:rota_option_add", args=(rota.id,)), "initial": initial, "rota": rota},
|
||||
{"form_action": reverse("rota:rota_option_add", args=(rota.id,)), "initial": initial, "rota": rota, "description": desc},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
@@ -551,9 +626,11 @@ def rota_option_inline(request, rota_id):
|
||||
pretty = json.dumps(parsed, indent=2, default=str)
|
||||
except Exception:
|
||||
pretty = str(parsed)
|
||||
# Include description for the saved key so the updated row has a tooltip
|
||||
desc = _get_constraint_description(key)
|
||||
row_html = render_to_string(
|
||||
"rota/partials/rota_option_row.html",
|
||||
{"rota": rota, "key": key, "value": parsed, "pretty": pretty},
|
||||
{"rota": rota, "key": key, "value": parsed, "pretty": pretty, "description": desc},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(row_html)
|
||||
@@ -658,9 +735,11 @@ def rota_option_edit(request, rota_id):
|
||||
vtype = "string"
|
||||
value = str(cur_val)
|
||||
|
||||
# Include description for the key in the edit modal
|
||||
desc = _get_constraint_description(key)
|
||||
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},
|
||||
{"form_action": reverse("rota:rota_option_edit", args=(rota.id,)), "initial": {"key": key, "value": value, "type": vtype}, "rota": rota, "description": desc},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
Reference in New Issue
Block a user