fix(admin-ui): UserPicker — TextInput fallback когда cache пустой
Если /api/v1/admin/users возвращает [] (cache пустой / writer только-что рестартован / у юзера нет INTERNAL scope → 403 → catch → []), picker показывал «Пользователи не найдены» и фильтр становился недоступен. До MR !263 здесь был обычный TextInput, не лишаем юзера возможности вписать UUID руками. При isLoading=false, isError=false, data.length===0 — рендерим TextInput с подсказкой «Список юзеров пуст — введите вручную». Backend cache прогреется по мере того как юзеры будут делать authenticated requests (JwtUserCaptureFilter перепишет user_display_cache); тогда picker включится автоматически.
This commit is contained in:
@@ -2,7 +2,7 @@ import * as React from 'react'
|
|||||||
import { useMemo, useState } from 'react'
|
import { useMemo, useState } from 'react'
|
||||||
import { CaretDownIcon, MagnifyingGlassIcon, UserIcon, XIcon } from '@phosphor-icons/react'
|
import { CaretDownIcon, MagnifyingGlassIcon, UserIcon, XIcon } from '@phosphor-icons/react'
|
||||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from 'cmdk'
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from 'cmdk'
|
||||||
import { Popover, PopoverTrigger, PopoverContent, FieldLabel } from '@/ui'
|
import { Popover, PopoverTrigger, PopoverContent, FieldLabel, TextInput } from '@/ui'
|
||||||
import { useAllUsers, type UserListItem } from '@/api/queries'
|
import { useAllUsers, type UserListItem } from '@/api/queries'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
@@ -38,11 +38,32 @@ export function UserPicker({ value, onChange, label, placeholder, disabled }: Us
|
|||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const usersQ = useAllUsers()
|
const usersQ = useAllUsers()
|
||||||
|
|
||||||
|
// Fallback на TextInput если cache пустой или endpoint вернул 403/404 (юзер
|
||||||
|
// без INTERNAL scope, либо writer был только-что рестартован и cache не
|
||||||
|
// прогрелся). Без этого user-фильтр становится недоступен — раньше тут был
|
||||||
|
// TextInput, не лишаем юзера возможности вписать UUID руками.
|
||||||
|
const usersList = usersQ.data ?? []
|
||||||
|
const fallbackToTextInput =
|
||||||
|
!usersQ.isLoading && !usersQ.isError && usersList.length === 0
|
||||||
|
|
||||||
const usersBySub = useMemo(() => {
|
const usersBySub = useMemo(() => {
|
||||||
const m = new Map<string, UserListItem>()
|
const m = new Map<string, UserListItem>()
|
||||||
for (const u of usersQ.data ?? []) m.set(u.sub, u)
|
for (const u of usersList) m.set(u.sub, u)
|
||||||
return m
|
return m
|
||||||
}, [usersQ.data])
|
}, [usersList])
|
||||||
|
|
||||||
|
if (fallbackToTextInput) {
|
||||||
|
return (
|
||||||
|
<TextInput
|
||||||
|
label={label}
|
||||||
|
value={value ?? ''}
|
||||||
|
onChange={(e) => onChange(e.target.value || undefined)}
|
||||||
|
placeholder="UUID или username"
|
||||||
|
hint="Список юзеров пуст — введите вручную"
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const selected = value ? usersBySub.get(value) : undefined
|
const selected = value ? usersBySub.get(value) : undefined
|
||||||
const triggerLabel = useMemo(() => {
|
const triggerLabel = useMemo(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user