diff --git a/octoprint_klipper/__init__.py b/octoprint_klipper/__init__.py index 20e84e4..4cc2688 100644 --- a/octoprint_klipper/__init__.py +++ b/octoprint_klipper/__init__.py @@ -139,6 +139,7 @@ class KlipperPlugin( old_config="", logpath="/tmp/klippy.log", reload_command="RESTART", + restart_onsave=False, shortStatus_navbar=True, shortStatus_sidebar=True, parse_check=False, @@ -146,40 +147,7 @@ class KlipperPlugin( ) ) - def on_settings_load(self): - data = octoprint.plugin.SettingsPlugin.on_settings_load(self) - - configpath = os.path.expanduser( - self._settings.get(["configuration", "configpath"]) - ) - standardconfigfile = os.path.join(configpath, "printer.cfg") - data["config"] = cfgUtils.get_cfg(self, standardconfigfile) - util.send_message(self, "reload", "config", "", data["config"]) - # send the configdata to frontend to update ace editor - return data - def on_settings_save(self, data): - if "config" in data: - if cfgUtils.save_cfg(self, data["config"], "printer.cfg"): - #load the reload command from changed data if it is not existing load the saved setting - if util.key_exist(data, "configuration", "reload_command"): - reload_command = os.path.expanduser( - data["configuration"]["reload_command"] - ) - else: - reload_command = self._settings.get(["configuration", "reload_command"]) - - if reload_command != "manually": - # Restart klippy to reload config - self._printer.commands(reload_command) - logger.log_info(self, "Restarting Klipper.") - # we dont want to write the klipper conf to the octoprint settings - else: - # save not sure. saving to the octoprintconfig: - self._settings.set(["configuration", "temp_config"], data) - data.pop("config", None) - - # save the rest of changed settings into config.yaml of octoprint old_debug_logging = self._settings.get_boolean(["configuration", "debug_logging"]) octoprint.plugin.SettingsPlugin.on_settings_save(self, data) @@ -205,6 +173,10 @@ class KlipperPlugin( ) def get_settings_version(self): + # Settings_Versionhistory: + # 3 = add shortstatus on navbar. migrate the navbar setting for this + # 4 = -change of configpath to only path without filename + # -add setting for restart checkbox on editor save return 4 @@ -213,35 +185,43 @@ class KlipperPlugin( settings = self._settings if current is None: self.migrate_old_settings(settings) + if current is not None and current < 3: - self.migrate_configuration( + self.migrate_settings_configuration( settings, "shortStatus_navbar", "navbar", ) if current is not None and current < 4: - self.migrate_configuration( + self.migrate_settings_configuration( settings, "old_config", "temp_config", ) - setting_path = settings.get(["configuration", "configpath"]) - if setting_path.find("printer.cfg")!=-1: - new_setting_path = setting_path.replace("printer.cfg","") - logger.log_info(self, "migrate setting for 'configuration/configpath': " + setting_path + " -> " + new_setting_path) - settings.set(["configuration", "configpath"], new_setting_path) + cfg_path = settings.get(["configuration", "configpath"]) + if cfg_path.find("printer.cfg") != -1: + new_cfg_path = cfg_path.replace("printer.cfg","") + logger.log_info(self, "migrate setting for 'configuration/configpath': " + cfg_path + " -> " + new_cfg_path) + settings.set(["configuration", "configpath"], new_cfg_path) + + if settings.get(["configuration", "reload_command"]) != "manually" : + logger.log_info(self, "migrate setting for 'configuration/restart_onsave': False -> True") + settings.set(["configuration", "restart_onsave"], True) + def migrate_old_settings(self, settings): - + ''' + For Old settings + ''' self.migrate_settings(settings, "serialport", "connection", "port") self.migrate_settings(settings, "replace_connection_panel", "connection", "replace_connection_panel") self.migrate_settings(settings, "probeHeight", "probe", "height") self.migrate_settings(settings, "probeLift", "probe", "lift") self.migrate_settings(settings, "probeSpeedXy", "probe", "speed_xy") self.migrate_settings(settings, "probeSpeedZ", "probe", "speed_z") - self.migrate_settings(settings, "configPath", "configpath") + self.migrate_settings(settings, "configPath", "configuration", "configpath") if settings.has(["probePoints"]): points = settings.get(["probePoints"]) @@ -250,6 +230,14 @@ class KlipperPlugin( settings.remove(["probePoints"]) def migrate_settings(self, settings, old, new, new2="") -> None: + """migrate setting to setting with additional group + + Args: + settings (any): instance of self._settings + old (str): the old setting to migrate + new (str): group or only new setting if there is no new2 + new2 (str, optional): the new setting to migrate to. Defaults to "". + """ '''''' if settings.has([old]): if new2 != "": logger.log_info(self, "migrate setting for '" + old + "' -> '" + new + "/" + new2 + "'") @@ -574,6 +562,20 @@ class KlipperPlugin( if saved == True: util.send_message(self, "reload", "configlist", "", "") return flask.jsonify(saved = saved) + + # restart klipper + @octoprint.plugin.BlueprintPlugin.route("/restart", methods=["POST"]) + @restricted_access + @Permissions.PLUGIN_KLIPPER_CONFIG.require(403) + def restart_klipper(self): + reload_command = self._settings.get(["configuration", "reload_command"]) + + if reload_command != "manually": + + # Restart klippy to reload config + self._printer.commands(reload_command) + logger.log_info(self, "Restarting Klipper.") + return NO_CONTENT # APIs end diff --git a/octoprint_klipper/cfgUtils.py b/octoprint_klipper/cfgUtils.py index 7cf2959..f6bc465 100644 --- a/octoprint_klipper/cfgUtils.py +++ b/octoprint_klipper/cfgUtils.py @@ -113,34 +113,35 @@ def save_cfg(self, content, filename="printer.cfg"): if sys.version_info[0] < 3: content = content.encode('utf-8') - check_parse = self._settings.get(["configuration", "parse_check"]) - logger.log_debug(self, "check_parse on filesave: {}".format(check_parse)) + configpath = os.path.expanduser(self._settings.get(["configuration", "configpath"])) + if filename[-4:] != ".cfg": + filename += ".cfg" filepath = os.path.join(configpath, filename) logger.log_debug(self, "save filepath: {}".format(filepath)) self._settings.set(["configuration", "temp_config"], content) - check = True - if check_parse: - check=check_cfg(self, content) - if check == True: - try: - logger.log_debug(self, "Writing Klipper config to {}".format(filepath)) - with open(filepath, "w") as f: - f.write(content) - except IOError: - logger.log_error(self, "Error: Couldn't open Klipper config file: {}".format(filepath)) - return False - else: - logger.log_debug(self, "Writen Klipper config to {}".format(filepath)) - return True - finally: - f.close() - copy_cfg_to_backup(self, filepath) - else: + + check_parse = self._settings.get(["configuration", "parse_check"]) + logger.log_debug(self, "check_parse on filesave: {}".format(check_parse)) + if check_parse and not check_cfg(self, content): return False + try: + logger.log_debug(self, "Writing Klipper config to {}".format(filepath)) + with open(filepath, "w") as f: + f.write(content) + except IOError: + logger.log_error(self, "Error: Couldn't open Klipper config file: {}".format(filepath)) + return False + else: + logger.log_debug(self, "Writen Klipper config to {}".format(filepath)) + return True + finally: + f.close() + copy_cfg_to_backup(self, filepath) + def check_cfg(self, data): """Checks the given data on parsing errors. @@ -158,37 +159,46 @@ def check_cfg(self, data): dataToValidated.readfp(buf) else: dataToValidated.read_string(data) - is_float_ok(self, dataToValidated) except configparser.Error as error: - error.message = error.message.replace("\\n","") - if sys.version_info[0] < 3: - error.message = error.message.replace("file: u","Klipper Configuration", 1) - error.message = error.message.replace("'","", 2) - error.message = error.message.replace("u'","'", 1) - - else: - error.message = error.message.replace("file:","Klipper Configuration", 1) - error.message = error.message.replace("'","", 2) - logger.log_error( - self, - "Error: Invalid Klipper config file:\n" - + "{}".format(str(error)) - ) - util.send_message(self, "PopUp", "warning", "Invalid Config data\n", - "\n" - + str(error)) - + show_error_message(self, error) + logger.log_debug(self, 'check_cfg: NOK!') return False else: + if not is_float_ok(self, dataToValidated): + logger.log_debug(self, "check_cfg: NOK!") + return False + logger.log_debug(self, "check_cfg: OK") return True +def show_error_message(self, error): + error.message = error.message.replace('\\n', '') + if sys.version_info[0] < 3: + error.message = error.message.replace('file: u', 'Klipper Configuration', 1) + error.message = error.message.replace("'", '', 2) + error.message = error.message.replace("u'", "'", 1) + else: + error.message = error.message.replace('file:', 'Klipper Configuration', 1) + error.message = error.message.replace("'", '', 2) + logger.log_error( + self, + ('Error: Invalid Klipper config file:\n' + '{}'.format(str(error))), + ) + + util.send_message( + self, 'PopUp', 'warning', 'Invalid Config data\n', ('\n' + str(error)) + ) + def is_float_ok(self, dataToValidated): - sections_search_list = ["bltouch", - "probe"] - value_search_list = ["x_offset", - "y_offset", - "z_offset"] + sections_search_list = [ + "bltouch", + "probe" + ] + value_search_list = [ + "x_offset", + "y_offset", + "z_offset" + ] try: # cycle through sections and then values for y in sections_search_list: diff --git a/octoprint_klipper/static/clientjs/klipper.js b/octoprint_klipper/static/clientjs/klipper.js index aedc85d..26c01b6 100644 --- a/octoprint_klipper/static/clientjs/klipper.js +++ b/octoprint_klipper/static/clientjs/klipper.js @@ -1,72 +1,76 @@ (function (global, factory) { - if (typeof define === "function" && define.amd) { - define(["OctoPrintClient"], factory); - } else { - factory(global.OctoPrintClient); - } + if (typeof define === "function" && define.amd) { + define(["OctoPrintClient"], factory); + } else { + factory(global.OctoPrintClient); + } })(this, function (OctoPrintClient) { - var OctoKlipperClient = function (base) { - this.base = base; - this.url = this.base.getBlueprintUrl("klipper"); - }; + var OctoKlipperClient = function (base) { + this.base = base; + this.url = this.base.getBlueprintUrl("klipper"); + }; - OctoKlipperClient.prototype.getCfg = function (config, opts) { - return this.base.get(this.url + "config/" + config, opts); - }; + OctoKlipperClient.prototype.restartKlipper = function (opts) { + return this.base.post(this.url + "restart", opts); + }; - OctoKlipperClient.prototype.getCfgBak = function (backup, opts) { - return this.base.get(this.url + "backup/" + backup, opts); - }; + OctoKlipperClient.prototype.getCfg = function (config, opts) { + return this.base.get(this.url + "config/" + config, opts); + }; - OctoKlipperClient.prototype.listCfg = function (opts) { - return this.base.get(this.url + "config/list", opts); - }; + OctoKlipperClient.prototype.getCfgBak = function (backup, opts) { + return this.base.get(this.url + "backup/" + backup, opts); + }; - OctoKlipperClient.prototype.listCfgBak = function (opts) { - return this.base.get(this.url + "backup/list", opts); - }; + OctoKlipperClient.prototype.listCfg = function (opts) { + return this.base.get(this.url + "config/list", opts); + }; - OctoKlipperClient.prototype.checkCfg = function (content, opts) { - content = content || []; + OctoKlipperClient.prototype.listCfgBak = function (opts) { + return this.base.get(this.url + "backup/list", opts); + }; - var data = { - DataToCheck: content, - }; + OctoKlipperClient.prototype.checkCfg = function (content, opts) { + content = content || []; - return this.base.postJson(this.url + "config/check", data, opts); - }; + var data = { + DataToCheck: content, + }; - OctoKlipperClient.prototype.saveCfg = function (content, filename, opts) { - content = content || []; - filename = filename || []; + return this.base.postJson(this.url + "config/check", data, opts); + }; - var data = { - DataToSave: content, - filename: filename, - }; + OctoKlipperClient.prototype.saveCfg = function (content, filename, opts) { + content = content || []; + filename = filename || []; - return this.base.postJson(this.url + "config/save", data, opts); - }; + var data = { + DataToSave: content, + filename: filename, + }; - OctoKlipperClient.prototype.deleteCfg = function (config, opts) { - return this.base.delete(this.url + "config/" + config, opts); - }; + return this.base.postJson(this.url + "config/save", data, opts); + }; - OctoKlipperClient.prototype.deleteBackup = function (backup, opts) { - return this.base.delete(this.url + "backup/" + backup, opts); - }; + OctoKlipperClient.prototype.deleteCfg = function (config, opts) { + return this.base.delete(this.url + "config/" + config, opts); + }; - OctoKlipperClient.prototype.restoreBackup = function (backup, opts) { - return this.base.get(this.url + "backup/restore/" + backup, opts); - }; + OctoKlipperClient.prototype.deleteBackup = function (backup, opts) { + return this.base.delete(this.url + "backup/" + backup, opts); + }; - OctoKlipperClient.prototype.restoreBackupFromUpload = function (file, data) { - data = data || {}; + OctoKlipperClient.prototype.restoreBackup = function (backup, opts) { + return this.base.get(this.url + "backup/restore/" + backup, opts); + }; - var filename = data.filename || undefined; - return this.base.upload(this.url + "restore", file, filename, data); - }; + OctoKlipperClient.prototype.restoreBackupFromUpload = function (file, data) { + data = data || {}; - OctoPrintClient.registerPluginComponent("klipper", OctoKlipperClient); - return OctoKlipperClient; + var filename = data.filename || undefined; + return this.base.upload(this.url + "restore", file, filename, data); + }; + + OctoPrintClient.registerPluginComponent("klipper", OctoKlipperClient); + return OctoKlipperClient; }); diff --git a/octoprint_klipper/static/css/klipper.css b/octoprint_klipper/static/css/klipper.css index 2b517d1..445c932 100644 --- a/octoprint_klipper/static/css/klipper.css +++ b/octoprint_klipper/static/css/klipper.css @@ -256,47 +256,40 @@ div#settings_plugin_klipper div.tab-content div#conf.tab-pane div.control-group @media (max-width: 979px) { - div#klipper_editor.modal { + /* div#klipper_editor.modal { height: unset !important; + } */ + + div#klipper_editor .modal-footer .btn { + margin-bottom: 1px; + margin-left: 5px; } } -#klipper_editor { - - display: flex; - flex-flow: column; -} .octoprint-container.UICMainCont.container-fluid { margin-top:0px !important; } +div#klipper_editor .modal-header div button.btn + button.btn { + margin-right: 12px; +} + div#klipper_editor .modal-body { overflow: auto; - display: flex; - flex-flow: column; } .klipper-btn-group { display: inline-block; } -div#klipper_editor .modal-body label.checkbox { - display: unset; -} - -div#klipper_editor .modal-body input[type="text"] { +div#klipper_editor .modal-footer input[type="text"] { margin-bottom: 0px !important; } -div#klipper_editor .modal-body input[type="checkbox"] { - float: unset; - margin-left: unset; - vertical-align: unset; -} -div#klipper_editor .modal-body .editor-controls { +div#klipper_editor .modal-footer .editor-controls { flex: 0 auto; display: flex; align-items: center; @@ -308,29 +301,17 @@ div#klipper_editor div.conf-editor { width: calc(100% - 4px); margin-top: 5px; overflow: auto; - flex-grow : 1; } div#klipper_editor div.conf-editor div#plugin-klipper-config { font-family: monospace; overflow: auto; -} - -.ace_editor { - margin: auto; - height: 200px; width: 100%; + margin: auto; } -/* div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div#conf.tab-pane.active button.btn.btn-small ,div#klipper_editor button.btn.btn-small{ - width: 30%; - display: inline-block; - margin: 0px 2px 2px 2px; -} */ - /*checkboxes*/ -div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div.tab-pane.active input.inline-checkbox, -div#klipper_editor input.inline-checkbox { +div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content div.tab-pane.active input.inline-checkbox { vertical-align: -0.2em; } @@ -343,10 +324,6 @@ div#settings_plugin_klipper.tab-pane.active form.form-horizontal div.tab-content margin-top: 8px; } -div#settings_plugin_klipper div#basic label.checkbox { - padding-left: 0px; -} - /*macros*/ div#settings_plugin_klipper div#macros label.control-label { width: 80px; diff --git a/octoprint_klipper/static/js/klipper.js b/octoprint_klipper/static/js/klipper.js index 261d8b6..2d3eacb 100644 --- a/octoprint_klipper/static/js/klipper.js +++ b/octoprint_klipper/static/js/klipper.js @@ -51,27 +51,12 @@ $(function () { }); }; - self.onStartupComplete = function () { - var klipper_editor = $('#klipper_editor') - var modalOverflow = $(window).height() - 10 < klipper_editor.height(); - - klipper_editor.css('display', 'none'); - if (modalOverflow) { - klipper_editor - .css('margin-top', 0) - .addClass('modal-overflow'); - } else { - klipper_editor - .css('margin-top', 0 - klipper_editor.height() / 2) - .removeClass('modal-overflow'); - } - }; - self.showEditorDialog = function () { if (!self.hasRight("CONFIG")) return; var editorDialog = $("#klipper_editor"); editorDialog.modal({ show: "true", + width: "90%", backdrop: "static", }); } @@ -162,6 +147,8 @@ $(function () { case "PopUp": self.showPopUp(data.subtype, data.title, data.payload); break; + case "start": + break; case "reload": break; case "console": @@ -245,6 +232,25 @@ $(function () { } }; + self.requestRestart = function () { + if (!self.loginState.hasPermission(self.access.permissions.PLUGIN_KLIPPER_CONFIG)) return; + + var request = function () { + OctoPrint.plugins.klipper.restartKlipper().done(function () { + self.consoleMessage("debug", "requestRestart"); + }); + }; + + var html = "

