diff --git a/ordinis-admin-ui/src/components/editor/EditorInfoPanel.tsx b/ordinis-admin-ui/src/components/editor/EditorInfoPanel.tsx index 664808a..56e2417 100644 --- a/ordinis-admin-ui/src/components/editor/EditorInfoPanel.tsx +++ b/ordinis-admin-ui/src/components/editor/EditorInfoPanel.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react' import { Link } from '@tanstack/react-router' import { useTranslation } from 'react-i18next' -import { ClockCounterClockwiseIcon, MapTrifoldIcon } from '@phosphor-icons/react' +import { ClockCounterClockwiseIcon, MapTrifoldIcon, DownloadSimpleIcon } from '@phosphor-icons/react' import { Badge } from '@/ui' import { useDictionaryDependents } from '@/api/queries' import type { DictionaryDetail } from '@/api/client' @@ -25,13 +25,15 @@ import { cn } from '@/lib/utils' export type EditorInfoPanelProps = { detail: DictionaryDetail recordCount: number - /** Optional action buttons (Time-travel / AOI filter) — bottom of panel + /** Optional action buttons (Time-travel / AOI / Export) — bottom of panel * per redesign prototype. Toggle handlers come from route's state. */ actions?: { onTimeTravel?: () => void timeTravelActive?: boolean onAoi?: () => void aoiActive?: boolean + onExport?: () => void + exportPending?: boolean } } @@ -109,6 +111,19 @@ export function EditorInfoPanel({ detail, recordCount, actions }: EditorInfoPane {t('aoi.button', { defaultValue: 'AOI фильтр…' })} )} + {actions.onExport && ( + + )} )} diff --git a/ordinis-admin-ui/src/routes/dictionaries.$name.tsx b/ordinis-admin-ui/src/routes/dictionaries.$name.tsx index 416fabf..bbaa025 100644 --- a/ordinis-admin-ui/src/routes/dictionaries.$name.tsx +++ b/ordinis-admin-ui/src/routes/dictionaries.$name.tsx @@ -570,6 +570,17 @@ function DictionaryDetail() { timeTravelActive: Boolean(timeTravelAt), onAoi: () => setAoiOpen(true), aoiActive: Boolean(aoi), + onExport: () => { + // Export all visible records (filtered + paginated set OR full + // dictionary). Если selection непустой — exports selection, + // иначе — все filtered records. + const keys = + selection.size > 0 + ? Array.from(selection) + : filteredRecords.map((r) => r.businessKey) + if (keys.length > 0) bulkExportMut.mutate(keys) + }, + exportPending: bulkExportMut.isPending, }} /> )}