Merge branch 'p8-w12-release-track-normalize' into dev
This commit is contained in:
@@ -89,22 +89,22 @@ public class TrackClient
|
||||
: ApiResult<TrackDto?>.CreateFailResult("Failed to deserialize response");
|
||||
}
|
||||
|
||||
public async Task<ApiResult<List<AlbumSummaryDto>>> GetAlbums()
|
||||
public async Task<ApiResult<List<ReleaseDto>>> GetAlbums()
|
||||
{
|
||||
var response = await _http.GetAsync("api/track/albums");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return ApiResult<List<AlbumSummaryDto>>.CreateFailResult($"HTTP {(int)response.StatusCode}");
|
||||
return ApiResult<List<ReleaseDto>>.CreateFailResult($"HTTP {(int)response.StatusCode}");
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
var albums = JsonSerializer.Deserialize<List<AlbumSummaryDto>>(json, new JsonSerializerOptions
|
||||
var releases = JsonSerializer.Deserialize<List<ReleaseDto>>(json, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
|
||||
return albums is not null
|
||||
? ApiResult<List<AlbumSummaryDto>>.CreatePassResult(albums)
|
||||
: ApiResult<List<AlbumSummaryDto>>.CreateFailResult("Failed to deserialize response");
|
||||
return releases is not null
|
||||
? ApiResult<List<ReleaseDto>>.CreatePassResult(releases)
|
||||
: ApiResult<List<ReleaseDto>>.CreateFailResult("Failed to deserialize response");
|
||||
}
|
||||
|
||||
public async Task<ApiResult<List<GenreSummaryDto>>> GetGenres()
|
||||
|
||||
@@ -13,26 +13,26 @@
|
||||
</a>
|
||||
<MudText Typo="Typo.subtitle2" Class="track-meta-sep"> - </MudText>
|
||||
<MudText Typo="Typo.caption" Class="track-meta-artist text-truncate">
|
||||
@Track.Artist
|
||||
@Track.Release?.Artist
|
||||
</MudText>
|
||||
</div>
|
||||
|
||||
<div class="track-meta-accents">
|
||||
@if (!string.IsNullOrEmpty(Track.Genre))
|
||||
@if (!string.IsNullOrEmpty(Track.Release?.Genre))
|
||||
{
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Tertiary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@Track.Genre
|
||||
@Track.Release.Genre
|
||||
</MudChip>
|
||||
}
|
||||
|
||||
@if (Track.ReleaseDate.HasValue)
|
||||
@if (Track.Release?.ReleaseDate.HasValue == true)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Class="track-meta-year">
|
||||
@Track.ReleaseDate.Value.Year
|
||||
@Track.Release.ReleaseDate.Value.Year
|
||||
</MudText>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="np-title">@(Player?.CurrentTrack?.TrackName ?? "Nothing playing")</div>
|
||||
<div class="np-sub">
|
||||
@(Player?.CurrentTrack != null
|
||||
? $"{Player.CurrentTrack.Artist} · {Player.CurrentTrack.Album ?? "Single"}"
|
||||
? $"{Player.CurrentTrack.Release?.Artist} · {Player.CurrentTrack.Release?.Title ?? "Single"}"
|
||||
: "Select a track to begin")
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@{
|
||||
var hasLink = !string.IsNullOrEmpty(TrackModel?.EntryKey);
|
||||
var trackHref = hasLink ? $"/track/{TrackModel!.EntryKey}" : null;
|
||||
var hasArt = !string.IsNullOrEmpty(TrackModel?.ImagePath);
|
||||
var hasArt = !string.IsNullOrEmpty(TrackModel?.Release?.ImagePath);
|
||||
}
|
||||
|
||||
@if (ViewMode == GalleryViewMode.Grid)
|
||||
@@ -13,9 +13,9 @@
|
||||
@if (hasLink)
|
||||
{
|
||||
<a href="@trackHref" class="deepdrft-track-card-link">
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.ImagePath))
|
||||
{
|
||||
<div class="deepdrft-track-card-bg" style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.ImagePath)');">
|
||||
<div class="deepdrft-track-card-bg" style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.Release!.ImagePath)');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -24,9 +24,9 @@
|
||||
}
|
||||
</a>
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||
else if (!string.IsNullOrEmpty(TrackModel?.Release?.ImagePath))
|
||||
{
|
||||
<div class="deepdrft-track-card-bg" style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.ImagePath)');">
|
||||
<div class="deepdrft-track-card-bg" style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.Release!.ImagePath)');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-artist text-truncate mb-2">
|
||||
@TrackModel?.Artist
|
||||
@TrackModel?.Release?.Artist
|
||||
</MudText>
|
||||
</div>
|
||||
</a>
|
||||
@@ -62,38 +62,38 @@
|
||||
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-artist text-truncate mb-2">
|
||||
@TrackModel?.Artist
|
||||
@TrackModel?.Release?.Artist
|
||||
</MudText>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="deepdrft-track-info-middle">
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Album))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.Title))
|
||||
{
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-meta text-truncate">
|
||||
@TrackModel.Album
|
||||
@TrackModel.Release!.Title
|
||||
</MudText>
|
||||
}
|
||||
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Genre))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.Genre))
|
||||
{
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Tertiary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@TrackModel.Genre
|
||||
@TrackModel.Release!.Genre
|
||||
</MudChip>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="deepdrft-track-info-bottom">
|
||||
@if (TrackModel?.ReleaseDate.HasValue == true)
|
||||
@if (TrackModel?.Release?.ReleaseDate.HasValue == true)
|
||||
{
|
||||
<MudText Typo="Typo.caption"
|
||||
Class="deepdrft-track-meta">
|
||||
@TrackModel.ReleaseDate.Value.Year
|
||||
@TrackModel.Release!.ReleaseDate!.Value.Year
|
||||
</MudText>
|
||||
}
|
||||
else
|
||||
@@ -127,10 +127,10 @@ else
|
||||
{
|
||||
<a href="@trackHref" class="deepdrft-track-row-link">
|
||||
@* art thumb *@
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.ImagePath))
|
||||
{
|
||||
<div class="deepdrft-track-row-thumb"
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.ImagePath)');">
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.Release!.ImagePath)');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -141,7 +141,7 @@ else
|
||||
@* text block *@
|
||||
<div class="deepdrft-track-row-text">
|
||||
<MudText Typo="Typo.subtitle2" Class="deepdrft-track-title text-truncate">
|
||||
@TrackModel?.Artist
|
||||
@TrackModel?.Release?.Artist
|
||||
</MudText>
|
||||
<MudText Typo="Typo.caption" Class="deepdrft-track-meta text-truncate">
|
||||
@TrackModel?.TrackName
|
||||
@@ -150,20 +150,20 @@ else
|
||||
|
||||
@* right metadata *@
|
||||
<div class="deepdrft-track-row-meta">
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Genre))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.Genre))
|
||||
{
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Tertiary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@TrackModel.Genre
|
||||
@TrackModel.Release!.Genre
|
||||
</MudChip>
|
||||
}
|
||||
@if (TrackModel?.ReleaseDate.HasValue == true)
|
||||
@if (TrackModel?.Release?.ReleaseDate.HasValue == true)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Class="deepdrft-track-meta">
|
||||
@TrackModel.ReleaseDate.Value.Year
|
||||
@TrackModel.Release!.ReleaseDate!.Value.Year
|
||||
</MudText>
|
||||
}
|
||||
</div>
|
||||
@@ -172,10 +172,10 @@ else
|
||||
else
|
||||
{
|
||||
@* same structure without anchor *@
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.ImagePath))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.ImagePath))
|
||||
{
|
||||
<div class="deepdrft-track-row-thumb"
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.ImagePath)');">
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(TrackModel.Release!.ImagePath)');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -184,27 +184,27 @@ else
|
||||
}
|
||||
<div class="deepdrft-track-row-text">
|
||||
<MudText Typo="Typo.subtitle2" Class="deepdrft-track-title text-truncate">
|
||||
@TrackModel?.Artist
|
||||
@TrackModel?.Release?.Artist
|
||||
</MudText>
|
||||
<MudText Typo="Typo.caption" Class="deepdrft-track-meta text-truncate">
|
||||
@TrackModel?.TrackName
|
||||
</MudText>
|
||||
</div>
|
||||
<div class="deepdrft-track-row-meta">
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Genre))
|
||||
@if (!string.IsNullOrEmpty(TrackModel?.Release?.Genre))
|
||||
{
|
||||
<MudChip T="string"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Tertiary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@TrackModel.Genre
|
||||
@TrackModel.Release!.Genre
|
||||
</MudChip>
|
||||
}
|
||||
@if (TrackModel?.ReleaseDate.HasValue == true)
|
||||
@if (TrackModel?.Release?.ReleaseDate.HasValue == true)
|
||||
{
|
||||
<MudText Typo="Typo.caption" Class="deepdrft-track-meta">
|
||||
@TrackModel.ReleaseDate.Value.Year
|
||||
@TrackModel.Release!.ReleaseDate!.Value.Year
|
||||
</MudText>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -33,11 +33,11 @@
|
||||
<div class="album-card"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
@onclick="@(() => OpenAlbum(album.Album))">
|
||||
@if (!string.IsNullOrEmpty(album.CoverImageKey))
|
||||
@onclick="@(() => OpenAlbum(album.Title))">
|
||||
@if (!string.IsNullOrEmpty(album.ImagePath))
|
||||
{
|
||||
<div class="album-card-cover"
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(album.CoverImageKey)');">
|
||||
style="background-image: url('api/image/@Uri.EscapeDataString(album.ImagePath)');">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
<div class="album-card-body">
|
||||
<MudText Typo="Typo.subtitle1" Class="album-card-title text-truncate">
|
||||
@album.Album
|
||||
@album.Title
|
||||
</MudText>
|
||||
<MudText Typo="Typo.caption" Class="album-card-count">
|
||||
@album.TrackCount @(album.TrackCount == 1 ? "track" : "tracks")
|
||||
|
||||
@@ -10,7 +10,7 @@ public partial class AlbumsView : ComponentBase
|
||||
[Inject] public required NavigationManager Navigation { get; set; }
|
||||
|
||||
private bool _loading = true;
|
||||
private List<AlbumSummaryDto> _albums = [];
|
||||
private List<ReleaseDto> _albums = [];
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
||||
@@ -43,7 +43,9 @@ else if (ViewModel.Track is not null)
|
||||
var isThisTrackPlaying = PlayerService.CurrentTrack?.Id == track.Id
|
||||
&& PlayerService.IsPlaying
|
||||
&& !PlayerService.IsPaused;
|
||||
var hasMeta = track.Album is not null || track.Genre is not null || track.ReleaseDate is not null;
|
||||
var release = track.Release;
|
||||
var hasMeta = release is not null
|
||||
&& (release.Title is not null || release.Genre is not null || release.ReleaseDate is not null);
|
||||
|
||||
<div class="deepdrft-track-detail-container">
|
||||
|
||||
@@ -54,7 +56,7 @@ else if (ViewModel.Track is not null)
|
||||
<MudStack Row AlignItems="AlignItems.Start" Justify="Justify.SpaceBetween" Style="margin: 2rem 0 1.5rem;">
|
||||
<div class="deepdrft-track-detail-masthead">
|
||||
<MudText Typo="Typo.h3">@track.TrackName</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@track.Artist</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@release?.Artist</MudText>
|
||||
</div>
|
||||
|
||||
<MudStack Row AlignItems="AlignItems.Center" Spacing="1">
|
||||
@@ -64,10 +66,10 @@ else if (ViewModel.Track is not null)
|
||||
</MudStack>
|
||||
|
||||
<div class="deepdrft-track-detail-cover">
|
||||
@if (!string.IsNullOrEmpty(track.ImagePath))
|
||||
@if (!string.IsNullOrEmpty(release?.ImagePath))
|
||||
{
|
||||
<MudPaper Elevation="2" Class="deepdrft-track-detail-cover-art"
|
||||
Style="@($"background-image: url('api/image/{Uri.EscapeDataString(track.ImagePath)}');")" />
|
||||
Style="@($"background-image: url('api/image/{Uri.EscapeDataString(release.ImagePath)}');")" />
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -82,31 +84,31 @@ else if (ViewModel.Track is not null)
|
||||
<MudDivider />
|
||||
|
||||
<div class="deepdrft-track-detail-meta">
|
||||
@if (track.Album is not null)
|
||||
@if (release?.Title is not null)
|
||||
{
|
||||
<div>
|
||||
<MudText Typo="Typo.overline">Album</MudText>
|
||||
<MudText Typo="Typo.body1">@track.Album</MudText>
|
||||
<MudText Typo="Typo.body1">@release.Title</MudText>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (track.Genre is not null)
|
||||
@if (release?.Genre is not null)
|
||||
{
|
||||
<div>
|
||||
<MudChip T="string"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Tertiary"
|
||||
Class="deepdrft-genre-chip">
|
||||
@track.Genre
|
||||
@release.Genre
|
||||
</MudChip>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (track.ReleaseDate is not null)
|
||||
@if (release?.ReleaseDate is not null)
|
||||
{
|
||||
<div>
|
||||
<MudText Typo="Typo.overline">Released</MudText>
|
||||
<MudText Typo="Typo.body1">@track.ReleaseDate.Value.ToString("MMMM yyyy")</MudText>
|
||||
<MudText Typo="Typo.body1">@release.ReleaseDate.Value.ToString("MMMM yyyy")</MudText>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -21,8 +21,8 @@ public interface ITrackDataService
|
||||
string? album = null,
|
||||
string? genre = null);
|
||||
|
||||
/// <summary>Distinct non-null albums with track counts and a representative cover key.</summary>
|
||||
Task<ApiResult<List<AlbumSummaryDto>>> GetAlbums();
|
||||
/// <summary>All releases with track counts, title-ascending.</summary>
|
||||
Task<ApiResult<List<ReleaseDto>>> GetAlbums();
|
||||
|
||||
/// <summary>Distinct non-null genres with track counts.</summary>
|
||||
Task<ApiResult<List<GenreSummaryDto>>> GetGenres();
|
||||
|
||||
@@ -29,7 +29,7 @@ public class TrackClientDataService : ITrackDataService
|
||||
string? genre = null)
|
||||
=> _trackClient.GetPage(pageNumber, pageSize, sortColumn, sortDescending, searchText, album, genre);
|
||||
|
||||
public Task<ApiResult<List<AlbumSummaryDto>>> GetAlbums()
|
||||
public Task<ApiResult<List<ReleaseDto>>> GetAlbums()
|
||||
=> _trackClient.GetAlbums();
|
||||
|
||||
public Task<ApiResult<List<GenreSummaryDto>>> GetGenres()
|
||||
|
||||
Reference in New Issue
Block a user