feat/AddTheming #6
@@ -12,8 +12,9 @@
|
|||||||
<script type="importmap"></script>
|
<script type="importmap"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
window.themeLoader = {
|
window.frontendConfig = {
|
||||||
STYLE_TAG_ID: 'theme-variables',
|
STYLE_TAG_ID: 'theme-variables',
|
||||||
|
configuration: {},
|
||||||
|
|
||||||
applyTheme: function(cssContent) {
|
applyTheme: function(cssContent) {
|
||||||
// Find or create the style tag
|
// Find or create the style tag
|
||||||
@@ -29,25 +30,33 @@
|
|||||||
styleTag.textContent = cssContent;
|
styleTag.textContent = cssContent;
|
||||||
},
|
},
|
||||||
|
|
||||||
loadInitialThemeSync: function() {
|
reloadConfiguration: function (){
|
||||||
try {
|
try {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', '/api/frontend/config', false);
|
xhr.open('GET', '/api/frontend/config', false);
|
||||||
xhr.send(null);
|
xhr.send(null);
|
||||||
|
|
||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
const config = JSON.parse(xhr.responseText);
|
this.configuration = JSON.parse(xhr.responseText);
|
||||||
|
|
||||||
this.applyTheme(config.themeCss);
|
|
||||||
document.title = config.name;
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to load initial theme:', error);
|
console.error('Failed to load initial theme:', error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getConfiguration: function (){
|
||||||
|
return this.configuration;
|
||||||
|
},
|
||||||
|
|
||||||
|
reload: function () {
|
||||||
|
this.reloadConfiguration();
|
||||||
|
|
||||||
|
document.title = this.configuration.name;
|
||||||
|
this.applyTheme(this.configuration.themeCss);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.themeLoader.loadInitialThemeSync();
|
window.frontendConfig.reload();
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
9
Moonlight.Frontend/Models/FrontendConfiguration.cs
Normal file
9
Moonlight.Frontend/Models/FrontendConfiguration.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Moonlight.Frontend.Models;
|
||||||
|
|
||||||
|
public class FrontendConfiguration
|
||||||
|
{
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
24
Moonlight.Frontend/Services/FrontendService.cs
Normal file
24
Moonlight.Frontend/Services/FrontendService.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.JSInterop;
|
||||||
|
using Moonlight.Frontend.Models;
|
||||||
|
|
||||||
|
namespace Moonlight.Frontend.Services;
|
||||||
|
|
||||||
|
public class FrontendService
|
||||||
|
{
|
||||||
|
private readonly IJSRuntime JsRuntime;
|
||||||
|
|
||||||
|
public FrontendService(IJSRuntime jsRuntime)
|
||||||
|
{
|
||||||
|
JsRuntime = jsRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<FrontendConfiguration> GetConfigurationAsync()
|
||||||
|
{
|
||||||
|
return await JsRuntime.InvokeAsync<FrontendConfiguration>("frontendConfig.getConfiguration");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ReloadAsync()
|
||||||
|
{
|
||||||
|
await JsRuntime.InvokeVoidAsync("frontendConfig.reload");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moonlight.Frontend.Implementations;
|
using Moonlight.Frontend.Implementations;
|
||||||
using Moonlight.Frontend.Interfaces;
|
using Moonlight.Frontend.Interfaces;
|
||||||
|
using Moonlight.Frontend.Services;
|
||||||
using Moonlight.Frontend.UI;
|
using Moonlight.Frontend.UI;
|
||||||
using ShadcnBlazor;
|
using ShadcnBlazor;
|
||||||
using ShadcnBlazor.Extras;
|
using ShadcnBlazor.Extras;
|
||||||
@@ -22,5 +23,7 @@ public partial class Startup
|
|||||||
builder.Services.AddShadcnBlazorExtras();
|
builder.Services.AddShadcnBlazorExtras();
|
||||||
|
|
||||||
builder.Services.AddSingleton<ISidebarProvider, SidebarProvider>();
|
builder.Services.AddSingleton<ISidebarProvider, SidebarProvider>();
|
||||||
|
|
||||||
|
builder.Services.AddScoped<FrontendService>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
@using Microsoft.AspNetCore.Authorization
|
@using Microsoft.AspNetCore.Authorization
|
||||||
@using Moonlight.Shared
|
@using Moonlight.Shared
|
||||||
@using LucideBlazor
|
@using LucideBlazor
|
||||||
|
@using Moonlight.Frontend.Services
|
||||||
@using Moonlight.Shared.Http.Requests.Themes
|
@using Moonlight.Shared.Http.Requests.Themes
|
||||||
@using ShadcnBlazor.Buttons
|
@using ShadcnBlazor.Buttons
|
||||||
@using ShadcnBlazor.Labels
|
@using ShadcnBlazor.Labels
|
||||||
@@ -18,6 +19,7 @@
|
|||||||
@inject HttpClient HttpClient
|
@inject HttpClient HttpClient
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject ToastService ToastService
|
@inject ToastService ToastService
|
||||||
|
@inject FrontendService FrontendService
|
||||||
|
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@@ -129,6 +131,8 @@
|
|||||||
$"Successfully created theme {Request.Name}"
|
$"Successfully created theme {Request.Name}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await FrontendService.ReloadAsync();
|
||||||
|
|
||||||
Navigation.NavigateTo("/admin/system?tab=themes");
|
Navigation.NavigateTo("/admin/system?tab=themes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
@using Moonlight.Shared
|
@using Moonlight.Shared
|
||||||
@using LucideBlazor
|
@using LucideBlazor
|
||||||
@using Moonlight.Frontend.Mappers
|
@using Moonlight.Frontend.Mappers
|
||||||
|
@using Moonlight.Frontend.Services
|
||||||
@using Moonlight.Shared.Http.Requests.Themes
|
@using Moonlight.Shared.Http.Requests.Themes
|
||||||
@using Moonlight.Shared.Http.Responses.Themes
|
@using Moonlight.Shared.Http.Responses.Themes
|
||||||
@using ShadcnBlazor.Buttons
|
@using ShadcnBlazor.Buttons
|
||||||
@@ -21,6 +22,7 @@
|
|||||||
@inject HttpClient HttpClient
|
@inject HttpClient HttpClient
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject ToastService ToastService
|
@inject ToastService ToastService
|
||||||
|
@inject FrontendService FrontendService
|
||||||
|
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
@@ -142,6 +144,8 @@
|
|||||||
$"Successfully updated theme {Request.Name}"
|
$"Successfully updated theme {Request.Name}"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await FrontendService.ReloadAsync();
|
||||||
|
|
||||||
Navigation.NavigateTo("/admin/system?tab=themes");
|
Navigation.NavigateTo("/admin/system?tab=themes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
@using Microsoft.AspNetCore.Authorization
|
@using System.Text.Json
|
||||||
|
@using Microsoft.AspNetCore.Authorization
|
||||||
@using Microsoft.AspNetCore.Components.Authorization
|
@using Microsoft.AspNetCore.Components.Authorization
|
||||||
@using Moonlight.Frontend.Interfaces
|
@using Moonlight.Frontend.Interfaces
|
||||||
@using Moonlight.Frontend.Models
|
@using Moonlight.Frontend.Models
|
||||||
|
@using Moonlight.Frontend.Services
|
||||||
@using ShadcnBlazor.Sidebars
|
@using ShadcnBlazor.Sidebars
|
||||||
|
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject IAuthorizationService AuthorizationService
|
@inject IAuthorizationService AuthorizationService
|
||||||
|
@inject FrontendService FrontendService
|
||||||
@inject IEnumerable<ISidebarProvider> Providers
|
@inject IEnumerable<ISidebarProvider> Providers
|
||||||
|
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
@@ -21,7 +24,7 @@
|
|||||||
<SidebarMenuButton>
|
<SidebarMenuButton>
|
||||||
<a href="/" class="flex flex-row items-center">
|
<a href="/" class="flex flex-row items-center">
|
||||||
<img alt="Logo" src="/_content/Moonlight.Frontend/logo.svg" class="size-6"/>
|
<img alt="Logo" src="/_content/Moonlight.Frontend/logo.svg" class="size-6"/>
|
||||||
<span class="ms-2.5 text-lg font-semibold">Moonlight</span>
|
<span class="ms-2.5 text-lg font-semibold">@FrontendConfiguration?.Name</span>
|
||||||
</a>
|
</a>
|
||||||
</SidebarMenuButton>
|
</SidebarMenuButton>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
@@ -74,6 +77,7 @@
|
|||||||
[CascadingParameter] public Task<AuthenticationState> AuthState { get; set; }
|
[CascadingParameter] public Task<AuthenticationState> AuthState { get; set; }
|
||||||
|
|
||||||
private readonly List<SidebarItem> Items = new();
|
private readonly List<SidebarItem> Items = new();
|
||||||
|
private FrontendConfiguration? FrontendConfiguration;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
@@ -98,6 +102,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Navigation.LocationChanged += OnLocationChanged;
|
Navigation.LocationChanged += OnLocationChanged;
|
||||||
|
|
||||||
|
FrontendConfiguration = await FrontendService.GetConfigurationAsync();
|
||||||
|
|
||||||
|
Console.WriteLine(JsonSerializer.Serialize(FrontendConfiguration));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user