diff --git a/Moonlight.ApiServer/Moonlight.ApiServer.csproj b/Moonlight.ApiServer/Moonlight.ApiServer.csproj index c3acad43..cd92652b 100644 --- a/Moonlight.ApiServer/Moonlight.ApiServer.csproj +++ b/Moonlight.ApiServer/Moonlight.ApiServer.csproj @@ -17,6 +17,7 @@ + diff --git a/Moonlight.Client/Implementations/AuthenticationUiHandler.cs b/Moonlight.Client/Implementations/AuthenticationUiHandler.cs index fef8e2ad..95de0d66 100644 --- a/Moonlight.Client/Implementations/AuthenticationUiHandler.cs +++ b/Moonlight.Client/Implementations/AuthenticationUiHandler.cs @@ -14,7 +14,7 @@ public class AuthenticationUiHandler : IAppLoader, IAppScreen { var identityService = serviceProvider.GetRequiredService(); - return Task.FromResult(identityService.IsLoggedIn); + return Task.FromResult(!identityService.IsLoggedIn); // Only show the screen when we are not logged in } public RenderFragment Render() => ComponentHelper.FromType(); diff --git a/Moonlight.Client/Interfaces/IAppLoader.cs b/Moonlight.Client/Interfaces/IAppLoader.cs index f1e2b5e0..4cc8c280 100644 --- a/Moonlight.Client/Interfaces/IAppLoader.cs +++ b/Moonlight.Client/Interfaces/IAppLoader.cs @@ -1,3 +1,5 @@ +using Moonlight.Client.UI.Layouts; + namespace Moonlight.Client.Interfaces; public interface IAppLoader diff --git a/Moonlight.Client/Moonlight.Client.csproj b/Moonlight.Client/Moonlight.Client.csproj index bc3f6ec7..bc029be0 100644 --- a/Moonlight.Client/Moonlight.Client.csproj +++ b/Moonlight.Client/Moonlight.Client.csproj @@ -11,7 +11,7 @@ - + @@ -29,4 +29,10 @@ + + + ..\..\..\..\GitHub\Marcel-Baumgartner\MoonCore\MoonCore\MoonCore.Blazor.Tailwind\bin\Debug\net8.0\MoonCore.Blazor.Tailwind.dll + + + diff --git a/Moonlight.Client/Program.cs b/Moonlight.Client/Program.cs index b947e06c..696c47d9 100644 --- a/Moonlight.Client/Program.cs +++ b/Moonlight.Client/Program.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using MoonCore.Blazor.Tailwind.Extensions; +using MoonCore.Blazor.Tailwind.Forms; +using MoonCore.Blazor.Tailwind.Forms.Components; using MoonCore.Extensions; using MoonCore.Helpers; using MoonCore.PluginFramework.Services; @@ -48,8 +50,13 @@ builder.RootComponents.Add("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddScoped(sp => new HttpApiClient(sp.GetRequiredService())); +builder.Services.AutoAddServices(); + builder.Services.AddMoonCoreBlazorTailwind(); +FormComponentRepository.Set(); +FormComponentRepository.Set(); + // Implementation service var implementationService = new ImplementationService(); diff --git a/Moonlight.Client/Services/IdentityService.cs b/Moonlight.Client/Services/IdentityService.cs index 46fdb9ff..a5491d8c 100644 --- a/Moonlight.Client/Services/IdentityService.cs +++ b/Moonlight.Client/Services/IdentityService.cs @@ -1,3 +1,4 @@ +using MoonCore.Attributes; using MoonCore.Blazor.Tailwind.Services; using MoonCore.Exceptions; using MoonCore.Helpers; @@ -5,6 +6,7 @@ using Moonlight.Shared.Http.Responses.Auth; namespace Moonlight.Client.Services; +[Scoped] public class IdentityService { public string Username { get; private set; } @@ -40,7 +42,7 @@ public class IdentityService IsLoggedIn = false; } - await OnStateChanged(); + //await OnStateChanged?.Invoke(); } public async Task Login(string token) diff --git a/Moonlight.Client/Styles/style.css b/Moonlight.Client/Styles/style.css index ca2a44da..a82a8fff 100644 --- a/Moonlight.Client/Styles/style.css +++ b/Moonlight.Client/Styles/style.css @@ -12,4 +12,66 @@ #blazor-error-ui { display: none; +} + +#loader { + display: block; + width: 10rem; + height: 10rem; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #9370DB; + -webkit-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; + @apply border-t-primary-500 +} +#loader:before { + content: ""; + position: absolute; + top: 5px; + left: 5px; + right: 5px; + bottom: 5px; + border-radius: 50%; + border: 3px solid transparent; + -webkit-animation: spin 3s linear infinite; + animation: spin 3s linear infinite; + @apply border-t-tertiary-500 +} +#loader:after { + content: ""; + position: absolute; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + border-radius: 50%; + border: 3px solid transparent; + -webkit-animation: spin 1.5s linear infinite; + animation: spin 1.5s linear infinite; + @apply border-t-info-500 +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } +} +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } } \ No newline at end of file diff --git a/Moonlight.Client/UI/Layouts/MainLayout.razor b/Moonlight.Client/UI/Layouts/MainLayout.razor index 9a37c48f..63224017 100644 --- a/Moonlight.Client/UI/Layouts/MainLayout.razor +++ b/Moonlight.Client/UI/Layouts/MainLayout.razor @@ -11,13 +11,15 @@ @if (IsLoading) { - - - +
+
+
} else if (CurrentScreen != null) { - @CurrentScreen + + @CurrentScreen + } else { @@ -60,21 +62,28 @@ else private bool IsLoading = true; private RenderFragment? CurrentScreen; - private async Task Load(LazyLoader lazyLoader) + protected override async Task OnAfterRenderAsync(bool firstRender) { - await lazyLoader.UpdateText("Retrieving data"); - await RunLoaders(); + if(!firstRender) + return; - await RenderScreens(); - - IsLoading = false; - await InvokeAsync(StateHasChanged); + await Load(); } - public async Task Reload() + public async Task Load() { IsLoading = true; await InvokeAsync(StateHasChanged); + + // + await RunLoaders(); + + // Screens + await RenderScreens(); + + // + IsLoading = false; + await InvokeAsync(StateHasChanged); } private async Task RunLoaders() @@ -87,6 +96,7 @@ else { try { + Logger.LogDebug("Running application loader '{name}'", loader.GetType().Name); await loader.Load(ServiceProvider); } catch (Exception e) @@ -110,9 +120,11 @@ else continue; CurrentScreen = screen.Render(); + await InvokeAsync(StateHasChanged); - return; } + + await InvokeAsync(StateHasChanged); } } \ No newline at end of file diff --git a/Moonlight.Client/UI/Partials/AppHeader.razor b/Moonlight.Client/UI/Partials/AppHeader.razor index 6e137ea0..0da86ce0 100644 --- a/Moonlight.Client/UI/Partials/AppHeader.razor +++ b/Moonlight.Client/UI/Partials/AppHeader.razor @@ -1,4 +1,8 @@ -@using Moonlight.Client.UI.Layouts +@using Moonlight.Client.Services +@using Moonlight.Client.UI.Layouts + +@inject IdentityService IdentityService +@inject ToastService ToastService
@if (Layout.ShowMobileNavigation) @@ -35,7 +39,7 @@
-
@@ -72,11 +76,42 @@ { [Parameter] public MainLayout Layout { get; set; } - protected override async Task OnAfterRenderAsync(bool firstRender) + private bool ShowProfileNav = false; + + protected override Task OnAfterRenderAsync(bool firstRender) { if(!firstRender) - return; + return Task.CompletedTask; Layout.OnStateChanged += () => InvokeAsync(StateHasChanged); + + return Task.CompletedTask; + } + + private async Task ToggleProfileNav() + { + ShowProfileNav = !ShowProfileNav; + await InvokeAsync(StateHasChanged); + } + + private Task ProfileNav_OnFocusOut() + { + Task.Run(async () => + { + await Task.Delay(200); + + ShowProfileNav = false; + await InvokeAsync(StateHasChanged); + }); + + return Task.CompletedTask; + } + + private async Task Logout() + { + await IdentityService.Logout(); + await ToastService.Info("Successfully logged out"); + + await Layout.Load(); } } diff --git a/Moonlight.Client/UI/Partials/AppSidebar.razor b/Moonlight.Client/UI/Partials/AppSidebar.razor index 277d6349..a354ac01 100644 --- a/Moonlight.Client/UI/Partials/AppSidebar.razor +++ b/Moonlight.Client/UI/Partials/AppSidebar.razor @@ -38,8 +38,8 @@
-
- Your Company +
a + Moonlight