mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
fix(printers): refuse to add a printer when the MQTT probe fails (#empty-card-reports)
Several support reports traced back to one root cause: a mistyped access
code in Add Printer left an empty card on the dashboard. POST /printers/
was persisting the row first, then firing connect_printer() fire-and-forget.
Now we test_connection() BEFORE the insert; failure returns HTTP 400 and
the row is never written.
Structured error response -- detail={"code", "message"} -- so the toast
shows the localized message instead of the English fallback. New
ApiError.code field on the frontend; printers.toast.connectionFailedNotAdded
This commit is contained in:
@@ -4,10 +4,15 @@ const API_BASE = '/api/v1';
|
||||
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
constructor(message: string, status: number) {
|
||||
/** Stable error code from a structured backend detail (`{code, message}`).
|
||||
* Frontend uses this to look up an i18n key instead of showing the raw
|
||||
* English fallback. Null when the backend returned a plain-string detail. */
|
||||
code: string | null;
|
||||
constructor(message: string, status: number, code: string | null = null) {
|
||||
super(message);
|
||||
this.name = 'ApiError';
|
||||
this.status = status;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +110,7 @@ async function request<T>(
|
||||
const error = await response.json().catch(() => ({}));
|
||||
const detail = error.detail;
|
||||
let message: string;
|
||||
let code: string | null = null;
|
||||
if (typeof detail === 'string') {
|
||||
message = detail;
|
||||
} else if (Array.isArray(detail)) {
|
||||
@@ -117,6 +123,11 @@ async function request<T>(
|
||||
.filter(Boolean)
|
||||
.join('; ');
|
||||
message = joined || JSON.stringify(detail) || `HTTP ${response.status}`;
|
||||
} else if (detail && typeof detail === 'object') {
|
||||
// Structured detail `{code, message}` — frontend uses the code to
|
||||
// pick an i18n key, message is the English fallback.
|
||||
code = typeof detail.code === 'string' ? detail.code : null;
|
||||
message = typeof detail.message === 'string' ? detail.message : `HTTP ${response.status}`;
|
||||
} else {
|
||||
message = `HTTP ${response.status}`;
|
||||
}
|
||||
@@ -136,7 +147,7 @@ async function request<T>(
|
||||
}
|
||||
}
|
||||
|
||||
throw new ApiError(message, response.status);
|
||||
throw new ApiError(message, response.status, code);
|
||||
}
|
||||
|
||||
// Handle empty responses (204 No Content, etc.)
|
||||
|
||||
Reference in New Issue
Block a user