client_v2: let a label print the spool's own tare weight

The v1 client offered the spool's empty-spool weight and its filament's as two
separate label tokens. v2 kept only the filament's, so `{spool_weight}` in a
migrated v1 design had no equivalent to map to and resolved to "?" — and a
design rebuilt in v2 could only print the filament's figure, which is not
necessarily the one that spool is measured against.

`spool.spoolWeight` falls back to the filament the way `spool.price` already
does, so a `spool.*` token prints what actually applies to that spool.
This commit is contained in:
Donkie committed 2026-08-03 20:09:42 +02:00
1 parent 155e8f3737
commit 4ed1fbfc67
3 files changed
+15

No files matched your search

@@ -25,6 +25,13 @@ describe('migrateTemplate', () => {
expect(migrateTemplate('{filament.spool_weight}')).toBe('{filament.spoolWeight}');
});
// v1's two tare weights are different fields, and a label that printed the
// spool's own must not silently start printing its filament's (#1013).
it("keeps the spool's own tare weight apart from its filament's", () => {
expect(migrateTemplate('{spool_weight}')).toBe('{spool.spoolWeight}');
expect(migrateTemplate('{filament.spool_weight}')).toBe('{filament.spoolWeight}');
});
it('leaves paths that are already identical in both versions', () => {
for (const t of ['{filament.name}', '{filament.material}', '{filament.density}']) {
expect(migrateTemplate(t)).toBe(t);
+4
View File
@@ -72,6 +72,10 @@ const PATH_MAP: Record<string, string> = {
remaining_weight: 'spool.remaining',
initial_weight: 'spool.initial',
used_weight: 'spool.used',
// v1 offered the spool's own tare weight as a bare `spool_weight`. It had no v2
// equivalent until the spool gained the field back (#1013), so a migrated design
// using it resolved to "?".
spool_weight: 'spool.spoolWeight',
// Filament
'filament.spool_weight': 'filament.spoolWeight',
'filament.settings_extruder_temp': 'filament.nozzleTemp',
+4
View File
@@ -39,7 +39,10 @@ const RESOLVERS: Record<string, (b: LabelBinding) => string | number | null | un
'spool.remaining': (b) => fmtNum(b.spool?.remaining),
'spool.initial': (b) => fmtNum(b.spool?.initial),
'spool.used': (b) => (b.spool ? fmtNum(b.spool.initial - b.spool.remaining) : null),
// Both of these fall back to the filament, the way the spool itself does: a
// `spool.*` token has to print the figure that actually applies to that spool.
'spool.price': (b) => fmtNum(b.spool?.price ?? b.filament?.price),
'spool.spoolWeight': (b) => fmtNum(b.spool?.spoolWeight ?? b.filament?.spoolWeight),
'spool.registered': (b) => b.spool?.registeredLabel,
'spool.firstUsed': (b) => b.spool?.firstUsedLabel,
'spool.lastUsed': (b) => b.spool?.lastUsedLabel,
@@ -149,6 +152,7 @@ const FIXED_GROUPS: PlaceholderGroup[] = [
{ token: 'spool.remaining', labelKey: m['labels.fields.remainingG'] },
{ token: 'spool.initial', labelKey: m['labels.fields.initialG'] },
{ token: 'spool.used', labelKey: m['spool.fields.usedWeight'] },
{ token: 'spool.spoolWeight', labelKey: m['spool.fields.spoolWeight'] },
{ token: 'spool.price', labelKey: m['spool.fields.price'] },
{ token: 'spool.registered', labelKey: m['spool.fields.registered'] },
{ token: 'spool.firstUsed', labelKey: m['spool.fields.firstUsed'] },