✨ FlexDash alpha release - round 3

I look forward to the results 'cause that kind of CSS tweaking is outside of my skillset :laughing:

1 Like

I've certainly got to grips with CSS in more detail in the past 12m. I've really come to appreciate CSS variables and calculated values now. It let me build a CSS file that can automatically switch to light and dark based on your browser preference (or on some simple controls if you prefer).

1 Like

image

6 Likes

@smcgann99 Nice! are you sharing an example flow :wink:

2 Likes

@Paul-Reed Sure but its in need of some more work.

Shadows need to automatically adjust in size, (need to be computed) and at the moment colours have to be valid for Vue and "regular" CSS :wink:

[{"id":"9e00f73ed906e7a7","type":"inject","z":"b1fe02d0f08961f9","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":715,"y":930,"wires":[["48feeb03597e2f0c"]]},{"id":"7ad6d551fcbeaf32","type":"inject","z":"b1fe02d0f08961f9","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":715,"y":975,"wires":[["48feeb03597e2f0c"]]},{"id":"48feeb03597e2f0c","type":"flexdash custom","z":"b1fe02d0f08961f9","title":"LED","sfc_source":"<template>\r\n    <!-- For classes see the entire styles section of https://next.vuetifyjs.com/en/styles/border-radius/ -->\r\n    <div class=\"flex-grow-1 w-100 pa-2 d-flex flex-row align-center justify-space-around\">\r\n        <div>{{ label }}</div>\r\n        <div :class=\"`led bg-${color}`\" />\r\n    </div>\r\n</template>\r\n\r\n<style scoped>\r\n    div.led {\r\n        height: 80%;\r\n        aspect-ratio: 1;\r\n        width: min-content;\r\n        border-radius: 50%;\r\n        box-shadow: 0px 0px 15px 0px v-bind(color), rgba(0, 0, 0, 0.17) 0px -3px 2.5px 0px inset, rgba(0, 0, 0, 0.15) 0px -5px 4px 0px inset, rgba(0, 0, 0,\r\n                0.1) 0px -11px 5px 0px inset;\r\n    }\r\n</style>\r\n\r\n<script>\r\n    export default {\r\n    props: {\r\n        payload: { default: undefined }, // type is \"any\"\r\n        label: { default: \"state\", type: String }\r\n    },\r\n    computed: {\r\n        color() {\r\n            // use any material-design color: https://vuetifyjs.com/en/styles/colors/#material-colors\r\n            // (warning, it's link to the old docs 'cause that page is broken in the new ones...)\r\n            if (this.payload == 0) return \"green\"\r\n            else if (this.payload == null) return \"grey\" // null or undefined\r\n            else return \"red\"\r\n        }\r\n    }\r\n}\r\n</script>","fd_container":"","fd_cols":1,"fd_rows":1,"fd_array":false,"fd_array_max":10,"x":920,"y":960,"wires":[[]]}]
4 Likes

In a change of subject...
I switched to FlexDash recently and am impressed for the most part.
At this point the main thing I'm missing is a UI-Notification type of widget for FlexDash, like in the traditional dashboard.
Could anyone point me in the right direction to do something like this?

Basically I would like a widget that would popup in the lower right corner, and disappear after a few seconds. Also would be nice to have the option of having it pop up in the center with a OK button to close it.

A quick forum and google search brought me no results, or am I missing the obvious somewhere?

1 Like

Thanks for the feedback! I'm glad things are mostly working for you.
You didn't miss anything WRT pop-up, it's something that has been on my list but never got done. You can write one using a custom widget or using a pop-up grid, but it will be constrained to a specific tab, which is probably not what you're looking for. Let me see what I can do...

Someone asked via PM:

Do you plan to include a Sankey diagram node?

I'm unlikely to be able to write a sankey diagram node, but I'd be happy to help someone who wants to write one. I assume this would use D3? It's been a long time that I've used D3, but I can probably jog my memory... I could help, for example, getting D3 to work...

1 Like

Plotly includes Sankey-diagram, and in another thread we have the Plotly library working in flexdash.

Just a thought...

1 Like

Awesome!
The popup grid would likely do for my specific application, but yes a site-wide notification would come in real handy yet.

I built a popup grid, but I have not yet figured out how to make it pop up on an event, does the FD control node need to trigger it? Or is it simpler than that?

1 Like

Yep the FD ctrl node is needed to open/close the pop-up grid

in the known issues section of the docs you have
a FlexDash node in the flow editor uses typed input input fields which have various issues with defaults for boolean values, null as object or string values, not supporting the input of multi-line strings, not supporting a color picker, and more. An input field better suited for FlexDash is badly needed.

are you able to spell out all the issues/requirements needed for typedInput ? I just happen to play with it and might be able to help.., typedInput though it has some limitations, the use of any html elements into the widget is possible using the call back valueLabel . It has the container as parameter, and value so you can hook up any elements to the container. I used it to create my custom input fields. I have not tested the behavior of a multi-line input element for example, but I suppose it should be similar and it could relatively still look neat. I like typedInput because it has become defacto , and it is concise and reduces the need for many input rows.
you may have already tried everything but just thought I'd ask !

Do you have an example that uses that? I've not tried it yet and it would be interesting. I can think of several uses.

Here you go a simple one..

