From d294fa57240a1ce9db1e0a14035ed3dda0d4b14f Mon Sep 17 00:00:00 2001 From: sergiuToporjinschi Date: Sat, 5 Feb 2022 13:44:49 +0200 Subject: [PATCH] -refactoring js files, -implementing 3 decimal observer -reusing load steps and save steps event -adding settings for xyzSteps -subsection macro default spacing = true --- octoprint_CalibrationTools/EStepsApi.py | 25 +- octoprint_CalibrationTools/__init__.py | 17 +- .../js/{ESteps.js => EStepsViewModel.js} | 6 +- .../static/js/GeneralViewModel.js | 37 + .../static/js/XYZStepsViewModel.js | 94 +++ octoprint_CalibrationTools/static/js/test.js | 694 ++++++++++++++++++ .../CalibrationTools_settings.jinja2 | 12 +- .../templates/CalibrationTools_tab.jinja2 | 4 +- .../templates/macros.jinja2 | 4 +- .../templates/tabs/tab-content.jinja2 | 4 +- .../templates/tabs/tab-esteps.jinja2 | 4 +- .../templates/tabs/tab-pid.jinja2 | 6 +- .../templates/tabs/tab-xyz.jinja2 | 91 ++- 13 files changed, 971 insertions(+), 27 deletions(-) rename octoprint_CalibrationTools/static/js/{ESteps.js => EStepsViewModel.js} (96%) create mode 100644 octoprint_CalibrationTools/static/js/GeneralViewModel.js create mode 100644 octoprint_CalibrationTools/static/js/XYZStepsViewModel.js create mode 100644 octoprint_CalibrationTools/static/js/test.js diff --git a/octoprint_CalibrationTools/EStepsApi.py b/octoprint_CalibrationTools/EStepsApi.py index c221e30..e0488f8 100644 --- a/octoprint_CalibrationTools/EStepsApi.py +++ b/octoprint_CalibrationTools/EStepsApi.py @@ -16,7 +16,7 @@ class API(octoprint.plugin.SimpleApiPlugin): @staticmethod def apiCommands(): return { - CMD_ESTEPS_SAVE: ['newESteps'], + CMD_ESTEPS_SAVE: [], CMD_ESTEPS_LOAD_STEPS: [], CMD_ESTEPS_START_EXTRUSION: ['extrudeLength','extrudeSpeed','extrudeTemp'] } @@ -56,11 +56,26 @@ class API(octoprint.plugin.SimpleApiPlugin): self._printer.commands("M104 S%(extrudeTemp)s" % data) if command == CMD_ESTEPS_SAVE: - eStepsSettings = self._settings.get(['eSteps']) - userControlsTemp = eStepsSettings.get("userControlsTemp") - turnOffHotend = eStepsSettings.get("turnOffHotend") + if "newESteps" not in data and ("newXSteps" not in data and "newYSteps" not in data and "newZSteps" not in data): + return flask.abort(400, { + "msg": "Invalid arguments. No value provided for X,Y, Z or E steps" + }) + + stopHeater = [] + if "newESteps" in data: + eStepsSettings = self._settings.get(['eSteps']) + userControlsTemp = eStepsSettings.get("userControlsTemp") + turnOffHotend = eStepsSettings.get("turnOffHotend") + stopHeater = ["M104 S0"] if turnOffHotend and not userControlsTemp else [] + + steps = ("M92 " + + ("E%(newESteps)s " % data if "newESteps" in data else "") + + ("X%(newXSteps)s " % data if "newXSteps" in data else "") + + ("Y%(newYSteps)s " % data if "newYSteps" in data else "") + + ("Z%(newYSteps)s " % data if "newZSteps" in data else "")) + #save data to EEPROM and cool-down - self._printer.commands(["M92 E%(newESteps)s" % data, "M500"] + ["M104 S0"] if turnOffHotend and not userControlsTemp else []) + self._printer.commands([steps, "M500"] + stopHeater) return diff --git a/octoprint_CalibrationTools/__init__.py b/octoprint_CalibrationTools/__init__.py index 8689160..31c0519 100644 --- a/octoprint_CalibrationTools/__init__.py +++ b/octoprint_CalibrationTools/__init__.py @@ -14,13 +14,21 @@ defaultSettings = { "extrudeSpeed": 50, "markLength": 120 }, + "XYZSteps": { + "gCodeCubeSize": { + "X":20, + "Y":20, + "Z":20 + } + }, "pid": { "hotEnd":{ "fanSpeed": 255, "noCycles": 8, "hotEndIndex": 0, "targetTemp": 200, - },"bed":{ + }, + "bed":{ "fanSpeed": 255, "noCycles": 8, "hotEndIndex": -1, @@ -55,7 +63,12 @@ class CalibrationtoolsPlugin( # Define your plugin's asset files to automatically include in the # core UI here. return { - "js": ["js/ESteps.js","js/PIDTuneViewModel.js"], + "js": [ + "js/GeneralViewModel.js", + "js/EStepsViewModel.js", + "js/PIDTuneViewModel.js", + "js/XYZStepsViewModel.js" + ], "css": ["css/style.css"] } diff --git a/octoprint_CalibrationTools/static/js/ESteps.js b/octoprint_CalibrationTools/static/js/EStepsViewModel.js similarity index 96% rename from octoprint_CalibrationTools/static/js/ESteps.js rename to octoprint_CalibrationTools/static/js/EStepsViewModel.js index 6ce969e..c3298f8 100644 --- a/octoprint_CalibrationTools/static/js/ESteps.js +++ b/octoprint_CalibrationTools/static/js/EStepsViewModel.js @@ -1,7 +1,6 @@ $(function () { - function CalibrationToolsViewModel(parameters) { + function CalibrationToolsEStepsModelView(parameters) { var self = this; - console.log(gettext("test")); self.loginStateViewModel = parameters[0]; self.settingsViewModel = parameters[1]; self.controlViewModel = parameters[2]; @@ -97,7 +96,6 @@ $(function () { self.onAllBound = self.onEventConnected = function () { OctoPrint.simpleApiGet("CalibrationTools").done(function (response) { - console.log("CalibrationTools"); self.from_json(response); }); } @@ -107,7 +105,7 @@ $(function () { // information to the global variable OCTOPRINT_VIEWMODELS OCTOPRINT_VIEWMODELS.push({ // This is the constructor to call for instantiating the plugin - construct: CalibrationToolsViewModel, + construct: CalibrationToolsEStepsModelView, // This is a list of dependencies to inject into the plugin, the order which you request // here is the order in which the dependencies will be injected into your view model upon // instantiation via the parameters argument diff --git a/octoprint_CalibrationTools/static/js/GeneralViewModel.js b/octoprint_CalibrationTools/static/js/GeneralViewModel.js new file mode 100644 index 0000000..00d4440 --- /dev/null +++ b/octoprint_CalibrationTools/static/js/GeneralViewModel.js @@ -0,0 +1,37 @@ +$(function () { + function CalibrationToolsGeneralViewModel(parameters) { + this.loginState = parameters[0]; + this.decimal3 = function (defaultVal) { + return { + numeric: { + decimals: 3, + default: defaultVal + } + } + } + ko.extenders.numeric = function (target, options) { + var returnObs = ko.pureComputed({ + read: target, + write: function (value) { + var newVal = options.decimals ? parseFloat(value).toFixed(options.decimals) : parseInt(value); + target(isNaN(newVal) ? options.default : newVal); + } + }).extend({ + notify: 'always' + }); + returnObs(target()); + return returnObs; + }; + } + // OCTOPRINT_VIEWMODELS.push([GeneralViewModel, ["loginStateViewModel"], []]); + OCTOPRINT_VIEWMODELS.push({ + // This is the constructor to call for instantiating the plugin + construct: CalibrationToolsGeneralViewModel, + name: "calibrationToolsGeneralViewModel", + // This is a list of dependencies to inject into the plugin, the order which you request + // here is the order in which the dependencies will be injected into your view model upon + // instantiation via the parameters argument + dependencies: ["loginStateViewModel"] + // Finally, this is the list of selectors for all elements we want this view model to be bound to. + }); +}); \ No newline at end of file diff --git a/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js b/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js new file mode 100644 index 0000000..f8dba18 --- /dev/null +++ b/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js @@ -0,0 +1,94 @@ +$(function () { + function CalibrationToolsXYZStepsModelView(parameters) { + var self = this; + self.loginStateViewModel = parameters[0]; + self.settingsViewModel = parameters[1]; + self.controlViewModel = parameters[2]; + generalVM = parameters[5]; + + self.eStepsXYZ = { + currentSteps: { + X: ko.observable(0).extend(generalVM.decimal3(0.000)), + Y: ko.observable(0).extend(generalVM.decimal3(0.000)), + Z: ko.observable(0).extend(generalVM.decimal3(0.000)) + }, + gCodeCubeSize: { + X: ko.observable().extend(generalVM.decimal3(22.000)), + Y: ko.observable().extend(generalVM.decimal3(22.000)), + Z: ko.observable().extend(generalVM.decimal3(22.000)) + }, + printedCubeSize: { + X: ko.observable().extend(generalVM.decimal3(25.000)), + Y: ko.observable().extend(generalVM.decimal3(25.000)), + Z: ko.observable().extend(generalVM.decimal3(25.000)) + }, + newSteps: { + X: ko.observable().extend(generalVM.decimal3(0.000)), + Y: ko.observable().extend(generalVM.decimal3(0.000)), + Z: ko.observable().extend(generalVM.decimal3(0.000)) + } + }; + + self.eStepsXYZ.newSteps.X = ko.computed(function () { + return parseFloat(self.eStepsXYZ.currentSteps.X() * self.eStepsXYZ.gCodeCubeSize.X() / self.eStepsXYZ.printedCubeSize.X()).toFixed(3); + }, self); + self.eStepsXYZ.newSteps.Y = ko.computed(function () { + return parseFloat(self.eStepsXYZ.currentSteps.Y() * self.eStepsXYZ.gCodeCubeSize.Y() / self.eStepsXYZ.printedCubeSize.Y()).toFixed(3); + }, self); + self.eStepsXYZ.newSteps.Z = ko.computed(function () { + return parseFloat(self.eStepsXYZ.currentSteps.Z() * self.eStepsXYZ.gCodeCubeSize.Z() / self.eStepsXYZ.printedCubeSize.Z()).toFixed(3); + }, self); + + self.loadEStepsActive = ko.observable(true); + self.loadESteps = function () { + self.loadEStepsActive(false); + OctoPrint.simpleApiCommand("CalibrationTools", "eSteps_load").done(function (response) { + self.eStepsXYZ.currentSteps.X(response.data.X); + self.eStepsXYZ.currentSteps.Y(response.data.Y); + self.eStepsXYZ.currentSteps.Z(response.data.Z); + }).always(function (response) { + self.loadEStepsActive(true); + }) + }; + + self.saveEStepsXYZActive = ko.observable(true) + self.saveEStepsXYZ = function () { + self.saveEStepsXYZActive(false); + OctoPrint.simpleApiCommand("CalibrationTools", "eSteps_save", { + "newXSteps": self.eStepsXYZ.newSteps.X(), + "newYSteps": self.eStepsXYZ.newSteps.Y(), + "newZSteps": self.eStepsXYZ.newSteps.Z() + }).done(function (response) { + + }).always(function (response) { + self.saveEStepsXYZActive(true); + }) + }; + + + + self.isAdmin = ko.observable(false); + + self.onBeforeBinding = self.onUserLoggedIn = self.onUserLoggedOut = function () { + self.eStepsXYZ.gCodeCubeSize.X(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.X()); + self.eStepsXYZ.gCodeCubeSize.Y(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Y()); + self.eStepsXYZ.gCodeCubeSize.Z(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Z()); + + self.eStepsXYZ.printedCubeSize.X(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.X()); + self.eStepsXYZ.printedCubeSize.Y(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Y()); + self.eStepsXYZ.printedCubeSize.Z(self.settingsViewModel.settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Z()); + + self.isAdmin(self.loginStateViewModel.isAdmin()); + } + } + OCTOPRINT_VIEWMODELS.push({ + // This is the constructor to call for instantiating the plugin + construct: CalibrationToolsXYZStepsModelView, + // This is a list of dependencies to inject into the plugin, the order which you request + // here is the order in which the dependencies will be injected into your view model upon + // instantiation via the parameters argument + dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel", "calibrationToolsGeneralViewModel"], + // Finally, this is the list of selectors for all elements we want this view model to be bound to. + elements: ["#calibration_x-y-z"] + }); +}); \ No newline at end of file diff --git a/octoprint_CalibrationTools/static/js/test.js b/octoprint_CalibrationTools/static/js/test.js new file mode 100644 index 0000000..da537b0 --- /dev/null +++ b/octoprint_CalibrationTools/static/js/test.js @@ -0,0 +1,694 @@ +$(function () { + function AccessViewModel(parameters) { + var access = this; + access.loginState = parameters[0]; + var GROUP_ADMINS = "admins"; + var GROUP_GUESTS = "guests"; + access.users = (function () { + var self = {}; + self.listHelper = new ItemListHelper("users", { + name: function (a, b) { + if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) + return -1; + if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) + return 1; + return 0; + } + }, {}, "name", [], [], CONFIG_USERSPERPAGE); + self.emptyUser = { + name: "", + active: false + }; + self.currentUser = ko.observable(self.emptyUser).extend({ + notify: "always" + }); + self.editor = { + name: ko.observable(undefined), + groups: ko.observableArray([]), + permissions: ko.observableArray([]), + password: ko.observable(undefined), + repeatedPassword: ko.observable(undefined), + passwordMismatch: ko.pureComputed(function () { + return self.editor.password() !== self.editor.repeatedPassword(); + }), + apikey: ko.observable(undefined), + active: ko.observable(undefined), + permissionSelectable: function (permission) { + return true; + }, + permissionSelected: function (permission) { + var index = self.editor.permissions().indexOf(permission); + return index >= 0; + }, + togglePermission: function (permission) { + var permissions = self.editor.permissions(); + var index = permissions.indexOf(permission); + if (index < 0) { + permissions.push(permission); + } else { + permissions.splice(index, 1); + } + self.editor.permissions(permissions); + }, + groupSelected: function (group) { + var index = self.editor.groups().indexOf(group); + return index >= 0; + }, + toggleGroup: function (group) { + var groups = self.editor.groups(); + var index = groups.indexOf(group); + if (index < 0) { + groups.push(group); + } else { + groups.splice(index, 1); + } + self.editor.groups(groups); + }, + joinedGroupPermissions: function (group) { + return access.permissionList(group); + }, + header: ko.observable(undefined), + new: ko.observable(true), + confirm: undefined, + valid: ko.pureComputed(function () { + return (self.editor.name() && self.editor.name().trim() && (!self.editor.new() || (self.editor.password() && self.editor.password().trim() && !self.editor.passwordMismatch()))); + }), + dangerRestricted: function () { + return false; + }, + dangerRestrictedText: gettext("This user may not have dangerous permissions.") + }; + self.userEditorDialog = undefined; + self.changePasswordDialog = undefined; + self.currentUser.subscribe(function (newValue) { + if (newValue === undefined) { + self.editor.name(undefined); + self.editor.groups(access.groups.defaults.slice(0)); + self.editor.permissions([]); + self.editor.active(true); + self.editor.apikey(undefined); + self.editor.header(gettext("Add user")); + self.editor.new(true); + self.editor.confirm = self.confirmAddUser; + } else { + self.editor.name(newValue.name); + self.editor.groups(newValue.groups.slice(0)); + self.editor.permissions(newValue.permissions.slice(0)); + self.editor.active(newValue.active); + self.editor.apikey(newValue.apikey); + self.editor.header(_.sprintf(gettext('Edit user "%(name)s"'), { + name: newValue.name + })); + self.editor.new(false); + self.editor.confirm = self.confirmEditUser; + } + self.editor.password(undefined); + self.editor.repeatedPassword(undefined); + }); + self.requestData = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + if (!access.loginState.hasPermissionKo(access.permissions.ADMIN)) + return; + return OctoPrint.access.users.list().done(self.fromResponse); + } + ; + self.fromResponse = function (response) { + self.listHelper.updateItems(response.users); + } + ; + self.showAddUserDialog = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + self.currentUser(undefined); + $('ul.nav-pills a[data-toggle="tab"]:first', self.userEditorDialog).tab("show"); + self.userEditorDialog.modal({ + minHeight: function () { + return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); + } + }).css({ + "margin-left": function () { + return -($(this).width() / 2); + } + }); + } + ; + self.confirmAddUser = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + var user = { + name: self.editor.name(), + password: self.editor.password(), + groups: self.editor.groups(), + permissions: self.editor.permissions(), + active: self.editor.active() + }; + self.addUser(user).done(function () { + self.currentUser(undefined); + self.userEditorDialog.modal("hide"); + }); + } + ; + self.showEditUserDialog = function (user) { + if (!CONFIG_ACCESS_CONTROL) + return; + var process = function (user) { + self.currentUser(user); + $('ul.nav-pills a[data-toggle="tab"]:first', self.userEditorDialog).tab("show"); + self.userEditorDialog.modal({ + minHeight: function () { + return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); + } + }).css({ + "margin-left": function () { + return -($(this).width() / 2); + } + }); + }; + OctoPrint.users.get(user.name).done(function (data) { + process(data); + }).fail(function () { + log.warn("Could not fetch current user data, proceeding with client side data copy"); + process(user); + }); + } + ; + self.confirmEditUser = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + var user = self.currentUser(); + user.active = self.editor.active(); + user.groups = self.editor.groups(); + user.permissions = self.editor.permissions(); + self.updateUser(user).done(function () { + self.currentUser(undefined); + self.userEditorDialog.modal("hide"); + }); + } + ; + self.showChangePasswordDialog = function (user) { + if (!CONFIG_ACCESS_CONTROL) + return; + self.currentUser(user); + self.changePasswordDialog.modal("show"); + } + ; + self.confirmChangePassword = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + self.updatePassword(self.currentUser().name, self.editor.password()).done(function () { + self.currentUser(undefined); + self.changePasswordDialog.modal("hide"); + }); + } + ; + self.confirmGenerateApikey = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + self.generateApikey(self.currentUser().name).done(function (response) { + self._updateApikey(response.apikey); + }); + } + ; + self.copyApikey = function () { + copyToClipboard(self.editor.apikey()); + } + ; + self._updateApikey = function (apikey) { + self.editor.apikey(apikey); + self.requestData(); + } + ; + self.confirmDeleteApikey = function () { + if (!CONFIG_ACCESS_CONTROL) + return; + self.deleteApikey(self.currentUser().name).done(function () { + self._updateApikey(undefined); + }); + } + ; + self.onStartup = function () { + self.userEditorDialog = $("#settings-usersEditorDialog"); + self.changePasswordDialog = $("#settings-usersDialogChangePassword"); + } + ; + self.addUser = function (user) { + if (!user) { + throw OctoPrint.InvalidArgumentError("user must be set"); + } + if (!access.loginState.hasPermissionKo(access.permissions.ADMIN)) + return $.Deferred().reject("You are not authorized to perform this action").promise(); + return OctoPrint.access.users.add(user).done(self.fromResponse); + } + ; + self.removeUser = function (user) { + if (!user) { + throw OctoPrint.InvalidArgumentError("user must be set"); + } + if (!access.loginState.hasPermissionKo(access.permissions.ADMIN)) + return $.Deferred().reject("You are not authorized to perform this action").promise(); + if (user.name === access.loginState.username()) { + new PNotify({ + title: gettext("Not possible"), + text: gettext("You may not delete your own account."), + type: "error" + }); + return $.Deferred().reject("You may not delete your own account").promise(); + } + showConfirmationDialog({ + title: gettext("Are you sure?"), + message: _.sprintf(gettext('You are about to delete the user "%(name)s".'), { + name: user.name + }), + proceed: gettext("Delete"), + onproceed: function () { + OctoPrint.access.users.delete(user.name).done(self.fromResponse); + } + }); + } + ; + self.updateUser = function (user) { + if (!user) { + throw OctoPrint.InvalidArgumentError("user must be set"); + } + return OctoPrint.access.users.update(user.name, user.active, user.admin, user.permissions, user.groups).done(self.fromResponse); + } + ; + self.updatePassword = function (username, password) { + return OctoPrint.access.users.changePassword(username, password); + } + ; + self.generateApikey = function (username) { + return OctoPrint.access.users.generateApiKey(username).done(function () { + self.requestData(); + }); + } + ; + self.deleteApikey = function (username) { + return OctoPrint.access.users.resetApiKey(username); + } + ; + return self; + } + )(); + access.groups = (function () { + var self = {}; + self.listHelper = new ItemListHelper("groups", { + name: function (a, b) { + if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) + return -1; + if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) + return 1; + return 0; + } + }, {}, "name", [], [], CONFIG_GROUPSPERPAGE); + self.groupsList = self.listHelper.items; + self.lookup = {}; + self.defaults = []; + self.emptyGroup = { + name: "" + }; + self.currentGroup = ko.observable(self.emptyGroup); + self.editor = { + key: ko.observable(undefined), + name: ko.observable(undefined), + description: ko.observable(undefined), + permissions: ko.observableArray([]), + subgroups: ko.observableArray([]), + default: ko.observable(false), + permissionSelectable: function (permission) { + return self.editor.key() !== GROUP_GUESTS || !permission.dangerous; + }, + permissionSelected: function (permission) { + var index = self.editor.permissions().indexOf(permission); + return index >= 0; + }, + togglePermission: function (permission) { + var permissions = self.editor.permissions(); + var index = permissions.indexOf(permission); + if (index < 0) { + permissions.push(permission); + } else { + permissions.splice(index, 1); + } + self.editor.permissions(permissions); + }, + subgroupSelectable: function (subgroup) { + return (self.editor.key() !== subgroup.key && (self.editor.key() !== GROUP_GUESTS || !subgroup.dangerous)); + }, + subgroupSelected: function (subgroup) { + var index = self.editor.subgroups().indexOf(subgroup); + return index >= 0; + }, + toggleSubgroup: function (subgroup) { + var subgroups = self.editor.subgroups(); + var index = subgroups.indexOf(subgroup); + if (index < 0) { + subgroups.push(subgroup); + } else { + subgroups.splice(index, 1); + } + self.editor.subgroups(subgroups); + }, + joinedGroupPermissions: function (group) { + return access.permissionList(group); + }, + header: ko.observable(undefined), + new: ko.observable(true), + confirm: undefined, + valid: ko.pureComputed(function () { + return self.editor.name() && self.editor.name().trim(); + }), + dangerRestricted: function () { + return self.editor.key() === GROUP_GUESTS; + }, + dangerRestrictedText: gettext("This group may not have dangerous permissions or subgroups.") + }; + self.groupEditorDialog = undefined; + self.groupsList.subscribe(function (oldValue) { + if (oldValue === undefined || oldValue.length === 0) + return; + oldValue.forEach(function (p) { + delete self[p.key.toUpperCase()]; + }); + }, null, "beforeChange"); + self.groupsList.subscribe(function (newValue) { + if (newValue === undefined) + return; + newValue.forEach(function (g) { + var needs = []; + g.permissions.forEach(function (p) { + for (var key in p.needs) { + p.needs[key].forEach(function (value) { + needs.push(access.permissions.need(key, value)); + }); + } + }); + if (needs.length > 0) { + self.registerGroup(g.key.toUpperCase(), needs); + } + }); + }); + self.registerGroup = function (name, group) { + Object.defineProperty(self, name, { + value: group, + enumerable: true, + configurable: true + }); + } + ; + self.currentGroup.subscribe(function (newValue) { + if (newValue === undefined) { + self.editor.key(undefined); + self.editor.name(undefined); + self.editor.description(undefined); + self.editor.permissions([]); + self.editor.subgroups([]); + self.editor.default(false); + self.editor.header(gettext("Add group")); + self.editor.new(true); + self.editor.confirm = self.confirmAddGroup; + } else { + self.editor.key(newValue.key); + self.editor.name(newValue.name); + self.editor.description(newValue.description); + self.editor.permissions(newValue.permissions.slice(0)); + self.editor.subgroups(newValue.subgroups.slice(0)); + self.editor.default(newValue.default); + self.editor.header(_.sprintf(gettext('Edit group "%(name)s"'), { + name: newValue.name + })); + self.editor.new(false); + self.editor.confirm = self.confirmEditGroup; + } + }); + self.requestData = function () { + return OctoPrint.access.groups.list().done(self.fromResponse); + } + ; + self.fromResponse = function (response) { + var lookup = {}; + var defaults = []; + _.each(response.groups, function (group) { + lookup[group.key] = group; + if (group.default) { + defaults.push(group.key); + } + }); + self.lookup = lookup; + self.defaults = defaults; + self.listHelper.updateItems(response.groups); + } + ; + self.showAddGroupDialog = function () { + self.currentGroup(undefined); + $('ul.nav-pills a[data-toggle="tab"]:first', self.groupEditorDialog).tab("show"); + self.groupEditorDialog.modal({ + minHeight: function () { + return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); + } + }).css({ + "margin-left": function () { + return -($(this).width() / 2); + } + }); + } + ; + self.confirmAddGroup = function () { + var group = { + key: self.editor.name().toLowerCase().replace(/[^a-z0-9_ ]/g, "").replace(/ /g, "_"), + name: self.editor.name(), + description: self.editor.description(), + permissions: self.editor.permissions(), + subgroups: self.editor.subgroups(), + default: self.editor.default() + }; + self.addGroup(group).done(function () { + self.currentGroup(undefined); + self.groupEditorDialog.modal("hide"); + }); + } + ; + self.showEditGroupDialog = function (group) { + if (!group.changeable) + return; + self.currentGroup(group); + $('ul.nav-pills a[data-toggle="tab"]:first', self.groupEditorDialog).tab("show"); + self.groupEditorDialog.modal({ + minHeight: function () { + return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); + } + }).css({ + "margin-left": function () { + return -($(this).width() / 2); + } + }); + } + ; + self.confirmEditGroup = function () { + var group = self.currentGroup(); + var data = { + key: group.key, + name: group.name, + description: self.editor.description(), + permissions: self.editor.permissions(), + subgroups: self.editor.subgroups(), + default: self.editor.default() + }; + self.updateGroup(data).done(function () { + self.currentGroup(undefined); + self.groupEditorDialog.modal("hide"); + }); + } + ; + self.onStartup = function () { + self.groupEditorDialog = $("#settings-groupsEditorDialog"); + } + ; + self.addGroup = function (group) { + if (!group) { + throw OctoPrint.InvalidArgumentError("group must be set"); + } + return OctoPrint.access.groups.add(group).done(self.fromResponse); + } + ; + self.removeGroup = function (group) { + if (!group) { + throw OctoPrint.InvalidArgumentError("group must be set"); + } + if (!group.removable) + return; + showConfirmationDialog({ + title: gettext("Are you sure?"), + message: _.sprintf(gettext('You are about to delete the group "%(name)s".'), { + name: group.name + }), + proceed: gettext("Delete"), + onproceed: function () { + OctoPrint.access.groups.delete(group.key).done(function (response) { + self.fromResponse(response); + access.users.requestData(); + }); + } + }); + } + ; + self.updateGroup = function (group) { + if (!group) { + throw OctoPrint.InvalidArgumentError("group must be set"); + } + return OctoPrint.access.groups.update(group).done(self.fromResponse); + } + ; + return self; + } + )(); + access.permissions = (function () { + var self = {}; + self.need = function (method, value) { + return { + method: method, + value: value + }; + } + ; + self.roleNeed = function (value) { + return self.need("role", value); + } + ; + self.permissionList = ko.observableArray([]); + self.lookup = {}; + var registeredPermissions = []; + var registerPermission = function (key, permission) { + Object.defineProperty(self, key, { + value: permission, + enumerable: true, + configurable: true + }); + registeredPermissions.push(key); + }; + var clearAllRegisteredPermissions = function () { + _.each(registeredPermissions, function (key) { + delete self[key]; + }); + registeredPermissions = []; + }; + self.initialize = function () { + clearAllRegisteredPermissions(); + var permissionList = []; + var lookup = {}; + _.each(PERMISSIONS, function (permission) { + var needs = []; + _.each(permission.needs, function (value, key) { + needs.push(self.need(key, value)); + }); + if (needs.length > 0) { + registerPermission(permission.key, needs); + } + if (!permission.combined) { + permissionList.push(permission); + } + lookup[permission.key] = permission; + }); + permissionList.sort(access.permissionComparator); + self.permissionList(permissionList); + self.lookup = lookup; + } + ; + return self; + } + )(); + access.groupComparator = function (a, b) { + var nameA = a.name ? a.name.toUpperCase() : ""; + var nameB = b.name ? b.name.toUpperCase() : ""; + if (nameA < nameB) { + return -1; + } else if (nameA > nameB) { + return 1; + } else { + return 0; + } + } + ; + access.permissionComparator = function (a, b) { + var nameA = a.name ? a.name.toUpperCase() : ""; + var nameB = b.name ? b.name.toUpperCase() : ""; + var pluginA = a.plugin || ""; + var pluginB = b.plugin || ""; + var compA = pluginA + ":" + nameA; + var compB = pluginB + ":" + nameB; + if (compA < compB) { + return -1; + } else if (compA > compB) { + return 1; + } else { + return 0; + } + } + ; + access.groupList = function (data) { + if (data.groups === undefined) + return ""; + var mappedGroups = _.filter(_.map(data.groups, function (g) { + return access.groups.lookup[g]; + }), function (g) { + return g !== undefined; + }); + mappedGroups.sort(access.groupComparator); + return _.map(mappedGroups, function (g) { + return g.name; + }).join(", "); + } + ; + access.subgroupList = function (data) { + if (data.subgroups === undefined) + return ""; + var mappedGroups = _.filter(_.map(data.subgroups, function (g) { + return access.groups.lookup[g]; + }), function (g) { + return g !== undefined; + }); + mappedGroups.sort(access.groupComparator); + return _.map(mappedGroups, function (g) { + return g.name; + }).join(", "); + } + ; + access.permissionList = function (data) { + if (!data || data.permissions === undefined) + return ""; + var mappedPermissions = _.filter(_.map(data.permissions, function (p) { + return access.permissions.lookup[p]; + }), function (p) { + return p !== undefined; + }); + mappedPermissions.sort(access.permissionComparator); + return _.map(mappedPermissions, function (p) { + return p.name; + }).join(", "); + } + ; + access.onStartup = function () { + access.groups.onStartup(); + access.users.onStartup(); + } + ; + access.onServerConnect = function () { + access.permissions.initialize(); + } + ; + access.onServerReconnect = function () { + access.permissions.initialize(); + } + ; + access.onUserPermissionsChanged = access.onUserLoggedIn = access.onUserLoggedOut = function (user) { + if (access.loginState.hasPermission(access.permissions.SETTINGS)) { + access.groups.requestData().done(function () { + access.users.requestData(); + }); + } + } + ; + } + OCTOPRINT_VIEWMODELS.push([AccessViewModel, ["loginStateViewModel"], []]); +}); \ No newline at end of file diff --git a/octoprint_CalibrationTools/templates/CalibrationTools_settings.jinja2 b/octoprint_CalibrationTools/templates/CalibrationTools_settings.jinja2 index b0947af..a970d51 100644 --- a/octoprint_CalibrationTools/templates/CalibrationTools_settings.jinja2 +++ b/octoprint_CalibrationTools/templates/CalibrationTools_settings.jinja2 @@ -1,5 +1,5 @@ {% import "macros.jinja2" as snipped %} -{{ snipped.subSection("E-Steps default settings", true) }} +{{ snipped.subSection("E-Steps default values",true) }}
@@ -23,14 +23,18 @@ {{ snipped.field("Filament mark length", "The length marked on filament", "number", "settings.plugins.CalibrationTools.eSteps.markLength", "true", "mm", 50) }} -{{ snipped.subSection("X-Y-Z-Steps", true) }} +{{ snipped.subSection("X-Y-Z-Steps default values") }} +{{ snipped.field("gCode cube size of X", "", "number", "settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.X", "true", "mm", 0.01, 10.00, "") }} +{{ snipped.field("gCode cube size of Y", "", "number", "settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Y", "true", "mm", 0.01, 10.00, "") }} +{{ snipped.field("gCode cube size of Z", "", "number", "settings.plugins.CalibrationTools.XYZSteps.gCodeCubeSize.Z", "true", "mm", 0.01, 10.00, "") }} -{{ snipped.subSection("Hot-end PID", true) }} + +{{ snipped.subSection("Hot-end PID default values") }} {{ snipped.field("Fan speed", "Default value for fan speed while tuning", "number", "settings.plugins.CalibrationTools.pid.hotEnd.fanSpeed", "true", "", 1, 0, 255) }} {{ snipped.field("Number of cycles", "Default number of cycles to sample while tuning", "number", "settings.plugins.CalibrationTools.pid.hotEnd.noCycles", "true", "", 1, 3, 200) }} {{ snipped.field("HotEnd index", "Default number of cycles to sample while tuning", "number", "settings.plugins.CalibrationTools.pid.hotEnd.hotEndIndex", "true", "", 1, 0) }} {{ snipped.field("Target temperature", "Default target temperature for tuning", "number", "settings.plugins.CalibrationTools.pid.hotEnd.targetTemp", "true", "ºC", 1, 3, 200) }} -{{ snipped.subSection("Bed PID", true) }} +{{ snipped.subSection("Bed PID default values") }} {{ snipped.field("Fan speed", "Default value for fan speed while tuning", "number", "settings.plugins.CalibrationTools.pid.bed.fanSpeed", "true", "", 1, 0, 255) }} {{ snipped.field("Number of cycles", "Default number of cycles to sample while tuning", "number", "settings.plugins.CalibrationTools.pid.bed.noCycles", "true", "", 1, 3, 200) }} {{ snipped.field("Target temperature", "Default target temperature for tuning", "number", "settings.plugins.CalibrationTools.pid.bed.targetTemp", "true", "ºC", 1, 3, 200) }} \ No newline at end of file diff --git a/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 b/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 index 0671001..4a851da 100644 --- a/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 +++ b/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 @@ -26,13 +26,13 @@