6.9 KiB
6.9 KiB
Phase 6: Global Site Selection - Context
Gathered: 2026-04-07 Status: Ready for planning
## Phase BoundaryAdministrators can select one or more target sites once from the toolbar and have every feature tab use that selection by default — eliminating the need to re-enter site URLs on each tab. Individual tabs can override the global selection without clearing the global state.
Requirements: SITE-01, SITE-02
Success Criteria:
- A multi-site picker control is visible in the main toolbar at all times, regardless of which tab is active
- Selecting sites in the toolbar causes all feature tabs to default to those sites when an operation is run
- A user can override the global selection on any individual tab without clearing the global state
- The global site selection persists across tab switches within the same session
Toolbar site picker placement
- Add a "Select Sites" button to the existing ToolBar (after the Clear Session button, separated by a Separator)
- Next to the button, show a summary label: "3 site(s) selected" or "No sites selected"
- Clicking the button opens the existing SitePickerDialog pattern (reuse from PermissionsViewModel)
- The picker requires a connected tenant (button disabled when no profile is connected)
Global selection broadcast
- Create a new
GlobalSitesChangedMessage(ValueChangedMessage<IReadOnlyList>) sent via WeakReferenceMessenger when the toolbar selection changes MainWindowViewModelowns the global site selection state:ObservableCollection<SiteInfo> GlobalSelectedSites- On tenant switch, clear the global selection (sites belong to a tenant)
Tab consumption of global selection
FeatureViewModelBaseregisters forGlobalSitesChangedMessageinOnActivated()and stores the global sites in a protected propertyIReadOnlyList<SiteInfo> GlobalSites- Each tab's
RunOperationAsyncchecks: if local override sites exist, use those; else if GlobalSites is non-empty, use those; else fall back to the SiteUrl text box - The SiteUrl TextBox on each tab shows a placeholder/hint when global sites are active (e.g., "Using 3 globally selected sites" as watermark text)
Local override behavior
- Tabs that already have per-tab site pickers (like Permissions) keep them
- When a user picks sites locally on a tab, that overrides the global selection for that tab only
- A "Clear local selection" action resets the tab back to using global sites
- The global selection in the toolbar is never modified by per-tab overrides
Tabs that DO NOT consume global sites
- Settings tab: no site URL needed
- Bulk Sites tab: creates sites from CSV, does not target existing sites
- Templates tab (apply): creates a new site, does not target existing sites
Tabs that consume global sites (single-site)
- Storage, Search, Duplicates, Folder Structure: these currently take a single SiteUrl
- When global sites are selected, these tabs use the first site in the global list by default
- The SiteUrl TextBox is pre-filled with the first global site URL (user can change it = local override)
Tabs that consume global sites (multi-site)
- Permissions: already supports multi-site; global sites pre-populate its SelectedSites collection
- Transfer: source site pre-filled from first global site
Claude's Discretion
- Exact XAML layout of the toolbar site picker button and label
- Whether to refactor SitePickerDialog or reuse as-is from MainWindow code-behind
- Internal naming of properties and helper methods
- Whether to add a chip/tag display for selected sites or keep it as a count label
- Localization key names for new strings
<code_context>
Existing Code Insights
Reusable Assets
SitePickerDialog(Views/Dialogs/): Filterable checkbox list of sites with Select All/Deselect All — loads fromISiteListService.GetSitesAsync(). Currently only wired from PermissionsView; needs to be wired from MainWindow toolbar too.SiteInfo(string Url, string Title)record (Core/Models/): Already used by SitePickerDialog and PermissionsViewModelISiteListService.GetSitesAsync(TenantProfile, progress, ct): Enumerates all sites in a tenant. Already registered in DI.TenantSwitchedMessage: Broadcast pattern for tenant changes — global site selection follows the same patternWeakReferenceMessenger: Already used for TenantSwitched and ProgressUpdated messagesFeatureViewModelBase.OnActivated(): Already registers for TenantSwitchedMessage — extend to also register for GlobalSitesChangedMessage
Established Patterns
- Dialog factories set on ViewModels as
Func<Window>?from View code-behind (keeps Window refs out of VMs) [ObservableProperty]for bindable stateObservableCollection<T>for list-bound UI elements- Tab content resolved from DI in MainWindow.xaml.cs
- Localization via
TranslationSource.Instance["key"]with Strings.resx / Strings.fr.resx
Integration Points
MainWindow.xaml: Add site picker button + label to ToolBarMainWindowViewModel.cs: Add GlobalSelectedSites, OpenGlobalSitePickerCommand, GlobalSitesChangedMessage broadcastMainWindow.xaml.cs: Wire SitePickerDialog factory for the toolbar (same pattern as PermissionsView)FeatureViewModelBase.cs: Register for GlobalSitesChangedMessage, add GlobalSites propertyCore/Messages/: New GlobalSitesChangedMessage class- Each tab ViewModel: Update RunOperationAsync to check GlobalSites before falling back to SiteUrl
Strings.resx/Strings.fr.resx: New localization keys for toolbar site pickerApp.xaml.cs: No new DI registrations needed (SitePickerDialog factory and ISiteListService already registered)
Key Files
| File | Role |
|---|---|
MainWindow.xaml |
Toolbar XAML — add site picker controls |
MainWindowViewModel.cs |
Global selection state + command |
MainWindow.xaml.cs |
Wire SitePickerDialog factory for toolbar |
FeatureViewModelBase.cs |
Base class — receive global sites message |
Core/Messages/TenantSwitchedMessage.cs |
Pattern reference for new message |
Views/Dialogs/SitePickerDialog.xaml.cs |
Reuse as-is |
ViewModels/Tabs/PermissionsViewModel.cs |
Already has multi-site pattern — adapt to consume global sites |
ViewModels/Tabs/StorageViewModel.cs |
Single-site pattern — adapt to consume global sites |
</code_context>
## Specific Ideas- The toolbar site count label should update live when sites are selected/deselected
- When no tenant is connected, the "Select Sites" button should be disabled with a tooltip explaining why
- Clearing the session (Clear Session button) should also clear the global site selection
- The global selection should survive tab switching (it lives on MainWindowViewModel, not on any tab)
None — all items are within phase scope
Phase: 06-global-site-selection Context gathered: 2026-04-07