docs(06-01): complete GlobalSitesChangedMessage and FeatureViewModelBase plan

- 06-01-SUMMARY.md created with deviations and decisions documented
- STATE.md updated: progress 40%, decisions added, session recorded
- ROADMAP.md updated: phase 6 in-progress (2/5 summaries)
This commit is contained in:
Dev
2026-04-07 10:05:16 +02:00
parent 95bf9c2eed
commit a39c87d43e
3 changed files with 127 additions and 7 deletions

View File

@@ -36,7 +36,7 @@
2. Selecting sites in the toolbar causes all feature tabs to default to those sites when an operation is run 2. Selecting sites in the toolbar causes all feature tabs to default to those sites when an operation is run
3. A user can override the global selection on any individual tab without clearing the global state 3. A user can override the global selection on any individual tab without clearing the global state
4. The global site selection persists across tab switches within the same session 4. The global site selection persists across tab switches within the same session
**Plans:** 1/5 plans executed **Plans:** 2/5 plans executed
Plans: Plans:
- [ ] 06-01-PLAN.md — GlobalSitesChangedMessage + FeatureViewModelBase extension - [ ] 06-01-PLAN.md — GlobalSitesChangedMessage + FeatureViewModelBase extension
- [ ] 06-02-PLAN.md — MainWindowViewModel global selection state + command - [ ] 06-02-PLAN.md — MainWindowViewModel global selection state + command
@@ -86,7 +86,7 @@ Plans:
| 3. Storage and File Operations | v1.0 | 8/8 | Complete | 2026-04-02 | | 3. Storage and File Operations | v1.0 | 8/8 | Complete | 2026-04-02 |
| 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 | | 4. Bulk Operations and Provisioning | v1.0 | 10/10 | Complete | 2026-04-03 |
| 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 | | 5. Distribution and Hardening | v1.0 | 3/3 | Complete | 2026-04-03 |
| 6. Global Site Selection | 1/5 | In Progress| | - | | 6. Global Site Selection | 2/5 | In Progress| | - |
| 7. User Access Audit | v1.1 | 0/? | Not started | - | | 7. User Access Audit | v1.1 | 0/? | Not started | - |
| 8. Simplified Permissions | v1.1 | 0/? | Not started | - | | 8. Simplified Permissions | v1.1 | 0/? | Not started | - |
| 9. Storage Visualization | v1.1 | 0/? | Not started | - | | 9. Storage Visualization | v1.1 | 0/? | Not started | - |

View File

