docs: start milestone v2.2 Report Branding & User Directory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
131
.planning/phases/06-global-site-selection/06-CONTEXT.md
Normal file
131
.planning/phases/06-global-site-selection/06-CONTEXT.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Phase 6: Global Site Selection - Context
|
||||
|
||||
**Gathered:** 2026-04-07
|
||||
**Status:** Ready for planning
|
||||
|
||||
<domain>
|
||||
## Phase Boundary
|
||||
|
||||
Administrators 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:
|
||||
1. A multi-site picker control is visible in the main toolbar at all times, regardless of which tab is active
|
||||
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
|
||||
4. The global site selection persists across tab switches within the same session
|
||||
|
||||
</domain>
|
||||
|
||||
<decisions>
|
||||
## Implementation Decisions
|
||||
|
||||
### 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<SiteInfo>>) sent via WeakReferenceMessenger when the toolbar selection changes
|
||||
- `MainWindowViewModel` owns 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
|
||||
- `FeatureViewModelBase` registers for `GlobalSitesChangedMessage` in `OnActivated()` and stores the global sites in a protected property `IReadOnlyList<SiteInfo> GlobalSites`
|
||||
- Each tab's `RunOperationAsync` checks: 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
|
||||
|
||||
</decisions>
|
||||
|
||||
<code_context>
|
||||
## Existing Code Insights
|
||||
|
||||
### Reusable Assets
|
||||
- `SitePickerDialog` (Views/Dialogs/): Filterable checkbox list of sites with Select All/Deselect All — loads from `ISiteListService.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 PermissionsViewModel
|
||||
- `ISiteListService.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 pattern
|
||||
- `WeakReferenceMessenger`: Already used for TenantSwitched and ProgressUpdated messages
|
||||
- `FeatureViewModelBase.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 state
|
||||
- `ObservableCollection<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 ToolBar
|
||||
- `MainWindowViewModel.cs`: Add GlobalSelectedSites, OpenGlobalSitePickerCommand, GlobalSitesChangedMessage broadcast
|
||||
- `MainWindow.xaml.cs`: Wire SitePickerDialog factory for the toolbar (same pattern as PermissionsView)
|
||||
- `FeatureViewModelBase.cs`: Register for GlobalSitesChangedMessage, add GlobalSites property
|
||||
- `Core/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 picker
|
||||
- `App.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>
|
||||
|
||||
<specifics>
|
||||
## 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)
|
||||
|
||||
</specifics>
|
||||
|
||||
<deferred>
|
||||
## Deferred Ideas
|
||||
|
||||
None — all items are within phase scope
|
||||
|
||||
</deferred>
|
||||
|
||||
---
|
||||
|
||||
*Phase: 06-global-site-selection*
|
||||
*Context gathered: 2026-04-07*
|
||||
Reference in New Issue
Block a user