diff --git a/frontend/src/pages/SnapshotDashboard.tsx b/frontend/src/pages/SnapshotDashboard.tsx index 338e6e7..5709b55 100644 --- a/frontend/src/pages/SnapshotDashboard.tsx +++ b/frontend/src/pages/SnapshotDashboard.tsx @@ -3,6 +3,7 @@ import { DeleteOutlined, DownloadOutlined, EditOutlined, + EyeOutlined, PlayCircleOutlined, PlusOutlined, SettingOutlined, @@ -27,7 +28,7 @@ import type { ColumnsType } from 'antd/es/table' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import 'dayjs/locale/ru' -import { useMemo, useState } from 'react' +import { useMemo, useCallback, useRef, useState } from 'react' import { useSnapshotDashboard, useSnapshotPolicies, @@ -413,6 +414,15 @@ function ObjectsTable({ rowKey="object_id" size="small" pagination={false} + onRow={(record) => ({ + onClick: () => + setExpandedKeys( + expandedKeys.includes(record.object_id) + ? expandedKeys.filter((k) => k !== record.object_id) + : [...expandedKeys, record.object_id] + ), + style: { cursor: 'pointer' }, + })} expandable={{ expandedRowKeys: expandedKeys, onExpand: (expanded, record) => @@ -486,6 +496,9 @@ function DevicesList({ policyId: number }) { const { data: devices, isLoading } = useDashboardDevices(objId, policyId, true) + const [viewContent, setViewContent] = useState(null) + const [viewTitle, setViewTitle] = useState('') + const contentRef = useRef(null) const handleCopy = async (snapshotId: number) => { try { @@ -513,6 +526,30 @@ function DevicesList({ } } + const handleView = async (device: DeviceSnapshotStatus) => { + if (!device.snapshot_id) return + try { + const content = await fetchSnapshotContent(device.snapshot_id) + setViewTitle(`${device.hostname || device.ip} — ${objName}`) + setViewContent(content) + } catch { + message.error('Ошибка при загрузке') + } + } + + const handleSelectAll = useCallback((e: React.KeyboardEvent) => { + if ((e.ctrlKey || e.metaKey) && e.key === 'a') { + e.preventDefault() + if (contentRef.current) { + const range = document.createRange() + range.selectNodeContents(contentRef.current) + const sel = window.getSelection() + sel?.removeAllRanges() + sel?.addRange(range) + } + } + }, []) + if (isLoading) return Загрузка... if (!devices || devices.length === 0) return Нет устройств @@ -554,10 +591,18 @@ function DevicesList({ { title: '', key: 'actions', - width: 80, + width: 120, render: (_, row) => row.snapshot_id ? ( + +