--- phase: 08-simplified-permissions plan: 02 type: execute wave: 2 depends_on: ["08-01"] files_modified: - SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs autonomous: true requirements: - SIMP-01 - SIMP-02 - SIMP-03 must_haves: truths: - "IsSimplifiedMode toggle switches between raw and simplified permission labels in the DataGrid" - "IsDetailView toggle controls whether individual rows are shown or collapsed into summary rows" - "Toggling modes does NOT re-run the scan — it re-renders from existing Results data" - "Summary counts per risk level are available as observable properties when simplified mode is on" - "SimplifiedResults collection is computed from Results whenever Results changes or mode toggles" - "ActiveItemsSource provides the correct collection for DataGrid binding depending on current mode" artifacts: - path: "SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs" provides: "Extended PermissionsViewModel with simplified mode, detail toggle, and summary" contains: "IsSimplifiedMode" key_links: - from: "SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs" to: "SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs" via: "SimplifiedPermissionEntry.WrapAll uses PermissionLevelMapping internally" pattern: "SimplifiedPermissionEntry\\.WrapAll" - from: "SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs" to: "SharepointToolbox/Core/Models/PermissionSummary.cs" via: "PermissionSummaryBuilder.Build computes summary from simplified entries" pattern: "PermissionSummaryBuilder\\.Build" --- Extend PermissionsViewModel with IsSimplifiedMode toggle, IsDetailView toggle, SimplifiedResults collection, summary statistics, and an ActiveItemsSource that the DataGrid binds to. All toggles re-render from cached data — no re-scan required. Purpose: This is the ViewModel logic for all three SIMP requirements. The View (08-03) binds to these new properties. Output: Updated PermissionsViewModel.cs @C:/Users/dev/.claude/get-shit-done/workflows/execute-plan.md @C:/Users/dev/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/08-simplified-permissions/08-01-SUMMARY.md From SharepointToolbox/Core/Models/RiskLevel.cs: ```csharp public enum RiskLevel { High, Medium, Low, ReadOnly } ``` From SharepointToolbox/Core/Helpers/PermissionLevelMapping.cs: ```csharp public static class PermissionLevelMapping { public record MappingResult(string Label, RiskLevel RiskLevel); public static MappingResult GetMapping(string roleName); public static IReadOnlyList GetMappings(string permissionLevels); public static RiskLevel GetHighestRisk(string permissionLevels); public static string GetSimplifiedLabels(string permissionLevels); } ``` From SharepointToolbox/Core/Models/SimplifiedPermissionEntry.cs: ```csharp public class SimplifiedPermissionEntry { public PermissionEntry Inner { get; } public string SimplifiedLabels { get; } public RiskLevel RiskLevel { get; } public IReadOnlyList Mappings { get; } // Passthrough: ObjectType, Title, Url, HasUniquePermissions, Users, UserLogins, // PermissionLevels, GrantedThrough, PrincipalType public static IReadOnlyList WrapAll(IEnumerable entries); } ``` From SharepointToolbox/Core/Models/PermissionSummary.cs: ```csharp public record PermissionSummary(string Label, RiskLevel RiskLevel, int Count, int DistinctUsers); public static class PermissionSummaryBuilder { public static IReadOnlyList Build(IEnumerable entries); } ``` From SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs: ```csharp public partial class PermissionsViewModel : FeatureViewModelBase { // Existing fields and services — unchanged [ObservableProperty] private ObservableCollection _results = new(); // Existing commands — unchanged public IAsyncRelayCommand ExportCsvCommand { get; } public IAsyncRelayCommand ExportHtmlCommand { get; } public RelayCommand OpenSitePickerCommand { get; } // Full constructor and test constructor (internal) } ``` Task 1: Add simplified mode properties and summary computation to PermissionsViewModel SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs Modify `SharepointToolbox/ViewModels/Tabs/PermissionsViewModel.cs` to add simplified mode support. Add the following new using statements at the top: ```csharp using SharepointToolbox.Core.Helpers; ``` Add these new observable properties to the class (in the "Observable properties" section): ```csharp /// /// When true, displays simplified plain-language labels instead of raw SharePoint role names. /// Toggling does not re-run the scan. /// [ObservableProperty] private bool _isSimplifiedMode; /// /// When true, shows individual item-level rows (detailed view). /// When false, shows only summary rows grouped by risk level (simple view). /// Only meaningful when IsSimplifiedMode is true. /// [ObservableProperty] private bool _isDetailView = true; ``` Add these computed collection properties (NOT ObservableProperty — manually raised): ```csharp /// /// Simplified wrappers computed from Results. Rebuilt when Results changes. /// private IReadOnlyList _simplifiedResults = Array.Empty(); public IReadOnlyList SimplifiedResults { get => _simplifiedResults; private set => SetProperty(ref _simplifiedResults, value); } /// /// Summary counts grouped by risk level. Rebuilt when SimplifiedResults changes. /// private IReadOnlyList _summaries = Array.Empty(); public IReadOnlyList Summaries { get => _summaries; private set => SetProperty(ref _summaries, value); } /// /// The collection the DataGrid actually binds to. Returns: /// - Results (raw) when simplified mode is OFF /// - SimplifiedResults when simplified mode is ON and detail view is ON /// - (View handles summary display separately via Summaries property) /// public object ActiveItemsSource => IsSimplifiedMode ? (object)SimplifiedResults : Results; ``` Add partial methods triggered by property changes: ```csharp partial void OnIsSimplifiedModeChanged(bool value) { if (value && Results.Count > 0) RebuildSimplifiedData(); OnPropertyChanged(nameof(ActiveItemsSource)); } partial void OnIsDetailViewChanged(bool value) { OnPropertyChanged(nameof(ActiveItemsSource)); } ``` Add a private method to rebuild simplified data from existing Results: ```csharp /// /// Recomputes SimplifiedResults and Summaries from the current Results collection. /// Called when Results changes or when simplified mode is toggled on. /// private void RebuildSimplifiedData() { SimplifiedResults = SimplifiedPermissionEntry.WrapAll(Results); Summaries = PermissionSummaryBuilder.Build(SimplifiedResults); } ``` Modify the existing `RunOperationAsync` method: after the line that sets `Results = new ObservableCollection(allEntries);` (both in the dispatcher branch and the else branch), add: ```csharp if (IsSimplifiedMode) RebuildSimplifiedData(); OnPropertyChanged(nameof(ActiveItemsSource)); ``` So the end of RunOperationAsync becomes (both branches): ```csharp Results = new ObservableCollection(allEntries); if (IsSimplifiedMode) RebuildSimplifiedData(); OnPropertyChanged(nameof(ActiveItemsSource)); ``` Modify `OnTenantSwitched` to also reset simplified state: After `Results = new ObservableCollection();` add: ```csharp SimplifiedResults = Array.Empty(); Summaries = Array.Empty(); OnPropertyChanged(nameof(ActiveItemsSource)); ``` Do NOT change: - Constructor signatures (both full and test constructors remain unchanged) - Existing properties (SiteUrl, IncludeInherited, ScanFolders, etc.) - ExportCsvCommand and ExportHtmlCommand implementations (export updates are in plan 08-04) - OpenSitePickerCommand - _hasLocalSiteOverride / OnGlobalSitesChanged logic cd "C:\Users\dev\Documents\projets\Sharepoint" && dotnet build SharepointToolbox/SharepointToolbox.csproj --no-incremental 2>&1 | tail -5 PermissionsViewModel has IsSimplifiedMode, IsDetailView, SimplifiedResults, Summaries, and ActiveItemsSource properties. Toggling IsSimplifiedMode rebuilds simplified data from cached Results without re-scanning. Toggling IsDetailView triggers ActiveItemsSource change notification. Existing tests still compile (no constructor changes). - `dotnet build SharepointToolbox/SharepointToolbox.csproj` succeeds with 0 errors - `dotnet test SharepointToolbox.Tests/ --filter PermissionsViewModelTests` passes (no constructor changes) - PermissionsViewModel has IsSimplifiedMode, IsDetailView, SimplifiedResults, Summaries, ActiveItemsSource - Toggling IsSimplifiedMode calls RebuildSimplifiedData + raises ActiveItemsSource changed - RunOperationAsync calls RebuildSimplifiedData when IsSimplifiedMode is true - OnTenantSwitched resets SimplifiedResults and Summaries The ViewModel is the orchestration layer for SIMP-01/02/03. All mode toggles re-render from cached data. The View (08-03) can bind to IsSimplifiedMode, IsDetailView, ActiveItemsSource, and Summaries. Export services (08-04) can access SimplifiedResults and IsSimplifiedMode. After completion, create `.planning/phases/08-simplified-permissions/08-02-SUMMARY.md`