This commit is contained in:
Timothy Jaeryang Baek
2026-06-11 14:39:50 +01:00
Unverified
parent 49804e92d2
commit ae760e191a
3 changed files with 67 additions and 84 deletions
@@ -1,60 +0,0 @@
<script lang="ts">
import Icon from './Icon.svelte';
import Modal from './Modal.svelte';
import Users from './Admin/Users.svelte';
import Connections from './Admin/Connections.svelte';
import Models from './Admin/Models.svelte';
import AdminSettings from './Admin/Settings.svelte';
import { t } from '$lib/i18n';
interface Props {
onclose: () => void;
}
let { onclose }: Props = $props();
let activeTab = $state<'users' | 'connections' | 'models' | 'settings'>('users');
</script>
<Modal
{onclose}
class="w-full max-w-3xl mx-4 md:mx-0 flex flex-col md:flex-row max-h-[85vh] md:h-[560px]"
>
<nav
class="shrink-0 border-b md:border-b-0 md:border-r border-gray-200 dark:border-white/6 md:w-[180px]"
>
<div class="flex md:flex-col p-1 gap-px">
<button
class="flex items-center gap-1.5 h-7 px-2 md:w-full shrink-0 rounded-lg text-xs text-gray-400 dark:text-gray-600 hover:text-gray-700 dark:hover:text-gray-300 transition-colors duration-75 md:mb-1"
onclick={onclose}
>
<Icon name="chevron-left" size={12} />
<span>{$t('settings.back')}</span>
</button>
{#each [{ id: 'users', label: $t('admin.users'), icon: 'user' }, { id: 'connections', label: $t('admin.connections'), icon: 'plug' }, { id: 'models', label: $t('admin.models'), icon: 'cube' }, { id: 'settings', label: $t('admin.settings'), icon: 'settings' }] as tab}
<button
class="flex items-center gap-1.5 h-7 px-2 md:w-full shrink-0 rounded-lg text-xs text-left transition-colors duration-75
{activeTab === tab.id
? 'font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-white/6'
: 'text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'}"
onclick={() => (activeTab = tab.id as typeof activeTab)}
>
<Icon name={tab.icon} size={14} />
{tab.label}
</button>
{/each}
</div>
</nav>
<div class="flex-1 overflow-y-auto min-h-0 p-4 md:px-5">
{#if activeTab === 'users'}
<Users />
{:else if activeTab === 'connections'}
<Connections />
{:else if activeTab === 'models'}
<Models />
{:else if activeTab === 'settings'}
<AdminSettings />
{/if}
</div>
</Modal>
@@ -5,16 +5,47 @@
import Account from './Settings/Account.svelte';
import Keyboard from './Settings/Keyboard.svelte';
import About from './Settings/About.svelte';
import Users from './Admin/Users.svelte';
import Connections from './Admin/Connections.svelte';
import Models from './Admin/Models.svelte';
import AdminSettings from './Admin/Settings.svelte';
import { session } from '$lib/session';
import { t } from '$lib/i18n';
type Tab =
| 'general'
| 'keyboard'
| 'account'
| 'about'
| 'users'
| 'connections'
| 'models'
| 'admin_settings';
interface Props {
onclose: () => void;
initialTab?: 'general' | 'keyboard' | 'account' | 'about';
initialTab?: Tab;
}
let { onclose, initialTab = 'general' }: Props = $props();
let activeTab = $state<'general' | 'keyboard' | 'account' | 'about'>(initialTab);
let activeTab = $state<Tab>(initialTab);
const isAdmin = $derived($session?.role === 'admin');
const personalTabs: { id: Tab; label: string; icon: string }[] = [
{ id: 'general', label: 'General', icon: 'settings' },
{ id: 'keyboard', label: 'Keyboard', icon: 'terminal' },
{ id: 'account', label: 'Account', icon: 'user' },
{ id: 'about', label: 'About', icon: 'info' }
];
const adminTabs: { id: Tab; label: string; icon: string }[] = [
{ id: 'users', label: 'Users', icon: 'user' },
{ id: 'connections', label: 'Connections', icon: 'plug' },
{ id: 'models', label: 'Models', icon: 'cube' },
{ id: 'admin_settings', label: 'Configuration', icon: 'shield' }
];
</script>
<Modal
@@ -32,18 +63,38 @@
<Icon name="chevron-left" size={12} />
<span>{$t('settings.back')}</span>
</button>
{#each [{ id: 'general', label: $t('settings.general'), icon: 'settings' }, { id: 'keyboard', label: 'Keyboard', icon: 'terminal' }, { id: 'account', label: $t('settings.account'), icon: 'user' }, { id: 'about', label: $t('settings.about'), icon: 'info' }] as tab}
<!-- Personal -->
{#each personalTabs as tab}
<button
class="flex items-center gap-1.5 h-7 px-2 md:w-full shrink-0 rounded-lg text-xs text-left transition-colors duration-75
{activeTab === tab.id
? 'font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-white/6'
: 'text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'}"
onclick={() => (activeTab = tab.id as typeof activeTab)}
onclick={() => (activeTab = tab.id)}
>
<Icon name={tab.icon} size={14} />
{tab.label}
</button>
{/each}
<!-- Admin section -->
{#if isAdmin}
<span class="hidden md:block text-[10px] text-gray-400 dark:text-gray-600 px-2 mt-2 mb-0.5">Admin</span>
{#each adminTabs as tab}
<button
class="flex items-center gap-1.5 h-7 px-2 md:w-full shrink-0 rounded-lg text-xs text-left transition-colors duration-75
{activeTab === tab.id
? 'font-medium text-gray-900 dark:text-white bg-gray-100 dark:bg-white/6'
: 'text-gray-500 hover:text-gray-700 dark:hover:text-gray-300'}"
onclick={() => (activeTab = tab.id)}
>
<Icon name={tab.icon} size={14} />
{tab.label}
</button>
{/each}
{/if}
</div>
</nav>
@@ -56,6 +107,14 @@
<Account />
{:else if activeTab === 'about'}
<About />
{:else if activeTab === 'users'}
<Users />
{:else if activeTab === 'connections'}
<Connections />
{:else if activeTab === 'models'}
<Models />
{:else if activeTab === 'admin_settings'}
<AdminSettings />
{/if}
</div>
</Modal>
@@ -21,7 +21,7 @@
import DirectoryPicker from './DirectoryPicker.svelte';
import DropdownMenu from './DropdownMenu.svelte';
import SettingsModal from './SettingsModal.svelte';
import AdminPanel from './AdminPanel.svelte';
import { tooltip } from '$lib/tooltip';
import { session, clearSession } from '$lib/session';
import { getWelcome } from '$lib/apis/state';
@@ -37,8 +37,7 @@
let showPicker = $state(false);
let showMenu = $state(false);
let showSettings = $state(false);
let settingsTab = $state<'general' | 'account' | 'about'>('general');
let showAdmin = $state(false);
let settingsTab = $state<string>('general');
let wsMenuPath = $state<string | null>(null);
let wsMenuAnchor = $state<HTMLElement | null>(null);
@@ -508,25 +507,14 @@
image: $session.profile_image_url || '/user.png',
onclick: () => {
settingsTab = 'account';
showMenu = false;
showSettings = true;
}
}
]
: []),
...($session ? [{ divider: true, label: '', onclick: () => {} }] : []),
{ label: $t('sidebar.settings'), icon: 'settings', onclick: openSettings },
...($session?.role === 'admin'
? [
{
label: $t('sidebar.admin'),
icon: 'shield',
onclick: () => {
showMenu = false;
showAdmin = true;
}
}
]
: []),
{ label: $t('sidebar.settings'), icon: 'settings', shortcut: formatChord($keybindings.openSettings), onclick: openSettings },
{ divider: true, label: '', onclick: () => {} },
{ label: $t('sidebar.logOut'), icon: 'log-out', onclick: logout }
]}
@@ -562,10 +550,6 @@
/>
{/if}
{#if showAdmin}
<AdminPanel onclose={() => (showAdmin = false)} />
{/if}
<style>
@reference "../../app.css";