MrDraw/src/octoprint/plugins/pluginmanager/templates/pluginmanager_settings.jinja2
Gina Häußge 5c0a564592 PMGR: Better handling of plugins disabled on the repo
Switched button from "Incompatible" to "Disabled", added link to
plugin page on repo with the prominent alert box explaining the
reason for disabling.
2017-03-31 17:55:18 +02:00

298 lines
19 KiB
Django/Jinja

{% 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 %}
{% macro pluginmanager_nopip() %}
<div class="alert" data-bind="visible: !pipAvailable()">{% trans %}
The <code>pip</code> command could not be found or does not work correctly
for this installation of OctoPrint - please consult the log file for details
and if necessary configure it manually. No installation and uninstallation of plugin
packages is possible while <code>pip</code> is unavailable.
{% endtrans %}</div>
{% endmacro %}
{% macro pluginmanager_safemode() %}
<div class="alert" data-bind="visible: safeMode">{% trans %}
Safe mode is currently active. All third party plugins are disabled and cannot be
enabled. Installation of plugin packages is disabled.
{% endtrans %}</div>
{% endmacro %}
{{ pluginmanager_printing() }}
{{ pluginmanager_nopip() }}
{{ pluginmanager_safemode() }}
<div class="pull-right">
<button class="btn btn-small" data-bind="click: function() { $root.showPluginSettings(); }" title="{{ _('Plugin Configuration') }}"><i class="icon-wrench"></i></button>
</div>
<h3>{{ _('Installed Plugins') }}</h3>
<table class="table table-striped table-hover table-condensed table-hover">
<thead>
<tr>
<th class="settings_plugin_plugin_manager_plugins_name">{{ _('Name') }}</th>
<th class="settings_plugin_plugin_manager_plugins_actions">{{ _('Actions') }}</th>
</tr>
</thead>
<tbody data-bind="foreach: plugins.paginatedItems">
<tr>
<td class="settings_plugin_plugin_manager_plugins_name">
<div data-bind="css: {muted: !enabled}"><span data-bind="text: name"></span> <span data-bind="visible: version">(<span data-bind="text: version"></span>)</span> <i title="{{ _('Bundled with OctoPrint') }}" class="icon-th-large" data-bind="visible: bundled"></i> <i class="icon-lock" title="{{ _('Cannot be uninstalled through OctoPrint') }}" data-bind="visible: !managable"></i> <i title="{{ _('Restart of OctoPrint needed for changes to take effect') }}" class="icon-refresh" data-bind="visible: pending_enable || pending_disable || pending_install || pending_uninstall"></i> <i title="{{ _('Pending install') }}" class="icon-plus" data-bind="visible: pending_install"></i> <i title="{{ _('Pending uninstall') }}" class="icon-minus" data-bind="visible: pending_uninstall"></i> <i title="{{ _('Disabled due to safe mode') }}" class="icon-medkit" data-bind="visible: safe_mode_victim"></i> <i class="icon-exclamation-sign" title="{{ _('There are notices available regarding this plugin') }}" data-bind="visible: notifications && notifications.length"></i></div>
<div data-bind="visible: notifications && notifications.length"><a href="javascript:void(0)" class="text-error" style="text-decoration: underline" data-bind="click: function() { $root.showPluginNotifications($data) }, text: $root.showPluginNotificationsLinkText($data)"></a></div>
<div><small class="muted" data-bind="text: description">&nbsp;</small></div>
<div data-bind="css: {muted: !enabled}">
<small data-bind="visible: url"><i class="icon-home"></i> <a data-bind="attr: {href: url}" target="_blank" rel="noreferrer noopener">{{ _('Homepage') }}</a></small>
<small data-bind="visible: license"><i class="icon-legal"></i> <span data-bind="text: license"></span></small>
<small data-bind="visible: author"><i class="icon-user"></i> <span data-bind="text: author"></span></small>
<small>&nbsp;</small>
</div>
</td>
<td class="settings_plugin_plugin_manager_plugins_actions">
<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>
</table>
<div class="pagination pagination-mini pagination-centered">
<ul>
<li data-bind="css: {disabled: plugins.currentPage() === 0}"><a href="#" data-bind="click: plugins.prevPage">«</a></li>
</ul>
<ul data-bind="foreach: plugins.pages">
<li data-bind="css: { active: $data.number === $root.plugins.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.plugins.changePage($data.number); }"></a></li>
</ul>
<ul>
<li data-bind="css: {disabled: plugins.currentPage() === plugins.lastPage()}"><a href="#" data-bind="click: plugins.nextPage">»</a></li>
</ul>
</div>
<button class="btn btn-block" data-bind="click: $root.showRepository">{{ _('Get More...') }}</button>
<div class="muted" data-bind="visible: pipAvailable()">
<div>
<small>
<a href="javascript:void(0)" class="muted" onclick="$(this).children('i.toggle-arrow').toggleClass('icon-caret-right icon-caret-down').parent().parent().parent().next().slideToggle('fast')">
<i class="toggle-arrow icon-caret-right"></i> Using pip of "<span data-bind="text: pipPython"></span>", Version <span data-bind="text: pipVersion"></span>
</a>
</small>
</div>
<div class="hide">
<small>
Installation directory: <span data-bind="text: pipInstallDir"></span> ("--user" flag: <span data-bind="text: pipUseUserString"></span>)<br />
Virtual environment: <span data-bind="text: pipVirtualEnvString"></span><br />
<span data-bind="visible: pipAdditionalArgs">Additional Arguments: <span data-bind="text: pipAdditionalArgs"></span></span>
</small>
</div>
</div>
<div class="muted">
<div>
<small>
<a href="javascript:void(0)" class="muted" onclick="$(this).children('i.toggle-arrow').toggleClass('icon-caret-right icon-caret-down').parent().parent().parent().next().slideToggle('fast')">
<i class="toggle-arrow icon-caret-right"></i> <span data-bind="text: noticeCountText"></span>
</a>
</small>
</div>
<div class="hide">
<small>
<!-- ko if: noticeCount() > 0 --><a href="javascript:void(0)" data-bind="click: function() { reshowNotices(); }">{{ _('Reshow current notices') }}</a> &middot;<!-- /ko -->
<a href="javascript:void(0)" data-bind="click: function() { refreshNotices(); }">{{ _('Refresh notices from repository') }}</a>
</small>
</div>
</div>
<div id="settings_plugin_pluginmanager_workingdialog" class="modal hide fade">
<div class="modal-header">
<h3 data-bind="text: workingTitle"></h3>
</div>
<div class="modal-body">
<pre id="settings_plugin_pluginmanager_workingdialog_output" class="terminal pre-scrollable" style="height: 170px" data-bind="foreach: loglines"><span data-bind="text: line, css: {stdout: stream == 'stdout', stderr: stream == 'stderr', call: stream == 'call', message: stream == 'message'}"></span><br></pre>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" data-bind="enable: !$root.working()" aria-hidden="true">{{ _('Close') }}</button>
</div>
</div>
<div id="settings_plugin_pluginmanager_repositorydialog" class="modal hide fade">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">&times;</a>
<h3>{{ _('Install new Plugins...') }}</h3>
</div>
<div class="modal-body">
{{ pluginmanager_printing() }}
{{ pluginmanager_nopip() }}
{{ pluginmanager_safemode() }}
<h4 style="position: relative">
{{ _('... from the <a href="%(url)s" target="_blank">Plugin Repository</a>', url='http://plugins.octoprint.org') }}
<div class="dropdown pull-right">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<span class="icon-wrench"></span>
</a>
<ul class="dropdown-menu pull-right">
<li><a href="#" data-bind="click: function() { repositoryplugins.changeSorting('title'); }"><i class="icon-ok" data-bind="style: {visibility: repositoryplugins.currentSorting() == 'title' ? 'visible' : 'hidden'}"></i> {{ _('Sort by title') }} ({{ _('ascending') }})</a></li>
<li><a href="#" data-bind="click: function() { repositoryplugins.changeSorting('published'); }"><i class="icon-ok" data-bind="style: {visibility: repositoryplugins.currentSorting() == 'published' ? 'visible' : 'hidden'}"></i> {{ _('Sort by publication date') }} ({{ _('descending') }})</a></li>
<li class="divider"></li>
<li><a href="#" data-bind="click: function() { repositoryplugins.toggleFilter('filter_installed'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(repositoryplugins.currentFilters(), 'filter_installed') ? 'visible' : 'hidden'}"></i> {{ _('Only show uninstalled plugins') }}</a></li>
<li><a href="#" data-bind="click: function() { repositoryplugins.toggleFilter('filter_incompatible'); }"><i class="icon-ok" data-bind="style: {visibility: _.contains(repositoryplugins.currentFilters(), 'filter_incompatible') ? 'visible' : 'hidden'}"></i> {{ _('Only show compatible plugins') }}</a></li>
<li class="divider"></li>
<li><a href="#" data-bind="click: function() { refreshRepository(); }"><i class="icon-refresh"></i> {{ _('Refresh list from repository') }}</a></li>
</ul>
</div>
</h4>
<form class="form-search" data-bind="submit: performRepositorySearch">
<input type="text" class="input-block search-query" data-bind="value: repositorySearchQuery, valueUpdate: 'input'" placeholder="{{ _('Search...') }}">
</form>
<div data-bind="visible: repositoryAvailable()">
<div id="settings_plugin_pluginmanager_repositorydialog_list" data-bind="slimScrolledForeach: repositoryplugins.paginatedItems">
<div class="entry">
<div class="row-fluid">
<div class="span9">
<div><span data-bind="text: title"></span></div>
<div><small class="muted" data-bind="text: description">&nbsp;</small></div>
<div>
<small data-bind="visible: page"><i class="icon-info"></i> <a data-bind="attr: {href: page}" target="_blank">{{ _('Details') }}</a></small>
<small data-bind="visible: homepage"><i class="icon-home"></i> <a data-bind="attr: {href: homepage}" target="_blank">{{ _('Homepage') }}</a></small>
<small data-bind="visible: license"><i class="icon-legal"></i> <span data-bind="text: license"></span></small>
<small data-bind="visible: author"><i class="icon-user"></i> <span data-bind="text: author"></span></small>
<small>&nbsp;</small>
</div>
</div>
<div class="span3">
<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 data-bind="visible: $data.disabled !== undefined" style="text-align: center"><small><a data-bind="attr: {href: page}" target="_blank">{{ _('"Why?"') }}</a></small></div>
</div>
</div>
</div>
</div>
</div>
<div id="settings_plugin_pluginmanager_repositorydialog_unavailable" data-bind="visible: !repositoryAvailable()">
<div>
<p>
<strong>{{ _('Sadly the repository is currently not available') }}</strong>
</p>
<p>
<small>{{ _('Is your OctoPrint installation connected to the internet?') }}</small>
</p>
</div>
</div>
<h4>{{ _('... from URL') }}</h4>
<form class="form-inline">
<div class="control-group row-fluid" data-bind="css: {error: invalidUrl}">
<div class="span9">
<input type="text" class="input-block-level" data-bind="value: installUrl, valueUpdate: 'input'" placeholder="{{ _('Enter URL...') }}" >
</div>
<button class="btn btn-primary span3" data-bind="enable: enableUrlInstall, css: {disabled: !enableUrlInstall()}, click: function() { if (enableUrlInstall()) { $root.installPlugin(); } }">{{ _('Install') }}</button>
</div>
<span class="help-block" data-bind="visible: invalidUrl">{{ _('This does not look like a valid "http://" or "https://" URL.') }}</span>
</form>
<h4>{{ _('... from an uploaded archive') }}</h4>
<form class="form-inline">
<div class="control-group row-fluid" data-bind="css: {error: invalidArchive}">
<div class="input-prepend span9">
<span class="btn fileinput-button">
<span>{{ _('Browse...') }}</span>
<input id="settings_plugin_pluginmanager_repositorydialog_upload" type="file" name="file" accept="{{ ",".join(plugin_pluginmanager_archive_extensions) }}" data-url="{{ url_for("plugin.pluginmanager.upload_archive") }}">
</span>
<span class="add-on add-on-limited text-left" data-bind="text: uploadFilename, attr: {title: uploadFilename}"></span>
</div>
<button id="settings_plugin_pluginmanager_repositorydialog_upload_start" class="btn btn-primary span3" data-bind="enable: enableArchiveInstall, css: {disabled: !enableArchiveInstall()}, click: function(){}">{{ _('Install') }}</button>
</div>
<span class="help-block" data-bind="visible: invalidArchive">{{ _('This does not look like a valid plugin archive. Valid plugin archives should be either zip files or tarballs and have the extension ".zip", ".tar.gz", ".tgz" or ".tar"') }}</span>
</form>
<div>
<div><small><a href="#" class="muted" onclick="$(this).children().toggleClass('icon-caret-right icon-caret-down').parent().parent().parent().next().slideToggle('fast')"><i class="icon-caret-right"></i> {{ _('Advanced options') }}</a></small></div>
<div class="hide">
<form class="form-horizontal">
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: followDependencyLinks"> {{ _('Use <code>--process-dependency-links</code> with <code>pip install</code>') }}
</label>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Close') }}</button>
</div>
</div>
<div id="settings_plugin_pluginmanager_configurationdialog" class="modal hide fade">
<div class="modal-header">
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">&times;</a>
<h3>{{ _('Plugin Configuration') }}</h3>
</div>
<div class="modal-body">
<form class="form-horizontal">
<p>{% trans %}You should normally <strong>not</strong> have to change <strong>any</strong> of the following settings, they are purely provided for convenience here.{% endtrans %}</p>
<legend>{{ _('Plugin repository configuration') }}</legend>
<div class="control-group" title="{{ _('URL of the Plugin Repository to use. You should normally not have to change this.') }}">
<label class="control-label">{{ _('Repository URL') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: config_repositoryUrl">
</div>
</div>
<div class="control-group" title="{{ _('How long to cache repository data, in minutes. You should normally not have to change this.') }}">
<label class="control-label">{{ _('Repository cache TTL') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" class="input-mini" data-bind="value: config_repositoryTtl">
<span class="add-on">min</span>
</div>
</div>
</div>
<legend>{{ _('Notices configuration') }}</legend>
<div class="control-group" title="{{ _('URL of the Notices source to use. You should normally not have to change this.') }}">
<label class="control-label">{{ _('Notices URL') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: config_noticesUrl">
</div>
</div>
<div class="control-group" title="{{ _('How long to cache notices, in minutes. You should normally not have to change this.') }}">
<label class="control-label">{{ _('Notices cache TTL') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" class="input-mini" data-bind="value: config_noticesTtl">
<span class="add-on">min</span>
</div>
</div>
</div>
<legend>{{ _('pip configuration') }}</legend>
<div class="control-group" title="{{ _('Additional arguments for the pip command. You should normally not have to change this.') }}">
<label class="control-label">{{ _('Additional arguments') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: config_pipAdditionalArgs">
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: config_pipForceUser"> {{ _('Force the use of the <code>--user</code> flag with <code>pip install</code>') }}
</label>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Cancel') }}</button>
<button class="btn btn-primary" data-bind="click: savePluginSettings" aria-hidden="true">{{ _('Save') }}</button>
</div>
</div>