Move palette editor to left hand side

This commit is contained in:
Nick O'Leary 2016-08-04 16:49:36 +01:00
parent da818cf420
commit 7220af3ef0
18 changed files with 657 additions and 61 deletions

View File

@ -119,7 +119,7 @@ module.exports = function(grunt) {
"editor/js/ui/palette.js",
"editor/js/ui/tab-info.js",
"editor/js/ui/tab-config.js",
"editor/js/ui/tab-palette.js",
"editor/js/ui/palette-editor.js",
"editor/js/ui/editor.js",
"editor/js/ui/tray.js",
"editor/js/ui/clipboard.js",

View File

@ -56,11 +56,9 @@ var RED = (function() {
success: function(data) {
$("body").append(data);
$("body").i18n();
$(".palette-spinner").hide();
$(".palette-scroll").show();
$("#palette-search").show();
$(".palette-scroll").removeClass("hide");
$("#palette-search").removeClass("hide");
loadFlows();
}
});

View File

@ -32,12 +32,22 @@ RED.nodes = (function() {
}
var registry = (function() {
var moduleList = {};
var nodeList = [];
var nodeSets = {};
var typeToId = {};
var nodeDefinitions = {};
var exports = {
getModule: function(module) {
return moduleList[module];
},
getNodeSetForType: function(nodeType) {
return exports.getNodeSet(typeToId[nodeType]);
},
getModuleList: function() {
return moduleList;
},
getNodeList: function() {
return nodeList;
},
@ -55,27 +65,38 @@ RED.nodes = (function() {
typeToId[ns.types[j]] = ns.id;
}
nodeList.push(ns);
moduleList[ns.module] = moduleList[ns.module] || {
name:ns.module,
version:ns.version,
local:ns.local,
sets:{}
};
moduleList[ns.module].sets[ns.name] = ns;
RED.events.emit("registry:node-set-added",ns);
},
removeNodeSet: function(id) {
var ns = nodeSets[id];
for (var j=0;j<ns.types.length;j++) {
if (ns.added) {
// TODO: too tightly coupled into palette UI
RED.palette.remove(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
delete typeToId[ns.types[j]];
}
delete nodeSets[id];
for (var i=0;i<nodeList.length;i++) {
if (nodeList[i].id == id) {
if (nodeList[i].id === id) {
nodeList.splice(i,1);
break;
}
}
for (i=0;i<moduleList[ns.module].sets.length;i++) {
if (moduleList[ns.module].sets[i].id === id) {
moduleList[ns.module].sets[i].splice(i,1);
break;
}
}
if (moduleList[ns.module].sets.length === 0) {
delete moduleList[ns.module];
}
RED.events.emit("registry:node-set-removed",ns);
return ns;
},
getNodeSet: function(id) {
@ -84,32 +105,19 @@ RED.nodes = (function() {
enableNodeSet: function(id) {
var ns = nodeSets[id];
ns.enabled = true;
for (var j=0;j<ns.types.length;j++) {
// TODO: too tightly coupled into palette UI
RED.palette.show(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
}
RED.events.emit("registry:node-set-enabled",ns);
},
disableNodeSet: function(id) {
var ns = nodeSets[id];
ns.enabled = false;
for (var j=0;j<ns.types.length;j++) {
// TODO: too tightly coupled into palette UI
RED.palette.hide(ns.types[j]);
var def = nodeDefinitions[ns.types[j]];
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
RED.events.emit("registry:node-set-disabled",ns);
},
registerNodeType: function(nt,def) {
nodeDefinitions[nt] = def;
if (def.category != "subflows") {
def.set = nodeSets[typeToId[nt]];
nodeSets[typeToId[nt]].added = true;
nodeSets[typeToId[nt]].enabled = true;
var ns;
if (def.set.module === "node-red") {
@ -127,10 +135,7 @@ RED.nodes = (function() {
// TODO: too tightly coupled into palette UI
}
RED.palette.add(nt,def);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
RED.events.emit("registry:node-type-added",nt);
},
removeNodeType: function(nt) {
if (nt.substring(0,8) != "subflow:") {
@ -138,7 +143,7 @@ RED.nodes = (function() {
throw new Error("this api is subflow only. called with:",nt);
}
delete nodeDefinitions[nt];
RED.palette.remove(nt);
RED.events.emit("registry:node-type-removed",nt);
},
getNodeType: function(nt) {
return nodeDefinitions[nt];

View File

@ -67,6 +67,20 @@
});
}
if (this.element.css("position") === "absolute") {
this.element.css("position","static");
this.topContainer.css("position","absolute");
this.uiContainer.css("position","absolute");
["top","left","bottom","right"].forEach(function(s) {
var v = that.element.css(s);
if (s!=="auto" && s!=="") {
that.topContainer.css(s,v);
that.uiContainer.css(s,"0");
that.element.css(s,'auto');
}
})
}
this.uiContainer.addClass("red-ui-editableList-container");
this.uiHeight = this.element.height();
@ -152,7 +166,23 @@
addItem: function(data) {
var that = this;
data = data || {};
var li = $('<li>').appendTo(this.element);
var li = $('<li>');
var added = false;
if (this.options.sort) {
var items = this.items();
var skip = false;
items.each(function(i,el) {
if (added) { return }
var itemData = el.data('data');
if (that.options.sort(data,itemData) < 0) {
li.insertBefore(el.closest("li"));
added = true;
}
});
}
if (!added) {
li.appendTo(this.element);
}
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
row.data('data',data);
if (this.options.sortable === true) {

View File

@ -0,0 +1,317 @@
/**
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.palette.editor = (function() {
var nodeList;
var typesInUse = {};
var nodeEntries = {};
var eventTimers = {};
function changeNodeState(id,state,callback) {
$.ajax({
url:"nodes/"+id,
type: "PUT",
data: JSON.stringify({
enabled: state
}),
contentType: "application/json; charset=utf-8"
}).done(function(data,textStatus,xhr) {
callback();
}).fail(function(xhr,textStatus,err) {
callback(xhr);
})
}
function refreshNodeModule(module) {
if (!eventTimers.hasOwnProperty(module)) {
eventTimers[module] = setTimeout(function() {
delete eventTimers[module];
_refreshNodeModule(module);
},100);
}
}
function getContrastingBorder(rgbColor){
var parts = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)[,)]/.exec(rgbColor);
if (parts) {
var r = parseInt(parts[1]);
var g = parseInt(parts[2]);
var b = parseInt(parts[3]);
var yiq = ((r*299)+(g*587)+(b*114))/1000;
if (yiq > 160) {
r = Math.floor(r*0.8);
g = Math.floor(g*0.8);
b = Math.floor(b*0.8);
return "rgb("+r+","+g+","+b+")";
}
}
return rgbColor;
}
function _refreshNodeModule(module) {
if (!nodeEntries.hasOwnProperty(module)) {
nodeEntries[module] = {info:RED.nodes.registry.getModule(module)};
nodeList.editableList('addItem', nodeEntries[module]);
//console.log(nodeList.editableList('items'));
} else {
var moduleInfo = nodeEntries[module].info;
var nodeEntry = nodeEntries[module].elements;
if (nodeEntry) {
var activeTypeCount = 0;
var typeCount = 0;
nodeEntries[module].totalUseCount = 0;
nodeEntries[module].setUseCount = {};
for (var setName in moduleInfo.sets) {
if (moduleInfo.sets.hasOwnProperty(setName)) {
var inUseCount = 0;
var set = moduleInfo.sets[setName];
var setElements = nodeEntry.sets[setName];
if (set.enabled) {
activeTypeCount += set.types.length;
}
typeCount += set.types.length;
for (var i=0;i<moduleInfo.sets[setName].types.length;i++) {
var t = moduleInfo.sets[setName].types[i];
inUseCount += (typesInUse[t]||0);
var swatch = setElements.swatches[t];
if (set.enabled) {
var def = RED.nodes.getType(t);
if (def && def.color) {
swatch.css({background:def.color});
swatch.css({border: "1px solid "+getContrastingBorder(swatch.css('backgroundColor'))})
} else {
swatch.css({background:"#eee",border:"1px dashed #999"})
}
} else {
swatch.css({background:"#eee",border:"1px dashed #999"})
}
}
nodeEntries[module].setUseCount[setName] = inUseCount;
nodeEntries[module].totalUseCount += inUseCount;
if (inUseCount > 0) {
setElements.enableButton.html('in use');
setElements.enableButton.addClass('disabled');
} else {
setElements.enableButton.removeClass('disabled');
if (set.enabled) {
setElements.enableButton.html('disable');
} else {
setElements.enableButton.html('enable');
}
}
setElements.setRow.toggleClass("palette-module-set-disabled",!set.enabled);
}
}
var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount;
nodeEntry.setCount.html(nodeCount+" node"+(typeCount>1?"s":""));
if (nodeEntries[module].totalUseCount > 0) {
nodeEntry.enableButton.html("in use");
nodeEntry.enableButton.addClass('disabled');
nodeEntry.removeButton.hide();
} else {
nodeEntry.enableButton.removeClass('disabled');
nodeEntry.removeButton.show();
if (activeTypeCount === 0) {
nodeEntry.enableButton.html("enable all");
} else {
nodeEntry.enableButton.html("disable all");
}
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
}
}
}
}
function showPaletteEditor() {
$("#header-shade").show();
$("#editor-shade").show();
$("#sidebar-shade").show();
$("#main-container").addClass("palette-expanded");
}
function hidePaletteEditor() {
$("#main-container").removeClass("palette-expanded");
$("#header-shade").hide();
$("#editor-shade").hide();
$("#sidebar-shade").hide();
}
function init() {
$("#editor-shade").click(function() {
if ($("#main-container").hasClass("palette-expanded")) {
hidePaletteEditor();
}
});
$("#palette-edit").on("click",function(e) {
if ($("#main-container").hasClass("palette-expanded")) {
hidePaletteEditor();
} else {
showPaletteEditor();
}
});
$("#palette-editor-close").on("click", function(e) {
hidePaletteEditor();
})
var divTabs = $('<div>',{style:"position:absolute;top:80px;left:0;right:0;bottom:0"}).appendTo("#palette-editor");
nodeList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({
addButton: false,
sort: function(A,B) {
return A.info.name.localeCompare(B.info.name);
},
addItem: function(container,i,object) {
var entry = object.info;
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
var titleRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var chevron = $('<i class="fa fa-cube">').appendTo(titleRow);
var title = $('<span>',{class:"palette-module-name"}).html(entry.name).appendTo(titleRow);
var metaRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var version = $('<span class="palette-module-version"><i class="fa fa-tag"></i></span>').appendTo(metaRow);
$('<span>').html(entry.version).appendTo(version);
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var setButton = $('<a href="#" class="editor-button editor-button-small palette-module-set-button"><i class="fa fa-angle-right palette-module-node-chevron"></i> </a>').appendTo(buttonRow);
var setCount = $('<span>').appendTo(setButton);
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
var removeButton = $('<a href="#" class="editor-button editor-button-small"></a>').html('remove').appendTo(buttonGroup);
if (!entry.local) {
removeButton.hide();
}
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').html('disable all').appendTo(buttonGroup);
var contentRow = $('<div>',{class:"palette-module-content"}).appendTo(container);
object.elements = {
removeButton: removeButton,
enableButton: enableButton,
setCount: setCount,
container: container,
sets: {}
}
setButton.click(function() {
if (container.hasClass('expanded')) {
container.removeClass('expanded');
contentRow.slideUp();
} else {
container.addClass('expanded');
contentRow.slideDown();
}
})
var setList = Object.keys(entry.sets)
setList.sort(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
});
setList.forEach(function(setName) {
var set = entry.sets[setName];
var setRow = $('<div>',{class:"palette-module-set"}).appendTo(contentRow);
var buttonGroup = $('<div>',{class:"palette-module-set-button-group"}).appendTo(setRow);
var typeSwatches = {};
set.types.forEach(function(t) {
var typeDiv = $('<div>',{class:"palette-module-type"}).appendTo(setRow);
typeSwatches[t] = $('<span>',{class:"palette-module-type-swatch"}).appendTo(typeDiv);
$('<span>',{class:"palette-module-type-node"}).html(t).appendTo(typeDiv);
})
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').appendTo(buttonGroup);
enableButton.click(function(evt) {
if (object.setUseCount[setName] === 0) {
var currentSet = RED.nodes.registry.getNodeSet(set.id);
changeNodeState(set.id,!currentSet.enabled,function(xhr){
console.log(xhr)
});
}
evt.preventDefault();
})
object.elements.sets[set.name] = {
setRow: setRow,
enableButton: enableButton,
swatches: typeSwatches
};
});
enableButton.click(function(evt) {
if (object.totalUseCount === 0) {
changeNodeState(entry.name,(container.hasClass('disabled')),function(xhr){
console.log(xhr)
});
}
evt.preventDefault();
})
refreshNodeModule(entry.name);
}
});
RED.events.on('registry:node-set-enabled', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-set-disabled', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-type-added', function(nodeType) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-type-removed', function(nodeType) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-set-added', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('registry:node-set-removed', function(ns) {
refreshNodeModule(ns.module);
});
RED.events.on('nodes:add', function(n) {
typesInUse[n.type] = (typesInUse[n.type]||0)+1;
if (typesInUse[n.type] === 1) {
var ns = RED.nodes.registry.getNodeSetForType(n.type);
refreshNodeModule(ns.module);
}
})
RED.events.on('nodes:remove', function(n) {
if (typesInUse.hasOwnProperty(n.type)) {
typesInUse[n.type]--;
if (typesInUse[n.type] === 0) {
delete typesInUse[n.type];
var ns = RED.nodes.registry.getNodeSetForType(n.type);
refreshNodeModule(ns.module);
}
}
})
}
return {
init: init,
}
})();

View File

@ -393,6 +393,49 @@ RED.palette = (function() {
}
function init() {
RED.events.on('registry:node-type-added', function(nodeType) {
var def = RED.nodes.getType(nodeType);
addNodeType(nodeType,def);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
});
RED.events.on('registry:node-type-removed', function(nodeType) {
removeNodeType(nodeType);
});
RED.events.on('registry:node-set-enabled', function(nodeSet) {
for (var j=0;j<nodeSet.types.length;j++) {
showNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
def.onpaletteadd.call(def);
}
}
});
RED.events.on('registry:node-set-disabled', function(nodeSet) {
for (var j=0;j<nodeSet.types.length;j++) {
hideNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
});
RED.events.on('registry:node-set-removed', function(nodeSet) {
if (nodeSet.added) {
for (var j=0;j<nodeSet.types.length;j++) {
removeNodeType(nodeSet.types[j]);
var def = RED.nodes.getType(nodeSet.types[j]);
if (def.onpaletteremove && typeof def.onpaletteremove === "function") {
def.onpaletteremove.call(def);
}
}
}
});
$(".palette-spinner").show();
if (RED.settings.paletteCategories) {
RED.settings.paletteCategories.forEach(function(category){
@ -438,6 +481,8 @@ RED.palette = (function() {
}
}
});
RED.palette.editor.init();
}
return {

View File

@ -206,7 +206,6 @@ RED.sidebar = (function() {
showSidebar();
RED.sidebar.info.init();
RED.sidebar.config.init();
RED.sidebar.palette.init();
// hide info bar at start if screen rather narrow...
if ($(window).width() < 600) { toggleSidebar(); }
}

View File

@ -110,6 +110,7 @@ RED.tray = (function() {
$("#header-shade").show();
$("#editor-shade").show();
$("#palette-shade").show();
$(".sidebar-shade").show();
tray.preferredWidth = Math.max(el.width(),500);
@ -259,6 +260,7 @@ RED.tray = (function() {
if (stack.length === 0) {
$("#header-shade").hide();
$("#editor-shade").hide();
$("#palette-shade").hide();
$(".sidebar-shade").hide();
RED.events.emit("editor:close");
RED.view.focus();

View File

@ -167,7 +167,7 @@
background: $background-color;
color: $workspace-button-color;
}
#editor-shade, #header-shade {
#palette-shade, #editor-shade, #header-shade, #sidebar-shade {
position: absolute;
top:0;
bottom:0;

View File

@ -1,5 +1,5 @@
/**
* Copyright 2015 IBM Corp.
* Copyright 2015, 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -22,6 +22,14 @@
user-select: none;
}
@mixin enable-selection {
-webkit-user-select: auto;
-khtml-user-select: auto;
-moz-user-select: auto;
-ms-user-select: auto;
user-select: auto;
}
@mixin component-border {
border: 1px solid $primary-border-color;
box-sizing: border-box;
@ -43,14 +51,15 @@
cursor: default;
color: $workspace-button-color-disabled;
}
&:not(.disabled):hover {
&:hover, &:focus {
text-decoration: none;
}
&:not(.disabled):hover {
color: $workspace-button-color-hover;
background: $workspace-button-background-hover;
}
&:not(.disabled):focus {
color: $workspace-button-color-focus;
text-decoration: none;
}
&:not(.disabled):active {
color: $workspace-button-color-active;

View File

@ -0,0 +1,158 @@
/**
* Copyright 2016 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
#palette-editor {
text-align: left;
display: none;
position: absolute;
top: 0px;
right: 0;
bottom: 25px;
left:0;
padding: 0;
box-sizing:border-box;
background: #fff;
.red-ui-editableList-container {
border-left: none;
border-right: none;
border-bottom: none;
border-radius: 0;
padding: 0px;
li {
// border: none;
// border-top: 1px solid $primary-border-color;
padding: 0px;
.disabled {
background: #f3f3f3;
}
.red-ui-editableList-item-content {
padding: 12px 8px;
}
&:last-child {
// border-bottom: 1px solid $primary-border-color;
}
}
}
.palette-module-button-group {
position: absolute;
right: 0;
bottom: 0;
a {
margin-left: 5px;
}
}
.palette-module-meta {
overflow: hidden;
color: #666;
position: relative;
&.disabled {
color: #ccc;
}
.fa {
width: 15px;
text-align: center;
margin-right: 5px;
}
}
.palette-module-name {
white-space: nowrap;
@include enable-selection;
}
.palette-module-version {
font-style:italic;
font-size: 0.8em;
@include enable-selection;
}
.palette-module-set-button-group {
}
.palette-module-count {
border-radius: 4px;
background: #eee;
padding: 2px 8px;
font-size: 12px;
}
.palette-module-content {
display: none;
padding: 10px 3px;
}
i.fa.palette-module-node-chevron {
width: 8px;
margin-right: 0;
transform: rotate(0deg);
transition: transform 0.2s ease-in-out;
}
.expanded {
i.fa.palette-module-node-chevron {
transform: rotate(90deg);
}
.palette-module-set-button {
background:#f3f3f3 !important;
}
}
.palette-module-set {
border:1px solid $secondary-border-color;
border-radius: 0;
padding: 5px;
position: relative;
&:not(:last-child) {
border-bottom: none;
}
&:first-child {
border-top-right-radius: 2px;
border-top-left-radius: 2px;
}
&:last-child {
border-bottom-right-radius: 2px;
border-bottom-left-radius: 2px;
}
}
.palette-module-type {
color: #666;
padding-left: 5px;
font-size: 0.9em;
@include enable-selection;
}
.palette-module-type-swatch {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 3px;
vertical-align: middle;
margin-right: 5px;
background: #fff;
border: 1px solid #fff;
}
.palette-module-set-button-group {
position: absolute;
right: 4px;
top: 4px;
}
.palette-module-set-disabled {
background: #eee;
.palette-module-type {
color: #999;
}
}
}

View File

@ -25,10 +25,25 @@
text-align: center;
@include disable-selection;
@include component-border;
transition: width 0.2s ease-in-out;
}
.palette-expanded {
& #palette {
width: 380px;
box-shadow: 1px 0 6px rgba(0,0,0,0.1);
}
& #workspace { left: 379px !important; }
& #palette-collapse-all { display: none; }
& #palette-expand-all { display: none; }
& #palette-container { display: none !important; }
& #palette-search { display: none !important; }
& #palette-edit { background: $workspace-button-background-active }
& #palette-editor { display: block !important }
}
.palette-scroll {
display: none;
position: absolute;
top: 35px;
right: 0;
@ -41,9 +56,9 @@
.palette-spinner {
padding-top: 40px;
}
#palette-search {
position: absolute;
display: none;
top: 0;
left:0;
right:0;

View File

@ -40,6 +40,8 @@
@import "tab-info";
@import "popover";
@import "flow";
@import "palette-editor";
@import "typedInput";
@import "editableList";

View File

@ -40,6 +40,8 @@
right: 322px;
overflow: hidden;
@include component-border;
transition: left 0.2s ease-in-out;
}
.workspace-footer-button {

View File

@ -43,19 +43,6 @@
<div id="header-shade" class="hide"></div>
</div>
<div id="main-container" class="sidebar-closed hide">
<div id="palette">
<img src="red/images/spin.svg" class="palette-spinner hide"/>
<div id="palette-search">
<i class="fa fa-search"></i><input id="palette-search-input" type="text" data-i18n="[placeholder]palette.filter"><a href="#" id="palette-search-clear"><i class="fa fa-times"></i></a></input>
</div>
<div id="palette-container" class="palette-scroll"></div>
<div id="palette-footer">
<a class="palette-button" id="palette-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a>
<a class="palette-button" id="palette-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>
</div>
</div><!-- /palette -->
<div id="workspace">
<ul id="workspace-tabs"></ul>
<div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div>
@ -66,13 +53,32 @@
<a class="workspace-footer-button" id="btn-zoom-zero" href="#"><i class="fa fa-circle-o"></i></a>
<a class="workspace-footer-button" id="btn-zoom-in" href="#"><i class="fa fa-plus"></i></a>
</div>
<div id="editor-shade" class="hide"></div>
</div>
<div id="editor-shade" class="hide"></div>
<div id="editor-stack"></div>
<div id="palette">
<img src="red/images/spin.svg" class="palette-spinner hide"/>
<div id="palette-search" class="hide">
<i class="fa fa-search"></i><input id="palette-search-input" type="text" data-i18n="[placeholder]palette.filter"><a href="#" id="palette-search-clear"><i class="fa fa-times"></i></a></input>
</div>
<div id="palette-editor">
<div class="editor-tray-header"><div class="editor-tray-titlebar"><ul class="editor-tray-breadcrumbs"><li>Manage palette</li></ul></div><div class="editor-tray-toolbar"><button id="palette-editor-close" class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only primary" role="button" aria-disabled="false">Done</button></div></div>
</div>
<div id="palette-container" class="palette-scroll hide"></div>
<div id="palette-footer">
<div style="float:left">
<a class="palette-button palette-button-left" id="palette-edit" href="#"><i class="fa fa-cog"></i></a>
</div>
<a class="palette-button" id="palette-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a>
<a class="palette-button" id="palette-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>
</div>
<div id="palette-shade" class="hide"></div>
</div><!-- /palette -->
<div id="sidebar">
<ul id="sidebar-tabs"></ul>
<div id="sidebar-content"></div>
<div id="sidebar-footer"></div>
<div id="sidebar-shade" class="hide"></div>
</div>
<div id="sidebar-separator"></div>

View File

@ -188,7 +188,8 @@ function loadNodeConfig(fileInfo) {
template: file.replace(/\.js$/,".html"),
enabled: isEnabled,
loaded:false,
version: version
version: version,
local: fileInfo.local
};
if (fileInfo.hasOwnProperty("types")) {
node.types = fileInfo.types;

View File

@ -141,7 +141,8 @@ function scanTreeForNodesModules(moduleName) {
if (settings.userDir) {
userDir = path.join(settings.userDir,"node_modules");
results = results.concat(scanDirForNodesModules(userDir,moduleName));
results = scanDirForNodesModules(userDir,moduleName);
results.forEach(function(r) { r.local = true; });
}
if (dir) {
@ -240,12 +241,14 @@ function getNodeFiles(disableNodePathScan) {
nodeList[moduleFile.package.name] = {
name: moduleFile.package.name,
version: moduleFile.package.version,
local: moduleFile.local||false,
nodes: {}
};
if (moduleFile.package['node-red'].version) {
nodeList[moduleFile.package.name].redVersion = moduleFile.package['node-red'].version;
}
nodeModuleFiles.forEach(function(node) {
node.local = moduleFile.local||false;
nodeList[moduleFile.package.name].nodes[node.name] = node;
});
nodeFiles = nodeFiles.concat(nodeModuleFiles);

View File

@ -56,7 +56,8 @@ function filterNodeInfo(n) {
id: n.id||n.module+"/"+n.name,
name: n.name,
types: n.types,
enabled: n.enabled
enabled: n.enabled,
local: n.local||false
};
if (n.hasOwnProperty("module")) {
r.module = n.module;
@ -90,6 +91,7 @@ function saveNodeList() {
moduleList[module] = {
name: module,
version: moduleConfigs[module].version,
local: moduleConfigs[module].local||false,
nodes: {}
};
}
@ -179,6 +181,7 @@ function addNodeSet(id,set,version) {
if (version) {
moduleConfigs[set.module].version = version;
}
moduleConfigs[set.module].local = set.local;
moduleConfigs[set.module].nodes[set.name] = set;
nodeList.push(id);
@ -306,6 +309,7 @@ function getModuleInfo(module) {
var m = {
name: module,
version: moduleConfigs[module].version,
local: moduleConfigs[module].local,
nodes: []
};
for (var i = 0; i < nodes.length; ++i) {