Add config-node sidebar tab

Accessed from the drop-down menu
This commit is contained in:
Nick O'Leary 2014-01-25 22:31:43 +00:00
parent 1bdbd6a5b0
commit cfd8d137cf
9 changed files with 298 additions and 22 deletions

View File

@ -49,6 +49,8 @@
</ul>
</li>
<li class="divider"></li>
<li><a id="btn-config-nodes" tabindex="-1" href="#"><i class="icon-th-list"></i> Configuration nodes...</a></li>
<li class="divider"></li>
<li class="dropdown-submenu pull-left"><a tabindex="-1" href="#"><i class="icon-th-large"></i> Workspaces</a>
<ul class="dropdown-menu">
<li><a id="btn-workspace-add" tabindex="-1" href="#"><i class="icon-plus"></i> Add</a></li>
@ -307,6 +309,7 @@
<script src="red/ui/view.js"></script>
<script src="red/ui/sidebar.js"></script>
<script src="red/ui/palette.js"></script>
<script src="red/ui/tab-config.js"></script>
<script src="red/ui/editor.js"></script>
<script src="red/ui/library.js"></script>
<script src="red/ui/notifications.js"></script>

View File

@ -39,9 +39,27 @@ RED.nodes = function() {
function addNode(n) {
if (n._def.category == "config") {
configNodes[n.id] = n;
RED.configTab.refresh();
} else {
n.dirty = true;
nodes.push(n);
var updatedConfigNode = false;
for (var d in n._def.defaults) {
var property = n._def.defaults[d];
if (property.type) {
var type = getType(property.type)
if (type && type.category == "config") {
var configNode = configNodes[n[d]];
if (configNode) {
updatedConfigNode = true;
configNode.users.push(n);
}
}
}
}
if (updatedConfigNode) {
RED.configTab.refresh();
}
}
}
function addLink(l) {
@ -68,6 +86,7 @@ RED.nodes = function() {
var removedLinks = [];
if (id in configNodes) {
delete configNodes[id];
RED.configTab.refresh();
} else {
var node = getNode(id);
if (node) {
@ -75,6 +94,24 @@ RED.nodes = function() {
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
removedLinks.map(function(l) {links.splice(links.indexOf(l), 1); });
}
var updatedConfigNode = false;
for (var d in node._def.defaults) {
var property = node._def.defaults[d];
if (property.type) {
var type = getType(property.type)
if (type && type.category == "config") {
var configNode = configNodes[node[d]];
if (configNode) {
updatedConfigNode = true;
var users = configNode.users;
users.splice(users.indexOf(node),1);
}
}
}
}
if (updatedConfigNode) {
RED.configTab.refresh();
}
}
return removedLinks;
}

View File

@ -267,11 +267,12 @@ RED.editor = function() {
RED.keyboard.enable();
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(0);
RED.view.state(RED.state.DEFAULT);
}
$( this ).dialog('option','height','auto');
$( this ).dialog('option','width','500');
editing_node = null;
RED.configTab.refresh();
}
});
@ -462,14 +463,22 @@ RED.editor = function() {
resize: function(e,ui) {
},
open: function(e) {
if (RED.view.state() != RED.state.EDITING) {
RED.keyboard.disable();
}
},
close: function(e) {
if (RED.view.state() != RED.state.EDITING) {
RED.keyboard.enable();
}
RED.configTab.refresh();
}
});
return {
edit: showEditDialog,
editConfig: showEditConfigNodeDialog,
validateNode: validateNode,
updateNodeProperties: updateNodeProperties // TODO: only exposed for edit-undo
}

View File

