tenantpilot/specs/004-policy-explorer-v2/tasks.md
Ahmed Darrazi 41e80b6c0c
All checks were successful
Trigger Cloudarix Deploy / call-webhook (push) Successful in 2s
feat(policy-explorer-v2): implement MVP Phase 1-3
 New Features
- Advanced data table with TanStack Table v8 + Server Actions
- Server-side pagination (10/25/50/100 rows per page)
- Multi-column sorting with visual indicators
- Column management (show/hide, resize) persisted to localStorage
- URL state synchronization for shareable filtered views
- Sticky header with compact/comfortable density modes

📦 Components Added
- PolicyTableV2.tsx - Main table with TanStack integration
- PolicyTableColumns.tsx - 7 column definitions with sorting
- PolicyTablePagination.tsx - Pagination controls
- PolicyTableToolbar.tsx - Density toggle + column visibility menu
- ColumnVisibilityMenu.tsx - Show/hide columns dropdown

🔧 Hooks Added
- usePolicyTable.ts - TanStack Table initialization
- useURLState.ts - URL query param sync with nuqs
- useTablePreferences.ts - localStorage persistence

🎨 Server Actions Updated
- getPolicySettingsV2 - Pagination + sorting + filtering + Zod validation
- exportPolicySettingsCSV - Server-side CSV generation (max 5000 rows)

📚 Documentation Added
- Intune Migration Guide (1400+ lines) - Reverse engineering strategy
- Intune Reference Version tracking
- Tasks completed: 22/62 (Phase 1-3)

 Zero TypeScript compilation errors
 All MVP success criteria met (pagination, sorting, column management)
 Ready for Phase 4-7 (filtering, export, detail view, polish)

Refs: specs/004-policy-explorer-v2/tasks.md
2025-12-10 00:18:05 +01:00

16 KiB

Tasks: Policy Explorer V2

Input: Design documents from /specs/004-policy-explorer-v2/ Prerequisites: plan.md (required), spec.md (required)

Tests: Unit tests for utilities, E2E tests for table interactions

Organization: Tasks are grouped by user story to enable independent implementation and testing.

Format: [ID] [P?] [Story] Description

  • [P]: Can run in parallel (different files, no dependencies)
  • [Story]: Which user story this task belongs to (e.g., US1, US2, US3, US4)
  • Include exact file paths in descriptions

Path Conventions

  • App routes: app/(app)/search/
  • Components: components/policy-explorer/
  • Server Actions: lib/actions/policySettings.ts
  • Hooks: lib/hooks/
  • Utils: lib/utils/
  • Tests: tests/unit/ and tests/e2e/

Phase 1: Setup (Dependencies & Infrastructure)

Purpose: Install dependencies and create base infrastructure

  • T001 Install TanStack Table v8 (@tanstack/react-table) via npm
  • T002 [P] Install nuqs for URL state management via npm (or decide on native useSearchParams)
  • T003 [P] Create types file lib/types/policy-table.ts with DataTableState, FilterState, TablePreferences interfaces
  • T004 [P] Add composite database index for performance: (tenantId, policyType, settingName) in lib/db/schema/policySettings.ts

Phase 2: Foundational (Server Actions & Data Layer)

Purpose: Update Server Actions to support pagination, sorting, filtering

⚠️ CRITICAL: This must be complete before ANY user story UI can be built

  • T005 Update getPolicySettings Server Action in lib/actions/policySettings.ts to accept pagination params (page, pageSize)
  • T006 Add sorting support to getPolicySettings (sortBy, sortDir parameters) in lib/actions/policySettings.ts
  • T007 Add policyTypes filter support to getPolicySettings in lib/actions/policySettings.ts
  • T008 Update getPolicySettings return type to include meta (totalCount, pageCount, hasNextPage, hasPreviousPage) in lib/actions/policySettings.ts
  • T009 Add input validation for getPolicySettings (Zod schema for params) in lib/actions/policySettings.ts
  • T010 Create exportPolicySettingsCSV Server Action in lib/actions/policySettings.ts (server-side CSV generation, max 5000 rows)

Checkpoint: Server Actions ready - UI implementation can begin


Phase 3: User Story 1 - Advanced Data Table Navigation (Priority: P1) 🎯 MVP

Goal: Implement pagination, sorting, column management, sticky header

Independent Test: Load 500+ settings, paginate, sort by different columns, hide/show columns, resize columns

