diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index 1836b6a9e..0faa11151 100644 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -924,7 +924,8 @@ "date": "timestamp", "jsonata": "expression", "env": "env variable", - "cred": "credential" + "cred": "credential", + "conf-types": "config node" } }, "editableList": { diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index bf1faf0a4..63f0fae23 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -91,6 +91,31 @@ RED.nodes = (function() { getNodeTypes: function() { return Object.keys(nodeDefinitions); }, + /** + * Get an array of node definitions + * @param {Object} options - options object + * @param {boolean} [options.configOnly] - if true, only return config nodes + * @param {function} [options.filter] - a filter function to apply to the list of nodes + * @returns array of node definitions + */ + getNodeDefinitions: function(options) { + const result = [] + const configOnly = (options && options.configOnly) + const filter = (options && options.filter) + const keys = Object.keys(nodeDefinitions) + for (const key of keys) { + const def = nodeDefinitions[key] + if(!def) { continue } + if (configOnly && def.category !== "config") { + continue + } + if (filter && !filter(nodeDefinitions[key])) { + continue + } + result.push(nodeDefinitions[key]) + } + return result + }, setNodeList: function(list) { nodeList = []; for(var i=0;i opt.value === value)?.options || [] + const selectedOption = _options.find(opt => opt.value === value) || { + title: '', + name: '', + module: '' + } + container.attr("title", selectedOption.title) // set tooltip to the full path/id of the module/node + container.text(selectedOption.name) // apply the "name" of the selected option + // set "line-height" such as to make the "name" appear further up, giving room for the "module" to be displayed below the value + container.css("line-height", "1.4em") + // add the module name in smaller, lighter font below the value + $('
').text(selectedOption.module).css({ + // "font-family": "var(--red-ui-monospace-font)", + color: "var(--red-ui-tertiary-text-color)", + "font-size": "0.8em", + "line-height": "1em", + opacity: 0.8 + }).appendTo(container); + }, + // hasValue: false, + options: function () { + if (this._optionsCache) { + return this._optionsCache + } + const configNodes = RED.nodes.registry.getNodeDefinitions({configOnly: true, filter: (def) => def.type !== "global-config"}).map((def) => { + // create a container with with 2 rows (row 1 for the name, row 2 for the module name in smaller, lighter font) + const container = $('
') + const row1Name = $('
').text(def.set.name) + const row2Module = $('
').text(def.set.module) + container.append(row1Name, row2Module) + + return { + value: def.type, + name: def.set.name || def.type, + enabled: def.set.enabled ?? true, + local: def.set.local, + title: def.set.id, // tooltip e.g. "node-red-contrib-foo/bar" + module: def.set.module, + icon: container[0].outerHTML.trim(), // the typeInput will interpret this as html text and render it in the anchor + } + }) + this._optionsCache = configNodes + return configNodes + } } }; + // For a type with options, check value is a valid selection // If !opt.multiple, returns the valid option object // if opt.multiple, returns an array of valid option objects // If not valid, returns null; function isOptionValueValid(opt, currentVal) { + let _options = opt.options + if (typeof _options === "function") { + _options = _options.call(this) + } if (!opt.multiple) { - for (var i=0;i