feat: display-name aliases for Klipper objects#1902
Conversation
Add a user-editable, display-only alias map (objectKey -> friendly name) for fans, output_pins, LEDs, heaters and temperature sensors, mirroring the existing sensorColors feature end-to-end (store state/mutations/actions + dbKey persistence to the Moonraker DB `fluidd` namespace, auto-loaded via mergeWith). Printer getters resolve `aliases[key]` first and also expose a new `defaultPrettyName` (the true pre-alias name) for the settings panel placeholder. A new Settings panel sets/clears aliases. Display-only by construction: never renames a Klipper object, never emits config/G-code. G-code paths are keyed off the raw object `name` (extracted to output-gcode.ts), never the alias. User-supplied aliases are HTML-escaped at every raw-HTML sink — the ECharts thermal-tooltip formatter and the v-safe-html OutputFan/OutputPin labels — via a single escapeHtml impl. Hardening: guarded delete uses hasOwnProperty.call (prototype-chain safe); the same guard is back-ported to the pre-existing removeSensorColor. empty aliases are never persisted. tsconfig.vitest include mirrors the app source so store specs resolve the ambient globals + Vue augmentations under vue-tsc --build (repro-driven; narrow/reference alternatives don't apply — see the tech-spec dev record). i18n: en.yaml only (other locales are Weblate-managed). Tests: 51 new (store mutations/actions, guarded delete + prototype-chain, getter alias override + defaultPrettyName, escape + resolve-label utils, thermal-tooltip formatter XSS, output-label escape, display-only G-code regression, dbKey dot parity). Green: type-check, vitest (375), eslint, build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Philipp Oppolzer <philipp.oppolzer@gmail.com>
|
Hi @philippop thank you for sending this PR. From what I can see, this is related and would resolve #1343. However, and as I have previously stated on the above...
|
|
Hi @pedrolamas, |
What
Adds a user-editable, display-only alias map (
objectKey → friendly name) for fans,output_pins, LEDs, heaters and temperature sensors. Users can give an object a friendly name in the UI without renaming the underlying Klipper config section.Motivation: on some machines (e.g. rooted Creality K1) fans are hardcoded in firmware as
output_pin fan0/1/2; renaming the Klipper section breaks the printer's touchscreen fan control. This provides friendly names that never touch Klipper config or emit G-code.How
Mirrors the existing
sensorColorsfeature end-to-end:aliases: Record<string,string>onuiSettings.dashboard, withsetAlias/setRemoveAliasmutations andupdateAlias/removeAliasactions, persisted to the Moonraker DBfluiddnamespace via the existingdbKeymechanism. Auto-loaded through the existingmergeWithinsetInitUiSettings— no bespoke load wiring.getOutputs/getHeaters/getSensorsresolvealiases[key]first and expose a newdefaultPrettyName(the true pre-alias name) so the settings panel placeholder shows the real default even while an alias is active.AliasSettings.vueto set/clear aliases (placeholder =defaultPrettyName).name, never the alias (extracted tosrc/util/output-gcode.ts).v-safe-htmlOutputFan/OutputPinlabels — and are HTML-escaped at both via a singleescapeHtmlutil.src/locales/en.yamlonly (other locales left to Weblate).Testing
pnpm run lint,pnpm run type-check,pnpm run test(375 pass),pnpm run circular-check(no cycles), and a production build all pass clean.defaultPrettyName, escape/resolve-label utils, thermal-tooltip formatter XSS, output-label escape, a display-only G-code regression (asserts the command path usesname, not the alias), anddbKeydot-in-value parity.Note for reviewers (
tsconfig.vitest.json)The new store/getter specs import store source that references the ambient global namespaces (
Moonraker/Klipper/TSHelpersinsrc/typings) and the$filters/$colorsetVue augmentations declared insrc/plugins. Becausetsconfig.vitest.json'sincludeoverrides (does not merge with) the extendedtsconfig.appinclude, those globals were unresolved undervue-tsc --build. I widened the vitestincludeto mirror the app source so the globals resolve.A narrower include isn't possible without dragging the whole component graph in (
src/plugins/filters.tsvalue-imports@/router), and a project reference to the app project is blocked by itsnoEmit/non-composite config. Happy to take direction if you'd prefer a different structural fix here.Signed-off-by: Philipp Oppolzer philipp.oppolzer@gmail.com