@page "/versions" @attribute [Authorize] @inject IUserSessionService Session @inject IUserContextAccessor UserContext @inject ISessionManager SessionMgr @inject IElevationCoordinator Elevation @inject IVersionCleanupService VersionSvc @inject VersionCleanupHtmlExportService HtmlExport @inject WebExportService WebExport @rendermode InteractiveServer

Version Cleanup

@if (!Session.HasProfile) { return; } @if (UserContext.Role < UserRole.TechN1) { return; }
@if (_libraries.Count > 0) {
@foreach (var lib in _libraries) { }
}
@if (_running) { }
@if (!string.IsNullOrEmpty(_error)) {
@_error
} @if (_results.Count > 0) {
Results @_results.Count files
Versions deleted: @_results.Sum(r => r.VersionsDeleted) | Freed: @((_results.Sum(r => r.BytesFreed) / 1048576.0).ToString("F2")) MB | Errors: @_results.Count(r => r.Error != null)
@foreach (var r in _results.Take(500)) { }
LibraryFileBeforeDeletedFreed (KB)Error
@r.Library @r.FileName @r.VersionsBefore @r.VersionsDeleted @((r.BytesFreed / 1024.0).ToString("F1")) @r.Error
} @code { private string _siteUrl = string.Empty; private int _keepLast = 5; private bool _keepFirst; private List _libraries = new(), _selectedLibs = new(); private bool _running, _loading; private string _status = string.Empty, _error = string.Empty; private int _current, _total; private List _results = new(); private CancellationTokenSource? _cts; private async Task LoadLibraries() { _loading = true; _error = string.Empty; try { var siteUrl = string.IsNullOrWhiteSpace(_siteUrl) ? Session.CurrentProfile!.TenantUrl : _siteUrl.Trim(); _libraries = (await Elevation.RunAsync(async c => { var ctx = await SessionMgr.GetOrCreateContextAsync(siteUrl, Session.CurrentProfile!, c); return await VersionSvc.ListLibraryTitlesAsync(ctx, c); }, CancellationToken.None)).ToList(); } catch (Exception ex) { _error = ex.Message; } finally { _loading = false; } } private void ToggleLib(string lib, bool selected) { if (selected) _selectedLibs.Add(lib); else _selectedLibs.Remove(lib); } private async Task RunCleanup() { _error = string.Empty; _results.Clear(); _running = true; _cts = new CancellationTokenSource(); var siteUrl = string.IsNullOrWhiteSpace(_siteUrl) ? Session.CurrentProfile!.TenantUrl : _siteUrl.Trim(); var progress = new Progress(p => { _status = p.Message; _current = p.Current; _total = p.Total; InvokeAsync(StateHasChanged); }); try { var opts = new VersionCleanupOptions(_selectedLibs, _keepLast, _keepFirst); _results = (await Elevation.RunAsync(async c => { var ctx = await SessionMgr.GetOrCreateContextAsync(siteUrl, Session.CurrentProfile!, c); return await VersionSvc.DeleteOldVersionsAsync(ctx, opts, progress, c); }, _cts.Token)).ToList(); _status = $"Complete: {_results.Sum(r => r.VersionsDeleted)} versions deleted."; } catch (OperationCanceledException) { _status = "Cancelled."; } catch (Exception ex) { _error = ex.Message; } finally { _running = false; await InvokeAsync(StateHasChanged); } } private void Cancel() => _cts?.Cancel(); private async Task ExportHtml() { await WebExport.DownloadHtmlAsync(HtmlExport.BuildHtml(_results, Session.CurrentBranding), $"versions_{DateTime.Now:yyyyMMdd_HHmmss}.html"); } }