Setup: manage multiple device instances per category (add/remove)
The data model was already multi-instance (lane_devices = one row per instance; assign always inserts) -- the limitation was UI-only. Make the whole flow support more than one of every category: - Backend: add DELETE /api/setup/assign/:id (unassign by id). /state now redacts secrets (pushPassword/webPassword/relayPassword) via a shared redactSecrets() also used by /assign -- it was returning raw config rows. - Web: SetupWizard reworked from one fixed slot per category into a list of assigned instances (driver/role/host + Remove) plus an "Add another" form. select-type config fields (e.g. printer role) now render as dropdowns. - api.ts: add fetchState(), unassignDevice(), Assignment/SetupState types. Verified via Fastify inject: two printers assigned to one lane both list, no secret leak, delete -> 204, delete unknown -> 404, count drops to 1. Full repo typechecks. Wiki: first-run-setup documents multi-instance + delete + redaction.
This commit is contained in:
+27
-1
@@ -160,6 +160,32 @@ export interface AssignBody {
|
||||
}
|
||||
|
||||
/** Save + configure the device (preconditions, push setup), then persist. */
|
||||
export function assignDevice(body: AssignBody): Promise<{ id: string }> {
|
||||
export function assignDevice(body: AssignBody): Promise<Assignment> {
|
||||
return apiFetch("/api/setup/assign", { method: "POST", body: JSON.stringify(body) });
|
||||
}
|
||||
|
||||
/** A persisted device assignment (one per instance; secrets stripped). */
|
||||
export interface Assignment {
|
||||
id: string;
|
||||
lane: number;
|
||||
category: DeviceCategory;
|
||||
driverId: string;
|
||||
config: DeviceConfig;
|
||||
enabled: boolean;
|
||||
createdAt?: string;
|
||||
}
|
||||
|
||||
export interface SetupState {
|
||||
completedAt: string | null;
|
||||
assignments: Assignment[];
|
||||
}
|
||||
|
||||
/** Current setup status + all assigned device instances. */
|
||||
export function fetchState(): Promise<SetupState> {
|
||||
return apiFetch<SetupState>("/api/setup/state");
|
||||
}
|
||||
|
||||
/** Remove one assigned device instance by id. */
|
||||
export function unassignDevice(id: string): Promise<void> {
|
||||
return apiFetch(`/api/setup/assign/${id}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user