mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00: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:
committed by
Nick O'Leary
parent
cc88ebd2b9
commit
6d2389945b
@@ -24,7 +24,25 @@
|
||||
url: 'nodes',
|
||||
success: function(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>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||
}
|
||||
loadIconList();
|
||||
} else if (topic == "notification/node/removed") {
|
||||
for (i=0;i<msg.length;i++) {
|
||||
m = msg[i];
|
||||
@@ -131,6 +150,7 @@
|
||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
loadIconList();
|
||||
} else if (topic == "notification/node/enabled") {
|
||||
if (msg.types) {
|
||||
info = RED.nodes.getNodeSet(msg.id);
|
||||
|
@@ -40,6 +40,7 @@ RED.nodes = (function() {
|
||||
var nodeSets = {};
|
||||
var typeToId = {};
|
||||
var nodeDefinitions = {};
|
||||
var iconSets = {};
|
||||
|
||||
nodeDefinitions['tab'] = {
|
||||
defaults: {
|
||||
@@ -170,6 +171,12 @@ RED.nodes = (function() {
|
||||
},
|
||||
getNodeType: function(nt) {
|
||||
return nodeDefinitions[nt];
|
||||
},
|
||||
setIconSets: function(sets) {
|
||||
iconSets = sets;
|
||||
},
|
||||
getIconSets: function() {
|
||||
return iconSets;
|
||||
}
|
||||
};
|
||||
return exports;
|
||||
@@ -485,6 +492,12 @@ RED.nodes = (function() {
|
||||
if (n.outputs > 0 && n.outputLabels && !/^\s*$/.test(n.outputLabels.join(""))) {
|
||||
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;
|
||||
}
|
||||
@@ -915,6 +928,7 @@ RED.nodes = (function() {
|
||||
wires:n.wires,
|
||||
inputLabels: n.inputLabels,
|
||||
outputLabels: n.outputLabels,
|
||||
icon: n.icon,
|
||||
changed:false,
|
||||
_config:{}
|
||||
};
|
||||
@@ -1272,6 +1286,9 @@ RED.nodes = (function() {
|
||||
enableNodeSet: registry.enableNodeSet,
|
||||
disableNodeSet: registry.disableNodeSet,
|
||||
|
||||
setIconSets: registry.setIconSets,
|
||||
getIconSets: registry.getIconSets,
|
||||
|
||||
registerType: registry.registerNodeType,
|
||||
getType: registry.getNodeType,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
var input = $("#"+prefix+"-"+property);
|
||||
@@ -710,10 +735,76 @@ RED.editor = (function() {
|
||||
} else {
|
||||
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) {
|
||||
var editing_node = node;
|
||||
var isDefaultIcon;
|
||||
var defaultIcon;
|
||||
editStack.push(node);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var type = node.type;
|
||||
@@ -960,6 +1051,31 @@ RED.editor = (function() {
|
||||
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) {
|
||||
var wasChanged = editing_node.changed;
|
||||
editing_node.changed = true;
|
||||
@@ -1051,6 +1167,13 @@ RED.editor = (function() {
|
||||
} else {
|
||||
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);
|
||||
buildLabelForm(portLabels.content,node);
|
||||
|
||||
|
@@ -689,16 +689,21 @@ RED.utils = (function() {
|
||||
return result;
|
||||
}
|
||||
|
||||
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"
|
||||
function separateIconPath(icon) {
|
||||
var result = {module: "", file: ""};
|
||||
if (icon) {
|
||||
var index = icon.indexOf('/');
|
||||
if (index !== -1) {
|
||||
result.module = icon.slice(0, index);
|
||||
result.file = icon.slice(index + 1);
|
||||
} else {
|
||||
result.file = icon;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDefaultNodeIcon(def,node) {
|
||||
var icon_url;
|
||||
if (typeof def.icon === "function") {
|
||||
try {
|
||||
@@ -710,7 +715,34 @@ RED.utils = (function() {
|
||||
} else {
|
||||
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) {
|
||||
@@ -735,6 +767,8 @@ RED.utils = (function() {
|
||||
getMessageProperty: getMessageProperty,
|
||||
normalisePropertyExpression: normalisePropertyExpression,
|
||||
validatePropertyExpression: validatePropertyExpression,
|
||||
separateIconPath: separateIconPath,
|
||||
getDefaultNodeIcon: getDefaultNodeIcon,
|
||||
getNodeIcon: getNodeIcon,
|
||||
getNodeLabel: getNodeLabel,
|
||||
}
|
||||
|
@@ -320,6 +320,13 @@
|
||||
input {
|
||||
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 {
|
||||
span {
|
||||
|
Reference in New Issue
Block a user