diff --git a/.github/workflows/pkg.yaml b/.github/workflows/pkg.yaml index e053a8c3..bdc85fb7 100644 --- a/.github/workflows/pkg.yaml +++ b/.github/workflows/pkg.yaml @@ -28,7 +28,7 @@ jobs: permissions: id-token: write contents: read - uses: devpro/github-workflow-parts/.github/workflows/reusable-container-publication.yml@62dbf6e833e49230ab34ef3c44093ebb727a095f + uses: devpro/github-workflow-parts/.github/workflows/reusable-container-publication.yml@4f3152777635eb3bcf1ee21db103d70f790ff1cb with: create-latest: ${{ github.ref_name == 'main' }} image-definition: ${{ matrix.image-definition }} diff --git a/Directory.Packages.props b/Directory.Packages.props index a9d925a0..068affa9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,25 +4,25 @@ true - + - - - - - - - + + + + + + + - + diff --git a/README.md b/README.md index 73dd74d2..f54abab1 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=devpro_keeptrack&metric=alert_status)](https://sonarcloud.io/dashboard?id=devpro_keeptrack) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=devpro_keeptrack&metric=coverage)](https://sonarcloud.io/dashboard?id=devpro_keeptrack) [![Docker Image Version](https://img.shields.io/docker/v/devprofr/keeptrack-blazorapp?label=Image&logo=docker)](https://hub.docker.com/r/devprofr/keeptrack-blazorapp) + [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B60068%2Fgithub.com%2Fdevpro%2Fkeeptrack.svg?type=shield&issueType=license)](https://app.fossa.com/projects/custom%2B60068%2Fgithub.com%2Fdevpro%2Fkeeptrack?ref=badge_shield&issueType=license) [![FOSSA Status](https://app.fossa.com/api/projects/custom%2B60068%2Fgithub.com%2Fdevpro%2Fkeeptrack.svg?type=shield&issueType=security)](https://app.fossa.com/projects/custom%2B60068%2Fgithub.com%2Fdevpro%2Fkeeptrack?ref=badge_shield&issueType=security) diff --git a/src/BlazorApp/Components/Inventory/Clients/MoviesApiClient.cs b/src/BlazorApp/Components/Inventory/Clients/MovieApiClient.cs similarity index 80% rename from src/BlazorApp/Components/Inventory/Clients/MoviesApiClient.cs rename to src/BlazorApp/Components/Inventory/Clients/MovieApiClient.cs index e1b12b6f..2773d99c 100644 --- a/src/BlazorApp/Components/Inventory/Clients/MoviesApiClient.cs +++ b/src/BlazorApp/Components/Inventory/Clients/MovieApiClient.cs @@ -2,7 +2,7 @@ namespace Keeptrack.BlazorApp.Components.Inventory.Clients; -public sealed class MoviesApiClient(HttpClient http) +public sealed class MovieApiClient(HttpClient http) : InventoryApiClientBase(http) { protected override string ApiResourceName => "/api/movies"; diff --git a/src/BlazorApp/Components/Inventory/Clients/MusicAlbumApiClient.cs b/src/BlazorApp/Components/Inventory/Clients/MusicAlbumApiClient.cs new file mode 100644 index 00000000..9b7e5db7 --- /dev/null +++ b/src/BlazorApp/Components/Inventory/Clients/MusicAlbumApiClient.cs @@ -0,0 +1,9 @@ +using Keeptrack.WebApi.Contracts.Dto; + +namespace Keeptrack.BlazorApp.Components.Inventory.Clients; + +public sealed class MusicAlbumApiClient(HttpClient http) + : InventoryApiClientBase(http) +{ + protected override string ApiResourceName => "/api/movies"; +} diff --git a/src/BlazorApp/Components/Inventory/Pages/Books.razor b/src/BlazorApp/Components/Inventory/Pages/Books.razor index 4770787c..c22b772c 100644 --- a/src/BlazorApp/Components/Inventory/Pages/Books.razor +++ b/src/BlazorApp/Components/Inventory/Pages/Books.razor @@ -31,24 +31,51 @@ Title Author Series + Rating Finished at @book.Title @book.Author @book.Series - @book.FinishedAt?.ToString("yyyy-MM-dd") + + @book.FirstReadAt?.ToString("yyyy-MM-dd") - + + - - - - - - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
diff --git a/src/BlazorApp/Components/Inventory/Pages/Books.razor.cs b/src/BlazorApp/Components/Inventory/Pages/Books.razor.cs index 1d224898..18779d50 100644 --- a/src/BlazorApp/Components/Inventory/Pages/Books.razor.cs +++ b/src/BlazorApp/Components/Inventory/Pages/Books.razor.cs @@ -14,7 +14,10 @@ public partial class Books : InventoryPageBase Id = item.Id, Title = item.Title, Author = item.Author, - FinishedAt = item.FinishedAt, - Series = item.Series + Series = item.Series, + Genre = item.Genre, + Rating = item.Rating, + Notes = item.Notes, + FirstReadAt = item.FirstReadAt }; } diff --git a/src/BlazorApp/Components/Inventory/Pages/Movies.razor b/src/BlazorApp/Components/Inventory/Pages/Movies.razor index 180091a7..5363faed 100644 --- a/src/BlazorApp/Components/Inventory/Pages/Movies.razor +++ b/src/BlazorApp/Components/Inventory/Pages/Movies.razor @@ -30,54 +30,46 @@ Title Year - Genre Rating - Notes + First seen @movie.Title - @(movie.Year > 0 ? movie.Year : "—") - @(string.IsNullOrEmpty(movie.Genre) ? "—" : movie.Genre) - - @if (movie.Rating > 0) - { - - @(new string('★', movie.Rating ?? 0))@(new string('★', 5 - (movie.Rating ?? 0))) - - } - else - { - - } - - @(string.IsNullOrEmpty(movie.Notes) ? "—" : movie.Notes) + @(movie.Year > 0 ? movie.Year : "") + + @movie.FirstSeenAt?.ToString("yyyy-MM-dd") - + - - + + - - - - - - - - - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
diff --git a/src/BlazorApp/Components/Inventory/Pages/Movies.razor.cs b/src/BlazorApp/Components/Inventory/Pages/Movies.razor.cs index 494c5dca..e60a55aa 100644 --- a/src/BlazorApp/Components/Inventory/Pages/Movies.razor.cs +++ b/src/BlazorApp/Components/Inventory/Pages/Movies.razor.cs @@ -5,7 +5,7 @@ namespace Keeptrack.BlazorApp.Components.Inventory.Pages; public partial class Movies : InventoryPageBase { - [Inject] private MoviesApiClient MovieApi { get; set; } = null!; + [Inject] private MovieApiClient MovieApi { get; set; } = null!; protected override InventoryApiClientBase Api => MovieApi; @@ -16,6 +16,9 @@ public partial class Movies : InventoryPageBase Year = item.Year, Genre = item.Genre, Rating = item.Rating, - Notes = item.Notes + Notes = item.Notes, + FirstSeenAt = item.FirstSeenAt, + AllocineId = item.AllocineId, + ImdbPageId = item.ImdbPageId }; } diff --git a/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor b/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor new file mode 100644 index 00000000..026a0278 --- /dev/null +++ b/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor @@ -0,0 +1,67 @@ +@page "/music-albums" +@inherits InventoryPageBase +@rendermode InteractiveServer +@attribute [Authorize] + + + + Title + Artist + Rating + + + @album.Title + @album.Artist + + + + + + + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
diff --git a/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor.cs b/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor.cs new file mode 100644 index 00000000..8ff0ed0b --- /dev/null +++ b/src/BlazorApp/Components/Inventory/Pages/MusicAlbums.razor.cs @@ -0,0 +1,21 @@ +using Keeptrack.WebApi.Contracts.Dto; +using Microsoft.AspNetCore.Components; + +namespace Keeptrack.BlazorApp.Components.Inventory.Pages; + +public partial class MusicAlbums : InventoryPageBase +{ + [Inject] private MusicAlbumApiClient MusicAlbumApi { get; set; } = null!; + + protected override InventoryApiClientBase Api => MusicAlbumApi; + + protected override MusicAlbumDto CloneItem(MusicAlbumDto item) => new() + { + Id = item.Id, + Title = item.Title, + Artist = item.Artist, + Genre = item.Genre, + Year = item.Year, + Rating = item.Rating + }; +} diff --git a/src/BlazorApp/Components/Inventory/Pages/TvShows.razor b/src/BlazorApp/Components/Inventory/Pages/TvShows.razor index e95c7132..c963dbab 100644 --- a/src/BlazorApp/Components/Inventory/Pages/TvShows.razor +++ b/src/BlazorApp/Components/Inventory/Pages/TvShows.razor @@ -4,7 +4,7 @@ @attribute [Authorize] Title + Last episode seen + Rating - - @movie.Title + + @show.Title + @show.LastEpisodeSeen + - - + + + + - - - + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
diff --git a/src/BlazorApp/Components/Inventory/Pages/TvShows.razor.cs b/src/BlazorApp/Components/Inventory/Pages/TvShows.razor.cs index 02985a07..471c5e09 100644 --- a/src/BlazorApp/Components/Inventory/Pages/TvShows.razor.cs +++ b/src/BlazorApp/Components/Inventory/Pages/TvShows.razor.cs @@ -12,6 +12,13 @@ public partial class TvShows : InventoryPageBase protected override TvShowDto CloneItem(TvShowDto item) => new() { Id = item.Id, - Title = item.Title + Title = item.Title, + Rating = item.Rating, + AllocineId = item.AllocineId, + ImdbPageId = item.ImdbPageId, + Notes = item.Notes, + FinishedAt = item.FinishedAt, + LastEpisodeSeen = item.LastEpisodeSeen, + Year = item.Year }; } diff --git a/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor b/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor index aa548099..721abfd2 100644 --- a/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor +++ b/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor @@ -4,7 +4,7 @@ @attribute [Authorize] Title Platform State - Released + Rating Finished @game.Title @game.Platform @game.State - @game.ReleasedAt?.ToString("yyyy-MM-dd") + @game.FinishedAt?.ToString("yyyy-MM-dd") @@ -63,12 +63,16 @@ - - + + - - - + +
+ + +
+
+ - - - + - - - - +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
diff --git a/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor.cs b/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor.cs index c555a408..c5484b3f 100644 --- a/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor.cs +++ b/src/BlazorApp/Components/Inventory/Pages/VideoGames.razor.cs @@ -14,8 +14,10 @@ public partial class VideoGames : InventoryPageBase Id = item.Id, Title = item.Title, Platform = item.Platform, - ReleasedAt = item.ReleasedAt, State = item.State, - FinishedAt = item.FinishedAt + FinishedAt = item.FinishedAt, + Notes = item.Notes, + Rating = item.Rating, + Year = item.Year }; } diff --git a/src/BlazorApp/Components/Inventory/Shared/InventoryList.razor b/src/BlazorApp/Components/Inventory/Shared/InventoryList.razor index e9d43d8e..7824411d 100644 --- a/src/BlazorApp/Components/Inventory/Shared/InventoryList.razor +++ b/src/BlazorApp/Components/Inventory/Shared/InventoryList.razor @@ -5,10 +5,31 @@ } +@if (_showModal) +{ +
+
+
+
Edit item
+ +
+
+
+ @EditModalTemplate(InlineForm) +
+
+ +
+
+} + @if (ShowForm) {
-
@(Form.Id is null ? "New item" : "Edit item")
+
New item
@FormTemplate(Form)
@@ -60,30 +81,15 @@ else @foreach (var item in Items) { - @if (EditingInline?.Id == item.Id) - { - - @InlineEditTemplate(InlineForm) - -
- - -
- - - } - else - { - - @RowTemplate(item) - -
- - -
- - - } + + @RowTemplate(item) + +
+ + +
+ + } @@ -99,14 +105,47 @@ else @if (TotalPages > 1) {
- - @for (var p = 1; p <= TotalPages; p++) + + + @{ + int start, end; + if (TotalPages <= 3) + { + start = 1; + end = TotalPages; + } + else if (Page <= 2) + { + start = 1; + end = 3; + } + else if (Page >= TotalPages - 1) + { + start = TotalPages - 2; + end = TotalPages; + } + else + { + start = Page - 1; + end = Page + 1; + } + } + @for (var p = start; p <= end; p++) { var pageNum = p; } - + + @TotalCount results
} @@ -116,6 +155,8 @@ else @code { private bool _initialized; private string _localSearch = ""; + private bool _showModal; + private bool _mouseDownOnBackdrop; protected override void OnParametersSet() { @@ -137,6 +178,39 @@ else await OnClearSearch.InvokeAsync(); } + private async Task OpenEditModal(TDto item) + { + await OnStartInlineEdit.InvokeAsync(item); + _showModal = true; + } + + private async Task OnSaveModal() + { + await OnSaveInline.InvokeAsync(); + _showModal = false; + } + + private async Task OnCancelModal() + { + _showModal = false; + await OnCancelInline.InvokeAsync(); + } + + private void HandleBackdropMouseDown() + { + _mouseDownOnBackdrop = true; + } + + private async Task HandleBackdropClick() + { + if (_mouseDownOnBackdrop) + { + _mouseDownOnBackdrop = false; + await OnCancelModal(); + } + _mouseDownOnBackdrop = false; + } + [Parameter] public required string Title { get; set; } [Parameter] public required List Items { get; set; } [Parameter] public required TDto Form { get; set; } @@ -152,7 +226,7 @@ else [Parameter] public required RenderFragment HeaderTemplate { get; set; } [Parameter] public required RenderFragment RowTemplate { get; set; } [Parameter] public required RenderFragment FormTemplate { get; set; } - [Parameter] public required RenderFragment InlineEditTemplate { get; set; } + [Parameter] public required RenderFragment EditModalTemplate { get; set; } [Parameter] public required EventCallback OnSave { get; set; } [Parameter] public required EventCallback OnCancelForm { get; set; } [Parameter] public required EventCallback OnShowAddForm { get; set; } diff --git a/src/BlazorApp/Components/Inventory/Shared/StarRating.razor b/src/BlazorApp/Components/Inventory/Shared/StarRating.razor new file mode 100644 index 00000000..af9979db --- /dev/null +++ b/src/BlazorApp/Components/Inventory/Shared/StarRating.razor @@ -0,0 +1,15 @@ +@for (var i = 1; i <= 5; i++) +{ + +} + +@code { + [Parameter] public float? Rating { get; set; } + + private string GetStarClass(int position) + { + var rating = Rating ?? 0; + if (rating >= position) return "full"; + return rating >= position - 0.5f ? "half" : "empty"; + } +} diff --git a/src/BlazorApp/Components/Layout/NavMenu.razor b/src/BlazorApp/Components/Layout/NavMenu.razor index 7e8e6535..66a22a47 100644 --- a/src/BlazorApp/Components/Layout/NavMenu.razor +++ b/src/BlazorApp/Components/Layout/NavMenu.razor @@ -24,6 +24,11 @@ 🎬 Movies
+