From f3c9e1d9dae5b37856eddf65ab8d384878a04d64 Mon Sep 17 00:00:00 2001 From: Egamorf Date: Tue, 29 Apr 2025 23:49:11 +0200 Subject: [PATCH] Correct bunch of issues (#36) Reviewed-on: https://gitea.egamorf.com/PRJ-Game-Ideas/game-ideas/pulls/36 --- .drone.yml | 0 .vscode/extensions.json | 12 ----- README.md | 4 +- .../GameIdeas.BlazorApp.csproj | 3 +- .../Components/GameCreationForm.razor.css | 2 +- .../Games/Filter/AdvancedGameFilter.razor.cs | 1 - .../Pages/Games/Filter/GameFilter.razor | 3 +- .../Pages/Games/Filter/GameFilter.razor.css | 2 +- .../Pages/Games/Filter/GameFilterParams.cs | 3 +- .../Pages/Games/Games.razor | 10 ++-- .../Pages/Games/Gateways/GameGateway.cs | 4 +- .../Pages/Games/Header/GameHeader.razor | 45 ----------------- .../Pages/UserMenu/Gateways/AuthGateway.cs | 6 ++- .../Pages/UserMenu/UserMenu.razor.cs | 2 +- .../Pages/Users/Components/UserRow.razor | 5 +- .../Pages/Users/Components/UserRow.razor.cs | 1 + .../Pages/Users/Components/UserRow.razor.css | 20 ++++---- .../Pages/Users/Users.razor | 8 +-- .../Pages/Users/Users.razor.cs | 17 ++++++- .../Pages/Users/Users.razor.css | 2 +- .../Properties/launchSettings.json | 4 +- .../Services/HttpClientService.cs | 14 +++++- .../JwtAuthenticationStateProvider.cs | 13 ++++- .../Components/ButtonAdd/ButtonAdd.razor | 27 ++++++++++ .../Components/ButtonAdd/ButtonAdd.razor.cs} | 11 ++-- .../Components/ButtonAdd/ButtonAdd.razor.css} | 36 ++----------- .../Components/Header/HeaderGameIdeas.razor | 22 ++++++++ .../Header/HeaderGameIdeas.razor.cs | 12 +++++ .../Header/HeaderGameIdeas.razor.css | 28 +++++++++++ .../Components/Search/SearchInput.razor.cs | 3 +- .../Shared/Components/Slider/Slider.razor | 15 +++--- .../Shared/Components/Slider/Slider.razor.css | 21 ++++---- .../Components/SliderRange/SliderRange.razor | 12 ++--- .../SliderRange/SliderRange.razor.cs | 50 ++++++++++++------- .../Constants/GlobalConstants.cs | 6 ++- .../GameIdeas.Shared/Dto/MinMaxDto.cs | 7 +++ .../GameIdeas.WebAPI/GameIdeas.WebAPI.csproj | 1 - 37 files changed, 246 insertions(+), 186 deletions(-) delete mode 100644 .drone.yml delete mode 100644 .vscode/extensions.json delete mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor create mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor rename src/GameIdeas/Client/GameIdeas.BlazorApp/{Pages/Games/Header/GameHeader.razor.cs => Shared/Components/ButtonAdd/ButtonAdd.razor.cs} (82%) rename src/GameIdeas/Client/GameIdeas.BlazorApp/{Pages/Games/Header/GameHeader.razor.css => Shared/Components/ButtonAdd/ButtonAdd.razor.css} (55%) create mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor create mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.cs create mode 100644 src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.css create mode 100644 src/GameIdeas/GameIdeas.Shared/Dto/MinMaxDto.cs diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index e69de29..0000000 diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 728c8f3..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "recommendations": [ - "ms-dotnettools.vscode-dotnet-runtime", - "ms-dotnettools.csharp", - "ms-dotnettools.csdevkit", - "kreativ-software.csharpextensions", - "jorgeserrano.vscode-csharp-snippets", - "mhutchie.git-graph", - "lukas-tr.materialdesignicons-intellisense", - "ms-dotnettools.vscodeintellicode-csharp" - ] -} \ No newline at end of file diff --git a/README.md b/README.md index 3ebce33..5e1b34c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,9 @@ Store your favorite games, intelligent game add, store game files and data, mana . ├── README.md ├── .gitignore -├── .drone.yml (CI/CD) +├── .gitea +│ ├── build-pr.yaml (CI for Pull Request) +│ └── deploy.yaml (CD for deploy on own server) └── src/ ├── Client/ │ └── GameIdeas.BlazorApp diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj b/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj index 79da7a0..b8b0c18 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/GameIdeas.BlazorApp.csproj @@ -1,10 +1,9 @@ - + net9.0 enable enable - 5637e3c4-2341-4bdb-85ec-c75faeee9847 diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.css index f1fb03f..b512d37 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Components/GameCreationForm.razor.css @@ -69,7 +69,7 @@ } .slider { - padding: 0 20px; + margin-right: 20px; align-content: center; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs index 88f9655..9c6b796 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/AdvancedGameFilter.razor.cs @@ -1,5 +1,4 @@ using GameIdeas.BlazorApp.Helpers; -using GameIdeas.BlazorApp.Pages.Games.Header; using GameIdeas.BlazorApp.Shared.Components.Select.Models; using GameIdeas.Resources; using GameIdeas.Shared.Dto; diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor index d128e8f..6faba54 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor @@ -47,8 +47,7 @@
+ @bind-Value="Value.Interest" @bind-Value:after="HandleValueChanged" />
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.css index 748276e..c8cc520 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilter.razor.css @@ -2,7 +2,7 @@ display: flex; flex-direction: row; gap: 8px; - margin: 0 8px; + margin: 0 auto; align-items: center; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs index e2ae78a..b05fd87 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Filter/GameFilterParams.cs @@ -12,8 +12,7 @@ public class GameFilterParams public List? Tags { get; set; } public List? Publishers { get; set; } public List? Developers { get; set; } - public int MinInterest { get; set; } = 1; - public int MaxInterest { get; set; } = 5; + public MinMaxDto Interest { get; set; } = new() { Min = 1, Max = 5 }; public List? ReleaseYears { get; set; } public List? StorageSpaceIds { get; set; } } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Games.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Games.razor index e49ff7f..965d901 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Games.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Games.razor @@ -1,9 +1,10 @@ -@page "/Games" +@page "/" @using GameIdeas.BlazorApp.Layouts @using GameIdeas.BlazorApp.Pages.Games.Components @using GameIdeas.BlazorApp.Pages.Games.Filter -@using GameIdeas.BlazorApp.Pages.Games.Header @using GameIdeas.BlazorApp.Shared.Components +@using GameIdeas.BlazorApp.Shared.Components.ButtonAdd +@using GameIdeas.BlazorApp.Shared.Components.Header @using GameIdeas.BlazorApp.Shared.Components.Popup @using GameIdeas.Resources @@ -11,11 +12,12 @@ @ResourcesKey.GamesIdeas - + - + +
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs index 6494a4f..978d19b 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Gateways/GameGateway.cs @@ -43,8 +43,8 @@ public class GameGateway(IHttpClientService httpClientService) : IGameGateway { CurrentPage = currentPage, Title = filterParams.Title, - MaxInterest = filterParams.MaxInterest, - MinInterest = filterParams.MinInterest, + MaxInterest = filterParams.Interest.Max, + MinInterest = filterParams.Interest.Min, StorageSpaces = filterParams.StorageSpaceIds, DeveloperIds = filterParams.Developers?.Select(d => d.Id ?? 0).ToList(), PublisherIds = filterParams.Publishers?.Select(d => d.Id ?? 0).ToList(), diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor deleted file mode 100644 index 8f02472..0000000 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor +++ /dev/null @@ -1,45 +0,0 @@ -@using GameIdeas.BlazorApp.Pages.Games -@using GameIdeas.BlazorApp.Pages.UserMenu -@using GameIdeas.BlazorApp.Shared.Components.Select -@using GameIdeas.BlazorApp.Shared.Components.Select.Models -@using GameIdeas.BlazorApp.Shared.Models -@using GameIdeas.Resources -@using GameIdeas.Shared.Constants -@using Microsoft.AspNetCore.Components.Authorization - -@inherits ComponentBase - -
- - Game Ideas - - - @ChildContent - - -
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs index 4753e96..97c8804 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/Gateways/AuthGateway.cs @@ -14,8 +14,10 @@ public class AuthGateway(IHttpClientService httpClient, { try { - var token = await httpClient.PostAsync(Endpoints.Auth.Login, userDto); - await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserAuthenticationAsync(token!.Token!); + var token = await httpClient.PostAsync(Endpoints.Auth.Login, userDto) + ?? throw new InvalidOperationException("Could not retrieve token"); + + await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserAuthenticationAsync(token); return true; } catch (Exception) diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/UserMenu.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/UserMenu.razor.cs index b339592..093b70e 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/UserMenu.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/UserMenu/UserMenu.razor.cs @@ -14,7 +14,7 @@ public partial class UserMenu { ContentVisile = false; await AuthGateway.Logout(); - NavigationManager.NavigateTo("/Games"); + NavigationManager.NavigateTo("/"); } private void HandleAccountClicked() diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor index 760e5a1..5b2e99f 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor @@ -23,7 +23,10 @@
- + @if (CanDelete) + { + + } @if (CanEdit) { diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.cs index ebb1ea3..a1e0f28 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.cs @@ -12,6 +12,7 @@ public partial class UserRow [Parameter] public UserDto User { get; set; } = new(); [Parameter] public List Roles { get; set; } = []; [Parameter] public bool CanEdit { get; set; } = true; + [Parameter] public bool CanDelete { get; set; } = true; [Parameter] public bool IsEditing { get; set; } = false; [Parameter] public EventCallback OnRemove { get; set; } [Parameter] public EventCallback OnSubmit { get; set; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.css index b567a84..d82d6f8 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Components/UserRow.razor.css @@ -1,7 +1,7 @@ .row { height: 64px; display: grid; - grid-template-columns: 48px 1fr 1fr 1fr auto; + grid-template-columns: 48px 1fr 1fr 1fr 100px; grid-gap: 8px; padding: 0 8px; background: var(--input-secondary); @@ -9,25 +9,24 @@ border-radius: var(--big-radius); } -.row > * { - align-content: center; -} + .row > * { + align-content: center; + max-width: 160px; + width: 100%; + } .icon ::deep svg { fill: var(--line); } -.role { - min-width: 160px; - width: fit-content; -} - ::deep .input-name, ::deep .input-name[disabled], ::deep .input-password, ::deep .input-password[disabled], ::deep .input-password::placeholder { color: var(--white); + max-width: 160px; + width: 100%; } ::deep .input-name, @@ -61,12 +60,13 @@ flex-direction: row; gap: 8px; height:auto; + justify-content: end; } .buttons > * { border: none; outline: none; - margin: auto; + margin: auto 0; height: 28px; width: 28px; background: none; diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor index 3baff3f..dbf9d6b 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor @@ -1,7 +1,7 @@ @page "/Users" -@using GameIdeas.BlazorApp.Pages.Games.Header @using GameIdeas.BlazorApp.Layouts @using GameIdeas.BlazorApp.Pages.Users.Components +@using GameIdeas.BlazorApp.Shared.Components.Header @using GameIdeas.BlazorApp.Shared.Components.Popup @using GameIdeas.BlazorApp.Shared.Components.Popup.Components @using GameIdeas.BlazorApp.Shared.Components.Search @@ -13,13 +13,13 @@ @ResourcesKey.GamesIdeas - +
-
+
@@ -31,7 +31,7 @@ { @foreach (var user in UserList.Users ?? []) { - + } } else diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.cs index fc26089..bd55aba 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.cs @@ -1,14 +1,19 @@ using GameIdeas.BlazorApp.Pages.Users.Filters; using GameIdeas.BlazorApp.Pages.Users.Gateways; using GameIdeas.BlazorApp.Shared.Components.Popup; +using GameIdeas.Shared.Constants; using GameIdeas.Shared.Dto; using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; +using System.Security.Claims; namespace GameIdeas.BlazorApp.Pages.Users; public partial class Users { [Inject] private IUserGateway UserGateway { get; set; } = default!; + [Inject] private AuthenticationStateProvider StateProvider { get; set; } = default!; + [Inject] private NavigationManager NavigationManager { get; set; } = default!; private Popup? Popup; private bool IsLoading = false; @@ -18,9 +23,19 @@ public partial class Users private int CurrentPage = 1; private UserDto UserAdd = new(); private UserDto? UserDelete; - + private string? currentUserId; protected override async Task OnInitializedAsync() { + var authState = await StateProvider.GetAuthenticationStateAsync(); + currentUserId = authState.User.FindFirstValue(ClaimTypes.Sid); + + if (authState.User.FindFirstValue(ClaimTypes.Role) != GlobalConstants.ADMINISTRATOR || string.IsNullOrEmpty(currentUserId)) + { + NavigationManager.NavigateTo("/Unauthorized"); + return; + } + + await FetchData(); await base.OnInitializedAsync(); } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.css index 0bbbd2d..f306d94 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Users/Users.razor.css @@ -1,6 +1,6 @@ .header-content { + margin: 0 auto; display: flex; - flex-direction: row; gap: 8px; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json b/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json index fccd456..ee255b0 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Properties/launchSettings.json @@ -7,7 +7,7 @@ "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "http://localhost:5172", - "launchUrl": "http://localhost:5172/Games", + "launchUrl": "http://localhost:5172/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } @@ -18,7 +18,7 @@ "launchBrowser": true, "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", "applicationUrl": "https://localhost:7060;http://localhost:5172", - "launchUrl": "http://localhost:7060/Games", + "launchUrl": "http://localhost:7060/", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs index 41c4cf0..cf82e39 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/HttpClientService.cs @@ -5,13 +5,15 @@ using System.Text.Json; using System.Text; using Blazored.LocalStorage; using GameIdeas.Shared.Constants; +using Microsoft.AspNetCore.Components.Authorization; namespace GameIdeas.BlazorApp.Services; public class HttpClientService( IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, - ILocalStorageService localStorage) : IHttpClientService + ILocalStorageService localStorage, + AuthenticationStateProvider stateProvider) : IHttpClientService { private readonly HttpClient httpClient = httpClientFactory.CreateClient("GameIdeas.WebAPI"); private readonly ILogger logger = loggerFactory.CreateLogger(); @@ -141,6 +143,16 @@ public class HttpClientService( private async Task SetAuthorizationHeader() { + var expired = await localStorage.GetItemAsStringAsync(GlobalConstants.LS_EXPIRED_STORAGE_KEY); + + if (expired == null + || (DateTime.TryParse(expired, out DateTime expiration) + && expiration < DateTime.UtcNow)) + { + await ((JwtAuthenticationStateProvider)stateProvider).NotifyUserLogoutAsync(); + return; + } + var token = await localStorage.GetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token); diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs index 6ea212f..20eadc9 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Services/JwtAuthenticationStateProvider.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components.Authorization; using System.Security.Claims; using System.IdentityModel.Tokens.Jwt; using GameIdeas.Shared.Constants; +using GameIdeas.Shared.Dto; namespace GameIdeas.BlazorApp.Services; @@ -31,9 +32,17 @@ public class JwtAuthenticationStateProvider(ILocalStorageService localStorage) : return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } - public async Task NotifyUserAuthenticationAsync(string token) + public async Task NotifyUserAuthenticationAsync(TokenDto token) { - await localStorage.SetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY, token); + if (token?.Token != null) + { + await localStorage.SetItemAsStringAsync(GlobalConstants.LS_AUTH_STORAGE_KEY, token.Token); + } + + if (token?.Expiration != null) + { + await localStorage.SetItemAsStringAsync(GlobalConstants.LS_EXPIRED_STORAGE_KEY, token.Expiration.Value.ToString()); + } NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor new file mode 100644 index 0000000..2780524 --- /dev/null +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor @@ -0,0 +1,27 @@ +@using GameIdeas.BlazorApp.Shared.Components.Select +@using GameIdeas.BlazorApp.Shared.Components.Select.Models +@using GameIdeas.Shared.Constants +@using GameIdeas.BlazorApp.Shared.Models +@using Microsoft.AspNetCore.Components.Authorization + + + +
+
+ + + +
+ +
+
+
+ + diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.cs similarity index 82% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.cs index 3249a21..a20fa75 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.cs @@ -1,17 +1,14 @@ -using GameIdeas.BlazorApp.Shared.Components.Select; using GameIdeas.BlazorApp.Shared.Components.Select.Models; +using GameIdeas.BlazorApp.Shared.Components.Select; using GameIdeas.BlazorApp.Shared.Models; using GameIdeas.Resources; using Microsoft.AspNetCore.Components; -namespace GameIdeas.BlazorApp.Pages.Games.Header; +namespace GameIdeas.BlazorApp.Shared.Components.ButtonAdd; -public partial class GameHeader : ComponentBase +public partial class ButtonAdd { - [Parameter] public bool DisplayAdd { get; set; } = true; [Parameter] public EventCallback AddTypeChanged { get; set; } - [Parameter] public RenderFragment? ChildContent { get; set; } - private readonly Dictionary AddTypes = new() { { AddType.Manual, ResourcesKey.ManualAdd }, @@ -37,4 +34,4 @@ public partial class GameHeader : ComponentBase SelectListAdd?.Close(); await AddTypeChanged.InvokeAsync(values.FirstOrDefault().Key); } -} +} \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.css similarity index 55% rename from src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.css rename to src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.css index 4b6f742..5e1a04e 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Pages/Games/Header/GameHeader.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/ButtonAdd/ButtonAdd.razor.css @@ -1,40 +1,10 @@ -.header-tab { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: flex-end; - padding: 0px 10px; - height: 40px; -} - -.icon-container { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - width: 40px; - height: 100%; - cursor: pointer; -} - - .icon-container img { - max-height: 85%; - max-width: 85%; - } - -.account-add-container { - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: flex-end; -} - -.add-buttons { +.add-buttons { display: flex; flex-direction: row; background: var(--violet); border-radius: var(--small-radius); margin-right: 40px; + margin-left: 8px; } .button { @@ -64,4 +34,4 @@ .button-icon:hover { background: var(--violet-selected); cursor: pointer; - } \ No newline at end of file + } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor new file mode 100644 index 0000000..f83d69b --- /dev/null +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor @@ -0,0 +1,22 @@ + @using GameIdeas.BlazorApp.Pages.Games +@using GameIdeas.BlazorApp.Pages.UserMenu +@using GameIdeas.BlazorApp.Shared.Components.Select +@using GameIdeas.BlazorApp.Shared.Components.Select.Models +@using GameIdeas.BlazorApp.Shared.Models +@using GameIdeas.Resources +@using GameIdeas.Shared.Constants +@using Microsoft.AspNetCore.Components.Authorization + +@inherits ComponentBase + +
+ + Game Ideas + + +
+ @ChildContent +
+ + +
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.cs new file mode 100644 index 0000000..1939cb3 --- /dev/null +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.cs @@ -0,0 +1,12 @@ +using GameIdeas.BlazorApp.Shared.Components.Select; +using GameIdeas.BlazorApp.Shared.Components.Select.Models; +using GameIdeas.BlazorApp.Shared.Models; +using GameIdeas.Resources; +using Microsoft.AspNetCore.Components; + +namespace GameIdeas.BlazorApp.Shared.Components.Header; + +public partial class HeaderGameIdeas : ComponentBase +{ + [Parameter] public RenderFragment? ChildContent { get; set; } +} diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.css new file mode 100644 index 0000000..6a501b0 --- /dev/null +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Header/HeaderGameIdeas.razor.css @@ -0,0 +1,28 @@ +.header-tab { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: flex-end; + padding: 0px 10px; + height: 40px; +} + +.icon-container { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + width: 40px; + height: 100%; + cursor: pointer; +} + + .icon-container img { + max-height: 85%; + max-width: 85%; + } + +.content { + width: 100%; + display: flex; +} \ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs index f6521df..139726c 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Search/SearchInput.razor.cs @@ -1,4 +1,5 @@ using GameIdeas.BlazorApp.Shared.Constants; +using GameIdeas.Shared.Constants; using Microsoft.AspNetCore.Components; namespace GameIdeas.BlazorApp.Shared.Components.Search; @@ -21,7 +22,7 @@ public partial class SearchInput Text = string.Empty; Timer = new() { - Interval = 500, + Interval = GlobalConstants.DELAY_INPUT_MS, AutoReset = false, }; diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor index d4db8aa..59f2110 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor @@ -1,11 +1,10 @@ 
-
- - +
+
-
- @Params.Min - @Params.Max +
-
+ + @Value +
\ No newline at end of file diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor.css b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor.css index 09c613a..09a6339 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor.css +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/Slider/Slider.razor.css @@ -1,7 +1,7 @@ -.container { - position: relative; +.input { width: 100%; - z-index: 0 + position: relative; + height: 2px; } input[type="range"] { @@ -24,7 +24,6 @@ input[type="range"] { margin: auto; border-radius: 2px; background: var(--input-primary); - } input[type="range"]::-webkit-slider-runnable-track { @@ -75,15 +74,13 @@ input[type="range"]::-ms-thumb { } .values { - display: flex; - position: absolute; - margin-top: 2px; - width: 100%; font-weight: bold; - justify-content: space-between; + width: 1em; } -.value { - width: 1em; - text-align:center; +.container { + gap: 8px; + width: 100%; + display: flex; + align-items: center; } diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor index ca54e27..c143332 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor @@ -1,13 +1,13 @@ 
- - + +
- @Min - @Max + @Value.Min + @Value.Max
diff --git a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs index 2fee237..64ce34a 100644 --- a/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs +++ b/src/GameIdeas/Client/GameIdeas.BlazorApp/Shared/Components/SliderRange/SliderRange.razor.cs @@ -1,44 +1,58 @@ +using GameIdeas.Shared.Constants; +using GameIdeas.Shared.Dto; using Microsoft.AspNetCore.Components; -using System.Threading.Tasks; - namespace GameIdeas.BlazorApp.Shared.Components.SliderRange; public partial class SliderRange { [Parameter] public SliderRangeParams Params { get; set; } = new(); - [Parameter] public int Max { get; set; } - [Parameter] public EventCallback MaxChanged { get; set; } - [Parameter] public int Min { get; set; } - [Parameter] public EventCallback MinChanged { get; set; } + [Parameter] public MinMaxDto Value { get; set; } = new() { Min = 1, Max = 5 }; + [Parameter] public EventCallback ValueChanged { get; set; } - private async Task HandleSlideTwoInput() + private System.Timers.Timer? Timer; + + protected override void OnInitialized() { - if (Max - Min <= Params.Gap) + Timer = new() { - Min = Max - Params.Gap; - } + Interval = GlobalConstants.DELAY_INPUT_MS, + AutoReset = false, + }; - await MaxChanged.InvokeAsync(Max); + Timer.Elapsed += async (_, _) => await ValueChanged.InvokeAsync(Value); + base.OnInitialized(); } - private async Task HandleSlideOnInput() + private void HandleSlideTwoInput() { - if (Max - Min <= Params.Gap) + if (Value.Max - Value.Min <= Params.Gap) { - Max = Min + Params.Gap; + Value.Min = Value.Max - Params.Gap; } - await MinChanged.InvokeAsync(Min); + Timer?.Stop(); + Timer?.Start(); + } + + private void HandleSlideOnInput() + { + if (Value.Max - Value.Min <= Params.Gap) + { + Value.Max = Value.Min + Params.Gap; + } + + Timer?.Stop(); + Timer?.Start(); } private string FillColor() { - var percent1 = (double)(Min - Params.Min) / (Params.Max - Params.Min) * 100; - var percent2 = (double)(Max - Params.Min) / (Params.Max - Params.Min) * 100; + var percent1 = (double?)(Value.Min - Params.Min) / (Params.Max - Params.Min) * 100; + var percent2 = (double?)(Value.Max - Params.Min) / (Params.Max - Params.Min) * 100; return $"background: linear-gradient(to right, var(--line) {percent1}% , var(--violet) {percent1}% , var(--violet) {percent2}%, var(--line) {percent2}%)"; } - private string StatusColor(int value) + private string StatusColor(int? value) { string str = "--thumb-color: var({0});"; diff --git a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs index 6bacc90..86a6cd6 100644 --- a/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs +++ b/src/GameIdeas/GameIdeas.Shared/Constants/GlobalConstants.cs @@ -12,13 +12,15 @@ public class GlobalConstants public const string MEMBER_NORMALIZED = "MEMBRE"; public const string ADMIN_MEMBER = $"{ADMINISTRATOR}, {MEMBER}"; - public const int JWT_DURATION_HOUR = 12; + public const int JWT_DURATION_HOUR = 168; public const int NUMBER_PER_PAGE = 50; public const string LS_AUTH_STORAGE_KEY = "authToken"; + public const string LS_EXPIRED_STORAGE_KEY = "expiredToken"; public const int API_PORT = 8000; public const string SUB_DOMAIN_NAME = "api-"; + + public const double DELAY_INPUT_MS = 500; } - \ No newline at end of file diff --git a/src/GameIdeas/GameIdeas.Shared/Dto/MinMaxDto.cs b/src/GameIdeas/GameIdeas.Shared/Dto/MinMaxDto.cs new file mode 100644 index 0000000..81de49d --- /dev/null +++ b/src/GameIdeas/GameIdeas.Shared/Dto/MinMaxDto.cs @@ -0,0 +1,7 @@ +namespace GameIdeas.Shared.Dto; + +public class MinMaxDto +{ + public int? Min { get; set; } + public int? Max { get; set; } +} diff --git a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj index 644ced5..32e89b5 100644 --- a/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj +++ b/src/GameIdeas/Server/GameIdeas.WebAPI/GameIdeas.WebAPI.csproj @@ -4,7 +4,6 @@ net9.0 enable enable - c5ccfd3a-f458-4660-b6c4-81fcc2513737