This commit is contained in:
2026-06-02 17:39:58 +02:00
36 changed files with 2520 additions and 463 deletions
+29 -16
View File
@@ -2,49 +2,50 @@
@attribute [Authorize]
@inject IUserSessionService Session
@inject IJSRuntime JS
@inject TranslationSource T
@rendermode InteractiveServer
@using Microsoft.JSInterop
<h1 class="page-title">Settings</h1>
<h1 class="page-title">@T["tab.settings"]</h1>
<div class="card">
<div class="card-title">Display</div>
<div class="card-title">@T["settings.section.display"]</div>
<div class="form-group">
<label class="form-label">Language</label>
<label class="form-label">@T["settings.language"]</label>
<select class="form-select" style="width:160px" @bind="_lang" @bind:after="Save">
<option value="en">English</option>
<option value="fr">Français</option>
<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">Theme</label>
<label class="form-label">@T["settings.theme"]</label>
<select class="form-select" style="width:160px" @bind="_theme" @bind:after="Save">
<option value="System">System</option>
<option value="Light">Light</option>
<option value="System">@T["settings.theme.system"]</option>
<option value="Light">@T["settings.theme.light"]</option>
</select>
</div>
</div>
<div class="card">
<div class="card-title">Behavior</div>
<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" />
Auto-elevate ownership when permission scan is denied
@T["settings.behavior.autoElevate"]
</label>
</div>
</div>
<div class="card">
<div class="card-title">Report Branding</div>
<div class="card-title">@T["settings.section.branding"]</div>
<div class="form-group">
<label class="form-label">MSP logo</label>
<p class="text-muted" style="margin-top:0">Shown top-left on exported HTML reports. The client's logo (top-right) is set per profile.</p>
<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">Settings saved.</div> }
@if (_saved) { <div class="alert alert-success">@T["settings.saved"]</div> }
@code {
private string _lang = "en", _theme = "System";
@@ -54,7 +55,9 @@
protected override void OnInitialized()
{
var s = Session.Settings;
_lang = s.Lang;
// Reflect the culture actually resolved for this circuit (cookie-driven), not the
// possibly-not-yet-loaded persisted setting.
_lang = System.Globalization.CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "fr" ? "fr" : "en";
_theme = s.Theme is "System" or "Light" ? s.Theme : "System";
_autoTakeOwnership = s.AutoTakeOwnership;
_mspLogo = s.MspLogo;
@@ -68,9 +71,19 @@
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 });
SharepointToolbox.Web.Localization.TranslationSource.Instance.SetCulture(_lang);
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); });