From 9008f063c3544bdd73f2afae2f0fc797acf01d79 Mon Sep 17 00:00:00 2001 From: Steve-Mcl Date: Thu, 13 Jul 2023 19:49:17 +0100 Subject: [PATCH] hook up filtering to catalog selection --- .../editor-client/src/js/ui/palette-editor.js | 124 +++++++++++++----- 1 file changed, 92 insertions(+), 32 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js index 9df2d5911..df28755d0 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js @@ -16,15 +16,16 @@ RED.palette.editor = (function() { var disabled = false; - const catalogues = RED.settings.theme('palette.catalogues')||['https://catalogue.nodered.org/catalogue.json', 'http://192.168.86.130:3002/catalogue.json'] + 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 = {}; @@ -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); @@ -370,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; @@ -390,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; } @@ -405,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() { @@ -417,6 +431,7 @@ RED.palette.editor = (function() { function initInstallTab() { if (loadedList.length === 0) { + fullList = []; loadedList = []; loadedIndex = {}; packageList.editableList('empty'); @@ -432,36 +447,82 @@ RED.palette.editor = (function() { $("#red-ui-palette-module-install-shade").show(); catalogueLoadStart = Date.now(); var handled = 0; - const catalogTypes = [] + const catalogEntries = [] for (let index = 0; index < catalogues.length; index++) { - const catalog = catalogues[index]; - $.getJSON(catalog, {_: new Date().getTime()},function(v) { - catalogTypes.push(v); - handleCatalogResponse(null,catalog,index,v); + 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'); - console.log("adding types to typedInput", catalogTypes) - const catalogSelection = $('#red-catalogue-filter-select') - catalogSelection.empty() - // loop through catalogTypes, and option per entry - for (let index = 0; index < catalogTypes.length; index++) { - const catalog = catalogTypes[index]; - catalogSelection.append(``) - } - // select the 1st option - catalogSelection.val(catalogSelection.find('option:first').val()) + 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) + // 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") + // 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($('`) + } + // 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(``) + 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(); @@ -476,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}) } @@ -506,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; } @@ -815,7 +876,7 @@ RED.palette.editor = (function() { $('
',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container); } } - }); + }) } function createInstallTab(content) { @@ -845,7 +906,6 @@ RED.palette.editor = (function() { searchInput.searchBox('count',loadedList.length); packageList.editableList('empty'); packageList.editableList('addItem',{count:loadedList.length}); - } } });