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

341 lines
16 KiB
Markdown

# 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
- [X] T001 Install TanStack Table v8 (`@tanstack/react-table`) via npm
- [X] T002 [P] Install `nuqs` for URL state management via npm (or decide on native useSearchParams)
- [X] T003 [P] Create types file lib/types/policy-table.ts with DataTableState, FilterState, TablePreferences interfaces
- [X] 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
- [X] T005 Update getPolicySettings Server Action in lib/actions/policySettings.ts to accept pagination params (page, pageSize)
- [X] T006 Add sorting support to getPolicySettings (sortBy, sortDir parameters) in lib/actions/policySettings.ts
- [X] T007 Add policyTypes filter support to getPolicySettings in lib/actions/policySettings.ts
- [X] T008 Update getPolicySettings return type to include meta (totalCount, pageCount, hasNextPage, hasPreviousPage) in lib/actions/policySettings.ts
- [X] T009 Add input validation for getPolicySettings (Zod schema for params) in lib/actions/policySettings.ts
- [X] 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
- [X] T011 [P] [US1] Create PolicyTableColumns.tsx in components/policy-explorer/ with column definitions (settingName, settingValue, policyName, policyType, lastSyncedAt, graphPolicyId)
- [X] T012 [P] [US1] Create usePolicyTable hook in lib/hooks/usePolicyTable.ts (TanStack Table initialization with manual pagination mode)
- [X] T013 [P] [US1] Create useTablePreferences hook in lib/hooks/useTablePreferences.ts (localStorage persistence for columnVisibility, columnSizing, density)
- [X] T014 [P] [US1] Create useURLState hook in lib/hooks/useURLState.ts (sync pagination, sorting, filters with URL query params)
- [X] T015 [US1] Create PolicyTable.tsx in components/policy-explorer/ (main table component using TanStack Table + shadcn Table primitives)
- [X] T016 [US1] Implement pagination controls in PolicyTablePagination.tsx in components/policy-explorer/ (Previous, Next, Page Numbers, Page Size selector)
- [X] T017 [US1] Implement column sorting in PolicyTable.tsx (click header to toggle ASC/DESC, visual sort indicators)
- [X] T018 [US1] Create ColumnVisibilityMenu.tsx in components/policy-explorer/ (dropdown with checkboxes to show/hide columns)
- [X] T019 [US1] Implement column resizing in PolicyTable.tsx (drag column borders, persist width to localStorage)
- [X] T020 [US1] Implement sticky table header in PolicyTable.tsx (CSS position: sticky, remains visible on scroll)
- [X] T021 [US1] Implement density mode toggle in PolicyTableToolbar.tsx (compact vs comfortable row height, persist to localStorage)
- [X] 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
```mermaid
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:
```bash
# 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:
```bash
# 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:
```bash
# 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:
```bash
# 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)