From a2751b96d698c70b0b3c9b47d2c8773044df3ed3 Mon Sep 17 00:00:00 2001 From: Sergiu Toporjinschi Date: Tue, 8 Feb 2022 21:34:52 +0200 Subject: [PATCH] Fix design on standard view (#3) * Move notes above the fields * Adding documentation * Add documentation * Fix design issue on standard view --- README.md | 24 +- assets/PID-autotune.png | Bin 0 -> 34528 bytes assets/XYZSteps.png | Bin 0 -> 20826 bytes assets/eSteps.png | Bin 0 -> 26408 bytes .../static/js/EStepsViewModel.js | 11 +- .../static/js/GeneralViewModel.js | 6 +- .../static/js/PIDTuneViewModel.js | 12 +- .../static/js/XYZStepsViewModel.js | 37 +- octoprint_CalibrationTools/static/js/test.js | 694 ------------------ .../templates/CalibrationTools_tab.jinja2 | 30 +- .../templates/macros.jinja2 | 8 +- .../templates/tabs/tab-doc.jinja2 | 37 +- .../templates/tabs/tab-esteps.jinja2 | 46 +- .../templates/tabs/tab-pid.jinja2 | 51 +- .../templates/tabs/tab-xyz.jinja2 | 42 +- 15 files changed, 210 insertions(+), 788 deletions(-) create mode 100644 assets/PID-autotune.png create mode 100644 assets/XYZSteps.png create mode 100644 assets/eSteps.png delete mode 100644 octoprint_CalibrationTools/static/js/test.js diff --git a/README.md b/README.md index 39bfa53..44c5bdb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,23 @@ # OctoPrint-CalibrationTools -**TODO:** Describe what your plugin does. +A set of tools to help users with calibration process. +Supported tunings: + +- E Steps - calibrating number of steps/mm for E extruder; +- XYZ Steps - calibrating number of steps/mm for axes X, Y and Z; +- PID Auto-tune - calibration Proportional gain, Integral gain and Derivative values for hot-end and heated bed; + +Before start using this plugin I strongly recommend reading some documentation about tunning [teachingtechyt.github.io](https://teachingtechyt.github.io/calibration.html) + +## Supported frameworks + +- Marlin 2.x + +## Screens + +![E-Steps](assets/eSteps.png) +![X-Y-Z Steps](assets/XYZSteps.png) +![PID Autotune](assets/PID-autotune.png) ## Setup @@ -9,9 +26,6 @@ or manually using this URL: https://github.com/SergiuToporjinschi/OctoPrint-CalibrationTools/archive/master.zip -**TODO:** Describe how to install your plugin, if more needs to be done than just installing it via pip or through -the plugin manager. - ## Configuration -**TODO:** Describe your plugin's configuration options (if any). +You can set the default values for each tuning process. diff --git a/assets/PID-autotune.png b/assets/PID-autotune.png new file mode 100644 index 0000000000000000000000000000000000000000..cf51e64812999f80af81419419efefefc0b6303f GIT binary patch literal 34528 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

9-)>F*#C|TXIj&^CY^B||0=@h_QldQd{@%<_ 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 K7YcsA6ZT)m$@}5} literal 0 HcmV?d00001 diff --git a/assets/XYZSteps.png b/assets/XYZSteps.png new file mode 100644 index 0000000000000000000000000000000000000000..f3eb6f059029d01c13bca15ffb871ad63c1db5b0 GIT binary patch literal 20826 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 literal 0 HcmV?d00001 diff --git a/assets/eSteps.png b/assets/eSteps.png new file mode 100644 index 0000000000000000000000000000000000000000..dca7509a778202ebc830a0f1a1c8b7a4f40c95f9 GIT binary patch literal 26408 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 T#y()cO%67$7aGo8{^x%H81Uoa literal 0 HcmV?d00001 diff --git a/octoprint_CalibrationTools/static/js/EStepsViewModel.js b/octoprint_CalibrationTools/static/js/EStepsViewModel.js index c3298f8..9027acb 100644 --- a/octoprint_CalibrationTools/static/js/EStepsViewModel.js +++ b/octoprint_CalibrationTools/static/js/EStepsViewModel.js @@ -6,6 +6,14 @@ $(function () { self.controlViewModel = parameters[2]; self.terminalViewModel = parameters[3]; self.access = parameters[4]; + self.generalVM = parameters[5]; + + self.columnLabelCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span4" : "span3"; + }); + self.columnFieldCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span8" : "span9"; + }); self.is_admin = ko.observable(false); self.steps = ko.observable(); @@ -69,7 +77,6 @@ $(function () { text: "Heating nuzzle has started!!!
When extrusion stops you have to fulfil Length after extrusion and save the new value ", type: "warning" }); - console.log(response); }).fail(function (response) { new PNotify({ title: "Error on starting extrusion ", @@ -109,7 +116,7 @@ $(function () { // 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"], + 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_eSteps"] }); diff --git a/octoprint_CalibrationTools/static/js/GeneralViewModel.js b/octoprint_CalibrationTools/static/js/GeneralViewModel.js index 00d4440..b4d398c 100644 --- a/octoprint_CalibrationTools/static/js/GeneralViewModel.js +++ b/octoprint_CalibrationTools/static/js/GeneralViewModel.js @@ -9,6 +9,7 @@ $(function () { } } } + this.isSmall = ko.observable($("#tab_plugin_CalibrationTools").width() < 800); ko.extenders.numeric = function (target, options) { var returnObs = ko.pureComputed({ read: target, @@ -22,8 +23,11 @@ $(function () { returnObs(target()); return returnObs; }; + + this.onStartupComplete = function () { + this.isSmall($("#tabs_content").width() < 800); + } } - // OCTOPRINT_VIEWMODELS.push([GeneralViewModel, ["loginStateViewModel"], []]); OCTOPRINT_VIEWMODELS.push({ // This is the constructor to call for instantiating the plugin construct: CalibrationToolsGeneralViewModel, diff --git a/octoprint_CalibrationTools/static/js/PIDTuneViewModel.js b/octoprint_CalibrationTools/static/js/PIDTuneViewModel.js index 05d088e..5034f04 100644 --- a/octoprint_CalibrationTools/static/js/PIDTuneViewModel.js +++ b/octoprint_CalibrationTools/static/js/PIDTuneViewModel.js @@ -4,7 +4,13 @@ $(function () { self.loginStateViewModel = parameters[0]; self.settingsViewModel = parameters[1]; self.controlViewModel = parameters[2]; - + self.generalVM = parameters[5]; + self.columnLabelCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span3" : "span3"; + }); + self.columnFieldCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span9" : "span9"; + }); self.pidCurrentValues = { "hotEnd": { "P": ko.observable(0), @@ -79,7 +85,6 @@ $(function () { text: "In progress", type: "info" }); - console.log(response); }).fail(function (response) { new PNotify({ title: "Error on starting PID autotune ", @@ -102,7 +107,6 @@ $(function () { text: "In progress", type: "info" }); - console.log(response); }).fail(function (response) { new PNotify({ title: "Error on starting PID autotune ", @@ -119,7 +123,7 @@ $(function () { // 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"], + 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_pid"] }); diff --git a/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js b/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js index b73fe88..6050cc2 100644 --- a/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js +++ b/octoprint_CalibrationTools/static/js/XYZStepsViewModel.js @@ -4,28 +4,33 @@ $(function () { self.loginStateViewModel = parameters[0]; self.settingsViewModel = parameters[1]; self.controlViewModel = parameters[2]; - generalVM = parameters[5]; - + self.generalVM = parameters[5]; + self.columnLabelCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span2" : "span3"; + }); + self.columnFieldCls = ko.computed(function () { + return self.generalVM.isSmall() ? "span10" : "span9"; + }); 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)) + X: ko.observable(0).extend(self.generalVM.decimal3(0.000)), + Y: ko.observable(0).extend(self.generalVM.decimal3(0.000)), + Z: ko.observable(0).extend(self.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)) + X: ko.observable().extend(self.generalVM.decimal3(22.000)), + Y: ko.observable().extend(self.generalVM.decimal3(22.000)), + Z: ko.observable().extend(self.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)) + X: ko.observable().extend(self.generalVM.decimal3(25.000)), + Y: ko.observable().extend(self.generalVM.decimal3(25.000)), + Z: ko.observable().extend(self.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)) + X: ko.observable().extend(self.generalVM.decimal3(0.000)), + Y: ko.observable().extend(self.generalVM.decimal3(0.000)), + Z: ko.observable().extend(self.generalVM.decimal3(0.000)) } }; @@ -69,7 +74,9 @@ $(function () { }) }; - + // self.labelColumnCss = viewModel.profitStatus = ko.pureComputed(function () { + // return "span3" $("#tab_plugin_CalibrationTools").width() < 800 + // }); self.isAdmin = ko.observable(false); diff --git a/octoprint_CalibrationTools/static/js/test.js b/octoprint_CalibrationTools/static/js/test.js deleted file mode 100644 index da537b0..0000000 --- a/octoprint_CalibrationTools/static/js/test.js +++ /dev/null @@ -1,694 +0,0 @@ -$(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_tab.jinja2 b/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 index cdd4f42..7e82281 100644 --- a/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 +++ b/octoprint_CalibrationTools/templates/CalibrationTools_tab.jinja2 @@ -24,7 +24,7 @@

