+
+
{t("pbs.title")}
+
+
+
+
+ {(connectionError || statusError) &&
+ {String((connectionError || statusError)?.message || t("pbs.loadFailed"))}
}
+ {isLoading &&
{t("pbs.loading")}
}
+ {!selected && !connectionError && connections &&
{t("pbs.noServer")}
}
+ {manage &&
+ {t("pbs.manage")}
+
+ {t("pbs.permissionsHelp")}
+
+
+ {(["name", "url", "token_id", "token_secret", "fingerprint"] as const).map(field =>
+
+
+ setForm({ ...form, [field]: event.target.value })} />
+
)}
+
+ {t("pbs.tlsHelp")}
+ {error && {error}
}
+ {message && {message}
}
+
+
+ {form.id && }
+
+
+ }
+ {data && <>
+
{data.name} · PBS {data.version || "—"} · {t("pbs.sampled")} {new Date(data.fetched_at * 1000).toLocaleTimeString()}
+ {Object.keys(data.services).length > 0 &&
+ {Object.entries(data.services).map(([service, state]) => {service}: {state})}
+
}
+ {Object.entries(data.errors).map(([section, detail]) =>
{t(`pbs.${section}`)}: {detail}
)}
+
{t("pbs.datastores")}
+ {data.datastores?.length === 0 && {t("pbs.noDatastores")}
}
+ {data.datastores && data.datastores.length > 0 &&
+ | {t("pbs.name")} | {t("pbs.total")} | {t("pbs.used")} | {t("pbs.free")} |
+ {data.datastores.map(row => | {row.name}{row.error && {row.error} } | {capacity(row.total)} | {capacity(row.used)} | {capacity(row.avail)} |
)}
+
}
+
+
{t("pbs.tasks")}
+ {data.tasks?.length === 0 && {t("pbs.noTasks")}
}
+ {data.tasks && data.tasks.length > 0 &&
+ | {t("pbs.task")} | {t("pbs.started")} | {t("pbs.status")} |
+ {data.tasks.map(row => | {row.worker_type} {row.worker_id} | {row.starttime ? new Date(row.starttime * 1000).toLocaleString() : "—"} | {row.status || (row.endtime ? "—" : t("pbs.running"))} |
)}
+
}
+
+
{t("pbs.jobs")}
+
+ | {t("pbs.job")} | {t("pbs.datastores")} | {t("pbs.schedule")} | {t("pbs.status")} |
+ {(["sync", "verify", "prune"] as const).flatMap(kind => (data[kind] || []).map(row =>
+ | {t(`pbs.${kind}`)} · {row.id} | {row.store || "—"} | {row.schedule || "—"} | {row["last-run-state"] || "—"} |
))}
+
+
+ >}
+
+}
diff --git a/AppImage/components/proxmox-dashboard.tsx b/AppImage/components/proxmox-dashboard.tsx
index c09ea165..679c9aaf 100644
--- a/AppImage/components/proxmox-dashboard.tsx
+++ b/AppImage/components/proxmox-dashboard.tsx
@@ -18,6 +18,7 @@ import { Security } from "./security"
import { Profile } from "./profile"
import { About } from "./about"
import { BackupTab } from "./backup-tab"
+import { PBSDashboard } from "./pbs-dashboard"
import { OnboardingCarousel } from "./onboarding-carousel"
import { HealthStatusModal } from "./health-status-modal"
import { ReleaseNotesModal, useVersionCheck } from "./release-notes-modal"
@@ -96,6 +97,14 @@ interface FlaskSystemInfo {
const _dashboardPrefetchFetcher = (url: string) => fetchApi(url)
export function ProxmoxDashboard() {
+ const t = useT()
+ const { data, error } = useSWR<{ product: string }>("/api/platform", url => fetchApi<{ product: string }>(url), { revalidateOnFocus: false })
+ if (!data && !error) return