All checks were successful
Trigger Cloudarix Deploy / call-webhook (push) Successful in 2s
✨ 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
341 lines
16 KiB
Markdown
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)
|