This commit is contained in:
2026-06-02 11:46:00 +03:00
parent 1dec48079c
commit 7f48b19f28
38 changed files with 1238 additions and 308 deletions

View File

@@ -13,21 +13,23 @@
@UX_STATE: Authenticated -> User identity and logout action are rendered.
-->
<script lang="ts">
import { onMount } from 'svelte';
import { page } from '$app/state';
import { t } from '$lib/i18n/index.svelte.js';
import { LanguageSwitcher } from '$lib/ui';
import { auth } from '$lib/auth/store.svelte.js';
import { goto } from '$app/navigation';
import { ROUTES } from '$lib/routes';
let _authState = $state({ user: null, token: null, isAuthenticated: false, loading: true });
$effect(() => {
onMount(() => {
const unsub = auth.subscribe(v => { _authState = v; });
return unsub;
});
function handleLogout() {
auth.logout();
goto('/login');
goto(ROUTES.login());
}
</script>
@@ -46,7 +48,7 @@
{$t.nav.dashboard}
</a>
<a
href="/reports"
href={ROUTES.reports.list()}
class="text-gray-600 hover:text-primary font-medium {page.url.pathname.startsWith('/reports') ? 'text-primary border-b-2 border-blue-600' : ''}"
>
{$t.nav.reports}
@@ -56,8 +58,8 @@
{$t.nav.settings}
</button>
<div class="absolute hidden group-hover:block bg-white shadow-lg rounded-md mt-1 py-2 w-48 z-10 border border-gray-100 before:absolute before:-top-2 before:left-0 before:right-0 before:h-2 before:content-[''] right-0">
<a href="/settings" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.settings_general}</a>
<a href="/settings/git" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.settings_git}</a>
<a href={ROUTES.settings.general()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.settings_general}</a>
<a href={ROUTES.settings.git()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.settings_git}</a>
</div>
</div>
@@ -67,10 +69,10 @@
{$t.nav.admin}
</button>
<div class="absolute hidden group-hover:block bg-white shadow-lg rounded-md mt-1 py-2 w-48 z-10 border border-gray-100 before:absolute before:-top-2 before:left-0 before:right-0 before:h-2 before:content-[''] right-0">
<a href="/admin/users" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_users}</a>
<a href="/admin/roles" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_roles}</a>
<a href="/admin/settings" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_settings}</a>
<a href="/admin/settings/llm" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_llm}</a>
<a href={ROUTES.admin.users()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_users}</a>
<a href={ROUTES.admin.roles()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_roles}</a>
<a href={ROUTES.admin.settings()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_settings}</a>
<a href={ROUTES.admin.llmSettings()} class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-primary">{$t.nav.admin_llm}</a>
</div>
</div>
{/if}

View File

@@ -489,6 +489,7 @@
// #endregion getStatusBadgeClass:Function
$effect(() => {
console.count("[Grid.effect491]");
dashboards;
statusMode;
currentPage;

View File

@@ -18,6 +18,7 @@
* @UX_RECOVERY: User can switch to advanced settings or retry save with corrected data.
*/
import { goto } from "$app/navigation";
import { ROUTES } from "$lib/routes";
import { t } from "$lib/i18n/index.svelte.js";
import { api } from "$lib/api.js";
import { addToast } from "$lib/toasts.svelte.js";
@@ -74,7 +75,7 @@
}
async function openAdvancedSettings() {
await goto("/settings?tab=environments#environments");
await goto(ROUTES.settings.environmentsTab());
}
async function handleCreateEnvironment() {

View File

@@ -43,6 +43,7 @@
import { auth } from "../../lib/auth/store.svelte.js";
import { api } from "../../lib/api";
import { goto } from "$app/navigation";
import { ROUTES } from "$lib/routes";
import { hasPermission } from "$lib/auth/permissions.js";
const { requiredPermission = null, fallbackPath = "/profile", children } = $props();
@@ -76,7 +77,7 @@
if (!$auth.token) {
auth.setLoading(false);
console.info("[ProtectedRoute.verifySessionAndAccess][REFLECT] Missing token, redirecting to /login");
await goto("/login");
await goto(ROUTES.login());
return;
}
@@ -91,8 +92,8 @@
} catch (error) {
console.warn("[ProtectedRoute.verifySessionAndAccess][EXPLORE] Session validation failed", { error });
auth.logout();
await goto("/login");
return;
await goto(ROUTES.login());
return;
} finally {
auth.setLoading(false);
}
@@ -101,7 +102,7 @@
if (!currentUser) {
auth.logout();
console.info("[ProtectedRoute.verifySessionAndAccess][REFLECT] User unresolved, redirecting to /login");
await goto("/login");
await goto(ROUTES.login());
return;
}