Updated CI for Blazor WebAssembly. Added styles for product cards.
This commit is contained in:
@@ -36,6 +36,9 @@ jobs:
|
||||
- name: Docker sanity (ensures socket mount is working)
|
||||
run: docker version
|
||||
|
||||
- name: Install WASM workload
|
||||
run: dotnet workload install wasm-tools --skip-sign-check
|
||||
|
||||
- run: dotnet restore
|
||||
- run: dotnet build --configuration Release --no-restore
|
||||
- run: dotnet test --configuration Release --no-build --logger "trx;LogFileName=test-results.trx"
|
||||
|
||||
@@ -7,5 +7,6 @@ public enum VoiceWorkSortField
|
||||
Downloads,
|
||||
WishlistCount,
|
||||
SalesToWishlistRatio,
|
||||
StarRating
|
||||
StarRating,
|
||||
FavoriteCircle
|
||||
}
|
||||
@@ -324,6 +324,7 @@ public class VoiceWorkSearchProvider(AppDbContext context, IVoiceWorkFullTextSea
|
||||
VoiceWorkSortField.Downloads => x => x.VoiceWork.Downloads ?? 0,
|
||||
VoiceWorkSortField.WishlistCount => x => x.VoiceWork.WishlistCount ?? 0,
|
||||
VoiceWorkSortField.StarRating => x => x.VoiceWork.StarRating ?? 0,
|
||||
VoiceWorkSortField.FavoriteCircle => x => !x.Circle.Favorite,
|
||||
_ => x => x.VoiceWork.ProductId
|
||||
};
|
||||
|
||||
|
||||
25
JSMR.UI.Blazor/Components/JProduct.razor
Normal file
25
JSMR.UI.Blazor/Components/JProduct.razor
Normal file
@@ -0,0 +1,25 @@
|
||||
@using JSMR.Application.VoiceWorks.Queries.Search
|
||||
@using JSMR.UI.Blazor.Services
|
||||
|
||||
<div class="j-card j-voice-work-card">
|
||||
<div class="j-voice-work-image-container">
|
||||
<JImage ImageClass="j-voice-work-image" Source="@ImageUrlProvider.GetImageURL(Product.ProductId, Product.HasImage, Product.SalesDate, "main")"></JImage>
|
||||
</div>
|
||||
<div class="j-voice-work-content">
|
||||
<div class="j-product-title">@Product.ProductName</div>
|
||||
<div class="j-product-description">@Product.Description</div>
|
||||
<div class="j-tags">
|
||||
@foreach (var tag in Product.Tags)
|
||||
{
|
||||
<div class="j-tag">@tag.Name</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="j-voice-work-info">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public required VoiceWorkSearchResult Product { get; set; }
|
||||
}
|
||||
24
JSMR.UI.Blazor/Components/JProductCollection.razor
Normal file
24
JSMR.UI.Blazor/Components/JProductCollection.razor
Normal file
@@ -0,0 +1,24 @@
|
||||
@using JSMR.Application.VoiceWorks.Queries.Search
|
||||
|
||||
@if (Products is null)
|
||||
{
|
||||
<p>Loading…</p>
|
||||
}
|
||||
else if (Products.Length == 0)
|
||||
{
|
||||
<p>No results.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="j-product-items-container">
|
||||
@foreach (var product in Products)
|
||||
{
|
||||
<JProduct Product="@product"></JProduct>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public VoiceWorkSearchResult[]? Products { get; set; }
|
||||
}
|
||||
17
JSMR.UI.Blazor/Enums/ImageSize.cs
Normal file
17
JSMR.UI.Blazor/Enums/ImageSize.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace JSMR.UI.Blazor.Enums;
|
||||
|
||||
/// <summary>Image size selector for DLsite assets.</summary>
|
||||
public enum ImageSize
|
||||
{
|
||||
/// <summary>100×100 square thumbnail (DLsite: "sam").</summary>
|
||||
Thumb100,
|
||||
|
||||
/// <summary>240×240 square (DLsite: "main_240x240").</summary>
|
||||
Square240,
|
||||
|
||||
/// <summary>300×300 square (DLsite: "main_300x300").</summary>
|
||||
Square300,
|
||||
|
||||
/// <summary>Native “main” image (typically ~560×420).</summary>
|
||||
Main
|
||||
}
|
||||
@@ -40,11 +40,13 @@ else
|
||||
@foreach (var item in searchResults.Items)
|
||||
{
|
||||
<div class="circle-item">
|
||||
@* <JImage @key="item.CircleId" ContainerClass="j-circle-image-container" ImageClass="j-circle-image" Source="@ImageUrlProvider.GetImageURL(item.LatestProductId, item.LatestVoiceWorkHasImage ?? false, item.LatestVoiceWorkSalesDate, "main")" /> *@
|
||||
<JImage @key="item.CircleId" ContainerClass="j-circle-image-container-2" ImageClass="j-circle-image-2" Source="@ImageUrlProvider.GetImageURL(item.LatestProductId, item.LatestVoiceWorkHasImage ?? false, item.LatestVoiceWorkSalesDate, "main")" />
|
||||
|
||||
<div class="fdfs">
|
||||
<div class="circle-name">@item.Name</div>
|
||||
<div>@item.MakerId</div>
|
||||
</div>
|
||||
|
||||
@if (item.Favorite)
|
||||
{
|
||||
<MudChip T="string" Label="true" Color="Color.Info" Style="width: 100%" Variant="Variant.Outlined">Favorite</MudChip>
|
||||
@@ -195,7 +197,7 @@ else
|
||||
.circle-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
padding: .5rem;
|
||||
border-width: 2px;
|
||||
border-top-color: #353B4C;
|
||||
border-left-color: #212630;
|
||||
@@ -204,8 +206,23 @@ else
|
||||
border-radius: 30px;
|
||||
background-image: linear-gradient(0deg, #1C2029, #1C1F28);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 100px 100px 100px 100px;
|
||||
grid-column-gap: 2rem;
|
||||
grid-template-columns: auto 1fr 100px 100px 100px 100px;
|
||||
grid-column-gap: 1rem;
|
||||
}
|
||||
|
||||
.j-circle-image-container-2 {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.j-circle-image-2 {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
background-color: black;
|
||||
border: 1px solid #949494;
|
||||
box-sizing: border-box;
|
||||
border-radius: 100%;
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
.circle-name {
|
||||
|
||||
@@ -1,70 +1,84 @@
|
||||
@page "/"
|
||||
@inject VoiceWorksClient Client
|
||||
@using JSMR.Application.VoiceWorks.Queries.Search
|
||||
@using JSMR.UI.Blazor.Components
|
||||
@using JSMR.UI.Blazor.Services
|
||||
|
||||
<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>
|
||||
}
|
||||
<JProductCollection Products="availableVoiceWorks"></JProductCollection>
|
||||
</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>
|
||||
}
|
||||
<JProductCollection Products="upcomingVoiceWorks"></JProductCollection>
|
||||
</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>
|
||||
}
|
||||
<JProductCollection Products="announcedVoiceWorks"></JProductCollection>
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
|
||||
<style>
|
||||
.j-product-items-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.j-voice-work-card {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
background-image: linear-gradient(0deg, rgb(30, 53, 69), rgb(39, 59, 73));
|
||||
border-color: rgb(63, 78, 88);
|
||||
background-image: linear-gradient(0deg, rgb(30, 53, 69), rgb(57, 79, 94));
|
||||
}
|
||||
|
||||
.j-voice-work-image-container {
|
||||
width: 240px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-image-container {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.j-voice-work-image {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.j-voice-work-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.j-product-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
font-family: "Poppins", "M+ 1p";
|
||||
color: #d2dce6;
|
||||
text-shadow: 1px 1px 2px black;
|
||||
}
|
||||
|
||||
.j-product-description {
|
||||
/* color: #7C8099; */
|
||||
font-size: 1rem;
|
||||
font-family: "Poppins", "M+ 1p";
|
||||
}
|
||||
|
||||
.j-voice-work-info {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-info {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
VoiceWorkSearchResult[]? availableVoiceWorks;
|
||||
VoiceWorkSearchResult[]? upcomingVoiceWorks;
|
||||
@@ -143,7 +157,7 @@
|
||||
},
|
||||
SortOptions =
|
||||
[
|
||||
//new(VoiceWorkSortField.Fa, Application.Common.Search.SortDirection.Ascending),
|
||||
new(VoiceWorkSortField.FavoriteCircle, Application.Common.Search.SortDirection.Ascending),
|
||||
new(VoiceWorkSortField.WishlistCount, Application.Common.Search.SortDirection.Descending)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@page "/voiceworks"
|
||||
@using JSMR.Application.VoiceWorks.Queries.Search
|
||||
@using JSMR.UI.Blazor.Components
|
||||
@using JSMR.UI.Blazor.Services
|
||||
@inject VoiceWorksClient Client
|
||||
|
||||
@@ -7,26 +8,10 @@
|
||||
|
||||
<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>
|
||||
}
|
||||
<JProductCollection Products="items"></JProductCollection>
|
||||
|
||||
@code {
|
||||
List<VoiceWorkSearchResult>? items;
|
||||
VoiceWorkSearchResult[]? items;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -36,12 +21,6 @@ else
|
||||
|
||||
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();
|
||||
items = result?.Results.Items ?? [];
|
||||
}
|
||||
}
|
||||
@@ -41,19 +41,15 @@ public static class ImageUrlProvider
|
||||
|
||||
var imageUrlTemplate = "//img.dlsite.jp/[folder]/images2/[imageType1]/[imageWorkType]/[fullRoundedProductId]/[productId][imageType2]_img_[imageSize].jpg";
|
||||
|
||||
var productIdWithoutPrefixString = productId.Substring(2);
|
||||
string productIdWithoutPrefixString = productId.Substring(2);
|
||||
int productIdWithoutPrefix = Convert.ToInt32(productId.Substring(2));
|
||||
|
||||
string productIdPrefix = productId.Substring(0, 2);
|
||||
|
||||
double something = (double)((productIdWithoutPrefix / 1000) * 1000);
|
||||
int roundedProductId = (int)Math.Round(Math.Ceiling((double)productIdWithoutPrefix / 1000) * 1000);
|
||||
|
||||
//string actualRoundedProductId = ("000000" + roundedProductId.ToString()).Substring(roundedProductId.ToString().Length);
|
||||
//string fullRoundedProductId = productIdPrefix + actualRoundedProductId;
|
||||
|
||||
var productIdWithPrefixStringLength = productIdWithoutPrefixString.Length;
|
||||
var zeroPadLength = productIdWithPrefixStringLength - roundedProductId.ToString().Length;
|
||||
int productIdWithPrefixStringLength = productIdWithoutPrefixString.Length;
|
||||
int zeroPadLength = productIdWithPrefixStringLength - roundedProductId.ToString().Length;
|
||||
|
||||
var fullRoundedProductId = productIdPrefix.PadRight(productIdPrefix.Length + zeroPadLength, '0') + roundedProductId;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ a, .btn-link {
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
@@ -304,4 +304,100 @@ code {
|
||||
|
||||
.star_rating.mini.star_45::before {
|
||||
background-position: 0 -16px;
|
||||
}
|
||||
|
||||
/* Card */
|
||||
.j-card {
|
||||
padding-top: var(--card-padding-top);
|
||||
padding-bottom: var(--card-padding-bottom);
|
||||
padding-left: var(--card-padding-left);
|
||||
padding-right: var(--card-padding-right);
|
||||
border-width: var(--card-border-width);
|
||||
border-top-color: var(--card-border-top-color);
|
||||
border-left-color: var(--card-border-left-color);
|
||||
border-right-color: var(--card-border-right-color);
|
||||
border-bottom-color: var(--card-border-bottom-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
background-image: var(--card-background-image);
|
||||
}
|
||||
|
||||
/* Image */
|
||||
.j-image-container {
|
||||
|
||||
}
|
||||
|
||||
.j-image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Product */
|
||||
|
||||
.j-product-items-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.j-voice-work-card {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
background-image: linear-gradient(0deg, rgb(30, 53, 69), rgb(39, 59, 73));
|
||||
border-color: rgb(63, 78, 88);
|
||||
background-image: linear-gradient(0deg, rgb(30, 53, 69), rgb(57, 79, 94));
|
||||
}
|
||||
|
||||
.j-voice-work-image-container {
|
||||
width: 240px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-image-container {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.j-voice-work-image {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.j-voice-work-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .5rem;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.j-product-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
font-family: "Poppins", "M+ 1p";
|
||||
color: #d2dce6;
|
||||
text-shadow: 1px 1px 2px black;
|
||||
}
|
||||
|
||||
.j-product-description {
|
||||
/* color: #7C8099; */
|
||||
font-size: 1rem;
|
||||
font-family: "Poppins", "M+ 1p";
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-content > .j-product-description {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.j-voice-work-info {
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.j-voice-work-card > .j-voice-work-info {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Tags */
|
||||
.j-tags {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
:root {
|
||||
--font-family: 'Poppins';
|
||||
--background-color: #131419;
|
||||
--background-color-original: rgb(16, 36, 50);
|
||||
--background-color-backup: #131419;
|
||||
--background-color: rgb(16, 36, 50);
|
||||
--input-background-color: rgb(0,20,34);
|
||||
--input-border-color: #304562;
|
||||
--primary-text-color: rgb(180,200, 214);
|
||||
@@ -22,4 +22,26 @@
|
||||
--product-footer-text-color: rgb(220,230,234);
|
||||
--expected-date-text-color: #ffe073;
|
||||
--planned-date-text-color: #73bdff;
|
||||
--card-padding-top: .5rem;
|
||||
--card-padding-bottom: .5rem;
|
||||
--card-padding-left: .5rem;
|
||||
--card-padding-right: .5rem;
|
||||
--card-background-image: linear-gradient(0deg, #1C2029, #1C1F28);
|
||||
--card-border-radius: 30px;
|
||||
--card-border-width: 2px;
|
||||
--card-border-top-color: #353B4C;
|
||||
--card-border-left-color: #212630;
|
||||
--card-border-right-color: #212531;
|
||||
--card-border-bottom-color: #212530;
|
||||
}
|
||||
|
||||
/*
|
||||
padding: .5rem;
|
||||
border-width: 2px;
|
||||
border-top-color: #353B4C;
|
||||
border-left-color: #212630;
|
||||
border-right-color: #212531;
|
||||
border-bottom-color: #212530;
|
||||
border-radius: 30px;
|
||||
background-image: linear-gradient(0deg, #1C2029, #1C1F28);
|
||||
*/
|
||||
4
JSMR.sln
4
JSMR.sln
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.14.36408.4
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.0.11205.157 d18.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JSMR.Domain", "JSMR.Domain\JSMR.Domain.csproj", "{BC16F228-63B0-4EE6-9B96-19A38A31C125}"
|
||||
EndProject
|
||||
|
||||
Reference in New Issue
Block a user