tenantpilot/specs/003-policy-explorer-ux/tasks.md
Ahmed Darrazi f592e5f55b feat: Policy Explorer UX Upgrade (003)
Implemented MVP with all core features:
- Browse 50 newest policies on load with null filtering
- Click row to view details in slide-over sheet
- JSON detection and pretty formatting
- Search with real-time filtering
- Badge colors for policy types (Security=red, Compliance=blue, Config=gray, App=outline)
- Navigation consolidated to 'Policy Explorer'

New components:
- PolicyTable.tsx - table with badges and hover effects
- PolicySearchContainer.tsx - search state management
- PolicyDetailSheet.tsx - JSON detail view with formatting
- PolicyExplorerClient.tsx - client wrapper
- lib/utils/policyBadges.ts - badge color mapping

Updated:
- lib/actions/policySettings.ts - added getRecentPolicySettings() with null filtering
- app/(app)/search/page.tsx - converted to Server Component
- config/nav.ts - renamed Search to Policy Explorer, removed All Settings
- components/search/EmptyState.tsx - updated messaging

Tasks complete: 36/47 (MVP ready)
- Phase 1-7: All critical features implemented
- Phase 8: Core polish complete (T041), optional tasks remain

TypeScript:  No errors
Status: Production-ready MVP
2025-12-07 02:28:15 +01:00

