Merge branch 'main' of https://git.azuze.fr/kawa/SharepointToolbox-Web
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
@inject IJSRuntime JS
|
||||
@inject SharepointToolbox.Web.Services.OAuth.IOAuthFlowCache OAuthCache
|
||||
@inject SharepointToolbox.Web.Infrastructure.Persistence.ProfileRepository ProfileRepo
|
||||
@inject TranslationSource T
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
@using Microsoft.JSInterop
|
||||
@@ -23,7 +24,7 @@
|
||||
<span class="logo-mark">SP</span>
|
||||
<span class="logo-text">SP Toolbox</span>
|
||||
</div>
|
||||
<button class="toggle-btn @(_sidebarCollapsed ? "collapsed" : "")" @onclick="ToggleSidebar" title="Toggle sidebar">›</button>
|
||||
<button class="toggle-btn @(_sidebarCollapsed ? "collapsed" : "")" @onclick="ToggleSidebar" title="@T["nav.toggleSidebar"]">›</button>
|
||||
</div>
|
||||
|
||||
@* User identity badge *@
|
||||
@@ -44,7 +45,7 @@
|
||||
<div style="font-size:10px;color:var(--text-muted);margin-top:4px">
|
||||
SP: @_credUsername
|
||||
<button class="btn btn-secondary btn-sm" style="padding:2px 6px;font-size:10px;margin-left:4px"
|
||||
@onclick="ReconnectAsync">Reconnect</button>
|
||||
@onclick="ReconnectAsync">@T["nav.reconnect"]</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -61,11 +62,11 @@
|
||||
|
||||
<div class="nav-search">
|
||||
<span class="nav-icon">🔍</span>
|
||||
<input type="text" class="nav-search-input" placeholder="Search…"
|
||||
<input type="text" class="nav-search-input" placeholder="@T["nav.searchPlaceholder"]"
|
||||
@bind="_navFilter" @bind:event="oninput" />
|
||||
@if (!string.IsNullOrEmpty(_navFilter))
|
||||
{
|
||||
<button class="nav-search-clear" @onclick="ClearFilter" title="Clear">✕</button>
|
||||
<button class="nav-search-clear" @onclick="ClearFilter" title="@T["nav.clear"]">✕</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -81,16 +82,16 @@
|
||||
lastSection = item.Section;
|
||||
if (!string.IsNullOrEmpty(item.Section))
|
||||
{
|
||||
<div class="nav-divider">@item.Section</div>
|
||||
<div class="nav-divider">@T[item.Section]</div>
|
||||
}
|
||||
}
|
||||
<NavLink href="@item.Href" Match="@(item.Href == "/" ? NavLinkMatch.All : NavLinkMatch.Prefix)" class="nav-item">
|
||||
<span class="nav-icon">@item.Icon</span><span class="nav-label">@item.Label</span>
|
||||
<span class="nav-icon">@item.Icon</span><span class="nav-label">@T[item.Label]</span>
|
||||
</NavLink>
|
||||
}
|
||||
@if (items.Count == 0)
|
||||
{
|
||||
<div class="nav-empty">No match</div>
|
||||
<div class="nav-empty">@T["nav.noMatch"]</div>
|
||||
}
|
||||
</nav>
|
||||
|
||||
@@ -98,13 +99,13 @@
|
||||
<AuthorizeView>
|
||||
<Authorized>
|
||||
<a href="/account/logout" class="nav-item">
|
||||
<span class="nav-icon">🚪</span><span class="nav-label">Logout</span>
|
||||
<span class="nav-icon">🚪</span><span class="nav-label">@T["nav.logout"]</span>
|
||||
</a>
|
||||
</Authorized>
|
||||
</AuthorizeView>
|
||||
<button class="nav-item theme-toggle" @onclick="ToggleTheme">
|
||||
<span class="nav-icon">🌙</span>
|
||||
<span class="nav-label">@(_dark ? "Light Mode" : "Dark Mode")</span>
|
||||
<span class="nav-label">@(_dark ? T["nav.lightMode"] : T["nav.darkMode"])</span>
|
||||
<span class="switch @(_dark ? "on" : "")"></span>
|
||||
</button>
|
||||
</div>
|
||||
@@ -120,7 +121,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<div style="padding:2rem;color:var(--text-muted)">Loading…</div>
|
||||
<div style="padding:2rem;color:var(--text-muted)">@T["nav.loading"]</div>
|
||||
}
|
||||
</main>
|
||||
</div>
|
||||
@@ -137,23 +138,23 @@
|
||||
|
||||
private static readonly NavItem[] AllNavItems =
|
||||
{
|
||||
new("/", "🏠", "Home", "", "always"),
|
||||
new("/permissions", "🔐", "Permissions", "", "profile"),
|
||||
new("/storage", "💾", "Storage", "", "profile"),
|
||||
new("/duplicates", "📋", "Duplicates", "", "profile"),
|
||||
new("/versions", "🗂️", "Version Cleanup", "", "profile"),
|
||||
new("/transfer", "📦", "File Transfer", "", "profile"),
|
||||
new("/bulk-members", "👥", "Bulk Members", "Bulk", "profile"),
|
||||
new("/bulk-sites", "🌐", "Bulk Sites", "Bulk", "profile"),
|
||||
new("/folder-structure", "📁", "Folder Structure", "Bulk", "profile"),
|
||||
new("/user-audit", "👤", "User Access Audit","Audit", "profile"),
|
||||
new("/user-directory", "📖", "User Directory", "Audit", "profile"),
|
||||
new("/templates", "📐", "Templates", "Config", "profile"),
|
||||
new("/profiles", "⚙️", "Client Profiles", "Admin", "admin"),
|
||||
new("/admin/users", "👥", "User Management", "Admin", "admin"),
|
||||
new("/admin/audit", "📋", "Audit Logs", "Admin", "admin"),
|
||||
new("/settings", "🔧", "Settings", "", "always"),
|
||||
new("/account/change-password","🔑", "Change Password", "", "auth"),
|
||||
new("/", "🏠", "nav.home", "", "always"),
|
||||
new("/permissions", "🔐", "tab.permissions", "", "profile"),
|
||||
new("/storage", "💾", "tab.storage", "", "profile"),
|
||||
new("/duplicates", "📋", "tab.duplicates", "", "profile"),
|
||||
new("/versions", "🗂️", "versions.tab", "", "profile"),
|
||||
new("/transfer", "📦", "nav.fileTransfer", "", "profile"),
|
||||
new("/bulk-members", "👥", "tab.bulkMembers", "nav.section.bulk", "profile"),
|
||||
new("/bulk-sites", "🌐", "tab.bulkSites", "nav.section.bulk", "profile"),
|
||||
new("/folder-structure", "📁", "tab.folderStructure", "nav.section.bulk", "profile"),
|
||||
new("/user-audit", "👤", "tab.userAccessAudit", "nav.section.audit", "profile"),
|
||||
new("/user-directory", "📖", "nav.userDirectory", "nav.section.audit", "profile"),
|
||||
new("/templates", "📐", "tab.templates", "nav.section.config", "profile"),
|
||||
new("/profiles", "⚙️", "nav.clientProfiles", "nav.section.admin", "admin"),
|
||||
new("/admin/users", "👥", "nav.userManagement", "nav.section.admin", "admin"),
|
||||
new("/admin/audit", "📋", "nav.auditLogs", "nav.section.admin", "admin"),
|
||||
new("/settings", "🔧", "tab.settings", "", "always"),
|
||||
new("/account/change-password","🔑", "nav.changePassword", "", "auth"),
|
||||
};
|
||||
|
||||
private IEnumerable<NavItem> VisibleNavItems()
|
||||
@@ -168,7 +169,7 @@
|
||||
_ => true
|
||||
})
|
||||
.Where(i => filter.Length == 0
|
||||
|| i.Label.Contains(filter, StringComparison.OrdinalIgnoreCase));
|
||||
|| T[i.Label].Contains(filter, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private void ClearFilter() => _navFilter = string.Empty;
|
||||
@@ -177,6 +178,16 @@
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// Apply the user's language to this circuit's TranslationSource (used by every page in
|
||||
// the circuit) and to the ambient culture (used by the export services). Runs in both
|
||||
// the prerender and the interactive circuit, before any page renders — so the whole app
|
||||
// is in the right language and stays there across SPA navigation.
|
||||
var lang = Session.Settings.Lang;
|
||||
T.SetCulture(lang);
|
||||
var culture = TranslationSource.Resolve(lang);
|
||||
System.Globalization.CultureInfo.CurrentCulture = culture;
|
||||
System.Globalization.CultureInfo.CurrentUICulture = culture;
|
||||
|
||||
Session.ProfileChanged += OnProfileChanged;
|
||||
UserContext.Initialized += OnUserContextInitialized;
|
||||
_dark = string.Equals(Session.Settings.Theme, "Dark", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
Reference in New Issue
Block a user