Track Gallery front end

- For now uses a table but will replace with graphical media cards
This commit is contained in:
2025-09-01 16:50:08 -04:00
parent 3d79df725c
commit f0d60190cc
9 changed files with 176 additions and 60 deletions
+46
View File
@@ -0,0 +1,46 @@
using DeepDrftModels.Entities;
using DeepDrftModels.Models;
using NetBlocks.Models;
using System.Text.Json;
using System.Web;
namespace DeepDrftWeb.Client.Clients;
public class TrackClient : ApiClient<ClientConfig>
{
public TrackClient(ClientConfig config) : base(config) { }
public async Task<ApiResult<PagedResult<TrackEntity>>> GetPage(
int pageNumber,
int pageSize,
string? sortColumn = null,
bool sortDescending = false)
{
var uriBuilder = new UriBuilder(http.BaseAddress!)
{
Path = "api/track/page"
};
var query = HttpUtility.ParseQueryString(string.Empty);
query["pageNumber"] = pageNumber.ToString();
query["pageSize"] = pageSize.ToString();
if (!string.IsNullOrEmpty(sortColumn))
query["sortColumn"] = sortColumn;
if (sortDescending)
query["sortDescending"] = "true";
uriBuilder.Query = query.ToString();
var response = await http.GetAsync(uriBuilder.Uri);
var json = await response.Content.ReadAsStringAsync();
var dto = JsonSerializer.Deserialize<ApiResultDto<PagedResult<TrackEntity>>>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
return dto?.From() ?? ApiResult<PagedResult<TrackEntity>>.CreateFailResult("Failed to deserialize response");
}
}
+1 -4
View File
@@ -1,10 +1,7 @@
<MudNavMenu>
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
<MudNavLink Href="counter" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Add">Counter</MudNavLink>
<MudNavLink Href="weather" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Weather</MudNavLink>
<MudNavLink Href="/tracks" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.BrowseGallery">Track Gallery</MudNavLink>
</MudNavMenu>
+1 -56
View File
@@ -1,59 +1,4 @@
@page "/"
<PageTitle>Home</PageTitle>
<PageTitle>Deep Drft Home</PageTitle>
<MudText Typo="Typo.h3" GutterBottom="true">Hello, world!</MudText>
<MudText Class="mb-8">Welcome to your new app, powered by MudBlazor and the .NET 9 Template!</MudText>
<MudAlert Severity="Severity.Normal" ContentAlignment="HorizontalAlignment.Start">
You can find documentation and examples on our website here:
<MudLink Href="https://mudblazor.com" Target="_blank" Typo="Typo.body2" Color="Color.Primary">
<b>www.mudblazor.com</b>
</MudLink>
</MudAlert>
<br />
<MudText Typo="Typo.h5" GutterBottom="true">Interactivity in this Template</MudText>
<br />
<MudText Typo="Typo.body2">
When you opt for the "Global" Interactivity Location, <br />
the render modes are defined in App.razor and consequently apply to all child components.<br />
In this case, providers are globally set in the MainLayout.<br />
<br />
On the other hand, if you choose the "Per page/component" Interactivity Location,<br />
it is necessary to include the <br />
<br />
&lt;MudPopoverProvider /&gt; <br />
&lt;MudDialogProvider /&gt; <br />
&lt;MudSnackbarProvider /&gt; <br />
<br />
components on every interactive page.<br />
<br />
If a render mode is not specified for a page, it defaults to Server-Side Rendering (SSR),<br />
similar to this page. While MudBlazor allows pages to be rendered in SSR,<br />
please note that interactive features, such as buttons and dropdown menus, will not be functional.
</MudText>
<br />
<MudText Typo="Typo.h5" GutterBottom="true">What's New in Blazor with the Release of .NET 9</MudText>
<br />
<MudText Typo="Typo.h6" GutterBottom="true">Prerendering</MudText>
<MudText Typo="Typo.body2" GutterBottom="true">
If you're exploring the features of .NET 9 Blazor,<br /> you might be pleasantly surprised to learn that each page is prerendered on the server,<br /> regardless of the selected render mode.<br /><br />
This means that you'll need to inject all necessary services on the server,<br /> even when opting for the wasm (WebAssembly) render mode.<br /><br />
This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,<br /> especially when it comes to initial page load times.<br /><br />
For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following link:
<MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issuecomment-1783568121" Target="_blank" Typo="Typo.body2" Color="Color.Primary">
More details
</MudLink>
</MudText>
<br />
<MudText Typo="Typo.h6" GutterBottom="true">InteractiveAuto</MudText>
<MudText Typo="Typo.body2">
A discussion on how to achieve this can be found here:
<MudLink Href="https://github.com/dotnet/aspnetcore/issues/51468#issue-1950424116" Target="_blank" Typo="Typo.body2" Color="Color.Primary">
More details
</MudLink>
</MudText>
@@ -0,0 +1,40 @@
@page "/tracks"
@using DeepDrftModels.DTOs
@using DeepDrftModels.Entities
<h3>Track Gallery</h3>
<MudContainer>
@if (ViewModel.Page != null)
{
<MudTable T="TrackEntity" Items="@ViewModel.Page.Items" Hover="true" Breakpoint="Breakpoint.Sm">
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Artist</MudTh>
<MudTh>Album</MudTh>
<MudTh>Genre</MudTh>
<MudTh>Released</MudTh>
<MudTh>Actions</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Name">@context.TrackName</MudTd>
<MudTd DataLabel="Artist">@context.Artist</MudTd>
<MudTd DataLabel="Album">@context.Album</MudTd>
<MudTd DataLabel="Genre">@context.Genre</MudTd>
<MudTd DataLabel="Released">@context.ReleaseDate</MudTd>
<MudTd DataLabel="Actions">
<MudButton Variant="Variant.Text" Color="Color.Primary">View</MudButton>
</MudTd>
</RowTemplate>
</MudTable>
<MudPagination Count="@ViewModel.Page.TotalPages" Selected="@ViewModel.Page.Page" SelectedChanged="i => SetPage(i)" BoundaryCount="2" MiddleCount="3"/>
}
else
{
<MudSkeleton Height="650px" Class="pa-2 ma-2"/>
<MudSkeleton Height="80px"/>
<MudSpacer />
}
</MudContainer>
@@ -0,0 +1,29 @@
using DeepDrftModels.Entities;
using DeepDrftModels.Models;
using DeepDrftWeb.Client.ViewModels;
using Microsoft.AspNetCore.Components;
namespace DeepDrftWeb.Client.Pages;
public partial class TrackGallery : ComponentBase
{
[Inject]
public required TrackGalleryViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
await SetPage(1);
}
private async Task SetPage(int newPage)
{
var result = await ViewModel.TrackClient.GetPage(newPage, ViewModel.PageSize, ViewModel.SortBy, ViewModel.IsDescending);
if (result is { Success: true, Value: PagedResult<TrackEntity> pageResult })
{
ViewModel.Page = pageResult;
ViewModel.PageSize = pageResult.PageSize;
}
}
}
+3
View File
@@ -1,3 +1,4 @@
using DeepDrftWeb.Client;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MudBlazor.Services;
@@ -5,4 +6,6 @@ var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddMudServices();
Startup.ConfigureDomainServices(builder.Services, builder.HostEnvironment.BaseAddress);
await builder.Build().RunAsync();
+20
View File
@@ -0,0 +1,20 @@
using DeepDrftWeb.Client.Clients;
using DeepDrftWeb.Client.ViewModels;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using NetBlocks.Models;
namespace DeepDrftWeb.Client;
public static class Startup
{
public static void ConfigureDomainServices(IServiceCollection services, string baseAddress)
{
// HTTP Client for Server API
services.AddScoped(_ => new HttpClient { BaseAddress = new Uri(baseAddress) });
// Track Client
services.AddSingleton(new ClientConfig(baseAddress));
services.AddScoped<TrackClient>();
services.AddScoped<TrackGalleryViewModel>();
}
}
@@ -0,0 +1,34 @@
using DeepDrftModels.Entities;
using DeepDrftModels.Models;
using DeepDrftWeb.Client.Clients;
namespace DeepDrftWeb.Client.ViewModels;
public class TrackGalleryViewModel
{
public TrackClient TrackClient { get; }
// private int _pageNumber = 1;
public int PageNumber { get; set; } = 1;
public int PageSize
{
get => Page?.PageSize ?? 15;
set
{
if (Page == null) throw new Exception();
if (value != Page.PageSize)
{
Page.PageSize = value;
}
}
}
public string SortBy { get; set; } = string.Empty;
public bool IsDescending { get; set; } = false;
public PagedResult<TrackEntity>? Page { get; set; } = null;
public TrackGalleryViewModel(TrackClient trackClient)
{
TrackClient = trackClient;
}
}
+2
View File
@@ -11,6 +11,8 @@ builder.Services.AddMudServices();
Startup.ConfigureDomainServices(builder);
var hostUrl = builder.Configuration.GetValue<string>("ASPNETCORE_URLS")?.Split(';').First() ?? throw new Exception("ASPNETCORE_URLS undefined");
DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services, hostUrl);
builder.Services.AddControllers();