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

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 via npx shadcn@latest add sheet
  • T002 [P] Verify Shadcn Badge component exists at components/ui/badge.tsx, install if missing via npx 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 in lib/actions/policySettings.ts - returns 50 newest policies sorted by lastSyncedAt DESC, filtered by tenantId and excluding null values
  • T005 Extend searchPolicySettings() Server Action in lib/actions/policySettings.ts - add optional limit parameter (default 100, max 200)
  • T006 Add null-value filtering logic to Server Actions - filter out entries where settingValue === "null" or settingValue === null (backend approach for performance)
  • T007 Add type exports for PolicySettingSearchResult interface if not already exported from lib/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.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
  • T010 [P] [US1] Add row click handler prop to PolicyTable component - accepts onRowClick: (policy: PolicySettingSearchResult) => void
  • T011 [P] [US1] Add hover styles to table rows in PolicyTable - hover:bg-accent cursor-pointer classes
  • T012 [P] [US1] Create PolicySearchContainer.tsx client component in components/policy-explorer/PolicySearchContainer.tsx - manages search state, accepts initialPolicies prop
  • T013 [US1] Refactor app/(app)/search/page.tsx to Server Component pattern - call getRecentPolicySettings(50) in Server Component, pass data to PolicySearchContainer
  • 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 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

  • T017 [P] [US2] Create PolicyDetailSheet.tsx component in components/policy-explorer/PolicyDetailSheet.tsx - uses Shadcn Sheet, accepts policy, open, onOpenChange props
  • T018 [P] [US2] Implement JSON detection logic in PolicyDetailSheet - check if settingValue.trim().startsWith('{') or startsWith('[')
  • 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 in PolicyDetailSheet
  • 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 PolicyDetailSheet into PolicySearchContainer - add state for selected policy and sheet open/close
  • T024 [US2] Connect row click handler from PolicyTable to 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 SearchInput component into PolicySearchContainer in components/policy-explorer/PolicySearchContainer.tsx
  • T027 [US3] Add search handler in PolicySearchContainer - calls searchPolicySettings() 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 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

  • 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 text policyType with Shadcn Badge component
  • T034 [P] [US4] Apply badge variant/color based on policy type in PolicyTable component
  • 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.ts if it exists (from settings-overview feature)
  • 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

  • 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

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