mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-15 05:29:28 +00:00
feat(webui): redesign admin key gate
Add a circular key-icon badge and a small "LLM Gateway" wordmark, so the screen reads as this product's door and not a generic prompt. Restructure the dense security paragraph into a short description plus a three-item muted checklist. Each claim keeps its original strength: the key stays in this tab's session storage, the browser never writes it to disk, and requests go only to this page's own /admin/api/* routes. Add a show/hide toggle for the key input. It reuses the ghost icon-button composition SearchInput.vue already uses for its clear button. Autofocus the input on mount. Disable submit while the trimmed input is empty. Add a brief shake on the key input when auth.error is set. The animation respects prefers-reduced-motion and lives in a scoped <style> block local to this file — the first one in webui/src/components, added because no Tailwind-core or tw-animate-css keyframe reads as "rejected". Extend the header in App.vue with a GitHub repository link, per an operator scope addition mid-task: an icon-only ghost button that opens github.com/lukaszraczylo/traefik-llmgateway in a new tab. The link sits in App.vue's header, above the gate/dashboard switch, so it renders on every screen including the auth gate. Installs @fortawesome/free-brands-svg-icons, pinned like the other fontawesome packages, for the faGithub icon. auth.submit() semantics, dashboard.refresh() timing, and the backend stay unchanged.
This commit is contained in:
+21
-1
@@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faCircleExclamation } from '@fortawesome/free-solid-svg-icons'
|
||||
import { computed, defineAsyncComponent, onMounted, ref } from 'vue'
|
||||
|
||||
import AuthGate from '@/components/AuthGate.vue'
|
||||
import OverviewView from '@/components/OverviewView.vue'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import UsageView from '@/components/UsageView.vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
@@ -15,6 +17,10 @@ import { useDashboardStore } from '@/stores/dashboard'
|
||||
// lean; it fetches once, on first visit to the Charts tab.
|
||||
const ChartsView = defineAsyncComponent(() => import('@/components/ChartsView.vue'))
|
||||
|
||||
/** The module path (go.mod / .traefik.yml `import:`) — same repo the plugin
|
||||
* ships from, so this is the one canonical URL rather than a guess. */
|
||||
const GITHUB_REPO_URL = 'https://github.com/lukaszraczylo/traefik-llmgateway'
|
||||
|
||||
const auth = useAuthStore()
|
||||
const dashboard = useDashboardStore()
|
||||
|
||||
@@ -34,7 +40,21 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="flex w-full flex-col gap-6 px-4 py-8 sm:px-6 lg:px-8">
|
||||
<header class="flex flex-col gap-1">
|
||||
<h1 class="text-xl font-semibold tracking-tight">LLM Gateway — Admin</h1>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<h1 class="text-xl font-semibold tracking-tight">LLM Gateway — Admin</h1>
|
||||
<Button
|
||||
as="a"
|
||||
:href="GITHUB_REPO_URL"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
aria-label="GitHub repository"
|
||||
class="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<FontAwesomeIcon :icon="faGithub" class="size-4" aria-hidden="true" />
|
||||
</Button>
|
||||
</div>
|
||||
<p class="flex items-center gap-1.5 text-sm text-muted-foreground">
|
||||
<FontAwesomeIcon v-if="dashboard.error" :icon="faCircleExclamation" class="size-3.5 text-destructive" />
|
||||
<span :class="dashboard.error ? 'text-destructive' : undefined">{{ statusText }}</span>
|
||||
|
||||
Reference in New Issue
Block a user