diff --git a/src/octoprint/server/api/printer_profiles.py b/src/octoprint/server/api/printer_profiles.py index 3f3bcea0..0bfba610 100644 --- a/src/octoprint/server/api/printer_profiles.py +++ b/src/octoprint/server/api/printer_profiles.py @@ -23,6 +23,7 @@ def printerProfilesList(): return jsonify(dict(profiles=all_profiles.values())) @api.route("/printerProfiles", methods=["POST"]) +@restricted_access def printerProfilesAdd(): if not "application/json" in request.headers["Content-Type"]: return None, None, make_response("Expected content-type JSON", 400) @@ -42,18 +43,10 @@ def printerProfilesAdd(): if "name" in base_profile: del base_profile["name"] profile = dict_merge(base_profile, json_data["profile"]) + if not _validate_profile(profile): + return None, None, make_response("Profile is invalid, missing obligatory values", 400) - if not "id" in profile and not "name" in profile: - return None, None, make_response("Profile must contain either id or name") - elif not "name" in profile: - return None, None, make_response("Profile must contain a name") - - try: - saved_profile = printerProfileManager.save(profile, allow_overwrite=False) - except Exception as e: - return None, None, make_response("Could not save profile: %s" % e.message) - - return jsonify(dict(profile=_convert_profile(saved_profile))) + return _overwrite_profile(profile) @api.route("/printerProfiles/", methods=["GET"]) def printerProfilesGet(identifier): @@ -69,7 +62,7 @@ def printerProfilesDelete(identifier): @api.route("/printerProfiles/", methods=["PATCH"]) @restricted_access -def printerProfilesUpdate(identifier ): +def printerProfilesUpdate(identifier): if not "application/json" in request.headers["Content-Type"]: return None, None, make_response("Expected content-type JSON", 400) @@ -85,6 +78,9 @@ def printerProfilesUpdate(identifier ): new_profile = dict_merge(profile, new_profile) new_profile["id"] = identifier + if not _validate_profile(new_profile): + return None, None, make_response("Combined profile is invalid, missing obligatory values", 400) + try: saved_profile = printerProfileManager.save(new_profile, allow_overwrite=True) except Exception as e: @@ -105,4 +101,30 @@ def _convert_profile(profile, default=None): converted = copy.deepcopy(profile) converted["resource"] = url_for(".printerProfilesGet", identifier=profile["id"], _external=True) converted["default"] = (profile["id"] == default) - return converted \ No newline at end of file + return converted + +def _validate_profile(profile): + return "name" in profile \ + and "volume" in profile \ + and "width" in profile["volume"] \ + and "depth" in profile["volume"] \ + and "height" in profile["volume"] \ + and "formFactor" in profile["volume"] \ + and "heatedBed" in profile \ + and "extruder" in profile \ + and "count" in profile["extruder"] \ + and "offsets" in profile["extruder"] \ + and len(profile["extruder"]["offsets"]) == profile["extruder"]["count"] + +def _overwrite_profile(profile): + if not "id" in profile and not "name" in profile: + return None, None, make_response("Profile must contain either id or name") + elif not "name" in profile: + return None, None, make_response("Profile must contain a name") + + try: + saved_profile = printerProfileManager.save(profile, allow_overwrite=False) + except Exception as e: + return None, None, make_response("Could not save profile: %s" % e.message) + + return jsonify(dict(profile=_convert_profile(saved_profile))) diff --git a/src/octoprint/static/js/app/viewmodels/printerprofiles.js b/src/octoprint/static/js/app/viewmodels/printerprofiles.js index 89eef26b..a55851cf 100644 --- a/src/octoprint/static/js/app/viewmodels/printerprofiles.js +++ b/src/octoprint/static/js/app/viewmodels/printerprofiles.js @@ -1,28 +1,22 @@ function PrinterProfilesViewModel() { var self = this; - self.selected = ko.observable(); - self.default = ko.observable(); - self.available = ko.observableArray(); - self.currentProfile = ko.computed(function() { - var currentProfile = undefined; - var defaultProfile = undefined; - - _.each(self.available(), function(profile) { - if (profile.id() == self.selected()) { - currentProfile = profile; + self.profiles = new ItemListHelper( + "printerProfiles", + { + "name": function(a, b) { + // sorts ascending + if (a["name"].toLocaleLowerCase() < b["name"].toLocaleLowerCase()) return -1; + if (a["name"].toLocaleLowerCase() > b["name"].toLocaleLowerCase()) return 1; + return 0; } - if (profile.id() == self.default()) { - defaultProfile = profile; - } - }); - - if (currentProfile != undefined) { - return currentProfile; - } else { - return defaultProfile; - } - }); + }, + {}, + "name", + [], + [], + 5 + ); self.editorName = ko.observable(); self.editorColor = ko.observable(); @@ -57,9 +51,7 @@ function PrinterProfilesViewModel() { }; self.fromResponse = function(data) { - self.selectedProfile(data.current); - self.defaultProfile(data.default); - self.availableProfiles(data.profiles); + self.profiles.updateItems(data.profiles); }; self.addProfile = function() {