🎇 FlexDash alpha release - round 2

There is no repaint. I have not seen any issues WRT stuff not drawing... I have not tried your specific flow.

To reorder tabs:

  • enable edit mode in the top-right gear menu in FD
  • click on the pencil icon on the tab (icon) you want to move
  • use the left/right arrow buttons
  • when done, hit 'deploy' in the NR flow editor to persist the changes

That worked.

Where is the information stored? Is it persistent? Is it a cookie?

1 Like

I assume you're talking about the tab order: all dashboard configuration is stored in the flow, in this case each tab is a config node and the order of tabs is stored in the dashboard config node (type fd_dashboard).

I'm developing some logic for controlling garden lighting, which so far is working OK.
The buttons toggle their state, and the button colour changes only occur when feedback from the hardware confirms it's actually changed it's state (that's why there is a slight delay).

The only downside is that the buttons are not the same width because of their wordcount. Anyone any ideas how to create buttons of the same width.

Also... noticed that the panel which contains the buttons reacts to mouseover, should it?

buttons2

I haven't had any time to digg into FlexDash CSS and I have no clue how it is built up. Other than that I'm not sure about the CSS is meant to be overrided. From top of my head I kind of remember that correct path is to create kind of replica of the widget and do your stuff on top of it.
But that's only me with tiny knowledge base of topic

1 Like

I just had a good laugh imagining that all the lights are going on and off while you made the demo :joy:

1 Like

For me in Chrome it does not.

Version 105.0.5195.125 (Official Build) (x86_64)

output_buttons4

Albeit I cannot solve @Paul-Reed's question above, I would like to add some observation I made while playing with the buttons.

Setup:

and array of buttons[] is setup like this

Flow:

[{"id":"94ced6cd1748e170","type":"inject","z":"95e238910d29e0c2","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":60,"wires":[["f6032f8e6e47b319"]]},{"id":"8dbebc965a0f1df2","type":"inject","z":"95e238910d29e0c2","name":"","props":[{"p":"topic","v":"","vt":"date"},{"p":"title","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":160,"wires":[["75961e82d73d9aec"]]},{"id":"137570977409ef12","type":"debug","z":"95e238910d29e0c2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"topic","targetType":"msg","statusVal":"","statusType":"auto","x":540,"y":100,"wires":[]},{"id":"adb7eae63154ed82","type":"change","z":"95e238910d29e0c2","name":"","rules":[{"t":"set","p":"label","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":160,"wires":[["9408f7f8ce7a7483"]]},{"id":"04cee7036bd6529e","type":"change","z":"95e238910d29e0c2","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"","tot":"date"},{"t":"set","p":"title","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":310,"y":100,"wires":[["137570977409ef12","75961e82d73d9aec"]]},{"id":"f6032f8e6e47b319","type":"fd-date-time","z":"95e238910d29e0c2","fd_container":"2e1077589627ac5c","fd_cols":"2","fd_rows":1,"fd_array":false,"fd_array_max":10,"name":"","title":"Flow started at","popup_info":"","value":"","color":"","start_mode":0,"zoom":100,"low_threshold":null,"low_color":"blue","high_threshold":null,"high_color":"pink","chip":false,"units":["now","sec","min","hr","days","weeks","months"],"x":300,"y":60,"wires":[]},{"id":"9408f7f8ce7a7483","type":"fd-label","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":1,"fd_rows":1,"fd_array":false,"fd_array_max":10,"name":"","title":"","popup_info":"","label":"banane","color":"purple-accent-3","align":"center","justify":"center","weight":"400","size":"100%","padding":"4px","x":650,"y":160,"wires":[]},{"id":"3cb0ab8809391dd3","type":"fd-push-button","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":"2","fd_rows":1,"fd_array":false,"fd_array_max":10,"fd_output_topic":"","name":"","title":"add new button","popup_info":"","enabled":true,"color":"","output_value":25,"icon":null,"x":110,"y":100,"wires":[["04cee7036bd6529e"]]},{"id":"75961e82d73d9aec","type":"fd-push-button","z":"95e238910d29e0c2","fd_container":"6d69e6adc0fd0416","fd_cols":1,"fd_rows":1,"fd_array":true,"fd_array_max":"5","fd_output_topic":"bix","name":"array of buttons","title":"button1","popup_info":"","enabled":true,"color":"","output_value":25,"icon":null,"x":310,"y":160,"wires":[["adb7eae63154ed82"]]},{"id":"2e1077589627ac5c","type":"flexdash container","name":"Demo grid","kind":"StdGrid","fd_children":",f6032f8e6e47b319","title":"Demo grid","tab":"5671049acbf17679","min_cols":2,"max_cols":6,"parent":"","solid":false,"cols":"1","rows":"1"},{"id":"16ba1ce3418bf289","type":"flexdash container","name":"button static container","kind":"StdGrid","fd_children":",9408f7f8ce7a7483,3cb0ab8809391dd3","title":"button static container","tab":"5671049acbf17679","min_cols":"1","max_cols":"20","parent":"2e1077589627ac5c","solid":false,"cols":"1","rows":"1"},{"id":"6d69e6adc0fd0416","type":"flexdash container","name":"button container","kind":"StdGrid","fd_children":",75961e82d73d9aec","title":"button container","tab":"5671049acbf17679","min_cols":"1","max_cols":"20","parent":"","solid":false,"cols":"1","rows":"1"},{"id":"5671049acbf17679","type":"flexdash tab","name":"Demo","icon":"mdi-view-dashboard","title":"Demo","fd_children":",2e1077589627ac5c,16ba1ce3418bf289,6d69e6adc0fd0416","fd":"e8f5aea52ab49500"}]

Issue:
If I understand correctly, the limit of "Max widgets" should limit the array to 5 buttons.
Upon restart of node-red it looks normal. The array of buttons[] is empty, hence no button shown.
But then every click on the button ADD NEW BUTTON creates an additional button within the array and the limit of 5 is not enforced.

output_buttons3

Bonus question:
How can I empty the array of buttons except by restarting node-red?

Nope. Please live with it 'til there are more options for customization...

No it shouldn't, it's a bug I forgot to fix. Fortunately it's only cosmetic.

Bug.

https://flexdash.github.io/docs/using-flexdash/array-widgets/#deleting-array-elements

I've been wanting to add a message to delete-all but I'm not sure how to encode that...

2 Likes

This topic needs further exploration, prob best once Vuetify is released and has proper docs... IMHO the right way to do this type of stuff is to support fall through attributes in such a way that you can add arbitrary attributes to a FD node (e.g. in the general tab) and they "fall through" to the appropriate Vuetify or other main component. In addition, one of Vue's special attributes is style which would allow you to add CSS to some element.

All this needs some research and thinking so the end result is not a complete hodge-podge...

Deletion works if done item by item.

What sometimes does not work is the change of the dropdown list to empty.
Albeit, always sending { payload: "" }

For example:

const newbtn = oldbtn.filter(e => e !== topic)

return [
    { payload: "", choices: newbtn }
    ]

See in the example below... should be emptied whenever an item is deleted or all items are deleted. But sometimes it is not. Maybe a mistake in my code, but looks more like issue with logic inside dropdown.

output_buttons5

[{"id":"adb7eae63154ed82","type":"change","z":"95e238910d29e0c2","name":"","rules":[{"t":"set","p":"label","pt":"msg","to":"topic","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":680,"y":200,"wires":[["9408f7f8ce7a7483"]]},{"id":"6b55b3797fc1ce3d","type":"debug","z":"95e238910d29e0c2","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":850,"y":300,"wires":[]},{"id":"540205cc2cd8f831","type":"function","z":"95e238910d29e0c2","name":"add to list","func":"const topic = msg.topic\nvar btn = flow.get(\"btnarray\") || []\nbtn.push(topic)\nflow.set(\"btnarray\", btn)\n\nconst newPayload = flow.get(\"btnarray\") || []\n\nreturn [\n    { topic: topic, title: topic },\n    { payload: topic, choices: btn }\n];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":160,"y":200,"wires":[["75961e82d73d9aec"],["d7bb96a5b22e1080"]]},{"id":"ec335d92973b49df","type":"function","z":"95e238910d29e0c2","name":"remove from list","func":"var oldbtn = flow.get(\"btnarray\") || []\nconst topic = msg.payload\n\nconst newbtn = oldbtn.filter(e => e !== topic)\n\nflow.set(\"btnarray\", newbtn)\n\nreturn [\n    { topic: topic, _delete: true},\n    { payload: \"\", choices: newbtn }\n    ];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":140,"y":300,"wires":[["75961e82d73d9aec"],["d7bb96a5b22e1080"]]},{"id":"f89c21e8bfab9eb1","type":"http request","z":"95e238910d29e0c2","name":"","method":"GET","ret":"obj","paytoqs":"ignore","url":"https://random-word-api.herokuapp.com/word","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":350,"y":120,"wires":[["18c687013e62f435"]]},{"id":"18c687013e62f435","type":"change","z":"95e238910d29e0c2","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"msg.payload[0]","tot":"jsonata"},{"t":"set","p":"title","pt":"msg","to":"msg.payload[0]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":550,"y":120,"wires":[["540205cc2cd8f831"]]},{"id":"9408f7f8ce7a7483","type":"fd-label","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":1,"fd_rows":1,"fd_array":false,"fd_array_max":10,"name":"","title":"","popup_info":"","label":"banane","color":"purple-accent-3","align":"center","justify":"center","weight":"400","size":"100%","padding":"4px","x":830,"y":200,"wires":[]},{"id":"d7bb96a5b22e1080","type":"fd-dropdown-select","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":"2","fd_rows":1,"fd_array":false,"fd_array_max":10,"fd_output_topic":"","name":"","title":"Detele Button","popup_info":"","enabled":true,"value":"","choices":[],"labels":[],"allow_multiple":false,"color":"","x":610,"y":300,"wires":[["6b55b3797fc1ce3d","ec335d92973b49df"]]},{"id":"3cb0ab8809391dd3","type":"fd-push-button","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":"2","fd_rows":1,"fd_array":false,"fd_array_max":10,"fd_output_topic":"","name":"add new button","title":"add new button","popup_info":"","enabled":true,"color":"","output_value":25,"icon":null,"x":160,"y":120,"wires":[["f89c21e8bfab9eb1"]]},{"id":"75961e82d73d9aec","type":"fd-push-button","z":"95e238910d29e0c2","fd_container":"6d69e6adc0fd0416","fd_cols":1,"fd_rows":1,"fd_array":true,"fd_array_max":"5","fd_output_topic":"bix","name":"array of buttons","title":"button1","popup_info":"","enabled":true,"color":"","output_value":25,"icon":null,"x":490,"y":200,"wires":[["adb7eae63154ed82"]]},{"id":"7576b5c91ca5324e","type":"fd-push-button","z":"95e238910d29e0c2","fd_container":"16ba1ce3418bf289","fd_cols":"2","fd_rows":1,"fd_array":false,"fd_array_max":10,"fd_output_topic":"","name":"delete all","title":"delete all","popup_info":"","enabled":true,"color":"","output_value":25,"icon":null,"x":140,"y":400,"wires":[["4f6a3c53f61c5610"]]},{"id":"4f6a3c53f61c5610","type":"function","z":"95e238910d29e0c2","name":"delete all from list","func":"var oldbtn = flow.get(\"btnarray\") || []\n\nconst newbtn = []\n\nflow.set(\"btnarray\", newbtn)\n\nreturn [\n    oldbtn.map((e) => ({\n        topic: e,\n        _delete: true\n    }))\n,{payload: \"\", choices: []}]\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":400,"wires":[["53dcc48b954c6712","75961e82d73d9aec"],["d7bb96a5b22e1080","b7d412a169a434b2"]]},{"id":"53dcc48b954c6712","type":"debug","z":"95e238910d29e0c2","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":850,"y":380,"wires":[]},{"id":"b7d412a169a434b2","type":"debug","z":"95e238910d29e0c2","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":850,"y":420,"wires":[]},{"id":"16ba1ce3418bf289","type":"flexdash container","name":"button static container","kind":"StdGrid","fd_children":",9408f7f8ce7a7483,3cb0ab8809391dd3,d7bb96a5b22e1080,7576b5c91ca5324e","title":"button static container","tab":"5671049acbf17679","min_cols":"1","max_cols":"20","parent":"2e1077589627ac5c","solid":false,"cols":"1","rows":"1"},{"id":"6d69e6adc0fd0416","type":"flexdash container","name":"button container","kind":"StdGrid","fd_children":",75961e82d73d9aec","title":"button container","tab":"5671049acbf17679","min_cols":"1","max_cols":"20","parent":"","solid":false,"cols":"1","rows":"1"},{"id":"5671049acbf17679","type":"flexdash tab","name":"Demo","icon":"mdi-view-dashboard","title":"Demo","fd_children":",2e1077589627ac5c,16ba1ce3418bf289,6d69e6adc0fd0416","fd":"e8f5aea52ab49500"},{"id":"2e1077589627ac5c","type":"flexdash container","name":"Demo grid","kind":"StdGrid","fd_children":",f6032f8e6e47b319","title":"Demo grid","tab":"5671049acbf17679","min_cols":2,"max_cols":6,"parent":"","solid":false,"cols":"1","rows":"1"}]
1 Like

Just noticed this line in my node-RED log;

2 Oct 09:14:36 - [info] [flexdash dashboard:digitalnut] Sending config to UxW7pX5GYaG9R3RmAAAh from store undefined including dash, tabs, grids, widgets

It mentions store undefined, is this something that users need to define ?

1 Like

The 'store' here refers to something else, I should fix that. It's OK as-is.

1 Like

@tve, what is the proper way of emptying the dropdown list? Sending { payload: "" } works sometimes, but not always. Bug?

1 Like

@cameo69 Sorry, took a while. The problem is the same as for the toggle where the local feedback (you select a new value, it changes what the widgets displays and outputs the new value) fundamentally breaks what's happening. You can see that if you do the following:

  • add some buttons
  • select one button to delete
  • as you select, internally the value is set to the entry you choose
  • your flow then sets payload="" so the selection changes to empty
  • select another button to delete
  • as you select, internally the value is set to the entry you choose
  • your flow then sets payload="", but it's already "", so nothing changes
  • the drop-down thus continues to display the entry you deleted

I believe the fix is the same as for toggle and others: I need to move the feedback into node-red.

When using a Sparkline node, it does not load the previous value upon a browser connect, like a Stat node does.
Example, browser connects and the dashboard has a Stat node and a Sparkline node, both receiving the same payload. Initially, the Stat node displays the previous payload received (22.4°C), but the Sparkline node remains blank.
Only when another payload arrives (22.5°C) does the Sparkline node display any data (which could be minutes later).
Is this something that we need to manage in the flow? and if so, how can we determine that a browser has connected.
In the ui-dashboard, we used the ui_control node to determine a browser connect.

stat

1 Like

This is a bug that also affects the other time series plots. I have not looked into it, but it's at the top of my list. (I'm currently trying to use FD in another project.)

Edit: I spent some time looking at it. It's a slightly different issue. Well, there are really 2 issues :sleepy: One is easy to fix, which is that nothing appears when the widget is brought up. The harder one is that sending individual values (as opposed to an array) just fundamentally doesn't work the way I'm doing it. I need to fix that.
I will try to get another release out the coming week, but can't promise, some unexpected personal things have come up.

3 Likes

List of issues I have noted down:

  • Toggle and other input feedback/loopback has to go through server
  • Sending one value to plots or sparkline doesn't work when browser is refreshed, need to fix implementation
  • Log line "Sending config to ... from store undefined" is confusing
  • Panel shows a ripple on click, it shouldn't.
  • TimePlot is blank if both axes are used and the data for one of the axes is all null (prob. uPlot bug)
  • TimePlot should support SI prefixes
  • When there are many time plots on a page the tooltip can appear in the wrong plot (needs clean repro)
  • TimePlot: remove circles for data points when there are few points
  • TimelinePlot needs to be clickable
  • TimelinePlot: look into supporting multi-line labels
  • TextView: provide option to wrap text, also to scroll to bottom
  • Button: look into 100% width option as well as FAB support
  • Figure out support for per-connection data
  • Support simple login
  • Option to hide edit mode

Phew...

3 Likes

No worries, home life must always come first!

3 Likes

Thanks for your patience! If there's something you need fixed urgently please point it out and I'll take a crack at it.
I'm having trouble wrapping up a release of another open-source project (which actually uses FlexDash) and hope to get back to FlexDash this coming week, but I've been overly optimistic before...

4 Likes