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) }}
Let me to control temperature
@@ -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 @@
-
+
Documentation
E-Steps
-
+
X-Y-Z-Steps
diff --git a/octoprint_CalibrationTools/templates/macros.jinja2 b/octoprint_CalibrationTools/templates/macros.jinja2
index b3c601e..5d9e7b8 100644
--- a/octoprint_CalibrationTools/templates/macros.jinja2
+++ b/octoprint_CalibrationTools/templates/macros.jinja2
@@ -1,5 +1,5 @@
-{% macro subSection(title, spaceBefore) %}
-{% if (spaceBefore) %} {% endif %}
+{% macro subSection(title, spaceBefore = false) %}
+{% if (not spaceBefore) %} {% endif %}
{{ _(title) }}
{% endmacro %}
diff --git a/octoprint_CalibrationTools/templates/tabs/tab-content.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-content.jinja2
index 9b7c593..612b1a2 100644
--- a/octoprint_CalibrationTools/templates/tabs/tab-content.jinja2
+++ b/octoprint_CalibrationTools/templates/tabs/tab-content.jinja2
@@ -1,8 +1,8 @@
-
+
{% include "tabs/tab-doc.jinja2" %}
-
+
{% include "tabs/tab-xyz.jinja2" %}
diff --git a/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2
index 976a94f..02419f9 100644
--- a/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2
+++ b/octoprint_CalibrationTools/templates/tabs/tab-esteps.jinja2
@@ -51,7 +51,7 @@
-{{ snipped.subSection("Test results", true) }}
+{{ snipped.subSection("Test results") }}
@@ -102,7 +102,7 @@
-{{ snipped.subSection("Process description", true) }}
+{{ snipped.subSection("Process description") }}
{{ 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
diff --git a/octoprint_CalibrationTools/templates/tabs/tab-pid.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-pid.jinja2
index ed23781..6a4b8dd 100644
--- a/octoprint_CalibrationTools/templates/tabs/tab-pid.jinja2
+++ b/octoprint_CalibrationTools/templates/tabs/tab-pid.jinja2
@@ -48,7 +48,7 @@
-{{ snipped.subSection("Hot-end tuning", true) }}
+{{ snipped.subSection("Hot-end tuning") }}
-{{ snipped.subSection("Heated bed tuning", true) }}
+{{ snipped.subSection("Heated bed tuning") }}
-{{ snipped.subSection("Note", true) }}
+{{ snipped.subSection("Note") }}
{{ snipped.quote("It is recommended to run the tuning with conditions as close to printing as possible. This means filament loaded and the part cooling fan set to your normal speed. It is not essential, but you may
prefer to start this process with the hot end at room temperature.",
"
teachingtechyt.github.io ", "text-warning") }}
\ No newline at end of file
diff --git a/octoprint_CalibrationTools/templates/tabs/tab-xyz.jinja2 b/octoprint_CalibrationTools/templates/tabs/tab-xyz.jinja2
index 34c114e..ed37f9b 100644
--- a/octoprint_CalibrationTools/templates/tabs/tab-xyz.jinja2
+++ b/octoprint_CalibrationTools/templates/tabs/tab-xyz.jinja2
@@ -1 +1,90 @@
-Something in xyz tab...
\ No newline at end of file
+{% import "macros.jinja2" as snipped %}
+
+{{ snipped.subSection("Current PID values", true) }}
+
+
+
+ Current values
+
+
+
+
+
+
+
+ GCode cube size
+
+
+
+
+
+
+
+ Printed cube size
+
+
+
+
+
+
+
+
+
+   
+ Save to EEPROM
+
+
+
\ No newline at end of file