" + gettext("All ongoing Prints will be stopped!") + "

"; + + showConfirmationDialog({ + title: gettext("Klipper restart?"), + html: html, + proceed: gettext("Proceed"), + onproceed: request, + }); + }; + // OctoKlipper settings link self.openOctoKlipperSettings = function (profile_type) { if (!self.hasRight("CONFIG")) return; @@ -256,6 +262,10 @@ $(function () { $(query).click(); } }; + + self.sleep = function (ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + }; } OCTOPRINT_VIEWMODELS.push({ diff --git a/octoprint_klipper/static/js/klipper_backup.js b/octoprint_klipper/static/js/klipper_backup.js index fd2a977..dbf1010 100644 --- a/octoprint_klipper/static/js/klipper_backup.js +++ b/octoprint_klipper/static/js/klipper_backup.js @@ -79,11 +79,10 @@ $(function () { ); self.listBakFiles = function () { - self.klipperViewModel.consoleMessage("debug", "listBakFiles:"); + self.klipperViewModel.consoleMessage("debug", "listBakFiles"); OctoPrint.plugins.klipper.listCfgBak() .done(function (response) { - self.klipperViewModel.consoleMessage("debug", "listBakFilesdone: " + response); self.backups.updateItems(response.files); self.backups.resetPage(); }); @@ -132,7 +131,7 @@ $(function () { var restore = function () { OctoPrint.plugins.klipper.restoreBackup(backup).done(function (response) { - self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + response.text); + self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + backup + " / " + response.restored); }); }; @@ -142,7 +141,7 @@ $(function () { title: gettext("Are you sure you want to restore now?"), html: html, proceed: gettext("Proceed"), - onproceed: restore(), + onproceed: restore, }); }; @@ -207,7 +206,7 @@ $(function () { }), true ); - self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + response.text); + self.klipperViewModel.consoleMessage("debug", "restoreCfg: " + filename + " / " + response); self.markedForFileRestore.remove(function (item) { return item.name == filename; }); diff --git a/octoprint_klipper/static/js/klipper_editor.js b/octoprint_klipper/static/js/klipper_editor.js index 04a71b0..bd4d0e2 100644 --- a/octoprint_klipper/static/js/klipper_editor.js +++ b/octoprint_klipper/static/js/klipper_editor.js @@ -18,6 +18,7 @@ $(function () { var self = this; var obKlipperConfig = null; var editor = null; + var editor_dirty = false; self.settings = parameters[0]; self.klipperViewModel = parameters[1]; @@ -31,56 +32,122 @@ $(function () { "cache-control": "no-cache", }); - self.process = function (config) { - self.config = config; - self.CfgFilename(config.file); - self.CfgContent(config.content); + $('#klipper_editor').on('shown.bs.modal', function () { + editor.focus(); + self.setEditorDivSize(); + $(window).on('resize', function(){ + self.klipperViewModel.sleep(500).then( + function () { + self.setEditorDivSize(); + } + ); + }); + }); + self.closeEditor = function () { + if (editor_dirty===true) { + showConfirmationDialog({ + message: gettext( + "Your file seems to have changed." + ), + question: gettext("Do you really want to close it?"), + cancel: gettext("No"), + proceed: gettext("Yes"), + onproceed: function () { + var dialog = $("#klipper_editor"); + dialog.modal('hide'); + }, + nofade: true + }); + } else { + var dialog = $("#klipper_editor"); + dialog.modal('hide'); + } + } + + self.addStyleAttribute = function ($element, styleAttribute) { + $element.attr('style', $element.attr('style') + '; ' + styleAttribute); + } + + self.setEditorDivSize = function () { + var klipper_modal_body= $('#klipper_editor .modal-body'); + var klipper_config= $('#plugin-klipper-config'); + + var height = $(window).height() - $('#klipper_editor .modal-header').outerHeight() - $('#klipper_editor .modal-footer').outerHeight() - 118; + self.addStyleAttribute(klipper_modal_body, 'height: ' + height + 'px !important;'); + //self.addStyleAttribute(klipper_config, 'height: ' + height + 'px !important;'); + klipper_config.css('height', height); if (editor) { - editor.session.setValue(config.content); - self.settings.settings.plugins.klipper.configuration.old_config(config.content); - editor.clearSelection(); + editor.resize(); } }; + self.process = function (config) { + return new Promise(function (resolve) { + self.config = config; + self.CfgFilename(config.file); + self.CfgContent(config.content); + + if (editor) { + editor.session.setValue(self.CfgContent()); + editor_dirty=false; + editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize()); + self.settings.settings.plugins.klipper.configuration.old_config(config.content); + editor.clearSelection(); + self.klipperViewModel.sleep(500).then( + function() { + self.setEditorDivSize(); + resolve("done"); + } + ); + } + }); + } + self.checkSyntax = function () { if (editor.session) { - self.klipperViewModel.consoleMessage("debug", "checkSyntax:"); + self.klipperViewModel.consoleMessage("debug", "checkSyntax started"); OctoPrint.plugins.klipper.checkCfg(editor.session.getValue()) .done(function (response) { var msg = "" if (response.is_syntax_ok == true) { self.klipperViewModel.showPopUp("success", gettext("SyntaxCheck"), gettext("SyntaxCheck OK")); + self.editorFocusDelay(1000); } else { msg = gettext('Syntax NOK') showMessageDialog( msg, { - title: gettext("SyntaxCheck") + title: gettext("SyntaxCheck"), + onclose: function () { self.editorFocusDelay(1000); } } - ) + ); } - }); }; }; self.saveCfg = function () { if (editor.session) { - self.klipperViewModel.consoleMessage("debug", "Save:"); + self.klipperViewModel.consoleMessage("debug", "SaveCfg start"); OctoPrint.plugins.klipper.saveCfg(editor.session.getValue(), self.CfgFilename()) .done(function (response) { var msg = "" if (response.saved === true) { self.klipperViewModel.showPopUp("success", gettext("Save Config"), gettext("File saved.")); + editor_dirty = false; + if (self.settings.settings.plugins.klipper.configuration.restart_onsave()==true) { + self.klipperViewModel.requestRestart(); + } } else { msg = gettext('File not saved!') showMessageDialog( msg, { - title: gettext("Save Config") + title: gettext("Save Config"), + onclose: function () { self.editorFocusDelay(1000); } } ) } @@ -138,7 +205,7 @@ $(function () { OctoPrint.plugins.klipper.getCfg(self.CfgFilename()) .done(function (response) { - self.klipperViewModel.consoleMessage("debug", "reloadFromFile: " + response); + self.klipperViewModel.consoleMessage("debug", "reloadFromFile done"); if (response.response.text != "") { var msg = response.response.text showMessageDialog( @@ -152,6 +219,7 @@ $(function () { if (editor) { editor.session.setValue(response.response.config); editor.clearSelection(); + editor.focus(); } } }) @@ -166,32 +234,6 @@ $(function () { }); }; - self.configBound = function (config) { - config.withSilence = function () { - this.notifySubscribers = function () { - if (!this.isSilent) { - ko.subscribable.fn.notifySubscribers.apply(this, arguments); - } - } - - this.silentUpdate = function (newValue) { - this.isSilent = true; - this(newValue); - this.isSilent = false; - }; - - return this; - } - - obKlipperConfig = config.withSilence(); - if (editor) { - editor.setValue(obKlipperConfig()); - editor.setFontSize(self.settings.settings.plugins.klipper.configuration.fontsize()); - editor.resize(); - editor.clearSelection(); - } - return obKlipperConfig; - }; self.onStartup = function () { ace.config.set("basePath", "plugin/klipper/static/js/lib/ace/"); @@ -205,18 +247,23 @@ $(function () { vScrollBarAlwaysVisible: false, autoScrollEditorIntoView: true, showPrintMargin: false, - maxLines: "Infinity", - minLines: 100 //maxLines: "Infinity" }); editor.session.on('change', function (delta) { - if (obKlipperConfig) { - obKlipperConfig.silentUpdate(editor.getValue()); - editor.resize(); - } + self.CfgContent(editor.getValue()); + editor_dirty = true; + editor.resize(); }); }; + + self.editorFocusDelay = function (delay) { + self.klipperViewModel.sleep(delay).then( + function () { + editor.focus(); + } + ); + }; } OCTOPRINT_VIEWMODELS.push({ diff --git a/octoprint_klipper/static/js/klipper_settings.js b/octoprint_klipper/static/js/klipper_settings.js index 6103da3..8c2f8a7 100644 --- a/octoprint_klipper/static/js/klipper_settings.js +++ b/octoprint_klipper/static/js/klipper_settings.js @@ -38,6 +38,7 @@ $(function () { self.settings.settings.plugins.klipper.configuration.fontsize(9) } } + // initialize list helper self.configs = new ItemListHelper( "klipperCfgFiles", @@ -70,18 +71,31 @@ $(function () { self.onStartupComplete = function () { self.listCfgFiles(); + self.loadBaseConfig(); }; self.listCfgFiles = function () { - self.klipperViewModel.consoleMessage("debug", "listCfgFiles:"); + self.klipperViewModel.consoleMessage("debug", "listCfgFiles started"); OctoPrint.plugins.klipper.listCfg().done(function (response) { - self.klipperViewModel.consoleMessage("debug", "listCfgFiles: " + response); + self.klipperViewModel.consoleMessage("debug", "listCfgFiles done"); self.configs.updateItems(response.files); self.configs.resetPage(); }); }; + self.loadBaseConfig = function () { + if (!self.klipperViewModel.hasRight("CONFIG")) return; + + OctoPrint.plugins.klipper.getCfg("printer.cfg").done(function (response) { + var config = { + content: response.response.config, + file: "printer.cfg", + }; + self.klipperEditorViewModel.process(config).then(); + }); + }; + self.removeCfg = function (config) { if (!self.klipperViewModel.hasRight("CONFIG")) return; @@ -190,7 +204,7 @@ $(function () { }; self.showBackupsDialog = function () { - self.klipperViewModel.consoleMessage("debug", "showBackupsDialog:"); + self.klipperViewModel.consoleMessage("debug", "showBackupsDialog"); self.klipperBackupViewModel.listBakFiles(); var dialog = $("#klipper_backups_dialog"); dialog.modal({ @@ -198,21 +212,29 @@ $(function () { }); }; + self.showEditor = function () { + if (!self.klipperViewModel.hasRight("CONFIG")) return; + + var editorDialog = $("#klipper_editor"); + editorDialog.modal({ + show: "true", + width: "90%", + backdrop: "static", + }); + } + self.newFile = function () { if (!self.klipperViewModel.hasRight("CONFIG")) return; var config = { content: "", file: "Change Filename", }; - self.klipperEditorViewModel.process(config); - var editorDialog = $("#klipper_editor"); - editorDialog.modal({ - show: "true", - backdrop: "static", - }); + self.klipperEditorViewModel.process(config).then( + function() { self.showEditor(); } + ); }; - self.showEditUserDialog = function (file) { + self.openConfig = function (file) { if (!self.klipperViewModel.hasRight("CONFIG")) return; OctoPrint.plugins.klipper.getCfg(file).done(function (response) { @@ -220,23 +242,11 @@ $(function () { content: response.response.config, file: file, }; - self.klipperEditorViewModel.process(config); + self.klipperEditorViewModel.process(config).then( + function() { self.showEditor(); } + ); - var editorDialog = $("#klipper_editor"); - editorDialog.modal({ - show: "true", - backdrop: "static", - }); - }); - }; - self.showEditor = function () { - if (!self.klipperViewModel.hasRight("CONFIG")) return; - - var editorDialog = $("#klipper_editor"); - editorDialog.modal({ - show: "true", - backdrop: "static", }); }; @@ -302,8 +312,21 @@ $(function () { if (plugin == "klipper" && data.type == "reload" && data.subtype == "configlist") { self.klipperViewModel.consoleMessage("debug", "onDataUpdaterPluginMessage klipper reload configlist"); self.listCfgFiles(); + } else if (plugin == "klipper" && data.type == "start" && data.subtype == "config") { + self.klipperViewModel.consoleMessage("debug", "onDataUpdaterPluginMessage klipper start config"); + self.startConfig(data.title, data.payload); } }; + + self.startConfig = function (file, content) { + if (!self.klipperViewModel.hasRight("CONFIG")) return; + filename = file || ""; + var config = { + content: content, + file: filename, + }; + self.klipperEditorViewModel.process(config).then(); + }; } OCTOPRINT_VIEWMODELS.push({ diff --git a/octoprint_klipper/templates/klipper_backups_dialog.jinja2 b/octoprint_klipper/templates/klipper_backups_dialog.jinja2 index 90073db..1754550 100644 --- a/octoprint_klipper/templates/klipper_backups_dialog.jinja2 +++ b/octoprint_klipper/templates/klipper_backups_dialog.jinja2 @@ -84,7 +84,7 @@  |  - @@ -104,7 +104,7 @@
- +
diff --git a/octoprint_klipper/templates/klipper_editor.jinja2 b/octoprint_klipper/templates/klipper_editor.jinja2 index 8a0fec4..ccf4e1a 100644 --- a/octoprint_klipper/templates/klipper_editor.jinja2 +++ b/octoprint_klipper/templates/klipper_editor.jinja2 @@ -1,41 +1,46 @@ -
@@ -246,7 +247,7 @@ {{ _('New File') }}