Implementation for User Story 1

  • T011 [P] [US1] Create PolicyTableColumns.tsx in components/policy-explorer/ with column definitions (settingName, settingValue, policyName, policyType, lastSyncedAt, graphPolicyId)
  • T012 [P] [US1] Create usePolicyTable hook in lib/hooks/usePolicyTable.ts (TanStack Table initialization with manual pagination mode)
  • T013 [P] [US1] Create useTablePreferences hook in lib/hooks/useTablePreferences.ts (localStorage persistence for columnVisibility, columnSizing, density)
  • T014 [P] [US1] Create useURLState hook in lib/hooks/useURLState.ts (sync pagination, sorting, filters with URL query params)
  • T015 [US1] Create PolicyTable.tsx in components/policy-explorer/ (main table component using TanStack Table + shadcn Table primitives)
  • T016 [US1] Implement pagination controls in PolicyTablePagination.tsx in components/policy-explorer/ (Previous, Next, Page Numbers, Page Size selector)
  • T017 [US1] Implement column sorting in PolicyTable.tsx (click header to toggle ASC/DESC, visual sort indicators)
  • T018 [US1] Create ColumnVisibilityMenu.tsx in components/policy-explorer/ (dropdown with checkboxes to show/hide columns)
  • T019 [US1] Implement column resizing in PolicyTable.tsx (drag column borders, persist width to localStorage)
  • T020 [US1] Implement sticky table header in PolicyTable.tsx (CSS position: sticky, remains visible on scroll)
  • T021 [US1] Implement density mode toggle in PolicyTableToolbar.tsx (compact vs comfortable row height, persist to localStorage)
  • T022 [US1] Update app/(app)/search/page.tsx to fetch data with pagination/sorting params and pass to PolicyTable

Checkpoint: Data table with pagination, sorting, column management fully functional


Phase 4: User Story 2 - Enhanced Filtering (Priority: P1)

Goal: Implement PolicyType filter with multi-select checkboxes

Independent Test: Select policy types, verify filtered results, combine with search

Implementation for User Story 2

  • T023 [P] [US2] Create PolicyTypeFilter component in components/policy-explorer/PolicyTypeFilter.tsx (multi-select checkbox dropdown)
  • T024 [US2] Add PolicyTypeFilter to PolicyTableToolbar.tsx in components/policy-explorer/
  • T025 [US2] Connect PolicyTypeFilter to useURLState hook (sync selected types with URL query param)
  • T026 [US2] Update PolicyTable to trigger data refetch when policyTypes filter changes
  • T027 [US2] Implement filter badge/chip display in PolicyTableToolbar showing active filters with clear button
  • T028 [US2] Add "Clear All Filters" button to PolicyTableToolbar

Checkpoint: Filtering works, combines with search, persists in URL state


Phase 5: User Story 3 - Bulk Export (Priority: P1)

Goal: Implement CSV export for selected rows (client) and all filtered results (server)

Independent Test: Select rows, export CSV, open in Excel, verify content and escaping

Implementation for User Story 3

  • T029 [P] [US3] Create csv-export.ts utility in lib/utils/ (client-side CSV generation with proper escaping)
  • T030 [P] [US3] Add unit tests for CSV escaping (commas, quotes, newlines) in tests/unit/csv-export.test.ts
  • T031 [US3] Implement row selection in PolicyTable.tsx (checkboxes for individual rows + Select All)
  • T032 [US3] Create ExportButton component in components/policy-explorer/ExportButton.tsx (dropdown: "Export Selected" / "Export All Filtered")
  • T033 [US3] Implement "Export Selected" action in ExportButton (client-side CSV generation, trigger download)
  • T034 [US3] Implement "Export All Filtered" action in ExportButton (call exportPolicySettingsCSV Server Action, trigger download)
  • T035 [US3] Add export button to PolicyTableToolbar with disabled state when no rows selected
  • T036 [US3] Add warning UI when filtered results exceed 5000 rows ("Export limited to 5000 rows")
  • T037 [US3] Add loading state for server-side CSV generation (spinner + progress indicator)

Checkpoint: CSV export works for both selected rows and filtered results with proper escaping


Phase 6: User Story 4 - Enhanced Detail View (Priority: P2)

Goal: Add copy-to-clipboard buttons, raw JSON view, "Open in Intune" link to detail sheet

Independent Test: Open detail sheet, test copy buttons, view raw JSON, click Intune link

