UI Control Node - Hide all TABS, Display only a few

Hi All,

Is there a way to hide all tabs (Using a wildcard) using the UI Control node, then selectively only "unhiding" individual tabs that I want to be available, all in a single payload to the UI Control node if possible?

TIA
Ed

1 Like

Yes
You can set all tab names in an array, or use the file read to read the flow.json and parse all the ui-tabs to get every tab name.
You can then with this info send a hide for all tabs you wish to hide.
In this example i parse the flow.json for all names, i exclude Solar tab, I send the payload to hide all tabs except Solar
Add your path to flow.json in file node, the in the hide inject add all tabs you wish to show in the msg.show property as an array of tab names

[{"id":"c90310f21e6b3663","type":"inject","z":"b9860b4b9de8c8da","name":"hide","props":[{"p":"action","v":"hide","vt":"str"},{"p":"show","v":"[\"Home\"]","vt":"json"},{"p":"home","v":"Home","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":190,"y":300,"wires":[["a2abf886d0a3f790"]]},{"id":"a2abf886d0a3f790","type":"file in","z":"b9860b4b9de8c8da","name":"","filename":"path to flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":390,"y":260,"wires":[["e425e16722eeb24e"]]},{"id":"01601fe8aa4c7280","type":"inject","z":"b9860b4b9de8c8da","name":"show","props":[{"p":"action","v":"show","vt":"str"},{"p":"home","v":"Solar","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":210,"y":360,"wires":[["a2abf886d0a3f790"]]},{"id":"e425e16722eeb24e","type":"json","z":"b9860b4b9de8c8da","name":"","property":"payload","action":"","pretty":false,"x":390,"y":320,"wires":[["c975524a66591c25"]]},{"id":"c975524a66591c25","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"tab\":$$.home,\"tabs\": {$$.action: [$$.payload[type = \"ui_tab\"].name[$not($ in $$.show)]]}}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":320,"wires":[["c687df2f19fd51e1","c45bbf75f76a29cf"]]},{"id":"c687df2f19fd51e1","type":"debug","z":"b9860b4b9de8c8da","name":"debug 328","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":650,"y":360,"wires":[]},{"id":"c45bbf75f76a29cf","type":"ui_ui_control","z":"b9860b4b9de8c8da","name":"","events":"all","x":500,"y":440,"wires":[[]]}]

[edit] add tab property, to add a start/home tab.
example payload

{
    "tab": "Home",
    "tabs": {
        "hide": [
            "Demo",
            "Solar"
        ]
    }
}
3 Likes

That's pretty darn cool!

I have set up 4 categories of machine.... Panel / Viewer / Admin and Everybody else...

All seems to work on the faster networked clients... What I am finding though, is that the slower clients don't update the sidebar/tabs menu reliably...

Is there any way I can force a more "sequential" way of doing things? ie delay a moment before the tab list gets updated client side? But then again, I might have just screwed things up a bit, here are the nodes I have done so far...

[{"id":"2f860a789bbd7ec5","type":"link out","z":"3a22476a5982ab5f","name":"link out 63","mode":"link","links":["b2c5cadef6afa9bb"],"x":645,"y":20,"wires":[]},{"id":"f3daf1e039287aec","type":"ui_ui_control","z":"3a22476a5982ab5f","name":"","events":"connect","x":330,"y":80,"wires":[["4ab956f628bada36"]]},{"id":"14a00c8777ee43d9","type":"link in","z":"3a22476a5982ab5f","name":"link in 116","links":["0b76f64f8a91b2d6","99f7587b71d623ec","bdc1347fbdd3b474","cddc98225a153fe6","71c92899f88d349c","22f420fed2d86e6d","fa8d5692d2786cfb"],"x":225,"y":80,"wires":[["f3daf1e039287aec"]]},{"id":"4ab956f628bada36","type":"function","z":"3a22476a5982ab5f","name":"IP Filter","func":"let InfoPanel1 = global.get(\"InfoPanel1IP\", \"file\") \nlet InfoPanel2 = global.get(\"InfoPanel2IP\", \"file\")\nlet InfoPanel3 = global.get(\"InfoPanel3IP\", \"file\")\nlet InfoPanel4 = global.get(\"InfoPanel4IP\", \"file\")\nlet InfoPanel5 = global.get(\"InfoPanel5IP\", \"file\")\nlet ViewerIP1 = global.get(\"Viewer1IP\", \"file\")\nlet ViewerIP2 = global.get(\"Viewer2IP\", \"file\")\nlet ViewerIP3 = global.get(\"Viewer3IP\", \"file\")\nlet ViewerIP4 = global.get(\"Viewer4IP\", \"file\")\nlet ViewerIP5 = global.get(\"Viewer5IP\", \"file\")\nlet AdminIP1 = global.get(\"Admin1IP\", \"file\")\nlet AdminIP2 = global.get(\"Admin2IP\", \"file\")\nlet AdminIP3 = global.get(\"Admin3IP\", \"file\")\nlet AdminIP4 = global.get(\"Admin4IP\", \"file\")\nlet AdminIP5 = global.get(\"Admin5IP\", \"file\")\n\n//InfoPanel\nif (msg.socketip == InfoPanel1 || msg.socketip == InfoPanel2 || msg.socketip == InfoPanel3\n    || msg.socketip == InfoPanel4 || msg.socketip == InfoPanel5){\n    return [msg, null, null, null]\n}\n\n//Viewer\nif (msg.socketip == ViewerIP1 || msg.socketip == ViewerIP2 || msg.socketip == ViewerIP3\n    || msg.socketip == ViewerIP4 || msg.socketip == ViewerIP5) {\n    return [null, msg, null, null]\n}\n\n//Admin\nif (msg.socketip == AdminIP1 || msg.socketip == AdminIP2 || msg.socketip == AdminIP3\n    || msg.socketip == AdminIP4 || msg.socketip == AdminIP5) {\n    return [null, null, msg, null]\n}\n\n//Everyone Else\nreturn [null, null, null, msg]\n//return [null, null, null, { payload: msg.payload },]","outputs":4,"noerr":0,"initialize":"","finalize":"","libs":[],"x":480,"y":80,"wires":[["2f860a789bbd7ec5","8614c9c886d33aeb"],["fed3d88946a1d8ed","779ad893af943408"],["46db03038e2c3f80","aab5d7d768a3641e"],["d45b215ca3ad999f","d9cd03ce91fcce93"]],"outputLabels":["InfoPanel","Viewer","Admin","Everyone Else"]},{"id":"fed3d88946a1d8ed","type":"link out","z":"3a22476a5982ab5f","name":"link out 67","mode":"link","links":["2e725ea58846d2d1","dbbef5b4f1d35995","b63882206967bf1d"],"x":645,"y":60,"wires":[]},{"id":"46db03038e2c3f80","type":"link out","z":"3a22476a5982ab5f","name":"link out 70","mode":"link","links":["f076463fbcd0c90d"],"x":645,"y":100,"wires":[]},{"id":"d45b215ca3ad999f","type":"link out","z":"3a22476a5982ab5f","name":"link out 71","mode":"link","links":["64390b9a3e0dae4f"],"x":645,"y":140,"wires":[]},{"id":"8614c9c886d33aeb","type":"debug","z":"3a22476a5982ab5f","name":"Panel","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":20,"wires":[]},{"id":"779ad893af943408","type":"debug","z":"3a22476a5982ab5f","name":"Viewer","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":60,"wires":[]},{"id":"aab5d7d768a3641e","type":"debug","z":"3a22476a5982ab5f","name":"Admin","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":100,"wires":[]},{"id":"d9cd03ce91fcce93","type":"debug","z":"3a22476a5982ab5f","name":"Other","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":140,"wires":[]},{"id":"9352e7d986d0c921","type":"group","z":"3a22476a5982ab5f","name":"Info Panel Selector","style":{"label":true,"color":"#000000"},"nodes":["b7b764fe27ce4e4b","a2abf886d0a3f790","c90310f21e6b3663","01601fe8aa4c7280","e425e16722eeb24e","c975524a66591c25","cddc98225a153fe6","b2c5cadef6afa9bb"],"x":174,"y":159,"w":552,"h":162},{"id":"b7b764fe27ce4e4b","type":"function","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"Hide Except","func":"msg.action = \"hide\"\nmsg.show = [\n    \"KT Status\",\n    \"KT Lights\",\n    \"KT Control\"\n]\nmsg.home = \"KT Status\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":200,"wires":[["a2abf886d0a3f790"]]},{"id":"a2abf886d0a3f790","type":"file in","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"","filename":"/home/pi/.node-red/flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":490,"y":240,"wires":[["e425e16722eeb24e"]]},{"id":"c90310f21e6b3663","type":"inject","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"hide","props":[{"p":"action","v":"hide","vt":"str"},{"p":"show","v":"[\"KT Status\",\"KT Lights\",\"KT Control\"]","vt":"json"},{"p":"home","v":"KT Status","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":240,"wires":[["a2abf886d0a3f790"]]},{"id":"01601fe8aa4c7280","type":"inject","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"show","props":[{"p":"action","v":"show","vt":"str"},{"p":"home","v":"KT Status","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":270,"wires":[["a2abf886d0a3f790"]]},{"id":"e425e16722eeb24e","type":"json","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"","property":"payload","action":"","pretty":false,"x":420,"y":280,"wires":[["c975524a66591c25"]]},{"id":"c975524a66591c25","type":"change","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"tab\":$$.home,\"tabs\": {$$.action: [$$.payload[type = \"ui_tab\"].name[$not($ in $$.show)]]}}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":280,"wires":[["cddc98225a153fe6"]]},{"id":"cddc98225a153fe6","type":"link out","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"link out 65","mode":"link","links":["14a00c8777ee43d9"],"x":685,"y":280,"wires":[]},{"id":"b2c5cadef6afa9bb","type":"link in","z":"3a22476a5982ab5f","g":"9352e7d986d0c921","name":"link in 117","links":["2f860a789bbd7ec5"],"x":235,"y":200,"wires":[["b7b764fe27ce4e4b"]]},{"id":"f9b43deebca5b0b7","type":"group","z":"3a22476a5982ab5f","name":"Viewer Selector","style":{"label":true,"color":"#000000"},"nodes":["c43517bc13bb4d3a","999d035d72ebe534","d89bd82c55348dfc","3b9af972d45a36df","5351c323c569b152","fd50f919543f8422","71c92899f88d349c","2e725ea58846d2d1"],"x":174,"y":329,"w":552,"h":162},{"id":"c43517bc13bb4d3a","type":"function","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"Hide Except","func":"msg.action = \"hide\"\nmsg.show = [\n    \"Main Status\",\n    \"Info\",\n    \"IR Kitchen\",\n    \"Environment\"\n]\nmsg.home = \"Main Status\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":370,"wires":[["999d035d72ebe534"]]},{"id":"999d035d72ebe534","type":"file in","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"","filename":"/home/pi/.node-red/flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":490,"y":410,"wires":[["5351c323c569b152"]]},{"id":"d89bd82c55348dfc","type":"inject","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"hide","props":[{"p":"action","v":"hide","vt":"str"},{"p":"show","v":"[\"Main Status\",\"Info\",\"IR Kitchen\",\"Environment\"]","vt":"json"},{"p":"home","v":"Main Status","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":410,"wires":[["999d035d72ebe534"]]},{"id":"3b9af972d45a36df","type":"inject","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"show","props":[{"p":"action","v":"show","vt":"str"},{"p":"home","v":"KT Status","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":270,"y":440,"wires":[["999d035d72ebe534"]]},{"id":"5351c323c569b152","type":"json","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"","property":"payload","action":"","pretty":false,"x":420,"y":450,"wires":[["fd50f919543f8422"]]},{"id":"fd50f919543f8422","type":"change","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"tab\":$$.home,\"tabs\": {$$.action: [$$.payload[type = \"ui_tab\"].name[$not($ in $$.show)]]}}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":570,"y":450,"wires":[["71c92899f88d349c"]]},{"id":"71c92899f88d349c","type":"link out","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"link out 66","mode":"link","links":["14a00c8777ee43d9"],"x":685,"y":450,"wires":[]},{"id":"2e725ea58846d2d1","type":"link in","z":"3a22476a5982ab5f","g":"f9b43deebca5b0b7","name":"link in 119","links":["fed3d88946a1d8ed"],"x":235,"y":370,"wires":[["c43517bc13bb4d3a"]]}]

Thanx again!!
Ed

You can output an array of objects, then use a split node to send each in turn, limited by a delay/rate node.

[{"id":"c90310f21e6b3663","type":"inject","z":"743cc0234f1851f1","name":"hide","props":[{"p":"action","v":"hide","vt":"str"},{"p":"show","v":"[\"Home\"]","vt":"json"},{"p":"home","v":"Home","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":290,"y":140,"wires":[["a2abf886d0a3f790"]]},{"id":"a2abf886d0a3f790","type":"file in","z":"743cc0234f1851f1","name":"","filename":"path to/flows.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":610,"y":100,"wires":[["e425e16722eeb24e"]]},{"id":"01601fe8aa4c7280","type":"inject","z":"743cc0234f1851f1","name":"show","props":[{"p":"action","v":"show","vt":"str"},{"p":"home","v":"Solar","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":310,"y":200,"wires":[["a2abf886d0a3f790"]]},{"id":"e425e16722eeb24e","type":"json","z":"743cc0234f1851f1","name":"","property":"payload","action":"","pretty":false,"x":490,"y":160,"wires":[["c975524a66591c25"]]},{"id":"c975524a66591c25","type":"change","z":"743cc0234f1851f1","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"[\t    {\"tab\":$$.home},\t    [$$.payload[type = \"ui_tab\"].name[$not($ in $$.show)]].{\"tabs\": {$$.action: $}}\t]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":160,"wires":[["c687df2f19fd51e1","04755197fe7e8ece"]]},{"id":"c687df2f19fd51e1","type":"debug","z":"743cc0234f1851f1","name":"debug 328","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":750,"y":200,"wires":[]},{"id":"04755197fe7e8ece","type":"split","z":"743cc0234f1851f1","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":430,"y":260,"wires":[["866e57f92e493634"]]},{"id":"866e57f92e493634","type":"delay","z":"743cc0234f1851f1","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"2","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":570,"y":260,"wires":[["c45bbf75f76a29cf"]]},{"id":"c45bbf75f76a29cf","type":"ui_ui_control","z":"743cc0234f1851f1","name":"","events":"all","x":720,"y":260,"wires":[[]]}]

I tried splicing the split and limit into the incoming line on the ui control node.... Didn't make any difference......

Do the function nodes I hacked together seem to be in relative good order? nothing i messed up on?

Just wanna make sure...

Ed

Your functions look fine, my example has a new jsonata expression in the change node, did you replace the change node?

I did, still no change though.... I first deployed with yr original change node, then the updated one...no discernible difference ...

Possibly, no definitely, I am expecting a bit too much from the older kit I am running... A "double" instruction in too short an order seems to be a little too much for the panel client... It looks like it might just be easier to split the instruction into 2 blocks, not ideal, makes it a bit messy, but might be easier to debug... one to hide everything, the next to display only what is selected... Your change node - Way above my level unfortunately, haven't a clue how to split it...(Granted, the split node should do the trick, but even that's barely within my grasp as to where it will split the payload...)

E

You could try a larger rate limit 1/1s or 1/2s.
My change node outputs an array of objects.
The split splits the array into individual objects.
Add debug nodes to see what the split outputs each iteration.

Good thinking!

Here is the debug output which is just after the limit node... For some reason it doesn't seem to be splitting it into a hide and show object...

Edit: My bad.....Used the 2nd version of the set msg.payload and it is indeed splitting it!

Aha... Found my mistake.... I have been able to remove the delays.... The seemingly random Tab problem was because, while during testing, I used a single convenient machine and hopped its IP address around into the various categories...

The long and the short of it is, to cater for a machine changing address, I have to first "Show All Tabs" then "Hide" ... As a matter of course, I am giving a 250ms delay to the hide command to ensure it goes through the works once the previous instruction has completed....

Looks awesome!! Thanks ever so much for the help!!

Regds
Ed

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