feat: add supervisor role
This commit is contained in:
1 parent
dcd85bb911
commit
3af326251d
22 files changed
+270
-103
No files matched your search
@@ -29,14 +29,15 @@
|
||||
{% endif %}
|
||||
|
||||
{% set interactive = not is_past and spot.actionable %}
|
||||
{# An administrator may free somebody else's desk -- a colleague calls in sick and the spot
|
||||
should go back into the pool. Colours are untouched: MINE still means mine, and only
|
||||
clickability widens. Past days stay inert for admins too; there is no past-write path.
|
||||
{# A supervisor (and so an administrator) may free somebody else's desk -- a colleague calls in
|
||||
sick and the spot should go back into the pool. Colours are untouched: MINE still means
|
||||
mine, and only clickability widens. Past days stay inert for them too; there is no
|
||||
past-write path.
|
||||
|
||||
Only a card that is not already actionable: a partly booked one still opens the create
|
||||
modal, because taking the free window is the more useful act there and an admin can reach
|
||||
that booking from /admin/bookings anyway. #}
|
||||
{% set manageable = not is_past and not interactive and is_granted('ROLE_ADMIN') and spot.bookings is not empty %}
|
||||
modal, because taking the free window is the more useful act there and a supervisor can
|
||||
reach that booking from /manage/bookings anyway. #}
|
||||
{% set manageable = not is_past and not interactive and is_granted('ROLE_SUPERVISOR') and spot.bookings is not empty %}
|
||||
|
||||
{# One line per booking, then the window still free if there is one -- that last line is the
|
||||
reason a partly booked card is worth clicking, so it earns its place. #}
|
||||
@@ -78,9 +79,9 @@
|
||||
hx-target="body"
|
||||
hx-swap="beforeend"
|
||||
{%- elseif manageable %}
|
||||
{# Not app_booking_edit: a card can hold several bookings on one day, and an admin
|
||||
{# Not app_booking_edit: a card can hold several bookings on one day, and a supervisor
|
||||
releases rather than reschedules. The modal lists them and frees one. #}
|
||||
hx-get="{{ path('app_admin_spot', { id: spot.resource.id, date: selected_date|date('Y-m-d') }|merge(time_params)) }}"
|
||||
hx-get="{{ path('app_manage_spot', { id: spot.resource.id, date: selected_date|date('Y-m-d') }|merge(time_params)) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend"
|
||||
{%- endif %}>
|
||||
|
||||
@@ -62,11 +62,12 @@
|
||||
{% endif %}
|
||||
|
||||
{#
|
||||
The header is deliberately not navigation, so the dashboard is the only place an
|
||||
admin screen can be reached from.
|
||||
The header is deliberately not navigation, so the dashboard is the only place the
|
||||
overview and the admin screens can be reached from. ROLE_SUPERVISOR includes
|
||||
administrators through role_hierarchy.
|
||||
#}
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<a href="{{ path('app_admin_booking') }}"
|
||||
{% if is_granted('ROLE_SUPERVISOR') %}
|
||||
<a href="{{ path('app_manage_booking') }}"
|
||||
class="group flex flex-col rounded-md border border-gray-200 p-6 hover:border-primary hover:bg-gray-50">
|
||||
<div class="flex items-center gap-3 pb-2">
|
||||
{{ ux_icon('lucide:shield-check', { class: 'h-6 w-6 shrink-0 text-primary' }) }}
|
||||
@@ -76,7 +77,9 @@
|
||||
Buchungen aller Mitarbeitenden einsehen und ggf. freigeben.
|
||||
</p>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<a href="{{ path('app_admin_resource') }}"
|
||||
class="group flex flex-col rounded-md border border-gray-200 p-6 hover:border-primary hover:bg-gray-50">
|
||||
<div class="flex items-center gap-3 pb-2">
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{#
|
||||
What an administrator sees when clicking an occupied shape on the floor plan.
|
||||
What a supervisor (or an administrator) sees when clicking an occupied shape on the floor plan.
|
||||
|
||||
Not the edit modal: a shape can hold several bookings on one day once part-day spans exist,
|
||||
so "the booking" has no single referent -- and an administrator releases rather than
|
||||
reschedules. Each row posts to the ordinary app_booking_release route, whose ownership check
|
||||
admits an admin, so there is still one code path that removes a booking.
|
||||
so "the booking" has no single referent -- and a supervisor releases rather than reschedules.
|
||||
Each row posts to the ordinary app_booking_release route, whose ownership check admits
|
||||
supervisors, so there is still one code path that removes a booking.
|
||||
#}
|
||||
{% extends 'htmx_modal.html.twig' %}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
Filtering is a plain GET form -- the house rule hands navigation to the browser. The two
|
||||
destructive actions open the shared confirmation modal via htmx and then navigate back here,
|
||||
which is what ?return=admin says; without it a confirmed release swaps board fragments this
|
||||
which is what ?return=manage says; without it a confirmed release swaps board fragments this
|
||||
page does not have.
|
||||
|
||||
The appointment table is paginated; the series table is not, because a company has a handful of
|
||||
@@ -28,7 +28,7 @@
|
||||
{{ form_row(form.user) }}
|
||||
</div>
|
||||
<div class="flex justify-end gap-2 pt-2">
|
||||
<a class="button button--small button--neutral" href="{{ path('app_admin_booking') }}">Zurücksetzen</a>
|
||||
<a class="button button--small button--neutral" href="{{ path('app_manage_booking') }}">Zurücksetzen</a>
|
||||
<button type="submit" class="button button--small button--primary">Filtern</button>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
@@ -58,7 +58,7 @@
|
||||
<td>{{ entry.endDate|format_datetime(pattern: 'd. MMMM y') }}</td>
|
||||
<td class="text-right">
|
||||
<button type="button" class="button button--small button--warning"
|
||||
hx-get="{{ path('app_series_end', { id: entry.id, return: 'admin' }) }}"
|
||||
hx-get="{{ path('app_series_end', { id: entry.id, return: 'manage' }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
Wiederholung beenden
|
||||
@@ -115,7 +115,7 @@
|
||||
<a class="button button--small button--neutral"
|
||||
href="{{ path('app_board', { type: booking.resource.type.value, date: booking.date|date('Y-m-d') }) }}">Im Plan</a>
|
||||
<button type="button" class="button button--small button--warning"
|
||||
hx-get="{{ path('app_booking_release', { id: booking.id, return: 'admin' }) }}"
|
||||
hx-get="{{ path('app_booking_release', { id: booking.id, return: 'manage' }) }}"
|
||||
hx-target="body"
|
||||
hx-swap="beforeend">
|
||||
Freigeben
|
||||
Reference in new issue
Block a user