icon_paths[module.name].push(path.resolve(icon.path)) )
}
-
- if (version) {
- moduleConfigs[set.module].version = version;
- }
- moduleConfigs[set.module].local = set.local;
-
- moduleConfigs[set.module].nodes[set.name] = set;
- nodeList.push(id);
nodeConfigCache = null;
}
+
function removeNode(id) {
var config = moduleConfigs[getModule(id)].nodes[getNode(id)];
if (!config) {
@@ -346,6 +343,7 @@ function getModuleInfo(module) {
name: module,
version: moduleConfigs[module].version,
local: moduleConfigs[module].local,
+ path: moduleConfigs[module].path,
nodes: []
};
for (var i = 0; i < nodes.length; ++i) {
@@ -592,6 +590,7 @@ var iconCache = {};
var defaultIcon = path.resolve(__dirname + '/../../../../public/icons/arrow-in.png');
function nodeIconDir(dir) {
+ return;
icon_paths[dir.name] = icon_paths[dir.name] || [];
icon_paths[dir.name].push(path.resolve(dir.path));
@@ -647,11 +646,11 @@ function getNodeIcons() {
for (var module in moduleConfigs) {
if (moduleConfigs.hasOwnProperty(module)) {
if (moduleConfigs[module].icons) {
- iconList[module] = moduleConfigs[module].icons;
+ iconList[module] = [];
+ moduleConfigs[module].icons.forEach(icon=>{ iconList[module] = iconList[module].concat(icon.icons) });
}
}
}
-
return iconList;
}
@@ -663,7 +662,9 @@ var registry = module.exports = {
registerNodeConstructor: registerNodeConstructor,
getNodeConstructor: getNodeConstructor,
- addNodeSet: addNodeSet,
+
+ addModule: addModule,
+
enableNodeSet: enableNodeSet,
disableNodeSet: disableNodeSet,
diff --git a/test/red/runtime/nodes/registry/loader_spec.js b/test/red/runtime/nodes/registry/loader_spec.js
index 87e1c060b..d34d802a3 100644
--- a/test/red/runtime/nodes/registry/loader_spec.js
+++ b/test/red/runtime/nodes/registry/loader_spec.js
@@ -79,6 +79,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version": "1.2.3",
"nodes": {
"TestNode1": {
"file": path.join(resourcesDir,"TestNode1","TestNode1.js"),
@@ -91,34 +92,39 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
- registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-1');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","1.2.3");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("TestNode1");
+ module.nodes.TestNode1.should.have.property("id","node-red/TestNode1");
+ module.nodes.TestNode1.should.have.property("module","node-red");
+ module.nodes.TestNode1.should.have.property("name","TestNode1");
+ module.nodes.TestNode1.should.have.property("file");
+ module.nodes.TestNode1.should.have.property("template");
+ module.nodes.TestNode1.should.have.property("enabled",true);
+ module.nodes.TestNode1.should.have.property("loaded",true);
+ module.nodes.TestNode1.should.have.property("types");
+ module.nodes.TestNode1.types.should.have.a.length(1);
+ module.nodes.TestNode1.types[0].should.eql('test-node-1');
+ module.nodes.TestNode1.should.have.property("config");
+ module.nodes.TestNode1.should.have.property("help");
+ module.nodes.TestNode1.should.have.property("namespace","node-red");
nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode1');
nodes.registerType.lastCall.args[1].should.eql('test-node-1');
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -128,6 +134,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version": "4.5.6",
"nodes": {
"MultipleNodes1": {
"file": path.join(resourcesDir,"MultipleNodes1","MultipleNodes1.js"),
@@ -140,27 +147,33 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/MultipleNodes1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/MultipleNodes1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(2);
- registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-multiple-1a');
- registry.addNodeSet.lastCall.args[1].types[1].should.eql('test-node-multiple-1b');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
+
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","4.5.6");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("MultipleNodes1");
+ module.nodes.MultipleNodes1.should.have.property("id","node-red/MultipleNodes1");
+ module.nodes.MultipleNodes1.should.have.property("module","node-red");
+ module.nodes.MultipleNodes1.should.have.property("name","MultipleNodes1");
+ module.nodes.MultipleNodes1.should.have.property("file");
+ module.nodes.MultipleNodes1.should.have.property("template");
+ module.nodes.MultipleNodes1.should.have.property("enabled",true);
+ module.nodes.MultipleNodes1.should.have.property("loaded",true);
+ module.nodes.MultipleNodes1.should.have.property("types");
+ module.nodes.MultipleNodes1.types.should.have.a.length(2);
+ module.nodes.MultipleNodes1.types[0].should.eql('test-node-multiple-1a');
+ module.nodes.MultipleNodes1.types[1].should.eql('test-node-multiple-1b');
+ module.nodes.MultipleNodes1.should.have.property("config");
+ module.nodes.MultipleNodes1.should.have.property("help");
+ module.nodes.MultipleNodes1.should.have.property("namespace","node-red");
nodes.registerType.calledTwice.should.be.true();
nodes.registerType.firstCall.args[0].should.eql('node-red/MultipleNodes1');
@@ -168,8 +181,9 @@ describe("red/nodes/registry/loader",function() {
nodes.registerType.secondCall.args[0].should.eql('node-red/MultipleNodes1');
nodes.registerType.secondCall.args[1].should.eql('test-node-multiple-1b');
+
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -180,6 +194,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version":"2.4.6",
"nodes": {
"TestNode2": {
"file": path.join(resourcesDir,"TestNode2","TestNode2.js"),
@@ -192,34 +207,41 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode2");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode2");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
- registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-2');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
+
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","2.4.6");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("TestNode2");
+ module.nodes.TestNode2.should.have.property("id","node-red/TestNode2");
+ module.nodes.TestNode2.should.have.property("module","node-red");
+ module.nodes.TestNode2.should.have.property("name","TestNode2");
+ module.nodes.TestNode2.should.have.property("file");
+ module.nodes.TestNode2.should.have.property("template");
+ module.nodes.TestNode2.should.have.property("enabled",true);
+ module.nodes.TestNode2.should.have.property("loaded",true);
+ module.nodes.TestNode2.should.have.property("types");
+ module.nodes.TestNode2.types.should.have.a.length(1);
+ module.nodes.TestNode2.types[0].should.eql('test-node-2');
+ module.nodes.TestNode2.should.have.property("config");
+ module.nodes.TestNode2.should.have.property("help");
+ module.nodes.TestNode2.should.have.property("namespace","node-red");
+ module.nodes.TestNode2.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true();
nodes.registerType.lastCall.args[0].should.eql('node-red/TestNode2');
nodes.registerType.lastCall.args[1].should.eql('test-node-2');
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -230,6 +252,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version":"1.2.3",
"nodes": {
"TestNode3": {
"file": path.join(resourcesDir,"TestNode3","TestNode3.js"),
@@ -242,32 +265,38 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/TestNode3");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/TestNode3");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
- registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-3');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('err','fail');
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","1.2.3");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("TestNode3");
+ module.nodes.TestNode3.should.have.property("id","node-red/TestNode3");
+ module.nodes.TestNode3.should.have.property("module","node-red");
+ module.nodes.TestNode3.should.have.property("name","TestNode3");
+ module.nodes.TestNode3.should.have.property("file");
+ module.nodes.TestNode3.should.have.property("template");
+ module.nodes.TestNode3.should.have.property("enabled",true);
+ module.nodes.TestNode3.should.have.property("loaded",false);
+ module.nodes.TestNode3.should.have.property("types");
+ module.nodes.TestNode3.types.should.have.a.length(1);
+ module.nodes.TestNode3.types[0].should.eql('test-node-3');
+ module.nodes.TestNode3.should.have.property("config");
+ module.nodes.TestNode3.should.have.property("help");
+ module.nodes.TestNode3.should.have.property("namespace","node-red");
+ module.nodes.TestNode3.should.have.property('err','fail');
- nodes.registerType.calledOnce.should.be.false();
+ nodes.registerType.called.should.be.false();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -277,6 +306,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version":"1.2.3",
"nodes": {
"DoesNotExist": {
"file": path.join(resourcesDir,"doesnotexist"),
@@ -289,31 +319,37 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/DoesNotExist");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DoesNotExist");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0);
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('err');
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","1.2.3");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("DoesNotExist");
+ module.nodes.DoesNotExist.should.have.property("id","node-red/DoesNotExist");
+ module.nodes.DoesNotExist.should.have.property("module","node-red");
+ module.nodes.DoesNotExist.should.have.property("name","DoesNotExist");
+ module.nodes.DoesNotExist.should.have.property("file");
+ module.nodes.DoesNotExist.should.have.property("template");
+ module.nodes.DoesNotExist.should.have.property("enabled",true);
+ module.nodes.DoesNotExist.should.have.property("loaded",false);
+ module.nodes.DoesNotExist.should.have.property("types");
+ module.nodes.DoesNotExist.types.should.have.a.length(0);
+ module.nodes.DoesNotExist.should.not.have.property("config");
+ module.nodes.DoesNotExist.should.not.have.property("help");
+ module.nodes.DoesNotExist.should.not.have.property("namespace","node-red");
+ module.nodes.DoesNotExist.should.have.property('err');
- nodes.registerType.calledOnce.should.be.false();
+ nodes.registerType.called.should.be.false();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -323,6 +359,7 @@ describe("red/nodes/registry/loader",function() {
var result = {};
result["node-red"] = {
"name": "node-red",
+ "version": "1.2.3",
"nodes": {
"DuffNode": {
"file": path.join(resourcesDir,"DuffNode","DuffNode.js"),
@@ -335,32 +372,39 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
// This module isn't already loaded
stubs.push(sinon.stub(registry,"getNodeInfo", function(){ return null; }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.load().then(function(result) {
- registry.addNodeSet.called.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("node-red/DuffNode");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"node-red/DuffNode");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"node-red");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',false);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',undefined);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(0);
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('namespace','node-red');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('err');
- registry.addNodeSet.lastCall.args[1].err.should.endWith("DuffNode.html does not exist");
- nodes.registerType.calledOnce.should.be.false();
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","node-red");
+ module.should.have.property("version","1.2.3");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("DuffNode");
+ module.nodes.DuffNode.should.have.property("id","node-red/DuffNode");
+ module.nodes.DuffNode.should.have.property("module","node-red");
+ module.nodes.DuffNode.should.have.property("name","DuffNode");
+ module.nodes.DuffNode.should.have.property("file");
+ module.nodes.DuffNode.should.have.property("template");
+ module.nodes.DuffNode.should.have.property("enabled",true);
+ module.nodes.DuffNode.should.have.property("loaded",false);
+ module.nodes.DuffNode.should.have.property("types");
+ module.nodes.DuffNode.types.should.have.a.length(0);
+ module.nodes.DuffNode.should.not.have.property("config");
+ module.nodes.DuffNode.should.not.have.property("help");
+ module.nodes.DuffNode.should.not.have.property("namespace","node-red");
+ module.nodes.DuffNode.should.have.property('err');
+ module.nodes.DuffNode.err.should.endWith("DuffNode.html does not exist");
+
+ nodes.registerType.called.should.be.false();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -379,7 +423,7 @@ describe("red/nodes/registry/loader",function() {
stubs.push(sinon.stub(registry,"getModuleInfo",function(){return{}}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.addModule("test-module").otherwise(function(err) {
+ loader.addModule("test-module").catch(function(err) {
err.code.should.eql("module_already_loaded");
done();
});
@@ -390,7 +434,7 @@ describe("red/nodes/registry/loader",function() {
throw new Error("failure");
}));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
- loader.addModule("test-module").otherwise(function(err) {
+ loader.addModule("test-module").catch(function(err) {
err.message.should.eql("failure");
done();
});
@@ -419,29 +463,36 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},log:{info:function(){},_:function(){}},settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list");
- registry.addNodeSet.calledOnce.should.be.true();
- registry.addNodeSet.lastCall.args[0].should.eql("TestNodeModule/TestNode1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('id',"TestNodeModule/TestNode1");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('module',"TestNodeModule");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('enabled',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('loaded',true);
- registry.addNodeSet.lastCall.args[1].should.have.a.property('version',"1.2.3");
- registry.addNodeSet.lastCall.args[1].should.have.a.property('types');
- registry.addNodeSet.lastCall.args[1].types.should.have.a.length(1);
- registry.addNodeSet.lastCall.args[1].types[0].should.eql('test-node-mod-1');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('config');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('help');
- registry.addNodeSet.lastCall.args[1].should.have.a.property('namespace','TestNodeModule');
- registry.addNodeSet.lastCall.args[1].should.not.have.a.property('err');
+
+ registry.addModule.called.should.be.true();
+ var module = registry.addModule.lastCall.args[0];
+ module.should.have.property("name","TestNodeModule");
+ module.should.have.property("version","1.2.3");
+ module.should.have.property("nodes");
+ module.nodes.should.have.property("TestNode1");
+ module.nodes.TestNode1.should.have.property("id","TestNodeModule/TestNode1");
+ module.nodes.TestNode1.should.have.property("module","TestNodeModule");
+ module.nodes.TestNode1.should.have.property("name","TestNode1");
+ module.nodes.TestNode1.should.have.property("file");
+ module.nodes.TestNode1.should.have.property("template");
+ module.nodes.TestNode1.should.have.property("enabled",true);
+ module.nodes.TestNode1.should.have.property("loaded",true);
+ module.nodes.TestNode1.should.have.property("types");
+ module.nodes.TestNode1.types.should.have.a.length(1);
+ module.nodes.TestNode1.types[0].should.eql('test-node-mod-1');
+ module.nodes.TestNode1.should.have.property("config");
+ module.nodes.TestNode1.should.have.property("help");
+ module.nodes.TestNode1.should.have.property("namespace","TestNodeModule");
+ module.nodes.TestNode1.should.not.have.property('err');
nodes.registerType.calledOnce.should.be.true();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -469,15 +520,15 @@ describe("red/nodes/registry/loader",function() {
}));
stubs.push(sinon.stub(registry,"saveNodeList", function(){ return "a node list" }));
- stubs.push(sinon.stub(registry,"addNodeSet", function(){ return }));
+ stubs.push(sinon.stub(registry,"addModule", function(){ return }));
stubs.push(sinon.stub(nodes,"registerType"));
loader.init({log:{"_":function(){},warn:function(){}},nodes:nodes,i18n:{defaultLang:"en-US"},events:{on:function(){},removeListener:function(){}},version: function() { return "0.12.0"}, settings:{available:function(){return true;}}});
loader.addModule("TestNodeModule").then(function(result) {
result.should.eql("a node list");
- registry.addNodeSet.called.should.be.false();
+ registry.addModule.called.should.be.false();
nodes.registerType.called.should.be.false();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -498,7 +549,7 @@ describe("red/nodes/registry/loader",function() {
node.enabled.should.be.false();
nodes.registerType.called.should.be.false();
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -517,7 +568,7 @@ describe("red/nodes/registry/loader",function() {
node.err.toString().should.eql("Error: fail to require (line:1)");
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
diff --git a/test/red/runtime/nodes/registry/localfilesystem_spec.js b/test/red/runtime/nodes/registry/localfilesystem_spec.js
index d240e2ca5..2ffc220f4 100644
--- a/test/red/runtime/nodes/registry/localfilesystem_spec.js
+++ b/test/red/runtime/nodes/registry/localfilesystem_spec.js
@@ -166,7 +166,15 @@ describe("red/nodes/registry/localfilesystem",function() {
}},
settings:{coreNodesDir:resourcesDir}
});
- localfilesystem.getNodeFiles(true);
+ var list = localfilesystem.getNodeFiles(true);
+ list.should.have.property("node-red");
+ list["node-red"].should.have.property("icons");
+ list["node-red"].icons.should.have.length(2);
+ //list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/local/NestedDirectoryNode/NestedNode/icons"))
+ list["node-red"].icons[1].should.have.property("icons");
+ list["node-red"].icons[1].icons.should.have.length(1);
+ list["node-red"].icons[1].icons[0].should.eql("arrow-in.png");
+ done();
});
it("scans icons dir in library",function(done) {
var count = 0;
@@ -188,7 +196,15 @@ describe("red/nodes/registry/localfilesystem",function() {
}},
settings:{userDir:userDir}
});
- localfilesystem.getNodeFiles(true);
+ var list = localfilesystem.getNodeFiles(true);
+ list.should.have.property("node-red");
+ list["node-red"].should.have.property("icons");
+ list["node-red"].icons.should.have.length(2);
+ //list["node-red"].icons[1].should.have.property("path",path.join(__dirname,"resources/userDir/lib/icons"))
+ list["node-red"].icons[1].should.have.property("icons");
+ list["node-red"].icons[1].icons.should.have.length(1);
+ list["node-red"].icons[1].icons[0].should.eql("test_icon.png");
+ done();
});
});
describe("#getModuleFiles",function() {
@@ -256,6 +272,14 @@ describe("red/nodes/registry/localfilesystem",function() {
settings:{coreNodesDir:moduleDir}
});
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
+ nodeModule.should.have.property("TestNodeModule");
+ nodeModule.TestNodeModule.should.have.property('icons');
+
+ nodeModule.TestNodeModule.icons.should.have.length(1);
+ nodeModule.TestNodeModule.icons[0].should.have.property("path");
+ nodeModule.TestNodeModule.icons[0].should.have.property("icons");
+ nodeModule.TestNodeModule.icons[0].icons[0].should.eql("arrow-in.png");
+ done();
});
});
});
diff --git a/test/red/runtime/nodes/registry/registry_spec.js b/test/red/runtime/nodes/registry/registry_spec.js
index cdfba8c45..c5b9f6b5a 100644
--- a/test/red/runtime/nodes/registry/registry_spec.js
+++ b/test/red/runtime/nodes/registry/registry_spec.js
@@ -132,7 +132,7 @@ describe("red/nodes/registry/registry",function() {
});
- describe('#addNodeSet', function() {
+ describe.skip('#addNodeSet', function() {
it('adds a node set for an unknown module', function() {
typeRegistry.init(settings);
@@ -290,29 +290,34 @@ describe("red/nodes/registry/registry",function() {
describe('#saveNodeList',function() {
it('rejects when settings unavailable',function(done) {
- typeRegistry.init(stubSettings({},false,{}));
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
- typeRegistry.saveNodeList().otherwise(function(err) {
+ typeRegistry.init(stubSettings({},false,{}),null,events);
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {"test-name":{module:"test-module",name:"test-name",types:[]}}});
+ typeRegistry.saveNodeList().catch(function(err) {
done();
});
});
it('saves the list',function(done) {
var s = stubSettings({},true,{});
typeRegistry.init(s);
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
- typeRegistry.addNodeSet("test-module/test-name-2",testNodeSet2WithError, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":testNodeSet1,
+ "test-name-2":testNodeSet2WithError
+ }});
+
typeRegistry.saveNodeList().then(function() {
s.set.called.should.be.true();
s.set.lastCall.args[0].should.eql('nodes');
var nodes = s.set.lastCall.args[1];
nodes.should.have.property('test-module');
for (var n in nodes['test-module'].nodes) {
- var nn = nodes['test-module'].nodes[n];
- nn.should.not.have.property('err');
- nn.should.not.have.property('id');
+ if (nodes['test-module'].nodes.hasOwnProperty(n)) {
+ var nn = nodes['test-module'].nodes[n];
+ nn.should.not.have.property('err');
+ nn.should.not.have.property('id');
+ }
}
done();
- }).otherwise(function(err) {
+ }).catch(function(err) {
done(err);
});
});
@@ -338,7 +343,9 @@ describe("red/nodes/registry/registry",function() {
it('removes a known module', function() {
var s = stubSettings({},true,{});
typeRegistry.init(s);
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":testNodeSet1
+ }});
var moduleList = typeRegistry.getModuleList();
moduleList.should.have.a.property("test-module");
typeRegistry.getNodeList().should.have.lengthOf(1);
@@ -355,27 +362,28 @@ describe("red/nodes/registry/registry",function() {
typeRegistry.init(settings,{
getNodeHelp: function(config) { return "HE"+config.name+"LP" }
});
- typeRegistry.addNodeSet("test-module/test-name",{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"]
- }, "0.0.1");
- typeRegistry.getNodeConfig("test-module/test-name").should.eql('\nconfigAHEtest-nameLP');
- typeRegistry.getAllNodeConfigs().should.eql('\n\nconfigAHEtest-nameLP');
- typeRegistry.addNodeSet("test-module/test-name-2",{
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-c","test-d"]
- }, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"]
+ },
+ "test-name-2":{
+ id: "test-module/test-name-2",
+ module: "test-module",
+ name: "test-name-2",
+ enabled: true,
+ loaded: false,
+ config: "configB",
+ types: [ "test-c","test-d"]
+ }
+ }});
+ typeRegistry.getNodeConfig("test-module/test-name").should.eql('\nconfigAHEtest-nameLP');
typeRegistry.getNodeConfig("test-module/test-name-2").should.eql('\nconfigBHEtest-name-2LP');
typeRegistry.getAllNodeConfigs().should.eql('\n\nconfigAHEtest-nameLP\n\nconfigBHEtest-name-2LP');
});
@@ -383,16 +391,18 @@ describe("red/nodes/registry/registry",function() {
describe('#getModuleInfo', function() {
it('returns module info', function() {
typeRegistry.init(settings,{});
- typeRegistry.addNodeSet("test-module/test-name",{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
+ }
+ }});
var moduleInfo = typeRegistry.getModuleInfo("test-module");
moduleInfo.should.have.a.property('name','test-module');
moduleInfo.should.have.a.property('version','0.0.1');
@@ -405,16 +415,18 @@ describe("red/nodes/registry/registry",function() {
describe('#getNodeInfo', function() {
it('returns node info', function() {
typeRegistry.init(settings,{});
- typeRegistry.addNodeSet("test-module/test-name",{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
+ }
+ }});
var nodeSetInfo = typeRegistry.getNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.not.have.a.property('config');
@@ -424,17 +436,19 @@ describe("red/nodes/registry/registry",function() {
describe('#getFullNodeInfo', function() {
it('returns node info', function() {
typeRegistry.init(settings,{});
- typeRegistry.addNodeSet("test-module/test-name",{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
- }, "0.0.1");
+ }
+ }});
var nodeSetInfo = typeRegistry.getFullNodeInfo("test-module/test-name");
nodeSetInfo.should.have.a.property('id',"test-module/test-name");
nodeSetInfo.should.have.a.property('config');
@@ -447,26 +461,28 @@ describe("red/nodes/registry/registry",function() {
describe('#getNodeList', function() {
it("returns a filtered list", function() {
typeRegistry.init(settings,{});
- typeRegistry.addNodeSet("test-module/test-name",{
- id: "test-module/test-name",
- module: "test-module",
- name: "test-name",
- enabled: true,
- loaded: false,
- config: "configA",
- types: [ "test-a","test-b"],
- file: "abc"
- }, "0.0.1");
- typeRegistry.addNodeSet("test-module/test-name-2",{
- id: "test-module/test-name-2",
- module: "test-module",
- name: "test-name-2",
- enabled: true,
- loaded: false,
- config: "configB",
- types: [ "test-c","test-d"],
- file: "def"
- }, "0.0.1");
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
+ },
+ "test-name-2":{
+ id: "test-module/test-name-2",
+ module: "test-module",
+ name: "test-name-2",
+ enabled: true,
+ loaded: false,
+ config: "configB",
+ types: [ "test-c","test-d"],
+ file: "def"
+ }
+ }});
var filterCallCount = 0;
var filteredList = typeRegistry.getNodeList(function(n) { filterCallCount++; return n.name === 'test-name-2';});
filterCallCount.should.eql(2);
@@ -532,10 +548,22 @@ describe("red/nodes/registry/registry",function() {
});
it('returns a registered icon' , function() {
- var testIcon = path.resolve(__dirname+'/../../../../resources/icons/test_icon.png');
- events.emit("node-icon-dir",{name:"test-module", path: path.resolve(__dirname+'/../../../../resources/icons'), icons:[]});
+ var testIcon = path.resolve(__dirname+'/../../../../resources/icons/');
+ typeRegistry.init(settings,{});
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
+ }
+ },icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
- iconPath.should.eql(testIcon);
+ iconPath.should.eql(testIcon+"/test_icon.png");
});
it('returns the debug icon when getting an unknown module', function() {
@@ -552,14 +580,26 @@ describe("red/nodes/registry/registry",function() {
});
it('returns an icon list of registered node module', function() {
- typeRegistry.addNodeSet("test-module/test-name",testNodeSet1,"0.0.1");
- events.emit("node-icon-dir",{name:"test-module", path:"",icons:["test_icon1.png"]});
+ var testIcon = path.resolve(__dirname+'/resources/userDir/lib/icons/');
+ typeRegistry.init(settings,{},events);
+ typeRegistry.addModule({name: "test-module",version:"0.0.1",nodes: {
+ "test-name":{
+ id: "test-module/test-name",
+ module: "test-module",
+ name: "test-name",
+ enabled: true,
+ loaded: false,
+ config: "configA",
+ types: [ "test-a","test-b"],
+ file: "abc"
+ }
+ },icons: [{path:testIcon,icons:['test_icon.png']}]});
var iconList = typeRegistry.getNodeIcons();
- iconList.should.eql({"test-module":["test_icon1.png"]});
+ iconList.should.eql({"test-module":["test_icon.png"]});
});
- it('returns an icon list of unregistered node module', function() {
- events.emit("node-icon-dir",{name:"test-module", path:"", icons:["test_icon1.png", "test_icon2.png"]});
+ it.skip('returns an icon list of unregistered node module', function() {
+ // events.emit("node-icon-dir",{name:"test-module", path:"", icons:["test_icon1.png", "test_icon2.png"]});
var iconList = typeRegistry.getNodeIcons();
iconList.should.eql({"test-module":["test_icon1.png","test_icon2.png"]});
});
diff --git a/test/red/runtime/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png b/test/red/runtime/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/arrow-in.png
new file mode 100644
index 0000000000000000000000000000000000000000..e38f3914600901b736f5fa18786ee11be6d41c28
GIT binary patch
literal 393
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6icy_X9x!n)NrJ90QsB+9+AZi
z3~X;em{G3O!W1YdS>hT|5}cn_Ql40p%1~Zju9umYU7Va)kgAtols@~NjT8d|Bb%p-
zV~9uR+N-+$hZ97Oeyp#Y$RU!&XX#m>@|$agvYL9Jz$O6}72y^gZVi>ZMeaH^t*Q|!
zLhVk<0xdko8zYVo#8M-LBBd8b>1kw|i?FO)bWqsy_rwQg27N4y
zeX6pqO$_Cex^^A7_NsS@+=bOASA^wN0&GKN(hlAguRU&q-
jTBY?`*L>xN+|S&+7B*edvmQhOgN?z{)z4*}Q$iB}+9!`i
literal 0
HcmV?d00001
diff --git a/test/red/runtime/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/file.txt b/test/red/runtime/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/red/runtime/nodes/resources/local/NestedDirectoryNode/NestedNode/icons/file.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This file exists just to ensure the 'icons' directory is in the repository.
-TODO: a future test needs to ensure the right icon files are loaded - this
- directory can be used for that
diff --git a/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt b/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
deleted file mode 100644
index 59a29af14..000000000
--- a/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/file.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This file exists just to ensure the 'icons' directory is in the repository.
-TODO: a future test needs to ensure the right icon files are loaded - this
- directory can be used for that
From 184b1b018ce0e4c041370f2aa914663864432b89 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Mon, 21 May 2018 22:38:07 +0100
Subject: [PATCH 6/9] Add missing resource file
---
.../node_modules/TestNodeModule/icons/arrow-in.png | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
diff --git a/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png b/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
new file mode 100644
index 000000000..59a29af14
--- /dev/null
+++ b/test/red/runtime/nodes/resources/local/TestNodeModule/node_modules/TestNodeModule/icons/arrow-in.png
@@ -0,0 +1,3 @@
+This file exists just to ensure the 'icons' directory is in the repository.
+TODO: a future test needs to ensure the right icon files are loaded - this
+ directory can be used for that
From 36105412b1b8f27ce9344c62a39d1c40c9bdf184 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 22 May 2018 11:41:22 +0100
Subject: [PATCH 7/9] Add 'private' property to userDir generated package.json
This stops the warnings from npm about missing repo and license fields.
As there's no expectation for a user to publish their userDir to npm, then
setting private is entirely appropriate.
---
red/runtime/storage/localfilesystem/index.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/red/runtime/storage/localfilesystem/index.js b/red/runtime/storage/localfilesystem/index.js
index 2a57c7323..5a33aaecf 100644
--- a/red/runtime/storage/localfilesystem/index.js
+++ b/red/runtime/storage/localfilesystem/index.js
@@ -72,7 +72,8 @@ var localfilesystem = {
var defaultPackage = {
"name": "node-red-project",
"description": "A Node-RED Project",
- "version": "0.0.1"
+ "version": "0.0.1",
+ "private": true
};
return util.writeFile(packageFile,JSON.stringify(defaultPackage,"",4));
}
From a4eb8e11c3df0805ef347eb14ba4c77674638b47 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Wed, 23 May 2018 10:25:10 +0100
Subject: [PATCH 8/9] Collapse sidebar tabs
---
editor/js/ui/common/popover.js | 8 +-
editor/js/ui/common/tabs.js | 194 ++++++++++++++++----
editor/js/ui/projects/tab-versionControl.js | 2 +
editor/js/ui/sidebar.js | 7 +-
editor/js/ui/tab-config.js | 3 +-
editor/js/ui/tab-info.js | 2 +
editor/sass/popover.scss | 30 ++-
editor/sass/tabs.scss | 61 +++++-
nodes/core/core/58-debug.html | 4 +-
9 files changed, 269 insertions(+), 42 deletions(-)
diff --git a/editor/js/ui/common/popover.js b/editor/js/ui/common/popover.js
index 6a0bc9fdf..0170f7070 100644
--- a/editor/js/ui/common/popover.js
+++ b/editor/js/ui/common/popover.js
@@ -19,12 +19,14 @@ RED.popover = (function() {
"default": {
top: 10,
leftRight: 17,
- leftLeft: 25
+ leftLeft: 25,
+ leftBottom: 8,
},
"small": {
top: 5,
leftRight: 17,
- leftLeft: 16
+ leftLeft: 16,
+ leftBottom: 3,
}
}
function createPopover(options) {
@@ -69,6 +71,8 @@ RED.popover = (function() {
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left+targetWidth+deltaSizes[size].leftRight});
} else if (direction === 'left') {
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
+ } else if (direction === 'bottom') {
+ div.css({top: targetPos.top+targetHeight+deltaSizes[size].top,left:targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom});
}
if (instant) {
div.show();
diff --git a/editor/js/ui/common/tabs.js b/editor/js/ui/common/tabs.js
index f66b95421..23b69f5d1 100644
--- a/editor/js/ui/common/tabs.js
+++ b/editor/js/ui/common/tabs.js
@@ -19,8 +19,10 @@
RED.tabs = (function() {
function createTabs(options) {
var tabs = {};
+ var pinnedTabsCount = 0;
var currentTabWidth;
var currentActiveTabWidth = 0;
+ var collapsibleMenu;
var ul = options.element || $("#"+options.id);
var wrapper = ul.wrap( "" ).parent();
@@ -50,6 +52,55 @@ RED.tabs = (function() {
scrollRight = $('
').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
}
+
+ if (options.collapsible) {
+ // var dropDown = $('
',{class:"red-ui-tabs-select"}).appendTo(wrapper);
+ // ul.hide();
+ wrapper.addClass("red-ui-tabs-collapsible");
+
+ var collapsedButtonsRow = $('
').appendTo(wrapper);
+
+ var selectButton = $('
').appendTo(collapsedButtonsRow);
+ selectButton.addClass("red-ui-tab-link-button-menu")
+ selectButton.click(function(evt) {
+ evt.preventDefault();
+ if (!collapsibleMenu) {
+ var pinnedOptions = [];
+ var options = [];
+ ul.children().each(function(i,el) {
+ var id = $(el).data('tabId');
+ var opt = {
+ id:"red-ui-tabs-menu-option-"+id,
+ label: tabs[id].name,
+ onselect: function() {
+ activateTab(id);
+ }
+ };
+ if (tabs[id].pinned) {
+ pinnedOptions.push(opt);
+ } else {
+ options.push(opt);
+ }
+ });
+ options = pinnedOptions.concat(options);
+ collapsibleMenu = RED.menu.init({id:"debug-message-option-menu",options: options});
+ collapsibleMenu.css({
+ position: "absolute"
+ })
+ collapsibleMenu.on('mouseleave', function(){ $(this).hide() });
+ collapsibleMenu.on('mouseup', function() { $(this).hide() });
+ collapsibleMenu.appendTo("body");
+ var elementPos = selectButton.offset();
+ collapsibleMenu.css({
+ top: (elementPos.top+selectButton.height()-20)+"px",
+ left: (elementPos.left - collapsibleMenu.width() + selectButton.width())+"px"
+ })
+ }
+ collapsibleMenu.toggle();
+ })
+
+ }
+
function scrollEventHandler(evt,dir) {
evt.preventDefault();
if ($(this).hasClass('disabled')) {
@@ -118,6 +169,9 @@ RED.tabs = (function() {
ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"});
link.parent().addClass("active");
+ var parentId = link.parent().attr('id');
+ wrapper.find(".red-ui-tab-link-button").removeClass("active");
+ $("#"+parentId+"-link-button").addClass("active");
if (options.scrollable) {
var pos = link.parent().position().left;
if (pos-21 < 0) {
@@ -155,41 +209,70 @@ RED.tabs = (function() {
var tabs = ul.find("li.red-ui-tab");
var width = wrapper.width();
var tabCount = tabs.size();
- var tabWidth = (width-12-(tabCount*6))/tabCount;
- currentTabWidth = (100*tabWidth/width)+"%";
- currentActiveTabWidth = currentTabWidth+"%";
- if (options.scrollable) {
- tabWidth = Math.max(tabWidth,140);
- currentTabWidth = tabWidth+"px";
- currentActiveTabWidth = 0;
- var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
- ul.width(listWidth);
- updateScroll();
- } else if (options.hasOwnProperty("minimumActiveTabWidth")) {
- if (tabWidth < options.minimumActiveTabWidth) {
- tabCount -= 1;
- tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
- currentTabWidth = (100*tabWidth/width)+"%";
- currentActiveTabWidth = options.minimumActiveTabWidth+"px";
+ var tabWidth;
+
+ if (options.collapsible) {
+ tabWidth = width - collapsedButtonsRow.width()-10;
+ if (tabWidth < 198) {
+ var delta = 198 - tabWidth;
+ var b = collapsedButtonsRow.find("a:last").prev();
+ while (b.is(":not(:visible)")) {
+ b = b.prev();
+ }
+ if (!b.hasClass("red-ui-tab-link-button-pinned")) {
+ b.hide();
+ }
+ tabWidth = width - collapsedButtonsRow.width()-10;
} else {
- currentActiveTabWidth = 0;
+ var space = width - 198 - collapsedButtonsRow.width();
+ if (space > 40) {
+ collapsedButtonsRow.find("a:not(:visible):first").show();
+ tabWidth = width - collapsedButtonsRow.width()-10;
+ }
}
- }
- tabs.css({width:currentTabWidth});
- if (tabWidth < 50) {
- ul.find(".red-ui-tab-close").hide();
- ul.find(".red-ui-tab-icon").hide();
- ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
+ tabs.css({width:tabWidth});
+
} else {
- ul.find(".red-ui-tab-close").show();
- ul.find(".red-ui-tab-icon").show();
- ul.find(".red-ui-tab-label").css({paddingLeft:""})
- }
- if (currentActiveTabWidth !== 0) {
- ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
- ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
- ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
- ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
+ var tabWidth = (width-12-(tabCount*6))/tabCount;
+ currentTabWidth = (100*tabWidth/width)+"%";
+ currentActiveTabWidth = currentTabWidth+"%";
+ if (options.scrollable) {
+ tabWidth = Math.max(tabWidth,140);
+ currentTabWidth = tabWidth+"px";
+ currentActiveTabWidth = 0;
+ var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
+ ul.width(listWidth);
+ updateScroll();
+ } else if (options.hasOwnProperty("minimumActiveTabWidth")) {
+ if (tabWidth < options.minimumActiveTabWidth) {
+ tabCount -= 1;
+ tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
+ currentTabWidth = (100*tabWidth/width)+"%";
+ currentActiveTabWidth = options.minimumActiveTabWidth+"px";
+ } else {
+ currentActiveTabWidth = 0;
+ }
+ }
+ if (options.collapsible) {
+ console.log(currentTabWidth);
+ }
+
+ tabs.css({width:currentTabWidth});
+ if (tabWidth < 50) {
+ ul.find(".red-ui-tab-close").hide();
+ ul.find(".red-ui-tab-icon").hide();
+ ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
+ } else {
+ ul.find(".red-ui-tab-close").show();
+ ul.find(".red-ui-tab-icon").show();
+ ul.find(".red-ui-tab-label").css({paddingLeft:""})
+ }
+ if (currentActiveTabWidth !== 0) {
+ ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
+ ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
+ ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
+ ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
+ }
}
}
@@ -210,11 +293,15 @@ RED.tabs = (function() {
activateTab(tab.find("a"));
}
li.remove();
+ if (tabs[id].pinned) {
+ pinnedTabsCount--;
+ }
if (options.onremove) {
options.onremove(tabs[id]);
}
delete tabs[id];
updateTabWidths();
+ collapsibleMenu = null;
}
return {
@@ -223,13 +310,55 @@ RED.tabs = (function() {
var li = $("
",{class:"red-ui-tab"}).appendTo(ul);
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
li.data("tabId",tab.id);
+
+ if (options.maximumTabWidth) {
+ li.css("maxWidth",options.maximumTabWidth+"px");
+ }
var link = $("
",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
if (tab.icon) {
$('
').appendTo(link);
+ } else if (tab.iconClass) {
+ $('
',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link);
}
var span = $('',{class:"bidiAware"}).text(tab.label).appendTo(link);
span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label));
+ if (options.collapsible) {
+ li.addClass("red-ui-tab-pinned");
+ var pinnedLink = $('');
+ if (tab.pinned) {
+ if (pinnedTabsCount === 0) {
+ pinnedLink.prependTo(collapsedButtonsRow)
+ } else {
+ pinnedLink.insertAfter(collapsedButtonsRow.find("a.red-ui-tab-link-button-pinned:last"));
+ }
+ } else {
+ pinnedLink.insertBefore(collapsedButtonsRow.find("a:last"));
+ }
+ pinnedLink.attr('id',li.attr('id')+"-link-button");
+ if (tab.iconClass) {
+ $('',{class:tab.iconClass}).appendTo(pinnedLink);
+ } else {
+ $('',{class:"fa fa-lemon-o"}).appendTo(pinnedLink);
+ }
+ pinnedLink.click(function(evt) {
+ evt.preventDefault();
+ activateTab(tab.id);
+ });
+ if (tab.pinned) {
+ pinnedLink.addClass("red-ui-tab-link-button-pinned");
+ pinnedTabsCount++;
+ }
+ RED.popover.create({
+ target:$(pinnedLink),
+ trigger: "hover",
+ size: "small",
+ direction: "bottom",
+ content: tab.name,
+ delay: { show: 550, hide: 10 }
+ });
+
+ }
link.on("click",onTabClick);
link.on("dblclick",onTabDblClick);
if (tab.closeable) {
@@ -326,6 +455,7 @@ RED.tabs = (function() {
}
})
}
+ collapsibleMenu = null;
},
removeTab: removeTab,
activateTab: activateTab,
diff --git a/editor/js/ui/projects/tab-versionControl.js b/editor/js/ui/projects/tab-versionControl.js
index 44b602019..4560a56e5 100644
--- a/editor/js/ui/projects/tab-versionControl.js
+++ b/editor/js/ui/projects/tab-versionControl.js
@@ -1003,6 +1003,8 @@ RED.sidebar.versionControl = (function() {
name: "Project History",
content: sidebarContent,
enableOnEdit: false,
+ pinned: true,
+ iconClass: "fa fa-code-fork",
onchange: function() {
setTimeout(function() {
sections.resize();
diff --git a/editor/js/ui/sidebar.js b/editor/js/ui/sidebar.js
index 222217668..d9f302885 100644
--- a/editor/js/ui/sidebar.js
+++ b/editor/js/ui/sidebar.js
@@ -35,7 +35,8 @@ RED.sidebar = (function() {
tab.onremove.call(tab);
}
},
- minimumActiveTabWidth: 70
+ // minimumActiveTabWidth: 70,
+ collapsible: true
// scrollable: true
});
@@ -59,6 +60,8 @@ RED.sidebar = (function() {
options = title;
}
+ delete options.closeable;
+
options.wrapper = $('',{style:"height:100%"}).appendTo("#sidebar-content")
options.wrapper.append(options.content);
options.wrapper.hide();
@@ -82,6 +85,8 @@ RED.sidebar = (function() {
group: "sidebar-tabs"
});
+ options.iconClass = options.iconClass || "fa fa-square-o"
+
knownTabs[options.id] = options;
if (options.visible !== false) {
diff --git a/editor/js/ui/tab-config.js b/editor/js/ui/tab-config.js
index 9a4619b28..00caea6cd 100644
--- a/editor/js/ui/tab-config.js
+++ b/editor/js/ui/tab-config.js
@@ -221,8 +221,7 @@ RED.sidebar.config = (function() {
name: RED._("sidebar.config.name"),
content: content,
toolbar: toolbar,
- closeable: true,
- visible: false,
+ iconClass: "fa fa-cog",
onchange: function() { refreshConfigNodeList(); }
});
RED.actions.add("core:show-config-tab",function() {RED.sidebar.show('config')});
diff --git a/editor/js/ui/tab-info.js b/editor/js/ui/tab-info.js
index b4cf87d46..340a6bd74 100644
--- a/editor/js/ui/tab-info.js
+++ b/editor/js/ui/tab-info.js
@@ -83,7 +83,9 @@ RED.sidebar.info = (function() {
id: "info",
label: RED._("sidebar.info.label"),
name: RED._("sidebar.info.name"),
+ iconClass: "fa fa-info",
content: content,
+ pinned: true,
enableOnEdit: true
});
if (tips.enabled()) {
diff --git a/editor/sass/popover.scss b/editor/sass/popover.scss
index d3c077e6d..691acd5c8 100644
--- a/editor/sass/popover.scss
+++ b/editor/sass/popover.scss
@@ -30,7 +30,6 @@
}
.red-ui-popover:after, .red-ui-popover:before {
- top: 50%;
border: solid transparent;
content: " ";
height: 0;
@@ -39,12 +38,18 @@
pointer-events: none;
}
.red-ui-popover.red-ui-popover-right:after, .red-ui-popover.red-ui-popover-right:before {
+ top: 50%;
right: 100%;
}
.red-ui-popover.red-ui-popover-left:after, .red-ui-popover.red-ui-popover-left:before {
+ top: 50%;
left: 100%;
}
+.red-ui-popover.red-ui-popover-bottom:after, .red-ui-popover.red-ui-popover-bottom:before {
+ bottom: 100%;
+ left: 50%;
+}
.red-ui-popover.red-ui-popover-right:after {
border-color: rgba(136, 183, 213, 0);
@@ -72,6 +77,21 @@
margin-top: -11px;
}
+
+.red-ui-popover.red-ui-popover-bottom:after {
+ border-color: rgba(136, 183, 213, 0);
+ border-bottom-color: #fff;
+ border-width: 10px;
+ margin-left: -10px;
+}
+.red-ui-popover.red-ui-popover-bottom:before {
+ border-color: rgba(194, 225, 245, 0);
+ border-bottom-color: $primary-border-color;
+ border-width: 11px;
+ margin-left: -11px;
+}
+
+
.red-ui-popover-size-small {
font-size: 11px;
padding: 5px;
@@ -93,4 +113,12 @@
border-width: 6px;
margin-top: -6px;
}
+ &.red-ui-popover-bottom:after {
+ border-width: 5px;
+ margin-left: -5px;
+ }
+ &.red-ui-popover-bottom:before {
+ border-width: 6px;
+ margin-left: -6px;
+ }
}
diff --git a/editor/sass/tabs.scss b/editor/sass/tabs.scss
index 4b2dc7f5d..488f4f3c9 100644
--- a/editor/sass/tabs.scss
+++ b/editor/sass/tabs.scss
@@ -93,7 +93,7 @@
color: $workspace-button-color-hover;
}
}
- .red-ui-tab-icon {
+ img.red-ui-tab-icon {
opacity: 0.2;
}
}
@@ -113,6 +113,21 @@
&.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px;
}
+ &.red-ui-tabs-collapsible {
+ li:not(.active) {
+ display: none;
+ &.red-ui-tab-pinned {
+ a {
+ padding-left: 0;
+ text-align: center;
+ }
+ span {
+ display: none;
+ }
+ width: 32px;
+ }
+ }
+ }
&.red-ui-tabs-vertical {
box-sizing: border-box;
@@ -157,6 +172,15 @@
}
}
}
+ .red-ui-tabs-select {
+ position: absolute;
+ top:0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ opacity: 0.4;
+ background: red;
+ }
}
.red-ui-tab-button {
position: absolute;
@@ -180,7 +204,33 @@
z-index: 2;
}
}
-
+.red-ui-tab-link-buttons {
+ position: absolute;
+ box-sizing: border-box;
+ top: 0;
+ right: 0;
+ height: 35px;
+ background: #fff;
+ border-bottom: 1px solid $primary-border-color;
+ z-index: 2;
+ a {
+ @include workspace-button;
+ line-height: 26px;
+ height: 28px;
+ width: 28px;
+ margin: 4px 3px 3px;
+ border: 1px solid $primary-border-color;
+ z-index: 2;
+ &.red-ui-tab-link-button {
+ &:not(.active) {
+ background: #eee;
+ }
+ }
+ &.red-ui-tab-link-button-menu {
+ border-color: white;
+ }
+ }
+}
.red-ui-tab-scroll {
width: 21px;
top: 0;
@@ -216,7 +266,7 @@
right: 38px;
}
-.red-ui-tab-icon {
+img.red-ui-tab-icon {
margin-left: -8px;
margin-right: 3px;
margin-top: -2px;
@@ -225,6 +275,11 @@
height: 20px;
vertical-align: middle;
}
+i.red-ui-tab-icon {
+ opacity: 0.7;
+ width: 18px;
+ height: 20px;
+}
.red-ui-tabs-badges {
position: absolute;
diff --git a/nodes/core/core/58-debug.html b/nodes/core/core/58-debug.html
index 7317d7064..95b55d7f5 100644
--- a/nodes/core/core/58-debug.html
+++ b/nodes/core/core/58-debug.html
@@ -154,7 +154,9 @@
name: this._("debug.sidebar.name"),
content: uiComponents.content,
toolbar: uiComponents.footer,
- enableOnEdit: true
+ enableOnEdit: true,
+ pinned: true,
+ iconClass: "fa fa-wrench"
});
RED.actions.add("core:show-debug-tab",function() { RED.sidebar.show('debug'); });
From 26bc142cc25b03df42759b4bc3d8fe342911726c Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Wed, 23 May 2018 10:59:08 +0100
Subject: [PATCH 9/9] Handle loading empty nodesDir
---
red/runtime/nodes/registry/localfilesystem.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/red/runtime/nodes/registry/localfilesystem.js b/red/runtime/nodes/registry/localfilesystem.js
index b8a516597..b591245d5 100644
--- a/red/runtime/nodes/registry/localfilesystem.js
+++ b/red/runtime/nodes/registry/localfilesystem.js
@@ -88,7 +88,7 @@ function getLocalNodeFiles(dir) {
try {
files = fs.readdirSync(dir);
} catch(err) {
- return result;
+ return {files: [], icons: []};
}
files.sort();
files.forEach(function(fn) {