Don't allow plugin management while the printer is printing

This commit is contained in:
Gina Häußge 2015-06-18 11:37:08 +02:00
parent 268886576f
commit 0ce1575e12
4 changed files with 55 additions and 15 deletions

View file

@ -141,6 +141,10 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin,
if not admin_permission.can():
return make_response("Insufficient rights", 403)
if self._printer.is_printing() or self._printer.is_paused():
# do not update while a print job is running
return make_response("Printer is currently printing or paused", 409)
if command == "install":
url = data["url"]
plugin_name = data["plugin"] if "plugin" in data else None
@ -165,10 +169,6 @@ class PluginManagerPlugin(octoprint.plugin.SimpleApiPlugin,
plugin = self._plugin_manager.plugins[plugin_name]
return self.command_toggle(plugin, command)
elif command == "refresh_repository":
self._repository_available = self._refresh_repository()
return jsonify(repository=dict(available=self._repository_available, plugins=self._repository_plugins))
def command_install(self, url=None, path=None, force=False, reinstall=None, dependency_links=False):
if url is not None:
pip_args = ["install", sarge.shell_quote(url)]

View file

@ -4,6 +4,7 @@ $(function() {
self.loginState = parameters[0];
self.settingsViewModel = parameters[1];
self.printerState = parameters[2];
self.plugins = new ItemListHelper(
"plugin.pluginmanager.installedplugins",
@ -76,6 +77,22 @@ $(function() {
self.workingDialog = undefined;
self.workingOutput = undefined;
self.enableManagement = ko.computed(function() {
return !self.printerState.isPrinting();
});
self.enableToggle = function(data) {
return self.enableManagement() && data.key != 'pluginmanager';
};
self.enableUninstall = function(data) {
return self.enableManagement() && !data.bundled && data.key != 'pluginmanager' && !data.pending_uninstall;
};
self.enableRepoInstall = function(data) {
return self.enableManagement() && self.isCompatible(data);
};
self.invalidUrl = ko.computed(function() {
var url = self.installUrl();
return url !== undefined && url.trim() != "" && !(_.startsWith(url.toLocaleLowerCase(), "http://") || _.startsWith(url.toLocaleLowerCase(), "https://"));
@ -83,7 +100,7 @@ $(function() {
self.enableUrlInstall = ko.computed(function() {
var url = self.installUrl();
return url !== undefined && url.trim() != "" && !self.invalidUrl();
return self.enableManagement() && url !== undefined && url.trim() != "" && !self.invalidUrl();
});
self.invalidArchive = ko.computed(function() {
@ -93,7 +110,7 @@ $(function() {
self.enableArchiveInstall = ko.computed(function() {
var name = self.uploadFilename();
return name !== undefined && name.trim() != "" && !self.invalidArchive();
return self.enableManagement() && name !== undefined && name.trim() != "" && !self.invalidArchive();
});
self.uploadElement.fileupload({
@ -187,6 +204,10 @@ $(function() {
return;
}
if (!self.enableManagement()) {
return;
}
if (data.key == "pluginmanager") return;
var command = self._getToggleCommand(data);
@ -217,6 +238,10 @@ $(function() {
return;
}
if (!self.enableManagement()) {
return;
}
if (self.installed(data)) {
self.installPlugin(data.archive, data.title, data.id, data.follow_dependency_links || self.followDependencyLinks());
} else {
@ -229,6 +254,10 @@ $(function() {
return;
}
if (!self.enableManagement()) {
return;
}
if (url === undefined) {
url = self.installUrl();
}
@ -279,6 +308,10 @@ $(function() {
return;
}
if (!self.enableManagement()) {
return;
}
if (data.bundled) return;
if (data.key == "pluginmanager") return;
@ -305,9 +338,7 @@ $(function() {
return;
}
self._postCommand("refresh_repository", {}, function(data) {
self._fromRepositoryResponse(data.repository);
})
self.requestData(true);
};
self.installed = function(data) {
@ -420,7 +451,7 @@ $(function() {
self.toggleButtonCss = function(data) {
var icon = self._getToggleCommand(data) == "enable" ? "icon-circle-blank" : "icon-circle";
var disabled = (data.key == "pluginmanager") ? " disabled" : "";
var disabled = (self.enableToggle(data)) ? "" : " disabled";
return icon + disabled;
};
@ -578,5 +609,5 @@ $(function() {
}
// view model class, parameters for constructor, container to bind to
ADDITIONAL_VIEWMODELS.push([PluginManagerViewModel, ["loginStateViewModel", "settingsViewModel"], "#settings_plugin_pluginmanager"]);
ADDITIONAL_VIEWMODELS.push([PluginManagerViewModel, ["loginStateViewModel", "settingsViewModel", "printerStateViewModel"], "#settings_plugin_pluginmanager"]);
});

View file

@ -1,3 +1,11 @@
{% macro pluginmanager_printing() %}
<div class="alert" data-bind="visible: !enableManagement()">
{{ _('Take note that all plugin management functionality is disabled while your printer is printing.') }}
</div>
{% endmacro %}
{{ pluginmanager_printing() }}
<h3>{{ _('Installed Plugins') }}</h3>
<table class="table table-striped table-hover table-condensed table-hover">
@ -20,7 +28,7 @@
</div>
</td>
<td class="settings_plugin_plugin_manager_plugins_actions">
<a href="#" data-bind="css: $root.toggleButtonCss($data), attr: {title: $root.toggleButtonTitle($data)}, enable: key != 'pluginmanager', click: function() { $root.togglePlugin($data) }"></a>&nbsp;|&nbsp;<a href="#" class="icon-trash" title="{{ _('Uninstall Plugin') }}" data-bind="css: {disabled: bundled || key == 'pluginmanager' || pending_uninstall}, enable: !bundled && key != 'pluginmanager' && !pending_uninstall, click: function() { $root.uninstallPlugin($data) }"></a>
<a href="#" data-bind="css: $root.toggleButtonCss($data), attr: {title: $root.toggleButtonTitle($data)}, enable: $root.enableToggle($data), click: function() { $root.togglePlugin($data) }"></a>&nbsp;|&nbsp;<a href="#" class="icon-trash" title="{{ _('Uninstall Plugin') }}" data-bind="css: {disabled: !$root.enableUninstall($data)}, enable: $root.enableUninstall($data), click: function() { $root.uninstallPlugin($data) }"></a>
</td>
</tr>
</tbody>
@ -58,6 +66,7 @@
<h3>{{ _('Install new Plugins...') }}</h3>
</div>
<div class="modal-body">
{{ pluginmanager_printing() }}
<h4 style="position: relative">
{{ _('... from the <a href="%(url)s" target="_blank">Plugin Repository</a>', url='http://plugins.octoprint.org') }}
<a class="dropdown-toggle pull-right" data-toggle="dropdown" href="#">
@ -94,7 +103,7 @@
</div>
</div>
<div class="span3">
<button class="btn btn-primary btn-block" data-bind="enable: $root.isCompatible($data), css: {disabled: !$root.isCompatible($data)}, click: function() { if ($root.isCompatible($data)) { $root.installFromRepository($data); } else { return false; } }"><i class="icon-add"></i> <span data-bind="text: $root.installButtonText($data)"></span></button>
<button class="btn btn-primary btn-block" data-bind="enable: $root.enableRepoInstall($data), css: {disabled: !$root.enableRepoInstall($data)}, click: function() { if ($root.enableRepoInstall($data)) { $root.installFromRepository($data); } else { return false; } }"><i class="icon-add"></i> <span data-bind="text: $root.installButtonText($data)"></span></button>
</div>
</div>
</div>

View file

@ -116,10 +116,10 @@ class SoftwareUpdatePlugin(octoprint.plugin.BlueprintPlugin,
def perform_update(self):
if self._printer.is_printing() or self._printer.is_paused():
# do not update while a print job is running
flask.make_response("Printer is currently printing or paused", 409)
return flask.make_response("Printer is currently printing or paused", 409)
if not "application/json" in flask.request.headers["Content-Type"]:
flask.make_response("Expected content-type JSON", 400)
return flask.make_response("Expected content-type JSON", 400)
json_data = flask.request.json