Add install tab to palette-editor

This commit is contained in:
Nick O'Leary 2016-08-09 10:43:03 +01:00
parent 3017442702
commit e4d788ad0b
7 changed files with 324 additions and 124 deletions

View File

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

View File

@ -15,11 +15,17 @@
**/
RED.palette.editor = (function() {
var editorTabs;
var filterInput;
var searchInput;
var nodeList;
var packageList;
var loadedList = [];
var filteredList = [];
var typesInUse = {};
var nodeEntries = {};
var eventTimers = {};
var activeFilter = "";
function delayCallback(start,callback) {
@ -55,6 +61,23 @@ RED.palette.editor = (function() {
});
})
}
function installNodeModule(id,shade,callback) {
shade.show();
$.ajax({
url:"nodes",
type: "POST",
data: JSON.stringify({
module: id
}),
contentType: "application/json; charset=utf-8"
}).done(function(data,textStatus,xhr) {
shade.hide();
callback();
}).fail(function(xhr,textStatus,err) {
shade.hide();
callback(xhr);
});
}
function removeNodeModule(id,callback) {
$.ajax({
url:"nodes/"+id,
@ -92,6 +115,70 @@ RED.palette.editor = (function() {
return rgbColor;
}
function formatUpdatedAt(dateString) {
var now = new Date();
var d = new Date(dateString);
var delta = now.getTime() - d.getTime();
delta /= 1000;
if (delta < 60) {
return "seconds ago";
}
delta = Math.floor(delta/60);
if (delta < 10) {
return "minutes ago";
}
if (delta < 60) {
return delta+" minutes ago";
}
delta = Math.floor(delta/60);
if (delta < 24) {
return delta+" hour"+(delta>1?"s":"")+" ago";
}
delta = Math.floor(delta/24);
if (delta < 7) {
return delta+" day"+(delta>1?"s":"")+" ago";
}
var weeks = Math.floor(delta/7);
var days = delta%7;
if (weeks < 4) {
if (days === 0) {
return weeks+" week"+(weeks>1?"s":"")+" ago";
} else {
return weeks+" week"+(weeks>1?"s":"")+", "+days+" day"+(days>1?"s":"")+" ago";
}
}
var months = Math.floor(weeks/4);
weeks = weeks%4;
if (months < 12) {
if (weeks === 0) {
return months+" month"+(months>1?"s":"")+" ago";
} else {
return months+" month"+(months>1?"s":"")+", "+weeks+" week"+(weeks>1?"s":"")+" ago";
}
}
var years = Math.floor(months/12);
months = months%12;
if (months === 0) {
return years+" year"+(years>1?"s":"")+" ago";
} else {
return years+" year"+(years>1?"s":"")+", "+months+" month"+(months>1?"s":"")+" ago";
}
}
function _refreshNodeModule(module) {
if (!nodeEntries.hasOwnProperty(module)) {
@ -187,6 +274,10 @@ RED.palette.editor = (function() {
$("#editor-shade").show();
$("#sidebar-shade").show();
$("#main-container").addClass("palette-expanded");
setTimeout(function() {
editorTabs.resize();
},250);
}
function hidePaletteEditor() {
$("#main-container").removeClass("palette-expanded");
@ -197,22 +288,59 @@ RED.palette.editor = (function() {
$(el).find(".palette-module-content").slideUp();
$(el).removeClass('expanded');
});
$("#palette-editor-search input").val("");
filterChange("");
filterInput.searchBox('value',"");
}
function filterChange(val) {
activeFilter = val.toLowerCase();
var visible = nodeList.editableList('filter');
var size = nodeList.editableList('length');
if (val === "") {
$("#palette-editor-search a").hide();
activeFilter = val;
filterInput.searchBox('count');
} else {
$("#palette-editor-search a").show();
activeFilter = val.toLowerCase();
filterInput.searchBox('count',visible+" / "+size);
}
nodeList.editableList('filter');
}
function initInstallTab() {
$("#palette-module-install-shade").show();
$.getJSON('http://catalog.nodered.org/catalog.json',function(v) {
loadedList = v;
searchInput.searchBox('count',loadedList.length);
loadedList.forEach(function(m) {
m.index = [m.id];
if (m.keywords) {
m.index = m.index.concat(m.keywords);
}
m.index = m.index.join(",").toLowerCase();
})
$("#palette-module-install-shade").hide();
})
}
function init() {
editorTabs = RED.tabs.create({
id:"palette-editor-tabs",
onchange:function(tab) {
$("#palette-editor .palette-editor-tab").hide();
tab.content.show();
if (tab.id === 'install') {
initInstallTab();
if (searchInput) {
searchInput.focus();
}
} else {
if (filterInput) {
filterInput.focus();
}
}
},
minimumActiveTabWidth: 110
});
$("#editor-shade").click(function() {
if ($("#main-container").hasClass("palette-expanded")) {
hidePaletteEditor();
@ -229,30 +357,27 @@ RED.palette.editor = (function() {
hidePaletteEditor();
})
var divTabs = $('<div>',{style:"position:absolute;top:80px;left:0;right:0;bottom:0"}).appendTo("#palette-editor");
var modulesTab = $('<div>',{class:"palette-editor-tab"}).appendTo("#palette-editor");
var searchDiv = $('<div>',{id:"palette-editor-search",class:"palette-search"}).appendTo(divTabs);
$('<i class="fa fa-search"></i><input type="text" data-i18n="[placeholder]palette.filter"><a href="#" class="palette-search-clear"><i class="fa fa-times"></i></a></input>').appendTo(searchDiv)
editorTabs.addTab({
id: 'nodes',
label: 'Nodes',
name: 'Nodes',
content: modulesTab
})
$("#palette-editor-search a").on("click",function(e) {
e.preventDefault();
$("#palette-editor-search input").val("");
filterChange("");
$("#palette-editor-search input").focus();
});
$("#palette-editor-search input").val("");
$("#palette-editor-search input").on("keyup",function() {
filterChange($(this).val());
});
$("#palette-editor-search input").on("focus",function() {
$("body").one("mousedown",function() {
$("#palette-editor-search input").blur();
var filterDiv = $('<div>',{class:"palette-search"}).appendTo(modulesTab);
filterInput = $('<input type="text" data-i18n="[placeholder]palette.filter"></input>')
.appendTo(filterDiv)
.searchBox({
delay: 200,
change: function() {
filterChange($(this).val());
}
});
});
nodeList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({
nodeList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(modulesTab).editableList({
addButton: false,
sort: function(A,B) {
return A.info.name.localeCompare(B.info.name);
@ -266,41 +391,29 @@ RED.palette.editor = (function() {
},
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 titleRow = $('<div class="palette-module-meta"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
$('<span>',{class:"palette-module-name"}).html(entry.name).appendTo(titleRow);
var metaRow = $('<div class="palette-module-meta"><span class="palette-module-version"><i class="fa fa-tag"></i></span></div>').appendTo(headerRow);
$('<span>').html(entry.version).appendTo(metaRow.find(".palette-module-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);
removeButton.click(function() {
shade.show();
removeNodeModule(entry.name, function(xhr) {
console.log(xhr);
})
})
if (!entry.local) {
removeButton.hide();
} else {
removeButton.click(function() {
shade.show();
removeNodeModule(entry.name, function(xhr) {
console.log(xhr);
})
})
}
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);
var shade = $('<div>',{class:"palette-module-shade hide"}).appendTo(container);
$('<img src="red/images/spin.svg" class="palette-spinner"/>').appendTo(shade);
var shade = $('<div class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(container);
object.elements = {
removeButton: removeButton,
@ -365,6 +478,100 @@ RED.palette.editor = (function() {
}
});
var installTab = $('<div>',{class:"palette-editor-tab hide"}).appendTo("#palette-editor");
editorTabs.addTab({
id: 'install',
label: 'Install',
name: 'Install',
content: installTab
})
var searchDiv = $('<div>',{class:"palette-search"}).appendTo(installTab);
searchInput = $('<input type="text" data-i18n="[placeholder]palette.search"></input>')
.appendTo(searchDiv)
.searchBox({
delay: 300,
minimumLength: 2,
change: function() {
var searchTerm = $(this).val();
packageList.editableList('empty');
if (searchTerm.length >= 2) {
filteredList = loadedList.filter(function(m) {
return (m.index.indexOf(searchTerm) > -1);
}).map(function(f) { return {info:f}});
for (var i=0;i<Math.min(10,filteredList.length);i++) {
packageList.editableList('addItem',filteredList[i]);
}
if (filteredList.length > 10) {
packageList.editableList('addItem',{start:10,more:filteredList.length-10})
}
searchInput.searchBox('count',filteredList.length+" / "+loadedList.length);
} else {
searchInput.searchBox('count',loadedList.length);
}
}
});
$('<div id="palette-module-install-shade" class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(installTab);
packageList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
addButton: false,
// sort: function(A,B) {
// return A.info.name.localeCompare(B.info.name);
// },
addItem: function(container,i,object) {
if (object.more) {
container.addClass('palette-module-more');
var moreRow = $('<div>',{class:"palette-module-header palette-module"}).appendTo(container);
var moreLink = $('<a href="#"></a>').html("+ "+object.more+" more").appendTo(moreRow);
moreLink.click(function(e) {
e.preventDefault();
packageList.editableList('removeItem',object);
for (var i=object.start;i<Math.min(object.start+10,object.start+object.more);i++) {
packageList.editableList('addItem',filteredList[i]);
}
if (object.more > 10) {
packageList.editableList('addItem',{start:object.start+10, more:object.more-10})
}
})
return;
}
var entry = object.info;
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
var titleRow = $('<div class="palette-module-meta"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
$('<span>',{class:"palette-module-name"}).html(entry.name||entry.id).appendTo(titleRow);
$('<a target="_blank" class="palette-module-link"><i class="fa fa-external-link"></i></a>').attr('href',entry.url).appendTo(titleRow);
var descRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
$('<div>',{class:"palette-module-description"}).html(entry.description).appendTo(descRow);
var metaRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
$('<span class="palette-module-version"><i class="fa fa-tag"></i> '+entry.version+'</span>').appendTo(metaRow);
$('<span class="palette-module-updated"><i class="fa fa-calendar"></i> '+formatUpdatedAt(entry.updated_at)+'</span>').appendTo(metaRow);
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
var shade = $('<div class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(container);
var installButton = $('<a href="#" class="editor-button editor-button-small"></a>').html('install').appendTo(buttonGroup);
installButton.click(function(e) {
e.preventDefault();
installNodeModule(entry.id,shade,function(xhr) {
console.log(xhr);
})
})
if (nodeEntries.hasOwnProperty(entry.id)) {
installButton.hide();
}
object.elements = {
installButton:installButton
}
}
});
RED.events.on('registry:node-set-enabled', function(ns) {
refreshNodeModule(ns.module);
});
@ -381,6 +588,12 @@ RED.palette.editor = (function() {
});
RED.events.on('registry:node-set-added', function(ns) {
refreshNodeModule(ns.module);
for (var i=0;i<filteredList.length;i++) {
if (filteredList[i].info.id === ns.module) {
filteredList[i].elements.installButton.hide();
break;
}
}
});
RED.events.on('registry:node-set-removed', function(ns) {
var module = RED.nodes.registry.getModule(ns.module);
@ -389,6 +602,12 @@ RED.palette.editor = (function() {
if (entry) {
nodeList.editableList('removeItem', entry);
delete nodeEntries[ns.module];
for (var i=0;i<filteredList.length;i++) {
if (filteredList[i].info.id === ns.module) {
filteredList[i].elements.installButton.show();
break;
}
}
}
}
});

View File

@ -362,12 +362,6 @@ RED.palette = (function() {
}
function filterChange(val) {
if (val === "") {
$("#palette-search a").hide();
} else {
$("#palette-search a").show();
}
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
$("#palette-container .palette_node").each(function(i,el) {
var currentLabel = $(el).find(".palette_label").text();
@ -435,7 +429,15 @@ RED.palette = (function() {
});
$(".palette-spinner").show();
$("#palette > .palette-spinner").show();
$("#palette-search input").searchBox({
delay: 100,
change: function() {
filterChange($(this).val());
}
})
if (RED.settings.paletteCategories) {
RED.settings.paletteCategories.forEach(function(category){
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
@ -446,24 +448,6 @@ RED.palette = (function() {
});
}
$("#palette-search a").on("click",function(e) {
e.preventDefault();
$("#palette-search input").val("");
filterChange("");
$("#palette-search input").focus();
});
$("#palette-search input").val("");
$("#palette-search input").on("keyup",function() {
filterChange($(this).val());
});
$("#palette-search input").on("focus",function() {
$("body").one("mousedown",function() {
$("#palette-search input").blur();
});
});
$("#palette-collapse-all").on("click", function(e) {
e.preventDefault();
for (var cat in categoryContainers) {

View File

@ -27,9 +27,7 @@
background: #fff;
.red-ui-editableList-container {
border-left: none;
border-right: none;
border-bottom: none;
border: none;
border-radius: 0;
padding: 0px;
@ -50,6 +48,14 @@
}
}
.palette-editor-tab {
position:absolute;
top:115px;
left:0;
right:0;
bottom:0
}
.palette-module-button-group {
position: absolute;
right: 0;
@ -68,7 +74,6 @@
text-align: center;
}
.palette-module-meta {
overflow: hidden;
color: #666;
position: relative;
&.disabled {
@ -85,11 +90,25 @@
white-space: nowrap;
@include enable-selection;
}
.palette-module-version {
.palette-module-version, .palette-module-updated, .palette-module-link {
font-style:italic;
font-size: 0.8em;
@include enable-selection;
}
.palette-module-updated {
margin-left: 10px;
}
.palette-module-link {
margin-left: 5px;
}
.palette-module-description {
margin-left: 20px;
font-size: 0.9em;
color: #999;
}
.palette-module-link {
}
.palette-module-set-button-group {
}
.palette-module-count {
@ -163,5 +182,22 @@
color: #999;
}
}
.palette-module-more {
padding: 0 !important;
margin-top: 10px;
margin-bottom: 10px;
background: $tab-background-inactive;
a {
display: block;
text-align: center;
padding: 12px 8px;
color: #AD1625;
&:hover {
text-decoration: none;
background: $tab-background-hover;
}
}
}
}

View File

@ -69,49 +69,8 @@
padding: 3px;
border-bottom: 1px solid $primary-border-color;
box-sizing:border-box;
i {
font-size: 10px;
color: #666;
}
i.fa-search {
position: absolute;
pointer-events: none;
left: 12px;
top: 12px;
}
i.fa-times {
position: absolute;
right: 7px;
top: 12px;
}
input {
border-radius: 0;
border: none;
width: 100%;
box-shadow: none;
-webkit-box-shadow: none;
padding: 3px 17px 3px 22px;
margin: 0px;
height: 30px;
box-sizing:border-box;
&:focus {
border: none;
box-shadow: none;
-webkit-box-shadow: none;
}
}
.palette-search-clear {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 20px;
display: none;
}
}
#palette-footer {
@include component-footer;
}

View File

@ -59,10 +59,11 @@
<div id="palette">
<img src="red/images/spin.svg" class="palette-spinner hide"/>
<div id="palette-search" class="palette-search hide">
<i class="fa fa-search"></i><input type="text" data-i18n="[placeholder]palette.filter"><a href="#" class="palette-search-clear"><i class="fa fa-times"></i></a></input>
<input type="text" data-i18n="[placeholder]palette.filter"></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>
<ul id="palette-editor-tabs"></ul>
</div>
<div id="palette-container" class="palette-scroll hide"></div>
<div id="palette-footer">

View File

@ -180,6 +180,7 @@
"palette": {
"noInfo": "no information available",
"filter": "filter nodes",
"search": "search modules",
"label": {
"subflows": "subflows",
"input": "input",