@ -21,12 +21,15 @@ RED.sidebar = function() {
onchange:function(id) {
$("#sidebar-content").children().hide();
$("#"+id).show();
},
onremove: function(id) {
$("#"+id).remove();
}
});
function addTab(title,content) {
function addTab(title,content,closeable) {
$("#sidebar-content").append(content);
$(content).hide();
sidebar_tabs.addTab({id:"tab-"+title,label:title});
sidebar_tabs.addTab({id:"tab-"+title,label:title,closeable:closeable});
//content.style.position = "absolute";
//$('#sidebar').tabs("refresh");
}
@ -101,9 +104,21 @@ RED.sidebar = function() {
}
toggleSidebar();
function showSidebar(id) {
if (!$("#btn-sidebar").hasClass("active")) {
toggleSidebar();
}
sidebar_tabs.activateTab("tab-"+id);
}
function containsTab(id) {
return sidebar_tabs.contains("tab-"+id);
}
return {
addTab: addTab
addTab: addTab,
show: showSidebar,
containsTab: containsTab
}
}();

View File

@ -14,6 +14,7 @@
* limitations under the License.
**/
RED.state = {
DEFAULT: 0,
MOVING: 1,
JOINING: 2,
MOVING_ACTIVE: 3,

View File

@ -0,0 +1,84 @@
/**
* Copyright 2013 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.configTab = function() {
var content = document.createElement("div");
content.id = "tab-config";
content.style.paddingTop = "4px";
content.style.paddingLeft = "4px";
content.style.paddingRight = "4px";
var list = $("<ul>",{class:"tab-config-list"}).appendTo(content);
$("#btn-config-nodes").click(function(){
if (!RED.sidebar.containsTab("config")) {
RED.sidebar.addTab("config",content,true);
}
refresh();
RED.sidebar.show("config");
});
function refresh() {
list.empty();
var count = 0;
RED.nodes.eachConfig(function(node) {
count += 1;
var li = list.find("#tab-config-list-type-"+node.type);
if (li.length == 0) {
li = $("<li>",{id:"tab-config-list-type-"+node.type}).appendTo(list);
$('<div class="tab-config-list-type">'+node.type+'</div>').appendTo(li);
}
var label = "";
if (typeof node._def.label == "function") {
label = node._def.label.call(node);
} else {
label = node._def.label;
}
var entry = $('<div class="tab-config-list-entry"></div>').appendTo(li);
entry.on('dblclick',function(e) {
RED.editor.editConfig("", node.type, node.id);
});
var userArray = node.users.map(function(n) { return n.id });
entry.on('mouseover',function(e) {
RED.nodes.eachNode(function(node) {
if( userArray.indexOf(node.id) != -1) {
node.highlighted = true;
node.dirty = true;
}
});
RED.view.redraw();
});
entry.on('mouseout',function(e) {
RED.nodes.eachNode(function(node) {
if(node.highlighted) {
node.highlighted = false;
node.dirty = true;
}
});
RED.view.redraw();
});
$('<div class="tab-config-list-label">'+label+'</div>').appendTo(entry);
$('<div class="tab-config-list-users">'+node.users.length+'</div>').appendTo(entry);
});
}
return {
refresh:refresh
}
}();

View File

@ -34,6 +34,7 @@ RED.tabs = function() {
if (options.ondblclick) {
options.ondblclick($(this).attr('href').slice(1));
}
return false;
}
function activateTab(link) {
@ -61,13 +62,38 @@ RED.tabs = function() {
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
updateTabWidths();
function removeTab(id) {
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("active")) {
var tab = li.prev();
if (tab.size() == 0) {
tab = li.next();
}
activateTab(tab.find("a"));
}
li.remove();
if (options.onremove) {
options.onremove(id);
}
updateTabWidths();
}
return {
addTab: function(tab) {
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
var link = $("<a/>",{href:"#"+tab.id}).appendTo(li);
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
link.html(tab.label);
link.on("click",onTabClick);
link.on("dblclick",onTabDblClick);
if (tab.closeable) {
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
closeLink.html('<i class="icon-remove" />');
closeLink.on("click",function(event) {
removeTab(tab.id);
});
}
updateTabWidths();
if (options.onadd) {
options.onadd(tab);
@ -77,26 +103,16 @@ RED.tabs = function() {
activateTab(link);
}
},
removeTab: function(id) {
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("active")) {
var tab = li.prev();
if (tab.size() == 0) {
tab = li.next();
}
activateTab(tab.find("a"));
}
li.remove();
if (options.onremove) {
options.onremove(id);
}
},
removeTab: removeTab,
activateTab: activateTab,
resize: updateTabWidths,
count: function() {
return ul.find("li.red-ui-tab").size();
},
contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0;
}
}
}

View File

@ -704,11 +704,31 @@ ul.red-ui-tabs li {
white-space: nowrap;
}
ul.red-ui-tabs li a {
ul.red-ui-tabs li a.red-ui-tab-label {
display: block;
padding: 3px 16px;
color: #666;
}
ul.red-ui-tabs li {
position: relative;
}
ul.red-ui-tabs li a.red-ui-tab-close {
background: rgba(227,227,227,0.8);
position: absolute;
right: 2px;
top: 2px;
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
padding: 0px;
border-radius: 5px;
}
ul.red-ui-tabs li a.red-ui-tab-close:hover {
background: #bbb !important;
}
ul.red-ui-tabs li a:hover {
text-decoration: none;
background: #f0f0f0;
@ -721,7 +741,10 @@ ul.red-ui-tabs li.active {
ul.red-ui-tabs li.active a {
color: #333;
}
ul.red-ui-tabs li.active a:hover {
ul.red-ui-tabs li.active a.red-ui-tab-close {
background: rgba(255,255,255,0.8);
}
ul.red-ui-tabs li.active a.red-ui-tab-label:hover {
background: #fff;
}
ul.red-ui-tabs li.red-ui-add-tab {
@ -732,3 +755,56 @@ ul.red-ui-tabs li.red-ui-add-tab {
ul.red-ui-tabs li.red-ui-add-tab a {
padding: 2px 4px;
}
ul.tab-config-list {
list-style-type: none;
padding: 3px;
margin: 0;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ul.tab-config-list li {
max-width: 400px;
font-size: 13px;
background: #f3f3f3;
margin: 10px auto;
border-radius: 3px;
border: 1px solid #ccc;
padding: 3px 8px;
}
div.tab-config-list-type {
}
div.tab-config-list-entry {
position: relative;
margin: 4px 0;
padding: 8px 4px 8px 10px;
background: #fff;
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
}
div.tab-config-list-entry:hover {
background: #f6f6f6;
}
div.tab-config-list-label {
}
div.tab-config-list-users {
position: absolute;
right: 3px;
top: 3px;
bottom: 3px;
line-height: 27px;
font-size: 11px;
background: #f6f6f6;
float: right;
border: 1px solid #eee;
border-radius: 3px;
padding: 1px 5px;
}

View File

@ -239,6 +239,39 @@ module.exports.getNodeConfigs = node_type_registry.getNodeConfigs;
module.exports.addLogHandler = registry.addLogHandler;
module.exports.load = function(settings) {
function scanForNodes(dir) {
var pm = path.join(dir,"node_modules");
if (fs.existsSync(pm)) {
fs.readdirSync(pm).filter(function(fn) {
var pkgfn = path.join(pm,fn,"package.json");
if (fs.existsSync(pkgfn)) {
var pkg = require(pkgfn);
if (pkg['node-red']) {
console.log(pkg.name,pkg.version);
var nr = pkg['node-red'];
if (nr.nodes) {
var nrn = nr.nodes;
for (var i in nrn) {
console.log(" ",i,":",nrn[i]);
try {
require(path.join(pm,fn,nrn[i]));
} catch(err) {
util.log("["+i+"] "+err);
//console.log(err.stack);
}
}
}
}
}
});
}
var up = path.join(dir,"..");
if (up !== dir) {
scanForNodes(up);
}
}
function loadNodes(dir) {
fs.readdirSync(dir).sort().filter(function(fn){
var stats = fs.statSync(path.join(dir,fn));
@ -262,8 +295,10 @@ module.exports.load = function(settings) {
});
}
loadNodes(__dirname+"/../nodes");
scanForNodes(__dirname+"/../nodes");
if (settings.nodesDir) {
loadNodes(settings.nodesDir);
scanForNodes(settings.nodesDir);
}
//events.emit("nodes-loaded");
}