mirror of
https://github.com/aaru-dps/Aaru.Server.git
synced 2025-12-16 19:24:27 +00:00
Add device details view with report merging and linking functionality
This commit is contained in:
7
.idea/.idea.Aaru.Server.Old/.idea/vcs.xml
generated
Normal file
7
.idea/.idea.Aaru.Server.Old/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/Aaru.Server/Aaru.Documentation" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -4,7 +4,7 @@ namespace Aaru.Server.Database.Models;
|
||||
|
||||
public class DeviceDetails
|
||||
{
|
||||
public Device Report { get; set; }
|
||||
public Device? Report { get; set; }
|
||||
public List<int> SameAll { get; set; }
|
||||
public List<int> SameButManufacturer { get; set; }
|
||||
public List<int> ReportAll { get; set; }
|
||||
|
||||
483
Aaru.Server/Components/Admin/Pages/Devices/Details.razor
Normal file
483
Aaru.Server/Components/Admin/Pages/Devices/Details.razor
Normal file
@@ -0,0 +1,483 @@
|
||||
@page "/admin/devices/{id:int}"
|
||||
@attribute [Authorize]
|
||||
@layout AdminLayout
|
||||
|
||||
@inject Microsoft.EntityFrameworkCore.IDbContextFactory<DbContext> DbContextFactory
|
||||
|
||||
<PageTitle>Device reports</PageTitle>
|
||||
|
||||
@if(!_initialized)
|
||||
{
|
||||
<div class="stats-section">
|
||||
<h1 style="color: red; align-content: center; padding: 2rem">Loading...</h1>
|
||||
</div>
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@if(_notFound)
|
||||
{
|
||||
<div class="stats-section">
|
||||
<h1 style="color: red; align-content: center; padding: 2rem">Device report not found</h1>
|
||||
</div>
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
<section class="stats-section">
|
||||
<div>
|
||||
<h4>Device report</h4>
|
||||
<hr />
|
||||
<dl class="row">
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.AddedWhen))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.AddedWhen
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.ModifiedWhen))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.ModifiedWhen
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.Manufacturer))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.Manufacturer
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.Model))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.Model
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.Revision))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.Revision
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.CompactFlash))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.CompactFlash
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.OptimalMultipleSectorsRead))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.OptimalMultipleSectorsRead
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.CanReadGdRomUsingSwapDisc))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.CanReadGdRomUsingSwapDisc
|
||||
</dd>
|
||||
<dt class="col-sm-2">
|
||||
@DisplayNameHelper.GetDisplayName(typeof(Device), nameof(Device.Type))
|
||||
</dt>
|
||||
<dd class="col-sm-10">
|
||||
@model.Report?.Type
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div>
|
||||
<a href="/admin/devices/edit/@model.Report?.Id" class="btn btn-primary">
|
||||
<i class="bi bi-pencil"></i> Edit
|
||||
</a>
|
||||
<a href="/admin/devices" class="btn btn-secondary">
|
||||
<i class="bi bi-arrow-left"></i> Back to List
|
||||
</a>
|
||||
</div>
|
||||
@if(model.ReadCapabilitiesId != 0)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/tested-media/@model.ReadCapabilitiesId" target="_blank">Read capabilities</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.ATA != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/ata/@model.Report.ATA.Id" target="_blank">ATA report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.ATAPI != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/ata/@model.Report.ATAPI.Id" target="_blank">ATAPI report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.SCSI != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/scsi/@model.Report.SCSI.Id" target="_blank">SCSI report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.MultiMediaCard != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/mmc-sd/@model.Report.MultiMediaCard.Id" target="_blank">MultiMediaCard report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.SecureDigital != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/mmc-sd/@model.Report.SecureDigital.Id" target="_blank">SecureDigital report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.USB != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/usb/devices/@model.Report.USB.Id" target="_blank">USB report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.GdRomSwapDiscCapabilitiesId != null)
|
||||
{
|
||||
<div>
|
||||
<a href="/admin/gdrom/@model.Report.GdRomSwapDiscCapabilitiesId" target="_blank">GD-ROM swap-trick
|
||||
capabilities
|
||||
report</a>
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.FireWire != null)
|
||||
{
|
||||
<div>
|
||||
Has a FireWire report.
|
||||
</div>
|
||||
}
|
||||
@if(model.Report.PCMCIA != null)
|
||||
{
|
||||
<div>
|
||||
Has a PCMCIA report.
|
||||
</div>
|
||||
}
|
||||
@if(model.SameAll.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Other device reports with same manufacturer, model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Id
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(int item in model.SameAll)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/devices/@item" class="btn btn-primary" target="_blank">Details</a>
|
||||
<a @onclick="() => Merge(model.Report.Id, item)" class="btn btn-secondary">Merge</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.SameButManufacturer.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Other device reports with same model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Id
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(int item in model.SameButManufacturer)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/devices/@item" class="btn btn-primary" target="_blank">Details</a>
|
||||
<a @onclick="() => Merge(model.Report.Id, item)" class="btn btn-secondary">Merge</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.ReportAll.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Uploaded reports with same manufacturer, model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Id
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(int item in model.ReportAll)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/reports/@item" class="btn btn-primary" target="_blank">Details</a>
|
||||
<a @onclick="() => MergeReports(model.Report.Id, item)" class="btn btn-secondary">Merge</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.ReportButManufacturer.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Device reports with same model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
Id
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(int item in model.ReportButManufacturer)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/reports/@item" class="btn btn-primary" target="_blank">Details</a>
|
||||
<a @onclick="() => MergeReports(model.Report.Id, item)" class="btn btn-secondary">Merge</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.StatsAll.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Device statistics with same manufacturer, model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Manufacturer))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Model))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Revision))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Bus))
|
||||
</th>
|
||||
<th>
|
||||
Has a linked report?
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(DeviceStat item in model.StatsAll)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item.Manufacturer
|
||||
</td>
|
||||
<td>
|
||||
@item.Model
|
||||
</td>
|
||||
<td>
|
||||
@item.Revision
|
||||
</td>
|
||||
<td>
|
||||
@item.Bus
|
||||
</td>
|
||||
<td>
|
||||
@if(item.Report is null)
|
||||
{
|
||||
@("No")
|
||||
}
|
||||
else
|
||||
{
|
||||
@if(item.Report.Id == model.Report.Id)
|
||||
{
|
||||
@("Us")
|
||||
}
|
||||
else
|
||||
{
|
||||
@("Yes")
|
||||
}
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<a @onclick="() => LinkReports(model.Report.Id, item.Id)" class="btn btn-secondary">Link</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.StatsButManufacturer.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Device statistics with same model and revision:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Manufacturer))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Model))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Revision))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(DeviceStat), nameof(DeviceStat.Bus))
|
||||
</th>
|
||||
<th>
|
||||
Has a linked report?
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(DeviceStat item in model.StatsButManufacturer)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item.Manufacturer
|
||||
</td>
|
||||
<td>
|
||||
@item.Model
|
||||
</td>
|
||||
<td>
|
||||
@item.Revision
|
||||
</td>
|
||||
<td>
|
||||
@item.Bus
|
||||
</td>
|
||||
<td>
|
||||
@if(item.Report is null)
|
||||
{
|
||||
@("No")
|
||||
}
|
||||
else
|
||||
{
|
||||
<a href="/admin/reports/@item.Report.Id" target="_blank">Yes</a>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<a @onclick="() => LinkReports(model.Report.Id, item.Id)" class="btn btn-secondary">Link</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.TestedMedias.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Tested media:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedMedia), nameof(TestedMedia.Manufacturer))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedMedia), nameof(TestedMedia.Model))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedMedia), nameof(TestedMedia.MediumTypeName))
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(TestedMedia item in model.TestedMedias)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item.Manufacturer
|
||||
</td>
|
||||
<td>
|
||||
@item.Model
|
||||
</td>
|
||||
<td>
|
||||
@item.MediumTypeName
|
||||
</td>
|
||||
<td>
|
||||
<a href="/admin/tested-media/@item.Id" class="btn btn-secondary" target="_blank">Details</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if(model.TestedSequentialMedias.Count > 0)
|
||||
{
|
||||
<div>
|
||||
<h4>Tested media:</h4>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedSequentialMedia), nameof(TestedSequentialMedia.Manufacturer))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedSequentialMedia), nameof(TestedSequentialMedia.Model))
|
||||
</th>
|
||||
<th>
|
||||
@DisplayNameHelper.GetDisplayName(typeof(TestedSequentialMedia), nameof(TestedSequentialMedia.MediumTypeName))
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach(TestedSequentialMedia item in model.TestedSequentialMedias)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@item.Manufacturer
|
||||
</td>
|
||||
<td>
|
||||
@item.Model
|
||||
</td>
|
||||
<td>
|
||||
@item.MediumTypeName
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
345
Aaru.Server/Components/Admin/Pages/Devices/Details.razor.cs
Normal file
345
Aaru.Server/Components/Admin/Pages/Devices/Details.razor.cs
Normal file
@@ -0,0 +1,345 @@
|
||||
using Aaru.CommonTypes.Metadata;
|
||||
using Aaru.Server.Database.Models;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DbContext = Aaru.Server.Database.DbContext;
|
||||
|
||||
namespace Aaru.Server.Components.Admin.Pages.Devices;
|
||||
|
||||
public partial class Details
|
||||
{
|
||||
bool _initialized;
|
||||
bool _notFound;
|
||||
DeviceDetails model;
|
||||
[Parameter]
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
await RefreshItemsAsync();
|
||||
}
|
||||
|
||||
async Task RefreshItemsAsync()
|
||||
{
|
||||
_initialized = false;
|
||||
_notFound = false;
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
model = new DeviceDetails
|
||||
{
|
||||
Report = await ctx.Devices.Include(static deviceReport => deviceReport.ATAPI)
|
||||
.Include(static deviceReport => deviceReport.ATA)
|
||||
.ThenInclude(static ata => ata.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.MultiMediaDevice)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.SequentialDevice)
|
||||
.FirstOrDefaultAsync(m => m.Id == Id)
|
||||
};
|
||||
|
||||
if(model.Report is null)
|
||||
{
|
||||
_initialized = true;
|
||||
_notFound = true;
|
||||
StateHasChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
model.ReportAll = await ctx.Reports
|
||||
.Where(d => d.Manufacturer == model.Report.Manufacturer &&
|
||||
d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision)
|
||||
.Select(static d => d.Id)
|
||||
.ToListAsync();
|
||||
|
||||
model.ReportButManufacturer = await ctx.Reports
|
||||
.Where(d => d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision)
|
||||
.Select(static d => d.Id)
|
||||
.Where(d => model.ReportAll.All(r => r != d))
|
||||
.ToListAsync();
|
||||
|
||||
model.SameAll = await ctx.Devices
|
||||
.Where(d => d.Manufacturer == model.Report.Manufacturer &&
|
||||
d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision &&
|
||||
d.Id != Id)
|
||||
.Select(static d => d.Id)
|
||||
.ToListAsync();
|
||||
|
||||
model.SameButManufacturer = await ctx.Devices
|
||||
.Where(d => d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision &&
|
||||
d.Id != Id)
|
||||
.Select(static d => d.Id)
|
||||
.Where(d => model.SameAll.All(r => r != d))
|
||||
.ToListAsync();
|
||||
|
||||
model.StatsAll = await ctx.DeviceStats
|
||||
.Where(d => d.Manufacturer == model.Report.Manufacturer &&
|
||||
d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision &&
|
||||
d.Report != null &&
|
||||
d.Report.Id != model.Report.Id)
|
||||
.ToListAsync();
|
||||
|
||||
model.StatsButManufacturer = ctx.DeviceStats
|
||||
.Where(d => d.Model == model.Report.Model &&
|
||||
d.Revision == model.Report.Revision &&
|
||||
d.Report != null &&
|
||||
d.Report.Id != model.Report.Id)
|
||||
.AsEnumerable()
|
||||
.Where(d => model.StatsAll.All(s => s.Id != d.Id))
|
||||
.ToList();
|
||||
|
||||
model.ReadCapabilitiesId =
|
||||
model.Report.ATA?.ReadCapabilities?.Id ?? model.Report.SCSI?.ReadCapabilities?.Id ?? 0;
|
||||
|
||||
// So we can check, as we know IDs with 0 will never exist, and EFCore does not allow null propagation in the LINQ
|
||||
int ataId = model.Report.ATA?.Id ?? 0;
|
||||
int atapiId = model.Report.ATAPI?.Id ?? 0;
|
||||
int scsiId = model.Report.SCSI?.Id ?? 0;
|
||||
int mmcId = model.Report.SCSI?.MultiMediaDevice?.Id ?? 0;
|
||||
int sscId = model.Report.SCSI?.SequentialDevice?.Id ?? 0;
|
||||
|
||||
model.TestedMedias = await ctx.TestedMedia
|
||||
.Where(t => t.AtaId == ataId ||
|
||||
t.AtaId == atapiId ||
|
||||
t.ScsiId == scsiId ||
|
||||
t.MmcId == mmcId)
|
||||
.OrderBy(static t => t.Manufacturer)
|
||||
.ThenBy(static t => t.Model)
|
||||
.ThenBy(static t => t.MediumTypeName)
|
||||
.ToListAsync();
|
||||
|
||||
model.TestedSequentialMedias = await ctx.TestedSequentialMedia.Where(t => t.SscId == sscId)
|
||||
.OrderBy(static t => t.Manufacturer)
|
||||
.ThenBy(static t => t.Model)
|
||||
.ThenBy(static t => t.MediumTypeName)
|
||||
.ToListAsync();
|
||||
|
||||
_initialized = true;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
async Task Merge(int master, int slave)
|
||||
{
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
Device? masterDevice = await ctx.Devices.FirstOrDefaultAsync(m => m.Id == master);
|
||||
Device? slaveDevice = await ctx.Devices.FirstOrDefaultAsync(m => m.Id == slave);
|
||||
|
||||
if(masterDevice is null || slaveDevice is null) return;
|
||||
|
||||
if(masterDevice.ATAId != null && masterDevice.ATAId != slaveDevice.ATAId)
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in
|
||||
ctx.TestedMedia.Where(d => d.AtaId == slaveDevice.ATAId))
|
||||
{
|
||||
testedMedia.AtaId = masterDevice.ATAId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
}
|
||||
else if(masterDevice.ATAId == null && slaveDevice.ATAId != null)
|
||||
{
|
||||
masterDevice.ATAId = slaveDevice.ATAId;
|
||||
ctx.Update(masterDevice);
|
||||
}
|
||||
|
||||
if(masterDevice.ATAPIId != null && masterDevice.ATAPIId != slaveDevice.ATAPIId)
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in
|
||||
ctx.TestedMedia.Where(d => d.AtaId == slaveDevice.ATAPIId))
|
||||
{
|
||||
testedMedia.AtaId = masterDevice.ATAPIId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
}
|
||||
else if(masterDevice.ATAPIId == null && slaveDevice.ATAPIId != null)
|
||||
{
|
||||
masterDevice.ATAPIId = slaveDevice.ATAPIId;
|
||||
ctx.Update(masterDevice);
|
||||
}
|
||||
|
||||
if(masterDevice.SCSIId != null && masterDevice.SCSIId != slaveDevice.SCSIId)
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in
|
||||
ctx.TestedMedia.Where(d => d.ScsiId == slaveDevice.SCSIId))
|
||||
{
|
||||
testedMedia.ScsiId = masterDevice.SCSIId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
}
|
||||
else if(masterDevice.SCSIId == null && slaveDevice.SCSIId != null)
|
||||
{
|
||||
masterDevice.SCSIId = slaveDevice.SCSIId;
|
||||
ctx.Update(masterDevice);
|
||||
}
|
||||
|
||||
masterDevice.ModifiedWhen = DateTime.UtcNow;
|
||||
ctx.Update(masterDevice);
|
||||
ctx.Remove(slaveDevice);
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
Id = master;
|
||||
|
||||
await RefreshItemsAsync();
|
||||
}
|
||||
|
||||
async Task MergeReports(int deviceId, int reportId)
|
||||
{
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
|
||||
Device? device = await ctx.Devices.Include(static deviceReport => deviceReport.ATA)
|
||||
.ThenInclude(static ata => ata.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.MultiMediaDevice)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.SequentialDevice)
|
||||
.FirstOrDefaultAsync(m => m.Id == deviceId);
|
||||
|
||||
UploadedReport? report = await ctx.Reports.Include(static deviceReport => deviceReport.ATA)
|
||||
.ThenInclude(static ata => ata.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.ReadCapabilities)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.MultiMediaDevice)
|
||||
.Include(static deviceReport => deviceReport.SCSI)
|
||||
.ThenInclude(static scsi => scsi.SequentialDevice)
|
||||
.FirstOrDefaultAsync(m => m.Id == reportId);
|
||||
|
||||
if(device?.ATAId != null && device.ATAId != report?.ATAId)
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in
|
||||
ctx.TestedMedia.Where(d => report != null && d.AtaId == report.ATAId))
|
||||
{
|
||||
testedMedia.AtaId = device.ATAId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
|
||||
if(device.ATA is { ReadCapabilities: null } && report?.ATA?.ReadCapabilities != null)
|
||||
{
|
||||
device.ATA.ReadCapabilities = report.ATA.ReadCapabilities;
|
||||
ctx.Update(device.ATA);
|
||||
}
|
||||
}
|
||||
else if(device?.ATAId == null && report?.ATAId != null)
|
||||
{
|
||||
if(device != null)
|
||||
{
|
||||
device.ATAId = report.ATAId;
|
||||
ctx.Update(device);
|
||||
}
|
||||
}
|
||||
|
||||
switch(device)
|
||||
{
|
||||
case { ATAPIId: not null } when device.ATAPIId != report?.ATAPIId:
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in
|
||||
ctx.TestedMedia.Where(d => report != null && d.AtaId == report.ATAPIId))
|
||||
{
|
||||
testedMedia.AtaId = device.ATAPIId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case { ATAPIId: null } when report?.ATAPIId != null:
|
||||
device.ATAPIId = report.ATAPIId;
|
||||
ctx.Update(device);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
switch(device)
|
||||
{
|
||||
case { SCSIId: not null } when device.SCSIId != report?.SCSIId:
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in ctx.TestedMedia.Where(d => report != null &&
|
||||
d.ScsiId == report.SCSIId))
|
||||
{
|
||||
testedMedia.ScsiId = device.SCSIId;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
|
||||
if(device.SCSI is { ReadCapabilities: null } && report?.SCSI?.ReadCapabilities != null)
|
||||
{
|
||||
device.SCSI.ReadCapabilities = report.SCSI.ReadCapabilities;
|
||||
ctx.Update(device.SCSI);
|
||||
}
|
||||
|
||||
if(device.SCSI is { MultiMediaDevice: null } && report?.SCSI?.MultiMediaDevice != null)
|
||||
{
|
||||
device.SCSI.MultiMediaDevice = report.SCSI.MultiMediaDevice;
|
||||
ctx.Update(device.SCSI);
|
||||
}
|
||||
else if(device.SCSI?.MultiMediaDevice != null && report?.SCSI?.MultiMediaDevice != null)
|
||||
{
|
||||
foreach(CommonTypes.Metadata.TestedMedia testedMedia in ctx.TestedMedia.Where(d => d.MmcId ==
|
||||
report.SCSI.MultiMediaDevice.Id))
|
||||
{
|
||||
testedMedia.MmcId = device.SCSI.MultiMediaDevice.Id;
|
||||
ctx.Update(testedMedia);
|
||||
}
|
||||
}
|
||||
|
||||
if(device.SCSI is { SequentialDevice: null } && report?.SCSI?.SequentialDevice != null)
|
||||
{
|
||||
device.SCSI.SequentialDevice = report.SCSI.SequentialDevice;
|
||||
ctx.Update(device.SCSI);
|
||||
}
|
||||
else if(device.SCSI?.SequentialDevice != null && report?.SCSI?.SequentialDevice != null)
|
||||
{
|
||||
foreach(TestedSequentialMedia testedSequentialMedia in
|
||||
ctx.TestedSequentialMedia.Where(d => d.SscId == report.SCSI.SequentialDevice.Id))
|
||||
{
|
||||
testedSequentialMedia.SscId = device.SCSI.SequentialDevice.Id;
|
||||
ctx.Update(testedSequentialMedia);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case { SCSIId: null } when report?.SCSIId != null:
|
||||
device.SCSIId = report.SCSIId;
|
||||
ctx.Update(device);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ctx.Remove(report);
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
Id = deviceId;
|
||||
await RefreshItemsAsync();
|
||||
}
|
||||
|
||||
async Task LinkReports(int deviceId, int statsId)
|
||||
{
|
||||
await using DbContext ctx = await DbContextFactory.CreateDbContextAsync();
|
||||
Device? device = await ctx.Devices.FirstOrDefaultAsync(m => m.Id == deviceId);
|
||||
DeviceStat? stat = await ctx.DeviceStats.FirstOrDefaultAsync(m => m.Id == statsId);
|
||||
|
||||
if(stat != null)
|
||||
{
|
||||
stat.Report = device;
|
||||
ctx.Update(stat);
|
||||
}
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
Id = deviceId;
|
||||
await RefreshItemsAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user