Merge branch 'fix/sidebar-mydrafts-badge-status-filter' into 'main'
fix(admin-ui): sidebar badges — actionable only See merge request 2-6/2-6-4/terravault/ordinis!260
This commit is contained in:
@@ -19,7 +19,6 @@ import {
|
|||||||
useHasInternalScope,
|
useHasInternalScope,
|
||||||
} from '@/auth/usePermissions'
|
} from '@/auth/usePermissions'
|
||||||
import {
|
import {
|
||||||
useDictionaries,
|
|
||||||
useMyDrafts,
|
useMyDrafts,
|
||||||
useMySchemaDrafts,
|
useMySchemaDrafts,
|
||||||
useOutboxStats,
|
useOutboxStats,
|
||||||
@@ -28,6 +27,7 @@ import {
|
|||||||
} from '@/api/queries'
|
} from '@/api/queries'
|
||||||
import { Sheet, SheetContent, SheetTitle } from '@/ui'
|
import { Sheet, SheetContent, SheetTitle } from '@/ui'
|
||||||
import { ThemeSwitch } from '@/components/layout/ThemeSwitch'
|
import { ThemeSwitch } from '@/components/layout/ThemeSwitch'
|
||||||
|
import { classifyRecordStatus, classifySchemaStatus } from '@/components/reviews/MyDraftsPanel'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,12 +82,18 @@ export function Sidebar() {
|
|||||||
const canReviewSchema = useCanReviewSchema()
|
const canReviewSchema = useCanReviewSchema()
|
||||||
const canReviewRecord = useCanReviewRecord()
|
const canReviewRecord = useCanReviewRecord()
|
||||||
const isReviewer = canReviewSchema || canReviewRecord
|
const isReviewer = canReviewSchema || canReviewRecord
|
||||||
const dictsQuery = useDictionaries()
|
|
||||||
// Loaded just for сидбар counter — light request, кэшируется.
|
// Loaded just for сидбар counter — light request, кэшируется.
|
||||||
// Badge "Мои черновики" суммирует record (/drafts/me) + schema
|
// Badge "Мои черновики" суммирует record (/drafts/me) + schema
|
||||||
// (/admin/schema-drafts/me) — maker не должен помнить разные типы.
|
// (/admin/schema-drafts/me) — maker не должен помнить разные типы.
|
||||||
const myDrafts = useMyDrafts(0, 1)
|
//
|
||||||
const mySchemaDrafts = useMySchemaDrafts(0, 1)
|
// page=0 size=50 (не size=1!) — backend /drafts/me возвращает ВСЕ статусы
|
||||||
|
// (PENDING + APPROVED + REJECTED + WITHDRAWN), а totalElements не умеет
|
||||||
|
// filter по статусу. Нужно фильтровать на клиенте: считаем только
|
||||||
|
// pending/WIP-драфты, чтобы approved/rejected не «висели» в badge.
|
||||||
|
// Reuse: на /reviews этот же query (size=50) уже зовётся → TanStack
|
||||||
|
// дедуплицирует по queryKey, лишних запросов нет.
|
||||||
|
const myDrafts = useMyDrafts(0, 50)
|
||||||
|
const mySchemaDrafts = useMySchemaDrafts(0, 50)
|
||||||
// Reviews badge — суммирует record-reviews + schema-reviews pending queues
|
// Reviews badge — суммирует record-reviews + schema-reviews pending queues
|
||||||
// через size=1 paged запросы. Gated на authenticated.
|
// через size=1 paged запросы. Gated на authenticated.
|
||||||
const reviews = useReviewsBadgeCount(auth.isAuthenticated)
|
const reviews = useReviewsBadgeCount(auth.isAuthenticated)
|
||||||
@@ -99,9 +105,17 @@ export function Sidebar() {
|
|||||||
const outboxStats = useOutboxStats(hasInternal)
|
const outboxStats = useOutboxStats(hasInternal)
|
||||||
const webhooks = useWebhookSubscriptions(hasInternal)
|
const webhooks = useWebhookSubscriptions(hasInternal)
|
||||||
|
|
||||||
const dictsCount = dictsQuery.data?.length ?? 0
|
// Считаем только actionable-драфты (то же что tab-badge в ReviewsPage):
|
||||||
const myDraftsCount =
|
// record → 'pending', schema → 'pending'|'wip'. APPROVED/REJECTED/WITHDRAWN
|
||||||
(myDrafts.data?.totalElements ?? 0) + (mySchemaDrafts.data?.totalElements ?? 0)
|
// — терминальны, не считаем.
|
||||||
|
const myRecordPending = (myDrafts.data?.items ?? []).filter(
|
||||||
|
(r) => classifyRecordStatus(r.status) === 'pending',
|
||||||
|
).length
|
||||||
|
const mySchemaPending = (mySchemaDrafts.data?.items ?? []).filter((s) => {
|
||||||
|
const b = classifySchemaStatus(s.status)
|
||||||
|
return b === 'pending' || b === 'wip'
|
||||||
|
}).length
|
||||||
|
const myDraftsCount = myRecordPending + mySchemaPending
|
||||||
const reviewsCount = reviews.total
|
const reviewsCount = reviews.total
|
||||||
// Pending events ждут dispatch. dlq отдельно — alarming, но не блокирует
|
// Pending events ждут dispatch. dlq отдельно — alarming, но не блокирует
|
||||||
// нормальную работу, можно увидеть на /outbox. Badge показывает только
|
// нормальную работу, можно увидеть на /outbox. Badge показывает только
|
||||||
@@ -123,7 +137,9 @@ export function Sidebar() {
|
|||||||
to: '/dictionaries',
|
to: '/dictionaries',
|
||||||
label: t('nav.dictionaries'),
|
label: t('nav.dictionaries'),
|
||||||
icon: Database,
|
icon: Database,
|
||||||
badge: dictsCount > 0 ? dictsCount : undefined,
|
// Без badge: total count словарей — не actionable, только шумит
|
||||||
|
// (на проде ~40 dicts, цифра не меняется в течение работы юзера).
|
||||||
|
// Actionable badges остаются: «Мои черновики», «На ревью», «Outbox».
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/my-drafts',
|
to: '/my-drafts',
|
||||||
@@ -468,18 +484,27 @@ export function MobileSidebar({ open, onClose }: { open: boolean; onClose: () =>
|
|||||||
const canReviewSchema = useCanReviewSchema()
|
const canReviewSchema = useCanReviewSchema()
|
||||||
const canReviewRecord = useCanReviewRecord()
|
const canReviewRecord = useCanReviewRecord()
|
||||||
const isReviewer = canReviewSchema || canReviewRecord
|
const isReviewer = canReviewSchema || canReviewRecord
|
||||||
const dictsQuery = useDictionaries()
|
// size=50 (не size=1): см. desktop Sidebar — нужен .items[] для filter
|
||||||
const myDrafts = useMyDrafts(0, 1)
|
// по статусу (totalElements включает APPROVED/REJECTED).
|
||||||
const mySchemaDrafts = useMySchemaDrafts(0, 1)
|
const myDrafts = useMyDrafts(0, 50)
|
||||||
|
const mySchemaDrafts = useMySchemaDrafts(0, 50)
|
||||||
const reviews = useReviewsBadgeCount(auth.isAuthenticated)
|
const reviews = useReviewsBadgeCount(auth.isAuthenticated)
|
||||||
// Same INTERNAL-scope gate as desktop Sidebar (см. line ~92).
|
// Same INTERNAL-scope gate as desktop Sidebar (см. line ~92).
|
||||||
const hasInternal = useHasInternalScope()
|
const hasInternal = useHasInternalScope()
|
||||||
const outboxStats = useOutboxStats(hasInternal)
|
const outboxStats = useOutboxStats(hasInternal)
|
||||||
const webhooks = useWebhookSubscriptions(hasInternal)
|
const webhooks = useWebhookSubscriptions(hasInternal)
|
||||||
|
|
||||||
const dictsCount = dictsQuery.data?.length ?? 0
|
// Считаем только actionable-драфты (то же что tab-badge в ReviewsPage):
|
||||||
const myDraftsCount =
|
// record → 'pending', schema → 'pending'|'wip'. APPROVED/REJECTED/WITHDRAWN
|
||||||
(myDrafts.data?.totalElements ?? 0) + (mySchemaDrafts.data?.totalElements ?? 0)
|
// — терминальны, не считаем.
|
||||||
|
const myRecordPending = (myDrafts.data?.items ?? []).filter(
|
||||||
|
(r) => classifyRecordStatus(r.status) === 'pending',
|
||||||
|
).length
|
||||||
|
const mySchemaPending = (mySchemaDrafts.data?.items ?? []).filter((s) => {
|
||||||
|
const b = classifySchemaStatus(s.status)
|
||||||
|
return b === 'pending' || b === 'wip'
|
||||||
|
}).length
|
||||||
|
const myDraftsCount = myRecordPending + mySchemaPending
|
||||||
const reviewsCount = reviews.total
|
const reviewsCount = reviews.total
|
||||||
const outboxPending = outboxStats.data?.pending ?? 0
|
const outboxPending = outboxStats.data?.pending ?? 0
|
||||||
const webhooksActive =
|
const webhooksActive =
|
||||||
@@ -494,7 +519,9 @@ export function MobileSidebar({ open, onClose }: { open: boolean; onClose: () =>
|
|||||||
to: '/dictionaries',
|
to: '/dictionaries',
|
||||||
label: t('nav.dictionaries'),
|
label: t('nav.dictionaries'),
|
||||||
icon: Database,
|
icon: Database,
|
||||||
badge: dictsCount > 0 ? dictsCount : undefined,
|
// Без badge: total count словарей — не actionable, только шумит
|
||||||
|
// (на проде ~40 dicts, цифра не меняется в течение работы юзера).
|
||||||
|
// Actionable badges остаются: «Мои черновики», «На ревью», «Outbox».
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: '/my-drafts',
|
to: '/my-drafts',
|
||||||
|
|||||||
Reference in New Issue
Block a user