feat(02-07): create PermissionsView XAML + code-behind and register DI
- Created PermissionsView.xaml with left scan-config panel and right results DataGrid - Created PermissionsView.xaml.cs wiring ViewModel via IServiceProvider, factory for SitePickerDialog - Updated App.xaml.cs: registered IPermissionsService, ISiteListService, CsvExportService, HtmlExportService, PermissionsViewModel, PermissionsView, SitePickerDialog, and Func<TenantProfile, SitePickerDialog> factory; also registered ISessionManager -> SessionManager - Updated MainWindow.xaml: replaced FeatureTabBase stub with named PermissionsTabItem - Updated MainWindow.xaml.cs: wires PermissionsTabItem.Content from DI-resolved PermissionsView - Added CurrentProfile public accessor, SitesSelectedLabel computed property, and IsMaxDepth toggle property to PermissionsViewModel - Build: 0 errors, 0 warnings. Tests: 60 passed, 3 skipped (live/interactive)
This commit is contained in:
@@ -44,9 +44,27 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
||||
[ObservableProperty]
|
||||
private int _folderDepth = 1;
|
||||
|
||||
/// <summary>
|
||||
/// When true, sets FolderDepth to 999 (scan all levels).
|
||||
/// </summary>
|
||||
public bool IsMaxDepth
|
||||
{
|
||||
get => FolderDepth >= 999;
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
FolderDepth = 999;
|
||||
else if (FolderDepth >= 999)
|
||||
FolderDepth = 1;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<PermissionEntry> _results = new();
|
||||
|
||||
partial void OnFolderDepthChanged(int value) => OnPropertyChanged(nameof(IsMaxDepth));
|
||||
|
||||
// ── Commands ────────────────────────────────────────────────────────────
|
||||
|
||||
public IAsyncRelayCommand ExportCsvCommand { get; }
|
||||
@@ -69,6 +87,19 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
||||
|
||||
internal TenantProfile? _currentProfile;
|
||||
|
||||
/// <summary>
|
||||
/// Public accessor for the current tenant profile — used by View layer dialog factory.
|
||||
/// </summary>
|
||||
public TenantProfile? CurrentProfile => _currentProfile;
|
||||
|
||||
/// <summary>
|
||||
/// Label shown in the UI: "3 site(s) selected" or empty when none are selected.
|
||||
/// </summary>
|
||||
public string SitesSelectedLabel =>
|
||||
SelectedSites.Count > 0
|
||||
? string.Format(Localization.TranslationSource.Instance["perm.sites.selected"], SelectedSites.Count)
|
||||
: string.Empty;
|
||||
|
||||
// ── Constructors ────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>
|
||||
@@ -93,6 +124,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||
ExportHtmlCommand = new AsyncRelayCommand(ExportHtmlAsync, CanExport);
|
||||
OpenSitePickerCommand = new RelayCommand(ExecuteOpenSitePicker);
|
||||
SelectedSites.CollectionChanged += (_, _) => OnPropertyChanged(nameof(SitesSelectedLabel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,6 +147,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||
ExportHtmlCommand = new AsyncRelayCommand(ExportHtmlAsync, CanExport);
|
||||
OpenSitePickerCommand = new RelayCommand(ExecuteOpenSitePicker);
|
||||
SelectedSites.CollectionChanged += (_, _) => OnPropertyChanged(nameof(SitesSelectedLabel));
|
||||
}
|
||||
|
||||
// ── FeatureViewModelBase implementation ─────────────────────────────────
|
||||
@@ -184,6 +217,8 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
||||
Results = new ObservableCollection<PermissionEntry>();
|
||||
SiteUrl = string.Empty;
|
||||
SelectedSites.Clear();
|
||||
OnPropertyChanged(nameof(SitesSelectedLabel));
|
||||
OnPropertyChanged(nameof(CurrentProfile));
|
||||
ExportCsvCommand.NotifyCanExecuteChanged();
|
||||
ExportHtmlCommand.NotifyCanExecuteChanged();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user