136 lines
7.6 KiB
Plaintext
136 lines
7.6 KiB
Plaintext
@using Microsoft.AspNetCore.Components.Forms
|
|
|
|
<MudPaper Class="pa-4" Elevation="2">
|
|
<MudText Typo="Typo.h6" GutterBottom="true">Tracks</MudText>
|
|
|
|
@if (AllowNewTracks)
|
|
{
|
|
<InputFile OnChange="HandleWavFilesSelected" accept=".wav,audio/wav,audio/x-wav" multiple disabled="@Disabled" />
|
|
}
|
|
|
|
@if (Tracks.Count == 0)
|
|
{
|
|
<MudText Typo="Typo.body2" Color="Color.Default" Class="mt-3">No tracks added yet.</MudText>
|
|
}
|
|
else
|
|
{
|
|
<MudList T="BatchRowModel" Class="mt-3">
|
|
@for (var i = 0; i < Tracks.Count; i++)
|
|
{
|
|
var index = i;
|
|
var row = Tracks[index];
|
|
<div style="@RowStyle(index)" @onclick="() => SelectRow(index)">
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Class="pa-2">
|
|
<MudText Typo="Typo.body2" Style="min-width: 1.5rem;">@(index + 1).</MudText>
|
|
<MudText Typo="Typo.body2" Style="flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">@row.TrackName</MudText>
|
|
@StatusChip(row)
|
|
<MudIconButton Icon="@Icons.Material.Filled.ArrowUpward"
|
|
Size="Size.Small"
|
|
Disabled="@(index == 0 || Disabled)"
|
|
OnClick="@(() => OnMoveUp.InvokeAsync(index))"
|
|
aria-label="Move track up" />
|
|
<MudIconButton Icon="@Icons.Material.Filled.ArrowDownward"
|
|
Size="Size.Small"
|
|
Disabled="@(index == Tracks.Count - 1 || Disabled)"
|
|
OnClick="@(() => OnMoveDown.InvokeAsync(index))"
|
|
aria-label="Move track down" />
|
|
@* Replace audio: existing (persisted) rows only. New rows still pick their WAV
|
|
via the file input above, so a replace control there would be redundant. A
|
|
native <label for> drives a per-row hidden InputFile — clicking the icon
|
|
opens that row's picker with zero JS (no eval, no programmatic .click()). *@
|
|
@if (row.Id.HasValue)
|
|
{
|
|
<label for="@ReplaceInputId(index)" @onclick:stopPropagation="true"
|
|
style="display: inline-flex; @(Disabled ? "pointer-events: none; opacity: 0.5;" : "cursor: pointer;")">
|
|
<MudIcon Icon="@Icons.Material.Filled.SwapHoriz"
|
|
Color="Color.Primary"
|
|
Size="Size.Small"
|
|
aria-label="Replace audio" />
|
|
</label>
|
|
<InputFile id="@ReplaceInputId(index)"
|
|
OnChange="@(e => OnReplaceFileSelected.InvokeAsync((index, e.File)))"
|
|
accept=".wav,audio/wav,audio/x-wav"
|
|
disabled="@Disabled"
|
|
style="display: none;" />
|
|
}
|
|
@* Remove: hidden for the sole remaining persisted track so a release can never
|
|
be track-deleted down to zero (that path soft-deletes the whole release). New
|
|
rows are always removable — dropping one only discards a pending upload. *@
|
|
@if (!(row.Id.HasValue && ExistingTrackCount <= 1))
|
|
{
|
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
|
Color="Color.Error"
|
|
Size="Size.Small"
|
|
Disabled="@Disabled"
|
|
OnClick="@(() => OnRemove.InvokeAsync(index))"
|
|
aria-label="Remove track" />
|
|
}
|
|
</MudStack>
|
|
@if (row.Status == BatchRowStatus.Uploading)
|
|
{
|
|
<MudProgressLinear Color="Color.Info"
|
|
Value="@row.UploadPercent"
|
|
Class="mx-2 mb-2"
|
|
aria-label="@($"Uploading {row.TrackName}")" />
|
|
}
|
|
</div>
|
|
}
|
|
</MudList>
|
|
}
|
|
</MudPaper>
|
|
|
|
@code {
|
|
[Parameter] public List<BatchRowModel> Tracks { get; set; } = new();
|
|
[Parameter] public int SelectedIndex { get; set; }
|
|
[Parameter] public EventCallback<int> SelectedIndexChanged { get; set; }
|
|
[Parameter] public bool Disabled { get; set; }
|
|
[Parameter] public bool AllowNewTracks { get; set; } = true;
|
|
|
|
/// <summary>
|
|
/// Count of existing (persisted, Id-bearing) tracks in the list. When this is 1, the remove
|
|
/// control on the sole persisted row is suppressed so a release cannot be track-deleted to zero
|
|
/// (replace + release-level delete remain). New unsaved rows are excluded from this count.
|
|
/// </summary>
|
|
[Parameter] public int ExistingTrackCount { get; set; }
|
|
|
|
[Parameter] public EventCallback<IReadOnlyList<IBrowserFile>> OnWavFilesSelected { get; set; }
|
|
[Parameter] public EventCallback<int> OnMoveUp { get; set; }
|
|
[Parameter] public EventCallback<int> OnMoveDown { get; set; }
|
|
[Parameter] public EventCallback<int> OnRemove { get; set; }
|
|
|
|
/// <summary>
|
|
/// Raised when the admin picks a replacement WAV for an existing row, carrying the list index and
|
|
/// the chosen file. Only fired for persisted (Id-bearing) rows.
|
|
/// </summary>
|
|
[Parameter] public EventCallback<(int Index, IBrowserFile File)> OnReplaceFileSelected { get; set; }
|
|
|
|
// Stable per-row DOM id linking the swap-icon <label> to its hidden InputFile.
|
|
private static string ReplaceInputId(int index) => $"replace-audio-input-{index}";
|
|
|
|
private const int MaxFilesPerPick = 50;
|
|
|
|
private Task SelectRow(int index) => SelectedIndexChanged.InvokeAsync(index);
|
|
|
|
private Task HandleWavFilesSelected(InputFileChangeEventArgs e) =>
|
|
OnWavFilesSelected.InvokeAsync(e.GetMultipleFiles(MaxFilesPerPick));
|
|
|
|
private string RowStyle(int index)
|
|
{
|
|
const string baseStyle = "cursor: pointer; border-radius: 4px;";
|
|
return index == SelectedIndex
|
|
? $"{baseStyle} background-color: var(--mud-palette-action-default-hover);"
|
|
: baseStyle;
|
|
}
|
|
|
|
private RenderFragment StatusChip(BatchRowModel row) => row.Status switch
|
|
{
|
|
BatchRowStatus.Uploading => @<MudChip T="string" Size="Size.Small" Color="Color.Info" Variant="Variant.Text">
|
|
<MudProgressCircular Indeterminate="true" Size="Size.Small" Class="mr-1" />Uploading</MudChip>,
|
|
BatchRowStatus.PostProcessing => @<MudChip T="string" Size="Size.Small" Color="Color.Info" Variant="Variant.Text">
|
|
<MudProgressCircular Indeterminate="true" Size="Size.Small" Class="mr-1" />Post-Processing</MudChip>,
|
|
BatchRowStatus.Done => @<MudChip T="string" Size="Size.Small" Color="Color.Success" Variant="Variant.Text" Icon="@Icons.Material.Filled.CheckCircle">Done</MudChip>,
|
|
BatchRowStatus.Failed => @<MudChip T="string" Size="Size.Small" Color="Color.Error" Variant="Variant.Text" Icon="@Icons.Material.Filled.Error">Failed</MudChip>,
|
|
_ => @<MudChip T="string" Size="Size.Small" Color="Color.Default" Variant="Variant.Text">Queued</MudChip>
|
|
};
|
|
}
|