Implement Unique IDs for UI Elements, shows just the Labels to the User
Description
Summary: To improve code maintainability and avoid inconsistencies, it is proposed that all UI elements (such as Pages, Groups, and thus Menu items) in Node-RED Dashboard 2.0 should have unique IDs or codes. These IDs should be used for routing, authorization, and business logic instead of visible text labels.
Description: Currently, Node-RED Dashboard 2.0 uses visible text labels for UI elements such as Page Names in routing, authorization, and business logic. This approach can lead to several issues:
- Inconsistencies and poor code maintenance: Renaming a UI element requires a complete refactor of the authorization logic, which can be cumbersome and error-prone.
- Positional approach limitations: Using positional references for UI elements can lead to similar maintenance challenges.
Proposed Solution:
- Each UI element (Page, Group etc.) should have a unique ID or code.
- The ID should be randomly generated upon creation but can be overwritten by the user to provide a meaningful logical key.
Separation of Labels and IDs:
- The visible name of the UI element should be treated as a label and should not be used in routing, authorization, or business logic.
- Deep references to UI elements (e.g., programmatic UI-Control to show/hide components based on authenticated user) should leverage IDs, not names.
Benefits:
- Improved Maintainability: Changes to visible labels will not require refactoring of the underlying logic, reducing the risk of errors and simplifying maintenance.
- Consistency: Using unique IDs ensures that references to UI elements remain consistent, even if the visible labels are changed.
- Flexibility: Users can assign meaningful logical keys to IDs, making the system more intuitive and easier to manage. Naming convention (E.G. complex keys with prefixes and suffixes) could help in complex scenario without affecting the visible label.
Have you provided an initial effort estimate for this issue?
I have provided an initial effort estimate
Hi @andrea-tomassi, This was indeed the root cause for another issue I had this morning.
Note that pages, groups, ... are config nodes, which have a unique node id already. But of course the requested refactoring will result in quite some work.
@bartbutenaers actually the current behavior of the "Name" field is being an ID. And actually it is already what is being used by ui-controls. That part is just perfect.
So, probably, the only thing that is missing is a Label to be rendered instead of the current one. And just calling the one that now we call "Name" (From the screenshot above) something like "key" or "code", and pre-filling it
Few thoughts:
- "Name" is a standard practice for Node-RED and drives the text that appears on the node in the Node-RED editor.
- Every node (widget, page, group, etc) has a random ID already assigned to it by Node-RED.
- Being able to use this ID to drive
ui-controlis very sensible, the challenge is making theidmore visible in Node-RED itself, as its not an obvious/easy find. - We would still need to support label-driven control as that's a feature from Dashboard 1.0 we've inherited and need to support
@joepavitt I totally agree with your analysis, this is why I finished with thinking that just adding a Label field on top of the exiating was just easier. This would keep unchanged any deep behaviour. For a developer is just fine dealing with the current existing Name property.
This label could be optional. If left blank, the behavior remains the same as the current one. On the other hand, if one sets the label, the visible text on the left menu and as a page name will be the label, not the name.
Does this look good to you?
In the end, we want to add a way to re-label the technical name, decoupling it from the end-user label, right?
@bartbutenaers This would also allow the creation of, for instance, two pages with the same label (e.g. Settings), and one can show or hide the appropriate version (basic_settings or advanced_settings) based on the authenticated user’s role. I guess this is something related with your issue as well
In the end, we want to add a way to re-label the technical name, decoupling it from the end-user label, right?
Is there a reason you want to re-label the Node's ID? Can you not just use the Node's ID? Although, I guess the ID isn't very readable at a future date, so more difficult to track
@joepavitt I have been developing applications and products for decades. If I count the number of times I had to change the label that users see in a menu versus the number of times I had to change the underlying variable name, the difference is significant.
Even without a semantic change that justifies renaming variables, it’s common to change visible labels for reasons like UX or marketing.
That’s why I don’t want to use visible names as references in my code. I want to be able to change menu labels 100 times without altering any other code.
Node-RED is a great tool, but it doesn’t support using an IDE for development. Code refactoring has to be done manually, which is a significant effort. This can hinder the adoption of technology beyond small home automation dashboards to professional code production. With current capabilities, it would be a shame to get bogged down by these details.
I haven’t even mentioned i18n. Ideally, labels should be separate from the logic and contain an i18n key, not text. But that’s probably out of scope for now.
EDIT: +1: a label doesn't have the strict need to be unique, too
Hope this helps...
Think we're mis-communicating. Node-RED already provides a static ID for each node (including every group, page, etc.) that will not change. I was asking if there would be any issues with relying upon that for the business logic. It doesn't have the ability to rename it, but we could/should support that in the ui-control logic too.
It's not well surfaced by Node-RED though, you have to edit a node, then click the "i" icon in the sidebar to view it. We could show it as a static field in the page/group config tray to make this more accessible?
I'm absolutely in agreement with you re: relying on Name/Label.
Node-RED is a great tool, but it doesn’t support using an IDE for development. Code refactoring has to be done manually, which is a significant effort. This can hinder the adoption of technology beyond small home automation dashboards to professional code production. With current capabilities, it would be a shame to get bogged down by these details.
I agree here re: IDE, if there are some feature requests for Node-RED, make sure they're raised. It's very actively developed, and they're always open to improvements.
@joepavitt Yes, you're right, I ignored that hypothesis without explaining. I would avoid referencing node IDs in the application's business logic. They are physical keys tied to a specific instance of Node-RED. How can we make the solution robust when we want to transfer the logic to another instance?
Instead, if we ask the user to provide a logical key (the current name) and a label (optional) for each page, we can rely on that logical key (the Name) for references.
If I have a ui-control node that defines the behavior of my page with Name: "advanced_settings", I can be sure that this configuration, when exported, will always manage any page with this logical key on any Node-RED instance.
On the other hand, if my ui-control node references the node ID, it won't be transferable to a dashboard with a page named "advanced_settings" but with a different ID.
Moreover, this is simpler because it doesn't require any changes to the current behavior of ui-control, etc.
Using physical keys in business logic likely has other disadvantages that I can't see right now, but it's generally not a good practice.
They are physical keys tied to a specific instance of Node-RED. How can we make the solution robust when we want to transfer the logic to another instance?
If you copy flows between Node-RED instances, the ID's persist (unless you're importing into a flow where you already have a copy of that page/node, then it would be changed)
I think we're trending towards a key property that would be read-friendly (like Label) but more functional and persistent (like id)? Although, as a starting point, I think using the Node's id is a quick win, before we introduce new properties - as we this is something we'd likely have to introduce across all widgets eventually once we introduce #711
@joepavitt Ok, my scenario was a little different from this: When I copy a specific ui-control (like for home or settings pages) from Node-RED A (where I have clearly designed roles and authorization) to Node-RED B (a new application), Node-RED B has different pages (totally different pages IDs). Of course some more node is needed to implement some logic, but ui-control contains the mapping, so I'm focusing on it. Assume the "home" and "settings" pages for Node-Red B are different in content, and this is why I did not imported them, but the authorization logic is the same (likely). If the ui-control business logic uses physical IDs, being copyed from Node-Red A, it references pages IDs that won’t exist in Node-RED B.
Yes, my vote is for adding a "key" property, with the meaning of "logical key". Maybe it could be defaulted in some smart way? Personally I would stay away from phisical IDs. Soon or later, I guess using node IDs would reveal more issues.