Files
Sharepoint-Toolbox/.planning/phases/06-global-site-selection/06-04-PLAN.md
2026-04-07 09:57:15 +02:00

14 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
06-global-site-selection 04 execute 2
06-01
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
SharepointToolbox/ViewModels/Tabs/BulkMembersViewModel.cs
true
SITE-01
SITE-02
truths artifacts key_links
Permissions tab pre-populates SelectedSites from global sites when no local override exists
Storage, Search, Duplicates, FolderStructure tabs pre-fill SiteUrl from first global site URL
Transfer tab pre-fills SourceSiteUrl from first global site URL
BulkMembers tab does not consume global sites (CSV-driven, no SiteUrl field)
Settings, BulkSites, Templates tabs do not consume global sites (per CONTEXT decisions)
A user can type into a tab's SiteUrl field (local override) without clearing the global state
Global site selection changes update all consuming tabs automatically
path provides contains
SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs Multi-site global consumption — pre-populates SelectedSites OnGlobalSitesChanged
path provides contains
SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs Single-site global consumption — pre-fills SiteUrl OnGlobalSitesChanged
path provides contains
SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs Single-site global consumption — pre-fills SiteUrl OnGlobalSitesChanged
path provides contains
SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs Single-site global consumption — pre-fills SiteUrl OnGlobalSitesChanged
path provides contains
SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs Single-site global consumption — pre-fills SiteUrl OnGlobalSitesChanged
path provides contains
SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs Single-site global consumption — pre-fills SourceSiteUrl OnGlobalSitesChanged
from to via pattern
SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs SharepointToolbox/ViewModels/FeatureViewModelBase.cs Override of OnGlobalSitesChanged virtual method override.*OnGlobalSitesChanged
from to via pattern
SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs SharepointToolbox/ViewModels/FeatureViewModelBase.cs Override of OnGlobalSitesChanged virtual method override.*OnGlobalSitesChanged
Update all consuming tab ViewModels to react to global site selection changes. Multi-site tabs (Permissions) pre-populate their site list; single-site tabs pre-fill their SiteUrl from the first global site. Local overrides take priority at run time.

Purpose: Fulfills SITE-01 (all tabs consume global selection) and SITE-02 (per-tab override without clearing global state). Output: 6 updated tab ViewModels with OnGlobalSitesChanged overrides.

<execution_context> @C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/06-global-site-selection/06-CONTEXT.md @.planning/phases/06-global-site-selection/06-01-SUMMARY.md From SharepointToolbox/ViewModels/FeatureViewModelBase.cs: ```csharp protected IReadOnlyList GlobalSites { get; private set; }

protected virtual void OnGlobalSitesChanged(IReadOnlyList sites) { // Derived classes override to react to global site changes }


<!-- PermissionsViewModel — multi-site pattern (has SelectedSites collection) -->
From SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs:
```csharp
public ObservableCollection<SiteInfo> SelectedSites { get; } = new();
[ObservableProperty] private string _siteUrl = string.Empty;

// RunOperationAsync uses SelectedSites.Count > 0 ? SelectedSites : SiteUrl

From SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs:

[ObservableProperty] private string _siteUrl = string.Empty;

// RunOperationAsync checks string.IsNullOrWhiteSpace(SiteUrl)

From SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs:

[ObservableProperty] private string _sourceSiteUrl = string.Empty;
Task 1: Update PermissionsViewModel for multi-site global consumption SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs PermissionsViewModel already supports multi-site via its SelectedSites collection. The global sites should pre-populate SelectedSites when the user has not made a local override.
Add a private field to track whether the user has made a local site selection on this tab:
```csharp
private bool _hasLocalSiteOverride;
```

Override OnGlobalSitesChanged to pre-populate SelectedSites when no local override exists:
```csharp
protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites)
{
    if (_hasLocalSiteOverride) return;

    SelectedSites.Clear();
    foreach (var site in sites)
        SelectedSites.Add(site);
}
```

In the existing `ExecuteOpenSitePicker` method, set `_hasLocalSiteOverride = true;` after the user picks sites locally. Add this line right before `SelectedSites.Clear()`:
```csharp
private void ExecuteOpenSitePicker()
{
    if (OpenSitePickerDialog == null) return;
    var dialog = OpenSitePickerDialog.Invoke();
    if (dialog?.ShowDialog() == true && dialog is Views.Dialogs.SitePickerDialog picker)
    {
        _hasLocalSiteOverride = true;  // <-- ADD THIS LINE
        SelectedSites.Clear();
        foreach (var site in picker.SelectedUrls)
            SelectedSites.Add(site);
    }
}
```

In the existing `OnTenantSwitched` method, reset the local override flag:
```csharp
protected override void OnTenantSwitched(TenantProfile profile)
{
    _currentProfile = profile;
    _hasLocalSiteOverride = false;  // <-- ADD THIS LINE
    Results = new ObservableCollection<PermissionEntry>();
    SiteUrl = string.Empty;
    SelectedSites.Clear();
    // ... rest unchanged
}
```

Do NOT modify RunOperationAsync — its existing logic already handles the correct priority: `SelectedSites.Count > 0 ? SelectedSites : SiteUrl`. When global sites are active, SelectedSites will be populated, so it naturally uses global sites. When user picks locally, SelectedSites has the local override.
cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5 PermissionsViewModel overrides OnGlobalSitesChanged to pre-populate SelectedSites. Local site picker sets _hasLocalSiteOverride=true to prevent global from overwriting. Tenant switch resets the flag. Task 2: Update single-site tab VMs (Storage, Search, Duplicates, FolderStructure) for global consumption SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs, SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs, SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs, SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs All four single-site tabs follow the identical pattern: pre-fill SiteUrl from the first global site when the user has not typed a local URL.
For EACH of these four ViewModels, apply the same changes:

