fix(observability): router conflict, logout button, missing i18n
- Fix chi duplicate Route() panic by consolidating read/write routes into single Route blocks with nested admin Group - Add logout button to sidebar with token cleanup - Add missing settingsAuth.password i18n key
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<script lang="ts">
|
||||
interface Props { size?: number; class?: string; }
|
||||
const { size = 24, class: className = '' }: Props = $props();
|
||||
</script>
|
||||
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class={className}>
|
||||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
||||
<polyline points="16 17 21 12 16 7" />
|
||||
<line x1="21" y1="12" x2="9" y2="12" />
|
||||
</svg>
|
||||
@@ -47,3 +47,4 @@ export { default as IconWifi } from './IconWifi.svelte';
|
||||
export { default as IconRefresh } from './IconRefresh.svelte';
|
||||
export { default as IconProxies } from './IconProxies.svelte';
|
||||
export { default as IconEvents } from './IconEvents.svelte';
|
||||
export { default as IconLogout } from './IconLogout.svelte';
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"deploy": "Deploy",
|
||||
"proxies": "Proxies",
|
||||
"events": "Events",
|
||||
"settings": "Settings"
|
||||
"settings": "Settings",
|
||||
"logout": "Log out"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
@@ -311,7 +312,8 @@
|
||||
"createFailed": "Failed to create user",
|
||||
"deleteFailed": "Failed to delete user",
|
||||
"deleteConfirm": "Are you sure you want to delete this user?",
|
||||
"usernameRequired": "Username and password are required"
|
||||
"usernameRequired": "Username and password are required",
|
||||
"password": "Password"
|
||||
},
|
||||
"login": {
|
||||
"title": "Docker Watcher",
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
"deploy": "Деплой",
|
||||
"proxies": "Прокси",
|
||||
"events": "События",
|
||||
"settings": "Настройки"
|
||||
"settings": "Настройки",
|
||||
"logout": "Выйти"
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Панель управления",
|
||||
@@ -311,7 +312,8 @@
|
||||
"createFailed": "Не удалось создать пользователя",
|
||||
"deleteFailed": "Не удалось удалить пользователя",
|
||||
"deleteConfirm": "Вы уверены, что хотите удалить этого пользователя?",
|
||||
"usernameRequired": "Имя пользователя и пароль обязательны"
|
||||
"usernameRequired": "Имя пользователя и пароль обязательны",
|
||||
"password": "Пароль"
|
||||
},
|
||||
"login": {
|
||||
"title": "Docker Watcher",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import Toast from '$lib/components/Toast.svelte';
|
||||
import ThemeToggle from '$lib/components/ThemeToggle.svelte';
|
||||
import LocaleSwitcher from '$lib/components/LocaleSwitcher.svelte';
|
||||
import { IconDashboard, IconProjects, IconDeploy, IconProxies, IconEvents, IconSettings, IconMenu, IconX } from '$lib/components/icons';
|
||||
import { IconDashboard, IconProjects, IconDeploy, IconProxies, IconEvents, IconSettings, IconMenu, IconX, IconLogout } from '$lib/components/icons';
|
||||
import { connectGlobalEvents, type SSEConnection } from '$lib/sse';
|
||||
import { instanceStatusStore } from '$lib/stores/instance-status';
|
||||
import { resolvedTheme, applyTheme } from '$lib/stores/theme';
|
||||
@@ -58,6 +58,15 @@
|
||||
sidebarOpen = false;
|
||||
});
|
||||
|
||||
function logout() {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
localStorage.removeItem('auth_token');
|
||||
}
|
||||
sseConnection?.close();
|
||||
sseConnection = null;
|
||||
window.location.href = '/login';
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
sseConnection = connectGlobalEvents({
|
||||
onInstanceStatus(payload) {
|
||||
@@ -151,7 +160,17 @@
|
||||
<ThemeToggle />
|
||||
<LocaleSwitcher />
|
||||
</div>
|
||||
<p class="text-xs text-[var(--text-tertiary)]">{$t('app.name')} {$t('app.version')}</p>
|
||||
<div class="flex items-center justify-between">
|
||||
<p class="text-xs text-[var(--text-tertiary)]">{$t('app.name')} {$t('app.version')}</p>
|
||||
<button
|
||||
onclick={logout}
|
||||
class="inline-flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-[var(--text-secondary)] transition-colors hover:bg-[var(--surface-card-hover)] hover:text-[var(--color-danger)]"
|
||||
title={$t('nav.logout')}
|
||||
>
|
||||
<IconLogout size={14} />
|
||||
{$t('nav.logout')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user