this is a type to display two adjacant elements , a spinner and a select with values (minutes, hours, days, etc.) .. so I use it to capture things like durations (since) , for example 1-day, 5-minutes, etc.
So the output is a simple object with two keys "num", and "dur"

try this type into one of your TypedInput

image

					{
						value: 'since',
						label: 'since',
						icon: 'fa fa-angle-double-left',
						valueLabel: function (container, value) {
							container.append(
								$('<input>', {
									id: 'node-input-datefrom-number',
									type: 'number',
									style: 'height: 31px; bottom:1rem',
								})
							);
							$('#node-input-datefrom-number').wrap('<div id="div-input-since" style="display:flex;"></div>').spinner({ min: 1 }).width('40%');

							$('#div-input-since')
								.append(
									$('<select>', {
										id: 'node-input-datefrom-duration',
									})
								)
								.appendTo(container);
							$('#node-input-datefrom-duration')
								.append($('<option>', { value: 'm', text: 'Minutes' }))
								.append($('<option>', { value: 'h', text: 'Hours' }))
								.append($('<option>', { value: 'd', text: 'Days' }))
								.append($('<option>', { value: 'w', text: 'Weeks' }))
								.append($('<option>', { value: 'M', text: 'Months' }))
								.append($('<option>', { value: 'y', text: 'Years' }))
								.width('100%');

							if (value && isJSON(value)) {
								$('#node-input-datefrom-number').val(JSON.parse(value).num).trigger('change');
								$('#node-input-datefrom-duration').val(JSON.parse(value).dur).trigger('change');
							}
						},
						validate: function (v) {
							return v && $('#node-input-datefrom-number').spinner('isValid') && $('#node-input-datefrom-duration').val();
						},
					},
2 Likes

Nice, thanks. :grin:

1 Like

Thanks for asking! The biggest issue is supporting multi-line strings. For example, the markdown widget takes a string input for the text it is to show and it's really painful to input paragraphs of text using a single-line field. What's missing is an "expand" button similar to the json input type that brings up monaco in full-panel mode.

If you choose to have it this way then it would be fairly easy to add an expand button! have a look at my previous example it is basically two elements within the typedInput.
the piece of work would obviously be the window which gets invoked by the button, this would mostly be custom-built , we can already initiate ace code editor from node-red - take a look at my custom graphql-server node schema editor https://github.com/nileio/node-red-contrib-graphql-server/blob/master/src/graphql-schema/graphql-schema.html
this is effectively using the built-in ace editor, however, i only added graphql mode which does not come out of the box with Node-RED.

I guess it should be possible to have a decent-looking multi-line editor if we just rely on simple multi-line input field unless you want all the bells and whistles of ace I assume not
I should be able to create something as example!

2 Likes

@tve here is an idea .. this is not the full-fledged markdown editor ofcourse, but thought it may work for simple multi-line text.
might be just enough for the markdown widget payload needs and play a little with the size of the element, and rather than using just a textarea we can use something else !

$('#node-input-multiLine').typedInput({
		typeField: '#node-input-multiLineType',
		default: 'str',
		types: [
			{
				value: 'multiline',
				label: 'text',
				icon: 'fa fa-quote-right',
				valueLabel: function (container, value) {
					const nodeInput = $("<input>", { id: "node-input-multiLineText", type: "text", placeholder: "expand button if you need more room" }).css({ padding: "0 0 0 3", width: "100%" });
					const expandIcon = $("<i>", { class: "fa fa-expand", css: { float: "right", position: "relative", top: "-30px", right: "10px" } }).click(() => {
						const floatingWindow = $("<div>", {
							id: "floating-textarea-window",
							css: {
								position: "fixed",
								top: nodeInput.offset().top - nodeInput.outerHeight(),
								left: nodeInput.offset().left,
								background: "#fff",
								border: 0,
								padding: "5px",
								minWidth: nodeInput.outerWidth(),
								minHeight: "100px",
								zIndex: 1
							}
						}).appendTo(container)
						$("<textarea>", { id: "floating-textarea" }).css({ "box-sizing": "border-box", width: "100%", minHeight: "100px", height: "100%" })
							.focusout(() => {
								nodeInput.val($("#floating-textarea").val());
								floatingWindow.remove();
							})
							.appendTo(floatingWindow)
							.val(nodeInput.val())
							.focus()
					});
					$("<div>").append(nodeInput, expandIcon).appendTo(container);

					if (value) {
						nodeInput.val(value).trigger('change')
						$('#node-input-multiLine').typedInput('validate')
					}
				},
				validate: function (v) {
					return v // if this field is required
				}

			},
			'str'
		]

	})
}

and we need to make sure we save the data back to typedInput in oneditsave like this

if ($('#node-input-multiLine').typedInput('type') === 'multiline')
  $('#node-input-multiLine').typedInput('value', $("#node-input-multiLineText").val())

image

image

also out of curiosity , if you only intend to have a single type of input why bother using typedInput at all?!if you only have a single type you can pretty much have any type of element and not restrict yourself within the boundaries of the typedInput..

Most of the widget props can have multiple types. That's less common for long string inputs but there are probably some examples for that too. But the nodes are auto-generated and so it's easier to always generate a typedInput and offer the types that the input supports, if there is type information.