diff --git a/editor/js/main.js b/editor/js/main.js
index 06fd8cf9f..363db9b87 100644
--- a/editor/js/main.js
+++ b/editor/js/main.js
@@ -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();
diff --git a/editor/js/ui/palette-editor.js b/editor/js/ui/palette-editor.js
index f2fc57a02..4825d2f28 100644
--- a/editor/js/ui/palette-editor.js
+++ b/editor/js/ui/palette-editor.js
@@ -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 = $('
',{style:"position:absolute;top:80px;left:0;right:0;bottom:0"}).appendTo("#palette-editor");
+ var modulesTab = $('
',{class:"palette-editor-tab"}).appendTo("#palette-editor");
- var searchDiv = $('
',{id:"palette-editor-search",class:"palette-search"}).appendTo(divTabs);
- $('
').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 = $('
',{class:"palette-search"}).appendTo(modulesTab);
+ filterInput = $('
')
+ .appendTo(filterDiv)
+ .searchBox({
+ delay: 200,
+ change: function() {
+ filterChange($(this).val());
+ }
});
- });
- nodeList = $('
',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(divTabs).editableList({
+
+ nodeList = $('',{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 = $('',{class:"palette-module-header"}).appendTo(container);
-
- var titleRow = $('
',{class:"palette-module-meta"}).appendTo(headerRow);
- var chevron = $('
').appendTo(titleRow);
- var title = $('',{class:"palette-module-name"}).html(entry.name).appendTo(titleRow);
-
- var metaRow = $('',{class:"palette-module-meta"}).appendTo(headerRow);
- var version = $('
').appendTo(metaRow);
- $('
').html(entry.version).appendTo(version);
-
-
+ var titleRow = $('
').appendTo(headerRow);
+ $('',{class:"palette-module-name"}).html(entry.name).appendTo(titleRow);
+ var metaRow = $('
').appendTo(headerRow);
+ $('').html(entry.version).appendTo(metaRow.find(".palette-module-version"));
var buttonRow = $('',{class:"palette-module-meta"}).appendTo(headerRow);
-
var setButton = $('
').appendTo(buttonRow);
var setCount = $('
').appendTo(setButton);
-
var buttonGroup = $('',{class:"palette-module-button-group"}).appendTo(buttonRow);
var removeButton = $('
').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 = $('
').html('disable all').appendTo(buttonGroup);
var contentRow = $('
',{class:"palette-module-content"}).appendTo(container);
- var shade = $('
',{class:"palette-module-shade hide"}).appendTo(container);
- $('
').appendTo(shade);
-
+ var shade = $('
').appendTo(container);
object.elements = {
removeButton: removeButton,
@@ -365,6 +478,100 @@ RED.palette.editor = (function() {
}
});
+
+
+ var installTab = $('
',{class:"palette-editor-tab hide"}).appendTo("#palette-editor");
+
+ editorTabs.addTab({
+ id: 'install',
+ label: 'Install',
+ name: 'Install',
+ content: installTab
+ })
+
+ var searchDiv = $('
',{class:"palette-search"}).appendTo(installTab);
+ searchInput = $('
')
+ .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
10) {
+ packageList.editableList('addItem',{start:10,more:filteredList.length-10})
+ }
+ searchInput.searchBox('count',filteredList.length+" / "+loadedList.length);
+ } else {
+ searchInput.searchBox('count',loadedList.length);
+ }
+ }
+ });
+
+ $(' ').appendTo(installTab);
+
+
+ packageList = $('',{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 = $('',{class:"palette-module-header palette-module"}).appendTo(container);
+ var moreLink = $('
').html("+ "+object.more+" more").appendTo(moreRow);
+ moreLink.click(function(e) {
+ e.preventDefault();
+ packageList.editableList('removeItem',object);
+ for (var i=object.start;i
10) {
+ packageList.editableList('addItem',{start:object.start+10, more:object.more-10})
+ }
+ })
+ return;
+ }
+ var entry = object.info;
+ var headerRow = $('',{class:"palette-module-header"}).appendTo(container);
+ var titleRow = $('
').appendTo(headerRow);
+ $('
',{class:"palette-module-name"}).html(entry.name||entry.id).appendTo(titleRow);
+ $(' ').attr('href',entry.url).appendTo(titleRow);
+ var descRow = $('
').appendTo(headerRow);
+ $('',{class:"palette-module-description"}).html(entry.description).appendTo(descRow);
+
+ var metaRow = $('
').appendTo(headerRow);
+ $('
'+entry.version+'').appendTo(metaRow);
+ $('
'+formatUpdatedAt(entry.updated_at)+'').appendTo(metaRow);
+ var buttonRow = $('
',{class:"palette-module-meta"}).appendTo(headerRow);
+ var buttonGroup = $('
',{class:"palette-module-button-group"}).appendTo(buttonRow);
+ var shade = $('
').appendTo(container);
+ var installButton = $('
').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
.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) {
diff --git a/editor/sass/palette-editor.scss b/editor/sass/palette-editor.scss
index 5e8330c17..a2880b7cc 100644
--- a/editor/sass/palette-editor.scss
+++ b/editor/sass/palette-editor.scss
@@ -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;
+ }
+ }
+ }
}
diff --git a/editor/sass/palette.scss b/editor/sass/palette.scss
index 18ba0b59c..15089264c 100644
--- a/editor/sass/palette.scss
+++ b/editor/sass/palette.scss
@@ -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;
}
diff --git a/editor/templates/index.mst b/editor/templates/index.mst
index bd23b55e5..2ddbea2c3 100644
--- a/editor/templates/index.mst
+++ b/editor/templates/index.mst
@@ -59,10 +59,11 @@