We now have a global OctoPrintClient, which is the class from which
all clients are derived, and a global OctoPrint, which is a single
instance already setup and ready to use in case we only need one.
It would be cleaner to have clients create that singular instance
themselves, but we need to maintain backward compatibility for now
with how we established the client to work with the 1.3.0 release.
New clients can be create with
client = new OctoPrintClient({ /* options */ });
Alternatively the options can be left out and set at a later point:
client = new OctoPrintClient();
/* ... */
client.options = { /* options */ };
Individual client components register themselves with OctoPrintClient
via OctoPrintClient.registerComponent(name, component) from the
component JS files. Just like before their instances are then
available in the individual client instances under "<client>.<name>",
e.g. "OctoPrint.files".
Plugin components register themselves with OctoPrintClient via
OctoPrintClient.registerPluginComponent(name, component) from the
component JS files. Just like before their instances are then
available in the individual client instances under "<client>.plugins
.<name>", e.g. "OctoPrint.plugins.softwareupdate".
This should make it possible to create dashboard pages utilizing the
JS client that monitor the status of multiple OctoPrint instances,
without workarounds such as having to swap out the options globally
before each request.
See #1681 for the corresponding discussion.
884 lines
35 KiB
JavaScript
884 lines
35 KiB
JavaScript
(function (global, factory) {
|
|
if (typeof define === "function" && define.amd) {
|
|
define(["OctoPrintClient"], factory);
|
|
} else {
|
|
factory(global.OctoPrintClient);
|
|
}
|
|
})(this, function(OctoPrintClient) {
|
|
var OctoPrintPluginManagerClient = function(base) {
|
|
this.base = base;
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.get = function(refresh, opts) {
|
|
return this.base.get(this.base.getSimpleApiUrl("pluginmanager") + ((refresh) ? "?refresh_repository=true" : ""), opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.getWithRefresh = function(opts) {
|
|
return this.get(true, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.getWithoutRefresh = function(opts) {
|
|
return this.get(false, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.install = function(pluginUrl, dependencyLinks, opts) {
|
|
var data = {
|
|
url: pluginUrl,
|
|
dependency_links: !!dependencyLinks
|
|
};
|
|
return this.base.simpleApiCommand("pluginmanager", "install", data, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.reinstall = function(plugin, pluginUrl, dependencyLinks, opts) {
|
|
var data = {
|
|
url: pluginUrl,
|
|
dependency_links: !!dependencyLinks,
|
|
reinstall: plugin,
|
|
force: true
|
|
};
|
|
return this.base.simpleApiCommand("pluginmanager", "install", data, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.uninstall = function(plugin, opts) {
|
|
var data = {
|
|
plugin: plugin
|
|
};
|
|
return this.base.simpleApiCommand("pluginmanager", "uninstall", data, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.enable = function(plugin, opts) {
|
|
var data = {
|
|
plugin: plugin
|
|
};
|
|
return this.base.simpleApiCommand("pluginmanager", "enable", data, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.disable = function(plugin, opts) {
|
|
var data = {
|
|
plugin: plugin
|
|
};
|
|
return this.base.simpleApiCommand("pluginmanager", "disable", data, opts);
|
|
};
|
|
|
|
OctoPrintPluginManagerClient.prototype.upload = function(file) {
|
|
return this.base.upload(this.base.getBlueprintUrl("pluginmanager") + "upload_archive", file);
|
|
};
|
|
|
|
OctoPrintClient.registerPluginComponent("pluginmanager", OctoPrintPluginManagerClient);
|
|
return OctoPrintPluginManagerClient;
|
|
});
|
|
|
|
$(function() {
|
|
function PluginManagerViewModel(parameters) {
|
|
var self = this;
|
|
|
|
self.loginState = parameters[0];
|
|
self.settingsViewModel = parameters[1];
|
|
self.printerState = parameters[2];
|
|
self.systemViewModel = parameters[3];
|
|
|
|
self.config_repositoryUrl = ko.observable();
|
|
self.config_repositoryTtl = ko.observable();
|
|
self.config_pipAdditionalArgs = ko.observable();
|
|
self.config_pipForceUser = ko.observable();
|
|
|
|
self.configurationDialog = $("#settings_plugin_pluginmanager_configurationdialog");
|
|
|
|
self.plugins = new ItemListHelper(
|
|
"plugin.pluginmanager.installedplugins",
|
|
{
|
|
"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;
|
|
}
|
|
},
|
|
{
|
|
},
|
|
"name",
|
|
[],
|
|
[],
|
|
5
|
|
);
|
|
|
|
self.repositoryplugins = new ItemListHelper(
|
|
"plugin.pluginmanager.repositoryplugins",
|
|
{
|
|
"title": function (a, b) {
|
|
// sorts ascending
|
|
if (a["title"].toLocaleLowerCase() < b["title"].toLocaleLowerCase()) return -1;
|
|
if (a["title"].toLocaleLowerCase() > b["title"].toLocaleLowerCase()) return 1;
|
|
return 0;
|
|
},
|
|
"published": function (a, b) {
|
|
// sorts descending
|
|
if (a["published"].toLocaleLowerCase() > b["published"].toLocaleLowerCase()) return -1;
|
|
if (a["published"].toLocaleLowerCase() < b["published"].toLocaleLowerCase()) return 1;
|
|
return 0;
|
|
}
|
|
},
|
|
{
|
|
"filter_installed": function(plugin) {
|
|
return !self.installed(plugin);
|
|
},
|
|
"filter_incompatible": function(plugin) {
|
|
return plugin.is_compatible.octoprint && plugin.is_compatible.os;
|
|
}
|
|
},
|
|
"title",
|
|
["filter_installed", "filter_incompatible"],
|
|
[],
|
|
0
|
|
);
|
|
|
|
self.uploadElement = $("#settings_plugin_pluginmanager_repositorydialog_upload");
|
|
self.uploadButton = $("#settings_plugin_pluginmanager_repositorydialog_upload_start");
|
|
|
|
self.repositoryAvailable = ko.observable(false);
|
|
|
|
self.repositorySearchQuery = ko.observable();
|
|
self.repositorySearchQuery.subscribe(function() {
|
|
self.performRepositorySearch();
|
|
});
|
|
|
|
self.installUrl = ko.observable();
|
|
self.uploadFilename = ko.observable();
|
|
|
|
self.loglines = ko.observableArray([]);
|
|
self.installedPlugins = ko.observableArray([]);
|
|
|
|
self.followDependencyLinks = ko.observable(false);
|
|
|
|
self.pipAvailable = ko.observable(false);
|
|
self.pipVersion = ko.observable();
|
|
self.pipInstallDir = ko.observable();
|
|
self.pipUseUser = ko.observable();
|
|
self.pipVirtualEnv = ko.observable();
|
|
self.pipAdditionalArgs = ko.observable();
|
|
self.pipPython = ko.observable();
|
|
|
|
self.safeMode = ko.observable();
|
|
|
|
self.pipUseUserString = ko.pureComputed(function() {
|
|
return self.pipUseUser() ? "yes" : "no";
|
|
});
|
|
self.pipVirtualEnvString = ko.pureComputed(function() {
|
|
return self.pipVirtualEnv() ? "yes" : "no";
|
|
});
|
|
|
|
self.working = ko.observable(false);
|
|
self.workingTitle = ko.observable();
|
|
self.workingDialog = undefined;
|
|
self.workingOutput = undefined;
|
|
|
|
self.restartCommandSpec = undefined;
|
|
self.systemViewModel.systemActions.subscribe(function() {
|
|
var lastResponse = self.systemViewModel.lastCommandResponse;
|
|
if (!lastResponse || !lastResponse.core) {
|
|
self.restartCommandSpec = undefined;
|
|
return;
|
|
}
|
|
|
|
var restartSpec = _.filter(lastResponse.core, function(spec) { return spec.action == "restart" });
|
|
self.restartCommandSpec = restartSpec != undefined && restartSpec.length > 0 ? restartSpec[0] : undefined;
|
|
});
|
|
|
|
self.notifications = [];
|
|
|
|
self.enableManagement = ko.pureComputed(function() {
|
|
return !self.printerState.isPrinting();
|
|
});
|
|
|
|
self.enableToggle = function(data) {
|
|
var command = self._getToggleCommand(data);
|
|
return self.enableManagement() && (command == "disable" || !data.safe_mode_victim || data.safe_mode_enabled) && data.key != 'pluginmanager';
|
|
};
|
|
|
|
self.enableUninstall = function(data) {
|
|
return self.enableManagement()
|
|
&& (data.origin != "entry_point" || self.pipAvailable())
|
|
&& data.managable
|
|
&& !data.bundled
|
|
&& data.key != 'pluginmanager'
|
|
&& !data.pending_uninstall;
|
|
};
|
|
|
|
self.enableRepoInstall = function(data) {
|
|
return self.enableManagement() && self.pipAvailable() && !self.safeMode() && self.isCompatible(data);
|
|
};
|
|
|
|
self.invalidUrl = ko.pureComputed(function() {
|
|
var url = self.installUrl();
|
|
return url !== undefined && url.trim() != "" && !(_.startsWith(url.toLocaleLowerCase(), "http://") || _.startsWith(url.toLocaleLowerCase(), "https://"));
|
|
});
|
|
|
|
self.enableUrlInstall = ko.pureComputed(function() {
|
|
var url = self.installUrl();
|
|
return self.enableManagement() && self.pipAvailable() && !self.safeMode() && url !== undefined && url.trim() != "" && !self.invalidUrl();
|
|
});
|
|
|
|
self.invalidArchive = ko.pureComputed(function() {
|
|
var name = self.uploadFilename();
|
|
return name !== undefined && !(_.endsWith(name.toLocaleLowerCase(), ".zip") || _.endsWith(name.toLocaleLowerCase(), ".tar.gz") || _.endsWith(name.toLocaleLowerCase(), ".tgz") || _.endsWith(name.toLocaleLowerCase(), ".tar"));
|
|
});
|
|
|
|
self.enableArchiveInstall = ko.pureComputed(function() {
|
|
var name = self.uploadFilename();
|
|
return self.enableManagement() && self.pipAvailable() && !self.safeMode() && name !== undefined && name.trim() != "" && !self.invalidArchive();
|
|
});
|
|
|
|
self.uploadElement.fileupload({
|
|
dataType: "json",
|
|
maxNumberOfFiles: 1,
|
|
autoUpload: false,
|
|
add: function(e, data) {
|
|
if (data.files.length == 0) {
|
|
return false;
|
|
}
|
|
|
|
self.uploadFilename(data.files[0].name);
|
|
|
|
self.uploadButton.unbind("click");
|
|
self.uploadButton.bind("click", function() {
|
|
self._markWorking(gettext("Installing plugin..."), gettext("Installing plugin from uploaded archive..."));
|
|
data.formData = {
|
|
dependency_links: self.followDependencyLinks()
|
|
};
|
|
data.submit();
|
|
return false;
|
|
});
|
|
},
|
|
done: function(e, data) {
|
|
self._markDone();
|
|
self.uploadButton.unbind("click");
|
|
self.uploadFilename(undefined);
|
|
},
|
|
fail: function(e, data) {
|
|
new PNotify({
|
|
title: gettext("Something went wrong"),
|
|
text: gettext("Please consult octoprint.log for details"),
|
|
type: "error",
|
|
hide: false
|
|
});
|
|
self._markDone();
|
|
self.uploadButton.unbind("click");
|
|
self.uploadFilename(undefined);
|
|
}
|
|
});
|
|
|
|
self.performRepositorySearch = function() {
|
|
var query = self.repositorySearchQuery();
|
|
if (query !== undefined && query.trim() != "") {
|
|
query = query.toLocaleLowerCase();
|
|
self.repositoryplugins.changeSearchFunction(function(entry) {
|
|
return entry && (entry["title"].toLocaleLowerCase().indexOf(query) > -1 || entry["description"].toLocaleLowerCase().indexOf(query) > -1);
|
|
});
|
|
} else {
|
|
self.repositoryplugins.resetSearch();
|
|
}
|
|
return false;
|
|
};
|
|
|
|
self.fromResponse = function(data) {
|
|
self._fromPluginsResponse(data.plugins);
|
|
self._fromRepositoryResponse(data.repository);
|
|
self._fromPipResponse(data.pip);
|
|
|
|
self.safeMode(data.safe_mode || false);
|
|
};
|
|
|
|
self._fromPluginsResponse = function(data) {
|
|
var installedPlugins = [];
|
|
_.each(data, function(plugin) {
|
|
installedPlugins.push(plugin.key);
|
|
});
|
|
self.installedPlugins(installedPlugins);
|
|
self.plugins.updateItems(data);
|
|
};
|
|
|
|
self._fromRepositoryResponse = function(data) {
|
|
self.repositoryAvailable(data.available);
|
|
if (data.available) {
|
|
self.repositoryplugins.updateItems(data.plugins);
|
|
} else {
|
|
self.repositoryplugins.updateItems([]);
|
|
}
|
|
};
|
|
|
|
self._fromPipResponse = function(data) {
|
|
self.pipAvailable(data.available);
|
|
if (data.available) {
|
|
self.pipVersion(data.version);
|
|
self.pipInstallDir(data.install_dir);
|
|
self.pipUseUser(data.use_user);
|
|
self.pipVirtualEnv(data.virtual_env);
|
|
self.pipAdditionalArgs(data.additional_args);
|
|
self.pipPython(data.python);
|
|
} else {
|
|
self.pipVersion(undefined);
|
|
self.pipInstallDir(undefined);
|
|
self.pipUseUser(undefined);
|
|
self.pipVirtualEnv(undefined);
|
|
self.pipAdditionalArgs(undefined);
|
|
}
|
|
};
|
|
|
|
self.requestData = function(includeRepo) {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
OctoPrint.plugins.pluginmanager.get(includeRepo)
|
|
.done(self.fromResponse);
|
|
};
|
|
|
|
self.togglePlugin = function(data) {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (!self.enableManagement()) {
|
|
return;
|
|
}
|
|
|
|
if (data.key == "pluginmanager") return;
|
|
|
|
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
|
|
})
|
|
};
|
|
|
|
if (self._getToggleCommand(data) == "enable") {
|
|
if (data.safe_mode_victim && !data.safe_mode_enabled) return;
|
|
OctoPrint.plugins.pluginmanager.enable(data.key)
|
|
.done(onSuccess)
|
|
.fail(onError);
|
|
} else {
|
|
OctoPrint.plugins.pluginmanager.disable(data.key)
|
|
.done(onSuccess)
|
|
.fail(onError);
|
|
}
|
|
};
|
|
|
|
self.showRepository = function() {
|
|
self.repositoryDialog.modal("show");
|
|
};
|
|
|
|
self.pluginDetails = function(data) {
|
|
window.open(data.page);
|
|
};
|
|
|
|
self.installFromRepository = function(data) {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (!self.enableManagement()) {
|
|
return;
|
|
}
|
|
|
|
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) {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (!self.enableManagement()) {
|
|
return;
|
|
}
|
|
|
|
if (url === undefined) {
|
|
url = self.installUrl();
|
|
}
|
|
if (!url) return;
|
|
|
|
if (followDependencyLinks === undefined) {
|
|
followDependencyLinks = self.followDependencyLinks();
|
|
}
|
|
|
|
var workTitle, workText;
|
|
if (!reinstall) {
|
|
workTitle = gettext("Installing plugin...");
|
|
if (name) {
|
|
workText = _.sprintf(gettext("Installing plugin \"%(name)s\" from %(url)s..."), {url: url, name: name});
|
|
} else {
|
|
workText = _.sprintf(gettext("Installing plugin from %(url)s..."), {url: url});
|
|
}
|
|
} else {
|
|
workTitle = gettext("Reinstalling plugin...");
|
|
workText = _.sprintf(gettext("Reinstalling plugin \"%(name)s\" from %(url)s..."), {url: url, name: name});
|
|
}
|
|
self._markWorking(workTitle, workText);
|
|
|
|
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();
|
|
};
|
|
|
|
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) {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (!self.enableManagement()) {
|
|
return;
|
|
}
|
|
|
|
if (data.bundled) return;
|
|
if (data.key == "pluginmanager") return;
|
|
|
|
self._markWorking(gettext("Uninstalling plugin..."), _.sprintf(gettext("Uninstalling plugin \"%(name)s\""), {name: data.name}));
|
|
|
|
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.refreshRepository = function() {
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
self.requestData(true);
|
|
};
|
|
|
|
self.showPluginSettings = function() {
|
|
self._copyConfig();
|
|
self.configurationDialog.modal();
|
|
};
|
|
|
|
self.savePluginSettings = function() {
|
|
var repository = self.config_repositoryUrl();
|
|
if (repository != undefined && repository.trim() == "") {
|
|
repository = null;
|
|
}
|
|
|
|
var repositoryTtl;
|
|
try {
|
|
repositoryTtl = parseInt(self.config_repositoryTtl());
|
|
} catch (ex) {
|
|
repositoryTtl = null;
|
|
}
|
|
|
|
var pipArgs = self.config_pipAdditionalArgs();
|
|
if (pipArgs != undefined && pipArgs.trim() == "") {
|
|
pipArgs = null;
|
|
}
|
|
|
|
var data = {
|
|
plugins: {
|
|
pluginmanager: {
|
|
repository: repository,
|
|
repository_ttl: repositoryTtl,
|
|
pip_args: pipArgs,
|
|
pip_force_user: self.config_pipForceUser()
|
|
}
|
|
}
|
|
};
|
|
self.settingsViewModel.saveData(data, function() {
|
|
self.configurationDialog.modal("hide");
|
|
self._copyConfig();
|
|
self.refreshRepository();
|
|
});
|
|
};
|
|
|
|
self._copyConfig = function() {
|
|
self.config_repositoryUrl(self.settingsViewModel.settings.plugins.pluginmanager.repository());
|
|
self.config_repositoryTtl(self.settingsViewModel.settings.plugins.pluginmanager.repository_ttl());
|
|
self.config_pipAdditionalArgs(self.settingsViewModel.settings.plugins.pluginmanager.pip_args());
|
|
self.config_pipForceUser(self.settingsViewModel.settings.plugins.pluginmanager.pip_force_user());
|
|
};
|
|
|
|
self.installed = function(data) {
|
|
return _.includes(self.installedPlugins(), data.id);
|
|
};
|
|
|
|
self.isCompatible = function(data) {
|
|
return data.is_compatible.octoprint && data.is_compatible.os;
|
|
};
|
|
|
|
self.installButtonText = function(data) {
|
|
return self.isCompatible(data) ? (self.installed(data) ? gettext("Reinstall") : gettext("Install")) : gettext("Incompatible");
|
|
};
|
|
|
|
self._displayNotification = function(response, titleSuccess, textSuccess, textRestart, textReload, titleError, textError) {
|
|
var notification;
|
|
|
|
var beforeClose = function(notification) {
|
|
self.notifications = _.without(self.notifications, notification);
|
|
};
|
|
|
|
if (response.result) {
|
|
if (response.needs_restart) {
|
|
var options = {
|
|
title: titleSuccess,
|
|
text: textRestart,
|
|
buttons: {
|
|
closer: true,
|
|
sticker: false
|
|
},
|
|
callbacks: {
|
|
before_close: beforeClose
|
|
},
|
|
hide: false
|
|
};
|
|
|
|
if (self.restartCommandSpec) {
|
|
options.confirm = {
|
|
confirm: true,
|
|
buttons: [{
|
|
text: gettext("Restart now"),
|
|
click: function () {
|
|
showConfirmationDialog({
|
|
message: gettext("This will restart your OctoPrint server."),
|
|
onproceed: function() {
|
|
OctoPrint.system.executeCommand("core", "restart")
|
|
.done(function() {
|
|
new PNotify({
|
|
title: gettext("Restart in progress"),
|
|
text: gettext("The server is now being restarted in the background")
|
|
})
|
|
})
|
|
.fail(function() {
|
|
new PNotify({
|
|
title: gettext("Something went wrong"),
|
|
text: gettext("Trying to restart the server produced an error, please check octoprint.log for details. You'll have to restart manually.")
|
|
})
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
|
|
notification = PNotify.singleButtonNotify(options);
|
|
} else if (response.needs_refresh) {
|
|
notification = PNotify.singleButtonNotify({
|
|
title: titleSuccess,
|
|
text: textReload,
|
|
confirm: {
|
|
confirm: true,
|
|
buttons: [{
|
|
text: gettext("Reload now"),
|
|
click: function () {
|
|
location.reload(true);
|
|
}
|
|
}]
|
|
},
|
|
buttons: {
|
|
closer: true,
|
|
sticker: false
|
|
},
|
|
callbacks: {
|
|
before_close: beforeClose
|
|
},
|
|
hide: false
|
|
})
|
|
} else {
|
|
notification = new PNotify({
|
|
title: titleSuccess,
|
|
text: textSuccess,
|
|
type: "success",
|
|
callbacks: {
|
|
before_close: beforeClose
|
|
},
|
|
hide: false
|
|
})
|
|
}
|
|
} else {
|
|
notification = new PNotify({
|
|
title: titleError,
|
|
text: textError,
|
|
type: "error",
|
|
callbacks: {
|
|
before_close: beforeClose
|
|
},
|
|
hide: false
|
|
});
|
|
}
|
|
|
|
self.notifications.push(notification);
|
|
};
|
|
|
|
self._markWorking = function(title, line) {
|
|
self.working(true);
|
|
self.workingTitle(title);
|
|
|
|
self.loglines.removeAll();
|
|
self.loglines.push({line: line, stream: "message"});
|
|
self._scrollWorkingOutputToEnd();
|
|
|
|
self.workingDialog.modal({keyboard: false, backdrop: "static", show: true});
|
|
};
|
|
|
|
self._markDone = function() {
|
|
self.working(false);
|
|
self.loglines.push({line: gettext("Done!"), stream: "message"});
|
|
self._scrollWorkingOutputToEnd();
|
|
};
|
|
|
|
self._scrollWorkingOutputToEnd = function() {
|
|
self.workingOutput.scrollTop(self.workingOutput[0].scrollHeight - self.workingOutput.height());
|
|
};
|
|
|
|
self._getToggleCommand = function(data) {
|
|
var disable = (data.enabled || data.pending_enable || (data.safe_mode_victim && data.safe_mode_enabled)) && !data.pending_disable;
|
|
return disable ? "disable" : "enable";
|
|
};
|
|
|
|
self.toggleButtonCss = function(data) {
|
|
var icon = self._getToggleCommand(data) == "enable" ? "icon-circle-blank" : "icon-circle";
|
|
var disabled = (self.enableToggle(data)) ? "" : " disabled";
|
|
|
|
return icon + disabled;
|
|
};
|
|
|
|
self.toggleButtonTitle = function(data) {
|
|
var command = self._getToggleCommand(data);
|
|
if (command == "enable") {
|
|
if (data.safe_mode_victim && !data.safe_mode_enabled) {
|
|
return gettext("Disabled due to active safe mode");
|
|
} else {
|
|
return gettext("Enable Plugin");
|
|
}
|
|
} else {
|
|
return gettext("Disable Plugin");
|
|
}
|
|
};
|
|
|
|
self.onBeforeBinding = function() {
|
|
self.settings = self.settingsViewModel.settings;
|
|
};
|
|
|
|
self.onUserLoggedIn = function(user) {
|
|
if (user.admin) {
|
|
self.requestData();
|
|
} else {
|
|
self.onUserLoggedOut();
|
|
}
|
|
};
|
|
|
|
self.onUserLoggedOut = function() {
|
|
self._closeAllNotifications();
|
|
};
|
|
|
|
self._closeAllNotifications = function() {
|
|
if (self.notifications) {
|
|
_.each(self.notifications, function(notification) {
|
|
notification.remove();
|
|
});
|
|
}
|
|
};
|
|
|
|
self.onServerDisconnect = function() {
|
|
self._closeAllNotifications();
|
|
return true;
|
|
};
|
|
|
|
self.onStartup = function() {
|
|
self.workingDialog = $("#settings_plugin_pluginmanager_workingdialog");
|
|
self.workingOutput = $("#settings_plugin_pluginmanager_workingdialog_output");
|
|
self.repositoryDialog = $("#settings_plugin_pluginmanager_repositorydialog");
|
|
|
|
$("#settings_plugin_pluginmanager_repositorydialog_list").slimScroll({
|
|
height: "306px",
|
|
size: "5px",
|
|
distance: "0",
|
|
railVisible: true,
|
|
alwaysVisible: true,
|
|
scrollBy: "102px"
|
|
});
|
|
};
|
|
|
|
self.onDataUpdaterPluginMessage = function(plugin, data) {
|
|
if (plugin != "pluginmanager") {
|
|
return;
|
|
}
|
|
|
|
if (!self.loginState.isAdmin()) {
|
|
return;
|
|
}
|
|
|
|
if (!data.hasOwnProperty("type")) {
|
|
return;
|
|
}
|
|
|
|
var messageType = data.type;
|
|
|
|
if (messageType == "loglines" && self.working()) {
|
|
_.each(data.loglines, function(line) {
|
|
self.loglines.push(self._preprocessLine(line));
|
|
});
|
|
self._scrollWorkingOutputToEnd();
|
|
} else if (messageType == "result") {
|
|
var titleSuccess, textSuccess, textRestart, textReload, titleError, textError;
|
|
var action = data.action;
|
|
|
|
var name = "Unknown";
|
|
if (action == "install") {
|
|
var unknown = false;
|
|
|
|
if (data.hasOwnProperty("plugin")) {
|
|
if (data.plugin == "unknown") {
|
|
unknown = true;
|
|
} else {
|
|
name = data.plugin.name;
|
|
}
|
|
}
|
|
|
|
if (unknown) {
|
|
titleSuccess = _.sprintf(gettext("Plugin installed"));
|
|
textSuccess = gettext("A plugin was installed successfully, however it was impossible to detect which one. Please Restart OctoPrint to make sure everything will be registered properly");
|
|
textRestart = textSuccess;
|
|
textReload = textSuccess;
|
|
} else if (data.was_reinstalled) {
|
|
titleSuccess = _.sprintf(gettext("Plugin \"%(name)s\" reinstalled"), {name: name});
|
|
textSuccess = gettext("The plugin was reinstalled successfully");
|
|
textRestart = gettext("The plugin was reinstalled successfully, however a restart of OctoPrint is needed for that to take effect.");
|
|
textReload = gettext("The plugin was reinstalled successfully, however a reload of the page is needed for that to take effect.");
|
|
} else {
|
|
titleSuccess = _.sprintf(gettext("Plugin \"%(name)s\" installed"), {name: name});
|
|
textSuccess = gettext("The plugin was installed successfully");
|
|
textRestart = gettext("The plugin was installed successfully, however a restart of OctoPrint is needed for that to take effect.");
|
|
textReload = gettext("The plugin was installed successfully, however a reload of the page is needed for that to take effect.");
|
|
}
|
|
|
|
titleError = gettext("Something went wrong");
|
|
var url = "unknown";
|
|
if (data.hasOwnProperty("url")) {
|
|
url = data.url;
|
|
}
|
|
|
|
if (data.hasOwnProperty("reason")) {
|
|
if (data.was_reinstalled) {
|
|
textError = _.sprintf(gettext("Reinstalling the plugin from URL \"%(url)s\" failed: %(reason)s"), {reason: data.reason, url: url});
|
|
} else {
|
|
textError = _.sprintf(gettext("Installing the plugin from URL \"%(url)s\" failed: %(reason)s"), {reason: data.reason, url: url});
|
|
}
|
|
} else {
|
|
if (data.was_reinstalled) {
|
|
textError = _.sprintf(gettext("Reinstalling the plugin from URL \"%(url)s\" failed, please see the log for details."), {url: url});
|
|
} else {
|
|
textError = _.sprintf(gettext("Installing the plugin from URL \"%(url)s\" failed, please see the log for details."), {url: url});
|
|
}
|
|
}
|
|
|
|
} else if (action == "uninstall") {
|
|
if (data.hasOwnProperty("plugin")) {
|
|
name = data.plugin.name;
|
|
}
|
|
|
|
titleSuccess = _.sprintf(gettext("Plugin \"%(name)s\" uninstalled"), {name: name});
|
|
textSuccess = gettext("The plugin was uninstalled successfully");
|
|
textRestart = gettext("The plugin was uninstalled successfully, however a restart of OctoPrint is needed for that to take effect.");
|
|
textReload = gettext("The plugin was uninstalled successfully, however a reload of the page is needed for that to take effect.");
|
|
|
|
titleError = gettext("Something went wrong");
|
|
if (data.hasOwnProperty("reason")) {
|
|
textError = _.sprintf(gettext("Uninstalling the plugin failed: %(reason)s"), {reason: data.reason});
|
|
} else {
|
|
textError = gettext("Uninstalling the plugin failed, please see the log for details.");
|
|
}
|
|
|
|
} else if (action == "enable") {
|
|
if (data.hasOwnProperty("plugin")) {
|
|
name = data.plugin.name;
|
|
}
|
|
|
|
titleSuccess = _.sprintf(gettext("Plugin \"%(name)s\" enabled"), {name: name});
|
|
textSuccess = gettext("The plugin was enabled successfully.");
|
|
textRestart = gettext("The plugin was enabled successfully, however a restart of OctoPrint is needed for that to take effect.");
|
|
textReload = gettext("The plugin was enabled successfully, however a reload of the page is needed for that to take effect.");
|
|
|
|
titleError = gettext("Something went wrong");
|
|
if (data.hasOwnProperty("reason")) {
|
|
textError = _.sprintf(gettext("Toggling the plugin failed: %(reason)s"), {reason: data.reason});
|
|
} else {
|
|
textError = gettext("Toggling the plugin failed, please see the log for details.");
|
|
}
|
|
|
|
} else if (action == "disable") {
|
|
if (data.hasOwnProperty("plugin")) {
|
|
name = data.plugin.name;
|
|
}
|
|
|
|
titleSuccess = _.sprintf(gettext("Plugin \"%(name)s\" disabled"), {name: name});
|
|
textSuccess = gettext("The plugin was disabled successfully.");
|
|
textRestart = gettext("The plugin was disabled successfully, however a restart of OctoPrint is needed for that to take effect.");
|
|
textReload = gettext("The plugin was disabled successfully, however a reload of the page is needed for that to take effect.");
|
|
|
|
titleError = gettext("Something went wrong");
|
|
if (data.hasOwnProperty("reason")) {
|
|
textError = _.sprintf(gettext("Toggling the plugin failed: %(reason)s"), {reason: data.reason});
|
|
} else {
|
|
textError = gettext("Toggling the plugin failed, please see the log for details.");
|
|
}
|
|
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
self._displayNotification(data, titleSuccess, textSuccess, textRestart, textReload, titleError, textError);
|
|
self.requestData();
|
|
}
|
|
};
|
|
|
|
self._forcedStdoutLine = /You are using pip version .*?, however version .*? is available\.|You should consider upgrading via the '.*?' command\./;
|
|
self._preprocessLine = function(line) {
|
|
if (line.stream == "stderr" && line.line.match(self._forcedStdoutLine)) {
|
|
line.stream = "stdout";
|
|
}
|
|
return line;
|
|
}
|
|
}
|
|
|
|
// view model class, parameters for constructor, container to bind to
|
|
ADDITIONAL_VIEWMODELS.push([
|
|
PluginManagerViewModel,
|
|
["loginStateViewModel", "settingsViewModel", "printerStateViewModel", "systemViewModel"],
|
|
"#settings_plugin_pluginmanager"
|
|
]);
|
|
});
|