Multi-user dashboard

Hello,

I know this subject comes up regularly but I can't find the right answer or solution for me.

I use node-red for an internal ticket system (IT) I made a dashboard allowing me to fill in the different information.
How can I do so that 2 different users can fill in the fields each on their side without disturbing each other?

Knowing that they use the same link: ipnetwork/ui
My single user flow is working fine.

For the moment I do not necessarily want each user to connect with an identifier but if this is the solution I am interested in setting it up.

There is no reason why, what you currently have, should impact another user - unless:

  • you are using flow/global context to store input data
  • you are sending notifications back to all dashboard connections.

You will need to explain how the 2nd user is impacted before we can offer concrete advice.

I use two station with the same url.

On station 1 I write in the "Recherche" box. on station 2 the box is also filled

And yes I use global data for storage values.
but for last question i don't understand

[{"id":"61c321c8ce9e81a1","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Recherche","tooltip":"","group":"4dd0853eebc100e1","order":1,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":190,"y":440,"wires":[["cefcd803a849b4c9"]]},{"id":"cceb70a9c8cba525","type":"ui_dropdown","z":"1b31f693fdaa1a66","name":"","label":"Site : ","tooltip":"","place":"Select option","group":"4dd0853eebc100e1","order":2,"width":0,"height":0,"passthru":true,"multiple":false,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":770,"y":440,"wires":[["01c111e253f4d98b"]]},{"id":"cefcd803a849b4c9","type":"function","z":"1b31f693fdaa1a66","name":"SELECT","func":"msg.topic = \"SELECT * FROM CLIENT WHERE NOM LIKE '%\"+ msg.payload +\"%' ORDER BY NOM ASC\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":440,"wires":[[]]},{"id":"3d661a8bc3ce0e9e","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"options","pt":"msg","to":"msg.payload[*].Nom","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":440,"wires":[["cceb70a9c8cba525"]]},{"id":"5de3c6d68ac18eb6","type":"ui_text","z":"1b31f693fdaa1a66","group":"4dd0853eebc100e1","order":3,"width":0,"height":0,"name":"","label":"Numéro de contrat :","format":"{{msg.payload[0].NumberSite}}","layout":"row-left","className":"","x":1340,"y":440,"wires":[]},{"id":"7e1382e6bf8073ec","type":"ui_text","z":"1b31f693fdaa1a66","group":"4dd0853eebc100e1","order":4,"width":0,"height":0,"name":"","label":"Nom du Site :","format":"{{msg.payload[0].Nom}}","layout":"row-left","className":"","x":1320,"y":480,"wires":[]},{"id":"cc83cb4b4efe3bc2","type":"ui_text","z":"1b31f693fdaa1a66","group":"4dd0853eebc100e1","order":5,"width":0,"height":0,"name":"","label":"Materiel :","format":"{{msg.payload[0].Materiel}}","layout":"row-left","className":"","x":1300,"y":520,"wires":[]},{"id":"429c4a973ecd101e","type":"ui_text","z":"1b31f693fdaa1a66","group":"4dd0853eebc100e1","order":6,"width":0,"height":0,"name":"","label":"Mail :","format":"{{msg.payload[0].Mail}}","layout":"row-left","className":"","x":1290,"y":560,"wires":[]},{"id":"01c111e253f4d98b","type":"function","z":"1b31f693fdaa1a66","name":"SELECT","func":"msg.topic = \"SELECT * FROM CLIENT WHERE Nom LIKE '\"+ msg.payload +\"'\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":900,"y":440,"wires":[[]]},{"id":"63c461474f4ea480","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Nom :","tooltip":"","group":"bb84c8cdeda5483f","order":1,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":250,"y":680,"wires":[["31a3e1135d7cc234"]]},{"id":"b273355012eca779","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Email :","tooltip":"","group":"bb84c8cdeda5483f","order":2,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":250,"y":720,"wires":[["3d6cc5bfcb51e381"]]},{"id":"fa562fe40bde8e56","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Téléphone :","tooltip":"","group":"bb84c8cdeda5483f","order":3,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":270,"y":760,"wires":[["2ee3570b9fbe763a"]]},{"id":"5fc166c4020ced1e","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Complement information site :","tooltip":"","group":"bb84c8cdeda5483f","order":4,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":330,"y":800,"wires":[["88ce834bc4c65eba"]]},{"id":"ae2bf76c81484b8d","type":"ui_text_input","z":"1b31f693fdaa1a66","name":"","label":"Dysfonctionnement :","tooltip":"","group":"bb84c8cdeda5483f","order":6,"width":0,"height":0,"passthru":true,"mode":"text","delay":300,"topic":"topic","sendOnBlur":true,"className":"","topicType":"msg","x":300,"y":840,"wires":[["0b7619c129ccd460"]]},{"id":"8b4cba7a5b5ed5bb","type":"ui_date_picker","z":"1b31f693fdaa1a66","name":"","label":"Date de constation :","group":"bb84c8cdeda5483f","order":7,"width":0,"height":0,"passthru":true,"topic":"topic","topicType":"msg","className":"","x":300,"y":880,"wires":[["0f2f485759254030"]]},{"id":"bf7d49ede1863de6","type":"ui_switch","z":"1b31f693fdaa1a66","name":"","label":"Technicien sur site :","tooltip":"","group":"bb84c8cdeda5483f","order":8,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"oui","onvalueType":"str","onicon":"","oncolor":"","offvalue":"non","offvalueType":"str","officon":"","offcolor":"","animate":false,"className":"","x":290,"y":920,"wires":[["d11e897bcc4e50c7"]]},{"id":"0f2f485759254030","type":"moment","z":"1b31f693fdaa1a66","name":"DD-MM-YYYY","topic":"","input":"","inputType":"msg","inTz":"Europe/Paris","adjAmount":0,"adjType":"days","adjDir":"add","format":"DD-MM-YYYY","locale":"fr-FR","output":"","outputType":"msg","outTz":"Europe/Paris","x":500,"y":880,"wires":[["d7c2b748bacad6ae"]]},{"id":"c468f45240917412","type":"change","z":"1b31f693fdaa1a66","name":"non","rules":[{"t":"set","p":"payload","pt":"msg","to":"non","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":130,"y":920,"wires":[["bf7d49ede1863de6"]]},{"id":"6c1681ea1fe3a7fb","type":"change","z":"1b31f693fdaa1a66","name":"Now","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":130,"y":880,"wires":[["8b4cba7a5b5ed5bb"]]},{"id":"4ab134e09bbc73b6","type":"link in","z":"1b31f693fdaa1a66","name":"Reset HUB","links":[],"x":75,"y":580,"wires":[["63c461474f4ea480","b273355012eca779","fa562fe40bde8e56","5fc166c4020ced1e","ae2bf76c81484b8d","6c1681ea1fe3a7fb","c468f45240917412","34af3e26ec9baef7"]]},{"id":"31a3e1135d7cc234","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"nom.ClientNom","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":680,"wires":[[]]},{"id":"3d6cc5bfcb51e381","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"ClientMail","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":720,"wires":[[]]},{"id":"2ee3570b9fbe763a","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"ClientTel","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":760,"wires":[[]]},{"id":"88ce834bc4c65eba","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"SiteInfo","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":800,"wires":[[]]},{"id":"0b7619c129ccd460","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"Panne","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":840,"wires":[[]]},{"id":"d7c2b748bacad6ae","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"DatePanne","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":880,"wires":[[]]},{"id":"d11e897bcc4e50c7","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"Tech","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":920,"wires":[[]]},{"id":"8ae834be29b040aa","type":"ui_button","z":"1b31f693fdaa1a66","name":"","group":"bb84c8cdeda5483f","order":9,"width":0,"height":0,"passthru":false,"label":"Envoyer","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":260,"y":960,"wires":[["8410973ba5e5b10e"]]},{"id":"8410973ba5e5b10e","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"ClientNom","pt":"msg","to":"ClientNom","tot":"global"},{"t":"set","p":"ClientMail","pt":"msg","to":"ClientMail","tot":"global"},{"t":"set","p":"ClientTel","pt":"msg","to":"ClientTel","tot":"global"},{"t":"set","p":"DatePanne","pt":"msg","to":"DatePanne","tot":"global"},{"t":"set","p":"SiteInfo","pt":"msg","to":"SiteInfo","tot":"global"},{"t":"set","p":"Tech","pt":"msg","to":"Tech","tot":"global"},{"t":"set","p":"Panne","pt":"msg","to":"Panne","tot":"global"},{"t":"set","p":"Equipement","pt":"msg","to":"Equipement","tot":"global"},{"t":"set","p":"Nom","pt":"msg","to":"NomSite","tot":"global"},{"t":"set","p":"Techno","pt":"msg","to":"Techno","tot":"global"},{"t":"set","p":"NumberSite","pt":"msg","to":"NumberSite","tot":"global"},{"t":"set","p":"MailHub","pt":"msg","to":"MailHub","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":960,"wires":[["523b63a0d4ac14b1"]]},{"id":"65283eb7cc1fcda0","type":"function","z":"1b31f693fdaa1a66","name":"","func":"msg.payload = \"Bonjour,\"+\"\\n\"+\"\\n\"+\n\"Veuillez trouver ci-dessous la demande d'intervention N°: \"+msg.NumberTicket+\" .\"+\"\\n\"+\n\"Pour le site \"+msg.Nom+\" ayant le numero de contrat \"+msg.NumberSite+\" .\"+\"\\n\"+\n\"Informations complementaires :\"+\"\\n\"+\n\"- Nom du contact : \"+msg.ClientNom+\"\\n\"+\n\"- Téléphone du contact : \"+msg.ClientTel+\"\\n\"+\n\"- Mail du contact : \"+msg.ClientMail+\"\\n\"+\n\"- Complément d'information site : \"+msg.SiteInfo+\"\\n\"+\n\"- Equipement : \"+msg.Equipement+\"\\n\"+\n\"- Dysfonctionnement : \"+msg.Panne+\"\\n\"+\n\"- Date de constatation : \"+msg.DatePanne+\"\\n\"+\n\"- Technicien sur site : \"+msg.Tech+\"\\n\"+\"\\n\"+\n\"Cordialement,\"+\"\\n\"+\n\"Centre de Supervision\"+\"\\n\"+\n\"0 805 296 360\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":960,"wires":[[]]},{"id":"34af3e26ec9baef7","type":"ui_dropdown","z":"1b31f693fdaa1a66","name":"","label":"Equipement","tooltip":"","place":"Select option","group":"bb84c8cdeda5483f","order":5,"width":0,"height":0,"passthru":true,"multiple":false,"options":[{"label":"Pc gestion","value":"Pc gestion","type":"str"},{"label":"Acces pieton","value":"Acces pieton","type":"str"},{"label":"Valideur","value":"Valideur","type":"str"},{"label":"Caisse manuelle","value":"Caisse manuelle","type":"str"},{"label":"Caisse automatique","value":"Caisse automatique","type":"str"},{"label":"Borne entree","value":"Borne entree","type":"str"},{"label":"Borne sortie","value":"Borne sortie","type":"str"},{"label":"Barriere sortie","value":"Barriere entree","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":270,"y":640,"wires":[["5dbd956bd5ea1482"]]},{"id":"5dbd956bd5ea1482","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"hub.Equipement","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":640,"wires":[[]]},{"id":"9e893cca3245a96f","type":"change","z":"1b31f693fdaa1a66","name":"","rules":[{"t":"set","p":"NumberSite","pt":"global","to":"msg.payload[0].NumberSite","tot":"msg"},{"t":"set","p":"NomSite","pt":"global","to":"msg.payload[0].Nom","tot":"msg"},{"t":"set","p":"Techno","pt":"global","to":"msg.payload[0].Materiel","tot":"msg"},{"t":"set","p":"MailHub","pt":"global","to":"msg.payload[0].Mail","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1320,"y":600,"wires":[[]]},{"id":"523b63a0d4ac14b1","type":"moment","z":"1b31f693fdaa1a66","name":"DD-MM-YYYY","topic":"","input":"","inputType":"date","inTz":"Europe/Paris","adjAmount":0,"adjType":"days","adjDir":"add","format":"YYYYMMDDHHMMss","locale":"fr-FR","output":"NumberTicket","outputType":"msg","outTz":"Europe/Paris","x":650,"y":960,"wires":[["65283eb7cc1fcda0","77abde87545311bf"]]},{"id":"77abde87545311bf","type":"function","z":"1b31f693fdaa1a66","name":"INSERT TICKET","func":"msg.topic = \"INSERT INTO TICKETHUB (`NumberTicket`, `NumberSite`, `Nom`,`Materiel`, `Mail`,`ClientNom`, `ClientMail`, `ClientTel`, `InfoSite`, `Equipement`, `Panne`, `DatePanne`,`Tech`) VALUES ('\"+msg.NumberTicket+\"','\"+msg.NumberSite+\"','\"+msg.Nom+\"','\"+msg.Techno+\"','\"+msg.MailHub+\"','\"+msg.ClientNom+\"','\"+msg.ClientMail+\"','\"+msg.ClientTel+\"','\"+msg.SiteInfo+\"','\"+msg.Equipement+\"','\"+msg.Panne+\"','\"+msg.DatePanne+\"','\"+msg.Tech+\"')\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":1000,"wires":[[]]},{"id":"4dd0853eebc100e1","type":"ui_group","name":"Recherche","tab":"8e78d0779b57a450","order":1,"disp":true,"width":"12","collapse":false,"className":""},{"id":"bb84c8cdeda5483f","type":"ui_group","name":"Demande","tab":"8e78d0779b57a450","order":2,"disp":true,"width":"12","collapse":false,"className":""},{"id":"8e78d0779b57a450","type":"ui_tab","name":"HUB Ticket","icon":"local_parking","order":2,"disabled":false,"hidden":false}]

When >1 browser client tab connects to Dashboard, inputs from all client tabs come back to the output ports of the appropriate ui node. However, they have differences in the output data that lets you differentiate them.

Check the full returned messages and you will see what I mean.

Unfortunately, at present, the only differentiator is the socket id. This is absolutely unique between all browser tabs but it can also change for the same browser tab if someone reloads the page or it temporarily looses contact with the server (e.g. the computer goes to sleep).

Still, the socketid may well be enough for you. Or, you might not even need that if you can reasonably expect that there is no overlap between the entered data. In that case, you simply need to process every inbound msg.

If you need to better identify things, you have some choices. You could require the user to manually enter an id every time. You could force a login (perhaps using an external proxy to get round limitations of the Dashboards single user nature). Or you could use something like uibuilder which has some more stable user/browser-tab identifiers baked in.

I see the different socketid. Now how can I do for each user write each on their side without it being displayed on the page of the other?

To do that, you need to include the socketid in the return message. If you remove that, it will go to everyone. With it, it only goes to the single browser tab.

Just remember what I said though. If a browser tab temporarily loses connectivity for any reason or the user reloads the page, the socketid will change. So, for example, if you send a reply when a users browser tab or PC is sleeping and include the socketid from the last inbound msg, they won't get anything because the socketid would have changed when things wake up. May not be an issue depending on your expected workflow.

1 Like

I understand the creation of the ticket should not take long so little risk and otherwise they will start again.
I understand the outline but have trouble seeing the process.

  • it is not a problem that I register in a global variable
  • could you give me an example of formatting with a text box? that I understand the procedure

sorry for being so insistent :smiling_face:

Your issue is a combination of global context and individual controls. If you use the ui-form then store the user input upon submit, there will be no collision - all values would be posted at the same time from the same connection/browser

If you can do your input form in a ui-form, problem solved.

I appreciate the ui-form is less useful in many cases.

Alternatively, use the sessionid to store user input in context (flow/global) and collect the context value stored under the sessionid upon submitting.

If using a ui-form (as noted above by @Steve-Mcl) is not good enough for you (e.g., due to lack of drop-lists), you can use a ui-template where you define your own input controls and handle their messages on a per-user basis. This requires some HTML and JavaScript.
If you are interested to take this path, I can send some examples.

But if you find yourself relying more and more on the ui_template, it might be worth asking yourself whether Dashboard is the right tool for the job - there are alternatives after all :wink:

1 Like

Yep! and ui builder is definitely a worthy alternative!

1 Like

I see that everything remains favorable to change via ui builder. I will see what it looks like. a question bothers me ui and ui builder are compatible?
I have several dashboards for other applications but do not need to be multi-user. or will i have to do it all over again?

ui builder m will offer a login interface? or is it automatically possible to work in multi-user mode?

Thank's

Define "compatible" in this sense? Both are web apps. Dashboard is an SPA using AngularJS v1 where much of the UI is defined from Node-RED and sent dynamically to the clients. uibuilder is a more traditional approach that gives you the freedom to use standard front-end development frameworks and tools should you wish to but also gives an option to define UI's and amend them from Node-RED if you prefer. It does much more if you want it too as well of course.

So Dashboard and uibuilder can run in parallel certainly. But they dont' really interact other than via Node-RED itself.

You only need to re-do the part that you want in uibuilder itself. Bearing in mind that Dashboard and uibuilder both build web UI's and that web UI's can be made to interact - via iframes in-extremis.

uibuilder does not have a pre-built login interface any more than Dashboard does. I strongly recommend using a proxy tool such as NGINX, Caddy, etc in either case. This would also let you share a login between Dashboard and uibuilder which would help with a gradual migration from one to the other.

It is possible to build a bespoke identity and access control system with uibuilder though if you really must. It has good middleware capabilities for both ExpressJS (the web server) and Socket.IO.

uibuilder has some additional metadata to help with multi-user flows. Including a "stable" clent id, a browser tab id and the client IP address all available by default. The client id is static within a device/browser profile until the browser is restarted. Unlike the socket id which can change if the user reloads the page or the socket.io connection is temporarily lost (e.g. if the browser tab or the device goes to sleep and wakes up again).

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.