fix(admin-ui): хвосты — 404 на CREATE-черновиках + Radix DialogTitle warning
1. reviews.tsx: ReviewDrawer звал useLiveRecord для ЛЮБОГО черновика,
включая CREATE. У CREATE-черновика live-записи нет по определению →
GET /dictionaries/{id}/records/{key} → 404 (красный шум в консоли на
каждый CREATE-draft). Теперь для CREATE запрос не запускается, блок
«текущая версия» показывает «нет текущей версии».
2. modal.tsx: Modal рендерил DialogTitle только при наличии prop title.
Без title Radix писал в консоль «DialogContent requires a DialogTitle»
+ warning про aria-describedby. Теперь Modal всегда рендерит DialogTitle
(sr-only fallback) и гасит aria-describedby когда описания нет.
This commit is contained in:
@@ -614,9 +614,13 @@ function ReviewDrawer({ draftId, onClose }: DrawerProps) {
|
|||||||
const currentSub = auth.user?.profile?.sub
|
const currentSub = auth.user?.profile?.sub
|
||||||
const draftQ = useDraft(draftId)
|
const draftQ = useDraft(draftId)
|
||||||
const draft = draftQ.data
|
const draft = draftQ.data
|
||||||
|
// CREATE-черновик не имеет live-записи по определению — не пробуем её
|
||||||
|
// загружать (GET /dictionaries/{id}/records/{key} → 404, красный шум в
|
||||||
|
// консоли на каждый CREATE-draft). Для UPDATE/CLOSE — грузим как раньше.
|
||||||
|
const isCreateDraft = draft?.operation === 'CREATE'
|
||||||
const liveQ = useLiveRecord(
|
const liveQ = useLiveRecord(
|
||||||
draft ? draft.dictionaryId : undefined,
|
draft && !isCreateDraft ? draft.dictionaryId : undefined,
|
||||||
draft ? draft.businessKey : undefined,
|
draft && !isCreateDraft ? draft.businessKey : undefined,
|
||||||
)
|
)
|
||||||
const approveMut = useApproveDraft()
|
const approveMut = useApproveDraft()
|
||||||
const rejectMut = useRejectDraft()
|
const rejectMut = useRejectDraft()
|
||||||
@@ -810,7 +814,7 @@ function ReviewDrawer({ draftId, onClose }: DrawerProps) {
|
|||||||
{t('reviews.drawer.live')}
|
{t('reviews.drawer.live')}
|
||||||
</p>
|
</p>
|
||||||
{liveQ.isLoading && <LoadingBlock size="sm" label={t('loading')} />}
|
{liveQ.isLoading && <LoadingBlock size="sm" label={t('loading')} />}
|
||||||
{liveQ.data === null && (
|
{(liveQ.data === null || isCreateDraft) && (
|
||||||
<p className="text-cell text-mute italic">
|
<p className="text-cell text-mute italic">
|
||||||
{t('reviews.drawer.noLive')}
|
{t('reviews.drawer.noLive')}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -70,13 +70,24 @@ export function Modal({
|
|||||||
if (!open) onClose()
|
if (!open) onClose()
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DialogContent size={resolved} hideClose={hideClose} className={panelClassName}>
|
<DialogContent
|
||||||
|
size={resolved}
|
||||||
|
hideClose={hideClose}
|
||||||
|
className={panelClassName}
|
||||||
|
// Без DialogDescription Radix предупреждает о missing aria-describedby —
|
||||||
|
// явно гасим, когда описания нет.
|
||||||
|
{...(description ? {} : { 'aria-describedby': undefined })}
|
||||||
|
>
|
||||||
{(title || description) && (
|
{(title || description) && (
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
{title && <DialogTitle>{title}</DialogTitle>}
|
{title && <DialogTitle>{title}</DialogTitle>}
|
||||||
{description && <DialogDescription>{description}</DialogDescription>}
|
{description && <DialogDescription>{description}</DialogDescription>}
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
)}
|
)}
|
||||||
|
{/* Radix требует DialogTitle в каждом DialogContent для скринридеров.
|
||||||
|
* Если callsite не передал title — рендерим sr-only fallback, иначе
|
||||||
|
* console-warning + диалог без названия для a11y. */}
|
||||||
|
{!title && <DialogTitle className="sr-only">Диалог</DialogTitle>}
|
||||||
{bodyClassName ? <div className={bodyClassName}>{children}</div> : children}
|
{bodyClassName ? <div className={bodyClassName}>{children}</div> : children}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
Reference in New Issue
Block a user