fix(backups): восстанавливать вкладку и фильтры из ссылки

This commit is contained in:
Denozordec committed 2026-10-01 16:37:34 +07:00
1 parent 6f152c8dfe
commit 11e357cc94
8 files changed
+187 -12

No files matched your search

+7 -10
View File
@@ -1,10 +1,9 @@
"use client"
import { useCallback, useEffect, useRef, useState } from "react"
import { Suspense, useCallback, useEffect, useRef, useState } from "react"
import { PageHeader } from "@/components/page-header"
import { backups as mockBackups, servers as mockServers, type Backup, type Server } from "@/lib/data"
import { createFilterQuery } from "@/components/reui/filters/filters-query"
import type { FilterQuery } from "@/components/reui/filters/filters-types"
import { useBackupsUrlState } from "@/hooks/use-backups-url-state"
import { backupStorageSettingsDtoSchema, type BackupScheduleSettingsDto, type BackupStorageSettingsDto } from "@mmapp/contracts/backups"
import { KpiStatGrid } from "@/components/reui-kit/kpi-stat-grid"
import { Alert, AlertAction, AlertDescription, AlertTitle } from "@/components/reui/alert"
@@ -56,13 +55,13 @@ import { BackupCreateSheet } from "@/components/backups/backup-create-sheet"
import { BackupDeleteDialog, BackupRestoreDialog } from "@/components/backups/backup-confirm-dialogs"
type PageTab = "history" | "settings"
type KindFilter = "all" | "auto" | "manual"
type Resource = "backups" | "servers" | "schedule" | "storage"
type ResourceState = { known: boolean; error: string | null; receivedAt: string | null }
const unknownResource = (): ResourceState => ({ known: false, error: null, receivedAt: null })
export default function BackupsPage() {
export default function BackupsPage() { return <Suspense fallback={<p role="status" className="p-5">Загрузка контекста резервных копий…</p>}><BackupsSource /></Suspense> }
function BackupsSource() {
const { mode, backendUrl, prefsHydrated } = useDataSource()
if (!prefsHydrated) return <p role="status" className="p-5">Загрузка настроек источника…</p>
return <BackupsContent key={mode + ":" + backendUrl} />
@@ -86,11 +85,8 @@ function BackupsContent() {
const settingsController = useRef<AbortController | null>(null)
const known = (resource: Resource) => !isLive || resources[resource].known
const current = (resource: Resource) => known(resource) && !resources[resource].error
const [tab, setTab] = useState<PageTab>("history")
const { tab, setTab, kindFilter, setKindFilter, search, setSearch, filters: advancedFilters, setFilters: setAdvancedFilters, error: urlError, reset: resetContext } = useBackupsUrlState()
const [backupList, setBackupList] = useState<Backup[]>(isLive ? [] : mockBackups)
const [kindFilter, setKindFilter] = useState<KindFilter>("all")
const [search, setSearch] = useState("")
const [advancedFilters, setAdvancedFilters] = useState<FilterQuery>(() => createFilterQuery())
const [liveServers, setLiveServers] = useState<Server[]>(isLive ? [] : mockServers)
const baseCanCreate = canWrite && canReadServers && liveServers.length > 0 && current("servers") && current("storage")
const [loading, setLoading] = useState(false)
@@ -400,6 +396,7 @@ function BackupsContent() {
<div className="flex-1 overflow-y-auto p-6">
<div className="flex flex-col gap-5">
{urlError && <Alert variant="warning" aria-label="Контекст резервных копий"><AlertTitle>Не удалось прочитать ссылку</AlertTitle><AlertDescription>{urlError}</AlertDescription><AlertAction><Button type="button" variant="outline" onClick={resetContext}>Сбросить контекст</Button></AlertAction></Alert>}
{!isLive && <p role="status" className="text-sm text-muted-foreground">Демонстрационные данные. Операции и сохранение недоступны.</p>}
{!canRead && <p role="status">Нет права mm:backups:read</p>}
{isLive && !canReadServers && <p role="status">Каталог устройств недоступен без mm:servers:read.</p>}
@@ -483,7 +480,7 @@ function BackupsContent() {
<TabsTrigger value="settings">Настройки</TabsTrigger>
</TabsList>
<TabsContent value="history" className="flex flex-col gap-5">
{!canRead ? <p role="status">История недоступна без права чтения</p> : !known("backups") ? <p role="status">{resources.backups.error ? "История резервных копий пока неизвестна" : "Загрузка резервных копий…"}</p> : <BackupsHistory
{urlError ? null : !canRead ? <p role="status">История недоступна без права чтения</p> : !known("backups") ? <p role="status">{resources.backups.error ? "История резервных копий пока неизвестна" : "Загрузка резервных копий…"}</p> : <BackupsHistory
backups={backupList}
kindFilter={kindFilter}
onKindFilterChange={setKindFilter}