diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index a88890125..9cc557efd 100644 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -620,6 +620,8 @@ "pluginCount_plural": "__count__ plugins", "moduleCount": "__count__ module available", "moduleCount_plural": "__count__ modules available", + "updateCount": "__count__ update available", + "updateCount_plural": "__count__ updates available", "inuse": "in use", "enableall": "enable all", "disableall": "disable all", 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 3d949f8ca..a3653c072 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 @@ -461,6 +461,7 @@ RED.palette.editor = (function() { loadedCatalogs.push({ index: index, 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(); + refreshUpdateStatus(); }).fail(function(jqxhr, textStatus, error) { console.warn("Error loading catalog",url,":",error); handleCatalogResponse(jqxhr,url,index); @@ -625,6 +626,10 @@ RED.palette.editor = (function() { } }) + addUpdateInfoToStatusBar(); + // TODO: Periodically check + setTimeout(getSettingsPane, 1000); + RED.actions.add("core:manage-palette",function() { RED.userSettings.show('palette'); }); @@ -1462,6 +1467,59 @@ RED.palette.editor = (function() { }) } + const updateStatusWidget = $(''); + let updateAvailable = []; + + function addUpdateInfoToStatusBar() { + updateStatusWidget.on("click", function (evt) { + RED.actions.invoke("core:manage-palette", { + view: "install", + filter: '"' + updateAvailable.join('", "') + '"' + }); + }); + + RED.popover.tooltip(updateStatusWidget, function () { + const count = updateAvailable.length || 0; + return RED._("palette.editor.updateCount", { count: count }); + }); + + RED.statusBar.add({ + id: "update", + align: "right", + element: updateStatusWidget + }); + + updateStatus({ count: 0 }); + } + + function refreshUpdateStatus() { + updateAvailable = []; + + for (const module of Object.keys(nodeEntries)) { + if (loadedIndex.hasOwnProperty(module)) { + const moduleInfo = nodeEntries[module].info; + if (updateAllowed && + semVerCompare(loadedIndex[module].version, moduleInfo.version) > 0 && + RED.utils.checkModuleAllowed(module, null, updateAllowList, updateDenyList) + ) { + updateAvailable.push(module); + } + } + } + + updateStatus({ count: updateAvailable.length }); + } + + function updateStatus(opts) { + if (opts.count) { + RED.statusBar.show("update"); + updateStatusWidget.empty(); + $(' ' + opts.count + '').appendTo(updateStatusWidget); + } else { + RED.statusBar.hide("update"); + } + } + return { init: init, install: install diff --git a/packages/node_modules/@node-red/editor-client/src/sass/palette-editor.scss b/packages/node_modules/@node-red/editor-client/src/sass/palette-editor.scss index 947ada2e8..4e0d7fabc 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/palette-editor.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/palette-editor.scss @@ -305,3 +305,11 @@ button.red-ui-palette-editor-upload-button { margin-left: 10px; } } + +button.red-ui-update-status { + width: auto; + padding: 0 3px; + span { + color: var(--red-ui-text-color-warning); + } +}