--- phase: 14-user-directory-view plan: 01 type: execute wave: 1 depends_on: [] files_modified: - SharepointToolbox/Localization/Strings.resx - SharepointToolbox/Localization/Strings.fr.resx - SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs - SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs - SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs autonomous: true requirements: - UDIR-05 - UDIR-01 must_haves: truths: - "SelectDirectoryUserCommand takes a GraphDirectoryUser, converts it to GraphUserResult, adds it to SelectedUsers via existing logic" - "After SelectDirectoryUserCommand, the user appears in SelectedUsers and can be audited with RunCommand" - "SelectDirectoryUserCommand does not add duplicates (same UPN check as existing AddUserCommand)" - "Localization keys for directory UI exist in both EN and FR resource files" - "Code-behind has a DirectoryDataGrid_MouseDoubleClick handler that invokes SelectDirectoryUserCommand" artifacts: - path: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs" provides: "SelectDirectoryUserCommand bridging directory selection to audit pipeline" contains: "SelectDirectoryUserCommand" - path: "SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs" provides: "Event handler for directory DataGrid double-click" contains: "DirectoryDataGrid_MouseDoubleClick" - path: "SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs" provides: "Tests for SelectDirectoryUserCommand" contains: "SelectDirectoryUser" key_links: - from: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs" to: "SharepointToolbox/Core/Models/GraphDirectoryUser.cs" via: "command parameter type" pattern: "GraphDirectoryUser" - from: "SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs" to: "SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs" via: "command invocation" pattern: "SelectDirectoryUserCommand" --- Add localization keys for directory UI, the SelectDirectoryUserCommand that bridges directory selection to the audit pipeline, and a code-behind event handler for DataGrid double-click. Purpose: Provides the infrastructure (localization, command, event handler) that Plan 14-02 needs to build the XAML view. SC2 requires selecting a directory user to trigger an audit — this command makes that possible. Output: Localization keys (EN+FR), SelectDirectoryUserCommand with tests, code-behind event handler. @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/14-user-directory-view/14-RESEARCH.md From SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs: ```csharp public RelayCommand AddUserCommand { get; } private void ExecuteAddUser(GraphUserResult? user) { if (user == null) return; if (!SelectedUsers.Any(u => u.UserPrincipalName == user.UserPrincipalName)) { SelectedUsers.Add(user); } SearchQuery = string.Empty; SearchResults.Clear(); } ``` From SharepointToolbox/Core/Models/GraphDirectoryUser.cs: ```csharp public record GraphDirectoryUser( string DisplayName, string UserPrincipalName, string? Mail, string? Department, string? JobTitle, string? UserType); ``` From SharepointToolbox/Services/IGraphUserSearchService.cs: ```csharp public record GraphUserResult(string DisplayName, string UserPrincipalName, string? Mail); ``` From SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs: ```csharp private void SearchResultsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (sender is ListBox listBox && listBox.SelectedItem is GraphUserResult user) { var vm = (UserAccessAuditViewModel)DataContext; if (vm.AddUserCommand.CanExecute(user)) vm.AddUserCommand.Execute(user); listBox.SelectedItem = null; } } ``` From Strings.resx: ```xml Select Users Run Audit ``` Task 1: Add localization keys for directory UI (EN + FR) SharepointToolbox/Localization/Strings.resx, SharepointToolbox/Localization/Strings.fr.resx - Both resx files contain matching keys for directory browse UI 1. Add to `Strings.resx` (EN): - `audit.mode.search` = "Search" - `audit.mode.browse` = "Browse Directory" - `directory.grp.browse` = "User Directory" - `directory.btn.load` = "Load Directory" - `directory.btn.cancel` = "Cancel" - `directory.filter.placeholder` = "Filter users..." - `directory.chk.guests` = "Include guests" - `directory.status.count` = "users" - `directory.hint.doubleclick` = "Double-click a user to add to audit" - `directory.col.name` = "Name" - `directory.col.upn` = "Email" - `directory.col.department` = "Department" - `directory.col.jobtitle` = "Job Title" - `directory.col.type` = "Type" 2. Add to `Strings.fr.resx` (FR): - `audit.mode.search` = "Recherche" - `audit.mode.browse` = "Parcourir l'annuaire" - `directory.grp.browse` = "Annuaire utilisateurs" - `directory.btn.load` = "Charger l'annuaire" - `directory.btn.cancel` = "Annuler" - `directory.filter.placeholder` = "Filtrer les utilisateurs..." - `directory.chk.guests` = "Inclure les invités" - `directory.status.count` = "utilisateurs" - `directory.hint.doubleclick` = "Double-cliquez sur un utilisateur pour l'ajouter à l'audit" - `directory.col.name` = "Nom" - `directory.col.upn` = "Courriel" - `directory.col.department` = "Département" - `directory.col.jobtitle` = "Poste" - `directory.col.type` = "Type" dotnet build --no-restore -warnaserror 14 localization keys present in both EN and FR resource files. Task 2: Add SelectDirectoryUserCommand to ViewModel SharepointToolbox/ViewModels/Tabs/UserAccessAuditViewModel.cs, SharepointToolbox.Tests/ViewModels/UserAccessAuditViewModelDirectoryTests.cs - SelectDirectoryUserCommand is a RelayCommand - It converts GraphDirectoryUser to GraphUserResult and adds to SelectedUsers - Duplicate UPN check (same as AddUserCommand) - Does NOT clear SearchQuery/SearchResults (not in search mode context) - After execution, IsBrowseMode stays true — user can continue selecting from directory 1. Add command declaration in ViewModel: ```csharp public RelayCommand SelectDirectoryUserCommand { get; } ``` 2. Initialize in BOTH constructors: ```csharp SelectDirectoryUserCommand = new RelayCommand(ExecuteSelectDirectoryUser); ``` 3. Implement the command method: ```csharp private void ExecuteSelectDirectoryUser(GraphDirectoryUser? dirUser) { if (dirUser == null) return; var userResult = new GraphUserResult(dirUser.DisplayName, dirUser.UserPrincipalName, dirUser.Mail); if (!SelectedUsers.Any(u => u.UserPrincipalName == userResult.UserPrincipalName)) { SelectedUsers.Add(userResult); } } ``` 4. Add tests to `UserAccessAuditViewModelDirectoryTests.cs`: - Test: SelectDirectoryUserCommand adds user to SelectedUsers - Test: SelectDirectoryUserCommand skips duplicates - Test: SelectDirectoryUserCommand with null does nothing - Test: After SelectDirectoryUser, user can be audited with RunCommand (integration: add user + check SelectedUsers.Count > 0) dotnet build --no-restore -warnaserror && dotnet test SharepointToolbox.Tests --filter "FullyQualifiedName~UserAccessAuditViewModelDirectory" --no-build -q SelectDirectoryUserCommand bridges directory selection to audit pipeline. Tests pass. Task 3: Add code-behind event handler for directory DataGrid SharepointToolbox/Views/Tabs/UserAccessAuditView.xaml.cs - DirectoryDataGrid_MouseDoubleClick handler extracts the clicked GraphDirectoryUser - Invokes SelectDirectoryUserCommand with the selected user - Uses the same pattern as SearchResultsListBox_SelectionChanged 1. Add to `UserAccessAuditView.xaml.cs`: ```csharp private void DirectoryDataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (sender is DataGrid grid && grid.SelectedItem is GraphDirectoryUser user) { var vm = (UserAccessAuditViewModel)DataContext; if (vm.SelectDirectoryUserCommand.CanExecute(user)) vm.SelectDirectoryUserCommand.Execute(user); } } ``` 2. Add the required using statement if not present: ```csharp using System.Windows.Controls; // Already present using SharepointToolbox.Core.Models; // For GraphDirectoryUser ``` dotnet build --no-restore -warnaserror Code-behind event handler exists, ready to be wired in XAML (Plan 14-02). ```bash dotnet build --no-restore -warnaserror dotnet test SharepointToolbox.Tests --filter "FullyQualifiedName~UserAccessAuditViewModelDirectory" --no-build -q ``` Both must pass with zero failures. - 14 localization keys in both EN and FR resx files - SelectDirectoryUserCommand converts GraphDirectoryUser → GraphUserResult → SelectedUsers - Duplicate UPN check prevents adding same user twice - Code-behind event handler for DataGrid double-click - All tests pass, build clean After completion, create `.planning/phases/14-user-directory-view/14-01-SUMMARY.md`