Skip to content

feat: display-name aliases for Klipper objects#1902

Open
philippop wants to merge 1 commit into
fluidd-core:developfrom
philippop:feat/display-name-aliases
Open

feat: display-name aliases for Klipper objects#1902
philippop wants to merge 1 commit into
fluidd-core:developfrom
philippop:feat/display-name-aliases

Conversation

@philippop

Copy link
Copy Markdown

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 sensorColors feature end-to-end:

  • Store: aliases: Record<string,string> on uiSettings.dashboard, with setAlias/setRemoveAlias mutations and updateAlias/removeAlias actions, persisted to the Moonraker DB fluidd namespace via the existing dbKey mechanism. Auto-loaded through the existing mergeWith in setInitUiSettings — no bespoke load wiring.
  • Getters: getOutputs/getHeaters/getSensors resolve aliases[key] first and expose a new defaultPrettyName (the true pre-alias name) so the settings panel placeholder shows the real default even while an alias is active.
  • Settings panel: new AliasSettings.vue to set/clear aliases (placeholder = defaultPrettyName).
  • Display-only guarantee: the fan/pin G-code paths are keyed off the raw object name, never the alias (extracted to src/util/output-gcode.ts).
  • XSS: user aliases reach two raw-HTML sinks — the ECharts thermal-tooltip formatter and the v-safe-html OutputFan/OutputPin labels — and are HTML-escaped at both via a single escapeHtml util.
  • i18n: src/locales/en.yaml only (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.
  • 51 new unit tests: store mutations/actions incl. guarded delete + prototype-chain safety, getter alias-override + defaultPrettyName, escape/resolve-label utils, thermal-tooltip formatter XSS, output-label escape, a display-only G-code regression (asserts the command path uses name, not the alias), and dbKey dot-in-value parity.
  • Manually deployed to a Creality K1 Max: the alias settings panel renders and — critically for the display-only guarantee — the printer's touchscreen and physical fan control remain fully functional with aliases set.

Note for reviewers (tsconfig.vitest.json)

The new store/getter specs import store source that references the ambient global namespaces (Moonraker/Klipper/TSHelpers in src/typings) and the $filters/$colorset Vue augmentations declared in src/plugins. Because tsconfig.vitest.json's include overrides (does not merge with) the extended tsconfig.app include, those globals were unresolved under vue-tsc --build. I widened the vitest include to mirror the app source so the globals resolve.

A narrower include isn't possible without dragging the whole component graph in (src/plugins/filters.ts value-imports @/router), and a project reference to the app project is blocked by its noEmit/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

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>
@pedrolamas

Copy link
Copy Markdown
Member

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...

my personal view from this is that Creality has once again taken a different approach as to how Klipper is supposed to be used...

Personally, I have zero inclination to support Creality work as they have proven multiple times that they have no problems with taking open-source code (eg. Klipper, Moonraker, Fluidd, Mainsail, KlipperScreen), changing it, and then using it on their printers without releasing said changes (thus breaking the open-source licenses).

@philippop

Copy link
Copy Markdown
Author

Hi @pedrolamas,
Thanks for the response.
I get the stance. I just got really annoyed having to remember (or re-test), after not using the printer for a while, which fan is which and solved it like this. Since I know that others are annoyed by it too, I thought I share it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants