47 tasks organized across 8 phases by user story: Phase 1: Setup (3 tasks) - Install Shadcn Sheet and Badge components - Create component directory structure Phase 2: Foundation (5 tasks) ⚠️ BLOCKING - getRecentPolicySettings() Server Action - Extend searchPolicySettings() with limit param - Null-value filtering in backend - Type exports Phase 3: User Story 1 - Browse Recent (8 tasks) 🎯 MVP - PolicyTable component with click handlers - PolicySearchContainer client wrapper - Refactor page to Server Component - 50 newest policies on load, no empty state Phase 4: User Story 2 - Detail Sheet (9 tasks) 🎯 MVP - PolicyDetailSheet component - JSON detection and formatting - Click-to-open sheet integration - Handle long content and errors Phase 5: User Story 3 - Search (6 tasks) P2 - Integrate SearchInput component - Search state management - Null filtering in results Phase 6: User Story 4 - Visual (5 tasks) P3 - Badge color mapping - Badge rendering for policy types - Hover effects verification Phase 7: Navigation (4 tasks) - Update config/nav.ts - Remove 'All Settings' menu item - Consolidate to single 'Policy Explorer' Phase 8: Polish (7 tasks) - Responsive layout - Loading states - Performance validation (<2s load, <300ms sheet) - Accessibility and cross-browser testing MVP Scope: Phases 1-4 (25 tasks) Total: 47 tasks with dependency graph and parallel execution opportunities
15 KiB
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
- T001 [P] Verify Shadcn Sheet component exists at
components/ui/sheet.tsx, install if missing vianpx shadcn@latest add sheet - T002 [P] Verify Shadcn Badge component exists at
components/ui/badge.tsx, install if missing vianpx shadcn@latest add badge - 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
- T004 Add
getRecentPolicySettings(limit?: number)Server Action inlib/actions/policySettings.ts- returns 50 newest policies sorted by lastSyncedAt DESC, filtered by tenantId and excluding null values - T005 Extend
searchPolicySettings()Server Action inlib/actions/policySettings.ts- add optionallimitparameter (default 100, max 200) - T006 Add null-value filtering logic to Server Actions - filter out entries where
settingValue === "null"orsettingValue === null(backend approach for performance) - T007 Add type exports for
PolicySettingSearchResultinterface if not already exported fromlib/actions/policySettings.ts - 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
- T009 [P] [US1] Create
PolicyTable.tsxcomponent incomponents/policy-explorer/PolicyTable.tsx- display policies in table format with columns: Setting Name, Setting Value, Policy Name, Policy Type, Last Synced - T010 [P] [US1] Add row click handler prop to
PolicyTablecomponent - acceptsonRowClick: (policy: PolicySettingSearchResult) => void - T011 [P] [US1] Add hover styles to table rows in
PolicyTable-hover:bg-accent cursor-pointerclasses - T012 [P] [US1] Create
PolicySearchContainer.tsxclient component incomponents/policy-explorer/PolicySearchContainer.tsx- manages search state, acceptsinitialPoliciesprop - T013 [US1] Refactor
app/(app)/search/page.tsxto Server Component pattern - callgetRecentPolicySettings(50)in Server Component, pass data toPolicySearchContainer - T014 [US1] Update page CardTitle to "Policy Explorer" and CardDescription in
app/(app)/search/page.tsx - T015 [US1] Add empty state handling - if no policies returned, show message "Keine Policies gefunden - Starten Sie einen Sync"
- T016 [US1] Keep existing
SyncButtoncomponent in CardHeader ofapp/(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
- T017 [P] [US2] Create
PolicyDetailSheet.tsxcomponent incomponents/policy-explorer/PolicyDetailSheet.tsx- uses Shadcn Sheet, acceptspolicy,open,onOpenChangeprops - T018 [P] [US2] Implement JSON detection logic in
PolicyDetailSheet- check ifsettingValue.trim().startsWith('{')orstartsWith('[') - T019 [P] [US2] Implement JSON formatting utility -
JSON.stringify(JSON.parse(value), null, 2)wrapped in try/catch, fallback to plain text on error - T020 [P] [US2] Render JSON values in
<pre>tag with Tailwind prose classes for readability inPolicyDetailSheet - T021 [P] [US2] Render non-JSON values as normal text in
PolicyDetailSheet - T022 [P] [US2] Add Sheet styling - proper width (e.g.,
w-[600px]), padding, close button, scroll for long content (max-height+overflow-auto) - T023 [US2] Integrate
PolicyDetailSheetintoPolicySearchContainer- add state for selected policy and sheet open/close - T024 [US2] Connect row click handler from
PolicyTableto open detail sheet with clicked policy data - 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
- T026 [US3] Integrate existing
SearchInputcomponent intoPolicySearchContainerincomponents/policy-explorer/PolicySearchContainer.tsx - T027 [US3] Add search handler in
PolicySearchContainer- callssearchPolicySettings()Server Action with search term - T028 [US3] Implement search state management using
useTransition()hook for pending state - T029 [US3] Update table to show search results when search term is entered, show initial 50 policies when search is cleared
- T030 [US3] Verify null values are filtered from search results (handled by Server Action from T006)
- T031 [US3] Add loading indicator while search is in progress (use
isPendingfromuseTransition)
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
- T032 [P] [US4] Define policy type to badge color mapping - create utility function or constant (e.g., Compliance=blue, Configuration=gray, Security=red, etc.)
- T033 [P] [US4] Implement badge rendering in
PolicyTable- replace plain textpolicyTypewith Shadcn Badge component - T034 [P] [US4] Apply badge variant/color based on policy type in
PolicyTablecomponent - T035 [US4] Test badge colors with real data - verify at least 3 distinct colors are visible and accessible (contrast check)
- 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"
- T037 Update
config/nav.ts- replace{ title: "Search", href: "/search" }with{ title: "Policy Explorer", href: "/search" }(keep /search route for now) - T038 Remove "All Settings" menu item from
config/nav.tsif it exists (from settings-overview feature) - T039 Update page metadata (title, description) in
app/(app)/search/page.tsxto reflect "Policy Explorer" branding - T040 Add redirect from
/settings-overviewto/searchif 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
- T041 Update
EmptyStatecomponent message incomponents/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
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
/searchroute, 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
- Implementation Plan: plan.md
- Requirements Checklist: checklists/requirements.md
- Related Features: 001-global-policy-search, 002-manual-policy-sync