The app was built dark-first, so hundreds of hardcoded Tailwind semantic
text/icon utilities at light shades (text-amber-400, text-blue-300, ...) had
no dark: variant. With darkMode:'class' they applied in light theme too,
producing washed-out text on pale tints and white cards — including the three
reported spots (AMS Drying banner, Archives no-3MF warning, debug-logging
banner). Give each a theme-aware pair: a darker readable shade in light theme
with the original pinned to dark:, so dark theme is unchanged. ~100 files.
The bambu-* CSS-variable palette (self-correcting) and the dark-only SpoolBuddy
kiosk are left untouched. Plain text-white is already theme-aware via the
existing index.css .text-white override, so it needed no changes.
Restructures the queue page around three tabs (Queue / History / Timeline)
and adds first-class batch grouping plus a real time-based timeline.
Queue tab
- Layout toggle: Sort by Position (flat list) or Group by Printer (per-
printer section cards with aggregate count / time / weight headers).
- Batch grouping: pending items sharing a batch_id render as a single
collapsible row with aggregate stats; children draggable within the
batch only. Per-batch collapse state in localStorage.
- Multi-drag: dragging any selected row moves all selected items as a
contiguous block via DragOverlay (+N ghost).
- Selection bar gains a Group as batch action when 2+ ungrouped items
are selected. Ungroup lives on the batch parent row.
History tab
- Two-line rich rows: filament color swatch + weight + type, user
attribution, inline error message on failed / skipped rows.
- Responsive 1 / 2 / 3 column grid so a long history uses available
width instead of stretching one row per line.
- Batch siblings group into a collapsible parent with status-rollup
chips (3 OK / 1 failed / etc).
- Thumbnail hover preview shows the full image at 192x192 next to the
small thumb.
Timeline tab
- Replaces the hourly-list view with a Gantt swimlane: one row per
printer (plus per target_model and unassigned), horizontal hour
axis, jobs as bars positioned by start time and sized by duration.
- Live NOW marker.
- Only committed schedules are rendered: currently printing items,
pending items with scheduled_time, and pending ASAP behind an active
print. Staged (manual_start), waiting (waiting_reason), and ASAP
jobs on idle printers are filtered out.
- 24h rolling window with 12h step controls.
- Per-bar tooltip with start, end, progress, batch name.
Backend
- POST /queue/batches creates a batch, optionally assigning existing
pending item_ids (manual grouping) or returning an empty batch the
client can attach to subsequent /queue/ POSTs.
- POST /queue/batches/{id}/ungroup clears batch_id from all members
(skipping items the caller does not own) and deletes the batch row
when no members remain.
- POST /queue/ accepts an optional batch_id and validates that the
batch exists, is active, and the caller may modify it. The existing
quantity > 1 auto-batch path still fires when no batch_id is sent.
PrintModal
- When N plates from one source are queued in a single submission
(model assignment or single printer), the modal pre-creates a batch
and passes its id to each addToQueue call so multi-plate jobs land
grouped automatically. Falls back to ungrouped items if the batch
pre-create fails.
Queue page redesign: compact stats bar replaces summary cards, color-
coded left borders for status scanning, collapsible history with
condensed rows, and a new production schedule timeline view (#823)
showing estimated completion times grouped by hour with filter tabs
and day navigation. i18n keys added for all 7 languages.
Fix plate thumbnails returning 401 in print modal when auth is enabled
(missing stream token). Fix schedule calendar picker opening off-screen
(hidden input positioned with sr-only instead of near the date field).