Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Catalogue visibility #4248

Merged
merged 8 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@
"editor": {
"title": "Manage palette",
"palette": "Palette",
"allCatalogs": "All Catalogs",
"times": {
"seconds": "seconds ago",
"minutes": "minutes ago",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@
RED.palette.editor = (function() {

var disabled = false;

let catalogues = []
var editorTabs;
var filterInput;
var searchInput;
var nodeList;
var packageList;
var loadedList = [];
var filteredList = [];
var loadedIndex = {};
let filterInput;
let searchInput;
let nodeList;
let packageList;
let fullList = []
let loadedList = [];
let filteredList = [];
let loadedIndex = {};

var typesInUse = {};
var nodeEntries = {};
Expand Down Expand Up @@ -162,6 +163,18 @@ RED.palette.editor = (function() {
}
}

function filterByCatalog(selectedCatalog) {
const catalogCount = $('#red-catalogue-filter-select option').length
if (catalogCount <= 1 || selectedCatalog === "all") {
loadedList = fullList.slice();
} else {
loadedList = fullList.filter(function(m) {
return (m.catalog.name === selectedCatalog);
})
}
refreshFilteredItems();
searchInput.searchBox('count',filteredList.length+" / "+loadedList.length);
}

function getContrastingBorder(rgbColor){
var parts = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)[,)]/.exec(rgbColor);
Expand Down Expand Up @@ -232,6 +245,7 @@ RED.palette.editor = (function() {


function _refreshNodeModule(module) {
console.log("refresh",module);
Steve-Mcl marked this conversation as resolved.
Show resolved Hide resolved
if (!nodeEntries.hasOwnProperty(module)) {
nodeEntries[module] = {info:RED.nodes.registry.getModule(module)};
var index = [module];
Expand Down Expand Up @@ -369,10 +383,10 @@ RED.palette.editor = (function() {
var activeSort = sortModulesRelevance;

function handleCatalogResponse(err,catalog,index,v) {
const url = catalog.url
catalogueLoadStatus.push(err||v);
if (!err) {
if (v.modules) {
var a = false;
v.modules = v.modules.filter(function(m) {
if (RED.utils.checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
loadedIndex[m.id] = m;
Expand All @@ -389,13 +403,14 @@ RED.palette.editor = (function() {
m.timestamp = 0;
}
m.index = m.index.join(",").toLowerCase();
m.catalog = catalog;
m.catalogIndex = index;
return true;
}
return false;
})
loadedList = loadedList.concat(v.modules);
}
searchInput.searchBox('count',loadedList.length);
} else {
catalogueLoadErrors = true;
}
Expand All @@ -404,7 +419,7 @@ RED.palette.editor = (function() {
}
if (catalogueLoadStatus.length === catalogueCount) {
if (catalogueLoadErrors) {
RED.notify(RED._('palette.editor.errors.catalogLoadFailed',{url: catalog}),"error",false,8000);
RED.notify(RED._('palette.editor.errors.catalogLoadFailed',{url: url}),"error",false,8000);
}
var delta = 250-(Date.now() - catalogueLoadStart);
setTimeout(function() {
Expand All @@ -416,12 +431,13 @@ RED.palette.editor = (function() {

function initInstallTab() {
if (loadedList.length === 0) {
fullList = [];
loadedList = [];
loadedIndex = {};
packageList.editableList('empty');

$(".red-ui-palette-module-shade-status").text(RED._('palette.editor.loading'));
var catalogues = RED.settings.theme('palette.catalogues')||['https://catalogue.nodered.org/catalogue.json'];

catalogueLoadStatus = [];
catalogueLoadErrors = false;
catalogueCount = catalogues.length;
Expand All @@ -431,23 +447,82 @@ RED.palette.editor = (function() {
$("#red-ui-palette-module-install-shade").show();
catalogueLoadStart = Date.now();
var handled = 0;
catalogues.forEach(function(catalog,index) {
$.getJSON(catalog, {_: new Date().getTime()},function(v) {
handleCatalogResponse(null,catalog,index,v);
const catalogEntries = []
for (let index = 0; index < catalogues.length; index++) {
const url = catalogues[index];
$.getJSON(url, {_: new Date().getTime()},function(v) {
catalogEntries.push({ url: url, name: v.name, updated_at: v.updated_at, modules_count: (v.modules || []).length })
handleCatalogResponse(null,{ url: url, name: v.name},index,v);
refreshNodeModuleList();
}).fail(function(jqxhr, textStatus, error) {
console.warn("Error loading catalog",catalog,":",error);
handleCatalogResponse(jqxhr,catalog,index);
console.warn("Error loading catalog",url,":",error);
handleCatalogResponse(jqxhr,url,index);
}).always(function() {
handled++;
if (handled === catalogueCount) {
searchInput.searchBox('change');
updateCatalogFilter(catalogEntries)
}
})
});
}
}
}

/**
* Refreshes the catalog filter dropdown and updates local variables
* @param {[{url:String, name:String, updated_at:String, modules_count:Number}]} catalogEntries
*/
function updateCatalogFilter(catalogEntries, maxRetry = 3) {
console.log("updateCatalogFilter", catalogEntries, maxRetry)
Steve-Mcl marked this conversation as resolved.
Show resolved Hide resolved
// clean up existing filters
const catalogSelection = $('#red-catalogue-filter-select')
if (catalogSelection.length === 0) {
// sidebar not yet loaded (red-catalogue-filter-select is not in dom)
if (maxRetry > 0) {
console.log("updateCatalogFilter: sidebar not yet loaded, retrying in 100ms")
Steve-Mcl marked this conversation as resolved.
Show resolved Hide resolved
// try again in 100ms
setTimeout(() => {
updateCatalogFilter(catalogEntries, maxRetry - 1)
}, 100);
return;
}
return; // give up
}
catalogSelection.off("change") // remove any existing event handlers
catalogSelection.attr('disabled', 'disabled')
catalogSelection.empty()
catalogSelection.append($('<option>', { value: "loading", text: RED._('palette.editor.loading'), disabled: true, selected: true }));

fullList = loadedList.slice()
catalogSelection.empty() // clear the select list
// if there are more than 1 catalog, add an option to select all
if (catalogEntries.length > 1) {
}
// loop through catalogTypes, and an option entry per catalog
for (let index = 0; index < catalogEntries.length; index++) {
const catalog = catalogEntries[index];
catalogSelection.append(`<option value="${catalog.name}">${catalog.name}</option>`)
}
// select the 1st option in the select list
catalogSelection.val(catalogSelection.find('option:first').val())

// if there is only 1 catalog, hide the select
if (catalogEntries.length > 1) {
catalogSelection.prepend(`<option value="all">${RED._('palette.editor.allCatalogs')}</option>`)
catalogSelection.show()
catalogSelection.removeAttr('disabled') // permit the user to select a catalog
}
// refresh the searchInput counter and trigger a change
filterByCatalog(catalogSelection.val())
searchInput.searchBox('change');

// hook up the change event handler
catalogSelection.on("change", function() {
const selectedCatalog = $(this).val();
filterByCatalog(selectedCatalog);
searchInput.searchBox('change');
})
}

function refreshFilteredItems() {
packageList.editableList('empty');
var currentFilter = searchInput.searchBox('value').trim();
Expand All @@ -462,7 +537,6 @@ RED.palette.editor = (function() {
if (filteredList.length === 0) {
packageList.editableList('addItem',{});
}

if (filteredList.length > 10) {
packageList.editableList('addItem',{start:10,more:filteredList.length-10})
}
Expand Down Expand Up @@ -492,6 +566,7 @@ RED.palette.editor = (function() {
var updateDenyList = [];

function init() {
catalogues = RED.settings.theme('palette.catalogues')||['https://catalogue.nodered.org/catalogue.json']
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
return;
}
Expand Down Expand Up @@ -669,7 +744,8 @@ RED.palette.editor = (function() {
});


nodeList = $('<ol>',{id:"red-ui-palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(modulesTab).editableList({
nodeList = $('<ol>',{id:"red-ui-palette-module-list"}).appendTo(modulesTab).editableList({
class: "scrollable",
addButton: false,
scrollOnAdd: false,
sort: function(A,B) {
Expand Down Expand Up @@ -800,21 +876,20 @@ RED.palette.editor = (function() {
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
}
}
});
})
}

function createInstallTab(content) {
var installTab = $('<div>',{class:"red-ui-palette-editor-tab hide"}).appendTo(content);

const installTab = $('<div>',{class:"red-ui-palette-editor-tab", style: "display: none;"}).appendTo(content);
editorTabs.addTab({
id: 'install',
label: RED._('palette.editor.tab-install'),
content: installTab
})

var toolBar = $('<div>',{class:"red-ui-palette-editor-toolbar"}).appendTo(installTab);

var searchDiv = $('<div>',{class:"red-ui-palette-search"}).appendTo(installTab);
const toolBar = $('<div>',{class:"red-ui-palette-editor-toolbar"}).appendTo(installTab);
const searchDiv = $('<div>',{class:"red-ui-palette-search"}).appendTo(installTab);
searchInput = $('<input type="text" data-i18n="[placeholder]palette.search"></input>')
.appendTo(searchDiv)
.searchBox({
Expand All @@ -831,19 +906,26 @@ RED.palette.editor = (function() {
searchInput.searchBox('count',loadedList.length);
packageList.editableList('empty');
packageList.editableList('addItem',{count:loadedList.length});

}
}
});

$('<span>').text(RED._("palette.editor.sort")+' ').appendTo(toolBar);
var sortGroup = $('<span class="button-group"></span>').appendTo(toolBar);
var sortRelevance = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle selected"><i class="fa fa-sort-amount-desc"></i></a>').appendTo(sortGroup);
var sortAZ = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle" data-i18n="palette.editor.sortAZ"></a>').appendTo(sortGroup);
var sortRecent = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle" data-i18n="palette.editor.sortRecent"></a>').appendTo(sortGroup);
const catalogSelection = $('<select id="red-catalogue-filter-select">').appendTo(toolBar);
catalogSelection.addClass('red-ui-palette-editor-catalogue-filter');
catalogSelection.hide() // hide the select until the catalogues have been loaded

const toolBarActions = $('<div>',{class:"red-ui-palette-editor-toolbar-actions"}).appendTo(toolBar);

$('<span>').text(RED._("palette.editor.sort")+' ').appendTo(toolBarActions);
const sortGroup = $('<span class="button-group"></span>').appendTo(toolBarActions);
const sortRelevance = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle selected"><i class="fa fa-sort-amount-desc"></i></a>').appendTo(sortGroup);
const sortAZ = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle"><i class="fa fa-sort-alpha-asc"></i></a>').appendTo(sortGroup);
const sortRecent = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle"><i class="fa fa-calendar"></i></a>').appendTo(sortGroup);
RED.popover.tooltip(sortAZ,RED._("palette.editor.sortAZ"));
RED.popover.tooltip(sortRecent,RED._("palette.editor.sortRecent"));

var sortOpts = [

const sortOpts = [
{button: sortRelevance, func: sortModulesRelevance},
{button: sortAZ, func: sortModulesAZ},
{button: sortRecent, func: sortModulesRecent}
Expand All @@ -861,7 +943,7 @@ RED.palette.editor = (function() {
});
});

var refreshSpan = $('<span>').appendTo(toolBar);
var refreshSpan = $('<span>').appendTo(toolBarActions);
var refreshButton = $('<a href="#" class="red-ui-sidebar-header-button"><i class="fa fa-refresh"></i></a>').appendTo(refreshSpan);
refreshButton.on("click", function(e) {
e.preventDefault();
Expand All @@ -871,7 +953,8 @@ RED.palette.editor = (function() {
})
RED.popover.tooltip(refreshButton,RED._("palette.editor.refresh"));

packageList = $('<ol>',{style:"position: absolute;top: 79px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
packageList = $('<ol>').appendTo(installTab).editableList({
class: "scrollable",
addButton: false,
scrollOnAdd: false,
addItem: function(container,i,object) {
Expand Down Expand Up @@ -906,6 +989,9 @@ RED.palette.editor = (function() {
var metaRow = $('<div class="red-ui-palette-module-meta"></div>').appendTo(headerRow);
$('<span class="red-ui-palette-module-version"><i class="fa fa-tag"></i> '+entry.version+'</span>').appendTo(metaRow);
$('<span class="red-ui-palette-module-updated"><i class="fa fa-calendar"></i> '+formatUpdatedAt(entry.updated_at)+'</span>').appendTo(metaRow);
if (catalogSelection.val() === 'all') {
$('<span class="red-ui-palette-module-updated"><i class="fa fa-cubes"></i>' + (entry.catalog.name || entry.catalog.url) + '</span>').appendTo(metaRow);
}

var duplicateType = false;
if (entry.types && entry.types.length > 0) {
Expand Down Expand Up @@ -952,9 +1038,10 @@ RED.palette.editor = (function() {
}
}
});


if (RED.settings.get('externalModules.palette.allowUpload', true) !== false) {
var uploadSpan = $('<span class="button-group">').prependTo(toolBar);
var uploadSpan = $('<span class="button-group">').prependTo(toolBarActions);
var uploadButton = $('<button type="button" class="red-ui-sidebar-header-button red-ui-palette-editor-upload-button"><label><i class="fa fa-upload"></i><form id="red-ui-palette-editor-upload-form" enctype="multipart/form-data"><input name="tarball" type="file" accept=".tgz"></label></button>').appendTo(uploadSpan);

var uploadInput = uploadButton.find('input[type="file"]');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
**/

#red-ui-settings-tab-palette {
#red-ui-settings-tab-palette {
height: 100%;
}

Expand All @@ -28,7 +28,17 @@
padding: 0;
box-sizing:border-box;
background: var(--red-ui-secondary-background);
display: flex;
flex-direction: column;

.red-ui-tabs {
flex-shrink: 0;
margin-bottom: 0;
}

.red-ui-editableList.scrollable {
overflow-y: auto;
}
.red-ui-editableList-container {
border: none;
border-radius: 0;
Expand Down Expand Up @@ -72,18 +82,34 @@

}
.red-ui-palette-editor-tab {
position:absolute;
top:35px;
left:0;
right:0;
bottom:0
display: flex;
flex-direction: column;
min-height: 0;
}
.red-ui-palette-editor-toolbar {
background: var(--red-ui-primary-background);
box-sizing: border-box;
padding: 8px 10px;
border-bottom: 1px solid var(--red-ui-primary-border-color);
text-align: right;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 3px 12px;
.red-ui-palette-editor-toolbar-actions {
flex-shrink: 0;
flex-grow: 1;
}
.red-ui-palette-editor-catalogue-filter {
width: unset;
margin: 0;
flex-shrink: 1;
flex-grow: 1;
font-size: 12px;
height: 26px;
padding: 1px;
}
}
.red-ui-palette-module-shade-status {
color: var(--red-ui-secondary-text-color);
Expand Down