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..d1375f5b2 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 @@ -628,6 +628,7 @@ "remove": "remove", "update": "update to __version__", "updated": "updated", + "updating": "Updating...", "install": "install", "installed": "installed", "conflict": "conflict", @@ -667,6 +668,9 @@ "body": "

Updating '__module__'

Updating the node will require a restart of Node-RED to complete the update. This must be done manually.

", "title": "Update nodes" }, + "updateAll": { + "body": "

Updating __count__ nodes

Updating the nodes will require a restart of Node-RED to complete the update. This must be done manually.

" + }, "cannotUpdate": { "body": "An update for this node is available, but it is not installed in a location that the palette manager can update.

Please refer to the documentation for how to update this node." }, @@ -675,8 +679,12 @@ "install": "Install", "remove": "Remove", "update": "Update", + "updateAll": "Update all", "understood": "Understood" } + }, + "progress": { + "updated": "Updated __count__/__total__ modules" } } }, 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..42de7978a 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 @@ -473,6 +473,24 @@ RED.palette.editor = (function() { } }) } + } else { + const updateAllButton = $(nodesTabFooter).find("#red-ui-palette-button-updateAll"); + const progressRow = $(nodesTabFooter).find(".red-ui-palette-footer-progress"); + + // Update the "Update all" button when the Palette opening + if (updateAllButton.length) { + updateAllButton.text(RED._("palette.editor.confirm.button.updateAll")); + if (updateAvailable.length) { + updateAllButton.removeClass("disabled"); + } else { + updateAllButton.addClass("disabled"); + } + } + + // Set progress to empty when the Palette opening + if (progressRow.length) { + progressRow.text(""); + } } } @@ -625,6 +643,8 @@ RED.palette.editor = (function() { } }) + getSettingsPane(); + RED.actions.add("core:manage-palette",function() { RED.userSettings.show('palette'); }); @@ -728,6 +748,7 @@ RED.palette.editor = (function() { } var settingsPane; + var nodesTabFooter; function getSettingsPane() { initInstallTab(); @@ -829,7 +850,6 @@ RED.palette.editor = (function() { update(entry,loadedIndex[entry.name].version,loadedIndex[entry.name].pkg_url,container,function(err){}); }) - var removeButton = $('').text(RED._('palette.editor.remove')).appendTo(buttonGroup); removeButton.attr('id','up_'+Math.floor(Math.random()*1000000000)); removeButton.on("click", function(evt) { @@ -962,6 +982,25 @@ RED.palette.editor = (function() { } } }) + + nodesTabFooter = $('
', { class: "red-ui-palette-footer" }).appendTo(modulesTab); + const buttonRow = $('
', { class: "red-ui-palette-footer-button" }).appendTo(nodesTabFooter); + const updateAllButton = $('').appendTo(buttonRow); + $('').appendTo(nodesTabFooter); + $('').appendTo(updateAllButton); + + updateAllButton.on("click", function (evt) { + evt.preventDefault(); + if (updateAllButton.hasClass("disabled")) { + return; + } + + updateAllButton.text(RED._("palette.editor.updating")); + updateAllButton.addClass("disabled"); + autoUpdateModules(function () { + updateAllButton.text(RED._("palette.editor.updated")); + }); + }); } function createInstallTab(content) { @@ -1206,6 +1245,81 @@ RED.palette.editor = (function() { $('
').appendTo(installTab); } + function autoUpdateModules(done) { + if (RED.settings.get('externalModules.palette.allowInstall', true) === false) { + console.error(new Error('Update failed: Palette not editable')); + return; + } + + const updateAllButton = $(nodesTabFooter).find("#red-ui-palette-button-updateAll"); + const progressRow = $(nodesTabFooter).find(".red-ui-palette-footer-progress"); + const modules = updateAvailable.slice(); + const runUpdate = function () { + modules.forEach(function (moduleName, i) { + if (moduleName in nodeEntries) { + const { version, pkg_url } = loadedIndex[moduleName]; + const updatedCount = i + 1; + installNodeModule(moduleName, version, pkg_url, function (xhr) { + if (xhr) { + if (xhr.responseJSON) { + const notification = RED.notify(RED._("palette.editor.errors.updateFailed", { module: moduleName, message: xhr.responseJSON.message }), { + type: "error", + modal: true, + fixed: true, + buttons: [ + { + text: RED._("common.label.close"), + click: function() { + notification.close(); + } + }, { + text: RED._("eventLog.view"), + click: function() { + notification.close(); + RED.actions.invoke("core:show-event-log"); + } + } + ] + }); + } + } else { + progressRow.text(RED._("palette.editor.progress.updated", { + count: updatedCount, + total: modules.length + })); + if (i === modules.length - 1) { + done(); + } + } + }); + } + }); + } + + const notification = RED.notify(RED._("palette.editor.confirm.updateAll.body", { count: updateAvailable.length }), { + modal: true, + fixed: true, + buttons: [ + { + text: RED._("common.label.cancel"), + click: function () { + notification.close(); + updateAllButton.removeClass("disabled"); + updateAllButton.text(RED._("palette.editor.confirm.button.updateAll")); + } + }, + { + text: RED._("palette.editor.confirm.button.updateAll"), + class: "primary red-ui-palette-module-install-confirm-button-update", + click: function () { + notification.close(); + runUpdate(); + } + }, + ] + }); + } + function update(entry,version,url,container,done) { if (RED.settings.get('externalModules.palette.allowInstall', true) === false) { done(new Error('Palette not editable')); @@ -1462,6 +1576,8 @@ RED.palette.editor = (function() { }) } + let updateAvailable = []; + 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..0d4f3848b 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,13 @@ button.red-ui-palette-editor-upload-button { margin-left: 10px; } } + +.red-ui-palette-footer-button, +.red-ui-palette-footer-progress { + display: inline-block; + vertical-align: middle; + margin: 0 5px; +} +.red-ui-palette-footer-progress { + color: var(--red-ui-secondary-text-color); +}