add "conf-types" to typedInput

This commit is contained in:
Steve-Mcl 2024-03-01 11:06:27 +00:00
parent 7ee2b93b10
commit d509c1a57c
3 changed files with 108 additions and 14 deletions

View File

@ -924,7 +924,8 @@
"date": "timestamp", "date": "timestamp",
"jsonata": "expression", "jsonata": "expression",
"env": "env variable", "env": "env variable",
"cred": "credential" "cred": "credential",
"conf-types": "config node"
} }
}, },
"editableList": { "editableList": {

View File

@ -91,6 +91,31 @@ RED.nodes = (function() {
getNodeTypes: function() { getNodeTypes: function() {
return Object.keys(nodeDefinitions); 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) { setNodeList: function(list) {
nodeList = []; nodeList = [];
for(var i=0;i<list.length;i++) { for(var i=0;i<list.length;i++) {

View File

@ -578,18 +578,75 @@
eyeButton.show(); eyeButton.show();
} }
} }
},
'conf-types': {
value: "conf-types",
label: "config",
icon: "fa fa-cog",
// hasValue: false,
valueLabel: function (container, value) {
// get the selected option (for access to the "name" and "module" properties)
const _options = this._optionsCache || this.typeList.find(opt => 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
$('<div></div>').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 = $('<div style="display: flex; flex-direction: column; justify-content: space-between; row-gap: 1px;">')
const row1Name = $('<div>').text(def.set.name)
const row2Module = $('<div style="font-size: 0.8em; color: var(--red-ui-tertiary-text-color);">').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 // For a type with options, check value is a valid selection
// If !opt.multiple, returns the valid option object // If !opt.multiple, returns the valid option object
// if opt.multiple, returns an array of valid option objects // if opt.multiple, returns an array of valid option objects
// If not valid, returns null; // If not valid, returns null;
function isOptionValueValid(opt, currentVal) { function isOptionValueValid(opt, currentVal) {
let _options = opt.options
if (typeof _options === "function") {
_options = _options.call(this)
}
if (!opt.multiple) { if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) { for (var i=0;i<_options.length;i++) {
op = opt.options[i]; op = _options[i];
if (typeof op === "string" && op === currentVal) { if (typeof op === "string" && op === currentVal) {
return {value:currentVal} return {value:currentVal}
} else if (op.value === currentVal) { } else if (op.value === currentVal) {
@ -606,8 +663,8 @@
currentValues[v] = true; currentValues[v] = true;
} }
}); });
for (var i=0;i<opt.options.length;i++) { for (var i=0;i<_options.length;i++) {
op = opt.options[i]; op = _options[i];
var val = typeof op === "string" ? op : op.value; var val = typeof op === "string" ? op : op.value;
if (currentValues.hasOwnProperty(val)) { if (currentValues.hasOwnProperty(val)) {
delete currentValues[val]; delete currentValues[val];
@ -1034,7 +1091,9 @@
if (this.optionMenu) { if (this.optionMenu) {
this.optionMenu.remove(); this.optionMenu.remove();
} }
this.menu.remove(); if (this.menu) {
this.menu.remove();
}
this.uiSelect.remove(); this.uiSelect.remove();
}, },
types: function(types) { types: function(types) {
@ -1067,7 +1126,7 @@
this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) }); this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) });
if (currentType && !this.typeMap.hasOwnProperty(currentType)) { if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
if (!firstCall) { if (!firstCall) {
this.type(this.typeList[0].value); this.type(this.typeList[0]?.value || ""); // permit empty typeList
} }
} else { } else {
this.propertyType = null; this.propertyType = null;
@ -1104,6 +1163,11 @@
var selectedOption = []; var selectedOption = [];
var valueToCheck = value; var valueToCheck = value;
if (opt.options) { if (opt.options) {
let _options = opt.options
if (typeof opt.options === "function") {
_options = opt.options.call(this)
}
if (opt.hasValue && opt.parse) { if (opt.hasValue && opt.parse) {
var parts = opt.parse(value); var parts = opt.parse(value);
if (this.options.debug) { console.log(this.identifier,"new parse",parts) } if (this.options.debug) { console.log(this.identifier,"new parse",parts) }
@ -1117,8 +1181,8 @@
checkValues = valueToCheck.split(","); checkValues = valueToCheck.split(",");
} }
checkValues.forEach(function(valueToCheck) { checkValues.forEach(function(valueToCheck) {
for (var i=0;i<opt.options.length;i++) { for (var i=0;i<_options.length;i++) {
var op = opt.options[i]; var op = _options[i];
if (typeof op === "string") { if (typeof op === "string") {
if (op === valueToCheck || op === ""+valueToCheck) { if (op === valueToCheck || op === ""+valueToCheck) {
selectedOption.push(that.activeOptions[op]); selectedOption.push(that.activeOptions[op]);
@ -1153,7 +1217,7 @@
}, },
type: function(type) { type: function(type) {
if (!arguments.length) { if (!arguments.length) {
return this.propertyType; return this.propertyType || this.options?.default || '';
} else { } else {
var that = this; var that = this;
if (this.options.debug) { console.log(this.identifier,"----- SET TYPE -----",type) } if (this.options.debug) { console.log(this.identifier,"----- SET TYPE -----",type) }
@ -1254,6 +1318,10 @@
this.optionMenu = null; this.optionMenu = null;
} }
if (opt.options) { if (opt.options) {
let _options = opt.options
if (typeof _options === "function") {
_options = opt.options.call(this);
}
if (this.optionExpandButton) { if (this.optionExpandButton) {
this.optionExpandButton.hide(); this.optionExpandButton.hide();
this.optionExpandButton.shown = false; this.optionExpandButton.shown = false;
@ -1270,7 +1338,7 @@
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
} }
this.activeOptions = {}; this.activeOptions = {};
opt.options.forEach(function(o) { _options.forEach(function(o) {
if (typeof o === 'string') { if (typeof o === 'string') {
that.activeOptions[o] = {label:o,value:o}; that.activeOptions[o] = {label:o,value:o};
} else { } else {
@ -1290,7 +1358,7 @@
if (validValues) { if (validValues) {
that._updateOptionSelectLabel(validValues) that._updateOptionSelectLabel(validValues)
} else { } else {
op = opt.options[0]; op = _options[0] || {value:""}; // permit zero options
if (typeof op === "string") { if (typeof op === "string") {
this.value(op); this.value(op);
that._updateOptionSelectLabel({value:op}); that._updateOptionSelectLabel({value:op});
@ -1309,7 +1377,7 @@
that._updateOptionSelectLabel(validValues); that._updateOptionSelectLabel(validValues);
} }
} else { } else {
var selectedOption = this.optionValue||opt.options[0]; var selectedOption = this.optionValue||_options[0];
if (opt.parse) { if (opt.parse) {
var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption var selectedOptionObj = typeof selectedOption === "string"?{value:selectedOption}:selectedOption
var parts = opt.parse(this.input.val(),selectedOptionObj); var parts = opt.parse(this.input.val(),selectedOptionObj);
@ -1353,7 +1421,7 @@
}) })
} }
} }
this.optionMenu = this._createMenu(opt.options,opt,function(v){ this.optionMenu = this._createMenu(_options,opt,function(v){
if (!opt.multiple) { if (!opt.multiple) {
that._updateOptionSelectLabel(that.activeOptions[v]); that._updateOptionSelectLabel(that.activeOptions[v]);
if (!opt.hasValue) { if (!opt.hasValue) {