1. Add a using directive if not present:
```csharp
using SharepointToolbox.Core.Models;  // for SiteInfo — likely already imported for TenantProfile
```

2. Add a private tracking field (place near other private fields):
```csharp
private bool _hasLocalSiteOverride;
```

3. Override OnGlobalSitesChanged:
```csharp
protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites)
{
    if (_hasLocalSiteOverride) return;
    SiteUrl = sites.Count > 0 ? sites[0].Url : string.Empty;
}
```

4. Detect local override when user modifies SiteUrl. Add a partial method for the [ObservableProperty] SiteUrl change notification:
```csharp
partial void OnSiteUrlChanged(string value)
{
    // If the user typed something different from the global site, mark as local override.
    // Empty string means user cleared it — revert to global.
    if (string.IsNullOrWhiteSpace(value))
    {
        _hasLocalSiteOverride = false;
        // Re-apply global sites if available
        if (GlobalSites.Count > 0)
            SiteUrl = GlobalSites[0].Url;
    }
    else if (GlobalSites.Count == 0 || value != GlobalSites[0].Url)
    {
        _hasLocalSiteOverride = true;
    }
}
```

IMPORTANT: Check if any of these VMs already has a `partial void OnSiteUrlChanged` method. If so, merge the logic into the existing method rather than creating a duplicate. Currently:
- StorageViewModel: no OnSiteUrlChanged — add it
- SearchViewModel: no OnSiteUrlChanged — add it
- DuplicatesViewModel: no OnSiteUrlChanged — add it
- FolderStructureViewModel: no OnSiteUrlChanged — add it

5. In the existing `OnTenantSwitched` method of each VM, add `_hasLocalSiteOverride = false;` at the beginning of the method body (after `_currentProfile = profile;`).

Do NOT modify RunOperationAsync in any of these VMs — they already check `string.IsNullOrWhiteSpace(SiteUrl)` and use the value directly. When global sites are active, SiteUrl will be pre-filled, so the existing logic works.
cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5 StorageViewModel, SearchViewModel, DuplicatesViewModel, and FolderStructureViewModel all override OnGlobalSitesChanged to pre-fill SiteUrl from first global site. Local typing sets _hasLocalSiteOverride=true. Tenant switch resets the flag. Build succeeds. Task 3: Update TransferViewModel and verify BulkMembersViewModel excluded SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs, SharepointToolbox/ViewModels/Tabs/BulkMembersViewModel.cs **TransferViewModel** — Pre-fill SourceSiteUrl from first global site (same pattern as single-site tabs, but the field is SourceSiteUrl not SiteUrl).
1. Add tracking field:
```csharp
private bool _hasLocalSourceSiteOverride;
```

2. Override OnGlobalSitesChanged:
```csharp
protected override void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> sites)
{
    if (_hasLocalSourceSiteOverride) return;
    SourceSiteUrl = sites.Count > 0 ? sites[0].Url : string.Empty;
}
```

3. Add partial method for SourceSiteUrl change notification:
```csharp
partial void OnSourceSiteUrlChanged(string value)
{
    if (string.IsNullOrWhiteSpace(value))
    {
        _hasLocalSourceSiteOverride = false;
        if (GlobalSites.Count > 0)
            SourceSiteUrl = GlobalSites[0].Url;
    }
    else if (GlobalSites.Count == 0 || value != GlobalSites[0].Url)
    {
        _hasLocalSourceSiteOverride = true;
    }
}
```

4. In the existing `OnTenantSwitched` method, add `_hasLocalSourceSiteOverride = false;` at the beginning.

**BulkMembersViewModel** — Verify it does NOT need changes. BulkMembersViewModel has no SiteUrl field (it reads site URLs from CSV rows). Confirm this by checking: it should NOT have an OnGlobalSitesChanged override. Do NOT modify this file — only verify it has no SiteUrl property.

Note: SettingsViewModel, BulkSitesViewModel, and TemplatesViewModel also do NOT consume global sites per the CONTEXT decisions. Do NOT modify them.
cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5 TransferViewModel overrides OnGlobalSitesChanged to pre-fill SourceSiteUrl. BulkMembersViewModel is confirmed excluded (no SiteUrl, no override). Build succeeds. - `dotnet build SharepointToolbox/SharepointToolbox.csproj` succeeds with 0 errors - `dotnet test` shows no new failures - PermissionsViewModel has OnGlobalSitesChanged override populating SelectedSites - StorageViewModel, SearchViewModel, DuplicatesViewModel, FolderStructureViewModel have OnGlobalSitesChanged override setting SiteUrl - TransferViewModel has OnGlobalSitesChanged override setting SourceSiteUrl - BulkMembersViewModel, SettingsViewModel, BulkSitesViewModel, TemplatesViewModel are NOT modified - All consuming VMs have _hasLocalSiteOverride tracking - All consuming VMs reset the override flag on tenant switch

<success_criteria> Every tab that should consume global sites does so automatically. Multi-site tab (Permissions) pre-populates its SelectedSites collection. Single-site tabs pre-fill their SiteUrl/SourceSiteUrl from the first global site. Users can type a different URL on any tab without clearing the global state. Tabs that don't apply (Settings, BulkSites, Templates, BulkMembers) are unaffected. </success_criteria>

After completion, create `.planning/phases/06-global-site-selection/06-04-SUMMARY.md`