✨ FlexDash alpha release - round 3

Yeah fair enough. I thought that was the case.
see how you find the example above.. another option would be to replicate the same markdown editor of node-red and look similar to a JSON type for example with a button that opens the markdown editor window.it should also be fairly straightforward -

@tve
here is the other option, now creating a full-fledged markdown editor similar to what you get with the core nodes. it turned out much simpler than I imagined thanks to the good stuff in node-red editor api!!

in fact I think this should be an addition to node-red core as it would be good to add markdown as a supported type but obviously need to consider all test cases..

mentioning @knolleary in case you like me to create a PR for the relevant part in red.js, or perhaps there is already plan to include markdown as a new type given the recent changes with markdown enhancements!

image

image

the below follows similar apis used for other types such as JSON type..

$('#node-input-markdown').typedInput({
	typeField: '#node-input-markdownType',
	default: 'str',
	types: [
		{
			value: 'markdown',
			label: 'markdown',
			icon: 'fa fa-comment',
			valueLabel: function (container, value) {
				const nodeInput = $("<textarea>", { id: "valueLabelInput-markdown", resizable: false, placeholder: "expand button if you need more room" }).css({ display: "inline-block", padding: "0 0 0 3px", "border-radius": "0" })
				const optionExpandButton = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(nodeInput);
				$('<i class="red-ui-typedInput-icon fa fa-expand"></i>').appendTo(optionExpandButton);
				optionExpandButton.on('click', () => {
					RED.editor.editMarkdown({
						value: nodeInput.val(),
						stateId: RED.editor.generateViewStateId("typedInput", this, "markdown"),
						focus: true,
						complete: function (markdownValue) {
							nodeInput.val(markdownValue).trigger('change')
						}
					})
				})
				container.append(nodeInput, optionExpandButton)
				nodeInput.css({ width: `calc(100% - ${optionExpandButton.outerWidth()}px)`, height: "100%" })
				if (value) {
					try {
						nodeInput.val(JSON.parse(value)).trigger('change')
					} catch (error) {
						console.log('error parsing text')
					}
				}
			}

		}, 'str'

	]
})

not to then forget adding the below in oneditsave function for the data to be saved..

if ($('#node-input-markdown').typedInput('type') === 'markdown')
				$('#node-input-markdown').typedInput('value', JSON.stringify($("#valueLabelInput-markdown").val()))
2 Likes

A more re-usable way of achieving this is a helper function & using only the Client APIs to add buttons (no custom HTML or styles in the valueLabel callback)...

First a demo

typed-input-custom-types-demo (4)

HTML

    <div class="form-row">
        <label for="node-input-editor"><i class="fa fa-tag"></i> <span>My Editor</span></label>
        <input type="hidden" id="node-input-editorType">
        <input type="text" id="node-input-editor">
    </div>

DEFAULTS

Add the editor and editorType to the defaults: { ... } object

            editorType: {value:"str"},
            editor: {value:""}

SCRIPT (helper)

            // a helper for generating custom editor types
            const customEditorType = (type, label, icon, editorTitle) => {
                type = type || 'text'
                return {
                    value: type,
                    label: label || type,
                    icon: icon || 'fa fa-tag',
                    expand: function() {
                        const that = this;
                        RED.editor.editText({
                            mode: type,
                            title: editorTitle || `Edit ${type}`,
                            value: this.value().replace(/\t/g,"\n"),
                            stateId: RED.editor.generateViewStateId("typedInput", that, type),
                            focus: true,
                            complete: function(v) {
                                that.value(v.replace(/\n/g,"\t"));
                            }
                        })
                    }
                }
            }

SCRIPT (usage)

             // using the helper to generate custom editor types
            $('#node-input-editor').typedInput({
                typeField: '#node-input-editorType',
                default: 'str',
                types: [
                    customEditorType('markdown', 'markdown', 'fa fa-file-text'),
                    customEditorType('text', 'text', 'fa fa-file-text-o'),
                    customEditorType('sql', 'sql', 'fa fa-file-code-o'),
                    customEditorType('pgsql', 'pgsql', 'fa fa-file-code-o'),
                    customEditorType('css', 'css', 'fa fa-file-code-o'),
                    customEditorType('scss', 'scss', 'fa fa-file-code-o'),
                    customEditorType('html', 'html', 'fa fa-file-code-o'),
                    customEditorType('yaml', 'yaml', 'fa fa-file-code-o'),
                    customEditorType('xml', 'xml', 'fa fa-file-code-o'),
                    customEditorType('bat', 'bat', 'fa fa-file-code-o'),
                    customEditorType('shell', 'shell', 'fa fa-file-code-o'),
                    customEditorType('python', 'python', 'fa fa-file-code-o'),
                    'str'
                ]
            });
3 Likes

interesting one! thanks for sharing .. this expand property function is the trick !! yet another undocumented gem of the TypeDefinition that is useful in this context replacing the need to draw a custom button .. I do enjoy doing things from scratch though :grin:

Argh!! That's massive! (good I mean).

I can think of a number of areas of my nodes that are going to need redevelopment!


@Steve-Mcl - perhaps some thinking may be needed on some extended typedInput types to be built into the standard types?

Seems like YAML and Markdown might be 2 useful ones?

Hey Julian, this is a flexdash topic. Don't go stealing ideas from here for ui_builder :wink: :wink:

5 Likes

How do you mean Julian?

  1. like being able to specify 'yaml', 'markdown' in the types array
    OR -
  2. add to the APIs e.g. RED.editor.editYaml() and RED.editor.editMarkdown ( RED.editor.editMarkdown already exists on RED.editor).

