From f0d60190cc687a6fbad4cdb9331e2e2b582148a8 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Mon, 1 Sep 2025 16:50:08 -0400 Subject: [PATCH] Track Gallery front end - For now uses a table but will replace with graphical media cards --- DeepDrftWeb.Client/Clients/TrackClient.cs | 46 +++++++++++++++ DeepDrftWeb.Client/Layout/NavMenu.razor | 5 +- DeepDrftWeb.Client/Pages/Home.razor | 57 +------------------ DeepDrftWeb.Client/Pages/TrackGallery.razor | 40 +++++++++++++ .../Pages/TrackGallery.razor.cs | 29 ++++++++++ DeepDrftWeb.Client/Program.cs | 3 + DeepDrftWeb.Client/Startup.cs | 20 +++++++ .../ViewModels/TrackGalleryViewModel.cs | 34 +++++++++++ DeepDrftWeb/Program.cs | 2 + 9 files changed, 176 insertions(+), 60 deletions(-) create mode 100644 DeepDrftWeb.Client/Clients/TrackClient.cs create mode 100644 DeepDrftWeb.Client/Pages/TrackGallery.razor create mode 100644 DeepDrftWeb.Client/Pages/TrackGallery.razor.cs create mode 100644 DeepDrftWeb.Client/Startup.cs create mode 100644 DeepDrftWeb.Client/ViewModels/TrackGalleryViewModel.cs diff --git a/DeepDrftWeb.Client/Clients/TrackClient.cs b/DeepDrftWeb.Client/Clients/TrackClient.cs new file mode 100644 index 0000000..68f363e --- /dev/null +++ b/DeepDrftWeb.Client/Clients/TrackClient.cs @@ -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 +{ + public TrackClient(ClientConfig config) : base(config) { } + + public async Task>> 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>>(json, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + + return dto?.From() ?? ApiResult>.CreateFailResult("Failed to deserialize response"); + } +} \ No newline at end of file diff --git a/DeepDrftWeb.Client/Layout/NavMenu.razor b/DeepDrftWeb.Client/Layout/NavMenu.razor index 3f08809..2a2f905 100644 --- a/DeepDrftWeb.Client/Layout/NavMenu.razor +++ b/DeepDrftWeb.Client/Layout/NavMenu.razor @@ -1,10 +1,7 @@  Home - Counter - - Weather - + Track Gallery diff --git a/DeepDrftWeb.Client/Pages/Home.razor b/DeepDrftWeb.Client/Pages/Home.razor index 6aaa2a4..5f8670c 100644 --- a/DeepDrftWeb.Client/Pages/Home.razor +++ b/DeepDrftWeb.Client/Pages/Home.razor @@ -1,59 +1,4 @@ @page "/" -Home +Deep Drft Home -Hello, world! -Welcome to your new app, powered by MudBlazor and the .NET 9 Template! - - - You can find documentation and examples on our website here: - - www.mudblazor.com - - - -
-Interactivity in this Template -
- - When you opt for the "Global" Interactivity Location,
- the render modes are defined in App.razor and consequently apply to all child components.
- In this case, providers are globally set in the MainLayout.
-
- On the other hand, if you choose the "Per page/component" Interactivity Location,
- it is necessary to include the
-
- <MudPopoverProvider />
- <MudDialogProvider />
- <MudSnackbarProvider />
-
- components on every interactive page.
-
- If a render mode is not specified for a page, it defaults to Server-Side Rendering (SSR),
- similar to this page. While MudBlazor allows pages to be rendered in SSR,
- please note that interactive features, such as buttons and dropdown menus, will not be functional. -
- -
-What's New in Blazor with the Release of .NET 9 -
- -Prerendering - - If you're exploring the features of .NET 9 Blazor,
you might be pleasantly surprised to learn that each page is prerendered on the server,
regardless of the selected render mode.

- This means that you'll need to inject all necessary services on the server,
even when opting for the wasm (WebAssembly) render mode.

- This prerendering functionality is crucial to ensuring that WebAssembly mode feels fast and responsive,
especially when it comes to initial page load times.

- For more information on how to detect prerendering and leverage the RenderContext, you can refer to the following link: - - More details - -
- -
-InteractiveAuto - - A discussion on how to achieve this can be found here: - - More details - - diff --git a/DeepDrftWeb.Client/Pages/TrackGallery.razor b/DeepDrftWeb.Client/Pages/TrackGallery.razor new file mode 100644 index 0000000..0c2beab --- /dev/null +++ b/DeepDrftWeb.Client/Pages/TrackGallery.razor @@ -0,0 +1,40 @@ +@page "/tracks" +@using DeepDrftModels.DTOs +@using DeepDrftModels.Entities + +

Track Gallery

+ + + +@if (ViewModel.Page != null) +{ + + + Name + Artist + Album + Genre + Released + Actions + + + @context.TrackName + @context.Artist + @context.Album + @context.Genre + @context.ReleaseDate + + View + + + + + +} +else +{ + + + +} + diff --git a/DeepDrftWeb.Client/Pages/TrackGallery.razor.cs b/DeepDrftWeb.Client/Pages/TrackGallery.razor.cs new file mode 100644 index 0000000..3367d41 --- /dev/null +++ b/DeepDrftWeb.Client/Pages/TrackGallery.razor.cs @@ -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 pageResult }) + { + ViewModel.Page = pageResult; + ViewModel.PageSize = pageResult.PageSize; + } + } +} \ No newline at end of file diff --git a/DeepDrftWeb.Client/Program.cs b/DeepDrftWeb.Client/Program.cs index 57602e1..36a64fe 100644 --- a/DeepDrftWeb.Client/Program.cs +++ b/DeepDrftWeb.Client/Program.cs @@ -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(); diff --git a/DeepDrftWeb.Client/Startup.cs b/DeepDrftWeb.Client/Startup.cs new file mode 100644 index 0000000..3a7c015 --- /dev/null +++ b/DeepDrftWeb.Client/Startup.cs @@ -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(); + services.AddScoped(); + } +} \ No newline at end of file diff --git a/DeepDrftWeb.Client/ViewModels/TrackGalleryViewModel.cs b/DeepDrftWeb.Client/ViewModels/TrackGalleryViewModel.cs new file mode 100644 index 0000000..72d07db --- /dev/null +++ b/DeepDrftWeb.Client/ViewModels/TrackGalleryViewModel.cs @@ -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? Page { get; set; } = null; + + public TrackGalleryViewModel(TrackClient trackClient) + { + TrackClient = trackClient; + } +} \ No newline at end of file diff --git a/DeepDrftWeb/Program.cs b/DeepDrftWeb/Program.cs index 4c37fbb..2ad406d 100644 --- a/DeepDrftWeb/Program.cs +++ b/DeepDrftWeb/Program.cs @@ -11,6 +11,8 @@ builder.Services.AddMudServices(); Startup.ConfigureDomainServices(builder); +var hostUrl = builder.Configuration.GetValue("ASPNETCORE_URLS")?.Split(';').First() ?? throw new Exception("ASPNETCORE_URLS undefined"); +DeepDrftWeb.Client.Startup.ConfigureDomainServices(builder.Services, hostUrl); builder.Services.AddControllers();