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 <job>? ... 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.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { PrinterCard, type AppPrinterState } from "@continuum/ui";
|
||||
import { PrinterCard, type AppPrinterState, type PrinterCommand } from "@continuum/ui";
|
||||
import { useTelemetryStore } from "~/stores/telemetry";
|
||||
|
||||
const telemetry = useTelemetryStore();
|
||||
@@ -47,6 +47,22 @@ async function signalOffer(printerId: string, sdp: string): Promise<string> {
|
||||
return answer.sdp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends one command to a printer and turns a refusal into a sentence.
|
||||
*
|
||||
* The backend's `{ error: { message } }` body is what explains a 403 (a
|
||||
* viewer cannot command), a 409 (no gateway connected) or a 502 (the printer
|
||||
* would not do it), so it is surfaced rather than a bare "fetch failed".
|
||||
*/
|
||||
async function sendCommand(printerId: string, command: PrinterCommand): Promise<void> {
|
||||
try {
|
||||
await apiFetch(`/printers/${printerId}/commands`, { method: "POST", body: command });
|
||||
} catch (err) {
|
||||
const body = (err as { data?: { error?: { message?: string } } }).data;
|
||||
throw new Error(body?.error?.message ?? "the command could not be sent");
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
printers,
|
||||
(list) => {
|
||||
@@ -76,6 +92,7 @@ watch(
|
||||
:printer="current(printer)"
|
||||
:stream="streams[printer.id]"
|
||||
:signal="(sdp: string) => signalOffer(printer.id, sdp)"
|
||||
:send="(command: PrinterCommand) => sendCommand(printer.id, command)"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="!printers?.length">
|
||||
|
||||
Reference in New Issue
Block a user