Added Blazor projects. Minor API/core updates.
All checks were successful
ci / build-test (push) Successful in 1m35s
ci / publish-image (push) Has been skipped

This commit is contained in:
2025-11-07 22:18:04 -05:00
parent 4020a01682
commit 840bec72d2
77 changed files with 60692 additions and 1 deletions

View File

@@ -0,0 +1,9 @@
@page "/analytics"
<PageTitle>Analytics</PageTitle>
<h3>Analytics</h3>
@code {
}

View File

@@ -0,0 +1,57 @@
@page "/circles"
@inject HttpClient Http
<PageTitle>Circles</PageTitle>
<h1>Circles</h1>
<p>This component demonstrates fetching data from the server.</p>
@* @if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th aria-label="Temperature in Celsius">Temp. (C)</th>
<th aria-label="Temperature in Farenheit">Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
} *@
@code {
// private WeatherForecast[]? forecasts;
// protected override async Task OnInitializedAsync()
// {
// forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
// }
// public class WeatherForecast
// {
// public DateOnly Date { get; set; }
// public int TemperatureC { get; set; }
// public string? Summary { get; set; }
// public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
// }
}

View File

@@ -0,0 +1,18 @@
@page "/creators"
<PageTitle>Creators</PageTitle>
<h1>Creators</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View File

