Migrated existing javascript application files to use client lib

TODO: Testing & Debugging
This commit is contained in:
Gina Häußge 2015-09-25 13:53:42 +02:00
parent 1678951d84
commit bbd728c51b
28 changed files with 779 additions and 1119 deletions

View file

@ -53,26 +53,22 @@ $(function() {
};
self._sendData = function(data, callback) {
$.ajax({
url: BASEURL + "plugin/corewizard/acl",
type: "POST",
dataType: "json",
data: data,
success: function() {
OctoPrint.postJson("plugin/corewizard/acl", data)
.done(function() {
self.setup(true);
self.decision(data.ac);
if (data.ac) {
// we now log the user in
var user = data.user;
var pass = data.pass1;
self.loginStateViewModel.login(user, pass, true, function() {
if (callback) callback();
});
self.loginStateViewModel.login(user, pass, true)
.done(function() {
if (callback) callback();
});
} else {
if (callback) callback();
}
}
});
});
};
self.onWizardTabChange = function(current, next) {

View file

@ -70,6 +70,7 @@ $(function() {
dataType: "json",
maxNumberOfFiles: 1,
autoUpload: false,
headers: OctoPrint.getRequestHeaders(),
add: function(e, data) {
if (data.files.length == 0) {
return false;
@ -131,14 +132,11 @@ $(function() {
return (item.key == data.key);
});
$.ajax({
url: data.resource(),
type: "DELETE",
success: function() {
OctoPrint.slicing.deleteProfileForSlicer("cura", data.key, {url: data.resource})
.done(function() {
self.requestData();
self.slicingViewModel.requestData();
}
});
});
};
self.makeProfileDefault = function(data) {
@ -156,16 +154,10 @@ $(function() {
item.isdefault(true);
}
$.ajax({
url: data.resource(),
type: "PATCH",
dataType: "json",
data: JSON.stringify({default: true}),
contentType: "application/json; charset=UTF-8",
success: function() {
OctoPrint.slicing.updateProfileForSlicer("cura", data.key, {default: true}, {url: data.resource()})
.done(function() {
self.requestData();
}
});
});
};
self.showImportProfileDialog = function(makeDefault) {
@ -199,28 +191,13 @@ $(function() {
}
}
$.ajax({
url: API_BASEURL + "util/test",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "path",
path: enginePath,
check_type: "file",
check_access: "x"
}),
contentType: "application/json; charset=UTF-8",
success: successCallback
})
OctoPrint.util.test("path", {path: enginePath, check_type: "file", check_access: "x"})
.done(successCallback);
};
self.requestData = function() {
$.ajax({
url: API_BASEURL + "slicing/cura/profiles",
type: "GET",
dataType: "json",
success: self.fromResponse
});
OctoPrint.slicing.listProfilesForSlicer("cura")
.done(self.fromResponse);
};
self.fromResponse = function(data) {

View file

@ -1,4 +1,66 @@
$(function() {
OctoPrint.plugins.pluginmanager = (function($, _) {
var exports = {};
exports.get = function(refresh, opts) {
return OctoPrint.get(OctoPrint.getSimpleApiUrl("pluginmanager") + ((refresh) ? "?refresh_repository=true" : ""), opts);
};
exports.getWithRefresh = function(opts) {
return exports.get(true, opts);
};
exports.getWithoutRefresh = function(opts) {
return exports.get(false, opts);
};
exports.install = function(pluginUrl, dependencyLinks, opts) {
var data = {
url: pluginUrl,
dependency_links: !!dependencyLinks
};
return OctoPrint.simpleApiCommand(plugin, "install", data, opts);
};
exports.reinstall = function(plugin, pluginUrl, dependencyLinks, opts) {
var data = {
url: pluginUrl,
dependency_links: !!dependencyLinks,
reinstall: plugin,
force: true
};
return OctoPrint.simpleApiCommand(plugin, "install", data, opts);
};
exports.uninstall = function(plugin, opts) {
var data = {
plugin: plugin
};
return OctoPrint.simpleApiCommand(plugin, "uninstall", data, opts);
};
exports.enable = function(plugin, opts) {
var data = {
plugin: plugin
};
return OctoPrint.simpleApiCommand(plugin, "enable", data, opts);
};
exports.disable = function(plugin, opts) {
var data = {
plugin: plugin
};
return OctoPrint.simpleApiCommand(plugin, "disable", data, opts);
};
exports.upload = function(file) {
return OctoPrint.upload(OctoPrint.getBlueprintUrl("pluginmanager") + "upload_archive", file);
};
return exports;
})($, _);
function PluginManagerViewModel(parameters) {
var self = this;
@ -193,12 +255,8 @@ $(function() {
return;
}
$.ajax({
url: API_BASEURL + "plugin/pluginmanager" + ((includeRepo) ? "?refresh_repository=true" : ""),
type: "GET",
dataType: "json",
success: self.fromResponse
});
OctoPrint.plugins.pluginmanager.get(includeRepo)
.done(self.fromResponse);
};
self.togglePlugin = function(data) {
@ -212,19 +270,25 @@ $(function() {
if (data.key == "pluginmanager") return;
var command = self._getToggleCommand(data);
var onSuccess = self.requestData,
onError = function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
})
};
var payload = {plugin: data.key};
self._postCommand(command, payload, function(response) {
self.requestData();
}, function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
})
});
if (self._getToggleCommand(data) == "enable") {
OctoPrint.plugins.pluginmanager.enable(data.key)
.done(onSuccess)
.fail(onError);
} else {
OctoPrint.plugins.pluginmanager.disable(data.key)
.done(onSuccess)
.fail(onError);
}
};
self.showRepository = function() {
@ -244,11 +308,7 @@ $(function() {
return;
}
if (self.installed(data)) {
self.installPlugin(data.archive, data.title, data.id, data.follow_dependency_links || self.followDependencyLinks());
} else {
self.installPlugin(data.archive, data.title, undefined, data.follow_dependency_links || self.followDependencyLinks());
}
self.installPlugin(data.archive, data.title, (self.installed(data) ? data.id : undefined), data.follow_dependency_links || self.followDependencyLinks());
};
self.installPlugin = function(url, name, reinstall, followDependencyLinks) {
@ -283,26 +343,33 @@ $(function() {
}
self._markWorking(workTitle, workText);
var command = "install";
var payload = {url: url, dependency_links: followDependencyLinks};
if (reinstall) {
payload["plugin"] = reinstall;
payload["force"] = true;
}
var onSuccess = function() {
self.requestData();
self.installUrl("");
},
onError = function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
});
},
onAlways = function() {
self._markDone();
};
self._postCommand(command, payload, function(response) {
self.requestData();
self._markDone();
self.installUrl("");
}, function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
});
self._markDone();
});
if (reinstall) {
OctoPrint.plugins.pluginmanager.reinstall(reinstall, url, followDependencyLinks)
.done(onSuccess)
.fail(onError)
.always(onAlways);
} else {
OctoPrint.plugins.pluginmanager.install(url, followDependencyLinks)
.done(onSuccess)
.fail(onError)
.always(onAlways);
}
};
self.uninstallPlugin = function(data) {
@ -319,20 +386,19 @@ $(function() {
self._markWorking(gettext("Uninstalling plugin..."), _.sprintf(gettext("Uninstalling plugin \"%(name)s\""), {name: data.name}));
var command = "uninstall";
var payload = {plugin: data.key};
self._postCommand(command, payload, function(response) {
self.requestData();
self._markDone();
}, function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
OctoPrint.plugins.pluginmanager.uninstall(data.key)
.done(self.requestData)
.fail(function() {
new PNotify({
title: gettext("Something went wrong"),
text: gettext("Please consult octoprint.log for details"),
type: "error",
hide: false
});
})
.always(function() {
self._markDone();
});
self._markDone();
});
};
self.refreshRepository = function() {
@ -400,33 +466,6 @@ $(function() {
}
};
self._postCommand = function (command, data, successCallback, failureCallback, alwaysCallback, timeout) {
var payload = _.extend(data, {command: command});
var params = {
url: API_BASEURL + "plugin/pluginmanager",
type: "POST",
dataType: "json",
data: JSON.stringify(payload),
contentType: "application/json; charset=UTF-8",
success: function(response) {
if (successCallback) successCallback(response);
},
error: function() {
if (failureCallback) failureCallback();
},
complete: function() {
if (alwaysCallback) alwaysCallback();
}
};
if (timeout != undefined) {
params.timeout = timeout;
}
$.ajax(params);
};
self._markWorking = function(title, line) {
self.working(true);
self.workingTitle(title);

View file

@ -1,4 +1,38 @@
$(function() {
OctoPrint.plugins.softwareupdate = (function($, _) {
var exports = {};
var url = OctoPrint.getBlueprintUrl("softwareupdate");
var checkUrl = url + "check";
var updateUrl = url + "update";
exports.check = function(force, opts) {
return OctoPrint.get(checkUrl + ((!!force) ? "?force=true" : ""), opts);
};
exports.update = function(entries, force, opts) {
entries = entries || [];
if (typeof entries == "string") {
entries = [entries];
}
var data = {
entries: entries,
force: !!force
};
return OctoPrint.postJson(updateUrl, data, opts);
};
exports.updateAll = function(force, opts) {
var data = {
force: !!force
};
return OctoPrint.postJson(updateUrl, data, opts);
};
return exports;
})($, _);
function SoftwareUpdateViewModel(parameters) {
var self = this;
@ -221,20 +255,10 @@ $(function() {
self.performCheck = function(showIfNothingNew, force, ignoreSeen) {
if (!self.loginState.isUser()) return;
var url = PLUGIN_BASEURL + "softwareupdate/check";
if (force) {
url += "?force=true";
}
$.ajax({
url: url,
type: "GET",
dataType: "json",
success: function(data) {
OctoPrint.plugins.softwareupdate.check(force)
.done(function(data) {
self.fromCheckResponse(data, ignoreSeen, showIfNothingNew);
}
});
});
};
self._markNotificationAsSeen = function(data) {
@ -285,13 +309,12 @@ $(function() {
};
self._showPopup(options);
$.ajax({
url: PLUGIN_BASEURL + "softwareupdate/update",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({force: (force == true)}),
error: function() {
OctoPrint.plugins.softwareupdate.updateAll(force)
.done(function(data) {
self.currentlyBeingUpdated = data.checks;
self._markWorking(gettext("Updating..."), gettext("Updating, please wait."));
})
.fail(function() {
self.updateInProgress = false;
self._showPopup({
title: gettext("Update not started!"),
@ -302,12 +325,7 @@ $(function() {
sticker: false
}
});
},
success: function(data) {
self.currentlyBeingUpdated = data.checks;
self._markWorking(gettext("Updating..."), gettext("Updating, please wait."));
}
});
});
};
self.update = function(force) {

View file

@ -912,6 +912,25 @@ class Server(object):
"js/lib/loglevel.min.js",
"js/lib/sockjs-0.3.4.min.js"
]
js_client = [
"js/app/client/octoprint.js",
"js/app/client/socket.js",
"js/app/client/browser.js",
"js/app/client/connection.js",
"js/app/client/control.js",
"js/app/client/files.js",
"js/app/client/job.js",
"js/app/client/languages.js",
"js/app/client/logs.js",
"js/app/client/printer.js",
"js/app/client/printerprofiles.js",
"js/app/client/settings.js",
"js/app/client/slicing.js",
"js/app/client/timelapse.js",
"js/app/client/users.js",
"js/app/client/util.js",
"js/app/client/wizard.js"
]
js_app = dynamic_assets["js"] + [
"js/app/dataupdater.js",
"js/app/helpers.js",
@ -966,8 +985,10 @@ class Server(object):
js_libs_bundle = Bundle(*js_libs, output="webassets/packed_libs.js", filters="js_delimiter_bundler")
if minify:
js_client_bundle = Bundle(*js_client, output="webassets/packed_client.js", filters="rjsmin, js_delimiter_bundler")
js_app_bundle = Bundle(*js_app, output="webassets/packed_app.js", filters="rjsmin, js_delimiter_bundler")
else:
js_client_bundle = Bundle(*js_client, output="webassets/packed_client.js", filters="js_delimiter_bundler")
js_app_bundle = Bundle(*js_app, output="webassets/packed_app.js", filters="js_delimiter_bundler")
css_libs_bundle = Bundle(*css_libs, output="webassets/packed_libs.css")
@ -976,6 +997,7 @@ class Server(object):
all_less_bundle = Bundle(*less_app, output="webassets/packed_app.less", filters="cssrewrite, less_importrewrite")
assets.register("js_libs", js_libs_bundle)
assets.register("js_client", js_client_bundle)
assets.register("js_app", js_app_bundle)
assets.register("css_libs", css_libs_bundle)
assets.register("css_app", css_app_bundle)

View file

@ -217,7 +217,11 @@ def performSystemAction():
@api.route("/login", methods=["POST"])
def login():
if octoprint.server.userManager is not None and "user" in request.values.keys() and "pass" in request.values.keys():
data = request.values
if hasattr(request, "json") and request.json:
data = request.json
if octoprint.server.userManager is not None and "user" in data and "pass" in data:
username = request.values["user"]
password = request.values["pass"]
@ -241,7 +245,7 @@ def login():
return jsonify(user.asDict())
return make_response(("User unknown or password incorrect", 401, []))
elif "passive" in request.values:
elif "passive" in data:
return passive_login()
return NO_CONTENT

View file

@ -573,4 +573,3 @@ def localeJs(locale, domain):
def plugin_assets(name, filename):
return redirect(url_for("plugin." + name + ".static", filename=filename))

View file

@ -1,79 +0,0 @@
var OctoPrint = (function($, _, SockJS) {
var self = {
options: {
socketReconnectTimeouts: [0, 1, 1, 2, 3, 5, 8, 13, 20, 40, 100],
socketDebug: false,
socketNormalClose: 1000
}
};
var _socket = undefined;
var _socketAddress = undefined;
var _socketReconnecting = false;
var _socketReconnectTrial = 0;
var _socketIgnoreReconnects = 1;
function callCallback(callback, arguments) {
if (!_.isFunction(self.options[callback])) {
throw Error("No such callback: " + callback);
}
self.options[callback].bind(arguments);
}
function connect(socketAddress) {
var address = socketAddress || _socketAddress;
if (address == undefined) {
return;
}
var socketOptions = {
debug: options.socketDebug || false
};
if (_socket != undefined) {
self._socket.close();
delete self._socket;
}
_socketAddress = address;
_socket = new SockJS(address, undefined, socketOptions);
_socket.onopen = onSocketOpen;
_socket.onclose = onSocketClose;
_socket.onmessage = onSocketMessage;
}
function onSocketOpen() {
_socketReconnecting = false;
_socketReconnectTrial = 0;
}
function onSocketClose(error) {
if (error.code == options.socketNormalClose) {
return;
}
if (_socketReconnectTrial >= _socketIgnoreReconnects) {
if (options.onAttemptingReconnect) {
options.onAttemptingReconnect(_socketReconnectTrial);
}
}
if (_socketReconnectTrial < options.socketReconnectTimeouts.length) {
var timeout = options.socketReconnectTimeouts[_socketReconnectTrial];
log.info("Reconnect trial #" + self._autoReconnectTrial + ", waiting " + timeout + "s");
setTimeout(connect, timeout * 1000);
_socketReconnectTrial++;
} else {
if (options.onReconnectFailed) {
options.onReconnectFailed();
}
}
}
function onSocketMessage(data) {
}
return self;
}(jQuery, _, SockJS));

View file

@ -3,12 +3,6 @@ function DataUpdater(allViewModels) {
self.allViewModels = allViewModels;
self._socket = undefined;
self._autoReconnecting = false;
self._autoReconnectTrial = 0;
self._autoReconnectTimeouts = [0, 1, 1, 2, 3, 5, 8, 13, 20, 40, 100];
self._autoReconnectDialogIndex = 1;
self._pluginHash = undefined;
self._configHash = undefined;
@ -16,65 +10,39 @@ function DataUpdater(allViewModels) {
$("#reloadui_overlay_reload").click(function() { location.reload(true); });
self.connect = function() {
var options = {};
if (SOCKJS_DEBUG) {
options["debug"] = true;
}
self._socket = new SockJS(SOCKJS_URI, undefined, options);
self._socket.onopen = self._onconnect;
self._socket.onclose = self._onclose;
self._socket.onmessage = self._onmessage;
OctoPrint.socket.connect({debug: !!SOCKJS_DEBUG});
};
self.reconnect = function() {
self._socket.close();
delete self._socket;
self.connect();
OctoPrint.socket.reconnect();
};
self._onconnect = function() {
self._autoReconnecting = false;
self._autoReconnectTrial = 0;
};
self._onclose = function(e) {
if (e.code == SOCKJS_CLOSE_NORMAL) {
self._onReconnectAttempt = function(trial) {
if (trial <= 0) {
// Only consider it a real disconnect if the trial number has exceeded our threshold.
return;
}
if (self._autoReconnectTrial >= self._autoReconnectDialogIndex) {
// Only consider it a real disconnect if the trial number has exceeded our threshold.
var handled = false;
callViewModelsIf(
self.allViewModels,
"onServerDisconnect",
function() { return !handled; },
function(method) { handled = !method() || handled; }
);
var handled = false;
callViewModelsIf(
self.allViewModels,
"onServerDisconnect",
function() { return !handled; },
function(method) { handled = !method() || handled; }
);
if (handled) {
return;
}
showOfflineOverlay(
gettext("Server is offline"),
gettext("The server appears to be offline, at least I'm not getting any response from it. I'll try to reconnect automatically <strong>over the next couple of minutes</strong>, however you are welcome to try a manual reconnect anytime using the button below."),
self.reconnect
);
if (handled) {
return true;
}
if (self._autoReconnectTrial < self._autoReconnectTimeouts.length) {
var timeout = self._autoReconnectTimeouts[self._autoReconnectTrial];
log.info("Reconnect trial #" + self._autoReconnectTrial + ", waiting " + timeout + "s");
setTimeout(self.reconnect, timeout * 1000);
self._autoReconnectTrial++;
} else {
self._onreconnectfailed();
}
showOfflineOverlay(
gettext("Server is offline"),
gettext("The server appears to be offline, at least I'm not getting any response from it. I'll try to reconnect automatically <strong>over the next couple of minutes</strong>, however you are welcome to try a manual reconnect anytime using the button below."),
self.reconnect
);
};
self._onreconnectfailed = function() {
self._onReconnectFailed = function() {
var handled = false;
callViewModelsIf(
self.allViewModels,
@ -91,182 +59,181 @@ function DataUpdater(allViewModels) {
$("#offline_overlay_message").html(gettext("The server appears to be offline, at least I'm not getting any response from it. I <strong>could not reconnect automatically</strong>, but you may try a manual reconnect using the button below."));
};
self._onmessage = function(e) {
for (var prop in e.data) {
if (!e.data.hasOwnProperty(prop)) {
continue;
self._onConnected = function(event) {
var data = event.data;
// update version information
var oldVersion = VERSION;
VERSION = data["version"];
DISPLAY_VERSION = data["display_version"];
BRANCH = data["branch"];
$("span.version").text(DISPLAY_VERSION);
// update plugin hash
var oldPluginHash = self._pluginHash;
self._pluginHash = data["plugin_hash"];
// update config hash
var oldConfigHash = self._configHash;
self._configHash = data["config_hash"];
// if the offline overlay is still showing, now's a good time to
// hide it, plus reload the camera feed if it's currently displayed
if ($("#offline_overlay").is(":visible")) {
hideOfflineOverlay();
callViewModels(self.allViewModels, "onDataUpdaterReconnect");
if ($('#tabs li[class="active"] a').attr("href") == "#control") {
$("#webcam_image").attr("src", CONFIG_WEBCAM_STREAM + "?" + new Date().getTime());
}
}
var data = e.data[prop];
var gcodeUploadProgress = $("#gcode_upload_progress");
var gcodeUploadProgressBar = $(".bar", gcodeUploadProgress);
switch (prop) {
case "connected": {
// update the current UI API key and send it with any request
UI_API_KEY = data["apikey"];
$.ajaxSetup({
headers: {"X-Api-Key": UI_API_KEY}
});
var oldVersion = VERSION;
VERSION = data["version"];
DISPLAY_VERSION = data["display_version"];
BRANCH = data["branch"];
$("span.version").text(DISPLAY_VERSION);
var oldPluginHash = self._pluginHash;
self._pluginHash = data["plugin_hash"];
var oldConfigHash = self._configHash;
self._configHash = data["config_hash"];
if ($("#offline_overlay").is(":visible")) {
hideOfflineOverlay();
callViewModels(self.allViewModels, "onDataUpdaterReconnect");
if ($('#tabs li[class="active"] a').attr("href") == "#control") {
$("#webcam_image").attr("src", CONFIG_WEBCAM_STREAM + "?" + new Date().getTime());
}
}
var versionChanged = oldVersion != VERSION;
var pluginsChanged = oldPluginHash != undefined && oldPluginHash != self._pluginHash;
var configChanged = oldConfigHash != undefined && oldConfigHash != self._configHash;
if (versionChanged || pluginsChanged || configChanged) {
self.reloadOverlay.show();
}
break;
}
case "history": {
callViewModels(self.allViewModels, "fromHistoryData", [data]);
break;
}
case "current": {
callViewModels(self.allViewModels, "fromCurrentData", [data]);
break;
}
case "slicingProgress": {
gcodeUploadProgressBar.text(_.sprintf(gettext("Slicing ... (%(percentage)d%%)"), {percentage: Math.round(data["progress"])}));
callViewModels(self.allViewModels, "onSlicingProgress", [
data["slicer"],
data["model_path"],
data["machinecode_path"],
data["progress"]
]);
break;
}
case "event": {
var type = data["type"];
var payload = data["payload"];
var html = "";
var format = {};
log.debug("Got event " + type + " with payload: " + JSON.stringify(payload));
if (type == "SettingsUpdated") {
if (payload && payload.hasOwnProperty("config_hash")) {
self._configHash = payload.config_hash;
}
} else if (type == "MovieRendering") {
new PNotify({title: gettext("Rendering timelapse"), text: _.sprintf(gettext("Now rendering timelapse %(movie_basename)s"), payload)});
} else if (type == "MovieDone") {
new PNotify({title: gettext("Timelapse ready"), text: _.sprintf(gettext("New timelapse %(movie_basename)s is done rendering."), payload)});
} else if (type == "MovieFailed") {
html = "<p>" + _.sprintf(gettext("Rendering of timelapse %(movie_basename)s failed with return code %(returncode)s"), payload) + "</p>";
html += pnotifyAdditionalInfo('<pre style="overflow: auto">' + payload.error + '</pre>');
new PNotify({
title: gettext("Rendering failed"),
text: html,
type: "error",
hide: false
});
} else if (type == "PostRollStart") {
if (payload.postroll_duration > 60) {
format = {duration: _.sprintf(gettext("%(minutes)d min"), {minutes: payload.postroll_duration / 60})};
} else {
format = {duration: _.sprintf(gettext("%(seconds)d sec"), {seconds: payload.postroll_duration})};
}
new PNotify({
title: gettext("Capturing timelapse postroll"),
text: _.sprintf(gettext("Now capturing timelapse post roll, this will take approximately %(duration)s..."), format)
});
} else if (type == "SlicingStarted") {
gcodeUploadProgress.addClass("progress-striped").addClass("active");
gcodeUploadProgressBar.css("width", "100%");
if (payload.progressAvailable) {
gcodeUploadProgressBar.text(_.sprintf(gettext("Slicing ... (%(percentage)d%%)"), {percentage: 0}));
} else {
gcodeUploadProgressBar.text(gettext("Slicing ..."));
}
} else if (type == "SlicingDone") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
new PNotify({title: gettext("Slicing done"), text: _.sprintf(gettext("Sliced %(stl)s to %(gcode)s, took %(time).2f seconds"), payload), type: "success"});
} else if (type == "SlicingCancelled") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
} else if (type == "SlicingFailed") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
html = _.sprintf(gettext("Could not slice %(stl)s to %(gcode)s: %(reason)s"), payload);
new PNotify({title: gettext("Slicing failed"), text: html, type: "error", hide: false});
} else if (type == "TransferStarted") {
gcodeUploadProgress.addClass("progress-striped").addClass("active");
gcodeUploadProgressBar.css("width", "100%");
gcodeUploadProgressBar.text(gettext("Streaming ..."));
} else if (type == "TransferDone") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
new PNotify({
title: gettext("Streaming done"),
text: _.sprintf(gettext("Streamed %(local)s to %(remote)s on SD, took %(time).2f seconds"), payload),
type: "success"
});
gcodeFilesViewModel.requestData(payload.remote, "sdcard");
}
var legacyEventHandlers = {
"UpdatedFiles": "onUpdatedFiles",
"MetadataStatisticsUpdated": "onMetadataStatisticsUpdated",
"MetadataAnalysisFinished": "onMetadataAnalysisFinished",
"SlicingDone": "onSlicingDone",
"SlicingCancelled": "onSlicingCancelled",
"SlicingFailed": "onSlicingFailed"
};
_.each(self.allViewModels, function(viewModel) {
if (viewModel.hasOwnProperty("onEvent" + type)) {
viewModel["onEvent" + type](payload);
} else if (legacyEventHandlers.hasOwnProperty(type) && viewModel.hasOwnProperty(legacyEventHandlers[type])) {
// there might still be code that uses the old callbacks, make sure those still get called
// but log a warning
log.warn("View model " + viewModel.name + " is using legacy event handler " + legacyEventHandlers[type] + ", new handler is called " + legacyEventHandlers[type]);
viewModel[legacyEventHandlers[type]](payload);
}
});
break;
}
case "timelapse": {
callViewModels(self.allViewModels, "fromTimelapseData", [data]);
break;
}
case "plugin": {
callViewModels(self.allViewModels, "onDataUpdaterPluginMessage", [data.plugin, data.data]);
break;
}
}
// if the version, the plugin hash or the config hash changed, we
// want the user to reload the UI since it might be stale now
var versionChanged = oldVersion != VERSION;
var pluginsChanged = oldPluginHash != undefined && oldPluginHash != self._pluginHash;
var configChanged = oldConfigHash != undefined && oldConfigHash != self._configHash;
if (versionChanged || pluginsChanged || configChanged) {
self.reloadOverlay.show();
}
};
self._onHistoryData = function(event) {
callViewModels(self.allViewModels, "fromHistoryData", [event.data]);
};
self._onCurrentData = function(event) {
callViewModels(self.allViewModels, "fromCurrentData", [event.data]);
};
self._onSlicingProgress = function(event) {
$("#gcode_upload_progress").find(".bar").text(_.sprintf(gettext("Slicing ... (%(percentage)d%%)"), {percentage: Math.round(event.data["progress"])}));
callViewModels(self.allViewModels, "onSlicingProgress", [
data["slicer"],
data["model_path"],
data["machinecode_path"],
data["progress"]
]);
};
self._onEvent = function(event) {
var gcodeUploadProgress = $("#gcode_upload_progress");
var gcodeUploadProgressBar = $(".bar", gcodeUploadProgress);
var type = event.data["type"];
var payload = event.data["payload"];
var html = "";
var format = {};
log.debug("Got event " + type + " with payload: " + JSON.stringify(payload));
if (type == "SettingsUpdated") {
if (payload && payload.hasOwnProperty("config_hash")) {
self._configHash = payload.config_hash;
}
} else if (type == "MovieRendering") {
new PNotify({title: gettext("Rendering timelapse"), text: _.sprintf(gettext("Now rendering timelapse %(movie_basename)s"), payload)});
} else if (type == "MovieDone") {
new PNotify({title: gettext("Timelapse ready"), text: _.sprintf(gettext("New timelapse %(movie_basename)s is done rendering."), payload)});
} else if (type == "MovieFailed") {
html = "<p>" + _.sprintf(gettext("Rendering of timelapse %(movie_basename)s failed with return code %(returncode)s"), payload) + "</p>";
html += pnotifyAdditionalInfo('<pre style="overflow: auto">' + payload.error + '</pre>');
new PNotify({
title: gettext("Rendering failed"),
text: html,
type: "error",
hide: false
});
} else if (type == "PostRollStart") {
if (payload.postroll_duration > 60) {
format = {duration: _.sprintf(gettext("%(minutes)d min"), {minutes: payload.postroll_duration / 60})};
} else {
format = {duration: _.sprintf(gettext("%(seconds)d sec"), {seconds: payload.postroll_duration})};
}
new PNotify({
title: gettext("Capturing timelapse postroll"),
text: _.sprintf(gettext("Now capturing timelapse post roll, this will take approximately %(duration)s..."), format)
});
} else if (type == "SlicingStarted") {
gcodeUploadProgress.addClass("progress-striped").addClass("active");
gcodeUploadProgressBar.css("width", "100%");
if (payload.progressAvailable) {
gcodeUploadProgressBar.text(_.sprintf(gettext("Slicing ... (%(percentage)d%%)"), {percentage: 0}));
} else {
gcodeUploadProgressBar.text(gettext("Slicing ..."));
}
} else if (type == "SlicingDone") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
new PNotify({title: gettext("Slicing done"), text: _.sprintf(gettext("Sliced %(stl)s to %(gcode)s, took %(time).2f seconds"), payload), type: "success"});
} else if (type == "SlicingCancelled") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
} else if (type == "SlicingFailed") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
html = _.sprintf(gettext("Could not slice %(stl)s to %(gcode)s: %(reason)s"), payload);
new PNotify({title: gettext("Slicing failed"), text: html, type: "error", hide: false});
} else if (type == "TransferStarted") {
gcodeUploadProgress.addClass("progress-striped").addClass("active");
gcodeUploadProgressBar.css("width", "100%");
gcodeUploadProgressBar.text(gettext("Streaming ..."));
} else if (type == "TransferDone") {
gcodeUploadProgress.removeClass("progress-striped").removeClass("active");
gcodeUploadProgressBar.css("width", "0%");
gcodeUploadProgressBar.text("");
new PNotify({
title: gettext("Streaming done"),
text: _.sprintf(gettext("Streamed %(local)s to %(remote)s on SD, took %(time).2f seconds"), payload),
type: "success"
});
gcodeFilesViewModel.requestData(payload.remote, "sdcard");
}
var legacyEventHandlers = {
"UpdatedFiles": "onUpdatedFiles",
"MetadataStatisticsUpdated": "onMetadataStatisticsUpdated",
"MetadataAnalysisFinished": "onMetadataAnalysisFinished",
"SlicingDone": "onSlicingDone",
"SlicingCancelled": "onSlicingCancelled",
"SlicingFailed": "onSlicingFailed"
};
_.each(self.allViewModels, function(viewModel) {
if (viewModel.hasOwnProperty("onEvent" + type)) {
viewModel["onEvent" + type](payload);
} else if (legacyEventHandlers.hasOwnProperty(type) && viewModel.hasOwnProperty(legacyEventHandlers[type])) {
// there might still be code that uses the old callbacks, make sure those still get called
// but log a warning
log.warn("View model " + viewModel.name + " is using legacy event handler " + legacyEventHandlers[type] + ", new handler is called " + legacyEventHandlers[type]);
viewModel[legacyEventHandlers[type]](payload);
}
});
};
self._onTimelapse = function(event) {
callViewModels(self.allViewModels, "fromTimelapseData", [event.data]);
};
self._onPluginMessage = function(event) {
callViewModels(self.allViewModels, "onDataUpdaterPluginMessage", [event.data.plugin, event.data.data]);
};
OctoPrint.socket.onReconnectAttempt = self._onReconnectAttempt;
OctoPrint.socket.onReconnectFailed = self._onReconnectFailed;
OctoPrint.socket
.onMessage("connected", self._onConnected)
.onMessage("history", self._onHistoryData)
.onMessage("current", self._onCurrentData)
.onMessage("slicingProgress", self._onSlicingProgress)
.onMessage("event", self._onEvent)
.onMessage("timelapse", self._onTimelapse)
.onMessage("plugin", self._onPluginMessage);
self.connect();
}

View file

@ -7,6 +7,22 @@ $(function() {
log.setLevel(CONFIG_DEBUG ? "debug" : "info");
//~~ OctoPrint client setup
OctoPrint.options.baseurl = BASEURL;
OctoPrint.options.apikey = UI_API_KEY;
OctoPrint.socket.onMessage("connected", function(data) {
OctoPrint.options.apikey = data.apikey;
// update the API key directly in jquery's ajax options too,
// to ensure the fileupload plugin and any plugins still using
// $.ajax directly still work fine too
UI_API_KEY = data["apikey"];
$.ajaxSetup({
headers: {"X-Api-Key": UI_API_KEY}
});
});
//~~ AJAX setup
// work around a stupid iOS6 bug where ajax requests get cached and only work once, as described at

View file

@ -47,14 +47,8 @@ $(function() {
self.previousIsOperational = undefined;
self.requestData = function() {
$.ajax({
url: API_BASEURL + "connection",
method: "GET",
dataType: "json",
success: function(response) {
self.fromResponse(response);
}
})
OctoPrint.connection.getSettings()
.done(self.fromResponse);
};
self.fromResponse = function(response) {
@ -93,7 +87,7 @@ $(function() {
} else if (!self.isOperational() && !connectionTab.hasClass("in")) {
connectionTab.collapse("show");
}
}
};
self._processStateData = function(data) {
self.previousIsOperational = self.isOperational();
@ -116,7 +110,6 @@ $(function() {
self.connect = function() {
if (self.isErrorOrClosed()) {
var data = {
"command": "connect",
"port": self.selectedPort() || "AUTO",
"baudrate": self.selectedBaudrate() || 0,
"printerProfile": self.selectedPrinter(),
@ -126,26 +119,14 @@ $(function() {
if (self.saveSettings())
data["save"] = true;
$.ajax({
url: API_BASEURL + "connection",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data),
success: function(response) {
OctoPrint.connection.connect(data)
.done(function() {
self.settings.requestData();
self.settings.printerProfiles.requestData();
}
});
});
} else {
self.requestData();
$.ajax({
url: API_BASEURL + "connection",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({"command": "disconnect"})
})
OctoPrint.connection.disconnect();
}
};

View file

@ -108,14 +108,10 @@ $(function() {
};
self.requestData = function () {
$.ajax({
url: API_BASEURL + "printer/command/custom",
method: "GET",
dataType: "json",
success: function (response) {
OctoPrint.control.getCustomControls()
.done(function(response) {
self._fromResponse(response);
}
});
});
};
self._fromResponse = function (response) {
@ -254,26 +250,17 @@ $(function() {
multiplier *= -1;
}
var data = {
"command": "jog"
};
var data = {};
data[axis] = distance * multiplier;
self.sendPrintHeadCommand(data);
OctoPrint.printer.jog(data);
};
self.sendHomeCommand = function (axis) {
self.sendPrintHeadCommand({
"command": "home",
"axes": axis
});
OctoPrint.printer.home(axis);
};
self.sendFeedRateCommand = function () {
self.sendPrintHeadCommand({
"command": "feedrate",
"factor": self.feedRate()
});
OctoPrint.printer.setFeedrate(self.feedRate());
};
self.sendExtrudeCommand = function () {
@ -285,90 +272,46 @@ $(function() {
};
self.sendFlowRateCommand = function () {
self.sendToolCommand({
"command": "flowrate",
"factor": self.flowRate()
});
OctoPrint.printer.setFlowrate(self.flowRate());
};
self._sendECommand = function (dir) {
var length = self.extrusionAmount();
if (!length) length = self.settings.printer_defaultExtrusionLength();
self.sendToolCommand({
command: "extrude",
amount: length * dir
});
var length = self.extrusionAmount() || self.settings.printer_defaultExtrusionLength();
OctoPrint.printer.extrude(length * dir);
};
self.sendSelectToolCommand = function (data) {
if (!data || !data.key()) return;
self.sendToolCommand({
command: "select",
tool: data.key()
});
};
self.sendPrintHeadCommand = function (data) {
$.ajax({
url: API_BASEURL + "printer/printhead",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data)
});
};
self.sendToolCommand = function (data) {
$.ajax({
url: API_BASEURL + "printer/tool",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data)
});
OctoPrint.printer.selectTool(data.key());
};
self.sendCustomCommand = function (command) {
if (!command)
return;
var data = undefined;
if (command.hasOwnProperty("command")) {
// single command
data = {"command": command.command};
} else if (command.hasOwnProperty("commands")) {
// multi command
data = {"commands": command.commands};
} else if (command.hasOwnProperty("script")) {
data = {"script": command.script};
if (command.hasOwnProperty("context")) {
data["context"] = command.context;
if (command.hasOwnProperty("command") || command.hasOwnProperty("commands")) {
var commands = command.commands || [command.command];
if (commands.hasOwnProperty("input")) {
var parameters = {};
_.each(command.input, function(input) {
if (!input.hasOwnProperty("parameter") || !input.hasOwnProperty("value")) {
return;
}
parameters[input.parameter] = input.value();
});
OctoPrint.control.sendGcodeWithParameters(commands, parameters);
} else {
OctoPrint.control.sendGcode(commands);
}
} else {
return;
} else if (command.hasOwnProperty("script")) {
var script = command.script;
var context = command.context || {};
OctoPrint.control.sendGcodeScript(script, context);
}
if (command.hasOwnProperty("input")) {
// parametric command(s)
data["parameters"] = {};
_.each(command.input, function(input) {
if (!input.hasOwnProperty("parameter") || !input.hasOwnProperty("value")) {
return;
}
data["parameters"][input.parameter] = input.value();
});
}
$.ajax({
url: API_BASEURL + "printer/command",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data)
})
};
self.displayMode = function (customControl) {
@ -414,7 +357,7 @@ $(function() {
} else {
$("#webcam_rotator").css("height", "");
}
}
};
self.onSettingsBeforeSave = self.updateRotatorWidth;

View file

@ -146,18 +146,13 @@ $(function() {
if (self._otherRequestInProgress) return;
self._otherRequestInProgress = true;
$.ajax({
url: API_BASEURL + "files",
method: "GET",
dataType: "json",
success: function(response) {
OctoPrint.files.list()
.done(function(response) {
self.fromResponse(response, filenameToFocus, locationToFocus);
})
.always(function() {
self._otherRequestInProgress = false;
},
error: function() {
self._otherRequestInProgress = false;
}
});
});
};
self.fromResponse = function(response, filenameToFocus, locationToFocus) {
@ -192,55 +187,45 @@ $(function() {
};
self.loadFile = function(file, printAfterLoad) {
if (!file || !file.refs || !file.refs.hasOwnProperty("resource")) return;
$.ajax({
url: file.refs.resource,
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({command: "select", print: printAfterLoad})
});
if (!file) {
return;
}
OctoPrint.files.select(file.origin, file.name)
.done(function() {
if (printAfterLoad) {
OctoPrint.job.start();
}
});
};
self.removeFile = function(file) {
if (!file || !file.refs || !file.refs.hasOwnProperty("resource")) return;
$.ajax({
url: file.refs.resource,
type: "DELETE",
success: function() {
if (!file) {
return;
}
OctoPrint.files.delete(file.origin, file.name)
.done(function() {
self.requestData();
}
});
})
};
self.sliceFile = function(file) {
if (!file) return;
if (!file) {
return;
}
self.slicing.show(file.origin, file.name, true);
};
self.initSdCard = function() {
self._sendSdCommand("init");
OctoPrint.printer.initSd();
};
self.releaseSdCard = function() {
self._sendSdCommand("release");
OctoPrint.printer.releaseSd();
};
self.refreshSdFiles = function() {
self._sendSdCommand("refresh");
};
self._sendSdCommand = function(command) {
$.ajax({
url: API_BASEURL + "printer/sd",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({command: command})
});
OctoPrint.printer.refreshSd();
};
self.downloadLink = function(data) {

View file

@ -289,11 +289,8 @@ $(function() {
self.enableReload(false);
if (self.status == "idle" && self.errorCount < 3) {
self.status = "request";
$.ajax({
url: BASEURL + "downloads/files/local/" + filename,
data: { "ctime": date },
type: "GET",
success: function(response, rstatus) {
OctoPrint.files.download("local", filename)
.done(function(response, rstatus) {
if(rstatus === 'success'){
self.showGCodeViewer(response, rstatus);
self.loadedFilename = filename;
@ -301,12 +298,11 @@ $(function() {
self.status = "idle";
self.enableReload(true);
}
},
error: function() {
})
.fail(function() {
self.status = "idle";
self.errorCount++;
}
});
});
}
};

View file

@ -36,12 +36,8 @@ $(function() {
);
self.requestData = function() {
$.ajax({
url: API_BASEURL + "logs",
type: "GET",
dataType: "json",
success: self.fromResponse
});
OctoPrint.logs.list()
.done(self.fromResponse);
};
self.fromResponse = function(response) {
@ -53,12 +49,8 @@ $(function() {
};
self.removeFile = function(filename) {
$.ajax({
url: API_BASEURL + "logs/" + filename,
type: "DELETE",
dataType: "json",
success: self.requestData
});
OctoPrint.logs.delete(filename)
.done(self.requestData);
};
self.onUserLoggedIn = function(user) {
@ -73,4 +65,4 @@ $(function() {
["loginStateViewModel"],
"#logs"
]);
});
});

View file

@ -32,20 +32,13 @@ $(function() {
return;
}
$.ajax({
url: API_BASEURL + "users/" + self.currentUser().name,
type: "GET",
success: self.fromResponse
})
OctoPrint.users.get(self.currentUser().name)
.done(self.fromResponse);
};
self.requestData = function() {
$.ajax({
url: API_BASEURL + "login",
type: "POST",
data: {"passive": true},
success: self.fromResponse
})
OctoPrint.browser.passiveLogin()
.done(self.fromResponse);
};
self.fromResponse = function(response) {
@ -70,7 +63,7 @@ $(function() {
}
};
self.login = function(u, p, r, callback) {
self.login = function(u, p, r) {
var username = u || self.loginUser();
var password = p || self.loginPass();
var remember = (r != undefined ? r : self.loginRemember());
@ -79,30 +72,22 @@ $(function() {
self.loginPass("");
self.loginRemember(false);
$.ajax({
url: API_BASEURL + "login",
type: "POST",
data: {"user": username, "pass": password, "remember": remember},
success: function(response) {
return OctoPrint.browser.login(username, password, remember)
.done(function(response) {
new PNotify({title: gettext("Login successful"), text: _.sprintf(gettext('You are now logged in as "%(username)s"'), {username: response.name}), type: "success"});
self.fromResponse(response);
if (callback) callback(response);
},
error: function(jqXHR, textStatus, errorThrown) {
})
.fail(function() {
new PNotify({title: gettext("Login failed"), text: gettext("User unknown or wrong password"), type: "error"});
}
})
});
};
self.logout = function() {
$.ajax({
url: API_BASEURL + "logout",
type: "POST",
success: function(response) {
OctoPrint.browser.logout()
.done(function(response) {
new PNotify({title: gettext("Logout successful"), text: gettext("You are now logged out"), type: "success"});
self.fromResponse(response);
}
})
});
};
self.onLoginUserKeyup = function(data, event) {

View file

@ -19,22 +19,17 @@ $(function() {
self.triggerAction = function(action) {
var callback = function() {
$.ajax({
url: API_BASEURL + "system",
type: "POST",
dataType: "json",
data: "action=" + action.action,
success: function() {
new PNotify({title: "Success", text: _.sprintf(gettext("The command \"%(command)s\" executed successfully"), {command: action.name}), type: "success"});
},
error: function(jqXHR, textStatus, errorThrown) {
OctoPrint.control.executeSystemCommand(action.action)
.done(function() {
new PNotify({title: gettext("Success"), text: _.sprintf(gettext("The command \"%(command)s\" executed successfully"), {command: action.name}), type: "success"});
})
.fail(function() {
if (!action.hasOwnProperty("ignore") || !action.ignore) {
var error = "<p>" + _.sprintf(gettext("The command \"%(command)s\" could not be executed."), {command: action.name}) + "</p>";
error += pnotifyAdditionalInfo("<pre>" + jqXHR.responseText + "</pre>");
new PNotify({title: gettext("Error"), text: error, type: "error", hide: false});
}
}
})
});
};
if (action.confirm) {
showConfirmationDialog({

View file

@ -194,12 +194,8 @@ $(function() {
};
self.requestData = function() {
$.ajax({
url: API_BASEURL + "printerprofiles",
type: "GET",
dataType: "json",
success: self.fromResponse
})
OctoPrint.printerprofiles.get()
.done(self.fromResponse);
};
self.fromResponse = function(data) {
@ -228,43 +224,35 @@ $(function() {
self.addProfile = function(callback) {
var profile = self._editorData();
self.requestInProgress(true);
$.ajax({
url: API_BASEURL + "printerprofiles",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({profile: profile}),
success: function() {
self.requestInProgress(false);
OctoPrint.printerprofiles.add(profile)
.done(function() {
if (callback !== undefined) {
callback();
}
self.requestData();
},
error: function() {
self.requestInProgress(false);
})
.fail(function() {
var text = gettext("There was unexpected error while saving the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
});
})
.always(function() {
self.requestInProgress(false);
});
};
self.removeProfile = function(data) {
self.requestInProgress(true);
$.ajax({
url: data.resource,
type: "DELETE",
dataType: "json",
success: function() {
self.requestInProgress(false);
OctoPrint.printerprofiles.delete(data.id, {url: data.resource})
.done(function() {
self.requestData();
},
error: function() {
self.requestInProgress(false);
})
.fail(function() {
var text = gettext("There was unexpected error while removing the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
})
})
.always(function() {
self.requestInProgress(false);
});
};
self.updateProfile = function(profile, callback) {
@ -273,26 +261,20 @@ $(function() {
}
self.requestInProgress(true);
$.ajax({
url: API_BASEURL + "printerprofiles/" + profile.id,
type: "PATCH",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({profile: profile}),
success: function() {
self.requestInProgress(false);
OctoPrint.printerprofiles.update(profile.key, profile)
.done(function() {
if (callback !== undefined) {
callback();
}
self.requestData();
},
error: function() {
self.requestInProgress(false);
})
.fail(function() {
var text = gettext("There was unexpected error while updating the printer profile, please consult the logs.");
new PNotify({title: gettext("Saving failed"), text: text, type: "error", hide: false});
}
});
})
.always(function() {
self.requestInProgress(false);
});
};
self.showEditProfileDialog = function(data) {

View file

@ -198,45 +198,25 @@ $(function() {
};
self.print = function() {
var restartCommand = function() {
self._jobCommand("restart");
};
if (self.isPaused()) {
showConfirmationDialog({
message: gettext("This will restart the print job from the beginning."),
onproceed: function(e) {
restartCommand();
onproceed: function() {
OctoPrint.job.restart();
}
});
} else {
self._jobCommand("start");
OctoPrint.job.start();
}
};
self.pause = function() {
self._jobCommand("pause");
OctoPrint.job.pause();
};
self.cancel = function() {
self._jobCommand("cancel");
OctoPrint.job.cancel();
};
self._jobCommand = function(command, callback) {
$.ajax({
url: API_BASEURL + "job",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({command: command}),
success: function(response) {
if (callback != undefined) {
callback();
}
}
});
}
}
OCTOPRINT_VIEWMODELS.push([

View file

@ -225,18 +225,14 @@ $(function() {
var errorText = gettext("Could not retrieve snapshot URL, please double check the URL");
var errorTitle = gettext("Snapshot test failed");
$.ajax({
url: API_BASEURL + "util/test",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "url",
url: self.webcam_snapshotUrl(),
method: "GET",
response: true
}),
contentType: "application/json; charset=UTF-8",
success: function(response) {
var data = {
url: self.webcam_snapshotUrl(),
method: "GET",
response: true
};
OctoPrint.util.test("url", data)
.done(function(response) {
$("i.icon-spinner", target).remove();
if (!response.result) {
@ -260,15 +256,14 @@ $(function() {
title: gettext("Snapshot test"),
message: $('<p>' + text + '</p><p><img src="data:' + mimeType + ';base64,' + content + '" /></p>')
});
},
error: function() {
})
.fail(function() {
$("i.icon-spinner", target).remove();
showMessageDialog({
title: errorTitle,
message: errorText
});
}
});
});
};
self.testWebcamFfmpegPath = function() {
@ -293,19 +288,13 @@ $(function() {
};
var path = self.webcam_ffmpegPath();
$.ajax({
url: API_BASEURL + "util/test",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "path",
path: path,
check_type: "file",
check_access: "x"
}),
contentType: "application/json; charset=UTF-8",
success: successCallback
})
var data = {
path: path,
check_type: "file",
check_access: "x"
};
OctoPrint.util.test("path", data)
.done(successCallback);
};
self.onSettingsShown = function() {
@ -331,6 +320,7 @@ $(function() {
dataType: "json",
maxNumberOfFiles: 1,
autoUpload: false,
headers: OctoPrint.getRequestHeaders(),
add: function(e, data) {
if (data.files.length == 0) {
return false;
@ -418,11 +408,8 @@ $(function() {
}
self.receiving(true);
$.ajax({
url: API_BASEURL + "settings",
type: "GET",
dataType: "json",
success: function(response) {
OctoPrint.settings.get()
.done(function(response) {
if (callback) {
self.callbacks.push(callback);
}
@ -443,23 +430,15 @@ $(function() {
self.receiving(false);
self.callbacks = [];
}
},
error: function(xhr) {
})
.fail(function() {
self.receiving(false);
}
});
});
};
self.requestTranslationData = function(callback) {
$.ajax({
url: API_BASEURL + "languages",
type: "GET",
dataType: "json",
success: function(response) {
self.fromTranslationResponse(response);
if (callback) callback();
}
})
return OctoPrint.languages.list()
.done(self.fromTranslationResponse);
};
self.fromTranslationResponse = function(response) {
@ -509,14 +488,8 @@ $(function() {
});
self.deleteLanguagePack = function(locale, pack) {
$.ajax({
url: API_BASEURL + "languages/" + locale + "/" + pack,
type: "DELETE",
dataType: "json",
success: function(response) {
self.fromTranslationResponse(response);
}
})
OctoPrint.languages.delete(locale, pack)
.done(self.fromTranslationResponse);
};
/**
@ -690,13 +663,8 @@ $(function() {
data = getOnlyChangedData(self.getLocalData(), self.lastReceivedSettings);
}
$.ajax({
url: API_BASEURL + "settings",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data),
success: function(data, status, xhr) {
OctoPrint.settings.save(data)
.done(function(data, status, xhr) {
self.receiving(true);
self.sending(false);
try {
@ -705,15 +673,14 @@ $(function() {
} finally {
self.receiving(false);
}
},
error: function(xhr, status, error) {
})
.fail(function(xhr, status, error) {
self.sending(false);
if (options.error) options.error(xhr, status, error);
},
complete: function(xhr, status) {
})
.always(function(xhr, status) {
if (options.complete) options.complete(xhr, status);
}
});
});
};
self.onEventSettingsUpdated = function() {

View file

@ -65,17 +65,13 @@ $(function() {
});
self.requestData = function(callback) {
$.ajax({
url: API_BASEURL + "slicing",
type: "GET",
dataType: "json",
success: function(data) {
OctoPrint.slicing.listAllSlicersAndProfiles()
.done(function(data) {
self.fromResponse(data);
if (callback !== undefined) {
callback();
}
}
});
});
};
self.fromResponse = function(data) {
@ -150,7 +146,6 @@ $(function() {
}
var data = {
command: "slice",
slicer: self.slicer(),
profile: self.profile(),
printerProfile: self.printerProfile(),
@ -163,19 +158,14 @@ $(function() {
data["select"] = true;
}
$.ajax({
url: API_BASEURL + "files/" + self.target + "/" + self.file,
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data)
});
OctoPrint.files.slice(self.target, self.file, data)
.done(function() {
$("#slicing_configuration_dialog").modal("hide");
$("#slicing_configuration_dialog").modal("hide");
self.gcodeFilename(undefined);
self.slicer(self.defaultSlicer);
self.profile(self.defaultProfile);
self.gcodeFilename(undefined);
self.slicer(self.defaultSlicer);
self.profile(self.defaultProfile);
});
};
self._sanitize = function(name) {
@ -196,4 +186,4 @@ $(function() {
["loginStateViewModel", "printerProfilesViewModel"],
"#slicing_configuration_dialog"
]);
});
});

View file

@ -268,87 +268,84 @@ $(function() {
var value = item.newTarget();
if (!value) return;
self._sendToolCommand("target",
item.key(),
item.newTarget(),
function() {item.newTarget("");}
);
var onSuccess = function() {
item.newTarget("");
};
if (item.key() == "bed") {
self._setBedTemperature(value)
.done(onSuccess);
} else {
self._setToolTemperature(item.key(), value)
.done(onSuccess);
}
};
self.setTargetFromProfile = function(item, profile) {
if (!profile) return;
var value = undefined;
if (item.key() == "bed") {
value = profile.bed;
} else {
value = profile.extruder;
}
var onSuccess = function() {
item.newTarget("");
};
self._sendToolCommand("target",
item.key(),
value,
function() {item.newTarget("");}
);
if (item.key() == "bed") {
self._setBedTemperature(profile.bed)
.done(onSuccess);
} else {
self._setToolTemperature(item.key(), profile.extruder)
.done(onSuccess);
}
};
self.setTargetToZero = function(item) {
self._sendToolCommand("target",
item.key(),
0,
function() {item.newTarget("");}
);
var onSuccess = function() {
item.newTarget("");
};
if (item.key() == "bed") {
self._setBedTemperature(0)
.done(onSuccess);
} else {
self._setToolTemperature(item.key(), 0)
.done(onSuccess);
}
};
self.setOffset = function(item) {
self._sendToolCommand("offset",
item.key(),
item.newOffset(),
function() {item.newOffset("");}
);
};
var value = item.newOffset();
if (!value) return;
self._sendToolCommand = function(command, type, temp, successCb, errorCb) {
var data = {
command: command
var onSuccess = function() {
item.newOffset("");
};
var endpoint;
if (type == "bed") {
if ("target" == command) {
data["target"] = parseInt(temp);
} else if ("offset" == command) {
data["offset"] = parseInt(temp);
} else {
return;
}
endpoint = "bed";
if (item.key() == "bed") {
self._setBedOffset(value)
.done(onSuccess);
} else {
var group;
if ("target" == command) {
group = "targets";
} else if ("offset" == command) {
group = "offsets";
} else {
return;
}
data[group] = {};
data[group][type] = parseInt(temp);
endpoint = "tool";
self._setToolOffset(item.key(), value)
.done(onSuccess);
}
};
$.ajax({
url: API_BASEURL + "printer/" + endpoint,
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(data),
success: function() { if (successCb !== undefined) successCb(); },
error: function() { if (errorCb !== undefined) errorCb(); }
});
self._setToolTemperature = function(tool, temperature) {
var data = {};
data[tool] = parseInt(temperature);
return OctoPrint.printer.setToolTargetTemperatures(data);
};
self._setToolOffset = function(tool, offset) {
var data = {};
data[tool] = parseInt(offset);
return OctoPrint.printer.setToolTemperatureOffsets(data);
};
self._setBedTemperature = function(temperature) {
return OctoPrint.printer.setBedTargetTemperature(parseInt(temperature));
};
self._setBedOffset = function(offset) {
return OctoPrint.printer.setBedTemperatureOffset(parseInt(offset));
};
self.handleEnter = function(event, type, item) {
@ -375,4 +372,4 @@ $(function() {
["loginStateViewModel", "settingsViewModel"],
"#temp"
]);
});
});

View file

@ -158,29 +158,18 @@ $(function() {
}
if (command) {
$.ajax({
url: API_BASEURL + "printer/command",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({"command": command})
});
self.cmdHistory.push(command);
self.cmdHistory.slice(-300); // just to set a sane limit to how many manually entered commands will be saved...
self.cmdHistoryIdx = self.cmdHistory.length;
self.command("");
OctoPrint.control.sendGcode(command)
.done(function() {
self.cmdHistory.push(command);
self.cmdHistory.slice(-300); // just to set a sane limit to how many manually entered commands will be saved...
self.cmdHistoryIdx = self.cmdHistory.length;
self.command("");
});
}
};
self.fakeAck = function() {
$.ajax({
url: API_BASEURL + "connection",
type: "POST",
dataType: "json",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({"command": "fake_ack"})
});
OctoPrint.printer.fakeAck();
};
self.handleKeyDown = function(event) {
@ -232,4 +221,4 @@ $(function() {
["loginStateViewModel", "settingsViewModel"],
"#term"
]);
});
});

View file

@ -34,20 +34,20 @@ $(function() {
return self.isDirty() && self.isOperational() && !self.isPrinting() && self.loginState.isUser();
});
self.isOperational.subscribe(function(newValue) {
self.isOperational.subscribe(function() {
self.requestData();
});
self.timelapseType.subscribe(function(newValue) {
self.timelapseType.subscribe(function() {
self.isDirty(true);
});
self.timelapseTimedInterval.subscribe(function(newValue) {
self.timelapseTimedInterval.subscribe(function() {
self.isDirty(true);
});
self.timelapsePostRoll.subscribe(function(newValue) {
self.timelapsePostRoll.subscribe(function() {
self.isDirty(true);
});
self.timelapseFps.subscribe(function(newValue) {
self.timelapseFps.subscribe(function() {
self.isDirty(true);
});
@ -83,12 +83,8 @@ $(function() {
);
self.requestData = function() {
$.ajax({
url: API_BASEURL + "timelapse",
type: "GET",
dataType: "json",
success: self.fromResponse
});
OctoPrint.timelapse.get()
.done(self.fromResponse);
};
self.fromResponse = function(response) {
@ -141,15 +137,11 @@ $(function() {
};
self.removeFile = function(filename) {
$.ajax({
url: API_BASEURL + "timelapse/" + filename,
type: "DELETE",
dataType: "json",
success: self.requestData
});
OctoPrint.timelapse.delete(filename)
.done(self.requestData);
};
self.save = function(data, event) {
self.save = function() {
var payload = {
"type": self.timelapseType(),
"postRoll": self.timelapsePostRoll(),
@ -161,20 +153,15 @@ $(function() {
payload["interval"] = self.timelapseTimedInterval();
}
$.ajax({
url: API_BASEURL + "timelapse",
type: "POST",
dataType: "json",
data: payload,
success: self.fromResponse
});
OctoPrint.timelapse.saveConfig(payload)
.done(self.fromResponse);
};
self.onDataUpdaterReconnect = function() {
self.requestData();
};
self.onEventMovieDone = function(payload) {
self.onEventMovieDone = function() {
self.requestData();
};

View file

@ -60,12 +60,8 @@ $(function() {
self.requestData = function() {
if (!CONFIG_ACCESS_CONTROL) return;
$.ajax({
url: API_BASEURL + "users",
type: "GET",
dataType: "json",
success: self.fromResponse
});
OctoPrint.users.list()
.done(self.fromResponse);
};
self.fromResponse = function(response) {
@ -83,12 +79,19 @@ $(function() {
self.confirmAddUser = function() {
if (!CONFIG_ACCESS_CONTROL) return;
var user = {name: self.editorUsername(), password: self.editorPassword(), admin: self.editorAdmin(), active: self.editorActive()};
self.addUser(user, function() {
// close dialog
self.currentUser(undefined);
self.addUserDialog.modal("hide");
});
var user = {
name: self.editorUsername(),
password: self.editorPassword(),
admin: self.editorAdmin(),
active: self.editorActive()
};
self.addUser(user)
.done(function() {
// close dialog
self.currentUser(undefined);
self.addUserDialog.modal("hide");
});
};
self.showEditUserDialog = function(user) {
@ -105,12 +108,12 @@ $(function() {
user.active = self.editorActive();
user.admin = self.editorAdmin();
// make AJAX call
self.updateUser(user, function() {
// close dialog
self.currentUser(undefined);
self.editUserDialog.modal("hide");
});
self.updateUser(user)
.done(function() {
// close dialog
self.currentUser(undefined);
self.editUserDialog.modal("hide");
});
};
self.showChangePasswordDialog = function(user) {
@ -123,27 +126,30 @@ $(function() {
self.confirmChangePassword = function() {
if (!CONFIG_ACCESS_CONTROL) return;
self.updatePassword(self.currentUser().name, self.editorPassword(), function() {
// close dialog
self.currentUser(undefined);
self.changePasswordDialog.modal("hide");
});
self.updatePassword(self.currentUser().name, self.editorPassword())
.done(function() {
// close dialog
self.currentUser(undefined);
self.changePasswordDialog.modal("hide");
});
};
self.confirmGenerateApikey = function() {
if (!CONFIG_ACCESS_CONTROL) return;
self.generateApikey(self.currentUser().name, function(response) {
self._updateApikey(response.apikey);
})
self.generateApikey(self.currentUser().name)
.done(function(response) {
self._updateApikey(response.apikey);
});
};
self.confirmDeleteApikey = function() {
if (!CONFIG_ACCESS_CONTROL) return;
self.deleteApikey(self.currentUser().name, function() {
self._updateApikey(undefined);
})
self.deleteApikey(self.currentUser().name)
.done(function() {
self._updateApikey(undefined);
});
};
self._updateApikey = function(apikey) {
@ -159,108 +165,55 @@ $(function() {
self.changePasswordDialog = $("#settings-usersDialogChangePassword");
};
//~~ AJAX calls
//~~ API calls
self.addUser = function(user, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
if (user === undefined) return;
self.addUser = function(user) {
if (!user) {
throw OctoPrint.InvalidArgumentError("user must be set");
}
$.ajax({
url: API_BASEURL + "users",
type: "POST",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(user),
success: function(response) {
self.fromResponse(response);
if (callback) {
callback(response);
}
}
});
return OctoPrint.users.add(user)
.done(self.fromResponse);
};
self.removeUser = function(user, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
if (user === undefined) return;
self.removeUser = function(user) {
if (!user) {
throw OctoPrint.InvalidArgumentError("user must be set");
}
if (user.name == self.loginState.username()) {
// we do not allow to delete ourselves
new PNotify({title: "Not possible", text: "You may not delete your own account.", type: "error"});
return;
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();
}
$.ajax({
url: API_BASEURL + "users/" + user.name,
type: "DELETE",
success: function(response) {
self.fromResponse(response);
if (callback) {
callback(response);
}
}
});
return OctoPrint.users.delete(user.name)
.done(self.fromResponse);
};
self.updateUser = function(user, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
if (user === undefined) return;
self.updateUser = function(user) {
if (!user) {
throw OctoPrint.InvalidArgumentError("user must be set");
}
$.ajax({
url: API_BASEURL + "users/" + user.name,
type: "PUT",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(user),
success: function(response) {
self.fromResponse(response);
if (callback) {
callback(response);
}
}
});
return OctoPrint.users.update(user.name, user.active, user.admin)
.done(self.fromResponse);
};
self.updatePassword = function(username, password, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
$.ajax({
url: API_BASEURL + "users/" + username + "/password",
type: "PUT",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify({password: password}),
success: function(response) {
if (callback) {
callback(response);
}
}
});
self.updatePassword = function(username, password) {
return OctoPrint.users.changePassword(username, password);
};
self.generateApikey = function(username, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
$.ajax({
url: API_BASEURL + "users/" + username + "/apikey",
type: "POST",
success: function(response) {
if (callback) {
callback(response);
}
}
});
self.generateApikey = function(username) {
return OctoPrint.users.generateApiKey(username);
};
self.deleteApikey = function(username, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
$.ajax({
url: API_BASEURL + "users/" + username + "/apikey",
type: "DELETE",
success: function(response) {
if (callback) {
callback(response);
}
}
});
self.deleteApikey = function(username) {
return OctoPrint.users.resetApiKey(username);
};
self.onUserLoggedIn = function(user) {
@ -275,4 +228,4 @@ $(function() {
["loginStateViewModel"],
[]
]);
});
});

View file

@ -60,24 +60,17 @@ $(function() {
"language": self.interface_language()
}
};
self.updateSettings(self.currentUser().name, settings, function() {
// close dialog
self.currentUser(undefined);
self.userSettingsDialog.modal("hide");
self.loginState.reloadUser();
});
self.updateSettings(self.currentUser().name, settings)
.done(function() {
// close dialog
self.currentUser(undefined);
self.userSettingsDialog.modal("hide");
self.loginState.reloadUser();
});
};
self.updateSettings = function(username, settings, callback) {
if (!CONFIG_ACCESS_CONTROL) return;
$.ajax({
url: API_BASEURL + "users/" + username + "/settings",
type: "PATCH",
contentType: "application/json; charset=UTF-8",
data: JSON.stringify(settings),
success: callback
});
self.updateSettings = function(username, settings) {
return OctoPrint.users.saveSettings(username, settings);
};
self.saveEnabled = function() {

View file

@ -19,18 +19,19 @@ $(function() {
self.showDialog = function() {
if (!CONFIG_WIZARD || !(CONFIG_FIRST_RUN || self.loginState.isAdmin())) return;
self.getWizardDetails(function(response) {
callViewModels(self.allViewModels, "onWizardDetails", [response]);
self.getWizardDetails()
.done(function(response) {
callViewModels(self.allViewModels, "onWizardDetails", [response]);
if (!self.isDialogActive()) {
self.wizardDialog.modal({
minHeight: function() { return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); }
}).css({
width: 'auto',
'margin-left': function() { return -($(this).width() /2); }
});
}
});
if (!self.isDialogActive()) {
self.wizardDialog.modal({
minHeight: function() { return Math.max($.fn.modal.defaults.maxHeight() - 80, 250); }
}).css({
width: 'auto',
'margin-left': function() { return -($(this).width() /2); }
});
}
});
};
self.closeDialog = function() {
@ -121,53 +122,34 @@ $(function() {
// then
reload = (method() == "reload") || reload;
});
self.finishWizard(function() {
self.closeDialog();
if (reload) {
log.info("Wizard requested reloading");
location.reload(true);
}
});
self.finishWizard()
.done(function() {
self.closeDialog();
if (reload) {
log.info("Wizard requested reloading");
location.reload(true);
}
});
}
}
});
self.showDialog();
};
self.getWizardDetails = function(callback) {
if (!callback) return;
$.ajax({
url: API_BASEURL + "setup/wizard",
type: "GET",
dataType: "json",
success: function(response) {
self.getWizardDetails = function() {
return OctoPrint.wizard.get()
.done(function(response) {
self.wizards = _.filter(_.keys(response), function(key) { return response[key] && response[key]["required"] && !response[key]["ignored"]; });
if (callback) {
callback(response);
}
}
});
});
};
self.finishWizard = function(callback) {
self.finishWizard = function() {
self.finishing = true;
self.settingsViewModel.saveData();
$.ajax({
url: API_BASEURL + "setup/wizard",
type: "POST",
dataType: "json",
data: JSON.stringify({handled: self.wizards}),
contentType: "application/json; charset=UTF-8",
success: function() {
return OctoPrint.wizard.finish(self.wizards)
.always(function() {
self.finishing = false;
callback();
},
failure: function() {
self.finishing = false;
}
})
});
};
self.onSettingsPreventRefresh = function() {

View file

@ -2,6 +2,10 @@
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "js_client" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "js_app" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}