feat(ui): display door opening method and credential details in open longest ranking entries #24

Closed
opened 2026-09-21 13:29:53 +00:00 by gabogg · 0 comments
Owner

📌 Problem Statement

In the Tactical Operations Deck (DUAL_OPS_DECK), the "Doors Opened the Longest" ranking panel (#tactical-open-longest-panel) currently renders a single line per open door displaying:

  • Rank index (#1, #2, ...)
  • Door code ([ P-code ]) and Door name
  • Controller name
  • Sensor category badge
  • Live ticking duration (DURACIÓN: MM:SS)
  • Status badge ([ OPEN ] / [ ALARM ])

While this allows operators to see which doors are open and for how long, it provides zero visibility into HOW the door was opened. When investigating prolonged open states or security breaches, operators must navigate away to forensic logs to identify whether the door was opened by a legitimate cardholder, a manual exit button, or forced entry.


🎯 Proposed Solution

Modify each individual door entry in the "Doors Opened the Longest" ranking list to include a dedicated second line below the primary door telemetry, explicitly stating HOW it was opened.

Note

Layout Tradeoff: This intentionally doubles the vertical line height per entry in #tactical-open-longest-panel. This vertical space expansion is an explicit design decision prioritizing immediate operational context over compact density.

Second Line Display Requirements:

Below the main door information line, render a secondary contextual strip indicating:

  1. Manual Exit Button: If opened via request-to-exit / button:
    • Display badge/indicator: [BOTÓN / BOTÓN DE SALIDA] or [BUTTON / REX].
  2. Credential Authorization (Card / Fingerprint / PIN / Face Recognition):
    • Display the person's name and credential details reported by HikCentral:
    • e.g., PERSONA: Juan Pérez // TARJETA: 1049283 or CREDENCIAL: María Rodríguez [HUELLA].
    • If role or department is available: include role tag (e.g. // MANTENIMIENTO).
  3. Forced Entry / Direct Sensor Open / Unknown:
    • If no access event preceded the open transition (door forced open, maglock bypass, or sensor state changed directly):
    • Display hazard/warning badge: [APERTURA FORZADA / SENSOR DIRECTO] or [DESCONOCIDO].

🏗️ Technical Architecture & Seams

Backend (app/services/door_service.py & app/schemas/models.py):

  • DoorService.get_door_overview() already attaches active_cycle, personName, personRole, cardNo, and summaryLabel to each door in open_doors / open_longest.
  • Ensure the specific opening trigger mechanism (open_trigger: BUTTON | CREDENTIAL | MANUAL | FORCED | UNKNOWN) is resolved and serialized deterministically in the WebSocket snapshot and HTTP /api/doors/status response.

Frontend (app/static/js/src/ui/command_deck_adapter.js):

  • Update CommandDeckAdapter.renderOpenLongest(snapshot) to render the two-tier row structure:
    • Tier 1: Door Index, Code, Name, Controller, Duration, Status Badge.
    • Tier 2: Monospace secondary metadata row (text-[10px] text-slate-400 bg-slate-900/60 px-2 py-0.5 mt-1) displaying the opening method, actor name, and credential info.
  • Maintain seamless in-place timer updates (.open-dur-val) without destroying DOM nodes during live second-by-second updates.

✅ Acceptance Criteria

  • Each door row in the Open Longest panel displays a secondary row with opening method and credential details.
  • Button-triggered openings display [BOTÓN / REX].
  • Credential openings display the person's name and credential identifier reported by HikCentral.
  • Uncredentialed / forced door openings display an appropriate warning tag ([APERTURA FORZADA / SENSOR DIRECTO]).
  • Live duration timers continue ticking accurately without tearing or UI flickering.
  • Tested across both Spanish and English UI localizations.
## 📌 Problem Statement In the Tactical Operations Deck (`DUAL_OPS_DECK`), the "Doors Opened the Longest" ranking panel (`#tactical-open-longest-panel`) currently renders a single line per open door displaying: - Rank index (`#1`, `#2`, ...) - Door code (`[ P-code ]`) and Door name - Controller name - Sensor category badge - Live ticking duration (`DURACIÓN: MM:SS`) - Status badge (`[ OPEN ]` / `[ ALARM ]`) While this allows operators to see *which* doors are open and for *how long*, it provides zero visibility into **HOW** the door was opened. When investigating prolonged open states or security breaches, operators must navigate away to forensic logs to identify whether the door was opened by a legitimate cardholder, a manual exit button, or forced entry. --- ## 🎯 Proposed Solution Modify each individual door entry in the "Doors Opened the Longest" ranking list to include a dedicated second line below the primary door telemetry, explicitly stating **HOW** it was opened. > [!NOTE] > **Layout Tradeoff**: This intentionally doubles the vertical line height per entry in `#tactical-open-longest-panel`. This vertical space expansion is an explicit design decision prioritizing immediate operational context over compact density. ### Second Line Display Requirements: Below the main door information line, render a secondary contextual strip indicating: 1. **Manual Exit Button**: If opened via request-to-exit / button: - Display badge/indicator: `[BOTÓN / BOTÓN DE SALIDA]` or `[BUTTON / REX]`. 2. **Credential Authorization (Card / Fingerprint / PIN / Face Recognition)**: - Display the person's name and credential details reported by HikCentral: - e.g., `PERSONA: Juan Pérez // TARJETA: 1049283` or `CREDENCIAL: María Rodríguez [HUELLA]`. - If role or department is available: include role tag (e.g. `// MANTENIMIENTO`). 3. **Forced Entry / Direct Sensor Open / Unknown**: - If no access event preceded the open transition (door forced open, maglock bypass, or sensor state changed directly): - Display hazard/warning badge: `[APERTURA FORZADA / SENSOR DIRECTO]` or `[DESCONOCIDO]`. --- ## 🏗️ Technical Architecture & Seams ### Backend (`app/services/door_service.py` & `app/schemas/models.py`): - `DoorService.get_door_overview()` already attaches `active_cycle`, `personName`, `personRole`, `cardNo`, and `summaryLabel` to each door in `open_doors` / `open_longest`. - Ensure the specific opening trigger mechanism (`open_trigger`: `BUTTON` | `CREDENTIAL` | `MANUAL` | `FORCED` | `UNKNOWN`) is resolved and serialized deterministically in the WebSocket snapshot and HTTP `/api/doors/status` response. ### Frontend (`app/static/js/src/ui/command_deck_adapter.js`): - Update `CommandDeckAdapter.renderOpenLongest(snapshot)` to render the two-tier row structure: - **Tier 1**: Door Index, Code, Name, Controller, Duration, Status Badge. - **Tier 2**: Monospace secondary metadata row (`text-[10px] text-slate-400 bg-slate-900/60 px-2 py-0.5 mt-1`) displaying the opening method, actor name, and credential info. - Maintain seamless in-place timer updates (`.open-dur-val`) without destroying DOM nodes during live second-by-second updates. --- ## ✅ Acceptance Criteria - [ ] Each door row in the Open Longest panel displays a secondary row with opening method and credential details. - [ ] Button-triggered openings display `[BOTÓN / REX]`. - [ ] Credential openings display the person's name and credential identifier reported by HikCentral. - [ ] Uncredentialed / forced door openings display an appropriate warning tag (`[APERTURA FORZADA / SENSOR DIRECTO]`). - [ ] Live duration timers continue ticking accurately without tearing or UI flickering. - [ ] Tested across both Spanish and English UI localizations.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gabogg/hikcentral#24
No description provided.