Jul 9 - Update Dashboard separate open issue by Handler (add new cards)

This commit is contained in:
2026-07-09 13:05:07 -04:00
parent 59218a6717
commit 5ab816a158
2 changed files with 42 additions and 22 deletions
+4 -4
View File
@@ -1029,13 +1029,13 @@ The dashboard cards are organised into two labelled sections separated by a divi
4. Pending Follow-ups — inspections with `follow_up_required=True`; links to `inspections.index?status=follow_up` 4. Pending Follow-ups — inspections with `follow_up_required=True`; links to `inspections.index?status=follow_up`
**Issues section** (customers see first 3; staff see all 5): **Issues section** (customers see first 3; staff see all 5):
1. Open Issues — `status=open` with severity breakdown badges (C/H/M/L) **and** a "Handled by" split (Janitorial Staff / Facility Staff / External Vendor) from `handler_breakdown`. 1. Open Issues — **split into THREE cards** (all roles), one per handler from `handler_breakdown`: **Open · Janitorial** (`handler_type=internal`, bg-primary), **Open · Facility Staff** (`handler_type=facility`, bg-info), **Open · Vendor** (`handler_type=vendor`, bg-warning). Each is a full clickable card linking to `issues.index?status=open&handler_type=...`. (The single total Open-Issues card with severity C/H/M/L badges was replaced by these three; `severity_breakdown` is still passed but no longer rendered on the dashboard.)
2. Issues Opened Today — `date_from=today&date_to=today`, with a "Handled by" split from `opened_today_handler`. 2. Issues Opened Today — `date_from=today&date_to=today`, with a compact "Handled by" chip split from `opened_today_handler`.
3. Resolved Today — `status=resolved` + today's date range 3. Resolved Today — `status=resolved` + today's date range
4. Pending Verification — `status=pending_verification` 4. Pending Verification — `status=pending_verification`
5. Unassigned Open — `status=open&unassigned=1`, with a "Handled by" split from `unassigned_handler`. 5. Unassigned Open — `status=open&unassigned=1`, with a compact "Handled by" chip split from `unassigned_handler`.
**"Handled by" splits (phase35+):** cards 1, 2, and 5 render a handler breakdown via the `handler_chips(bd, base)` **Jinja macro** at the top of `dashboard.html` — full-text labels ("Janitorial N / Facility N / Vendor N") that each link to `issues.index` with the card's own filter (`base`) plus `handler_type=`. Breakdowns come from `_handler_split(list)` over the already-loaded issue lists (`open_issues_all`, `opened_today_all`, `unassigned_all`) — **no extra queries**. These three cards are no longer a single wrapping anchor — the count and each chip are separate links (nested `<a>` is invalid). `issues.index` gained an **`unassigned=1`** filter (`Issue.assigned_to.is_(None)`) so the Unassigned card and its chips link precisely; it is threaded through the list pagination links. **"Handled by" splits (phase35+):** the three Open-Issue cards are dedicated cards; cards 2 and 5 use the compact `handler_chips(bd, base)` **Jinja macro** at the top of `dashboard.html` — full-text chips ("Janitorial N / Facility N / Vendor N") linking to `issues.index` with the card's own filter (`base`) plus `handler_type=`. All breakdowns come from `_handler_split(list)` over already-loaded issue lists (`open_issues_all`, `opened_today_all`, `unassigned_all`) — **no extra queries**. Cards with inner links are not wrapped in an outer anchor (nested `<a>` is invalid). `issues.index` gained an **`unassigned=1`** filter (`Issue.assigned_to.is_(None)`), threaded through the list pagination links, so the Unassigned card and its chips link precisely.
Each card has a subtitle line (or the handler split) explaining what it counts. Section dividers use `d-flex align-items-center gap-2` with a `<div style="flex:1;height:1px;background:#e2e8f0;">` rule. Each card has a subtitle line (or the handler split) explaining what it counts. Section dividers use `d-flex align-items-center gap-2` with a `<div style="flex:1;height:1px;background:#e2e8f0;">` rule.
+36 -16
View File
@@ -156,30 +156,50 @@
</div> </div>
<div class="row g-3 mb-4"> <div class="row g-3 mb-4">
{# Open issues split into three cards by who handles them. #}
<div class="col-6 col-md"> <div class="col-6 col-md">
<div class="card text-white bg-warning h-100"> <a href="{{ url_for('issues.index', status='open', handler_type='internal') }}" class="text-decoration-none">
<div class="card text-white bg-primary h-100">
<div class="card-body"> <div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-1"> <div class="d-flex justify-content-between align-items-start mb-1">
<span class="small text-white-50 fw-semibold">Open Issues</span> <span class="small text-white-50 fw-semibold">Open · Janitorial</span>
<i class="bi bi-exclamation-triangle" style="font-size:1.4rem;opacity:.3;"></i> <i class="bi bi-people" style="font-size:1.4rem;opacity:.3;"></i>
</div>
<div class="fs-1 fw-bold lh-1">{{ handler_breakdown.internal }}</div>
<div class="mt-2" style="font-size:.72rem;opacity:.7;">Open issues handled by our crew</div>
</div>
</div> </div>
<a href="{{ url_for('issues.index', status='open') }}" class="text-white text-decoration-none">
<div class="fs-1 fw-bold lh-1">{{ open_issues }}</div>
</a> </a>
{% if open_issues > 0 %}
<div class="mt-2" style="font-size:.72rem;opacity:.85;">
{% if severity_breakdown.critical > 0 %}<span class="badge bg-danger">{{ severity_breakdown.critical }}C</span> {% endif %}
{% if severity_breakdown.high > 0 %}<span class="badge bg-danger">{{ severity_breakdown.high }}H</span> {% endif %}
{% if severity_breakdown.medium > 0 %}<span class="badge bg-dark">{{ severity_breakdown.medium }}M</span> {% endif %}
{% if severity_breakdown.low > 0 %}<span class="badge bg-secondary">{{ severity_breakdown.low }}L</span>{% endif %}
</div> </div>
{# ── Split by who handles it (click to drill in) ── #}
{{ handler_chips(handler_breakdown, {'status': 'open'}) }} <div class="col-6 col-md">
{% else %} <a href="{{ url_for('issues.index', status='open', handler_type='facility') }}" class="text-decoration-none">
<div class="mt-2" style="font-size:.72rem;opacity:.75;">Active issues not yet resolved</div> <div class="card text-dark bg-info h-100">
{% endif %} <div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-1">
<span class="small fw-semibold" style="color:rgba(0,0,0,.55);">Open · Facility Staff</span>
<i class="bi bi-building" style="font-size:1.4rem;opacity:.3;"></i>
</div>
<div class="fs-1 fw-bold lh-1">{{ handler_breakdown.facility }}</div>
<div class="mt-2" style="font-size:.72rem;color:rgba(0,0,0,.6);">Open issues the facility staff handle</div>
</div> </div>
</div> </div>
</a>
</div>
<div class="col-6 col-md">
<a href="{{ url_for('issues.index', status='open', handler_type='vendor') }}" class="text-decoration-none">
<div class="card text-dark bg-warning h-100">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start mb-1">
<span class="small fw-semibold" style="color:rgba(0,0,0,.55);">Open · Vendor</span>
<i class="bi bi-person-gear" style="font-size:1.4rem;opacity:.3;"></i>
</div>
<div class="fs-1 fw-bold lh-1">{{ handler_breakdown.vendor }}</div>
<div class="mt-2" style="font-size:.72rem;color:rgba(0,0,0,.6);">Open issues an outside vendor handles</div>
</div>
</div>
</a>
</div> </div>
<div class="col-6 col-md"> <div class="col-6 col-md">