3.3 KiB
3.3 KiB
Research — Tenant UI Polish (Dashboard + Inventory Hub + Operations)
Goal
Deliver a drift-first, tenant-scoped UI polish pass that is:
- DB-only on render and on any auto-refresh.
- Calm (polling only when needed; no modal churn).
- Consistent IA (Inventory hub sub-navigation; canonical Operations).
Existing Code & Patterns (to reuse)
Operations
- Canonical list/detail already exist via
OperationRunResource(/operations). - Tenant scoping already enforced in
OperationRunResource::getEloquentQuery(). - Detail view already uses conditional polling with safeguards (tab hidden / modal open) via
RunDetailPolling.
Inventory
- Inventory entry page exists as
InventoryLanding. - Inventory “Items” and “Sync Runs” are currently resources (
InventoryItemResource,InventorySyncRunResource). - Inventory sync “start surface” already follows constitution rules: authorize → create/reuse
OperationRun→ enqueue job → “View run”.
Monitoring DB-only + Tenant isolation tests
- Monitoring/Operations has DB-only tests and tenant scope tests.
- Inventory landing + coverage have basic smoke tests.
Key Decisions
Decision: Use Filament clusters to implement the Inventory “hub” navigation
- Decision: Create an Inventory cluster and attach:
InventoryLanding(page)- Inventory items resource
- Inventory sync runs resource
InventoryCoverage(page)
- Rationale: Filament clusters are designed for “common sub-navigation between pages”, including mixing pages and resources.
- Notes:
- Requires enabling cluster discovery in the panel provider.
- Sub-navigation position will be set to
Startto achieve left-side navigation.
Decision: Implement KPI headers as widgets (StatsOverviewWidget / TableWidget)
- Decision: Use Filament widgets for KPI headers on:
- Tenant dashboard (drift + ops)
- Inventory hub (inventory KPIs)
- Operations index (ops KPIs)
- Rationale: Widgets are first-class, composable, and can optionally poll (with
$pollingInterval) while remaining DB-only.
Decision: “Calm UI” auto-refresh strategy
- Decision:
- Dashboard + Operations index: enable polling only while active runs exist.
- Widgets/tables: polling is disabled when no active runs exist.
- No polling inside modals.
- Rationale: Matches FR-012 and avoids background churn.
- Implementation approach:
- Use Filament polling mechanisms:
- Widgets:
$pollingInterval = null | '10s'depending on “active runs exist”. - Tables: enable
$table->poll('10s')only when “active runs exist”.
- Widgets:
- Use Filament polling mechanisms:
Decision: No Graph / remote dependencies
- Decision: All queries for this feature are Eloquent/PostgreSQL queries.
- Rationale: Matches constitution and SC-005.
Alternatives Considered
- Custom Blade layouts for hub navigation: Rejected because clusters provide consistent sub-nav across resources/pages without fragile view overrides.
- Always-on polling: Rejected to comply with calm UI rules and avoid waste.
- Keep
Monitoring/Operationsas canonical: Rejected becauseOperationRunResourceis already the canonical Operations surface with correct routing and detail pages.
Open Questions
None — all “NEEDS CLARIFICATION” items are resolved for planning.