From 8a64596d8b0b3068f7abe8f7c666dc52e643142b Mon Sep 17 00:00:00 2001 From: Jason Staack Date: Thu, 12 Mar 2026 23:22:22 -0500 Subject: [PATCH] docs(08-01): complete diff viewer plan Co-Authored-By: Claude Opus 4.6 --- .planning/REQUIREMENTS.md | 4 +- .planning/ROADMAP.md | 8 +- .planning/STATE.md | 27 +++--- .../08-diff-viewer-download/08-01-SUMMARY.md | 92 +++++++++++++++++++ 4 files changed, 113 insertions(+), 18 deletions(-) create mode 100644 .planning/phases/08-diff-viewer-download/08-01-SUMMARY.md diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index 46263d7..45741a4 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -40,7 +40,7 @@ - [x] **UI-01**: Device page shows Configuration History section below Remote Access - [x] **UI-02**: Timeline displays change entries with component, summary, and timestamp -- [ ] **UI-03**: Diff viewer shows unified diff with add/remove highlighting +- [x] **UI-03**: Diff viewer shows unified diff with add/remove highlighting - [ ] **UI-04**: User can download snapshot as `router-{device_name}-{timestamp}.rsc` ### Observability @@ -89,7 +89,7 @@ | API-04 | Phase 6: History API | Complete | | UI-01 | Phase 7: Config History UI | Complete | | UI-02 | Phase 7: Config History UI | Complete | -| UI-03 | Phase 8: Diff Viewer & Download | Pending | +| UI-03 | Phase 8: Diff Viewer & Download | Complete | | UI-04 | Phase 8: Diff Viewer & Download | Pending | | OBS-01 | Phase 10: Audit & Observability | Pending | | OBS-02 | Phase 10: Audit & Observability | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 15d108e..cc787a6 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -133,11 +133,11 @@ Plans: 1. Clicking a timeline entry opens a diff viewer showing unified diff with add (green) / remove (red) line highlighting 2. User can download any snapshot as `router-{device_name}-{timestamp}.rsc` file 3. Diff viewer handles large configs without performance degradation -**Plans**: TBD +**Plans**: 2 plans Plans: -- [ ] 08-01: Unified diff viewer component with syntax highlighting -- [ ] 08-02: Snapshot download as .rsc file +- [ ] 08-01-PLAN.md — Unified diff viewer component with syntax highlighting and clickable timeline entries +- [ ] 08-02-PLAN.md — Snapshot download as .rsc file with download button on timeline entries ### Phase 9: Retention & Cleanup **Goal**: Snapshots older than the retention period are automatically cleaned up, keeping storage bounded @@ -181,6 +181,6 @@ Note: Phase 9 depends only on Phase 3 and Phase 10 depends on Phases 3/4/5, so P | 5. Diff Engine | 2/2 | Complete | 2026-03-13 | | 6. History API | 2/2 | Complete | 2026-03-13 | | 7. Config History UI | 1/1 | Complete | 2026-03-13 | -| 8. Diff Viewer & Download | 0/2 | Not started | - | +| 8. Diff Viewer & Download | 1/2 | In Progress| | | 9. Retention & Cleanup | 0/1 | Not started | - | | 10. Audit & Observability | 0/1 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index f579b51..8e4bd3e 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,14 +3,14 @@ gsd_state_version: 1.0 milestone: v9.6 milestone_name: milestone status: completed -stopped_at: Completed 07-01-PLAN.md -last_updated: "2026-03-13T04:14:00.000Z" +stopped_at: Completed 08-01-PLAN.md +last_updated: "2026-03-13T04:21:58.035Z" last_activity: 2026-03-13 -- Completed 07-01 config history UI timeline component progress: total_phases: 10 completed_phases: 7 - total_plans: 10 - completed_plans: 10 + total_plans: 12 + completed_plans: 11 percent: 100 --- @@ -21,16 +21,16 @@ progress: See: .planning/PROJECT.md (updated 2026-03-12) **Core value:** Operators can see exactly what changed on a router and when, with reliable config snapshots for download -**Current focus:** Phase 7: Config History UI +**Current focus:** Phase 8: Diff Viewer & Download ## Current Position -Phase: 7 of 10 (Config History UI) -- COMPLETE -Plan: 1 of 1 in current phase (all complete) -Status: Phase 7 complete -Last activity: 2026-03-13 -- Completed 07-01 config history UI timeline component +Phase: 8 of 10 (Diff Viewer & Download) +Plan: 1 of 2 in current phase +Status: Plan 08-01 complete +Last activity: 2026-03-13 -- Completed 08-01 diff viewer component -Progress: [██████████] 100% +Progress: [█████████░] 92% ## Performance Metrics @@ -58,6 +58,7 @@ Progress: [██████████] 100% | Phase 06 P01 | 2min | 2 tasks | 4 files | | Phase 06 P02 | 2min | 2 tasks | 3 files | | Phase 07 P01 | 3min | 2 tasks | 3 files | +| Phase 08 P01 | 1min | 2 tasks | 3 files | ## Accumulated Context @@ -89,6 +90,8 @@ Recent decisions affecting current work: - [Phase 06]: 500 error wrapping for Transit decrypt failures in router layer, not service - [Phase 07]: Reimplemented formatRelativeTime locally in ConfigHistorySection (matches BackupTimeline pattern) - [Phase 07]: 60s refetchInterval polling for near-real-time config change visibility +- [Phase 08]: DiffViewer rendered inline above timeline (not modal) for context preservation +- [Phase 08]: Line classification function for unified diff: +green, -red, @@blue, ---/+++ muted ### Pending Todos @@ -100,6 +103,6 @@ None yet. ## Session Continuity -Last session: 2026-03-13T04:14:00.000Z -Stopped at: Completed 07-01-PLAN.md +Last session: 2026-03-13T04:21:58.032Z +Stopped at: Completed 08-01-PLAN.md Resume file: None diff --git a/.planning/phases/08-diff-viewer-download/08-01-SUMMARY.md b/.planning/phases/08-diff-viewer-download/08-01-SUMMARY.md new file mode 100644 index 0000000..1fcbdad --- /dev/null +++ b/.planning/phases/08-diff-viewer-download/08-01-SUMMARY.md @@ -0,0 +1,92 @@ +--- +phase: 08-diff-viewer-download +plan: 01 +subsystem: ui +tags: [react, diff-viewer, tanstack-query, tailwind] + +requires: + - phase: 07-config-history-ui + provides: ConfigHistorySection timeline component with ConfigChangeEntry data + - phase: 06-config-history-api + provides: GET /config/{snapshot_id}/diff endpoint returning DiffResponse +provides: + - DiffViewer component with unified diff rendering (green/red line highlighting) + - configHistoryApi.getDiff() API client method + - Clickable timeline entries in ConfigHistorySection +affects: [08-diff-viewer-download] + +tech-stack: + added: [] + patterns: [inline diff viewer with line-level classification] + +key-files: + created: + - frontend/src/components/config/DiffViewer.tsx + modified: + - frontend/src/lib/api.ts + - frontend/src/components/config/ConfigHistorySection.tsx + +key-decisions: + - "DiffViewer rendered inline above timeline (not modal) for context preservation" + - "Line classification function for unified diff: +green, -red, @@blue, ---/+++ muted" + +patterns-established: + - "Inline viewer pattern: state-driven component rendered above list, closed via callback" + +requirements-completed: [UI-03] + +duration: 1min +completed: 2026-03-13 +--- + +# Phase 8 Plan 1: Diff Viewer Summary + +**Inline diff viewer with green/red line highlighting, wired into clickable config history timeline entries** + +## Performance + +- **Duration:** 1 min +- **Started:** 2026-03-13T04:19:53Z +- **Completed:** 2026-03-13T04:20:56Z +- **Tasks:** 2 +- **Files modified:** 3 + +## Accomplishments +- DiffViewer component renders unified diffs with color-coded lines (green additions, red removals, blue hunk headers) +- API client getDiff method fetches diff data from backend endpoint +- Timeline entries in ConfigHistorySection are clickable with hover states + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Add diff API client and create DiffViewer component** - `dda00fb` (feat) +2. **Task 2: Wire DiffViewer into ConfigHistorySection timeline entries** - `2cf426f` (feat) + +## Files Created/Modified +- `frontend/src/components/config/DiffViewer.tsx` - Unified diff viewer with line-level color highlighting, loading skeleton, error state +- `frontend/src/lib/api.ts` - Added DiffResponse interface and configHistoryApi.getDiff() method +- `frontend/src/components/config/ConfigHistorySection.tsx` - Added click handlers, selectedSnapshotId state, inline DiffViewer rendering + +## Decisions Made +- Rendered DiffViewer inline above the timeline rather than in a modal, preserving context +- Used a classifyLine helper function for clean line-type detection (handles +++ and --- separately from + and -) +- Loading skeleton uses randomized widths for visual variety + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered +None + +## User Setup Required +None - no external service configuration required. + +## Next Phase Readiness +- Diff viewer complete, ready for config download functionality (plan 08-02) +- All TypeScript compiles cleanly + +--- +*Phase: 08-diff-viewer-download* +*Completed: 2026-03-13*