fix(admin-ui): guest nav filter + suppress drafts 401
This commit is contained in:
@@ -3,6 +3,7 @@ import type { QueryClient } from '@tanstack/react-query'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { LanguageSwitch } from '@nstart/ui'
|
||||
import { AuthBadge } from '@/auth/AuthBadge'
|
||||
import { useCanMutate } from '@/auth/useCanMutate'
|
||||
import { UpdateBanner } from '@/components/version/UpdateBanner'
|
||||
import { VersionBadge } from '@/components/version/VersionBadge'
|
||||
|
||||
@@ -17,6 +18,11 @@ const LANG_OPTIONS = [
|
||||
|
||||
function RootLayout() {
|
||||
const { t, i18n } = useTranslation()
|
||||
// Гость (anonymous) видит только ссылку на /dictionaries и /search.
|
||||
// Аудит, outbox, webhooks, drafts, reviews — admin-only страницы, требуют
|
||||
// JWT (backend SecurityConfig + admin role). Скрываем из top-nav чтобы
|
||||
// user не получал 401 toast при навигации.
|
||||
const canMutate = useCanMutate()
|
||||
return (
|
||||
<div className="min-h-full flex flex-col bg-white">
|
||||
<UpdateBanner />
|
||||
@@ -33,27 +39,6 @@ function RootLayout() {
|
||||
>
|
||||
{t('nav.dictionaries')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/audit"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.audit')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/outbox"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.outbox')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/webhooks"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.webhooks')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/search"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
@@ -61,20 +46,45 @@ function RootLayout() {
|
||||
>
|
||||
{t('nav.search')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/reviews"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.reviews')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/my-drafts"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.myDrafts')}
|
||||
</Link>
|
||||
{canMutate && (
|
||||
<>
|
||||
<Link
|
||||
to="/audit"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.audit')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/outbox"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.outbox')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/webhooks"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.webhooks')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/reviews"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.reviews')}
|
||||
</Link>
|
||||
<Link
|
||||
to="/my-drafts"
|
||||
className="text-carbon hover:text-ultramarain"
|
||||
activeProps={{ className: 'text-ultramarain font-medium' }}
|
||||
>
|
||||
{t('nav.myDrafts')}
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</nav>
|
||||
<div className="ml-auto flex items-center gap-3">
|
||||
<VersionBadge />
|
||||
|
||||
@@ -136,8 +136,10 @@ function DictionaryDetail() {
|
||||
* "На review" в каждой строке records table. Polled 30s. Bypass'нем если
|
||||
* dict не approval-required (нет смысла грузить).
|
||||
*/
|
||||
// Гость (anonymous) — drafts polling требует JWT (401 каждые 30s в console).
|
||||
// Disable если не авторизован.
|
||||
const pendingDraftsQuery = useDictPendingDrafts(
|
||||
detailQuery.data?.approvalRequired ? name : undefined,
|
||||
canMutate && detailQuery.data?.approvalRequired ? name : undefined,
|
||||
)
|
||||
const pendingByKey = useMemo(() => {
|
||||
const set = new Set<string>()
|
||||
|
||||
Reference in New Issue
Block a user