fix(ui): учитывать готовность устройства в действиях IPsec
This commit is contained in:
1 parent
b8923d075d
commit
f0071a495c
7 files changed
+97
-12
No files matched your search
@@ -300,6 +300,13 @@ function IpsecPage() {
|
||||
const failedServerIds = new Set(failures.map(f => f.serverId))
|
||||
const scopeUnknown = isLive && (!hasLoaded || !!dataError || (effectiveServerId === ALL_SERVERS_ID ? failures.length > 0 : failedServerIds.has(effectiveServerId)))
|
||||
|
||||
const canManage = (serverId: string) => isLive && hasLoaded && !dataError && !inventoryError &&
|
||||
!loading && !busy && !historyRestoring && !failedServerIds.has(serverId) && liveServers.some(s => s.id === serverId)
|
||||
const assertDeviceReady = (serverId: string) => {
|
||||
if (!canManage(serverId)) throw new Error("Сначала подтвердите актуальное состояние устройства: повторите опрос IPsec")
|
||||
}
|
||||
const hasReadyDevice = displayServers.some(s => canManage(s.id))
|
||||
|
||||
const scopedClients = useMemo(() => {
|
||||
if (effectiveServerId === ALL_SERVERS_ID) return displayClients
|
||||
return displayClients.filter((c) => c.serverId === effectiveServerId)
|
||||
@@ -370,6 +377,7 @@ function IpsecPage() {
|
||||
}, [displayServers, displayClients])
|
||||
|
||||
const handleInit = async (form: IpsecInitFormState) => {
|
||||
assertDeviceReady(form.serverId)
|
||||
setBusy(true)
|
||||
try {
|
||||
await initIpsecServer(backendUrl, {
|
||||
@@ -391,6 +399,7 @@ function IpsecPage() {
|
||||
}
|
||||
|
||||
const handleCreateUser = async (form: IpsecUserFormState) => {
|
||||
assertDeviceReady(form.serverId)
|
||||
setBusy(true)
|
||||
try {
|
||||
const res = await createIpsecUser(backendUrl, {
|
||||
@@ -424,6 +433,7 @@ function IpsecPage() {
|
||||
|
||||
const handleEditUser = async (form: IpsecUserFormState) => {
|
||||
if (!editing) return
|
||||
assertDeviceReady(editing.serverId)
|
||||
setBusy(true)
|
||||
try {
|
||||
await patchIpsecUser(backendUrl, editing.serverId, editing.rosId, {
|
||||
@@ -490,6 +500,8 @@ function IpsecPage() {
|
||||
const confirmDelete = async (force = false) => {
|
||||
if (!pendingDelete || deleteLock.current || (force && !forceAllowed)) return
|
||||
const target = pendingDelete
|
||||
const serverId = target.kind === "user" ? target.client.serverId : target.kind === "server" ? target.summary.serverId : target.serverId
|
||||
if (!canManage(serverId)) { setDeleteError("Повторите опрос IPsec перед удалением"); return }
|
||||
deleteLock.current = true
|
||||
setBusy(true)
|
||||
setDeleteError(null)
|
||||
@@ -523,6 +535,7 @@ function IpsecPage() {
|
||||
|
||||
const handleEditPeer = async (form: IpsecPeerFormState) => {
|
||||
if (!editingPeer) return
|
||||
assertDeviceReady(editingPeer.serverId)
|
||||
setBusy(true)
|
||||
try {
|
||||
await patchIpsecPeer(backendUrl, editingPeer.serverId, editingPeer.peer.rosId, {
|
||||
@@ -586,7 +599,7 @@ function IpsecPage() {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={loading}
|
||||
disabled={loading || busy || historyRestoring}
|
||||
onClick={() => void loadLive()}
|
||||
>
|
||||
<RefreshCwIcon className={`size-4 ${loading ? "animate-spin" : ""}`} />
|
||||
@@ -597,7 +610,7 @@ function IpsecPage() {
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
disabled={loading || !historyServerId}
|
||||
disabled={loading || busy || historyRestoring || !historyServerId}
|
||||
title={!historyServerId ? "Выберите сервер, чтобы смотреть историю" : "История версий и откат"}
|
||||
onClick={() => {
|
||||
setHistoryOpen(true)
|
||||
@@ -609,7 +622,7 @@ function IpsecPage() {
|
||||
</Button>
|
||||
)}
|
||||
{isLive ? (
|
||||
<Button size="sm" onClick={() => setUserOpen(true)}>
|
||||
<Button size="sm" disabled={!hasReadyDevice} onClick={() => setUserOpen(true)}>
|
||||
<PlusIcon className="size-4" />
|
||||
Новый клиент
|
||||
</Button>
|
||||
@@ -713,7 +726,7 @@ function IpsecPage() {
|
||||
searchPlaceholder="Поиск по имени / CN / IP…"
|
||||
actions={
|
||||
isLive ? (
|
||||
<Button size="sm" onClick={() => { setEditing(null); setUserOpen(true) }}>
|
||||
<Button size="sm" disabled={!hasReadyDevice} onClick={() => { setEditing(null); setUserOpen(true) }}>
|
||||
<PlusIcon className="size-4" />
|
||||
Клиент
|
||||
</Button>
|
||||
@@ -722,6 +735,7 @@ function IpsecPage() {
|
||||
/>
|
||||
{isLive && !hasLoaded ? <p role="status" className="p-5 text-sm text-muted-foreground">{loading ? "Загрузка клиентов IPsec…" : "Клиенты IPsec пока неизвестны"}</p> : <IpsecUsersGrid
|
||||
clients={filteredClients}
|
||||
canManage={canManage}
|
||||
emptyTitle={scopeUnknown ? "Клиенты IPsec пока неизвестны" : undefined}
|
||||
emptyDescription={scopeUnknown ? "Повторите опрос устройств, чтобы подтвердить состояние" : undefined}
|
||||
compactServer={compactServer}
|
||||
@@ -735,6 +749,7 @@ function IpsecPage() {
|
||||
<TabsContent value="server" className="mt-0 outline-none">
|
||||
{isLive && !hasLoaded ? <p role="status" className="p-5 text-sm text-muted-foreground">Состояние серверов IPsec пока неизвестно</p> : <IpsecServerGrid
|
||||
servers={scopedSummaries}
|
||||
canManage={canManage}
|
||||
onInit={isLive ? (s) => { setSelectedServerId(s.serverId); setInitOpen(true) } : undefined}
|
||||
onRemove={isLive ? (s) => setPendingDelete({ kind: "server", summary: s }) : undefined}
|
||||
onEditPeer={isLive ? openEditPeer : undefined}
|
||||
@@ -814,7 +829,7 @@ function IpsecPage() {
|
||||
<IpsecUserSheet
|
||||
open={userOpen}
|
||||
onOpenChange={(v) => { setUserOpen(v); if (!v) setEditing(null) }}
|
||||
servers={serverOptions}
|
||||
servers={serverOptions.filter(s => canManage(s.id) || busy)}
|
||||
peers={peerOptions}
|
||||
busy={busy}
|
||||
defaultServerId={sheetServerId}
|
||||
|
||||
Reference in new issue
Block a user