(Brain: It might be enough to enumerate all the supported languages and if a match is found, add an expand button :thinking:)

At the heart of the TypedInput is an <input> which cannot contain newline characters. They will get stripped out by the browser.

This is why it doesn't support any types that rely on newline formatting that must be preserved (JSON can be minified and we wrote a custom minified/formatter for JSONata to get around this).

This is why I don't think Steve's proposal will work - it will lose all newline characters when saving the value.

The previous suggestion from @nileio required the oneditsave to get the value from a separate textarea, rather than rely on the editor getting the value from the TypedInput itself.

There's room in the Node-RED world for choice I hope. :grin: Anyway, as an IT architect and long-time IT consultant - "adopting with pride" is built into my DNA! :rofl:

Yes, indeed.

I've already used the markdown editor in a different node so was aware of that. I know a few people have mentioned YAML and it is popular for some things so may be worth considering. I know that not everything can be supported and it isn't too hard to add libraries to a custom node. But a couple more might be of use. Though maybe lazy loading might be called for if it doesn't already do that.

Ah, now that is an interesting thought indeed.

2 Likes

Thanks for all the typedInput input :laughing: I need to digest...

I did release a new version of node-red-flexdash in the meantime. No new features, I disabled the editing in FlexDash itself, removed all the related code, and added more integrity checks to node-red-flexdash. So if things currently are working for you or you don't have an easy roll-back you should probably not update.

I actually used the jsonata code as the basis for that example & in my brief test (as seen in the gif) it works as well as jsonata does (newlines are converted back and forth as the editor is opened and closed). Not sure why you would think it wouldn't work? it seems ok!? :man_shrugging:

Edit.

Ah, do you mean the text will need to be corrected again when the node author uses it?

Sorry, I missed you were doing the trick of replacing newlines with tabs (and vice versa).

That could well be problematic for formats that expect tabs to occur "naturally" in the content (which JSON and JSONata do not). For example, the importance of whitespace in YAML. This is why I hadn't previously pursued other multiline formats.

Hmmm needs more testing and thought. But hopefully there are enough clues for @tve to make progress :slightly_smiling_face:

trying to get my head around the custom FD node..
first observation: in your code below

this.sfc_editor = RED.editor.createEditor({
          id: 'node-input-sfc_source',
          mode: 'ace/mode/vue',
          value: this.sfc_source || sfc_template,
          minimap: { enabled: false },
        })

the editor assumed is Ace which is not anymore the default. Monaco is now the default.
was trying to use it for custom code but formatting, etc. is not working.
if you using monaco , then i think the only change you need is to change mode to language: "vue"
havent tested that change though. I believe that RED.editor.createEditor just takes in options supported by the respective code editor, and based on the user's settings.js either monaco or ace is loaded.

1 Like

Hmm, you didn't link to which code you looked at...

  • The "custom FD" node is written in Vue
  • The editor instantiation is in node-red-vue
  • I picked ace/mode/vue 'cause convertAceModeToMonacoLang converts it to "html" when using monaco and I'm hoping this produces something reasonable for folks still using ace (haven't tested that)
  • For me, using NR 3.0.2 this results in HTML formatting in monaco, which is pretty good 'cause it does the right thing for the HTML template, the CSS, and the javascript. Does it not for you?
  • I don't think you can get better formatting and syntax checking without running a language server, which I'd be interested in figuring out, but it's a bit low in the priority list

indentation and formatting in general with long lines of code does not work properly at all- I am just using my code editor then copy/paste.. I feel it has to do with monaco itself though or some sort of config because even in ui_template I am seeing strange behavior with long code - I find some sectins formatted OK and the rest of the code is not as if it has got an issue but I know the code is OK so my javascript <script> section is not formatted properly .. not sure what but I can't be bothered at this time digging onto that as I usually just copy and paste from my code editor..

1 Like

New bugfix release:

20 Feb 09:30:35 - [info] Node-RED FlexDash plugin version 0.4.151                                
20 Feb 09:30:35 - [info] Node-RED Vue version 0.1.15                                             
20 Feb 09:30:37 - [info] Node-RED FlexDash version 0.4.151                                       
20 Feb 09:30:37 - [info] Node-RED FD Core Widgets version 0.4.63                                 
20 Feb 09:30:39 - [info] FlexDash UI version 0.4.90

This fixes a number of issues when creating FlexDash config nodes that caused errors or values entered not to be saved.

Just updated node-red-flexdash via palette, and I get;

Node-RED FlexDash plugin version 0.4.151
Node-RED Vue version 0.1.10
Node-RED FlexDash version 0.4.151
Node-RED FD Core Widgets version 0.4.64
FlexDash UI version 0.4.90

...which is different to what you have.

I checked because the fd custom widget does not appear to show it's tabs as described in the widget help -

1) the widget source code that gets loaded into FlexDash
2) the standard FlexDash node configuration in the general tab
3) special widget configuration, including imports, in the config tab

custom

I've restarted node-RED, refreshed the browser cache, and can't see any obvious errors in the browser console of NR log.

1 Like

Looks like update via the palette doesn't upgrade dependencies, so I'll have to explicitly require node-red-vue 0.1.15, ugh. The corewidgets difference is inconsequential. The custom widget issue seems to be due to the node-red-vue version.
I'll update in ~1 hour.

1 Like

No rush... my existing custom widgets are still working fine - no tabs but they are still in their correct grids & panels in my dashboard.

1 Like