feat(11-03): inject IBrandingService into all 5 export ViewModels and assemble branding in ExportHtmlAsync
- Add IBrandingService field and DI constructor parameter to all 5 ViewModels - Add optional IBrandingService? parameter to test constructors (PermissionsViewModel, StorageViewModel, UserAccessAuditViewModel) - Assemble ReportBranding from GetMspLogoAsync + _currentProfile.ClientLogo before each WriteAsync call - Pass branding as last parameter to WriteAsync in all ExportHtmlAsync methods - Guard clause: branding assembly skipped (branding = null) when _brandingService is null (test constructors) - Build: 0 warnings, 0 errors; tests: 254 passed / 0 failed / 26 skipped
This commit is contained in:
@@ -31,6 +31,7 @@ public partial class DuplicatesViewModel : FeatureViewModelBase
|
|||||||
private readonly IDuplicatesService _duplicatesService;
|
private readonly IDuplicatesService _duplicatesService;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly DuplicatesHtmlExportService _htmlExportService;
|
private readonly DuplicatesHtmlExportService _htmlExportService;
|
||||||
|
private readonly IBrandingService _brandingService;
|
||||||
private readonly ILogger<FeatureViewModelBase> _logger;
|
private readonly ILogger<FeatureViewModelBase> _logger;
|
||||||
private TenantProfile? _currentProfile;
|
private TenantProfile? _currentProfile;
|
||||||
private IReadOnlyList<DuplicateGroup> _lastGroups = Array.Empty<DuplicateGroup>();
|
private IReadOnlyList<DuplicateGroup> _lastGroups = Array.Empty<DuplicateGroup>();
|
||||||
@@ -64,12 +65,14 @@ public partial class DuplicatesViewModel : FeatureViewModelBase
|
|||||||
IDuplicatesService duplicatesService,
|
IDuplicatesService duplicatesService,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
DuplicatesHtmlExportService htmlExportService,
|
DuplicatesHtmlExportService htmlExportService,
|
||||||
|
IBrandingService brandingService,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_duplicatesService = duplicatesService;
|
_duplicatesService = duplicatesService;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_htmlExportService = htmlExportService;
|
_htmlExportService = htmlExportService;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportHtmlCommand = new AsyncRelayCommand(ExportHtmlAsync, CanExport);
|
ExportHtmlCommand = new AsyncRelayCommand(ExportHtmlAsync, CanExport);
|
||||||
@@ -168,7 +171,15 @@ public partial class DuplicatesViewModel : FeatureViewModelBase
|
|||||||
if (dialog.ShowDialog() != true) return;
|
if (dialog.ShowDialog() != true) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _htmlExportService.WriteAsync(_lastGroups, dialog.FileName, CancellationToken.None);
|
ReportBranding? branding = null;
|
||||||
|
if (_brandingService is not null)
|
||||||
|
{
|
||||||
|
var mspLogo = await _brandingService.GetMspLogoAsync();
|
||||||
|
var clientLogo = _currentProfile?.ClientLogo;
|
||||||
|
branding = new ReportBranding(mspLogo, clientLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _htmlExportService.WriteAsync(_lastGroups, dialog.FileName, CancellationToken.None, branding);
|
||||||
Process.Start(new ProcessStartInfo(dialog.FileName) { UseShellExecute = true });
|
Process.Start(new ProcessStartInfo(dialog.FileName) { UseShellExecute = true });
|
||||||
}
|
}
|
||||||
catch (Exception ex) { StatusMessage = $"Export failed: {ex.Message}"; _logger.LogError(ex, "HTML export failed."); }
|
catch (Exception ex) { StatusMessage = $"Export failed: {ex.Message}"; _logger.LogError(ex, "HTML export failed."); }
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly CsvExportService? _csvExportService;
|
private readonly CsvExportService? _csvExportService;
|
||||||
private readonly HtmlExportService? _htmlExportService;
|
private readonly HtmlExportService? _htmlExportService;
|
||||||
|
private readonly IBrandingService? _brandingService;
|
||||||
private readonly ILogger<FeatureViewModelBase> _logger;
|
private readonly ILogger<FeatureViewModelBase> _logger;
|
||||||
|
|
||||||
// ── Observable properties ───────────────────────────────────────────────
|
// ── Observable properties ───────────────────────────────────────────────
|
||||||
@@ -128,6 +129,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
CsvExportService csvExportService,
|
CsvExportService csvExportService,
|
||||||
HtmlExportService htmlExportService,
|
HtmlExportService htmlExportService,
|
||||||
|
IBrandingService brandingService,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
@@ -136,6 +138,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = csvExportService;
|
_csvExportService = csvExportService;
|
||||||
_htmlExportService = htmlExportService;
|
_htmlExportService = htmlExportService;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -149,7 +152,8 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
IPermissionsService permissionsService,
|
IPermissionsService permissionsService,
|
||||||
ISiteListService siteListService,
|
ISiteListService siteListService,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger,
|
||||||
|
IBrandingService? brandingService = null)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_permissionsService = permissionsService;
|
_permissionsService = permissionsService;
|
||||||
@@ -157,6 +161,7 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = null;
|
_csvExportService = null;
|
||||||
_htmlExportService = null;
|
_htmlExportService = null;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -313,10 +318,18 @@ public partial class PermissionsViewModel : FeatureViewModelBase
|
|||||||
if (dialog.ShowDialog() != true) return;
|
if (dialog.ShowDialog() != true) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ReportBranding? branding = null;
|
||||||
|
if (_brandingService is not null)
|
||||||
|
{
|
||||||
|
var mspLogo = await _brandingService.GetMspLogoAsync();
|
||||||
|
var clientLogo = _currentProfile?.ClientLogo;
|
||||||
|
branding = new ReportBranding(mspLogo, clientLogo);
|
||||||
|
}
|
||||||
|
|
||||||
if (IsSimplifiedMode && SimplifiedResults.Count > 0)
|
if (IsSimplifiedMode && SimplifiedResults.Count > 0)
|
||||||
await _htmlExportService.WriteAsync(SimplifiedResults.ToList(), dialog.FileName, CancellationToken.None);
|
await _htmlExportService.WriteAsync(SimplifiedResults.ToList(), dialog.FileName, CancellationToken.None, branding);
|
||||||
else
|
else
|
||||||
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None);
|
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None, branding);
|
||||||
OpenFile(dialog.FileName);
|
OpenFile(dialog.FileName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public partial class SearchViewModel : FeatureViewModelBase
|
|||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly SearchCsvExportService _csvExportService;
|
private readonly SearchCsvExportService _csvExportService;
|
||||||
private readonly SearchHtmlExportService _htmlExportService;
|
private readonly SearchHtmlExportService _htmlExportService;
|
||||||
|
private readonly IBrandingService _brandingService;
|
||||||
private readonly ILogger<FeatureViewModelBase> _logger;
|
private readonly ILogger<FeatureViewModelBase> _logger;
|
||||||
private TenantProfile? _currentProfile;
|
private TenantProfile? _currentProfile;
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ public partial class SearchViewModel : FeatureViewModelBase
|
|||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
SearchCsvExportService csvExportService,
|
SearchCsvExportService csvExportService,
|
||||||
SearchHtmlExportService htmlExportService,
|
SearchHtmlExportService htmlExportService,
|
||||||
|
IBrandingService brandingService,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
@@ -66,6 +68,7 @@ public partial class SearchViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = csvExportService;
|
_csvExportService = csvExportService;
|
||||||
_htmlExportService = htmlExportService;
|
_htmlExportService = htmlExportService;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -168,7 +171,15 @@ public partial class SearchViewModel : FeatureViewModelBase
|
|||||||
if (dialog.ShowDialog() != true) return;
|
if (dialog.ShowDialog() != true) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None);
|
ReportBranding? branding = null;
|
||||||
|
if (_brandingService is not null)
|
||||||
|
{
|
||||||
|
var mspLogo = await _brandingService.GetMspLogoAsync();
|
||||||
|
var clientLogo = _currentProfile?.ClientLogo;
|
||||||
|
branding = new ReportBranding(mspLogo, clientLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None, branding);
|
||||||
OpenFile(dialog.FileName);
|
OpenFile(dialog.FileName);
|
||||||
}
|
}
|
||||||
catch (Exception ex) { StatusMessage = $"Export failed: {ex.Message}"; _logger.LogError(ex, "HTML export failed."); }
|
catch (Exception ex) { StatusMessage = $"Export failed: {ex.Message}"; _logger.LogError(ex, "HTML export failed."); }
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public partial class StorageViewModel : FeatureViewModelBase
|
|||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly StorageCsvExportService _csvExportService;
|
private readonly StorageCsvExportService _csvExportService;
|
||||||
private readonly StorageHtmlExportService _htmlExportService;
|
private readonly StorageHtmlExportService _htmlExportService;
|
||||||
|
private readonly IBrandingService? _brandingService;
|
||||||
private readonly ILogger<FeatureViewModelBase> _logger;
|
private readonly ILogger<FeatureViewModelBase> _logger;
|
||||||
private TenantProfile? _currentProfile;
|
private TenantProfile? _currentProfile;
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ public partial class StorageViewModel : FeatureViewModelBase
|
|||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
StorageCsvExportService csvExportService,
|
StorageCsvExportService csvExportService,
|
||||||
StorageHtmlExportService htmlExportService,
|
StorageHtmlExportService htmlExportService,
|
||||||
|
IBrandingService brandingService,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
@@ -141,6 +143,7 @@ public partial class StorageViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = csvExportService;
|
_csvExportService = csvExportService;
|
||||||
_htmlExportService = htmlExportService;
|
_htmlExportService = htmlExportService;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -151,13 +154,15 @@ public partial class StorageViewModel : FeatureViewModelBase
|
|||||||
internal StorageViewModel(
|
internal StorageViewModel(
|
||||||
IStorageService storageService,
|
IStorageService storageService,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger,
|
||||||
|
IBrandingService? brandingService = null)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_storageService = storageService;
|
_storageService = storageService;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = null!;
|
_csvExportService = null!;
|
||||||
_htmlExportService = null!;
|
_htmlExportService = null!;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -296,7 +301,15 @@ public partial class StorageViewModel : FeatureViewModelBase
|
|||||||
if (dialog.ShowDialog() != true) return;
|
if (dialog.ShowDialog() != true) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _htmlExportService.WriteAsync(Results, FileTypeMetrics, dialog.FileName, CancellationToken.None);
|
ReportBranding? branding = null;
|
||||||
|
if (_brandingService is not null)
|
||||||
|
{
|
||||||
|
var mspLogo = await _brandingService.GetMspLogoAsync();
|
||||||
|
var clientLogo = _currentProfile?.ClientLogo;
|
||||||
|
branding = new ReportBranding(mspLogo, clientLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _htmlExportService.WriteAsync(Results, FileTypeMetrics, dialog.FileName, CancellationToken.None, branding);
|
||||||
OpenFile(dialog.FileName);
|
OpenFile(dialog.FileName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly UserAccessCsvExportService? _csvExportService;
|
private readonly UserAccessCsvExportService? _csvExportService;
|
||||||
private readonly UserAccessHtmlExportService? _htmlExportService;
|
private readonly UserAccessHtmlExportService? _htmlExportService;
|
||||||
|
private readonly IBrandingService? _brandingService;
|
||||||
private readonly ILogger<FeatureViewModelBase> _logger;
|
private readonly ILogger<FeatureViewModelBase> _logger;
|
||||||
|
|
||||||
// ── People picker debounce ──────────────────────────────────────────────
|
// ── People picker debounce ──────────────────────────────────────────────
|
||||||
@@ -118,6 +119,7 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
UserAccessCsvExportService csvExportService,
|
UserAccessCsvExportService csvExportService,
|
||||||
UserAccessHtmlExportService htmlExportService,
|
UserAccessHtmlExportService htmlExportService,
|
||||||
|
IBrandingService brandingService,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
@@ -126,6 +128,7 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = csvExportService;
|
_csvExportService = csvExportService;
|
||||||
_htmlExportService = htmlExportService;
|
_htmlExportService = htmlExportService;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -145,7 +148,8 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
IUserAccessAuditService auditService,
|
IUserAccessAuditService auditService,
|
||||||
IGraphUserSearchService graphUserSearchService,
|
IGraphUserSearchService graphUserSearchService,
|
||||||
ISessionManager sessionManager,
|
ISessionManager sessionManager,
|
||||||
ILogger<FeatureViewModelBase> logger)
|
ILogger<FeatureViewModelBase> logger,
|
||||||
|
IBrandingService? brandingService = null)
|
||||||
: base(logger)
|
: base(logger)
|
||||||
{
|
{
|
||||||
_auditService = auditService;
|
_auditService = auditService;
|
||||||
@@ -153,6 +157,7 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
_csvExportService = null;
|
_csvExportService = null;
|
||||||
_htmlExportService = null;
|
_htmlExportService = null;
|
||||||
|
_brandingService = brandingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
||||||
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
ExportCsvCommand = new AsyncRelayCommand(ExportCsvAsync, CanExport);
|
||||||
@@ -329,7 +334,15 @@ public partial class UserAccessAuditViewModel : FeatureViewModelBase
|
|||||||
if (dialog.ShowDialog() != true) return;
|
if (dialog.ShowDialog() != true) return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None);
|
ReportBranding? branding = null;
|
||||||
|
if (_brandingService is not null)
|
||||||
|
{
|
||||||
|
var mspLogo = await _brandingService.GetMspLogoAsync();
|
||||||
|
var clientLogo = _currentProfile?.ClientLogo;
|
||||||
|
branding = new ReportBranding(mspLogo, clientLogo);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _htmlExportService.WriteAsync(Results, dialog.FileName, CancellationToken.None, branding);
|
||||||
OpenFile(dialog.FileName);
|
OpenFile(dialog.FileName);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Reference in New Issue
Block a user