From 571a2c0ca77015580fd2d92e057caa1c97edab6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Thu, 29 Oct 2026 14:41:26 +0000 Subject: [PATCH] Show each farm's gateway status and what discovery found When the fleet page is empty or a printer is "unknown", the reason is almost always upstream: the gateway is not connected, or discovery never reported. A strip per farm now says which - "Gateway online/offline/ checking" (no answer yet is not offline) - with a collapsible list of the printers discovery found, each marked already added, same address as an added printer, or not added yet, using the backend's serial/address match. It also says plainly when discovery has not reported at all, which is the default, as distinct from a scan that found nothing. Read-only on purpose: adding a printer from the UI still needs the proxy's offline-capable store and a credential pass-through that is never kept in the cloud. Polled every 10s (gateway presence has no push channel); a failed poll keeps the last answer instead of flipping to offline. Checked in real Chrome against the live stack (Gateway online, discovery not reported, no page errors); the static SPA still generates, now 6 routes. --- apps/web/pages/index.vue | 33 +++++++++- packages/ui/src/components/FarmStatus.vue | 75 +++++++++++++++++++++++ packages/ui/src/index.ts | 3 +- packages/ui/src/types.ts | 22 +++++++ 4 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 packages/ui/src/components/FarmStatus.vue diff --git a/apps/web/pages/index.vue b/apps/web/pages/index.vue index fe3507c..4c851c2 100644 --- a/apps/web/pages/index.vue +++ b/apps/web/pages/index.vue @@ -1,5 +1,12 @@ + + + + diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 2278115..955be66 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -4,4 +4,5 @@ export { default as TemperatureGraph } from "./components/TemperatureGraph.vue"; export { default as WebRTCStreamView } from "./components/WebRTCStreamView.vue"; export { default as JobList } from "./components/JobList.vue"; export { default as JobUpload } from "./components/JobUpload.vue"; -export type { AppFarm, AppJob, AppPrinterState, AppTelemetryMessage, PrinterCommand } from "./types"; +export { default as FarmStatus } from "./components/FarmStatus.vue"; +export type { AppDiscoveredCandidate, AppFarm, AppFarmDiscovery, AppJob, AppPrinterState, AppTelemetryMessage, PrinterCommand } from "./types"; diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index 7257fb3..c3bc1ac 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -79,3 +79,25 @@ export interface AppJob { progressPct?: number | null; createdAt: string; } + +/** + * `GET /farms/:id/discovered-printers`. `discovery` is null when the gateway + * has never reported a scan - almost always because discovery is off, which + * is its default - and that is not the same as a report with no printers. + */ +export interface AppDiscoveredCandidate { + address: string; + vendor: string; + name?: string | null; + model?: string | null; + serial?: string | null; + /** The printer row this candidate looks like, and how sure that is. */ + existingPrinterId?: string | null; + matchedOn?: "serial" | "address" | null; +} + +export interface AppFarmDiscovery { + farmId: string; + gatewayOnline: boolean; + discovery: { scannedAt: string; printers: AppDiscoveredCandidate[] } | null; +}