docs(17-02): complete group expansion HTML reports plan
- 17-02-SUMMARY.md created - STATE.md updated: session, decisions, progress - ROADMAP.md: phase 17 marked complete (2/2 plans) - REQUIREMENTS.md: RPT-01 marked complete
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
---
|
||||
phase: 17-group-expansion-html-reports
|
||||
plan: "02"
|
||||
subsystem: html-export
|
||||
tags: [html-export, group-expansion, permissions-viewmodel, tdd]
|
||||
dependency_graph:
|
||||
requires: ["17-01"]
|
||||
provides: ["expandable-group-pills-html", "group-resolver-wired-to-export"]
|
||||
affects: ["HtmlExportService", "PermissionsViewModel"]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns: ["optional-parameter-backward-compat", "pre-render-resolution", "inline-js-toggle"]
|
||||
key_files:
|
||||
created: []
|
||||
modified:
|
||||
- SharepointToolbox/Services/Export/HtmlExportService.cs
|
||||
- SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs
|
||||
- SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs
|
||||
decisions:
|
||||
- "groupMembers added as optional last parameter to both BuildHtml overloads and WriteAsync methods — null produces byte-identical output to pre-Phase 17"
|
||||
- "Group pill expansion uses name-based lookup in groupMembers dict (not login) — matches how SharePoint groups are identified in Users field"
|
||||
- "ISharePointGroupResolver injected as optional last parameter in PermissionsViewModel main constructor — DI works without explicit resolver if not registered"
|
||||
- "Resolution failure logged as Warning and export proceeds without expansion — never blocks user export"
|
||||
metrics:
|
||||
duration_seconds: 204
|
||||
completed_date: "2026-04-09"
|
||||
tasks_completed: 2
|
||||
files_modified: 3
|
||||
---
|
||||
|
||||
# Phase 17 Plan 02: Group Expansion Wire-up Summary
|
||||
|
||||
Expandable SharePoint group pills in HTML reports with toggleGroup JS and PermissionsViewModel pre-render resolution via ISharePointGroupResolver.
|
||||
|
||||
## Tasks Completed
|
||||
|
||||
| Task | Description | Commit | Status |
|
||||
|------|-------------|--------|--------|
|
||||
| 1 (RED) | Failing tests for group pill expansion | c35ee76 | Done |
|
||||
| 1 (GREEN) | HtmlExportService: groupMembers param + expandable pills + toggleGroup JS | 07ed6e2 | Done |
|
||||
| 2 | PermissionsViewModel: ISharePointGroupResolver injection + ExportHtmlAsync wiring | aab3aee | Done |
|
||||
|
||||
## What Was Built
|
||||
|
||||
Both `BuildHtml` overloads in `HtmlExportService` now accept an optional `IReadOnlyDictionary<string, IReadOnlyList<ResolvedMember>>? groupMembers` parameter. When provided:
|
||||
|
||||
- SharePoint group pills render as `<span class="user-pill group-expandable" onclick="toggleGroup('grpmem0')">` with a down-arrow indicator
|
||||
- A hidden `<tr data-group="grpmem0" style="display:none">` sub-row is injected immediately after the parent row, containing resolved member display names and logins
|
||||
- Empty member lists (resolution failed) render `<em style="color:#888">members unavailable</em>`
|
||||
- `toggleGroup(id)` JS function is added to the inline script block
|
||||
- `filterTable()` updated to skip `data-group` sub-rows
|
||||
- CSS `.group-expandable` adds cursor pointer and hover opacity
|
||||
|
||||
`PermissionsViewModel` now injects `ISharePointGroupResolver?` as an optional last constructor parameter. In `ExportHtmlAsync`, before calling `WriteAsync`, it:
|
||||
1. Collects all distinct group names from `Results` where `PrincipalType == "SharePointGroup"`
|
||||
2. Calls `_groupResolver.ResolveGroupsAsync(ctx, clientId, groupNames, ct)` if resolver is non-null and groups were found
|
||||
3. Passes the resulting `groupMembers` dict to both `WriteAsync` call sites (standard and simplified paths)
|
||||
4. On resolution failure, logs a warning and exports without expansion (graceful degradation)
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Verification
|
||||
|
||||
- `dotnet build` — 0 errors, 0 warnings
|
||||
- `dotnet test --filter "FullyQualifiedName~HtmlExportServiceTests"` — 32 tests pass (includes 6 new group expansion tests)
|
||||
- `dotnet test` — 320 passed, 0 failed, 28 skipped (full suite green)
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
Files verified:
|
||||
- SharepointToolbox/Services/Export/HtmlExportService.cs — contains `toggleGroup`, `groupMembers`, `group-expandable`
|
||||
- SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs — contains `_groupResolver`, `ResolveGroupsAsync`
|
||||
- SharepointToolbox.Tests/Services/Export/HtmlExportServiceTests.cs — contains `grpmem` test patterns
|
||||
|
||||
Commits verified:
|
||||
- c35ee76 — test(17-02): RED phase
|
||||
- 07ed6e2 — feat(17-02): HtmlExportService implementation
|
||||
- aab3aee — feat(17-02): PermissionsViewModel wiring
|
||||
Reference in New Issue
Block a user