LANCommander/LANCommander.Server/UI/Pages/Settings/Tools/OrphanedFiles.razor
2025-02-04 19:32:33 -06:00

131 lines
4 KiB
Text

@page "/Settings/Tools/OrphanedFiles"
@using LANCommander.Helpers;
@attribute [Authorize(Roles = RoleService.AdministratorRoleName)]
@inject ArchiveService ArchiveService
@inject StorageLocationService StorageLocationService
@inject MediaService MediaService
<PageHeader>
<PageHeaderTitle>Orphaned Files</PageHeaderTitle>
<PageHeaderExtra>
<Popconfirm OnConfirm="DeleteAll" Title="Delete all orphan files?" Disabled="@(!Orphans.Any())">
<Button Type="@ButtonType.Primary" Disabled="@(!Orphans.Any())">Delete All</Button>
</Popconfirm>
</PageHeaderExtra>
</PageHeader>
<PageContent>
<p>
These files exist on the server, but aren't linked in the database. Use this tool to identify and delete orphaned files.
</p>
</PageContent>
<Table TItem="OrphanedFile" DataSource="@Orphans" Loading="@Loading" PageSize="25" Responsive>
<PropertyColumn Property="f => f.Path" />
<PropertyColumn Property="f => f.Size" Sortable>
<ByteSize Value="context.Size" />
</PropertyColumn>
<PropertyColumn Property="f => f.CreatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable />
<ActionColumn Title="" Style="text-align: right">
<Space Direction="SpaceDirection.Horizontal">
<SpaceItem>
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this file?">
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
</Popconfirm>
</SpaceItem>
</Space>
</ActionColumn>
</Table>
@code {
ICollection<OrphanedFile> Orphans = new List<OrphanedFile>();
bool Loading = true;
readonly Settings Settings = SettingService.GetSettings();
protected override async Task OnInitializedAsync()
{
await LoadData();
}
async Task LoadData()
{
Loading = true;
Orphans = new List<OrphanedFile>();
var storageLocations = await StorageLocationService.GetAsync();
var archives = await ArchiveService.GetAsync();
var archiveFiles = await Task.WhenAll(archives.Select(a => ArchiveService.GetArchiveFileLocationAsync(a)));
foreach (var storageLocation in storageLocations.Where(l => l.Type == SDK.Enums.StorageLocationType.Archive))
{
var localArchiveFiles = Directory.GetFiles(storageLocation.Path);
foreach (var file in localArchiveFiles.Where(f => !archiveFiles.Contains(f)))
{
var fileInfo = new FileInfo(file);
Orphans.Add(new OrphanedFile
{
Path = file,
Size = fileInfo.Length,
CreatedOn = fileInfo.CreationTime
});
}
}
var media = await MediaService.GetAsync();
var mediaFiles = media.Select(m => MediaService.GetMediaPath(m));
foreach (var storageLocation in storageLocations.Where(l => l.Type == SDK.Enums.StorageLocationType.Media))
{
var localMediaFiles = Directory.GetFiles(storageLocation.Path).Where(f => !f.EndsWith(".Thumb"));
foreach (var file in localMediaFiles.Where(f => !mediaFiles.Contains(f)))
{
var fileInfo = new FileInfo(file);
Orphans.Add(new OrphanedFile
{
Path = file,
Size = fileInfo.Length,
CreatedOn = fileInfo.CreationTime
});
}
}
Orphans = Orphans.OrderByDescending(f => f.Size).ToList();
Loading = false;
}
async Task Delete(OrphanedFile file)
{
Loading = true;
FileHelpers.DeleteIfExists(file.Path);
await LoadData();
Loading = false;
await InvokeAsync(StateHasChanged);
}
async Task DeleteAll()
{
Loading = true;
foreach (var file in Orphans)
{
FileHelpers.DeleteIfExists(file.Path);
}
await LoadData();
Loading = false;
await InvokeAsync(StateHasChanged);
}
}