mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-22 06:06:59 +00:00
chore(webui): drop dead clear() from useSearchQuery, add spec, doc composables
- useSearchQuery.ts: remove clear() — zero callers, since SearchInput's
clear button already clears by emitting update:modelValue('') through
v-model, no separate imperative clear needed.
- Add composables/useSearchQuery.spec.ts (3 cases: normalized trims,
normalized lowercases, hasQuery false for whitespace-only query).
- README.md Structure section: document src/composables/ (useThemeColors,
useSearchQuery) and mention the new shared SearchInput component
alongside the existing components/lib entries.
This commit is contained in:
+11
-6
@@ -73,12 +73,17 @@ npm run build # what `make admin-ui` runs, plus webui/generate.mjs
|
|||||||
- `src/components/` — `AuthGate`, `OverviewView`, `UsageView`,
|
- `src/components/` — `AuthGate`, `OverviewView`, `UsageView`,
|
||||||
`ChartsView`/`UsageChart`, `UsageTable`, `DataTable` (the shared
|
`ChartsView`/`UsageChart`, `UsageTable`, `DataTable` (the shared
|
||||||
sortable-table wrapper — shadcn-vue's DataTable pattern, `@tanstack/
|
sortable-table wrapper — shadcn-vue's DataTable pattern, `@tanstack/
|
||||||
vue-table`, generic over row type); `ui/` holds the shadcn-vue
|
vue-table`, generic over row type), `SearchInput` (the shared search-box
|
||||||
primitives this panel actually uses (Accordion, Card, Table, Tabs,
|
— icon + shadcn `Input` + shadcn `Button` clear button — every search
|
||||||
Button, Input, Alert, Select, Badge) — nothing installed and unused.
|
filter in the panel renders); `ui/` holds the shadcn-vue primitives this
|
||||||
Providers (Overview) and Groups (Usage) render as a real Accordion —
|
panel actually uses (Accordion, Card, Table, Tabs, Button, Input, Alert,
|
||||||
expanding a group shows its member users' own usage rows, a
|
Select, Badge) — nothing installed and unused. Providers (Overview) and
|
||||||
client-side join on `AdminUsageEntryView.groupName`.
|
Groups (Usage) render as a real Accordion — expanding a group shows its
|
||||||
|
member users' own usage rows, a client-side join on
|
||||||
|
`AdminUsageEntryView.groupName`.
|
||||||
|
- `src/composables/` — `useThemeColors` (Chart.js axis/grid/legend colors
|
||||||
|
off the current design tokens), `useSearchQuery` (the shared
|
||||||
|
`query`/`normalized`/`hasQuery` state every `SearchInput` pairs with).
|
||||||
- `src/lib/` — `api.ts` (the `/admin/api/*` fetch wrapper), `format.ts`,
|
- `src/lib/` — `api.ts` (the `/admin/api/*` fetch wrapper), `format.ts`,
|
||||||
`key-storage.ts`, `chart-setup.ts`, `search-expand.ts` (search-aware
|
`key-storage.ts`, `chart-setup.ts`, `search-expand.ts` (search-aware
|
||||||
expand state, adapted to drive Accordion's v-model — shared by
|
expand state, adapted to drive Accordion's v-model — shared by
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { describe, expect, it } from 'vitest'
|
||||||
|
|
||||||
|
import { useSearchQuery } from './useSearchQuery'
|
||||||
|
|
||||||
|
describe('useSearchQuery', () => {
|
||||||
|
it('normalized trims leading/trailing whitespace', () => {
|
||||||
|
const { query, normalized } = useSearchQuery()
|
||||||
|
query.value = ' alice '
|
||||||
|
expect(normalized.value).toBe('alice')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('normalized lowercases the query', () => {
|
||||||
|
const { query, normalized } = useSearchQuery()
|
||||||
|
query.value = 'AlIcE'
|
||||||
|
expect(normalized.value).toBe('alice')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('hasQuery is false for a whitespace-only query', () => {
|
||||||
|
const { query, hasQuery } = useSearchQuery()
|
||||||
|
query.value = ' '
|
||||||
|
expect(hasQuery.value).toBe(false)
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,24 +1,26 @@
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* useSearchQuery is the one raw-query → {normalized, hasQuery, clear}
|
* useSearchQuery is the one raw-query → {normalized, hasQuery} adapter
|
||||||
* adapter every search filter in this panel uses — OverviewView's model
|
* every search filter in this panel uses — OverviewView's model search,
|
||||||
* search, UsageView's user/group search, ChartsView's scope-picker search
|
* UsageView's user/group search, ChartsView's scope-picker search all had
|
||||||
* all had their own copy of this identical query/normalizedQuery/hasQuery/
|
* their own copy of this identical query/normalizedQuery/hasQuery
|
||||||
* clearQuery quartet; extracted so it exists once (vue.md: "if you've
|
* pairing; extracted so it exists once (vue.md: "if you've written it
|
||||||
* written it twice, you owe an abstraction"). Callers still own their own
|
* twice, you owe an abstraction"). Callers still own their own matching
|
||||||
* matching logic entirely (OverviewView's modelMatches/providerMatches,
|
* logic entirely (OverviewView's modelMatches/providerMatches,
|
||||||
* lib/usage-search.ts's helpers) — this only normalizes the raw input the
|
* lib/usage-search.ts's helpers) — this only normalizes the raw input the
|
||||||
* same way every call site already agreed on: trimmed, lowercased.
|
* same way every call site already agreed on: trimmed, lowercased.
|
||||||
|
*
|
||||||
|
* No `clear()` here — clearing is just setting `query.value = ''`, and
|
||||||
|
* every caller already gets that for free from SearchInput.vue's own
|
||||||
|
* clear button emitting `update:modelValue('')` through the `v-model`
|
||||||
|
* binding, so a separate clear function would be dead API surface no
|
||||||
|
* caller needs.
|
||||||
*/
|
*/
|
||||||
export function useSearchQuery() {
|
export function useSearchQuery() {
|
||||||
const query = ref('')
|
const query = ref('')
|
||||||
const normalized = computed(() => query.value.trim().toLowerCase())
|
const normalized = computed(() => query.value.trim().toLowerCase())
|
||||||
const hasQuery = computed(() => normalized.value.length > 0)
|
const hasQuery = computed(() => normalized.value.length > 0)
|
||||||
|
|
||||||
function clear(): void {
|
return { query, normalized, hasQuery }
|
||||||
query.value = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
return { query, normalized, hasQuery, clear }
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user