.
This commit is contained in:
@@ -2,7 +2,14 @@
|
||||
<div id="leave-list">
|
||||
<ul>
|
||||
{% for l in leaves %}
|
||||
<li data-start="{{ l.start_date|date:'Y-m-d' }}" data-end="{{ l.end_date|date:'Y-m-d' }}">{{ l.start_date }} → {{ l.end_date }}{% if l.reason %} ({{ l.reason }}){% endif %}</li>
|
||||
<li data-start="{{ l.start_date|date:'Y-m-d' }}" data-end="{{ l.end_date|date:'Y-m-d' }}">
|
||||
<span class="leave-range">{{ l.start_date }} → {{ l.end_date }}</span>{% if l.reason %} <em>({{ l.reason }})</em>{% endif %}
|
||||
<form method="post" hx-post="{% url 'rota:leave_delete' l.id %}" hx-target="#leave-list" hx-swap="outerHTML" style="display:inline;margin-left:0.5rem">
|
||||
{% csrf_token %}
|
||||
{% if token %}<input type="hidden" name="token" value="{{ token }}">{% endif %}
|
||||
<button class="button is-small is-danger" type="submit" onclick="return confirm('Delete this leave request?');">Delete</button>
|
||||
</form>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>No leave recorded</li>
|
||||
{% endfor %}
|
||||
|
||||
@@ -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("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"),
|
||||
path("run/<int:run_id>/export/html/", views.rota_run_export_html, name="rota_run_export_html"),
|
||||
|
||||
@@ -512,7 +512,7 @@ def request_leave(request, token=None):
|
||||
# Render updated leave list and return OOB swaps: update leave-list and clear modal.
|
||||
leave_list_html = render_to_string(
|
||||
"rota/partials/leave_list.html",
|
||||
{"leaves": worker.leaves.all()},
|
||||
{"leaves": worker.leaves.all(), "token": token},
|
||||
request=request,
|
||||
)
|
||||
resp = (
|
||||
@@ -563,7 +563,7 @@ def request_leave(request, token=None):
|
||||
)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
return render(request, "rota/leave_request.html", {"form": form, "worker": worker})
|
||||
return render(request, "rota/leave_request.html", {"form": form, "worker": worker, "token": token})
|
||||
|
||||
|
||||
def rota_options(request, rota_id):
|
||||
@@ -952,6 +952,51 @@ def leaves_json(request, worker_id):
|
||||
return JsonResponse({'leaves': data})
|
||||
|
||||
|
||||
@require_POST
|
||||
def leave_delete(request, leave_id):
|
||||
"""Delete a Leave record. Allowed if the requester is staff, or if a valid token matches the worker, or the authenticated user's email matches the worker email."""
|
||||
from .models import Leave
|
||||
|
||||
leave = get_object_or_404(Leave, pk=leave_id)
|
||||
worker = leave.worker
|
||||
|
||||
# permission checks
|
||||
allowed = False
|
||||
token = request.POST.get('token') or request.GET.get('token')
|
||||
try:
|
||||
if request.user and request.user.is_authenticated and request.user.is_staff:
|
||||
allowed = True
|
||||
elif request.user and request.user.is_authenticated and getattr(request.user, 'email', None) and request.user.email == (worker.email or ''):
|
||||
allowed = True
|
||||
elif token:
|
||||
try:
|
||||
import uuid
|
||||
token_uuid = uuid.UUID(token)
|
||||
if worker.request_token == token_uuid:
|
||||
allowed = True
|
||||
except Exception:
|
||||
allowed = False
|
||||
except Exception:
|
||||
allowed = False
|
||||
|
||||
if not allowed:
|
||||
return HttpResponseBadRequest('Permission denied')
|
||||
|
||||
# perform delete
|
||||
leave.delete()
|
||||
|
||||
# render updated leave list for the worker
|
||||
leave_list_html = render_to_string(
|
||||
"rota/partials/leave_list.html",
|
||||
{"leaves": worker.leaves.all(), "token": token},
|
||||
request=request,
|
||||
)
|
||||
resp = f'<div id="leave-list" hx-swap-oob="true">{leave_list_html}</div>'
|
||||
response = HttpResponse(resp)
|
||||
response["HX-Trigger"] = "leaveUpdated"
|
||||
return response
|
||||
|
||||
|
||||
@require_POST
|
||||
def rota_run_export_regenerate(request, run_id):
|
||||
"""Regenerate the HTML export for a completed run and persist it on the RotaRun.
|
||||
|
||||
Reference in New Issue
Block a user