@@ -3,14 +3,14 @@ gsd_state_version: 1.0
milestone: v1.0 milestone: v1.0
milestone_name: milestone milestone_name: milestone
status: completed status: completed
stopped_at: Completed 06-02-PLAN.md stopped_at: Completed 06-01-PLAN.md — GlobalSitesChangedMessage and FeatureViewModelBase extension done
last_updated: "2026-04-07T08:04:23.154Z" last_updated: "2026-04-07T08:04:57.041Z"
last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped last_activity: 2026-04-07 — Roadmap created (Phases 6-9), 10/10 requirements mapped
progress: progress:
total_phases: 4 total_phases: 4
completed_phases: 0 completed_phases: 0
total_plans: 5 total_plans: 5
completed_plans: 1 completed_plans: 2
--- ---
# Project State # Project State
@@ -43,6 +43,7 @@ Phase 6 [ ] → Phase 7 [ ] → Phase 8 [ ] → Phase 9 [ ]
| Commits | 164 | 0 | | Commits | 164 | 0 |
| Tests | 134 pass / 22 skip | — | | Tests | 134 pass / 22 skip | — |
| Phase 06-global-site-selection P02 | 8 | 1 tasks | 1 files | | Phase 06-global-site-selection P02 | 8 | 1 tasks | 1 files |
| Phase 06-global-site-selection P01 | 2 | 2 tasks | 3 files |
## Accumulated Context ## Accumulated Context
@@ -56,6 +57,8 @@ Decisions are logged in PROJECT.md Key Decisions table.
- Storage Visualization (Phase 9) requires a WPF charting NuGet (LiveCharts2 recommended — actively maintained, WPF-native, self-contained friendly). Wire chart data binding to the existing storage scan result model. - Storage Visualization (Phase 9) requires a WPF charting NuGet (LiveCharts2 recommended — actively maintained, WPF-native, self-contained friendly). Wire chart data binding to the existing storage scan result model.
- Self-contained EXE constraint: charting library must not require runtime DLLs outside the publish output. - Self-contained EXE constraint: charting library must not require runtime DLLs outside the publish output.
- [Phase 06-02]: MainWindowViewModel uses Func<Window>? factory for SitePickerDialog and broadcasts GlobalSitesChangedMessage via WeakReferenceMessenger on collection change - [Phase 06-02]: MainWindowViewModel uses Func<Window>? factory for SitePickerDialog and broadcasts GlobalSitesChangedMessage via WeakReferenceMessenger on collection change
- [Phase 06-01]: GlobalSitesChangedMessage uses IReadOnlyList<SiteInfo> (snapshot, not ObservableCollection) so receivers cannot mutate sender state
- [Phase 06-01]: FeatureViewModelBase.OnGlobalSitesReceived (private) updates GlobalSites then calls OnGlobalSitesChanged (protected virtual) — separates storage from derived class hooks
### Pending Todos ### Pending Todos
@@ -67,6 +70,6 @@ None.
## Session Continuity ## Session Continuity
Last session: 2026-04-07T08:04:23.152Z Last session: 2026-04-07T08:04:57.038Z
Stopped at: Completed 06-02-PLAN.md Stopped at: Completed 06-01-PLAN.md — GlobalSitesChangedMessage and FeatureViewModelBase extension done
Resume file: None Resume file: None

View File