Implementation for User Story 4

  • T038 [P] [US4] Create useCopyToClipboard hook in lib/hooks/useCopyToClipboard.ts (wrapper for Clipboard API with success toast)
  • T039 [P] [US4] Add unit tests for clipboard utility in tests/unit/clipboard.test.ts
  • T040 [US4] Update PolicyDetailSheet.tsx in components/policy-explorer/ to add "Copy Policy ID" button
  • T041 [US4] Add "Copy Setting Name" and "Copy Setting Value" buttons to PolicyDetailSheet.tsx
  • T042 [US4] Add tabs to PolicyDetailSheet: "Details" and "Raw JSON"
  • T043 [US4] Implement Raw JSON tab in PolicyDetailSheet showing formatted JSON with syntax highlighting
  • T044 [US4] Create getIntunePortalLink utility in lib/utils/policy-table-helpers.ts (construct Intune URL by policy type)
  • T045 [US4] Add "Open in Intune" button to PolicyDetailSheet (external link icon, opens in new tab)
  • T046 [US4] Add fallback for "Open in Intune" when URL construction fails (copy policy ID instead)

Checkpoint: Detail sheet has enhanced functionality, all copy buttons work, raw JSON displays correctly


Phase 7: Polish & Cross-Cutting Concerns

Purpose: Meta info, truncation, edge cases, accessibility, testing

  • T047 [P] Create PolicyTableMeta component in components/policy-explorer/PolicyTableMeta.tsx (displays "X settings · Y policies · Last sync")
  • T048 [P] Add PolicyTableMeta above table in app/(app)/search/page.tsx
  • T049 [P] Implement value truncation with tooltip in PolicyTableColumns.tsx (long settingValue, graphPolicyId)
  • T050 [P] Add responsive behavior: disable column resizing on mobile (<768px) in PolicyTable.tsx
  • T051 [P] Add horizontal scroll for wide tables with sticky first column in PolicyTable.tsx
  • T052 Add ARIA labels for accessibility (table, pagination, filters, sort buttons)
  • T053 Add keyboard navigation support (arrow keys for rows, Enter to open detail sheet)
  • T054 Create E2E tests for pagination in tests/e2e/policy-explorer.spec.ts
  • T055 Create E2E tests for sorting in tests/e2e/policy-explorer.spec.ts
  • T056 Create E2E tests for filtering in tests/e2e/policy-explorer.spec.ts
  • T057 Create E2E tests for CSV export in tests/e2e/policy-explorer.spec.ts
  • T058 Create E2E tests for column management in tests/e2e/policy-explorer.spec.ts
  • T059 Add loading skeleton states for table, filters, export
  • T060 Add error boundary for table component with retry button
  • T061 Performance optimization: Add React.memo to table rows if needed
  • T062 Update README.md or documentation with Policy Explorer V2 features

Dependencies

User Story Completion Order

graph TD
    Setup[Phase 1: Setup] --> Foundation[Phase 2: Foundation]
    Foundation --> US1[Phase 3: US1 - Data Table]
    Foundation --> US2[Phase 4: US2 - Filtering]
    Foundation --> US3[Phase 5: US3 - Export]
    US1 --> US4[Phase 6: US4 - Detail View]
    US1 --> Polish[Phase 7: Polish]
    US2 --> Polish
    US3 --> Polish
    US4 --> Polish

Explanation:

  • Setup & Foundation must complete first (T001-T010)
  • US1 (Data Table) is the foundation for all other user stories
  • US2 (Filtering) depends on table being functional
  • US3 (Export) depends on row selection from US1
  • US4 (Detail View) extends existing sheet, can happen in parallel with US2/US3
  • Polish comes last after all core features work

Task-Level Dependencies

Critical Path (must complete in order):

  1. T001-T004 (setup) → T005-T010 (Server Actions)
  2. T005-T010 (Server Actions) → T011-T022 (US1 table implementation)
  3. T011-T022 (table) → All other user stories can begin
  4. T031 (row selection) → T033-T037 (export features)

Parallel Opportunities:

  • T001, T002, T003, T004 can run in parallel (setup tasks)
  • T005-T010 can run in parallel after T004 (Server Action updates)
  • T011, T012, T013, T014 can run in parallel (hooks and column definitions)
  • T023, T029, T030, T038, T039, T047, T049 can run in parallel after table is functional
  • T054-T058 can run in parallel during polish phase

Parallel Execution Examples

Phase 1 - Setup (All tasks in parallel)

Run these tasks simultaneously:

# Terminal 1: Install TanStack Table
npm install @tanstack/react-table

# Terminal 2: Install nuqs
npm install nuqs

# Terminal 3: Create types file
# T003 - Create lib/types/policy-table.ts

# Terminal 4: Add database index
# T004 - Update schema

