docs(tasks): add Phase 5 Sessions UI overhaul, slide-over guest drawer, and revoke fix task
This commit is contained in:
parent
0c4f7ac5d2
commit
a194844309
@ -0,0 +1,96 @@
|
|||||||
|
# TASK METADATA
|
||||||
|
|
||||||
|
- **Target Files:** `server/routes/sessions.ts`, `server/routes/events.ts`, `ui/components/SessionsPage.tsx`, `ui/components/sessions/EventCockpitDeck.tsx`, `ui/components/sessions/EventAttendeesDrawer.tsx` (refactored/renamed to `EventGuestsDrawer.tsx`), `ui/components/sessions/SessionDeck.tsx`, `ui/components/sessions/SessionTable.tsx`, `ui/components/sessions/SessionsScript.tsx`, `server/tests/events.test.ts`, `server/tests/scopes.test.ts`, `ui/ui_scripts.test.ts`
|
||||||
|
- **Core Objective:** Implement Phase 5 Overhaul: Fix backend attendee session revocation permission checks, build a true fixed slide-over Guest Drawer, standardize dynamic countdown pills, add multi-event compact density toggle, and clean up page/session visual hierarchy.
|
||||||
|
- **Dependencies:** None.
|
||||||
|
- **Additional Important Notes:** Must remain 100% pure React-free Hono SSR JSX. All client interactions in `SessionsScript.tsx` must use native vanilla JavaScript DOM APIs.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Architectural Considerations & Risks
|
||||||
|
|
||||||
|
- **Risks:**
|
||||||
|
- **Zero-Trust Revocation Leakage:** When allowing event creators to delete/revoke attendee sessions via `DELETE /api/sessions/:id`, ensure the query strictly verifies that the session belongs to a guest user claimed under an event pass created by `auth.userId` (or that caller is global admin). Never allow arbitrary session deletions across different event creators.
|
||||||
|
- **DOM Stacking & Focus Trapping:** A fixed slide-over drawer must properly layer (`z-index: 1050`) over the background page and support backdrop dismissal and `Escape` key capture without disrupting background table states.
|
||||||
|
- **Mobile Density Regressions:** Ensure the mobile slide-up bottom sheet does not block necessary viewport scrolling or clip action buttons on small mobile viewports (320px–375px).
|
||||||
|
|
||||||
|
- **Alternatives:**
|
||||||
|
- *In-Page Expandable Row vs. Fixed Slide-Over Panel:* In-page expandable cards cause massive vertical jumping and layout disruption when 5–10 events are active. A dedicated fixed slide-over drawer (right panel on desktop, bottom sheet on mobile) provides isolated context, independent scrolling, and a pinned summary header without disturbing the background dashboard.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Proposed Implementation
|
||||||
|
|
||||||
|
### Phase 1: Backend Revocation Permission Fix (`server/routes/sessions.ts`)
|
||||||
|
|
||||||
|
1. **Authorize Event Creators in `DELETE /api/sessions/:id`:**
|
||||||
|
- Update `DELETE /api/sessions/:id` to check whether the target session is owned by `auth.userId`, or if caller is `isGlobalAdmin`, OR if the session belongs to a guest user of an event pass created by `auth.userId`:
|
||||||
|
```sql
|
||||||
|
SELECT s.id
|
||||||
|
FROM sessions s
|
||||||
|
JOIN users u ON s.user_id = u.id
|
||||||
|
WHERE s.id = ${targetSessionId}
|
||||||
|
AND (
|
||||||
|
s.user_id = ${auth.userId}
|
||||||
|
OR ${isAdmin}
|
||||||
|
OR EXISTS (
|
||||||
|
SELECT 1 FROM event_passes ep
|
||||||
|
WHERE ep.created_by = ${auth.userId}
|
||||||
|
AND u.username LIKE 'guest_' || ep.slug || '_%'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
- If found, delete the session from Valkey cache (`valkey.del`) and PostgreSQL (`DELETE FROM sessions WHERE id = ${targetSessionId}`), logging the audit event.
|
||||||
|
- Return `{ success: true }`.
|
||||||
|
|
||||||
|
### Phase 2: Page Hierarchy & Section Titles (`ui/components/SessionsPage.tsx`)
|
||||||
|
|
||||||
|
1. **Page Title:**
|
||||||
|
- Update top `<h1>` in `SessionsPage.tsx` from `Active Sessions & Passes` to **`Sessions & Passes`**.
|
||||||
|
2. **Missing Section Headings:**
|
||||||
|
- Section 1: `<h2>Event Passes</h2>` (with compact density toggle).
|
||||||
|
- Section 2: Add a prominent `<h2>Sessions</h2>` heading directly above `SessionTable` and `SessionDeck` with subtitle *"Direct device logins, passkey authentications, and delegated agent tokens."*
|
||||||
|
|
||||||
|
### Phase 3: True Fixed Slide-Over Panel (`EventGuestsDrawer.tsx` & `SessionsScript.tsx`)
|
||||||
|
|
||||||
|
1. **Drawer Component Overhaul (`ui/components/sessions/EventAttendeesDrawer.tsx` -> `EventGuestsDrawer.tsx`):**
|
||||||
|
- Refactor the component from an in-line `<div class="card">` into a fixed slide-over overlay:
|
||||||
|
- **Desktop:** `position: fixed; top: 0; right: 0; width: 420px; height: 100vh; background: var(--surface-card); box-shadow: var(--shadow-lg); z-index: 1050; display: flex; flex-direction: column;`
|
||||||
|
- **Mobile:** Full-width slide-up bottom sheet (`width: 100vw; height: 80vh; bottom: 0; right: 0; border-radius: 16px 16px 0 0;`).
|
||||||
|
- **Backdrop:** Dimmed backdrop overlay (`position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 1040;`) closing on click.
|
||||||
|
2. **Pinned Contextual Header:**
|
||||||
|
- **Title:** `<h2 id="guestDrawerTitle" style="margin: 0; font-size: 1.25rem;">[Event Name] Guests</h2>`
|
||||||
|
- **Subheader Context Bar:** `<div id="guestDrawerContext" style="font-size: 0.8rem; color: var(--text-secondary); margin-top: 0.25rem;">Event Pass · [N] / [Max] Claimed Seats · ⏳ [Xh Ym left] · (Expires [Time])</div>`
|
||||||
|
- **Close Button:** Accessible close button in top right.
|
||||||
|
3. **Streamlined Roster Rows (`SessionsScript.tsx`):**
|
||||||
|
- Discard repeated static expiration timestamps from individual rows.
|
||||||
|
- Render clean, distinct cards for each guest seat:
|
||||||
|
- **Left:** `Seat #[N]` (`guest_<slug>_<N>`) + relative join timestamp (`Joined 5m ago`).
|
||||||
|
- **Status Badge:** `🟢 Active` / `⏸️ Paused`.
|
||||||
|
- **Right Actions:** Compact `[ ⏸️ Pause ]` / `[ ▶️ Resume ]` toggle and `[ 🗑️ Revoke ]` trigger.
|
||||||
|
4. **Standardize Terminology:**
|
||||||
|
- Use **`Event Guests`** and **`Claimed Seats`** across all drawer titles, buttons (`[ 👥 Manage Guests (N) ]`), and notices.
|
||||||
|
|
||||||
|
### Phase 4: Dynamic Countdown Standardization & Density Polish (`EventCockpitDeck.tsx`, `SessionDeck.tsx`, `SessionTable.tsx`)
|
||||||
|
|
||||||
|
1. **Standardized Countdown Pill:**
|
||||||
|
- Create a reusable countdown formatter rendering: `⏳ 2h 45m left · (Expires 10:39 PM)` (or `⏳ 29d left · (Expires Sep 25)`).
|
||||||
|
- Dynamic status coloring: **Green** (healthy) -> **Amber** (<1h remaining) -> **Red** (expired).
|
||||||
|
- Apply consistently across Event Pass Cards and the Sessions Table/Deck.
|
||||||
|
2. **Multi-Event Compact Density Toggle (`EventCockpitDeck.tsx`):**
|
||||||
|
- Add a `[ 🗂️ Grid ]` / `[ 📋 Compact ]` density toggle at the top of the `Event Passes` section.
|
||||||
|
- In **Compact Mode**, collapse each event card into a sleek 1-row summary strip (`Title · 🟢 Active · ⏳ 2h 45m left · 12/50 Seats · PIN: 749-123 · [ 👥 Guests (12) ] · [ ▸ Details ]`), fitting 10+ active events in a single screen.
|
||||||
|
3. **Mobile Session Card Optimization (`SessionDeck.tsx`):**
|
||||||
|
- Remove the dedicated full-width bottom row on remote session cards.
|
||||||
|
- Move `[ 🗑️ Revoke ]` inline into the top card header row next to the status badge as a compact button (`btn-outline-danger`), reducing card height by 50% and fitting 4–5 more sessions per screen.
|
||||||
|
|
||||||
|
### Phase 5: Quality Gates & Testing
|
||||||
|
|
||||||
|
1. **Unit Tests (`server/tests/events.test.ts` & `scopes.test.ts`):**
|
||||||
|
- Test event host revoking a guest attendee session via `DELETE /api/sessions/:id` succeeds (200 OK).
|
||||||
|
- Test non-owner unauthorized user attempting to revoke an attendee session is rejected (404/403).
|
||||||
|
- Test guest list API returns active claimed seats.
|
||||||
|
2. **Hermetic UI Validation (`ui/ui_scripts.test.ts`):**
|
||||||
|
- Verify all vanilla JavaScript drawer controllers, density toggles, and countdown scripts in `SessionsScript.tsx` parse and evaluate cleanly with zero syntax errors.
|
||||||
|
3. **Formatting & Linting:**
|
||||||
|
- Ensure `deno fmt`, `deno task lint`, `deno task check`, and `deno test --allow-all` execute with 100% green status.
|
||||||
Loading…
x
Reference in New Issue
Block a user