mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Allow a node to declare what settings should be made available to the editor. (#1185)
* Implement register/exportNodeSettings. * Change normaliseRegisterTypeName to normaliseNodeTypeName. Force it to name in a camel case.
This commit is contained in:
parent
fca77a868f
commit
34089aec70
@ -216,14 +216,6 @@ module.exports = function(RED) {
|
||||
credentials: {
|
||||
user: {type:"text"},
|
||||
password: {type: "password"}
|
||||
},
|
||||
settings: {
|
||||
httpRequestColour: {
|
||||
value: "red",
|
||||
// validate: function(v) { return IT MUST BE A NUMBER },
|
||||
// required: false,
|
||||
exportable: true
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -493,6 +493,7 @@ function enableNodeSet(typeOrId) {
|
||||
delete config.err;
|
||||
config.enabled = true;
|
||||
nodeConfigCache = null;
|
||||
settings.enableNodeSettings(config.types);
|
||||
return saveNodeList().then(function() {
|
||||
return filterNodeInfo(config);
|
||||
});
|
||||
@ -515,6 +516,7 @@ function disableNodeSet(typeOrId) {
|
||||
// TODO: persist setting
|
||||
config.enabled = false;
|
||||
nodeConfigCache = null;
|
||||
settings.disableNodeSettings(config.types);
|
||||
return saveNodeList().then(function() {
|
||||
return filterNodeInfo(config);
|
||||
});
|
||||
|
@ -18,10 +18,12 @@ var when = require("when");
|
||||
var clone = require("clone");
|
||||
var assert = require("assert");
|
||||
var log = require("./log");
|
||||
var util = require("./util");
|
||||
|
||||
var userSettings = null;
|
||||
var globalSettings = null;
|
||||
var nodeSettings = null;
|
||||
var disableNodeSettings = null;
|
||||
var storage = null;
|
||||
|
||||
var persistentSettings = {
|
||||
@ -40,6 +42,7 @@ var persistentSettings = {
|
||||
}
|
||||
globalSettings = null;
|
||||
nodeSettings = {};
|
||||
disableNodeSettings = {};
|
||||
},
|
||||
load: function(_storage) {
|
||||
storage = _storage;
|
||||
@ -103,24 +106,49 @@ var persistentSettings = {
|
||||
storage = null;
|
||||
},
|
||||
registerNodeSettings: function(type, opts) {
|
||||
//console.log(type,opts);
|
||||
// 1. TODO: validate the option names are allowed for the node type
|
||||
|
||||
// 2. store this information against the node type
|
||||
nodeSettings[type] = opts;
|
||||
|
||||
|
||||
// TODO: remove the node settings if the node is disabled/removed from runtime
|
||||
try {
|
||||
for (var property in opts) {
|
||||
if (opts.hasOwnProperty(property)) {
|
||||
var normalisedType = util.normaliseNodeTypeName(type);
|
||||
if (!property.startsWith(normalisedType)) {
|
||||
throw new Error("The name of node setting property " + property + " must start with \"" + normalisedType + "\" (case sensitive).");
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeSettings[type] = opts;
|
||||
} catch (err) {
|
||||
console.log(err.toString());
|
||||
}
|
||||
},
|
||||
exportNodeSettings: function(safeSettings) {
|
||||
// 1. forEach type in nodeSettings...
|
||||
// 2. forEach setting for that type...
|
||||
// 3. if globalSettings has a property with the required name...
|
||||
// 4. set safeSettings.property to that value
|
||||
// 5. else if the setting has a default 'value' provided
|
||||
// 6. set safeSettings.property to that value
|
||||
safeSettings["nodeSettings"] = {};
|
||||
for (var type in nodeSettings) {
|
||||
if (nodeSettings.hasOwnProperty(type) && !disableNodeSettings[type]) {
|
||||
var nodeTypeSettings = nodeSettings[type];
|
||||
for (var property in nodeTypeSettings) {
|
||||
if (nodeTypeSettings.hasOwnProperty(property)) {
|
||||
var setting = nodeTypeSettings[property];
|
||||
if (userSettings.hasOwnProperty(property)) {
|
||||
safeSettings["nodeSettings"][property] = userSettings[property];
|
||||
} else if (setting.exportable) {
|
||||
safeSettings["nodeSettings"][property] = setting.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return safeSettings;
|
||||
},
|
||||
enableNodeSettings: function(types) {
|
||||
types.forEach(function(type) {
|
||||
disableNodeSettings[type] = false;
|
||||
});
|
||||
},
|
||||
disableNodeSettings: function(types) {
|
||||
types.forEach(function(type) {
|
||||
disableNodeSettings[type] = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,6 +328,18 @@ function evaluateNodeProperty(value, type, node, msg) {
|
||||
return value;
|
||||
}
|
||||
|
||||
function normaliseNodeTypeName(name) {
|
||||
var result = name.replace(/[^a-zA-Z0-9]/g, " ");
|
||||
result = result.trim();
|
||||
result = result.replace(/ +/g, " ");
|
||||
result = result.replace(/ ./g,
|
||||
function(s) {
|
||||
return s.charAt(1).toUpperCase();
|
||||
}
|
||||
);
|
||||
result = result.charAt(0).toLowerCase() + result.slice(1);
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ensureString: ensureString,
|
||||
@ -338,5 +350,6 @@ module.exports = {
|
||||
getMessageProperty: getMessageProperty,
|
||||
setMessageProperty: setMessageProperty,
|
||||
evaluateNodeProperty: evaluateNodeProperty,
|
||||
normalisePropertyExpression: normalisePropertyExpression
|
||||
normalisePropertyExpression: normalisePropertyExpression,
|
||||
normaliseNodeTypeName: normaliseNodeTypeName
|
||||
};
|
||||
|
@ -142,4 +142,85 @@ describe("red/settings", function() {
|
||||
settings.should.not.have.property("c");
|
||||
|
||||
});
|
||||
|
||||
it('registers node settings and exports them', function() {
|
||||
var userSettings = {};
|
||||
settings.init(userSettings);
|
||||
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}, injectSize:{value:"100", exportable:true}} );
|
||||
settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:false}, mqttSize:{value:"50", exportable:true}} );
|
||||
settings.registerNodeSettings("http request", {httpRequest1:{value:"a1", exportable:true}} );
|
||||
settings.registerNodeSettings(" http--request<> ", {httpRequest2:{value:"a2", exportable:true}} );
|
||||
settings.registerNodeSettings("_http_request_", {httpRequest3:{value:"a3", exportable:true}} );
|
||||
settings.registerNodeSettings("mQtT", {mQtTColor:{value:"purple", exportable:true}} );
|
||||
settings.registerNodeSettings("abc123", {abc123:{value:"def456", exportable:true}} );
|
||||
var safeSettings = {};
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
|
||||
safeSettings["nodeSettings"].should.have.property("injectSize", "100");
|
||||
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
|
||||
safeSettings["nodeSettings"].should.have.property("mqttSize", "50");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequest1", "a1");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequest2", "a2");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequest3", "a3");
|
||||
safeSettings["nodeSettings"].should.have.property("mQtTColor", "purple");
|
||||
safeSettings["nodeSettings"].should.have.property("abc123", "def456");
|
||||
});
|
||||
|
||||
it('prohibits registering the property whose name do not start with type name', function() {
|
||||
var userSettings = {};
|
||||
settings.init(userSettings);
|
||||
settings.registerNodeSettings("inject", {color:{value:"red", exportable:true}} );
|
||||
settings.registerNodeSettings("_a_b_1_", {ab1Color:{value:"red", exportable:true}} );
|
||||
settings.registerNodeSettings("AB2", {AB2Color:{value:"red", exportable:true}} );
|
||||
settings.registerNodeSettings("abcDef", {abcColor:{value:"red", exportable:true}} );
|
||||
var safeSettings = {};
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.not.have.property("color");
|
||||
safeSettings["nodeSettings"].should.not.have.property("ab1Color", "blue");
|
||||
safeSettings["nodeSettings"].should.not.have.property("AB2Color");
|
||||
safeSettings["nodeSettings"].should.not.have.property("abcColor");
|
||||
});
|
||||
|
||||
it('overwrites node settings with user settings', function() {
|
||||
var userSettings = {
|
||||
injectColor: "green",
|
||||
mqttColor: "yellow",
|
||||
c: [1,2,3]
|
||||
}
|
||||
settings.init(userSettings);
|
||||
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
|
||||
var safeSettings = {};
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.have.property("injectColor", "green");
|
||||
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
|
||||
});
|
||||
|
||||
it('disables/enables node settings', function() {
|
||||
var userSettings = {};
|
||||
settings.init(userSettings);
|
||||
|
||||
var safeSettings = {};
|
||||
settings.registerNodeSettings("inject", {injectColor:{value:"red", exportable:true}} );
|
||||
settings.registerNodeSettings("mqtt", {mqttColor:{value:"purple", exportable:true}} );
|
||||
settings.registerNodeSettings("http request", {httpRequestColor:{value:"yellow", exportable:true}} );
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
|
||||
safeSettings["nodeSettings"].should.have.property("mqttColor", "purple");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
|
||||
|
||||
var types = ["inject", "mqtt"];
|
||||
settings.disableNodeSettings(types);
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.not.have.property("injectColor");
|
||||
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
|
||||
|
||||
types = ["inject"];
|
||||
settings.enableNodeSettings(types);
|
||||
settings.exportNodeSettings(safeSettings);
|
||||
safeSettings["nodeSettings"].should.have.property("injectColor", "red");
|
||||
safeSettings["nodeSettings"].should.not.have.property("mqttColor");
|
||||
safeSettings["nodeSettings"].should.have.property("httpRequestColor", "yellow");
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -364,4 +364,21 @@ describe("red/util", function() {
|
||||
it("fail <blank>",function() { testInvalid("");})
|
||||
|
||||
});
|
||||
|
||||
describe('normaliseNodeTypeName', function() {
|
||||
function normalise(input, expected) {
|
||||
var result = util.normaliseNodeTypeName(input);
|
||||
result.should.eql(expected);
|
||||
}
|
||||
|
||||
it('pass blank',function() { normalise("", "") });
|
||||
it('pass ab1',function() { normalise("ab1", "ab1") });
|
||||
it('pass AB1',function() { normalise("AB1", "aB1") });
|
||||
it('pass a b 1',function() { normalise("a b 1", "aB1") });
|
||||
it('pass a-b-1',function() { normalise("a-b-1", "aB1") });
|
||||
it('pass ab1 ',function() { normalise(" ab1 ", "ab1") });
|
||||
it('pass _a_b_1_',function() { normalise("_a_b_1_", "aB1") });
|
||||
it('pass http request',function() { normalise("http request", "httpRequest") });
|
||||
it('pass HttpRequest',function() { normalise("HttpRequest", "httpRequest") });
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user