fix(frontend): auto-close WinRM update success panel after 30s (0.20.24)

Remote action log dock closes on successful fallback; no duplicate inline message.
This commit is contained in:
PTah
2026-06-21 20:41:42 +10:00
parent 5bd1333928
commit b3d28cd5d8
5 changed files with 32 additions and 7 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
"""Единый источник версии SAC (API, health, логи, OpenAPI).""" """Единый источник версии SAC (API, health, логи, OpenAPI)."""
APP_NAME = "Security Alert Center" APP_NAME = "Security Alert Center"
APP_VERSION = "0.20.23" APP_VERSION = "0.20.24"
APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}" APP_VERSION_LABEL = f"{APP_NAME} v.{APP_VERSION}"
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"name": "sac-ui", "name": "sac-ui",
"private": true, "private": true,
"version": "0.11.1", "version": "0.11.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -1,4 +1,4 @@
import { reactive } from "vue"; import { reactive } from "vue";
import { import {
ApiError, ApiError,
fetchHost, fetchHost,
@@ -23,11 +23,29 @@ export const hostRemoteActionLog = reactive({
}); });
const POLL_MS = 1500; const POLL_MS = 1500;
const SUCCESS_AUTO_CLOSE_MS = 30_000;
let successAutoCloseTimer: ReturnType<typeof setTimeout> | null = null;
function sleep(ms: number): Promise<void> { function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms)); 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) { function applyJobToModal(job: HostRemoteActionJobStatus) {
hostRemoteActionLog.title = job.title || hostRemoteActionLog.title; hostRemoteActionLog.title = job.title || hostRemoteActionLog.title;
hostRemoteActionLog.message = job.message || hostRemoteActionLog.message; hostRemoteActionLog.message = job.message || hostRemoteActionLog.message;
@@ -39,6 +57,9 @@ function finishModal(job: HostRemoteActionJobStatus) {
hostRemoteActionLog.ok = job.ok ?? job.status === "success"; hostRemoteActionLog.ok = job.ok ?? job.status === "success";
applyJobToModal(job); applyJobToModal(job);
hostRemoteActionLog.open = true; hostRemoteActionLog.open = true;
if (hostRemoteActionLog.ok) {
scheduleSuccessAutoClose();
}
} }
async function pollRemoteJob(hostId: number): Promise<HostRemoteActionJobStatus> { async function pollRemoteJob(hostId: number): Promise<HostRemoteActionJobStatus> {
@@ -83,6 +104,7 @@ export async function runHostRemoteAction(
title: string, title: string,
kind: HostRemoteActionKind, kind: HostRemoteActionKind,
): Promise<HostRemoteActionJobStatus | null> { ): Promise<HostRemoteActionJobStatus | null> {
clearSuccessAutoCloseTimer();
hostRemoteActionLog.open = true; hostRemoteActionLog.open = true;
hostRemoteActionLog.loading = true; hostRemoteActionLog.loading = true;
hostRemoteActionLog.ok = null; hostRemoteActionLog.ok = null;
@@ -116,6 +138,7 @@ export async function runHostRemoteAction(
} }
export function closeHostRemoteActionLog() { export function closeHostRemoteActionLog() {
clearSuccessAutoCloseTimer();
hostRemoteActionLog.open = false; hostRemoteActionLog.open = false;
} }
+1 -1
View File
@@ -1,4 +1,4 @@
/** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */ /** Fallback до загрузки /health; при релизе держите в sync с backend/app/version.py */
export const APP_NAME = "Security Alert Center"; 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}`; export const APP_VERSION_LABEL = `${APP_NAME} v.${APP_VERSION}`;
+4 -2
View File
@@ -1,4 +1,4 @@
<template> <template>
<p><RouterLink to="/hosts"> Хосты</RouterLink></p> <p><RouterLink to="/hosts"> Хосты</RouterLink></p>
<p v-if="error" class="error">{{ error }}</p> <p v-if="error" class="error">{{ error }}</p>
<p v-else-if="loading">Загрузка</p> <p v-else-if="loading">Загрузка</p>
@@ -623,9 +623,11 @@ async function runAgentFallback() {
const job = await runHostRemoteAction(hostId.value, title, "fallback"); const job = await runHostRemoteAction(hostId.value, title, "fallback");
if (job) { if (job) {
agentControlOk.value = job.ok ?? false; agentControlOk.value = job.ok ?? false;
agentControlMessage.value = job.message || "";
if (job.ok) { if (job.ok) {
agentControlMessage.value = "";
await loadHost(); await loadHost();
} else {
agentControlMessage.value = job.message || "";
} }
} }
} finally { } finally {