Phase 2 - Server Actions (After T004 completes)

Run Server Action updates in parallel:

# All T005-T010 modify lib/actions/policySettings.ts
# Can be done together or split by developer
# T005-T009: Update getPolicySettings
# T010: Create exportPolicySettingsCSV

Phase 3 - US1 Foundation (After Phase 2)

Run these in parallel:

# Terminal 1: T011 - Column definitions
# Terminal 2: T012 - usePolicyTable hook
# Terminal 3: T013 - useTablePreferences hook
# Terminal 4: T014 - useURLState hook

Phase 7 - Polish (After Phase 3-6 complete)

Run tests and polish tasks in parallel:

# Terminal 1: T054-T058 - E2E tests
# Terminal 2: T047, T048 - Meta info component
# Terminal 3: T049, T050, T051 - Responsive behavior
# Terminal 4: T052, T053 - Accessibility

Implementation Strategy

MVP Scope (Ship This First)

Phase 3: User Story 1 - Advanced Data Table Navigation

  • This is the core value: pagination, sorting, column management
  • Includes: T011-T022 (12 tasks)
  • Delivers SC-001, SC-002, SC-003: Fast pagination, sorting, persistent settings
  • Can be shipped independently: Provides immediate value even without filtering/export

Incremental Delivery

  1. MVP (Phase 3): Ship US1 data table → users can navigate large datasets
  2. V1.1 (Phase 4): Add US2 filtering → users can narrow down results by policy type
  3. V1.2 (Phase 5): Add US3 export → users can extract data for reports
  4. V1.3 (Phase 6): Add US4 enhanced detail view → power users get advanced features
  5. V2.0 (Phase 7): Polish + complete testing → production-ready

Success Metrics (Track These)

  • SC-001: Page load time <500ms (50 rows) → Measure with Lighthouse/DevTools
  • SC-002: Sorting performance <200ms → Measure with Performance API
  • SC-003: localStorage persistence → Test browser reload, verify settings restored
  • SC-004: Client CSV export <2s (1000 rows) → Measure download trigger time
  • SC-005: Server CSV export <5s (5000 rows) → Measure Server Action execution time
  • SC-006: Filter + search AND logic → Verify result counts match expectations
  • SC-007: URL state shareable → Copy URL, paste in new tab, verify identical view
  • SC-008: Copy buttons work → Test in Chrome, Firefox, Safari, Edge

Validation Checklist

Before marking tasks complete, verify:

  • All Server Actions have input validation (Zod schemas)
  • All Server Actions enforce tenant isolation (check user session)
  • Table pagination works with 0 results, 1 result, 1000+ results
  • Sorting works correctly for strings, numbers, dates
  • Column visibility changes persist after browser reload
  • CSV export handles special characters (commas, quotes, newlines)
  • CSV export is Excel-compatible (UTF-8 BOM, proper line endings)
  • URL state works with browser back/forward buttons
  • Sticky header works on different viewport sizes
  • Row selection persists across page changes (or clears intentionally)
  • All interactive elements have keyboard support
  • All interactive elements have ARIA labels
  • Loading states show for all async operations
  • Error states show helpful messages with retry options
  • TypeScript strict mode passes (no any types)
  • All new components use Shadcn UI primitives

Notes

About TanStack Table Integration:

  • Use "manual" pagination mode (table doesn't handle data fetching)
  • Server Actions fetch data, table handles UI state only
  • This keeps us constitution-compliant (server-first architecture)

About CSV Export:

  • Client-side (<1000 rows): Fast, no server load, instant download
  • Server-side (1000-5000 rows): Handles larger datasets, proper memory management
  • Always include CSV header row with column names
  • Use UTF-8 BOM for Excel compatibility: \uFEFF prefix

About localStorage Schema:

  • Version field enables migrations when adding new preferences
  • Store only user preferences, never actual data
  • Handle quota exceeded gracefully (clear old data, warn user)

About URL State:

  • Keep URLs shareable (don't include sensitive data)
  • Use short query param names (p=page, ps=pageSize, sb=sortBy)
  • Handle malformed URLs gracefully (validate and reset to defaults)

Performance Considerations:

  • Add database index on (tenantId, policyType, settingName) for sorting
  • Use React.memo on table rows only if profiling shows re-render issues
  • Debounce search input to avoid excessive Server Action calls
  • Consider virtual scrolling if page size >100 causes jank

Tasks Version: 1.0
Last Updated: 2025-12-09
Total Tasks: 62
Estimated MVP Scope: T001-T022 (22 tasks)