Files
ss-tools/frontend/src/components/Navbar.svelte
busya a3c7c402b7 fix(llm): add fetch-models endpoint, fix SQL Lab INSERT (client_id truncation, sync mode, target_column, timestamp normalization)
- Add POST /api/llm/providers/fetch-models route with LLMClient.fetch_models()
- Add target_column to TranslationJob model/schema/service/orchestrator
- Fix SQL Lab execute: truncate client_id to 11 chars (varchar(11))
- Switch SQL Lab to sync mode (runAsync: false) — no Celery workers
- Fix polling: unwrap nested result from Superset query API
- Fix ClickHouse timestamp: normalize float timestamps to YYYY-MM-DD
2026-05-13 20:06:15 +03:00

91 lines
4.4 KiB
Svelte

<!-- #region Navbar [C:3] [TYPE Component] [SEMANTICS navigation, header, auth, layout] -->
<!-- @BRIEF Component component: components/Navbar.svelte -->
<!-- @LAYER UI -->
<!--
@SEMANTICS: navbar, navigation, header, layout
@PURPOSE: Main navigation bar for the application.
@LAYER: UI
@RELATION: BINDS_TO -> [authStore]
@RELATION: BINDS_TO -> [i18n]
@RELATION: DEPENDS_ON -> [LanguageSwitcher]
@UX_STATE: Idle -> Navigation links and settings menus are visible.
@UX_STATE: Authenticated -> User identity and logout action are rendered.
-->
<script>
import { page } from '$app/state';
import { fromStore } from 'svelte/store';
import { t } from '$lib/i18n';
import { LanguageSwitcher } from '$lib/ui';
import { auth } from '$lib/auth/store';
import { goto } from '$app/navigation';
const authState = fromStore(auth);
function handleLogout() {
auth.logout();
goto('/login');
}
</script>
<header class="bg-white shadow-md p-4 flex justify-between items-center">
<a
href="/"
class="text-2xl font-bold text-gray-800 focus:outline-none"
>
Superset Tools
</a>
<nav class="flex items-center space-x-4">
<a
href="/"
class="text-gray-600 hover:text-blue-600 font-medium {page.url.pathname === '/' ? 'text-blue-600 border-b-2 border-blue-600' : ''}"
>
{$t.nav.dashboard}
</a>
<a
href="/reports"
class="text-gray-600 hover:text-blue-600 font-medium {page.url.pathname.startsWith('/reports') ? 'text-blue-600 border-b-2 border-blue-600' : ''}"
>
{$t.nav.reports}
</a>
<div class="relative inline-block group">
<button class="text-gray-600 hover:text-blue-600 font-medium pb-1 {page.url.pathname.startsWith('/settings') ? 'text-blue-600 border-b-2 border-blue-600' : ''}">
{$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-blue-600">{$t.nav.settings_general}</a>
<a href="/settings/connections" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">{$t.nav.settings_connections}</a>
<a href="/settings/git" class="block px-4 py-2 text-sm text-gray-700 hover:bg-blue-50 hover:text-blue-600">{$t.nav.settings_git}</a>
</div>
</div>
{#if authState.current?.isAuthenticated && authState.current?.user?.roles?.some(r => r.name === 'Admin')}
<div class="relative inline-block group">
<button class="text-gray-600 hover:text-blue-600 font-medium pb-1 {page.url.pathname.startsWith('/admin') ? 'text-blue-600 border-b-2 border-blue-600' : ''}">
{$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-blue-600">{$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-blue-600">{$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-blue-600">{$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-blue-600">{$t.nav.admin_llm}</a>
</div>
</div>
{/if}
<LanguageSwitcher />
{#if authState.current?.isAuthenticated}
<div class="flex items-center space-x-2 border-l pl-4 ml-4">
<span class="text-sm text-gray-600">{authState.current?.user?.username}</span>
<button
onclick={handleLogout}
class="text-sm text-red-600 hover:text-red-800 font-medium"
>
Logout
</button>
</div>
{/if}
</nav>
</header>
<!-- #endregion Navbar -->