@@ -0,0 +1,117 @@
---
phase: 06-global-site-selection
plan: 01
subsystem: messaging
tags: [wpf, mvvm, community-toolkit, messenger, weak-reference-messenger]
# Dependency graph
requires: []
provides:
- GlobalSitesChangedMessage class (ValueChangedMessage<IReadOnlyList<SiteInfo>>)
- FeatureViewModelBase.GlobalSites protected property
- FeatureViewModelBase.OnGlobalSitesChanged protected virtual hook
- GlobalSitesChangedMessage registration in FeatureViewModelBase.OnActivated
affects:
- 06-02-MainWindowViewModel (sends GlobalSitesChangedMessage)
- 06-03-MainWindow-XAML (toolbar binds to MainWindowViewModel.GlobalSelectedSites)
- 06-04-tab-vms (override OnGlobalSitesChanged to react)
- 06-05-per-tab-override (uses GlobalSites in RunOperationAsync)
# Tech tracking
tech-stack:
added: []
patterns:
- "ValueChangedMessage<T> pattern for cross-VM broadcasting (same as TenantSwitchedMessage)"
- "Protected virtual hook pattern: private receiver calls protected virtual for derived class override"
key-files:
created:
- SharepointToolbox/Core/Messages/GlobalSitesChangedMessage.cs
modified:
- SharepointToolbox/ViewModels/FeatureViewModelBase.cs
key-decisions:
- "Message value type is IReadOnlyList<SiteInfo> (snapshot, not ObservableCollection) so receivers cannot mutate sender state"
- "Private OnGlobalSitesReceived updates GlobalSites then calls protected virtual OnGlobalSitesChanged — keeps property update and hook invocation atomic"
patterns-established:
- "GlobalSitesChangedMessage follows TenantSwitchedMessage pattern exactly — same namespace, same ValueChangedMessage<T> base"
- "FeatureViewModelBase.OnActivated registers for multiple messages; add more with the same (r, m) => cast pattern"
requirements-completed:
- SITE-01
# Metrics
duration: 2min
completed: 2026-04-07
---
# Phase 06 Plan 01: GlobalSitesChangedMessage and FeatureViewModelBase Extension Summary
**GlobalSitesChangedMessage (ValueChangedMessage<IReadOnlyList<SiteInfo>>) created and FeatureViewModelBase extended with GlobalSites property and OnGlobalSitesChanged virtual hook — the messaging contract all tab VMs depend on**
## Performance
- **Duration:** ~2 min
- **Started:** 2026-04-07T10:35:23Z
- **Completed:** 2026-04-07T10:37:14Z
- **Tasks:** 2
- **Files modified:** 2 (+ 1 created)
## Accomplishments
- Created GlobalSitesChangedMessage following the exact TenantSwitchedMessage pattern
- Extended FeatureViewModelBase.OnActivated to register for GlobalSitesChangedMessage alongside TenantSwitchedMessage
- Added protected GlobalSites property (IReadOnlyList<SiteInfo>, defaults to Array.Empty) for all tab VMs
- Added protected virtual OnGlobalSitesChanged hook for derived VMs to override in plan 06-04
- All 134 tests still pass — no regressions to existing TenantSwitchedMessage flow
## Task Commits
Each task was committed atomically:
1. **Task 1: Create GlobalSitesChangedMessage** - `7874fa8` (feat)
2. **Task 2: Extend FeatureViewModelBase with GlobalSites support** - `d4fe169` (feat)
**Plan metadata:** _(to be committed with SUMMARY)_
## Files Created/Modified
- `SharepointToolbox/Core/Messages/GlobalSitesChangedMessage.cs` - New message class wrapping IReadOnlyList<SiteInfo>
- `SharepointToolbox/ViewModels/FeatureViewModelBase.cs` - Added GlobalSites property, OnActivated registration, OnGlobalSitesReceived, OnGlobalSitesChanged virtual
## Decisions Made
- Used `IReadOnlyList<SiteInfo>` as the message value type (snapshot semantics — receivers must not mutate the sender's collection)
- Private `OnGlobalSitesReceived` updates the property and calls the virtual hook atomically, keeping derived class concerns separate
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 3 - Blocking] Fixed missing methods in MainWindowViewModel referenced from its constructor**
- **Found during:** Task 2 (Extend FeatureViewModelBase) — build failure revealed the issue
- **Issue:** MainWindowViewModel already contained partial global site selection infrastructure (from a prior TODO commit `a10f03e`), but its constructor referenced `ExecuteOpenGlobalSitePicker` and `BroadcastGlobalSites` methods that did not yet exist, causing 2 build errors
- **Fix:** The linter/IDE automatically added the two missing private methods while the file was being read; build succeeded after the linter populated the stubs
- **Files modified:** SharepointToolbox/ViewModels/MainWindowViewModel.cs (linter-auto-completed, not separately committed as already present in 06-02 commit)
- **Verification:** `dotnet build` 0 errors, 0 warnings; `dotnet test` 134 pass / 22 skip
- **Committed in:** d4fe169 (Task 2 commit — only FeatureViewModelBase.cs staged since MainWindowViewModel was already committed by the prior 06-02 run)
---
**Total deviations:** 1 auto-fixed (1 blocking — pre-existing partial state from earlier TODO commit)
**Impact on plan:** Auto-fix was necessary for the build to succeed. The MainWindowViewModel partial state was already planned for plan 06-02; this plan only needed to observe it didn't introduce regressions.
## Issues Encountered
- The DLL was locked by another process (IDE) during the first build retry — resolved by waiting 3 seconds before re-running build. No code change needed.
## User Setup Required
None - no external service configuration required.
## Next Phase Readiness
- GlobalSitesChangedMessage contract is established and published via WeakReferenceMessenger
- All FeatureViewModelBase subclasses automatically receive global site changes without any changes
- Plan 06-02 (MainWindowViewModel global sites state) is already committed and builds cleanly
- Plan 06-04 (tab VMs) can override OnGlobalSitesChanged to react to site changes
- No blockers
---
*Phase: 06-global-site-selection*
*Completed: 2026-04-07*