mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
feat(admin): surface the GeoLite2 availability state on the system status page
Both the `/admin` overview snapshot and the full `/admin/system-status` page now read `offlineGeoEnabled` from `/api/version` and render a status row with a green chip when the offline databases are loaded or a yellow chip with the configuration hint when the runtime is on the ipwho.is fallback. The row only renders when the field is present so legacy `/api/version` responses do not produce a placeholder slot. Adds six locale keys per bundle (`admin.offlineGeoLabel`, `offlineGeoEnabled`, `offlineGeoFallback` plus the three `admin.overview.snapshotOfflineGeo*` siblings) across all six locales.
This commit is contained in:
1 parent
4eb22387a2
commit
82a23069a5
8 files changed
+99
No files matched your search
@@ -13,15 +13,36 @@ import {
|
||||
Globe,
|
||||
Key,
|
||||
Loader2,
|
||||
Map,
|
||||
RotateCw,
|
||||
Server,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { formatDateTime } from "@/lib/format";
|
||||
import { useFormatters, useTranslations } from "@/lib/i18n/context";
|
||||
import { StatusItem, useSystemStatus } from "./_shared";
|
||||
|
||||
interface VersionResponse {
|
||||
version: string;
|
||||
buildSha: string | null;
|
||||
builtAt: string | null;
|
||||
offlineGeoEnabled?: boolean;
|
||||
}
|
||||
|
||||
function useOfflineGeoState() {
|
||||
return useQuery({
|
||||
queryKey: ["public", "version"],
|
||||
queryFn: async () => {
|
||||
const res = await fetch("/api/version");
|
||||
if (!res.ok) throw new Error("Failed to load version");
|
||||
return (await res.json()).data as VersionResponse;
|
||||
},
|
||||
staleTime: 5 * 60_000,
|
||||
});
|
||||
}
|
||||
|
||||
// v1.4.16 phase B3: Recharts is ~108 KiB Brotli — defer-load the host
|
||||
// metrics chart so the system-status page only ships it when an admin
|
||||
// actually opens this view. Splitting at the wrapper boundary (instead
|
||||
@@ -44,6 +65,7 @@ export function SystemStatusSection() {
|
||||
const { t } = useTranslations();
|
||||
const fmt = useFormatters();
|
||||
const { data: status, isError, refetch, isFetching } = useSystemStatus();
|
||||
const { data: version } = useOfflineGeoState();
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -163,6 +185,25 @@ export function SystemStatusSection() {
|
||||
className="text-dracula-green"
|
||||
/>
|
||||
)}
|
||||
{/* v1.4.27 R5 — offline GeoLite2 availability. Renders only
|
||||
when /api/version returns the new field so legacy
|
||||
responses do not produce a placeholder row. */}
|
||||
{version?.offlineGeoEnabled !== undefined && (
|
||||
<StatusItem
|
||||
icon={Map}
|
||||
label={t("admin.offlineGeoLabel")}
|
||||
value={
|
||||
version.offlineGeoEnabled
|
||||
? t("admin.offlineGeoEnabled")
|
||||
: t("admin.offlineGeoFallback")
|
||||
}
|
||||
className={
|
||||
version.offlineGeoEnabled
|
||||
? "text-dracula-green"
|
||||
: "text-dracula-yellow"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : isError ? (
|
||||
// P19: surface load failures inline instead of leaving the
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
Cog,
|
||||
Database,
|
||||
GitCommit,
|
||||
Globe,
|
||||
Loader2,
|
||||
Server,
|
||||
Tag,
|
||||
@@ -30,6 +31,7 @@ interface VersionResponse {
|
||||
version: string;
|
||||
buildSha: string | null;
|
||||
builtAt: string | null;
|
||||
offlineGeoEnabled?: boolean;
|
||||
}
|
||||
|
||||
function useVersion() {
|
||||
@@ -116,6 +118,26 @@ export function SystemStatusSummary() {
|
||||
value={formatDateTime(version.builtAt)}
|
||||
/>
|
||||
)}
|
||||
{/* v1.4.27 R5 — surface the offline-geo state so the maintainer
|
||||
spots the missing MAXMIND_LICENSE_KEY without crawling logs.
|
||||
The field is undefined on legacy responses; the row only
|
||||
renders when /api/version answers the new shape. */}
|
||||
{version?.offlineGeoEnabled !== undefined && (
|
||||
<StatusItem
|
||||
icon={Globe}
|
||||
label={t("admin.overview.snapshotOfflineGeo")}
|
||||
value={
|
||||
version.offlineGeoEnabled
|
||||
? t("admin.overview.snapshotOfflineGeoOn")
|
||||
: t("admin.overview.snapshotOfflineGeoOff")
|
||||
}
|
||||
className={
|
||||
version.offlineGeoEnabled
|
||||
? "text-dracula-green"
|
||||
: "text-dracula-yellow"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : isError ? (
|
||||
<div
|
||||
|
||||
Reference in new issue
Block a user