// // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . $(function () { function KlipperBackupViewModel(parameters) { var self = this; self.loginState = parameters[0]; self.klipperViewModel = parameters[1]; self.access = parameters[2]; self.header = OctoPrint.getRequestHeaders({ "content-type": "application/json", "cache-control": "no-cache", }); self.apiUrl = OctoPrint.getSimpleApiUrl("klipper"); self.Url = OctoPrint.getBlueprintUrl("klipper"); self.markedForFileRestore = ko.observableArray([]); self.CfgContent = ko.observable(); //uploads self.maxUploadSize = ko.observable(0); self.backupUploadData = undefined; self.backupUploadName = ko.observable(); self.isAboveUploadSize = function (data) { return data.size > self.maxUploadSize(); }; self.onStartupComplete = function () { $('#klipper_backups_dialog').css('display', 'none'); if (self.loginState.loggedIn()) { self.listBakFiles(); } }; // initialize list helper self.backups = new ItemListHelper( "klipperBakFiles", { name: function (a, b) { // sorts ascending if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1; if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1; return 0; }, date: function (a, b) { // sorts descending if (a["date"] > b["date"]) return -1; if (a["date"] < b["date"]) return 1; return 0; }, size: function (a, b) { // sorts descending if (a["bytes"] > b["bytes"]) return -1; if (a["bytes"] < b["bytes"]) return 1; return 0; }, }, {}, "name", [], [], 5 ); self.listBakFiles = function () { self.klipperViewModel.consoleMessage("debug", "listBakFiles"); OctoPrint.plugins.klipper.listCfgBak() .done(function (response) { self.backups.updateItems(response.files); self.backups.resetPage(); }); }; self.showCfg = function (backup) { if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return; OctoPrint.plugins.klipper.getCfgBak(backup).done(function (response) { $('#klipper_backups_dialog textarea').attr('rows', response.response.config.split(/\r\n|\r|\n/).length); self.CfgContent(response.response.config); }); }; self.removeCfg = function (backup) { if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return; var perform = function () { OctoPrint.plugins.klipper .deleteBackup(backup) .done(function () { self.listBakFiles(); }) .fail(function (response) { var html = "

" + _.sprintf(gettext("Failed to remove config %(name)s.

Please consult octoprint.log for details.

"), { name: _.escape(backup) }); html += pnotifyAdditionalInfo('
' + _.escape(response.responseText) + "
"); new PNotify({ title: gettext("Could not remove config"), text: html, type: "error", hide: false, }); }); }; showConfirmationDialog( _.sprintf(gettext('You are about to delete backed config file "%(name)s".'), { name: _.escape(backup), }), perform ); }; self.restoreBak = function (backup) { if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return; var restore = function () { OctoPrint.plugins.klipper.restoreBackup(backup).done(function (response) { self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + backup + " / " + response.restored); }); }; var html = "

" + gettext("This will overwrite any file with the same name on the configpath.") + "

" + "

" + backup + "

"; showConfirmationDialog({ title: gettext("Are you sure you want to restore now?"), html: html, proceed: gettext("Proceed"), onproceed: restore, }); }; self.markFilesOnPage = function () { self.markedForFileRestore(_.uniq(self.markedForFileRestore().concat(_.map(self.backups.paginatedItems(), "file")))); }; self.markAllFiles = function () { self.markedForFileRestore(_.map(self.backups.allItems, "file")); }; self.clearMarkedFiles = function () { self.markedForFileRestore.removeAll(); }; self.restoreMarkedFiles = function () { var perform = function () { self._bulkRestore(self.markedForFileRestore()).done(function () { self.markedForFileRestore.removeAll(); }); }; showConfirmationDialog( _.sprintf(gettext("You are about to restore %(count)d backed config files."), { count: self.markedForFileRestore().length, }), perform ); }; self.removeMarkedFiles = function () { var perform = function () { self._bulkRemove(self.markedForFileRestore()).done(function () { self.markedForFileRestore.removeAll(); }); }; showConfirmationDialog( _.sprintf(gettext("You are about to delete %(count)d backed config files."), { count: self.markedForFileRestore().length, }), perform ); }; self._bulkRestore = function (files) { var title, message, handler; title = gettext("Restoring klipper config files"); self.klipperViewModel.consoleMessage("debug", title); message = _.sprintf(gettext("Restoring %(count)d backed config files..."), { count: files.length, }); handler = function (filename) { return OctoPrint.plugins.klipper .restoreBackup(filename) .done(function (response) { deferred.notify( _.sprintf(gettext("Restored %(filename)s..."), { filename: _.escape(filename), }), true ); self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + filename + " / " + response); self.markedForFileRestore.remove(function (item) { return item.name == filename; }); }) .fail(function () { deferred.notify(_.sprintf(gettext("Restoring of %(filename)s failed, continuing..."), { filename: _.escape(filename) }), false); }); }; var deferred = $.Deferred(); var promise = deferred.promise(); var options = { title: title, message: message, max: files.length, output: true, }; showProgressModal(options, promise); var requests = []; _.each(files, function (filename) { var request = handler(filename); requests.push(request); }); $.when.apply($, _.map(requests, wrapPromiseWithAlways)).done(function () { deferred.resolve(); }); return promise; }; self._bulkRemove = function (files) { var title, message, handler; title = gettext("Deleting backup files"); message = _.sprintf(gettext("Deleting %(count)d backed files..."), { count: files.length, }); handler = function (filename) { return OctoPrint.plugins.klipper .deleteBackup(filename) .done(function () { deferred.notify(_.sprintf(gettext("Deleted %(filename)s..."), { filename: _.escape(filename) }), true); self.markedForFileRestore.remove(function (item) { return item.name == filename; }); }) .fail(function () { deferred.notify(_.sprintf(gettext("Deleting of %(filename)s failed, continuing..."), { filename: _.escape(filename) }), false); }); }; var deferred = $.Deferred(); var promise = deferred.promise(); var options = { title: title, message: message, max: files.length, output: true, }; showProgressModal(options, promise); var requests = []; _.each(files, function (filename) { var request = handler(filename); requests.push(request); }); $.when.apply($, _.map(requests, wrapPromiseWithAlways)).done(function () { deferred.resolve(); self.listBakFiles(); }); return promise; }; } OCTOPRINT_VIEWMODELS.push({ construct: KlipperBackupViewModel, dependencies: ["loginStateViewModel", "klipperViewModel", "accessViewModel"], elements: ["#klipper_backups_dialog"], }); });