mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 21:47:39 +02:00
Fix cross-model queue items being misrepresented and editable into a broken state (#671)
The edit dialog offered a printer picker and target-model dropdown for an item with alternatives. Saving left a row with variants AND a printer_id, and the scheduler's fixed-printer branch wins that race, so it dispatched a row whose library_file_id is still null and failed in the upload. PATCH now refuses printer/model changes on such an item — comparing against the current value, since the dialog re-sends target_model unchanged — and the route eager-loads variants, without which the guard could not see them and every PATCH response dropped the alternatives from its payload. Names come from a shared helper now. A cross-model item holds neither archive_id nor library_file_id until dispatch, so five separate inlined fallbacks all rendered "File #null"; they now read "x1c.gcode.3mf +1 more". The queue also grouped these under "Any H2D" — the first candidate mirrored onto the row — filing a job under a printer it might never run on. It groups as "Any H2D / X1C", matching the row beneath it.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Display name for a queue item, wherever one is shown.
|
||||
*
|
||||
* Every surface used to inline the same fallback chain, which produced
|
||||
* `File #null` for a cross-model item (#671): those deliberately hold neither
|
||||
* `archive_id` nor `library_file_id` until dispatch resolves a candidate, so
|
||||
* that the ON DELETE CASCADE on `library_file_id` can't destroy the whole job
|
||||
* when one alternative is deleted. Nothing to point at is the design working;
|
||||
* the label just had nowhere to look.
|
||||
*/
|
||||
|
||||
interface NameableQueueItem {
|
||||
archive_name?: string | null;
|
||||
library_file_name?: string | null;
|
||||
archive_id?: number | null;
|
||||
library_file_id?: number | null;
|
||||
variants?: Array<{ filename: string }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param item the queue item to name
|
||||
* @param moreLabel formats the "+N more" suffix for a cross-model item; pass
|
||||
* the caller's `t` binding so the count stays translated.
|
||||
* Omitted in compact surfaces that only have room for a name.
|
||||
*/
|
||||
export function queueItemDisplayName(
|
||||
item: NameableQueueItem,
|
||||
moreLabel?: (count: number) => string,
|
||||
): string {
|
||||
if (item.archive_name) return item.archive_name;
|
||||
if (item.library_file_name) return item.library_file_name;
|
||||
|
||||
// Cross-model item: name it after the candidate the user put first — the one
|
||||
// the scheduler will try first — and say how many others are behind it.
|
||||
const variants = item.variants ?? [];
|
||||
if (variants.length > 0) {
|
||||
const first = variants[0].filename;
|
||||
const others = variants.length - 1;
|
||||
if (others > 0 && moreLabel) return `${first} ${moreLabel(others)}`;
|
||||
return first;
|
||||
}
|
||||
|
||||
return `File #${item.archive_id ?? item.library_file_id}`;
|
||||
}
|
||||
Reference in New Issue
Block a user