100 lines
3.7 KiB
Plaintext
100 lines
3.7 KiB
Plaintext
@page "/settings"
|
|
@attribute [Authorize]
|
|
@inject IUserSessionService Session
|
|
@inject IUserContextAccessor UserContext
|
|
@inject IJSRuntime JS
|
|
@inject TranslationSource T
|
|
@rendermode InteractiveServer
|
|
@using Microsoft.JSInterop
|
|
@using SharepointToolbox.Web.Core.Models
|
|
@using SharepointToolbox.Web.Services.Session
|
|
|
|
<h1 class="page-title">@T["tab.settings"]</h1>
|
|
|
|
<div class="card">
|
|
<div class="card-title">@T["settings.section.display"]</div>
|
|
<div class="form-group">
|
|
<label class="form-label">@T["settings.language"]</label>
|
|
<select class="form-select" style="width:160px" @bind="_lang" @bind:after="Save">
|
|
<option value="en">@T["settings.lang.en"]</option>
|
|
<option value="fr">@T["settings.lang.fr"]</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">@T["settings.theme"]</label>
|
|
<select class="form-select" style="width:160px" @bind="_theme" @bind:after="Save">
|
|
<option value="System">@T["settings.theme.system"]</option>
|
|
<option value="Light">@T["settings.theme.light"]</option>
|
|
<option value="Dark">@T["settings.theme.dark"]</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-title">@T["settings.section.behavior"]</div>
|
|
<div class="form-group">
|
|
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
|
<input type="checkbox" @bind="_autoTakeOwnership" @bind:after="Save" />
|
|
@T["settings.behavior.autoElevate"]
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
@if (UserContext.Role == UserRole.Admin)
|
|
{
|
|
@* MSP branding is shared (global settings file) — only Admins set it for everyone. *@
|
|
<div class="card">
|
|
<div class="card-title">@T["settings.section.branding"]</div>
|
|
<div class="form-group">
|
|
<label class="form-label">@T["settings.logo.title"]</label>
|
|
<p class="text-muted" style="margin-top:0">@T["settings.logo.description"]</p>
|
|
<LogoUpload Value="_mspLogo" ValueChanged="OnMspLogoChanged" />
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
@if (_saved) { <div class="alert alert-success">@T["settings.saved"]</div> }
|
|
|
|
@code {
|
|
private string _lang = "en", _theme = "System";
|
|
private bool _autoTakeOwnership, _saved;
|
|
private LogoData? _mspLogo;
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
var s = Session.Settings;
|
|
// Read the persisted language directly — the interactive circuit doesn't reliably inherit
|
|
// ambient CurrentUICulture (see TranslationSource), so reading it here shows the wrong value.
|
|
_lang = s.Lang is "fr" or "en" ? s.Lang : "fr";
|
|
_theme = s.Theme is "System" or "Light" or "Dark" ? s.Theme : "System";
|
|
_autoTakeOwnership = s.AutoTakeOwnership;
|
|
_mspLogo = s.MspLogo;
|
|
}
|
|
|
|
private async Task OnMspLogoChanged(LogoData? logo)
|
|
{
|
|
_mspLogo = logo;
|
|
await Save();
|
|
}
|
|
|
|
private async Task Save()
|
|
{
|
|
var langChanged = !string.Equals(Session.Settings.Lang, _lang, StringComparison.Ordinal);
|
|
Session.UpdateSettings(new AppSettings { Lang = _lang, Theme = _theme, AutoTakeOwnership = _autoTakeOwnership, MspLogo = _mspLogo });
|
|
T.SetCulture(_lang);
|
|
await JS.InvokeVoidAsync("sptb.setTheme", _theme);
|
|
|
|
// Persisted above. A full reload restarts the circuit; MainLayout then applies the new
|
|
// language (from the just-saved settings) before anything renders.
|
|
if (langChanged)
|
|
{
|
|
await JS.InvokeVoidAsync("location.reload");
|
|
return;
|
|
}
|
|
|
|
_saved = true;
|
|
StateHasChanged();
|
|
_ = Task.Delay(2000).ContinueWith(_ => { _saved = false; InvokeAsync(StateHasChanged); });
|
|
}
|
|
}
|