@@ -0,0 +1,157 @@
@page "/"
@inject VoiceWorksClient Client
@using JSMR.Application.VoiceWorks.Queries.Search
<PageTitle>Home</PageTitle>
<MudTabs Elevation="2" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pa-6">
<MudTabPanel Text="Available" Icon="@Icons.Material.Filled.Home">
@if (availableVoiceWorks is null)
{
<p>Loading…</p>
}
else if (availableVoiceWorks.Length == 0)
{
<p>No results.</p>
}
else
{
<ul>
@foreach (var v in availableVoiceWorks)
{
<li>@v.ProductId @v.ProductName</li>
}
</ul>
}
</MudTabPanel>
<MudTabPanel Text="Upcoming" Icon="@Icons.Material.Filled.ArrowUpward">
@if (upcomingVoiceWorks is null)
{
<p>Loading…</p>
}
else if (upcomingVoiceWorks.Length == 0)
{
<p>No results.</p>
}
else
{
<ul>
@foreach (var v in upcomingVoiceWorks)
{
<li>@v.ProductId @v.ProductName</li>
}
</ul>
}
</MudTabPanel>
<MudTabPanel Text="Announcements" Icon="@Icons.Material.Filled.Home">
@if (announcedVoiceWorks is null)
{
<p>Loading…</p>
}
else if (announcedVoiceWorks.Length == 0)
{
<p>No results.</p>
}
else
{
<ul>
@foreach (var v in announcedVoiceWorks)
{
<li>@v.ProductId @v.ProductName</li>
}
</ul>
}
</MudTabPanel>
</MudTabs>
@code {
VoiceWorkSearchResult[]? availableVoiceWorks;
VoiceWorkSearchResult[]? upcomingVoiceWorks;
VoiceWorkSearchResult[]? announcedVoiceWorks;
protected override Task OnInitializedAsync()
{
_ = LoadAvailableVoiceWorksAsync();
_ = LoadUpcomingVoiceWorksAsync();
_ = LoadAnnouncedVoiceWorksAsync();
// availableVoiceWorks = await GetAvailableVoiceWorksAsync();
// upcomingVoiceWorks = await GetUpcomingVoiceWorksAsync();
return Task.CompletedTask;
}
private async Task LoadAvailableVoiceWorksAsync()
{
SearchVoiceWorksRequest request = new(
Options: new()
{
Criteria = new()
{
CircleStatus = CircleStatus.Favorited,
ReleaseDateStart = DateOnly.FromDateTime(DateTime.Today.AddDays(-6))
},
SortOptions =
[
new(VoiceWorkSortField.ReleaseDate, Application.Common.Search.SortDirection.Descending),
new(VoiceWorkSortField.Downloads, Application.Common.Search.SortDirection.Descending)
]
}
);
var result = await Client.SearchAsync(request);
availableVoiceWorks = result.Results.Items;
await InvokeAsync(StateHasChanged);
}
private async Task LoadUpcomingVoiceWorksAsync()
{
SearchVoiceWorksRequest request = new(
Options: new()
{
Criteria = new()
{
CircleStatus = CircleStatus.Favorited,
ScheduledReleaseDateEnd = DateOnly.FromDateTime(DateTime.Today.AddDays(8))
},
SortOptions =
[
new(VoiceWorkSortField.ScheduledReleaseDate, Application.Common.Search.SortDirection.Ascending),
new(VoiceWorkSortField.WishlistCount, Application.Common.Search.SortDirection.Descending)
]
}
);
var result = await Client.SearchAsync(request);
upcomingVoiceWorks = result.Results.Items;
await InvokeAsync(StateHasChanged);
}
private async Task LoadAnnouncedVoiceWorksAsync()
{
SearchVoiceWorksRequest request = new(
Options: new()
{
Criteria = new()
{
Status = Domain.Enums.VoiceWorkStatus.NewAndUpcoming
},
SortOptions =
[
//new(VoiceWorkSortField.Fa, Application.Common.Search.SortDirection.Ascending),
new(VoiceWorkSortField.WishlistCount, Application.Common.Search.SortDirection.Descending)
]
}
);
var result = await Client.SearchAsync(request);
announcedVoiceWorks = result.Results.Items;
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,18 @@
@page "/scanner"
<PageTitle>Scanner</PageTitle>
<h1>Scanner</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

View File

@@ -0,0 +1,95 @@
@page "/tags"
@inject VoiceWorksClient Client
@using JSMR.Application.Common.Search
@using JSMR.Application.Tags.Queries.Search
@using JSMR.Application.Tags.Queries.Search.Contracts
<PageTitle>Tags</PageTitle>
<h1>Tags</h1>
@if (searchResults is null)
{
<p>Loading…</p>
}
else if (searchResults.Items.Length == 0)
{
<p>No results.</p>
}
else
{
<MudDataGrid Items="@searchResults.Items">
<Columns>
<PropertyColumn Property="x => x.Name" Title="Name" />
<PropertyColumn Property="x => x.EnglishName" Title="English Name" />
<PropertyColumn Property="x => x.VoiceWorkCount" Title="Voice Works" />
<PropertyColumn Property="x => x.Favorite" Title="Favorite" />
<PropertyColumn Property="x => x.Blacklisted" Title="Blacklisted" />
</Columns>
</MudDataGrid>
<MudPagination ShowFirstButton="true" ShowLastButton="true" Count="@((int)Math.Ceiling((decimal)searchResults.TotalItems / (decimal)100))" @bind-Selected="@PageNumber" Class="j-pager" />
}
<style>
.j-pager {
position: fixed;
bottom: 0;
left: 0;
right: 0;
justify-content: center;
z-index: 2;
background: var(--mud-palette-background);
padding: .5em 1em;
}
</style>
@code {
private int pageNumber = 1;
public int PageNumber
{
get { return pageNumber; }
set
{
pageNumber = value;
_ = LoadTagsAsync();
}
}
int pageSize = 100;
SearchResult<TagSearchItem>? searchResults;
protected override Task OnInitializedAsync()
{
_ = LoadTagsAsync();
return Task.CompletedTask;
}
private async Task LoadTagsAsync()
{
SearchTagsRequest request = new(
Options: new()
{
PageNumber = PageNumber,
PageSize = pageSize,
Criteria = new()
{
},
SortOptions =
[
new(TagSortField.Name, Application.Common.Search.SortDirection.Ascending)
]
}
);
var result = await Client.SearchAsync(request);
searchResults = result?.Results ?? new();
await InvokeAsync(StateHasChanged);
}
}

View File

@@ -0,0 +1,46 @@
@page "/voiceworks"
@using JSMR.Application.VoiceWorks.Queries.Search
@inject VoiceWorksClient Client
<PageTitle>Voice Works</PageTitle>
<h3>VoiceWorks</h3>
@if (items is null)
{
<p>Loading…</p>
}
else if (items.Count == 0)
{
<p>No results.</p>
}
else
{
<ul>
@foreach (var v in items)
{
<li>@v.ProductId @v.ProductName</li>
}
</ul>
}
@code {
List<VoiceWorkSearchResult>? items;
protected override async Task OnInitializedAsync()
{
SearchVoiceWorksRequest request = new(
Options: new()
);
var result = await Client.SearchAsync(request);
// if (result.Ok)
// {
// items = result.Value!.Results.Items.ToList();
// }
//items = result.Value?.Results.Items ?? [];
items = result.Results.Items.ToList();
}
}