From a9b0c4e0f45d9abbb4b487daf097d81bd4c0f1fc Mon Sep 17 00:00:00 2001 From: "Leon.Schmidt" Date: Thu, 20 Aug 2026 21:06:53 +0200 Subject: [PATCH] ENH - compact admin workspace navigation --- .../components/AdminPanel.contract.test.ts | 19 + frontend/src/components/AdminPanel.vue | 401 ++++++++++++++++-- frontend/src/stores/phone.ts | 22 +- sky_phone/config/locales/de.lua | 6 +- sky_phone/config/locales/en.lua | 6 +- 5 files changed, 422 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/AdminPanel.contract.test.ts b/frontend/src/components/AdminPanel.contract.test.ts index 0832f07..6d2af77 100644 --- a/frontend/src/components/AdminPanel.contract.test.ts +++ b/frontend/src/components/AdminPanel.contract.test.ts @@ -59,6 +59,25 @@ describe('standalone admin panel contracts', () => { expect(source).toContain('@media (prefers-reduced-motion: reduce)') }) + it('uses a compact transparent shell with dedicated admin workspaces', () => { + expect(source).toContain('background: transparent') + expect(source).toContain('width: min(84vw, 1420px)') + expect(source).toContain('height: min(82vh, 820px)') + expect(source).not.toContain('backdrop-filter: blur(2px)') + + for (const tab of [ + 'overview', + 'players', + 'devices', + 'apps', + 'security', + 'audit', + ]) { + expect(source).toContain(`selectTab('${tab}')`) + expect(source).toContain(`t('tabs.${tab}')`) + } + }) + it('stages app changes locally and saves them only from the toolbar action', () => { expect(source).toContain('const drafts = ref<') expect(source).toContain('@click="saveChanges"') diff --git a/frontend/src/components/AdminPanel.vue b/frontend/src/components/AdminPanel.vue index ee05e50..c934651 100644 --- a/frontend/src/components/AdminPanel.vue +++ b/frontend/src/components/AdminPanel.vue @@ -8,6 +8,7 @@ import { Clipboard, Database, Eye, + Grid2X2, HardDrive, KeyRound, LayoutDashboard, @@ -45,17 +46,22 @@ import { copyText } from '@/utils/clipboard' import { parseDatabaseDate } from '@/utils/date' import { nuiCall } from '@/utils/nui' -type AdminTab = 'players' | 'audit' +type AdminTab = + | 'overview' + | 'players' + | 'devices' + | 'apps' + | 'security' + | 'audit' type PendingAction = | { kind: 'close' } | { kind: 'player'; source: number } | { kind: 'refresh' } - | { kind: 'tab'; tab: AdminTab } const emit = defineEmits<{ close: [] }>() const admin = useAdminStore() const phone = usePhoneStore() -const tab = ref('players') +const tab = ref('overview') const playerQuery = ref('') const appQuery = ref('') const selectedImei = ref('') @@ -251,6 +257,10 @@ function queueAction(action: PendingAction): void { discardDialog.value = true } +function selectTab(nextTab: AdminTab): void { + tab.value = nextTab +} + async function runAction(action: PendingAction): Promise { if (action.kind === 'close') { const response = await nuiCall('admin:close') @@ -262,10 +272,6 @@ async function runAction(action: PendingAction): Promise { await refreshData() return } - if (action.kind === 'tab') { - tab.value = action.tab - return - } await loadPlayer(action.source) } @@ -387,7 +393,7 @@ onBeforeUnmount(() => {
- {{ tab === 'players' ? t('editor.players') : t('editor.audit') }} + {{ t('tabs.' + tab) }} {{ @@ -435,21 +441,57 @@ onBeforeUnmount(() => {