Implement automatic media list refresh in MediaPanel: add activity tracking for queued and processing items, ensuring the media list updates when statuses change. Enhance query handling with refetch logic to improve user experience in media management.
build / backend (push) Successful in 3m38s
build / frontend (push) Successful in 1m6s
tests / backend-tests (push) Successful in 3m3s

This commit is contained in:
Leonid Pershin
2026-07-26 16:06:02 +03:00
parent b5a47c6d8a
commit 8fa4ea02fe
@@ -1,5 +1,5 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { FolderInput, ListPlus, Upload } from 'lucide-react' import { FolderInput, ListPlus, Upload } from 'lucide-react'
import { HttpError } from '@/shared/api/client' import { HttpError } from '@/shared/api/client'
@@ -62,7 +62,7 @@ export function MediaPanel() {
toggle(key) toggle(key)
} }
const { data, isLoading } = useQuery({ const { data, isLoading, refetch } = useQuery({
queryKey: ['admin', 'media', filter, page, sort.key, sort.desc], queryKey: ['admin', 'media', filter, page, sort.key, sort.desc],
queryFn: () => queryFn: () =>
listMedia({ listMedia({
@@ -87,6 +87,20 @@ export function MediaPanel() {
(query.state.data?.queued ?? 0) + (query.state.data?.processing ?? 0) > 0 ? 4000 : 15000, (query.state.data?.queued ?? 0) + (query.state.data?.processing ?? 0) > 0 ? 4000 : 15000,
}) })
/**
* Сводка очереди опрашивается всегда, и она же служит датчиком: изменилась пара
* «в очереди / в обработке» — значит какая-то запись сменила статус, и список пора перечитать.
* Без этого список обновлялся бы, только пока активные записи видны на текущей странице: при
* фильтре «Готовые» или пустом списке опрос выключался, и новый файл из inbox не появлялся.
*/
const activity = `${stats?.queued ?? 0}:${stats?.processing ?? 0}`
const lastActivity = useRef(activity)
useEffect(() => {
if (lastActivity.current === activity) return
lastActivity.current = activity
void refetch()
}, [activity, refetch])
const invalidate = () => queryClient.invalidateQueries({ queryKey: ['admin', 'media'] }) const invalidate = () => queryClient.invalidateQueries({ queryKey: ['admin', 'media'] })
const onError = (error: unknown) => const onError = (error: unknown) =>
toast.error(error instanceof HttpError ? error.detail : t('common.error')) toast.error(error instanceof HttpError ? error.detail : t('common.error'))