mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-14 05:18:54 +00:00
Component-first admin-panel rework (operator directive), replacing hand-rolled patterns with the actual shadcn-vue library components rather than working around them. - Providers (OverviewView) and Groups (UsageView) now render as a real shadcn-vue Accordion: trigger is the summary line, content holds the detail (base URL, last refresh/error, model chips for providers; full stat grid + member users for groups) — the earlier hand-rolled second-<TableRow> toggle is retired. lib/provider-expand.ts's tested two-set expand-state module is unchanged; only the template now adapts it to Accordion's type="multiple" v-model via a writable computed instead of driving a plain v-if. - Usage view: expanding a group shows its member users' own usage rows — a client-side join on AdminUsageEntryView.groupName, which admin.go already sets per user (verified via admin_test.go's existing TestAdminUsage_MathAgainstSeededCounters; no backend change needed). - New DataTable.vue: the shadcn-vue DataTable pattern (@tanstack/vue-table, pinned to ^8.21.3 — the version whose API matches the documented pattern; npm's default "latest" resolves to v9, a breaking rewrite with a different API) factored into one reusable, generic component so every real table (users usage, aliases, a group's nested member list) gets clickable sortable headers with asc/desc indicators for free. usage-columns.ts holds the shared ColumnDef set; UsageTable.vue now delegates to DataTable. Groups themselves cannot be a literal <table> (Accordion wraps content in a <div>, illegal inside <tbody>), so their own sortability is driven by the same columns headlessly, surfaced as a small header-button toolbar above the Accordion. - Aliases table: alias id gets the ModelChip copy treatment (the alias name is the routable string); target stays plain text. - App.vue: dropped the max-w-6xl container — the panel now uses the full viewport width with responsive gutters (px-4 sm:px-6 lg:px-8). Table.vue already wraps every table in its own overflow-x-auto container, so a wide table still scrolls itself, never the page. shadcn-vue add accordion re-added @lucide/vue and required swapping its Chevron icons for FontAwesome (webui/README.md's own documented trap); components.json's iconLibrary/font keys stayed absent (verified main.css byte-identical after the add). Browser-verified against the real integration stack (real /admin over the Yaegi plugin, strict CSP incl. style-src 'self'): provider/group accordion expand, search auto-expand through the new Accordion adapter, sort toggles on aliases/users/groups-toolbar/nested-member tables, alias copy-to-clipboard, full-width at 1920px. Zero console errors (one unrelated MetaMask extension log).
34 lines
1.1 KiB
Vue
34 lines
1.1 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
|
|
import DataTable from '@/components/DataTable.vue'
|
|
import { usageColumns } from '@/lib/usage-columns'
|
|
import type { AdminUsageEntryView } from '@/types/api'
|
|
|
|
/**
|
|
* UsageTable renders one scope kind's usage rows (users, or a group's
|
|
* member users) as a sortable DataTable (shadcn-vue's DataTable pattern,
|
|
* via the shared usageColumns() defs — vue.md: extract before you paste
|
|
* it twice). The second column differs per kind: a user's row shows the
|
|
* group it belongs to; a group's row shows its member count (looked up
|
|
* from the Overview response, which is the only place member counts
|
|
* live).
|
|
*/
|
|
const props = defineProps<{
|
|
idLabel: string
|
|
entries: AdminUsageEntryView[]
|
|
secondaryColumnLabel: string
|
|
secondaryValue: (entry: AdminUsageEntryView) => string
|
|
}>()
|
|
|
|
const columns = computed(() => usageColumns(props.idLabel, props.secondaryColumnLabel, props.secondaryValue))
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
:columns="columns"
|
|
:data="entries"
|
|
:row-class="(entry) => (entry.storeDown ? 'bg-destructive/10' : undefined)"
|
|
/>
|
|
</template>
|