-
+ -
+
{% include "tabs/tab-content.jinja2" %}
@@ -49,12 +49,17 @@ {% block script%} {% endblock %} \ No newline at end of file diff --git a/octoprint_CalibrationTools/templates/macros.jinja2 b/octoprint_CalibrationTools/templates/macros.jinja2 index 766ebb1..95db195 100644 --- a/octoprint_CalibrationTools/templates/macros.jinja2 +++ b/octoprint_CalibrationTools/templates/macros.jinja2 @@ -26,12 +26,12 @@ {% set max = max|default("") %} {% set unit = unit|trim|default("") %}
-
+
-
+
{% if unit != "" %} @@ -49,12 +49,12 @@ {% set max = max|default("") %} {% set unit = unit|trim|default("") %}
-
+
-
+
{{ _(label) }} diff --git a/octoprint_CalibrationTools/templates/tabs/tab-doc.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-doc.jinja2 index da9fa03..38278fd 100644 --- a/octoprint_CalibrationTools/templates/tabs/tab-doc.jinja2 +++ b/octoprint_CalibrationTools/templates/tabs/tab-doc.jinja2 @@ -1,3 +1,38 @@ {% import "macros.jinja2" as snipped %} -{{ snipped.quote("For using this plugin, I strongly recommending you to read teachingtechyt.github.io","", "text-warning") }} \ No newline at end of file +{{ snipped.quote("Before starting I strongly recommend reading some documentation about tunning teachingtechyt.github.io","", +"text-warning") }} +The stepper motors divides a full rotation in a number of equal steps. +E-Steps tuning is a process of setting the exact number of steps need it for pushing a fix amount of filament for feeding the hot-end.
+ +{{ snipped.subSection("E-Steps") }} +You will have to: + +
  • Mark a specific length of filament at the extruder motor entrance;
  • +
  • Set the hot-end on a printing temperature in E-Steps tab;
  • +
  • Set the extrusion length and speed;
  • +
  • Press "Start extrusion";
  • +
  • When extrusion finished, check the remaining length between the extruder and the filament mark location;
  • +
  • Refresh the current values from EEPROM;
  • +
  • Feed data collected in E-Steps tab and save the results in EEPROM;
  • +
    + +{{ snipped.subSection("X-Y-Z Steps") }} +You will have to: + +
  • Print a test cube with a known size on all three axes X,Y,X;
  • +
  • Refresh the current values from EEPROM;
  • +
  • Feed data collected in E-Steps tab and save the results in EEPROM;
  • +
    + + +{{ snipped.subSection("PID Autotune") }} +You will have to: + +
  • Refresh the current values from EEPROM;
  • +
  • Set the hot-end index which you want to tune;
  • +
  • Set the usual temperature used in your prints for that specific hot-end;
  • +
  • Set the usual fan speed used in your prints;
  • +
  • Monitor temperature tab, when it starts to cool down save the results in EEPROM;
  • +
  • For tuning heated bed the index is already set on -1;
  • +
    \ No newline at end of file diff --git a/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2 index 60cb3d0..a55d901 100644 --- a/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2 +++ b/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2 @@ -1,24 +1,36 @@ {% import "macros.jinja2" as snipped %} {{ snipped.subSection("Process description", true) }} + +You will have to: + +
  • Mark a specific length of filament at the extruder motor entrance;
  • +
  • Set the hot-end on a printing temperature in E-Steps tab;
  • +
  • Set the extrusion length and speed;
  • +
  • Press "Start extrusion";
  • +
  • When extrusion finished, check the remaining length between the extruder and the filament mark location;
  • +
  • Refresh the current values from EEPROM;
  • +
  • Feed data collected in E-Steps tab and save the results in EEPROM;
  • +
    +
    + {{ snipped.quote(" This calibration is best done with the extruder detached from the hot end, so no restriction is present on the movement. If it is convenient, you can partially disassemble the printer so the output of the extruder is open and the filament exits in free air. If this is inconvenient, the process below aims to minimize restrictions by extruding very slowly and with a slightly higher temperature. The results from this should still be reliable. -", " -For more information about how to use this visit teachingtechyt.github.io -", "text-warning") }} +", "teachingtechyt.github.io", "text-warning") }} + +{{ snipped.subSection("Parameters", true) }} -{{ snipped.subSection("Test parameters") }}
    -
    +
    -
    +
    {{ snipped.linkToMarlin("M104", "Marlin website") }} M104   S @@ -29,12 +41,12 @@ reliable.
    -
    +
    -
    +
    {{ snipped.linkToMarlin("G000-G001", "Marlin website") }} G1   E @@ -49,8 +61,8 @@ reliable. {{ snipped.field("Extrusion marking length", "The length marked on filament before extrusion. ", "number", "$root.testParam.markLength", "true", "mm", 0.01, 50) }}
    -
    -
    +
    +
    -{{ snipped.subSection("Test results") }} +{{ snipped.subSection("Results") }}
    -
    +
    -
    +
    steps/mm @@ -85,12 +97,12 @@ reliable.
    -
    +
    -
    +
    {{ snipped.linkToMarlin("M092", "Marlin website") }} @@ -100,8 +112,8 @@ reliable.
    -
    -
    +
    +