From 2cc1c71cfaeccfc850bb653505a819e935e56acd Mon Sep 17 00:00:00 2001 From: dv Date: Thu, 28 May 2026 16:13:57 +0300 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D1=84=D0=B8=D0=BA?= =?UTF-8?q?=D1=81=20=D1=84=D0=B8=D0=BA=D1=81=20=D1=84=D0=B8=D0=BA=D1=81=20?= =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D1=84=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/routers/snapshot_policies.py | 3 +- frontend/src/api/snapshotPolicies.ts | 1 + frontend/src/pages/SnapshotDashboard.tsx | 176 ++++++++++++++--------- 3 files changed, 114 insertions(+), 66 deletions(-) diff --git a/backend/app/routers/snapshot_policies.py b/backend/app/routers/snapshot_policies.py index e9c2f32..ee3f234 100644 --- a/backend/app/routers/snapshot_policies.py +++ b/backend/app/routers/snapshot_policies.py @@ -269,7 +269,7 @@ async def dashboard_devices( # All eligible devices for this object+category devices_q = ( - select(Device.id, Device.ip, Device.hostname) + select(Device.id, Device.ip, Device.hostname, Device.status) .where( Device.object_id == obj_id, Device.category == policy.category, @@ -324,6 +324,7 @@ async def dashboard_devices( "device_id": d.id, "ip": d.ip, "hostname": d.hostname, + "status": d.status, "has_snapshot": has_snapshot, "last_collected_at": latest_map.get(d.id), "snapshot_id": snap_info[0] if snap_info else None, diff --git a/frontend/src/api/snapshotPolicies.ts b/frontend/src/api/snapshotPolicies.ts index e85c053..b3a219d 100644 --- a/frontend/src/api/snapshotPolicies.ts +++ b/frontend/src/api/snapshotPolicies.ts @@ -135,6 +135,7 @@ export interface DeviceSnapshotStatus { device_id: number ip: string hostname: string | null + status: string | null has_snapshot: boolean last_collected_at: string | null snapshot_id: number | null diff --git a/frontend/src/pages/SnapshotDashboard.tsx b/frontend/src/pages/SnapshotDashboard.tsx index 79ddb16..338e6e7 100644 --- a/frontend/src/pages/SnapshotDashboard.tsx +++ b/frontend/src/pages/SnapshotDashboard.tsx @@ -291,13 +291,12 @@ export function SnapshotDashboardPage() { {objects.length} ), - children: objects.map((obj) => ( - handleCollectObj(policyId, obj.object_id)} + children: ( + - )), + ), }))} /> @@ -331,51 +330,58 @@ export function SnapshotDashboardPage() { ) } -function ObjectPoliciesTable({ - obj, +function ObjectsTable({ + objects, onCollect, }: { - obj: ObjectSnapshotSummary - onCollect: (policyId: number) => void + objects: ObjectSnapshotSummary[] + onCollect: (policyId: number, objId: number) => void }) { - const [expandedKey, setExpandedKey] = useState(null) + const [expandedKeys, setExpandedKeys] = useState([]) - const columns: ColumnsType = [ + const columns: ColumnsType = [ { - title: 'Политика', - dataIndex: 'policy_label', - key: 'label', - }, - { - title: 'Категория', - dataIndex: 'category', - key: 'category', - render: (cat: string) => {cat}, + title: 'Объект', + key: 'name', + render: (_, obj) => ( + + {obj.object_name} + {obj.client && — {obj.client}} + + ), }, { title: 'Последний сбор', - dataIndex: 'last_collected_at', key: 'last_collected', - render: (val: string | null) => - val ? ( - - {dayjs(val).fromNow()} + width: 160, + render: (_, obj) => { + const latest = obj.policies.reduce((acc, p) => { + if (!p.last_collected_at) return acc + if (!acc) return p.last_collected_at + return p.last_collected_at > acc ? p.last_collected_at : acc + }, null) + return latest ? ( + + {dayjs(latest).fromNow()} ) : ( - ), + ) + }, }, { title: 'Покрытие', key: 'coverage', - render: (_, row) => { - const { success_count, total_devices } = row - if (total_devices === 0) return нет устройств - const ratio = success_count / total_devices + width: 120, + render: (_, obj) => { + const total = obj.policies.reduce((s, p) => s + p.total_devices, 0) + const success = obj.policies.reduce((s, p) => s + p.success_count, 0) + if (total === 0) return нет устройств + const ratio = success / total const color = ratio >= 1 ? 'green' : ratio > 0 ? 'orange' : 'red' return ( - {success_count} / {total_devices} + {success} / {total} ) }, @@ -383,16 +389,16 @@ function ObjectPoliciesTable({ { title: '', key: 'actions', - width: 60, - render: (_, row) => ( - + width: 50, + render: (_, obj) => ( +