fix(containers): подтверждать остановку и удаление контейнера

This commit is contained in:
Denozordec committed 2026-10-14 19:03:58 +07:00
1 parent b3d11276dd
commit 74151176d7
20 files changed
+414 -28

No files matched your search

+6 -3
View File
@@ -375,9 +375,12 @@ function ContainersContent() {
const stopped = scoped.filter((c) => c.status === "stopped").length
const errors = scoped.filter((c) => c.status === "error").length
const statusKnown = known && scoped.every(container => container.status !== "unknown")
const currentDeleteTarget = deleteTarget ? displayContainers.find(row => row.id === deleteTarget.id && row.rosId === deleteTarget.rosId && row.serverId === deleteTarget.serverId) : undefined
const deleteStopped = currentDeleteTarget?.status === "stopped"
async function mutate(c: ContainerView, action: ContainerAction) {
if (!isLive || !c.rosId || !canWrite || !nodeFresh(c.serverId) || mutationLock.current || !displayContainers.some(row => row.id === c.id && row.rosId === c.rosId && row.serverId === c.serverId)) return
if (action === "remove" && !displayContainers.some(row => row.id === c.id && row.rosId === c.rosId && row.serverId === c.serverId && row.status === "stopped")) return
mutationLock.current = true
const controller = new AbortController()
mutationController.current = controller
@@ -623,12 +626,12 @@ function ContainersContent() {
{deleteTarget && <AlertDialog open onOpenChange={open => { if (!open && !busyId) { setDeleteTarget(null); setOperationError(null) } }}>
<AlertDialogContent>
<AlertDialogHeader><AlertDialogTitle>Удалить контейнер?</AlertDialogTitle><AlertDialogDescription>{deleteTarget.name} · сервер {serverById[deleteTarget.serverId]?.name ?? deleteTarget.serverId}. Будет отправлена команда удаления в RouterOS.</AlertDialogDescription></AlertDialogHeader>
<AlertDialogHeader><AlertDialogTitle>Удалить контейнер?</AlertDialogTitle><AlertDialogDescription>{deleteTarget.name} · сервер {serverById[deleteTarget.serverId]?.name ?? deleteTarget.serverId}. {deleteStopped ? "Будет удалён остановленный контейнер. Дополнительная очистка файлов не выполняется." : "Сначала закройте это окно, остановите контейнер через меню действий и обновите каталог. Удаление доступно только после подтверждённой остановки."}</AlertDialogDescription></AlertDialogHeader>
{operationError && <p role="alert" aria-label="Удаление контейнера" className="text-sm text-destructive [overflow-wrap:anywhere]">{operationError}</p>}
<AlertDialogFooter>
{commandNeedsRead && <Button type="button" variant="outline" disabled={loading || !!busyId} onClick={() => { void loadLive() }}>Обновить каталог</Button>}
{(commandNeedsRead || !deleteStopped) && <Button type="button" variant="outline" disabled={loading || !!busyId} onClick={() => { void loadLive() }}>Обновить каталог</Button>}
<AlertDialogCancel disabled={!!busyId}>Отмена</AlertDialogCancel>
<AlertDialogAction type="button" variant="destructive" disabled={!!busyId || !nodeFresh(deleteTarget.serverId) || !displayContainers.some(row => row.id === deleteTarget.id && row.rosId === deleteTarget.rosId)} aria-busy={!!busyId} onClick={() => { void mutate(deleteTarget, "remove") }}>{busyId ? "Удаление…" : "Удалить"}</AlertDialogAction>
<AlertDialogAction type="button" variant="destructive" disabled={!!busyId || !deleteStopped || !nodeFresh(deleteTarget.serverId)} aria-busy={!!busyId} onClick={() => { void mutate(deleteTarget, "remove") }}>{busyId ? "Удаление…" : "Удалить"}</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>}