mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
allow a node's icon to be set dynamically (#1490)
* create a proto type * Fixed some problems after reviewing
This commit is contained in:
parent
cc88ebd2b9
commit
6d2389945b
@ -24,7 +24,25 @@
|
|||||||
url: 'nodes',
|
url: 'nodes',
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
RED.nodes.setNodeList(data);
|
RED.nodes.setNodeList(data);
|
||||||
RED.i18n.loadNodeCatalogs(loadNodes);
|
RED.i18n.loadNodeCatalogs(function() {
|
||||||
|
loadIconList(loadNodes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadIconList(done) {
|
||||||
|
$.ajax({
|
||||||
|
headers: {
|
||||||
|
"Accept":"application/json"
|
||||||
|
},
|
||||||
|
cache: false,
|
||||||
|
url: 'icons',
|
||||||
|
success: function(data) {
|
||||||
|
RED.nodes.setIconSets(data);
|
||||||
|
if (done) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -122,6 +140,7 @@
|
|||||||
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
||||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||||
}
|
}
|
||||||
|
loadIconList();
|
||||||
} else if (topic == "notification/node/removed") {
|
} else if (topic == "notification/node/removed") {
|
||||||
for (i=0;i<msg.length;i++) {
|
for (i=0;i<msg.length;i++) {
|
||||||
m = msg[i];
|
m = msg[i];
|
||||||
@ -131,6 +150,7 @@
|
|||||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadIconList();
|
||||||
} else if (topic == "notification/node/enabled") {
|
} else if (topic == "notification/node/enabled") {
|
||||||
if (msg.types) {
|
if (msg.types) {
|
||||||
info = RED.nodes.getNodeSet(msg.id);
|
info = RED.nodes.getNodeSet(msg.id);
|
||||||
|
@ -40,6 +40,7 @@ RED.nodes = (function() {
|
|||||||
var nodeSets = {};
|
var nodeSets = {};
|
||||||
var typeToId = {};
|
var typeToId = {};
|
||||||
var nodeDefinitions = {};
|
var nodeDefinitions = {};
|
||||||
|
var iconSets = {};
|
||||||
|
|
||||||
nodeDefinitions['tab'] = {
|
nodeDefinitions['tab'] = {
|
||||||
defaults: {
|
defaults: {
|
||||||
@ -170,6 +171,12 @@ RED.nodes = (function() {
|
|||||||
},
|
},
|
||||||
getNodeType: function(nt) {
|
getNodeType: function(nt) {
|
||||||
return nodeDefinitions[nt];
|
return nodeDefinitions[nt];
|
||||||
|
},
|
||||||
|
setIconSets: function(sets) {
|
||||||
|
iconSets = sets;
|
||||||
|
},
|
||||||
|
getIconSets: function() {
|
||||||
|
return iconSets;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return exports;
|
return exports;
|
||||||
@ -485,6 +492,12 @@ RED.nodes = (function() {
|
|||||||
if (n.outputs > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
|
if (n.outputs > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
|
||||||
node.outputLabels = n.outputLabels.slice();
|
node.outputLabels = n.outputLabels.slice();
|
||||||
}
|
}
|
||||||
|
if (n.icon) {
|
||||||
|
var defIcon = RED.utils.getDefaultNodeIcon(n._def, n);
|
||||||
|
if (n.icon !== defIcon.module+"/"+defIcon.file) {
|
||||||
|
node.icon = n.icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@ -915,6 +928,7 @@ RED.nodes = (function() {
|
|||||||
wires:n.wires,
|
wires:n.wires,
|
||||||
inputLabels: n.inputLabels,
|
inputLabels: n.inputLabels,
|
||||||
outputLabels: n.outputLabels,
|
outputLabels: n.outputLabels,
|
||||||
|
icon: n.icon,
|
||||||
changed:false,
|
changed:false,
|
||||||
_config:{}
|
_config:{}
|
||||||
};
|
};
|
||||||
@ -1272,6 +1286,9 @@ RED.nodes = (function() {
|
|||||||
enableNodeSet: registry.enableNodeSet,
|
enableNodeSet: registry.enableNodeSet,
|
||||||
disableNodeSet: registry.disableNodeSet,
|
disableNodeSet: registry.disableNodeSet,
|
||||||
|
|
||||||
|
setIconSets: registry.setIconSets,
|
||||||
|
getIconSets: registry.getIconSets,
|
||||||
|
|
||||||
registerType: registry.registerNodeType,
|
registerType: registry.registerNodeType,
|
||||||
getType: registry.getNodeType,
|
getType: registry.getNodeType,
|
||||||
convertNode: convertNode,
|
convertNode: convertNode,
|
||||||
|
@ -108,6 +108,14 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node.icon) {
|
||||||
|
var iconPath = RED.utils.separateIconPath(node.icon);
|
||||||
|
var iconSets = RED.nodes.getIconSets();
|
||||||
|
var iconFileList = iconSets[iconPath.module];
|
||||||
|
if (!iconFileList || iconFileList.indexOf(iconPath.file) === -1) {
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return isValid;
|
return isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +167,23 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (node.icon) {
|
||||||
|
var iconPath = RED.utils.separateIconPath(node.icon);
|
||||||
|
var iconSets = RED.nodes.getIconSets();
|
||||||
|
var iconFileList = iconSets[iconPath.module];
|
||||||
|
var iconModule = $("#node-settings-icon-module");
|
||||||
|
var iconFile = $("#node-settings-icon-file");
|
||||||
|
if (!iconFileList) {
|
||||||
|
iconModule.addClass("input-error");
|
||||||
|
iconFile.removeClass("input-error");
|
||||||
|
} else if (iconFileList.indexOf(iconPath.file) === -1) {
|
||||||
|
iconModule.removeClass("input-error");
|
||||||
|
iconFile.addClass("input-error");
|
||||||
|
} else {
|
||||||
|
iconModule.removeClass("input-error");
|
||||||
|
iconFile.removeClass("input-error");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function validateNodeEditorProperty(node,defaults,property,prefix) {
|
function validateNodeEditorProperty(node,defaults,property,prefix) {
|
||||||
var input = $("#"+prefix+"-"+property);
|
var input = $("#"+prefix+"-"+property);
|
||||||
@ -710,10 +735,76 @@ RED.editor = (function() {
|
|||||||
} else {
|
} else {
|
||||||
buildLabelRow().appendTo(outputsDiv);
|
buildLabelRow().appendTo(outputsDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('<div class="form-row"><div id="node-settings-icon"></div></div>').appendTo(dialogForm);
|
||||||
|
var iconDiv = $("#node-settings-icon");
|
||||||
|
$('<label data-i18n="editor.settingIcon">').appendTo(iconDiv);
|
||||||
|
var iconForm = $('<div>',{class:"node-label-form-row"});
|
||||||
|
iconForm.appendTo(iconDiv);
|
||||||
|
$('<label>').appendTo(iconForm);
|
||||||
|
|
||||||
|
var selectIconModule = $('<select id="node-settings-icon-module"><option value=""></option></select>').appendTo(iconForm);
|
||||||
|
var iconPath;
|
||||||
|
if (node.icon) {
|
||||||
|
iconPath = RED.utils.separateIconPath(node.icon);
|
||||||
|
} else {
|
||||||
|
iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
|
||||||
|
}
|
||||||
|
var iconSets = RED.nodes.getIconSets();
|
||||||
|
Object.keys(iconSets).forEach(function(moduleName) {
|
||||||
|
selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
|
||||||
|
});
|
||||||
|
if (iconPath.module && !iconSets[iconPath.module]) {
|
||||||
|
selectIconModule.append($("<option disabled></option>").val(iconPath.module).text(iconPath.module));
|
||||||
|
}
|
||||||
|
selectIconModule.val(iconPath.module);
|
||||||
|
var iconModuleHidden = $('<input type="hidden" id="node-settings-icon-module-hidden"></input>').appendTo(iconForm);
|
||||||
|
iconModuleHidden.val(iconPath.module);
|
||||||
|
|
||||||
|
var selectIconFile = $('<select id="node-settings-icon-file"><option value=""></option></select>').appendTo(iconForm);
|
||||||
|
selectIconModule.change(function() {
|
||||||
|
moduleChange(selectIconModule, selectIconFile, iconModuleHidden, iconFileHidden, iconSets, true);
|
||||||
|
});
|
||||||
|
var iconFileHidden = $('<input type="hidden" id="node-settings-icon-file-hidden"></input>').appendTo(iconForm);
|
||||||
|
iconFileHidden.val(iconPath.file);
|
||||||
|
selectIconFile.change(function() {
|
||||||
|
selectIconFile.removeClass("input-error");
|
||||||
|
var fileName = selectIconFile.val();
|
||||||
|
iconFileHidden.val(fileName);
|
||||||
|
});
|
||||||
|
|
||||||
|
moduleChange(selectIconModule, selectIconFile, iconModuleHidden, iconFileHidden, iconSets, false);
|
||||||
|
var iconFileList = iconSets[selectIconModule.val()];
|
||||||
|
if (!iconFileList || iconFileList.indexOf(iconPath.file) === -1) {
|
||||||
|
selectIconFile.append($("<option disabled></option>").val(iconPath.file).text(iconPath.file));
|
||||||
|
}
|
||||||
|
selectIconFile.val(iconPath.file);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moduleChange(selectIconModule, selectIconFile, iconModuleHidden, iconFileHidden, iconSets, updateIconFile) {
|
||||||
|
selectIconFile.children().remove();
|
||||||
|
var moduleName = selectIconModule.val();
|
||||||
|
if (moduleName !== null) {
|
||||||
|
iconModuleHidden.val(moduleName);
|
||||||
|
}
|
||||||
|
var iconFileList = iconSets[moduleName];
|
||||||
|
if (iconFileList) {
|
||||||
|
iconFileList.forEach(function(fileName) {
|
||||||
|
if (updateIconFile) {
|
||||||
|
updateIconFile = false;
|
||||||
|
iconFileHidden.val(fileName);
|
||||||
|
}
|
||||||
|
selectIconFile.append($("<option></option>").val(fileName).text(fileName));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
selectIconFile.prop("disabled", !iconFileList);
|
||||||
|
selectIconModule.removeClass("input-error");
|
||||||
}
|
}
|
||||||
|
|
||||||
function showEditDialog(node) {
|
function showEditDialog(node) {
|
||||||
var editing_node = node;
|
var editing_node = node;
|
||||||
|
var isDefaultIcon;
|
||||||
|
var defaultIcon;
|
||||||
editStack.push(node);
|
editStack.push(node);
|
||||||
RED.view.state(RED.state.EDITING);
|
RED.view.state(RED.state.EDITING);
|
||||||
var type = node.type;
|
var type = node.type;
|
||||||
@ -960,6 +1051,31 @@ RED.editor = (function() {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var iconModule = $("#node-settings-icon-module-hidden").val();
|
||||||
|
var iconFile = $("#node-settings-icon-file-hidden").val();
|
||||||
|
var icon = (iconModule && iconFile) ? iconModule+"/"+iconFile : "";
|
||||||
|
if (!isDefaultIcon) {
|
||||||
|
if (icon !== editing_node.icon) {
|
||||||
|
changes.icon = editing_node.icon;
|
||||||
|
editing_node.icon = icon;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (icon !== defaultIcon) {
|
||||||
|
changes.icon = editing_node.icon;
|
||||||
|
editing_node.icon = icon;
|
||||||
|
changed = true;
|
||||||
|
} else {
|
||||||
|
var iconPath = RED.utils.getDefaultNodeIcon(editing_node._def, editing_node);
|
||||||
|
var currentDefaultIcon = iconPath.module+"/"+iconPath.file;
|
||||||
|
if (defaultIcon !== currentDefaultIcon) {
|
||||||
|
changes.icon = editing_node.icon;
|
||||||
|
editing_node.icon = currentDefaultIcon;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
var wasChanged = editing_node.changed;
|
var wasChanged = editing_node.changed;
|
||||||
editing_node.changed = true;
|
editing_node.changed = true;
|
||||||
@ -1051,6 +1167,13 @@ RED.editor = (function() {
|
|||||||
} else {
|
} else {
|
||||||
ns = node._def.set.id;
|
ns = node._def.set.id;
|
||||||
}
|
}
|
||||||
|
var iconPath = RED.utils.getDefaultNodeIcon(node._def,node);
|
||||||
|
defaultIcon = iconPath.module+"/"+iconPath.file;
|
||||||
|
if (node.icon && node.icon !== defaultIcon) {
|
||||||
|
isDefaultIcon = false;
|
||||||
|
} else {
|
||||||
|
isDefaultIcon = true;
|
||||||
|
}
|
||||||
buildEditForm(nodeProperties.content,"dialog-form",type,ns);
|
buildEditForm(nodeProperties.content,"dialog-form",type,ns);
|
||||||
buildLabelForm(portLabels.content,node);
|
buildLabelForm(portLabels.content,node);
|
||||||
|
|
||||||
|
@ -689,16 +689,21 @@ RED.utils = (function() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeIcon(def,node) {
|
function separateIconPath(icon) {
|
||||||
if (def.category === 'config') {
|
var result = {module: "", file: ""};
|
||||||
return "icons/node-red/cog.png"
|
if (icon) {
|
||||||
} else if (node && node.type === 'tab') {
|
var index = icon.indexOf('/');
|
||||||
return "icons/node-red/subflow.png"
|
if (index !== -1) {
|
||||||
} else if (node && node.type === 'unknown') {
|
result.module = icon.slice(0, index);
|
||||||
return "icons/node-red/alert.png"
|
result.file = icon.slice(index + 1);
|
||||||
} else if (node && node.type === 'subflow') {
|
} else {
|
||||||
return "icons/node-red/subflow.png"
|
result.file = icon;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultNodeIcon(def,node) {
|
||||||
var icon_url;
|
var icon_url;
|
||||||
if (typeof def.icon === "function") {
|
if (typeof def.icon === "function") {
|
||||||
try {
|
try {
|
||||||
@ -710,7 +715,34 @@ RED.utils = (function() {
|
|||||||
} else {
|
} else {
|
||||||
icon_url = def.icon;
|
icon_url = def.icon;
|
||||||
}
|
}
|
||||||
return "icons/"+def.set.module+"/"+icon_url;
|
|
||||||
|
var iconPath = separateIconPath(icon_url);
|
||||||
|
if (!iconPath.module) {
|
||||||
|
iconPath.module = def.set.module;
|
||||||
|
}
|
||||||
|
return iconPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeIcon(def,node) {
|
||||||
|
if (def.category === 'config') {
|
||||||
|
return "icons/node-red/cog.png"
|
||||||
|
} else if (node && node.type === 'tab') {
|
||||||
|
return "icons/node-red/subflow.png"
|
||||||
|
} else if (node && node.type === 'unknown') {
|
||||||
|
return "icons/node-red/alert.png"
|
||||||
|
} else if (node && node.type === 'subflow') {
|
||||||
|
return "icons/node-red/subflow.png"
|
||||||
|
} else if (node && node.icon) {
|
||||||
|
var iconPath = separateIconPath(node.icon);
|
||||||
|
var iconSets = RED.nodes.getIconSets();
|
||||||
|
var iconFileList = iconSets[iconPath.module];
|
||||||
|
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||||
|
return "icons/" + node.icon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var iconPath = getDefaultNodeIcon(def, node);
|
||||||
|
return "icons/"+iconPath.module+"/"+iconPath.file;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeLabel(node,defaultLabel) {
|
function getNodeLabel(node,defaultLabel) {
|
||||||
@ -735,6 +767,8 @@ RED.utils = (function() {
|
|||||||
getMessageProperty: getMessageProperty,
|
getMessageProperty: getMessageProperty,
|
||||||
normalisePropertyExpression: normalisePropertyExpression,
|
normalisePropertyExpression: normalisePropertyExpression,
|
||||||
validatePropertyExpression: validatePropertyExpression,
|
validatePropertyExpression: validatePropertyExpression,
|
||||||
|
separateIconPath: separateIconPath,
|
||||||
|
getDefaultNodeIcon: getDefaultNodeIcon,
|
||||||
getNodeIcon: getNodeIcon,
|
getNodeIcon: getNodeIcon,
|
||||||
getNodeLabel: getNodeLabel,
|
getNodeLabel: getNodeLabel,
|
||||||
}
|
}
|
||||||
|
@ -320,6 +320,13 @@
|
|||||||
input {
|
input {
|
||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
}
|
}
|
||||||
|
#node-settings-icon-module {
|
||||||
|
width: calc(55% - 50px);
|
||||||
|
}
|
||||||
|
#node-settings-icon-file {
|
||||||
|
width: calc(45% - 55px);
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.node-label-form-none {
|
.node-label-form-none {
|
||||||
span {
|
span {
|
||||||
|
@ -94,6 +94,7 @@ function init(_server,_runtime) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);
|
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);
|
||||||
|
editorApp.get("/icons",needsPermission("nodes.read"),nodes.getIcons,errorHandler);
|
||||||
editorApp.get("/icons/:module/:icon",ui.icon);
|
editorApp.get("/icons/:module/:icon",ui.icon);
|
||||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||||
theme.init(runtime);
|
theme.init(runtime);
|
||||||
|
@ -210,9 +210,10 @@
|
|||||||
"editConfig": "Edit __type__ config node",
|
"editConfig": "Edit __type__ config node",
|
||||||
"addNewType": "Add new __type__...",
|
"addNewType": "Add new __type__...",
|
||||||
"nodeProperties": "node properties",
|
"nodeProperties": "node properties",
|
||||||
"portLabels": "port labels",
|
"portLabels": "node settings",
|
||||||
"labelInputs": "Inputs",
|
"labelInputs": "Inputs",
|
||||||
"labelOutputs": "Outputs",
|
"labelOutputs": "Outputs",
|
||||||
|
"settingIcon": "Icon",
|
||||||
"noDefaultLabel": "none",
|
"noDefaultLabel": "none",
|
||||||
"defaultLabel": "use default label",
|
"defaultLabel": "use default label",
|
||||||
"errors": {
|
"errors": {
|
||||||
|
@ -208,9 +208,10 @@
|
|||||||
"editConfig": "__type__ ノードの設定を編集",
|
"editConfig": "__type__ ノードの設定を編集",
|
||||||
"addNewType": "新規に __type__ を追加...",
|
"addNewType": "新規に __type__ を追加...",
|
||||||
"nodeProperties": "プロパティ",
|
"nodeProperties": "プロパティ",
|
||||||
"portLabels": "端子名",
|
"portLabels": "設定",
|
||||||
"labelInputs": "入力",
|
"labelInputs": "入力",
|
||||||
"labelOutputs": "出力",
|
"labelOutputs": "出力",
|
||||||
|
"settingIcon": "アイコン",
|
||||||
"noDefaultLabel": "なし",
|
"noDefaultLabel": "なし",
|
||||||
"defaultLabel": "既定の名前を使用",
|
"defaultLabel": "既定の名前を使用",
|
||||||
"errors": {
|
"errors": {
|
||||||
|
@ -229,6 +229,11 @@ module.exports = {
|
|||||||
log.audit({event: "nodes.module.set",module:mod,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
|
log.audit({event: "nodes.module.set",module:mod,enabled:body.enabled,error:err.code||"unexpected_error",message:err.toString()},req);
|
||||||
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
res.status(400).json({error:err.code||"unexpected_error", message:err.toString()});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getIcons: function(req,res) {
|
||||||
|
log.audit({event: "nodes.icons.get"},req);
|
||||||
|
res.json(redNodes.getNodeIcons());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ module.exports = {
|
|||||||
getNodeConfigs: registry.getNodeConfigs,
|
getNodeConfigs: registry.getNodeConfigs,
|
||||||
getNodeConfig: registry.getNodeConfig,
|
getNodeConfig: registry.getNodeConfig,
|
||||||
getNodeIconPath: registry.getNodeIconPath,
|
getNodeIconPath: registry.getNodeIconPath,
|
||||||
|
getNodeIcons: registry.getNodeIcons,
|
||||||
getNodeExampleFlows: library.getExampleFlows,
|
getNodeExampleFlows: library.getExampleFlows,
|
||||||
getNodeExampleFlowPath: library.getExampleFlowPath,
|
getNodeExampleFlowPath: library.getExampleFlowPath,
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ module.exports = {
|
|||||||
getNodeConfigs: registry.getAllNodeConfigs,
|
getNodeConfigs: registry.getAllNodeConfigs,
|
||||||
getNodeConfig: registry.getNodeConfig,
|
getNodeConfig: registry.getNodeConfig,
|
||||||
getNodeIconPath: registry.getNodeIconPath,
|
getNodeIconPath: registry.getNodeIconPath,
|
||||||
|
getNodeIcons: registry.getNodeIcons,
|
||||||
|
|
||||||
enableNode: enableNodeSet,
|
enableNode: enableNodeSet,
|
||||||
disableNode: registry.disableNodeSet,
|
disableNode: registry.disableNodeSet,
|
||||||
|
@ -24,6 +24,7 @@ var i18n;
|
|||||||
|
|
||||||
var settings;
|
var settings;
|
||||||
var disableNodePathScan = false;
|
var disableNodePathScan = false;
|
||||||
|
var iconFileExtensions = [".png", ".gif"];
|
||||||
|
|
||||||
function init(runtime) {
|
function init(runtime) {
|
||||||
settings = runtime.settings;
|
settings = runtime.settings;
|
||||||
@ -104,7 +105,8 @@ function getLocalNodeFiles(dir) {
|
|||||||
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
|
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
|
||||||
result = result.concat(getLocalNodeFiles(path.join(dir,fn)));
|
result = result.concat(getLocalNodeFiles(path.join(dir,fn)));
|
||||||
} else if (fn === "icons") {
|
} else if (fn === "icons") {
|
||||||
events.emit("node-icon-dir",{name:'node-red',path:path.join(dir,fn)});
|
var iconList = scanIconDir(path.join(dir,fn));
|
||||||
|
events.emit("node-icon-dir",{name:'node-red',path:path.join(dir,fn),icons:iconList});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -197,7 +199,8 @@ function getModuleNodeFiles(module) {
|
|||||||
if (iconDirs.indexOf(iconDir) == -1) {
|
if (iconDirs.indexOf(iconDir) == -1) {
|
||||||
try {
|
try {
|
||||||
fs.statSync(iconDir);
|
fs.statSync(iconDir);
|
||||||
events.emit("node-icon-dir",{name:pkg.name,path:iconDir});
|
var iconList = scanIconDir(iconDir);
|
||||||
|
events.emit("node-icon-dir",{name:pkg.name,path:iconDir,icons:iconList});
|
||||||
iconDirs.push(iconDir);
|
iconDirs.push(iconDir);
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
}
|
}
|
||||||
@ -218,6 +221,10 @@ function getNodeFiles(disableNodePathScan) {
|
|||||||
// Find all of the nodes to load
|
// Find all of the nodes to load
|
||||||
var nodeFiles = [];
|
var nodeFiles = [];
|
||||||
|
|
||||||
|
var dir = path.resolve(__dirname + '/../../../../public/icons');
|
||||||
|
var iconList = scanIconDir(dir);
|
||||||
|
events.emit("node-icon-dir",{name:'node-red',path:dir,icons:iconList});
|
||||||
|
|
||||||
if (settings.coreNodesDir) {
|
if (settings.coreNodesDir) {
|
||||||
nodeFiles = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
|
nodeFiles = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
|
||||||
var defaultLocalesPath = path.join(settings.coreNodesDir,"core","locales");
|
var defaultLocalesPath = path.join(settings.coreNodesDir,"core","locales");
|
||||||
@ -302,6 +309,20 @@ function getModuleFiles(module) {
|
|||||||
return nodeList;
|
return nodeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function scanIconDir(dir) {
|
||||||
|
var iconList = [];
|
||||||
|
try {
|
||||||
|
var files = fs.readdirSync(dir);
|
||||||
|
files.forEach(function(file) {
|
||||||
|
var stats = fs.statSync(path.join(dir, file));
|
||||||
|
if (stats.isFile() && iconFileExtensions.indexOf(path.extname(file)) !== -1) {
|
||||||
|
iconList.push(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
return iconList;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
init: init,
|
init: init,
|
||||||
|
@ -579,6 +579,25 @@ var defaultIcon = path.resolve(__dirname + '/../../../../public/icons/arrow-in.p
|
|||||||
function nodeIconDir(dir) {
|
function nodeIconDir(dir) {
|
||||||
icon_paths[dir.name] = icon_paths[dir.name] || [];
|
icon_paths[dir.name] = icon_paths[dir.name] || [];
|
||||||
icon_paths[dir.name].push(path.resolve(dir.path));
|
icon_paths[dir.name].push(path.resolve(dir.path));
|
||||||
|
|
||||||
|
if (dir.icons) {
|
||||||
|
if (!moduleConfigs[dir.name]) {
|
||||||
|
moduleConfigs[dir.name] = {
|
||||||
|
name: dir.name,
|
||||||
|
nodes: {},
|
||||||
|
icons: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var module = moduleConfigs[dir.name];
|
||||||
|
if (module.icons === undefined) {
|
||||||
|
module.icons = [];
|
||||||
|
}
|
||||||
|
dir.icons.forEach(function(icon) {
|
||||||
|
if (module.icons.indexOf(icon) === -1) {
|
||||||
|
module.icons.push(icon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeIconPath(module,icon) {
|
function getNodeIconPath(module,icon) {
|
||||||
@ -607,6 +626,20 @@ function getNodeIconPath(module,icon) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getNodeIcons() {
|
||||||
|
var iconList = {};
|
||||||
|
|
||||||
|
for (var module in moduleConfigs) {
|
||||||
|
if (moduleConfigs.hasOwnProperty(module)) {
|
||||||
|
if (moduleConfigs[module].icons) {
|
||||||
|
iconList[module] = moduleConfigs[module].icons;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return iconList;
|
||||||
|
}
|
||||||
|
|
||||||
var registry = module.exports = {
|
var registry = module.exports = {
|
||||||
init: init,
|
init: init,
|
||||||
load: load,
|
load: load,
|
||||||
@ -629,6 +662,7 @@ var registry = module.exports = {
|
|||||||
getModuleInfo: getModuleInfo,
|
getModuleInfo: getModuleInfo,
|
||||||
|
|
||||||
getNodeIconPath: getNodeIconPath,
|
getNodeIconPath: getNodeIconPath,
|
||||||
|
getNodeIcons: getNodeIcons,
|
||||||
/**
|
/**
|
||||||
* Gets all of the node template configs
|
* Gets all of the node template configs
|
||||||
* @return all of the node templates in a single string
|
* @return all of the node templates in a single string
|
||||||
|
@ -50,6 +50,7 @@ describe("nodes api", function() {
|
|||||||
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
|
app.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.getSet);
|
||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,nodes.putModule);
|
||||||
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
app.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,nodes.putSet);
|
||||||
|
app.get("/getIcons",nodes.getIcons);
|
||||||
app.delete("/nodes/:id",nodes.delete);
|
app.delete("/nodes/:id",nodes.delete);
|
||||||
sinon.stub(locales,"determineLangFromHeaders", function() {
|
sinon.stub(locales,"determineLangFromHeaders", function() {
|
||||||
return "en-US";
|
return "en-US";
|
||||||
@ -808,5 +809,29 @@ describe("nodes api", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('get icons', function() {
|
||||||
|
it('returns icon list', function(done) {
|
||||||
|
debugger;
|
||||||
|
initNodes({
|
||||||
|
nodes:{
|
||||||
|
getNodeIcons: function() {
|
||||||
|
return {"module":["1.png","2.png","3.png"]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
request(app)
|
||||||
|
.get('/getIcons')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
console.log(res.body);
|
||||||
|
res.body.should.have.property("module");
|
||||||
|
res.body.module.should.be.an.Array();
|
||||||
|
res.body.module.should.have.lengthOf(3);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -150,7 +150,22 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
});
|
});
|
||||||
it.skip("finds locales directory");
|
it.skip("finds locales directory");
|
||||||
it.skip("finds icon path directory");
|
it.skip("finds icon path directory");
|
||||||
|
it("scans icon files in the resources tree",function(done) {
|
||||||
|
var count = 0;
|
||||||
|
localfilesystem.init({
|
||||||
|
i18n:{registerMessageCatalog:function(){}},
|
||||||
|
events:{emit:function(eventName,dir){
|
||||||
|
eventName.should.equal("node-icon-dir");
|
||||||
|
dir.name.should.equal("node-red");
|
||||||
|
dir.icons.should.be.an.Array();
|
||||||
|
if (count++ === 1) {
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
}},
|
||||||
|
settings:{coreNodesDir:resourcesDir}
|
||||||
|
});
|
||||||
|
localfilesystem.getNodeFiles(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe("#getModuleFiles",function() {
|
describe("#getModuleFiles",function() {
|
||||||
it("gets a nodes module files",function(done) {
|
it("gets a nodes module files",function(done) {
|
||||||
@ -196,5 +211,27 @@ describe("red/nodes/registry/localfilesystem",function() {
|
|||||||
});
|
});
|
||||||
it.skip("finds locales directory");
|
it.skip("finds locales directory");
|
||||||
it.skip("finds icon path directory");
|
it.skip("finds icon path directory");
|
||||||
|
it("scans icon files with a module file",function(done) {
|
||||||
|
var _join = path.join;
|
||||||
|
stubs.push(sinon.stub(path,"join",function() {
|
||||||
|
if (arguments[0] == resourcesDir) {
|
||||||
|
// This stops the module tree scan from going any higher
|
||||||
|
// up the tree than resourcesDir.
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
return _join.apply(null,arguments);
|
||||||
|
}));
|
||||||
|
localfilesystem.init({
|
||||||
|
i18n:{registerMessageCatalog:function(){}},
|
||||||
|
events:{emit:function(eventName,dir){
|
||||||
|
eventName.should.equal("node-icon-dir");
|
||||||
|
dir.name.should.equal("TestNodeModule");
|
||||||
|
dir.icons.should.be.an.Array();
|
||||||
|
done();
|
||||||
|
}},
|
||||||
|
settings:{coreNodesDir:moduleDir}
|
||||||
|
});
|
||||||
|
var nodeModule = localfilesystem.getModuleFiles('TestNodeModule');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -493,7 +493,7 @@ describe("red/nodes/registry/registry",function() {
|
|||||||
|
|
||||||
it('returns a registered icon' , function() {
|
it('returns a registered icon' , function() {
|
||||||
var testIcon = path.resolve(__dirname+'/../../../../resources/icons/test_icon.png');
|
var testIcon = path.resolve(__dirname+'/../../../../resources/icons/test_icon.png');
|
||||||
events.emit("node-icon-dir",{name:"test-module", path: path.resolve(__dirname+'/../../../../resources/icons')});
|
events.emit("node-icon-dir",{name:"test-module", path: path.resolve(__dirname+'/../../../../resources/icons'), icons:[]});
|
||||||
var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
|
var iconPath = typeRegistry.getNodeIconPath('test-module','test_icon.png');
|
||||||
iconPath.should.eql(testIcon);
|
iconPath.should.eql(testIcon);
|
||||||
});
|
});
|
||||||
@ -505,4 +505,24 @@ describe("red/nodes/registry/registry",function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#getNodeIcons', function() {
|
||||||
|
it('returns empty icon list when no modules are registered', function() {
|
||||||
|
var iconList = typeRegistry.getNodeIcons();
|
||||||
|
iconList.should.eql({});
|
||||||
|
});
|
||||||
|
|
||||||
|
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 iconList = typeRegistry.getNodeIcons();
|
||||||
|
iconList.should.eql({"test-module":["test_icon1.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"]});
|
||||||
|
var iconList = typeRegistry.getNodeIcons();
|
||||||
|
iconList.should.eql({"test-module":["test_icon1.png","test_icon2.png"]});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user