Merge branch 'richardjm-devel' into devel
Conflicts: octoprint/server.py octoprint/settings.py octoprint/templates/index.jinja2master
commit
c6e15a7d32
|
@ -24,6 +24,7 @@ import octoprint.events as events
|
||||||
|
|
||||||
SUCCESS = {}
|
SUCCESS = {}
|
||||||
BASEURL = "/ajax/"
|
BASEURL = "/ajax/"
|
||||||
|
APIBASEURL = "/api/"
|
||||||
|
|
||||||
app = Flask("octoprint")
|
app = Flask("octoprint")
|
||||||
# Only instantiated by the Server().run() method
|
# Only instantiated by the Server().run() method
|
||||||
|
@ -319,6 +320,7 @@ def uploadGcodeFile():
|
||||||
eventManager.fire("Upload", filename)
|
eventManager.fire("Upload", filename)
|
||||||
return jsonify(files=gcodeManager.getAllFileData(), filename=filename)
|
return jsonify(files=gcodeManager.getAllFileData(), filename=filename)
|
||||||
|
|
||||||
|
|
||||||
@app.route(BASEURL + "gcodefiles/load", methods=["POST"])
|
@app.route(BASEURL + "gcodefiles/load", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def loadGcodeFile():
|
def loadGcodeFile():
|
||||||
|
@ -349,10 +351,47 @@ def deleteGcodeFile():
|
||||||
return readGcodeFiles()
|
return readGcodeFiles()
|
||||||
|
|
||||||
@app.route(BASEURL + "gcodefiles/refresh", methods=["POST"])
|
@app.route(BASEURL + "gcodefiles/refresh", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def refreshFiles():
|
def refreshFiles():
|
||||||
printer.updateSdFiles()
|
printer.updateSdFiles()
|
||||||
return jsonify(SUCCESS)
|
return jsonify(SUCCESS)
|
||||||
|
|
||||||
|
#-- very simple api routines
|
||||||
|
@app.route(APIBASEURL + "load", methods=["POST"])
|
||||||
|
@login_required
|
||||||
|
def apiLoad():
|
||||||
|
filename = None
|
||||||
|
s = settings()
|
||||||
|
if not s.get(["api", "allow"]):
|
||||||
|
return jsonify(success=False, message="API calls not enabled")
|
||||||
|
|
||||||
|
if not "apikey" in request.values.keys():
|
||||||
|
return jsonify(success=False, message="apikey not present")
|
||||||
|
|
||||||
|
if request.values["apikey"] <> s.get(["api", "key"]):
|
||||||
|
return jsonify(success=False, message="apikey incorrect" + s.get(["api","key"]) + " " + request.values["apikey"])
|
||||||
|
|
||||||
|
if "file" in request.files.keys():
|
||||||
|
# Perform an upload
|
||||||
|
file = request.files["file"]
|
||||||
|
filename = gcodeManager.addFile(file)
|
||||||
|
if filename is None:
|
||||||
|
return jsonify(success=False, message="failure loading gcode")
|
||||||
|
else:
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.info("loaded " + filename)
|
||||||
|
# Immediately perform a loadGcode and possibly print too
|
||||||
|
printAfterLoading = False
|
||||||
|
if "print" in request.values.keys() and request.values["print"] in valid_boolean_trues:
|
||||||
|
printAfterLoading = True
|
||||||
|
filepath = gcodeManager.getAbsolutePath(filename)
|
||||||
|
if filepath is not None:
|
||||||
|
printer.loadGcode(filepath, printAfterLoading)
|
||||||
|
else:
|
||||||
|
return jsonify(success=False, message="gcode file not present")
|
||||||
|
|
||||||
|
return jsonify(SUCCESS)
|
||||||
|
|
||||||
#~~ timelapse handling
|
#~~ timelapse handling
|
||||||
|
|
||||||
@app.route(BASEURL + "timelapse", methods=["GET"])
|
@app.route(BASEURL + "timelapse", methods=["GET"])
|
||||||
|
@ -427,6 +466,10 @@ def getSettings():
|
||||||
[movementSpeedX, movementSpeedY, movementSpeedZ, movementSpeedE] = s.get(["printerParameters", "movementSpeed", ["x", "y", "z", "e"]])
|
[movementSpeedX, movementSpeedY, movementSpeedZ, movementSpeedE] = s.get(["printerParameters", "movementSpeed", ["x", "y", "z", "e"]])
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
|
"api": {
|
||||||
|
"allow": s.getBoolean(["api", "allow"]),
|
||||||
|
"key": s.get(["api", "key"])
|
||||||
|
},
|
||||||
"appearance": {
|
"appearance": {
|
||||||
"name": s.get(["appearance", "name"]),
|
"name": s.get(["appearance", "name"]),
|
||||||
"color": s.get(["appearance", "color"])
|
"color": s.get(["appearance", "color"])
|
||||||
|
@ -476,6 +519,10 @@ def setSettings():
|
||||||
data = request.json
|
data = request.json
|
||||||
s = settings()
|
s = settings()
|
||||||
|
|
||||||
|
if "api" in data.keys():
|
||||||
|
if "allow" in data["api"].keys(): s.set(["api", "allow"], data["api"]["allow"])
|
||||||
|
if "key" in data["api"].keys(): s.set(["api", "key"], data["api"]["key"], True)
|
||||||
|
|
||||||
if "appearance" in data.keys():
|
if "appearance" in data.keys():
|
||||||
if "name" in data["appearance"].keys(): s.set(["appearance", "name"], data["appearance"]["name"])
|
if "name" in data["appearance"].keys(): s.set(["appearance", "name"], data["appearance"]["name"])
|
||||||
if "color" in data["appearance"].keys(): s.set(["appearance", "color"], data["appearance"]["color"])
|
if "color" in data["appearance"].keys(): s.set(["appearance", "color"], data["appearance"]["color"])
|
||||||
|
|
|
@ -7,6 +7,7 @@ import os
|
||||||
import yaml
|
import yaml
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
import uuid
|
||||||
|
|
||||||
APPNAME="OctoPrint"
|
APPNAME="OctoPrint"
|
||||||
|
|
||||||
|
@ -89,6 +90,10 @@ default_settings = {
|
||||||
"gcodeCommandTrigger": {
|
"gcodeCommandTrigger": {
|
||||||
"enabled": False
|
"enabled": False
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"allow": False,
|
||||||
|
"key": ''.join('%02X' % ord(z) for z in uuid.uuid4().bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1310,6 +1310,9 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
|
||||||
self.loginState = loginStateViewModel;
|
self.loginState = loginStateViewModel;
|
||||||
self.users = usersViewModel;
|
self.users = usersViewModel;
|
||||||
|
|
||||||
|
self.api_allow = ko.observable(undefined);
|
||||||
|
self.api_key = ko.observable(undefined);
|
||||||
|
|
||||||
self.appearance_name = ko.observable(undefined);
|
self.appearance_name = ko.observable(undefined);
|
||||||
self.appearance_color = ko.observable(undefined);
|
self.appearance_color = ko.observable(undefined);
|
||||||
|
|
||||||
|
@ -1362,6 +1365,9 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fromResponse = function(response) {
|
self.fromResponse = function(response) {
|
||||||
|
self.api_allow(response.api.allow);
|
||||||
|
self.api_key(response.api.key);
|
||||||
|
|
||||||
self.appearance_name(response.appearance.name);
|
self.appearance_name(response.appearance.name);
|
||||||
self.appearance_color(response.appearance.color);
|
self.appearance_color(response.appearance.color);
|
||||||
|
|
||||||
|
@ -1396,6 +1402,10 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
|
||||||
|
|
||||||
self.saveData = function() {
|
self.saveData = function() {
|
||||||
var data = {
|
var data = {
|
||||||
|
"api" : {
|
||||||
|
"allow": self.api_allow(),
|
||||||
|
"key": self.api_key()
|
||||||
|
},
|
||||||
"appearance" : {
|
"appearance" : {
|
||||||
"name": self.appearance_name(),
|
"name": self.appearance_name(),
|
||||||
"color": self.appearance_color()
|
"color": self.appearance_color()
|
||||||
|
|
|
@ -580,7 +580,6 @@
|
||||||
{% include 'settings.jinja2' %}
|
{% include 'settings.jinja2' %}
|
||||||
{% include 'dialogs.jinja2' %}
|
{% include 'dialogs.jinja2' %}
|
||||||
|
|
||||||
<!--<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>-->
|
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery/jquery.min.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/jquery/jquery.min.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/modernizr.custom.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/modernizr.custom.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/underscore.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/underscore.js') }}"></script>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<li><a href="#settings_temperature" data-toggle="tab">Temperature</a></li>
|
<li><a href="#settings_temperature" data-toggle="tab">Temperature</a></li>
|
||||||
<li><a href="#settings_appearance" data-toggle="tab">Appearance</a></li>
|
<li><a href="#settings_appearance" data-toggle="tab">Appearance</a></li>
|
||||||
{% if enableAccessControl %}<li><a href="#settings_users" data-toggle="tab">Users</a></li>{% endif %}
|
{% if enableAccessControl %}<li><a href="#settings_users" data-toggle="tab">Users</a></li>{% endif %}
|
||||||
|
<li><a href="#settings_api" data-toggle="tab">Api</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="tab-content span8">
|
<div class="tab-content span8">
|
||||||
|
@ -218,6 +219,23 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tab-pane" id="settings_api">
|
||||||
|
<form class="form-horizontal">
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" id="settings-apiallow" data-bind="checked: api_allow"> Allow
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label" for="settings-apikey">Apikey</label>
|
||||||
|
<div class="controls">
|
||||||
|
<input type="text" class="input-block-level" data-bind="value: api_key" id="settings-apikey">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if enableAccessControl %}
|
{% if enableAccessControl %}
|
||||||
<div class="tab-pane" id="settings_users">
|
<div class="tab-pane" id="settings_users">
|
||||||
|
|
Loading…
Reference in New Issue