.
This commit is contained in:
@@ -407,6 +407,56 @@ class RotaScheduleForm(forms.ModelForm):
|
||||
self.fields["end_date"].initial = end_date
|
||||
return cleaned
|
||||
|
||||
|
||||
class WorkerSelfServiceForm(forms.ModelForm):
|
||||
"""Small form exposed to workers via tokenized links so they can set
|
||||
their FTE and pick non-working days.
|
||||
"""
|
||||
WEEKDAYS = [
|
||||
('0', 'Monday'),
|
||||
('1', 'Tuesday'),
|
||||
('2', 'Wednesday'),
|
||||
('3', 'Thursday'),
|
||||
('4', 'Friday'),
|
||||
('5', 'Saturday'),
|
||||
('6', 'Sunday'),
|
||||
]
|
||||
|
||||
nwds = forms.MultipleChoiceField(choices=WEEKDAYS, required=False, widget=forms.CheckboxSelectMultiple, label="Non-working days")
|
||||
|
||||
class Meta:
|
||||
model = Worker
|
||||
fields = ["fte"]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
instance = kwargs.get('instance')
|
||||
initial = kwargs.get('initial', {})
|
||||
if instance is not None:
|
||||
try:
|
||||
opts = instance.options or {}
|
||||
nwds = opts.get('nwds', [])
|
||||
# store as strings for the MultipleChoiceField
|
||||
initial['nwds'] = [str(x) for x in (nwds or [])]
|
||||
initial['fte'] = instance.fte
|
||||
except Exception:
|
||||
pass
|
||||
kwargs['initial'] = initial
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
# persist non-working days into instance.options['nwds'] as list of ints
|
||||
opts = instance.options or {}
|
||||
nwds = self.cleaned_data.get('nwds') or []
|
||||
try:
|
||||
opts['nwds'] = [int(x) for x in nwds]
|
||||
except Exception:
|
||||
opts['nwds'] = nwds
|
||||
instance.options = opts
|
||||
if commit:
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
end_date = self.cleaned_data.get("end_date")
|
||||
|
||||
@@ -19,6 +19,7 @@ urlpatterns = [
|
||||
path("worker/<int:worker_id>/leaves.json", views.leaves_json, name="worker_leaves_json"),
|
||||
path("leave/request/", views.request_leave, name="request_leave"),
|
||||
path("leave/request/token/<uuid:token>/", views.request_leave, name="request_leave_token"),
|
||||
path("worker/settings/token/<uuid:token>/", views.worker_settings_token, name="worker_settings_token"),
|
||||
path("leave/<int:leave_id>/delete/", views.leave_delete, name="leave_delete"),
|
||||
path("worker/<int:worker_id>/regenerate_token/", views.regenerate_worker_token, name="regenerate_worker_token"),
|
||||
path("run/<int:run_id>/", views.rota_run_detail, name="rota_run_detail"),
|
||||
|
||||
@@ -3,6 +3,7 @@ from django.urls import reverse
|
||||
|
||||
from .models import RotaSchedule, Worker
|
||||
from .forms import WorkerForm, LeaveForm, RotaScheduleForm
|
||||
from .forms import WorkerSelfServiceForm
|
||||
from .services import run_rota_async
|
||||
from .forms import ShiftForm
|
||||
import json
|
||||
@@ -568,6 +569,51 @@ def request_leave(request, token=None):
|
||||
return render(request, "rota/leave_request.html", {"form": form, "worker": worker, "token": token})
|
||||
|
||||
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def worker_settings_token(request, token):
|
||||
"""Allow a worker identified by a request token to update simple settings
|
||||
such as FTE and non-working days without requiring authentication.
|
||||
"""
|
||||
worker = None
|
||||
if token:
|
||||
try:
|
||||
worker = get_object_or_404(Worker, request_token=token)
|
||||
except Exception:
|
||||
worker = None
|
||||
|
||||
if worker is None:
|
||||
return HttpResponseBadRequest("Invalid token")
|
||||
|
||||
is_hx = request.headers.get("HX-Request", "false").lower() == "true"
|
||||
|
||||
if request.method == "POST":
|
||||
form = WorkerSelfServiceForm(request.POST, instance=worker)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
if is_hx:
|
||||
# Return minimal fragment confirming success and trigger a leaveUpdated
|
||||
# so any calendars can refresh (if they rely on worker settings).
|
||||
resp = render_to_string("rota/partials/worker_settings_saved.html", {"worker": worker}, request=request)
|
||||
response = HttpResponse(resp)
|
||||
response["HX-Trigger"] = "closeModal,leaveUpdated"
|
||||
return response
|
||||
# Full page: redirect back to tokenized request page
|
||||
return redirect(reverse('rota:request_leave_token', args=[token]))
|
||||
else:
|
||||
form = WorkerSelfServiceForm(instance=worker)
|
||||
|
||||
# HTMX modal request: return partial modal
|
||||
if is_hx:
|
||||
modal_html = render_to_string(
|
||||
"rota/partials/worker_selfservice_modal.html",
|
||||
{"form": form, "form_action": request.get_full_path(), "worker": worker},
|
||||
request=request,
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
return render(request, "rota/worker_settings.html", {"form": form, "worker": worker, "token": token})
|
||||
|
||||
|
||||
def rota_options(request, rota_id):
|
||||
"""HTMX-aware modal edit for rota.options JSON.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user