---
phase: 06-global-site-selection
plan: 04
type: execute
wave: 2
depends_on: [06-01]
files_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
  - SharepointToolbox/ViewModels/Tabs/BulkMembersViewModel.cs
autonomous: true
requirements:
  - SITE-01
  - SITE-02
must_haves:
  truths:
    - "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"
  artifacts:
    - path: "SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs"
      provides: "Multi-site global consumption — pre-populates SelectedSites"
      contains: "OnGlobalSitesChanged"
    - path: "SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs"
      provides: "Single-site global consumption — pre-fills SiteUrl"
      contains: "OnGlobalSitesChanged"
    - path: "SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs"
      provides: "Single-site global consumption — pre-fills SiteUrl"
      contains: "OnGlobalSitesChanged"
    - path: "SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs"
      provides: "Single-site global consumption — pre-fills SiteUrl"
      contains: "OnGlobalSitesChanged"
    - path: "SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs"
      provides: "Single-site global consumption — pre-fills SiteUrl"
      contains: "OnGlobalSitesChanged"
    - path: "SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs"
      provides: "Single-site global consumption — pre-fills SourceSiteUrl"
      contains: "OnGlobalSitesChanged"
  key_links:
    - from: "SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs"
      to: "SharepointToolbox/ViewModels/FeatureViewModelBase.cs"
      via: "Override of OnGlobalSitesChanged virtual method"
      pattern: "override.*OnGlobalSitesChanged"
    - from: "SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs"
      to: "SharepointToolbox/ViewModels/FeatureViewModelBase.cs"
      via: "Override of OnGlobalSitesChanged virtual method"
      pattern: "override.*OnGlobalSitesChanged"
---

<objective>
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.
</objective>

<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>

<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

<interfaces>
<!-- Base class contract from plan 06-01 -->
From SharepointToolbox/ViewModels/FeatureViewModelBase.cs:
```csharp
protected IReadOnlyList<SiteInfo> GlobalSites { get; private set; }

protected virtual void OnGlobalSitesChanged(IReadOnlyList<SiteInfo> 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
```

<!-- Single-site tab pattern (Storage, Search, Duplicates, FolderStructure) -->
From SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs:
```csharp
[ObservableProperty] private string _siteUrl = string.Empty;

// RunOperationAsync checks string.IsNullOrWhiteSpace(SiteUrl)
```

<!-- Transfer tab pattern (has SourceSiteUrl, not SiteUrl) -->
From SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs:
```csharp
[ObservableProperty] private string _sourceSiteUrl = string.Empty;
```

<!-- Tabs that do NOT consume global sites (no changes needed): -->
<!-- SettingsViewModel — no SiteUrl -->
<!-- BulkSitesViewModel — creates sites from CSV -->
<!-- TemplatesViewModel — creates new sites -->
<!-- BulkMembersViewModel — CSV-driven, no SiteUrl field -->
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Update PermissionsViewModel for multi-site global consumption</name>
  <files>SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs</files>
  <action>
    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.
  </action>
  <verify>
    <automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5</automated>
  </verify>
  <done>PermissionsViewModel overrides OnGlobalSitesChanged to pre-populate SelectedSites. Local site picker sets _hasLocalSiteOverride=true to prevent global from overwriting. Tenant switch resets the flag.</done>
</task>

<task type="auto">
  <name>Task 2: Update single-site tab VMs (Storage, Search, Duplicates, FolderStructure) for global consumption</name>
  <files>
    SharepointToolbox/ViewModels/Tabs/StorageViewModel.cs,
    SharepointToolbox/ViewModels/Tabs/SearchViewModel.cs,
    SharepointToolbox/ViewModels/Tabs/DuplicatesViewModel.cs,
    SharepointToolbox/ViewModels/Tabs/FolderStructureViewModel.cs
  </files>
  <action>
    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.
  </action>
  <verify>
    <automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5</automated>
  </verify>
  <done>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.</done>
</task>

<task type="auto">
  <name>Task 3: Update TransferViewModel and verify BulkMembersViewModel excluded</name>
  <files>
    SharepointToolbox/ViewModels/Tabs/TransferViewModel.cs,
    SharepointToolbox/ViewModels/Tabs/BulkMembersViewModel.cs
  </files>
  <action>
    **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.
  </action>
  <verify>
    <automated>cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5</automated>
  </verify>
  <done>TransferViewModel overrides OnGlobalSitesChanged to pre-fill SourceSiteUrl. BulkMembersViewModel is confirmed excluded (no SiteUrl, no override). Build succeeds.</done>
</task>

</tasks>

<verification>
- `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
</verification>

<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>

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