diff --git a/backend/app/version.py b/backend/app/version.py index 28d1fca..789d830 100644 --- a/backend/app/version.py +++ b/backend/app/version.py @@ -1,5 +1,5 @@ """Единый источник версии SAC (API, health, логи, OpenAPI).""" APP_NAME = "Security Alert Center" -APP_VERSION = "0.20.23" +APP_VERSION = "0.20.24" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" diff --git a/frontend/package.json b/frontend/package.json index f17df46..f2499fc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ -{ +{ "name": "sac-ui", "private": true, - "version": "0.11.1", + "version": "0.11.2", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/composables/useHostRemoteAction.ts b/frontend/src/composables/useHostRemoteAction.ts index cb01be9..4053e96 100644 --- a/frontend/src/composables/useHostRemoteAction.ts +++ b/frontend/src/composables/useHostRemoteAction.ts @@ -1,4 +1,4 @@ -import { reactive } from "vue"; +import { reactive } from "vue"; import { ApiError, fetchHost, @@ -23,11 +23,29 @@ export const hostRemoteActionLog = reactive({ }); const POLL_MS = 1500; +const SUCCESS_AUTO_CLOSE_MS = 30_000; + +let successAutoCloseTimer: ReturnType | null = null; function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } +function clearSuccessAutoCloseTimer() { + if (successAutoCloseTimer != null) { + clearTimeout(successAutoCloseTimer); + successAutoCloseTimer = null; + } +} + +function scheduleSuccessAutoClose() { + clearSuccessAutoCloseTimer(); + successAutoCloseTimer = setTimeout(() => { + hostRemoteActionLog.open = false; + successAutoCloseTimer = null; + }, SUCCESS_AUTO_CLOSE_MS); +} + function applyJobToModal(job: HostRemoteActionJobStatus) { hostRemoteActionLog.title = job.title || hostRemoteActionLog.title; hostRemoteActionLog.message = job.message || hostRemoteActionLog.message; @@ -39,6 +57,9 @@ function finishModal(job: HostRemoteActionJobStatus) { hostRemoteActionLog.ok = job.ok ?? job.status === "success"; applyJobToModal(job); hostRemoteActionLog.open = true; + if (hostRemoteActionLog.ok) { + scheduleSuccessAutoClose(); + } } async function pollRemoteJob(hostId: number): Promise { @@ -83,6 +104,7 @@ export async function runHostRemoteAction( title: string, kind: HostRemoteActionKind, ): Promise { + clearSuccessAutoCloseTimer(); hostRemoteActionLog.open = true; hostRemoteActionLog.loading = true; hostRemoteActionLog.ok = null; @@ -116,6 +138,7 @@ export async function runHostRemoteAction( } export function closeHostRemoteActionLog() { + clearSuccessAutoCloseTimer(); hostRemoteActionLog.open = false; } diff --git a/frontend/src/version.ts b/frontend/src/version.ts index 61ecfb2..b1997aa 100644 --- a/frontend/src/version.ts +++ b/frontend/src/version.ts @@ -1,4 +1,4 @@ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ export const APP_NAME = "Security Alert Center"; -export const APP_VERSION = "0.20.23"; +export const APP_VERSION = "0.20.24"; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`; diff --git a/frontend/src/views/HostDetailView.vue b/frontend/src/views/HostDetailView.vue index 431d149..aeabe66 100644 --- a/frontend/src/views/HostDetailView.vue +++ b/frontend/src/views/HostDetailView.vue @@ -1,4 +1,4 @@ -