fix(ui): подтверждать перемещение правил Filters

This commit is contained in:
Denozordec committed 2026-09-30 11:35:36 +07:00
1 parent c4011cfaff
commit 7554f1804b
6 files changed
+138 -24

No files matched your search

+31 -15
View File
@@ -1361,6 +1361,9 @@ export default function FiltersPage() {
const [deletePending, setDeletePending] = useState(false)
const [deleteError, setDeleteError] = useState<string | null>(null)
const deleteLock = useRef(false)
const [movePending, setMovePending] = useState(false)
const [moveError, setMoveError] = useState<string | null>(null)
const moveLock = useRef(false)
const [liveStale, setLiveStale] = useState(false)
const [historyOpen, setHistoryOpen] = useState(false)
const [historyLoading, setHistoryLoading] = useState(false)
@@ -1458,7 +1461,7 @@ export default function FiltersPage() {
const allTunnels = !isLive || liveLoadState === "error" ? greTunnels : (greByServer[selectedServerId] ?? [])
const selectedServer = allServers.find(s => s.id === selectedServerId) ?? allServers[0]
const totalRules = rulesets.reduce((s, r) => s + r.rules.length, 0)
const mutationsLocked = isLive && (applyBusy || historyRestoring || liveStale || liveLoadState !== "idle")
const mutationsLocked = movePending || (isLive && (applyBusy || historyRestoring || liveStale || liveLoadState !== "idle"))
const filterRailItems = useMemo<ServerTileItem[]>(() => (
allServers.map((s) => ({
@@ -1479,6 +1482,7 @@ export default function FiltersPage() {
setSheetOpen(false)
setPendingDelete(null)
setDeleteError(null)
setMoveError(null)
setSelectedServerId(id)
setSearch("")
}, [])
@@ -1677,18 +1681,25 @@ export default function FiltersPage() {
const result = await applyRules(targetServerId, next, "copy")
return result.ok ? null : result.error ?? "Не удалось скопировать правила"
}, [rulesets, applyRules])
const handleMoveUp = (index: number) => {
if (mutationsLocked || index === 0) return
updateRules(selectedServerId, rules => {
const n = [...rules]; [n[index - 1], n[index]] = [n[index], n[index - 1]]; return n
})
}
const handleMoveDown = (index: number) => {
if (mutationsLocked) return
updateRules(selectedServerId, rules => {
if (index >= rules.length - 1) return rules
const n = [...rules]; [n[index], n[index + 1]] = [n[index + 1], n[index]]; return n
})
const handleMove = async (id: string, direction: -1 | 1) => {
if (mutationsLocked || applyLock.current || moveLock.current) return
const index = currentRules.findIndex(r => r.id === id)
const destination = index + direction
if (index < 0 || destination < 0 || destination >= currentRules.length) return
moveLock.current = true
setMovePending(true)
setMoveError(null)
const next = [...currentRules]
;[next[index], next[destination]] = [next[destination], next[index]]
try {
const result = await applyRules(selectedServerId, next)
if (!result.ok) setMoveError(result.error ?? "Не удалось переместить правило")
} catch (error) {
setMoveError(error instanceof Error ? error.message : "Не удалось переместить правило")
} finally {
moveLock.current = false
setMovePending(false)
}
}
if (isLive && liveLoadState === "loading") {
@@ -1868,6 +1879,9 @@ export default function FiltersPage() {
</div>
</div>
{movePending && <p role="status" className="px-5 py-2 text-sm text-muted-foreground">Ожидание подтверждения порядка…</p>}
{moveError && <p role="alert" className="px-5 py-2 text-sm text-destructive">{moveError}</p>}
{currentRules.length === 0 ? (
/* empty state */
<EmptyState
@@ -1896,6 +1910,8 @@ export default function FiltersPage() {
) : (
<FiltersDataGrid
rules={search ? filteredRules : currentRules}
orderedRules={currentRules}
mutationsLocked={mutationsLocked}
tunnelsList={allTunnels}
serversList={allServers}
communityNameMap={communityNameMap}
@@ -1903,8 +1919,8 @@ export default function FiltersPage() {
enableSorting={!!search}
onEdit={openEdit}
onDelete={handleDelete}
onMoveUp={(id) => handleMoveUp(currentRules.findIndex((r) => r.id === id))}
onMoveDown={(id) => handleMoveDown(currentRules.findIndex((r) => r.id === id))}
onMoveUp={(id) => { void handleMove(id, -1) }}
onMoveDown={(id) => { void handleMove(id, 1) }}
/>
)}