--- phase: 06-global-site-selection plan: 04 subsystem: tab-viewmodels tags: [wpf, mvvm, community-toolkit, global-sites, override-pattern] # Dependency graph requires: - 06-01 (FeatureViewModelBase.OnGlobalSitesChanged virtual hook) provides: - PermissionsViewModel.OnGlobalSitesChanged (multi-site: pre-populates SelectedSites) - StorageViewModel.OnGlobalSitesChanged (single-site: pre-fills SiteUrl) - SearchViewModel.OnGlobalSitesChanged (single-site: pre-fills SiteUrl) - DuplicatesViewModel.OnGlobalSitesChanged (single-site: pre-fills SiteUrl) - FolderStructureViewModel.OnGlobalSitesChanged (single-site: pre-fills SiteUrl) - TransferViewModel.OnGlobalSitesChanged (single-site: pre-fills SourceSiteUrl) affects: - 06-05-per-tab-override (consumes GlobalSites in RunOperationAsync as fallback) # Tech tracking tech-stack: added: [] patterns: - "partial void OnXxxChanged — CommunityToolkit partial property change notification used to detect local user input and set override flag" - "_hasLocalSiteOverride / _hasLocalSourceSiteOverride field pattern — prevents global site changes from overwriting user's local entry" - "Tenant switch resets override flag — ensures fresh tenant starts with global site pre-fill active" key-files: created: [] modified: - SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs - SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs - SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs - SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs - SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs - SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs key-decisions: - "PermissionsViewModel uses _hasLocalSiteOverride to guard SelectedSites; site picker dialog sets flag to true, tenant switch resets it to false" - "Single-site VMs use partial void OnSiteUrlChanged to detect local typing; clearing the field reverts to global, non-empty different value sets override" - "BulkMembersViewModel excluded: confirmed no SiteUrl field (CSV-driven per-row site URLs)" - "SettingsViewModel, BulkSitesViewModel, TemplatesViewModel excluded per CONTEXT decisions — not modified" # Metrics duration: 2min completed: 2026-04-07 requirements-completed: - SITE-01 - SITE-02 --- # Phase 06 Plan 04: Tab ViewModels Global Site Consumption Summary **All 6 consuming tab ViewModels wired to override OnGlobalSitesChanged — PermissionsViewModel pre-populates SelectedSites (multi-site), 4 single-site tabs pre-fill SiteUrl, TransferViewModel pre-fills SourceSiteUrl, all with local-override protection via _hasLocalSiteOverride flag** ## Performance - **Duration:** ~2 min - **Started:** 2026-04-07T08:06:19Z - **Completed:** 2026-04-07T08:08:35Z - **Tasks:** 3 - **Files modified:** 6 ## Accomplishments - PermissionsViewModel: Added `OnGlobalSitesChanged` override that pre-populates `SelectedSites` from global sites when no local override is active - PermissionsViewModel: Site picker dialog (`ExecuteOpenSitePicker`) now sets `_hasLocalSiteOverride = true` before clearing/repopulating SelectedSites - PermissionsViewModel: `OnTenantSwitched` resets `_hasLocalSiteOverride = false` so new tenant immediately uses global sites - StorageViewModel, SearchViewModel, DuplicatesViewModel, FolderStructureViewModel: Added identical `OnGlobalSitesChanged` + `partial void OnSiteUrlChanged` + `_hasLocalSiteOverride` pattern - TransferViewModel: Added `OnGlobalSitesChanged` + `partial void OnSourceSiteUrlChanged` + `_hasLocalSourceSiteOverride` pattern for `SourceSiteUrl` - BulkMembersViewModel confirmed excluded — no `SiteUrl` field, CSV-driven, no changes made - All 134 tests pass (0 failures, 22 skipped — same baseline as plan 06-01) - Build succeeds with 0 errors, 0 warnings ## Task Commits Each task was committed atomically: 1. **Task 1: Update PermissionsViewModel for multi-site global consumption** - `1bf47b5` (feat) 2. **Task 2: Update single-site tab VMs (Storage, Search, Duplicates, FolderStructure)** - `6a2e4d1` (feat) 3. **Task 3: Update TransferViewModel and verify BulkMembersViewModel excluded** - `0a91dd4` (feat) ## Files Created/Modified - `SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs` — Added `_hasLocalSiteOverride`, `OnGlobalSitesChanged`, updated `ExecuteOpenSitePicker` and `OnTenantSwitched` - `SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs` — Added `_hasLocalSiteOverride`, `OnGlobalSitesChanged`, `OnSiteUrlChanged`, updated `OnTenantSwitched` - `SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs` — Added `_hasLocalSiteOverride`, `OnGlobalSitesChanged`, `OnSiteUrlChanged`, updated `OnTenantSwitched` - `SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs` — Added `_hasLocalSiteOverride`, `OnGlobalSitesChanged`, `OnSiteUrlChanged`, updated `OnTenantSwitched` - `SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs` — Added `_hasLocalSiteOverride`, `OnGlobalSitesChanged`, `OnSiteUrlChanged`, updated `OnTenantSwitched` - `SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs` — Added `_hasLocalSourceSiteOverride`, `OnGlobalSitesChanged`, `OnSourceSiteUrlChanged`, updated `OnTenantSwitched` ## Decisions Made - Used `partial void OnSiteUrlChanged` (CommunityToolkit partial method) to detect user typing — this fires for every programmatic and user-driven change, so the guard `value != GlobalSites[0].Url` ensures global pre-fills don't incorrectly set the override flag - When user clears SiteUrl (empty string), the override resets and global is re-applied immediately — design choice to make clearing feel like "go back to global" - PermissionsViewModel pattern differs from single-site VMs: it has no `OnSiteUrlChanged` because its authoritative input is `SelectedSites` (managed by site picker dialog), not free text ## Deviations from Plan None — plan executed exactly as written. BulkMembersViewModel was confirmed to have no `SiteUrl` field as expected. ## Issues Encountered None. ## User Setup Required None — no external service configuration required. ## Self-Check: PASSED All 7 expected files found. All 3 task commits verified in git log. ## Next Phase Readiness - All 6 consuming tab VMs now react to `GlobalSitesChangedMessage` automatically - Local override pattern is consistent across all tabs — users can type freely without clearing global state - Plan 06-05 (per-tab override enforcement in RunOperationAsync) can proceed - No blockers