From 8bf56d13258ccfed1da5897d210619e9a6af1a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iwo=20Strzebo=C5=84ski?= Date: Thu, 29 Oct 2026 10:21:34 +0000 Subject: [PATCH] Add printer controls to the fleet cards: pause, resume, stop, fan The console could only watch. A printer card now offers what POST /printers/:id/commands accepts and a person should press: pause while printing, resume while paused, and a fan percentage. Stop is the one command with no undo (the printer reports FAILED), so it sits apart from Pause and needs a second, named confirmation ("Cancel ? ... cannot be resumed"). Offline and never-reported printers get no controls, since every command would be refused as unreachable. A successful reply only means the printer accepted the command, so the notice says to watch the status line rather than claiming the state changed. The backend's own error message is shown for a 403, 409 or 502. PrinterControls takes a `send` function like the card takes `signal`, so @continuum/ui still knows nothing of the API; no function, no controls. send_gcode_line and start_print are deliberately not offered here. Verified in real Chrome against the live stack with the command requests intercepted in the browser (the H2C was mid-print): controls render per state, Stop shows its confirmation and Keep printing sends nothing, the body is {action:"set_fan_speed",percent:100}, a 409 surfaces its message, no page errors. pnpm -r typecheck is clean. --- apps/web/pages/index.vue | 19 ++- packages/ui/src/components/PrinterCard.vue | 10 +- .../ui/src/components/PrinterControls.vue | 158 ++++++++++++++++++ packages/ui/src/index.ts | 3 +- packages/ui/src/types.ts | 10 ++ 5 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 packages/ui/src/components/PrinterControls.vue diff --git a/apps/web/pages/index.vue b/apps/web/pages/index.vue index abc297a..6395f30 100644 --- a/apps/web/pages/index.vue +++ b/apps/web/pages/index.vue @@ -1,5 +1,5 @@ + + + + diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 73adc55..0ab3fab 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -1,4 +1,5 @@ export { default as PrinterCard } from "./components/PrinterCard.vue"; +export { default as PrinterControls } from "./components/PrinterControls.vue"; export { default as TemperatureGraph } from "./components/TemperatureGraph.vue"; export { default as WebRTCStreamView } from "./components/WebRTCStreamView.vue"; -export type { AppPrinterState, AppTelemetryMessage } from "./types"; +export type { AppPrinterState, AppTelemetryMessage, PrinterCommand } from "./types"; diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index d77edeb..c0a33fe 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -48,3 +48,13 @@ export interface AppPrinterState { export type AppTelemetryMessage = | { type: "ready"; visiblePrinters: number } | { type: "printer.telemetry"; printer: AppPrinterState }; + +/** + * What `POST /printers/:id/commands` accepts: the edge schema's + * `printer_command.schema.json`, minus `start_print` (a job's dispatch sends + * that, never a person) and `send_gcode_line` (arbitrary g-code is not + * offered to a button). Hand-mirrored like the rest of this file. + */ +export type PrinterCommand = + | { action: "control_print"; control: "pause" | "resume" | "stop" } + | { action: "set_fan_speed"; percent: number };