335 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Tasks: Policy Explorer UX Upgrade
**Input**: Design documents from `/specs/003-policy-explorer-ux/`
**Prerequisites**: spec.md ✅, plan.md ✅
**Branch**: `003-policy-explorer-ux`
**Generated**: 2025-12-07
**Tests**: Tests are NOT included in this task list as they were not explicitly requested in the feature specification.
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
## Format: `- [ ] [ID] [P?] [Story?] Description with file path`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (US1, US2, US3, US4)
- File paths are absolute from repository root
---
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Verify prerequisites and install missing Shadcn UI components
- [X] T001 [P] Verify Shadcn Sheet component exists at `components/ui/sheet.tsx`, install if missing via `npx shadcn@latest add sheet`
- [X] T002 [P] Verify Shadcn Badge component exists at `components/ui/badge.tsx`, install if missing via `npx shadcn@latest add badge`
- [X] T003 Create new directory `components/policy-explorer/` for new feature components
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Core backend infrastructure that MUST be complete before ANY user story can be implemented
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
### Backend Server Actions
- [X] T004 Add `getRecentPolicySettings(limit?: number)` Server Action in `lib/actions/policySettings.ts` - returns 50 newest policies sorted by lastSyncedAt DESC, filtered by tenantId and excluding null values
- [X] T005 Extend `searchPolicySettings()` Server Action in `lib/actions/policySettings.ts` - add optional `limit` parameter (default 100, max 200)
- [X] T006 Add null-value filtering logic to Server Actions - filter out entries where `settingValue === "null"` or `settingValue === null` (backend approach for performance)
- [X] T007 Add type exports for `PolicySettingSearchResult` interface if not already exported from `lib/actions/policySettings.ts`
- [X] T008 Test Server Actions manually - verify tenant isolation, null filtering, and limit parameters work correctly
**Checkpoint**: Backend ready - all Server Actions functional and tested
---
## Phase 3: User Story 1 - Browse Recent Policies on Page Load (Priority: P1) 🎯 MVP
**Goal**: Admin sees 50 newest policy settings immediately when opening Policy Explorer (no empty state)
**Independent Test**: Navigate to `/policy-explorer`, verify 50 newest entries load without search, no null values visible
### Implementation for User Story 1
- [X] T009 [P] [US1] Create `PolicyTable.tsx` component in `components/policy-explorer/PolicyTable.tsx` - display policies in table format with columns: Setting Name, Setting Value, Policy Name, Policy Type, Last Synced
- [X] T010 [P] [US1] Add row click handler prop to `PolicyTable` component - accepts `onRowClick: (policy: PolicySettingSearchResult) => void`
- [X] T011 [P] [US1] Add hover styles to table rows in `PolicyTable` - `hover:bg-accent cursor-pointer` classes
- [X] T012 [P] [US1] Create `PolicySearchContainer.tsx` client component in `components/policy-explorer/PolicySearchContainer.tsx` - manages search state, accepts `initialPolicies` prop
- [X] T013 [US1] Refactor `app/(app)/search/page.tsx` to Server Component pattern - call `getRecentPolicySettings(50)` in Server Component, pass data to `PolicySearchContainer`
- [X] T014 [US1] Update page CardTitle to "Policy Explorer" and CardDescription in `app/(app)/search/page.tsx`
- [X] T015 [US1] Add empty state handling - if no policies returned, show message "Keine Policies gefunden - Starten Sie einen Sync"
- [X] T016 [US1] Keep existing `SyncButton` component in CardHeader of `app/(app)/search/page.tsx`
**Checkpoint**: Page loads with 50 newest policies, no null values, empty state works
---
## Phase 4: User Story 2 - View Policy Details in Slide-Over Sheet (Priority: P1) 🎯 MVP
**Goal**: Admin can click any policy row to see full details with formatted JSON in a slide-over sheet
**Independent Test**: Click any table row, verify sheet opens from right with policy details, JSON is formatted
### Implementation for User Story 2
- [X] T017 [P] [US2] Create `PolicyDetailSheet.tsx` component in `components/policy-explorer/PolicyDetailSheet.tsx` - uses Shadcn Sheet, accepts `policy`, `open`, `onOpenChange` props
- [X] T018 [P] [US2] Implement JSON detection logic in `PolicyDetailSheet` - check if `settingValue.trim().startsWith('{')` or `startsWith('[')`
- [X] T019 [P] [US2] Implement JSON formatting utility - `JSON.stringify(JSON.parse(value), null, 2)` wrapped in try/catch, fallback to plain text on error
- [X] T020 [P] [US2] Render JSON values in `<pre>` tag with Tailwind prose classes for readability in `PolicyDetailSheet`
- [X] T021 [P] [US2] Render non-JSON values as normal text in `PolicyDetailSheet`
- [X] T022 [P] [US2] Add Sheet styling - proper width (e.g., `w-[600px]`), padding, close button, scroll for long content (`max-height` + `overflow-auto`)
- [X] T023 [US2] Integrate `PolicyDetailSheet` into `PolicySearchContainer` - add state for selected policy and sheet open/close
- [X] T024 [US2] Connect row click handler from `PolicyTable` to open detail sheet with clicked policy data
- [X] T025 [US2] Test detail sheet with various data - nested JSON objects, arrays, long strings (>10KB), plain text values, malformed JSON
**Checkpoint**: Clicking rows opens detail sheet, JSON is formatted, sheet closes properly
---
## Phase 5: User Story 3 - Search with Data Cleaning (Priority: P2)
**Goal**: Admin can search policies and results are filtered to exclude null values
**Independent Test**: Enter search term "USB", verify results contain "USB" and no null values
### Implementation for User Story 3
- [X] T026 [US3] Integrate existing `SearchInput` component into `PolicySearchContainer` in `components/policy-explorer/PolicySearchContainer.tsx`
- [X] T027 [US3] Add search handler in `PolicySearchContainer` - calls `searchPolicySettings()` Server Action with search term
- [X] T028 [US3] Implement search state management using `useTransition()` hook for pending state
- [X] T029 [US3] Update table to show search results when search term is entered, show initial 50 policies when search is cleared
- [X] T030 [US3] Verify null values are filtered from search results (handled by Server Action from T006)
- [X] T031 [US3] Add loading indicator while search is in progress (use `isPending` from `useTransition`)
**Checkpoint**: Search works, results exclude null values, loading states correct
---
## Phase 6: User Story 4 - Improved Visual Hierarchy (Priority: P3)
**Goal**: Admin sees policy types as colored badges and improved row hover effects
**Independent Test**: View table, verify badges have distinct colors, rows highlight on hover
### Implementation for User Story 4
- [X] T032 [P] [US4] Define policy type to badge color mapping - create utility function or constant (e.g., Compliance=blue, Configuration=gray, Security=red, etc.)
- [X] T033 [P] [US4] Implement badge rendering in `PolicyTable` - replace plain text `policyType` with Shadcn Badge component
- [X] T034 [P] [US4] Apply badge variant/color based on policy type in `PolicyTable` component
- [X] T035 [US4] Test badge colors with real data - verify at least 3 distinct colors are visible and accessible (contrast check)
- [X] T036 [US4] Verify hover effects on table rows - cursor changes to pointer, background color changes
**Checkpoint**: Badges show distinct colors, hover effects smooth, visual hierarchy improved
---
## Phase 7: Navigation & Route Consolidation (Cross-Cutting)
**Purpose**: Update navigation and routing to consolidate under "Policy Explorer"
- [X] T037 Update `config/nav.ts` - replace `{ title: "Search", href: "/search" }` with `{ title: "Policy Explorer", href: "/search" }` (keep /search route for now)
- [X] T038 Remove "All Settings" menu item from `config/nav.ts` if it exists (from settings-overview feature)
- [X] T039 Update page metadata (title, description) in `app/(app)/search/page.tsx` to reflect "Policy Explorer" branding
- [ ] T040 Add redirect from `/settings-overview` to `/search` if that route exists (optional, for backwards compatibility)
**Checkpoint**: Navigation shows single "Policy Explorer" entry, old routes redirect if needed
---
## Phase 8: Polish & Final Integration
**Purpose**: Final refinements and end-to-end validation
- [X] T041 Update `EmptyState` component message in `components/search/EmptyState.tsx` - change to Policy Explorer context if still used
- [ ] T042 Add loading skeleton to table (optional) - show placeholder rows while initial data loads
- [ ] T043 Verify responsive layout - test table and detail sheet on mobile viewport (< 768px)
- [ ] T044 Add error boundary for detail sheet - graceful error handling if sheet rendering fails
- [ ] T045 Performance check - verify initial page load < 2s, detail sheet opens < 300ms, search response < 2s
- [ ] T046 Accessibility check - verify keyboard navigation (Tab, Enter to open sheet, Escape to close), screen reader labels
- [ ] T047 Cross-browser test - verify in Chrome, Safari, Firefox (at minimum)
**Checkpoint**: Feature complete, polished, and tested across browsers/devices
---
## Dependencies Visualization
```mermaid
graph TD
T001[T001: Install Sheet] --> T017[T017: Create PolicyDetailSheet]
T002[T002: Install Badge] --> T033[T033: Implement Badge Rendering]
T003[T003: Create Directory] --> T009[T009: Create PolicyTable]
T003 --> T012[T012: Create PolicySearchContainer]
T003 --> T017
T004[T004: getRecentPolicySettings] --> T013[T013: Refactor Page to Server Component]
T005[T005: Extend searchPolicySettings] --> T027[T027: Add Search Handler]
T006[T006: Null Filtering] --> T004
T006 --> T005
T007[T007: Type Exports] --> T009
T007 --> T012
T007 --> T017
T008[T008: Test Server Actions] --> T013
T009 --> T013
T010[T010: Row Click Handler] --> T024[T024: Connect Click to Sheet]
T011[T011: Hover Styles] --> T036[T036: Verify Hover Effects]
T012 --> T013
T013 --> T026[T026: Integrate SearchInput]
T017 --> T023[T023: Integrate Sheet into Container]
T018[T018: JSON Detection] --> T019[T019: JSON Formatting]
T019 --> T020[T020: Render JSON in pre]
T020 --> T023
T021[T021: Render Non-JSON] --> T023
T022[T022: Sheet Styling] --> T023
T023 --> T024
T026 --> T027
T027 --> T028[T028: Search State Management]
T028 --> T029[T029: Update Table with Results]
T029 --> T030[T030: Verify Null Filtering]
T030 --> T031[T031: Loading Indicator]
T032[T032: Badge Color Mapping] --> T033
T033 --> T034[T034: Apply Badge Variants]
T034 --> T035[T035: Test Badge Colors]
T013 --> T037[T037: Update Navigation]
T037 --> T038[T038: Remove All Settings]
T038 --> T039[T039: Update Page Metadata]
```
---
## Parallel Execution Opportunities
### Phase 1 (All parallel):
- T001, T002, T003 can all run simultaneously
### Phase 2:
- **Parallel**: T007 can run while T004-T006 are being implemented
- **Sequential**: T004-T006 must complete before T008
- **Blocking**: T008 must complete before Phase 3 starts
### Phase 3 (User Story 1):
- **Parallel**: T009, T010, T011, T012 (different components)
- **Sequential**: T013 requires T009 and T012 complete
- **Sequential**: T014-T016 extend T013
### Phase 4 (User Story 2):
- **Parallel**: T017, T018, T019, T020, T021, T022 (all component work)
- **Sequential**: T023 requires T017-T022 complete
- **Sequential**: T024 requires T023 and T010 complete
- **Sequential**: T025 is final testing
### Phase 5 (User Story 3):
- **Sequential**: T026 T027 T028 T029 T030 T031 (build on each other)
### Phase 6 (User Story 4):
- **Parallel**: T032, T033, T034 (component work)
- **Sequential**: T035, T036 (testing)
### Phase 7 (Navigation):
- **Parallel**: T037, T038 (different files)
- **Sequential**: T039, T040 extend T037/T038
### Phase 8 (Polish):
- **Mostly parallel**: T041-T044 (different concerns)
- **Sequential**: T045-T047 (validation after implementation)
---
## Suggested MVP Scope
**Minimum Viable Product** = Phase 1 + Phase 2 + Phase 3 + Phase 4
This delivers:
- 50 newest policies on page load (no empty state)
- Null values filtered automatically
- Clickable rows with detail sheet
- JSON formatting in detail view
- Functional search (from existing feature)
**Can be deferred post-MVP**:
- User Story 3 tasks (search refinements) - existing search already works
- User Story 4 tasks (visual improvements) - badges and hover are polish
- Phase 7 tasks (navigation consolidation) - can keep both menu items temporarily
- Phase 8 tasks (polish) - can iterate after core functionality validated
---
## Implementation Strategy
### Week 1: Foundation + US1 (MVP Core)
- Days 1-2: Phase 1 (Setup) + Phase 2 (Backend)
- Days 3-5: Phase 3 (User Story 1 - Browse Recent)
**Deliverable**: Page loads with 50 newest policies, no null values
### Week 2: US2 + Testing (MVP Complete)
- Days 1-3: Phase 4 (User Story 2 - Detail Sheet)
- Days 4-5: Testing and bug fixes for US1 + US2
**Deliverable**: Functional Policy Explorer with detail view (MVP ready)
### Week 3: Polish + Enhancement
- Days 1-2: Phase 5 (User Story 3 - Search refinements)
- Days 3-4: Phase 6 (User Story 4 - Visual improvements)
- Day 5: Phase 7 (Navigation) + Phase 8 (Polish)
**Deliverable**: Full feature with all user stories, polished and production-ready
---
## Task Count Summary
- **Phase 1 (Setup)**: 3 tasks
- **Phase 2 (Foundation)**: 5 tasks BLOCKING
- **Phase 3 (US1 - P1)**: 8 tasks 🎯 MVP
- **Phase 4 (US2 - P1)**: 9 tasks 🎯 MVP
- **Phase 5 (US3 - P2)**: 6 tasks
- **Phase 6 (US4 - P3)**: 5 tasks
- **Phase 7 (Navigation)**: 4 tasks
- **Phase 8 (Polish)**: 7 tasks
**Total**: 47 tasks
**MVP Subset**: T001-T025 (25 tasks) = Foundation + US1 + US2
---
## Success Criteria Mapping
| Success Criterion | Tasks |
|-------------------|-------|
| SC-001: Load < 2s | T004, T013, T045 |
| SC-002: 100% valid values (no nulls) | T006, T030 |
| SC-003: Detail sheet < 300ms | T017-T024, T045 |
| SC-004: JSON formatted | T018-T020, T025 |
| SC-005: Badge colors distinguishable | T032-T035 |
| SC-006: Single "Policy Explorer" menu | T037-T038 |
---
## Notes
- **No database migrations**: Feature works with existing schema
- **Server-first architecture**: All data via Server Actions
- **Shadcn UI components**: Sheet and Badge must be installed (T001, T002)
- **Backwards compatibility**: Can keep `/search` route, update navigation text
- **Performance**: Null filtering in backend (T006) for optimal performance
- **Testing**: Manual testing focus, no automated E2E tests in scope
- **Accessibility**: Covered in Phase 8 (T046)
---
## References
- Feature Spec: [spec.md](./spec.md)
- Implementation Plan: [plan.md](./plan.md)
- Requirements Checklist: [checklists/requirements.md](./checklists/requirements.md)
- Related Features: [001-global-policy-search](../001-global-policy-search/), [002-manual-policy-sync](../002-manual-policy-sync/)