feat(print-modal): show each printer slot's colour in the filament mapping (issue #3159)

The Print / Schedule dialog's filament mapping is where the colour a slice
asked for is compared against the colour actually loaded, and only the
left-hand side of that comparison had a swatch. The slot, and every slot in
its dropdown, was text -- and the text cannot be trusted: a slot's colour name
is resolved from the Color Catalog or, failing that, from hue, so a
third-party beige is announced as "Orange". A "Color mismatch" warning then
gives no way to tell a real mismatch from two names for the same hex without
opening the printer card in another tab, which on a farm swapping twenty or
thirty non-Bambu colours between machines is a check made many times a day.

Each slot now carries its colour and its hex, and the slot whose colour is
exactly the one the slice asked for is ticked. This works for a slot bound to
an inventory spool and for one configured through Configure Slot or on the
printer itself: the second kind has no inventory row behind it, and the
printer's own tray colour is then what draws. A bound spool contributes what a
tray record cannot -- SlotSpoolIdentity gains extra_colors and effect_type, so
a two-tone or glittery spool draws as itself rather than as its base colour.

The same treatment goes to the filament-override picker used for model-based
assignment. It is the same choice on the other dispatch path, and leaving it
text-only would have made one decision read two ways.

Both controls stop being <select>s to do it, because an <option> renders text
and nothing else. SlotPicker keeps what the select gave for free -- arrow,
Home/End, Enter and Escape keys, listbox semantics, and the border colouring
that encodes match, same-type-different-colour and not-loaded -- and is
portaled with position:fixed so it is not clipped by the dialog's own scroll
container, flipping above the row when there is no room below.
This commit is contained in:
maziggy
2026-09-25 11:38:13 +02:00
parent 64817ecc18
commit 1a84dfea5b
33 changed files with 1110 additions and 249 deletions
@@ -991,8 +991,52 @@ class TestSlotSpoolIdentity:
# naming this slot from the hex is exactly the bug.
"color_name": "Orange",
"rgba": "FEC600FF",
# A plain single-colour spool: nothing extra to draw (#3159).
"extra_colors": None,
"effect_type": None,
}
@pytest.mark.asyncio
async def test_internal_mode_carries_the_rest_of_the_colour(self, db_session, printer_factory):
"""A tray record holds one hex, so the binding is the only source for the rest.
Without this the Print dialog's slot picker (#3159) draws a two-tone or
glittery spool as its base colour -- the one comparison the picker
exists to make, made against the wrong swatch.
"""
from backend.app.services.filament_deficit import build_slot_materials
printer = await printer_factory(model="H2C")
spool = Spool(
brand="eSUN",
material="PLA",
subtype="Multicolor",
color_name="Rainbow",
rgba="FF0000FF",
extra_colors="00FF00,0000FF",
effect_type="Glitter",
label_weight=1000,
weight_used=0.0,
)
db_session.add(spool)
await db_session.commit()
await db_session.refresh(spool)
await _assign(db_session, printer_id=printer.id, spool_id=spool.id, ams_id=2, tray_id=0)
patches = TestFilamentDeficitBackupAware._patch_status(printer_id=printer.id, backup_on=False, model="H2C")
for p in patches:
p.start()
try:
slots = await build_slot_materials(db_session, printer.id)
finally:
for p in patches:
p.stop()
identity = slots[0].spool
assert identity is not None
assert identity.extra_colors == "00FF00,0000FF"
assert identity.effect_type == "Glitter"
@pytest.mark.asyncio
async def test_blank_fields_become_null_so_the_client_can_fall_back(self, db_session, printer_factory):
"""Per-field, not all-or-nothing: an unnamed colour still falls back to