This way it will also be possible to easily add another qrcode to the user api key later. Refused to work for now (value binding doesn't update), so commented out right now, but works in theory.
684 lines
47 KiB
Django/Jinja
684 lines
47 KiB
Django/Jinja
<div id="settings_dialog" class="modal hide fade container" tabindex="-1" role="dialog" aria-labelledby="settings_dialog_label" aria-hidden="true">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal">×</button>
|
|
<h3 id="settings_dialog_label">{{ _('OctoPrint Settings') }}</h3>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="tabbable">
|
|
<ul class="nav nav-list span4" id="settingsTabs">
|
|
<li class="nav-header">{{ _('Printer') }}</li>
|
|
<li class="active"><a href="#settings_serialConnection" data-toggle="tab">{{ _('Serial Connection') }}</a></li>
|
|
<li><a href="#settings_printerParameters" data-toggle="tab">{{ _('Printer Parameters') }}</a></li>
|
|
<li><a href="#settings_temperature" data-toggle="tab">{{ _('Temperatures') }}</a></li>
|
|
<li><a href="#settings_terminalFilters" data-toggle="tab">{{ _('Terminal filters') }}</a></li>
|
|
<li class="nav-header">{{ _('Features') }}</li>
|
|
<li><a href="#settings_features" data-toggle="tab">{{ _('Features') }}</a></li>
|
|
<li><a href="#settings_webcam" data-toggle="tab">{{ _('Webcam') }}</a></li>
|
|
{% if enableAccessControl %}<li><a href="#settings_users" data-toggle="tab">{{ _('Access Control') }}</a></li>{% endif %}
|
|
<li><a href="#settings_api" data-toggle="tab">{{ _('API') }}</a></li>
|
|
<li class="nav-header">OctoPrint</li>
|
|
<li><a href="#settings_folder" data-toggle="tab">{{ _('Folders') }}</a></li>
|
|
<li><a href="#settings_appearance" data-toggle="tab">{{ _('Appearance') }}</a></li>
|
|
<li><a href="#settings_logs" data-toggle="tab">{{ _('Logs') }}</a></li>
|
|
{% if settingsPlugins %}
|
|
<li class="nav-header">Plugins</li>
|
|
{% for plugin_name, vars in settingsPlugins.items() %}
|
|
{% if vars._settings_menu_entry %}
|
|
<li><a href="#settings_plugin_{{ plugin_name }}" data-toggle="tab">{{ vars._settings_menu_entry }}</a></li>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
</ul>
|
|
|
|
<div class="tab-content span8">
|
|
<div class="tab-pane active" id="settings_serialConnection">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-serialPort">{{ _('Serial Port') }}</label>
|
|
<div class="controls">
|
|
<select id="settings-serialPort" data-bind="options: serial_portOptions, optionsCaption: 'AUTO', value: serial_port"></select>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-baudrate">{{ _('Baudrate') }}</label>
|
|
<div class="controls">
|
|
<select id="settings-baudrate" data-bind="options: serial_baudrateOptions, optionsCaption: 'AUTO', value: serial_baudrate"></select>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: serial_autoconnect" id="settings-serialAutoconnect"> {{ _('Auto-connect to printer on server start') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-serialTimeoutCommunication">{{ _('Communication timeout') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutCommunication" id="settings-serialTimeoutCommunication">
|
|
<span class="add-on">s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-movementSpeedE">{{ _('Temperature timeout') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutTemperature" id="settings-serialTimeoutTemperature">
|
|
<span class="add-on">s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-serialTimeoutSdStatus">{{ _('SD status timeout') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutSdStatus" id="settings-serialTimeoutSdStatus">
|
|
<span class="add-on">s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-serialTimeoutConnection">{{ _('Connection timeout') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutConnection" id="settings-serialTimeoutConnection">
|
|
<span class="add-on">s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-serialTimeoutDetection">{{ _('Autodetection timeout') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutDetection" id="settings-serialTimeoutDetection">
|
|
<span class="add-on">s</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: serial_log" id="settings-serialLog"> {{ _('Log communication to serial.log (might negatively impact performance)') }} <span class="label label-important">{{ _('Warning') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_printerParameters">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label">{{ _('Axis') }}</label>
|
|
<div class="controls form-inline">
|
|
<label>{{ _('X') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" class="input-mini text-right" data-bind="value: printer_movementSpeedX" id="settings-movementSpeedX">
|
|
<span class="add-on">mm/min</span>
|
|
</div>
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: printer_invertX" id="settings-printerInvertX"> {{ _('Invert control') }}
|
|
</label>
|
|
</div>
|
|
<div class="controls form-inline">
|
|
<label>{{ _('Y') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" class="input-mini text-right" data-bind="value: printer_movementSpeedY" id="settings-movementSpeedY">
|
|
<span class="add-on">mm/min</span>
|
|
</div>
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: printer_invertY" id="settings-printerInvertY"> {{ _('Invert control') }}
|
|
</label>
|
|
</div>
|
|
<div class="controls form-inline">
|
|
<label>{{ _('Z') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" class="input-mini text-right" data-bind="value: printer_movementSpeedZ" id="settings-movementSpeedZ">
|
|
<span class="add-on">mm/min</span>
|
|
</div>
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: printer_invertZ" id="settings-printerInvertZ"> {{ _('Invert control') }}
|
|
</label>
|
|
</div>
|
|
<div class="controls form-inline">
|
|
<label>{{ _('E') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" class="input-mini text-right" data-bind="value: printer_movementSpeedE" id="settings-movementSpeedE">
|
|
<span class="add-on">mm/min</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-defaultExtrusionLength">{{ _('Default extrusion length') }}</label>
|
|
<div class="controls">
|
|
<input type="number" class="input-mini text-right" min="1" data-bind="value: printer_defaultExtrusionLength" id="settings-defaultExtrusionLength">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-numExtruders">{{ _('Number of Extruders') }}</label>
|
|
<div class="controls">
|
|
<input type="number" class="input-mini text-right" min="1" max="5" data-bind="value: printer_numExtruders" id="settings-numExtruders">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-extruderOffsets">{{ _('Extruder Offsets') }}</label>
|
|
<!-- ko foreach: ko_printer_extruderOffsets -->
|
|
<div class="controls form-inline">
|
|
<label>X:</label>
|
|
<div class="input-append">
|
|
<input type="number" step="0.01" class="input-mini text-right" data-bind="value: x">
|
|
<span class="add-on">mm</span>
|
|
</div>
|
|
<label>Y:</label>
|
|
<div class="input-append">
|
|
<input type="number" step="0.01" class="input-mini text-right" data-bind="value: y">
|
|
<span class="add-on">mm</span>
|
|
</div>
|
|
</div>
|
|
<!-- /ko -->
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-bedSize">{{ _('Bed Size') }}</label>
|
|
<div class="controls form-inline" data-bind="ifnot: printer_bedCircular">
|
|
<label>{{ _('X') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" step="0.01" class="input-mini text-right" data-bind="value: printer_bedDimensionX" id="settings-bedX">
|
|
<span class="add-on">mm</span>
|
|
</div>
|
|
<label>{{ _('Y') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" step="0.01" class="input-mini text-right" data-bind="value: printer_bedDimensionY" id="settings-bedY">
|
|
<span class="add-on">mm</span>
|
|
</div>
|
|
</div>
|
|
<div class="controls form-inline" data-bind="if: printer_bedCircular">
|
|
<label>{{ _('Radius') }}:</label>
|
|
<div class="input-append">
|
|
<input type="number" step="0.01" class="input-mini text-right" data-bind="value: printer_bedDimensionR" id="settings-bedR">
|
|
<span class="add-on">mm</span>
|
|
</div>
|
|
</div>
|
|
<div class="controls form-inline">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: printer_bedCircular" id="settings-bedCircular"> {{ _('Circular') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_webcam">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-webcamStreamUrl">{{ _('Stream URL') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: webcam_streamUrl" id="settings-webcamStreamUrl">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-webcamStreamUrl">{{ _('Snapshot URL') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: webcam_snapshotUrl" id="settings-webcamSnapshotUrl">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-webcamStreamUrl">{{ _('Path to FFMPEG') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: webcam_ffmpegPath" id="settings-webcamFfmpegPath">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-webcamBitrate">{{ _('Timelapse bitrate') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: webcam_bitrate" id="settings-webcamBitrate">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: webcam_watermark" id="settings-webcamWatermark"> {{ _('Enable OctoPrint watermark in timelapse movies') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: webcam_flipH" id="settings-webcamFlipH"> {{ _('Flip webcam horizontally') }}
|
|
</label>
|
|
</div>
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: webcam_flipV" id="settings-webcamFlipV"> {{ _('Flip webcam vertically') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_features">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_temperatureGraph" id="settings-featureTemperatureGraph"> {{ _('Enable Temperature Graph') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_gcodeViewer" id="settings-featureGcodeViewer"> {{ _('Enable GCode Visualizer') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_sdSupport" id="settings-featureSdSupport"> {{ _('Enable SD support') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_sdAlwaysAvailable" id="settings-featureSdAlwaysAvailable"> {{ _('Always assume SD card is present') }} <span class="label">{{ _('Repetier') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_waitForStart" id="settings-featureWaitForStart"> {{ _('Wait for <code>start</code> on connect') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_alwaysSendChecksum" id="settings-featureAlwaysSendChecksum"> {{ _('Send a checksum with <strong>every</strong> command') }} <span class="label">{{ _('Repetier') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_repetierTargetTemp" id="settings-featureRepetierTargetTemp"> {{ _('Support <code>TargetExtr%%n</code>/<code>TargetBed</code> target temperature format') }} <span class="label">{{ _('Repetier') }}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" data-bind="checked: feature_swallowOkAfterResend" id="settings-swallowOkAfterResend"> {{ _('Swallow the first "ok" after a resend response') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_folder">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-folderUploads">{{ _('Upload Folder') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: folder_uploads" id="settings-folderUploads">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-folderTimelapse">{{ _('Timelapse Folder') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: folder_timelapse" id="settings-folderTimelapse">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-folderTimelapseTemp">{{ _('Timelapse Temp Folder') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: folder_timelapseTmp" id="settings-folderTimelapseTemp">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-folderLogs">{{ _('Logs Folder') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: folder_logs" id="settings-folderLogs">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-watchedLogs">{{ _('Watched Folder') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: folder_watched" id="settings-folderWatched">
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_temperature">
|
|
<form class="form-horizontal">
|
|
<div class="row-fluid">
|
|
<div class="offset3 span3"><h4>{{ _('Extruder') }}</h4></div>
|
|
<div class="span3"><h4>{{ _('Bed') }}</h4></div>
|
|
</div>
|
|
<div data-bind="foreach: temperature_profiles">
|
|
<div class="row-fluid" style="margin-bottom: 5px">
|
|
<div class="span3">
|
|
<input type="text" class="span12 text-right" data-bind="value: name">
|
|
</div>
|
|
<div class="input-append span3">
|
|
<input type="number" class="input-mini text-right" data-bind="value: extruder">
|
|
<span class="add-on">°C</span>
|
|
</div>
|
|
<div class="input-append span3">
|
|
<input type="number" class="input-mini text-right" data-bind="value: bed">
|
|
<span class="add-on">°C</span>
|
|
</div>
|
|
<div class="span2">
|
|
<a title="Remove profile" class="btn btn-danger" data-bind="click: $parent.removeTemperatureProfile"><i class="icon-trash"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row-fluid">
|
|
<div class="offset9 span2">
|
|
<a title="Add Profile" class="btn btn-primary" data-bind="click: addTemperatureProfile"><i class="icon-plus"></i></a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_terminalFilters">
|
|
<form class="form-horizontal">
|
|
<div class="row-fluid">
|
|
<div class="span4"><h4>{{ _('Name') }}</h4></div>
|
|
<div class="span6"><h4>{{ _('RegExp') }} <small><a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions">?</a></small></h4></div>
|
|
</div>
|
|
<div data-bind="foreach: terminalFilters">
|
|
<div class="row-fluid" style="margin-bottom: 5px">
|
|
<div class="span4">
|
|
<input type="text" class="span12" data-bind="value: name">
|
|
</div>
|
|
<div class="span6">
|
|
<input type="text" class="span12" data-bind="value: regex">
|
|
</div>
|
|
<div class="span2">
|
|
<a title="Remove Filter" class="btn btn-danger" data-bind="click: $parent.removeTerminalFilter"><i class="icon-trash"></i></a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row-fluid">
|
|
<div class="offset10 span2">
|
|
<a title="Add Filter" class="btn btn-primary" data-bind="click: addTerminalFilter"><i class="icon-plus"></i></a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_appearance">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-appearanceName">{{ _('Title') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: appearance_name" id="settings-appearanceName">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-appearanceColor">{{ _('Color') }}</label>
|
|
<div class="controls">
|
|
<select id="settings-appearanceColor" data-bind="value: appearance_color, options: appearance_available_colors, optionsText: 'name', optionsValue: 'key'">
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="tab-pane" id="settings_api">
|
|
<form class="form-horizontal" onsubmit="return false;">
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-apiEnabled" data-bind="checked: api_enabled"> {{ _('Enable') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-apiCors" data-bind="checked: api_allowCrossOrigin"> {{ _('Allow <a href="%(url)s">Cross Origin Resource Sharing (CORS)</a>', url = "https://en.wikipedia.org/wiki/Cross-origin_resource_sharing") }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-apiKey">{{ _('API Key') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" data-bind="value: api_key, valueUpdate: 'afterkeydown'" id="settings-apikey">
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label">{{ _('QR Code') }}</label>
|
|
<div class="controls">
|
|
<div data-bind="qrcode: {text: api_key, size: 180}"></div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{% if enableAccessControl %}
|
|
<div class="tab-pane" id="settings_users">
|
|
<table class="table table-condensed table-hover" id="system_users">
|
|
<thead>
|
|
<tr>
|
|
<th class="settings_users_name">{{ _('Name') }}</th>
|
|
<th class="settings_users_active">{{ _('Active') }}</th>
|
|
<th class="settings_users_admin">{{ _('Admin') }}</th>
|
|
<th class="settings_users_actions">{{ _('Action') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody data-bind="foreach: users.listHelper.paginatedItems">
|
|
<tr>
|
|
<td class="settings_users_name"><span data-bind="text: name"></span><span class="muted" data-bind="visible: $root.api_enabled() && apikey"><br /><small>{{ _('API Key') }}: <span data-bind="text: apikey"></span></small></span></td>
|
|
<td class="settings_users_active"><i data-bind="css: { 'icon-check': active, 'icon-check-empty': !active }"></i></td>
|
|
<td class="settings_users_admin"><i data-bind="css: { 'icon-check': admin, 'icon-check-empty': !admin }"></i></td>
|
|
<td class="settings_users_actions" class="system_users_action">
|
|
<a href="#" class="icon-pencil" title="{{ _('Update User') }}" data-bind="click: function() { $root.users.showEditUserDialog($data); }"></a> | <a href="#" class="icon-key" title="{{ _('Change password') }}" data-bind="click: function() { $root.users.showChangePasswordDialog($data); }"></a> | <a href="#" class="icon-trash" title="{{ _('Delete user') }}" data-bind="click: function() { $root.users.removeUser($data); }"></a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="pagination pagination-mini pagination-centered">
|
|
<ul>
|
|
<li data-bind="css: {disabled: users.listHelper.currentPage() === 0}"><a href="#" data-bind="click: users.listHelper.prevPage">«</a></li>
|
|
</ul>
|
|
<ul data-bind="foreach: users.listHelper.pages">
|
|
<li data-bind="css: { active: $data.number === $root.users.listHelper.currentPage(), disabled: $data.number === -1 }"><a href="#" data-bind="text: $data.text, click: function() { $root.users.listHelper.changePage($data.number); }"></a></li>
|
|
</ul>
|
|
<ul>
|
|
<li data-bind="css: {disabled: users.listHelper.currentPage() === users.listHelper.lastPage()}"><a href="#" data-bind="click: users.listHelper.nextPage">»</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<button title="Add user" class="btn" data-bind="click: $root.users.showAddUserDialog"><i class="icon-plus"></i> {{ _('Add user') }}</button>
|
|
|
|
<!-- Modals for user management -->
|
|
|
|
<div id="settings-usersDialogAddUser" class="modal hide fade">
|
|
<div class="modal-header">
|
|
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
|
|
<h3>{{ _('Add user') }}</h3>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-usersDialogAddUserName">{{ _('Username') }}</label>
|
|
<div class="controls">
|
|
<input type="text" class="input-block-level" id="settings-usersDialogAddUserName" data-bind="value: $root.users.editorUsername" required>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-usersDialogAddUserPassword1">{{ _('Password') }}</label>
|
|
<div class="controls">
|
|
<input type="password" class="input-block-level" id="settings-usersDialogAddUserPassword1" data-bind="value: $root.users.editorPassword" required>
|
|
</div>
|
|
</div>
|
|
<div class="control-group" data-bind="css: {error: $root.users.editorPasswordMismatch()}">
|
|
<label class="control-label" for="settings-usersDialogAddUserPassword2">{{ _('Repeat Password') }}</label>
|
|
<div class="controls">
|
|
<input type="password" class="input-block-level" id="settings-usersDialogAddUserPassword2" data-bind="value: $root.users.editorRepeatedPassword, valueUpdate: 'afterkeydown'" required>
|
|
<span class="help-inline" data-bind="visible: $root.users.editorPasswordMismatch()">{{ _('Passwords do not match') }}</span>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-usersDialogAddUserActive" data-bind="checked: $root.users.editorActive"> {{ _('Active') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-usersDialogAddUserAdmin" data-bind="checked: $root.users.editorAdmin"> {{ _('Admin') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Abort') }}</button>
|
|
<button class="btn btn-primary" data-bind="click: function() { $root.users.confirmAddUser(); }, enable: !$root.users.editorPasswordMismatch()">{{ _('Confirm') }}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-usersDialogEditUser" class="modal hide fade">
|
|
<div class="modal-header">
|
|
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
|
|
<h3>{{ _('Edit user "%(user)s"', user = '<span data-bind="text: $root.users.editorUsername"></span>') }}</h3>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-usersDialogEditUserActive" data-bind="checked: $root.users.editorActive"> {{ _('Active') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="control-group">
|
|
<div class="controls">
|
|
<label class="checkbox">
|
|
<input type="checkbox" id="settings-usersDialogEditUserAdmin" data-bind="checked: $root.users.editorAdmin"> {{ _('Admin') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Abort') }}</button>
|
|
<button class="btn btn-primary" data-bind="click: function() { $root.users.confirmEditUser(); }">{{ _('Confirm') }}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-usersDialogChangePassword" class="modal hide fade">
|
|
<div class="modal-header">
|
|
<a href="#" class="close" data-dismiss="modal" aria-hidden="true">×</a>
|
|
<h3>{{ _('Change password for user "%(user)s"', user='<span data-bind="text: $root.users.editorUsername"></span>') }}</h3>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form class="form-horizontal">
|
|
<div class="control-group">
|
|
<label class="control-label" for="settings-usersDialogChangePasswordPassword1">{{ _('New Password') }}</label>
|
|
<div class="controls">
|
|
<input type="password" class="input-block-level" id="settings-usersDialogChangePasswordPassword1" data-bind="value: $root.users.editorPassword" required>
|
|
</div>
|
|
</div>
|
|
<div class="control-group" data-bind="css: {error: $root.users.editorPasswordMismatch()}">
|
|
<label class="control-label" for="settings-usersDialogChangePasswordPassword2">{{ _('Repeat Password') }}</label>
|
|
<div class="controls">
|
|
<input type="password" class="input-block-level" id="settings-usersDialogChangePasswordPassword2" data-bind="value: $root.users.editorRepeatedPassword, valueUpdate: 'afterkeydown'" required>
|
|
<span class="help-inline" data-bind="visible: $root.users.editorPasswordMismatch()">{{ _('Passwords do not match') }}</span>
|
|
</div>
|
|
</div>
|
|
<fieldset data-bind="visible: api_enabled">
|
|
<legend>Apikey</legend>
|
|
<div class="control-group">
|
|
<label class="control-label">{{ _('Current API Key') }}</label>
|
|
<div class="controls">
|
|
<div class="input-append">
|
|
<input type="text" class="input-block-level uneditable-input" data-bind="value: $root.users.editorApikey, valueUpdate: 'input', attr: {placeholder: '{{ _('N/A') }}'}">
|
|
<a class="btn" title="Generate new Apikey" data-bind="click: function() { $root.users.confirmGenerateApikey(); }"><i class="icon-refresh"></i></a>
|
|
<a class="btn btn-danger" title="Delete Apikey" data-bind="click: function() { $root.users.confirmDeleteApikey(); }"><i class="icon-trash"></i></a>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<!-- TODO Figure out issue where text isn't properly bound and hence the QR code is worthless
|
|
<div class="control-group">
|
|
<label class="control-label">{{ _('QR Code') }}</label>
|
|
<div class="controls">
|
|
<div data-bind="qrcode: {text: $root.users.editorApiKey, size: 150}"></div>
|
|
</div>
|
|
</div>
|
|
-->
|
|
</fieldset>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Abort') }}</button>
|
|
<button class="btn btn-primary" data-bind="click: function() { $root.users.confirmChangePassword(); }, enable: !$root.users.editorPasswordMismatch()">{{ _('Confirm') }}</button>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% for plugin_name, vars in settingsPlugins.items() %}
|
|
<div class="tab-pane" id="settings_plugin_{{ plugin_name }}" data-bind="allowBindings: false">
|
|
{% include plugin_name+"_settings_dialog.jinja2" ignore missing %}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="tab-pane" id="settings_logs" data-bind="allowBindings: false">
|
|
<div id="logs">
|
|
<h1>{{ _('Logs') }}</h1>
|
|
|
|
<div class="pull-right">
|
|
<small>
|
|
{{ _('Sort by') }}: <a href="#" data-bind="click: function() { listHelper.changeSorting('name'); }">{{ _('Name') }} ({{ _('ascending') }})</a> | <a href="#" data-bind="click: function() { listHelper.changeSorting('modification'); }">{{ _('Modification date') }} ({{ _('descending') }})</a> | <a href="#" data-bind="click: function() { listHelper.changeSorting('size'); }">{{ _('Size') }} ({{ _('descending') }})</a>
|
|
</small>
|
|
</div>
|
|
<table class="table table-striped table-hover table-condensed table-hover" id="log_files">
|
|
<thead>
|
|
<tr>
|
|
<th class="settings_logs_name">{{ _('Name') }}</th>
|
|
<th class="settings_logs_size">{{ _('Size') }}</th>
|
|
<th class="settings_logs_date">{{ _('Date') }}</th>
|
|
<th class="settings_logs_action">{{ _('Action') }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody data-bind="foreach: listHelper.paginatedItems">
|
|
<tr data-bind="attr: {title: name}">
|
|
<td class="settings_logs_name" data-bind="text: name"></td>
|
|
<td class="settings_logs_size" data-bind="text: formatSize(size)"></td>
|
|
<td class="settings_logs_date" data-bind="text: formatDate(date)"></td>
|
|
<td class="settings_logs_action">
|
|
<a href="#" class="icon-trash" data-bind="click: function() { if ($root.loginState.isUser()) { $parent.removeFile($data.name); } else { return; } }, css: {disabled: !$root.loginState.isUser()}"></a> | <a href="#" class="icon-download" data-bind="attr: {href: refs.download}"></a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<div class="pagination pagination-mini pagination-centered">
|
|
<ul>
|
|
<li data-bind="css: {disabled: listHelper.currentPage() === 0}">
|
|
<a href="#" data-bind="click: listHelper.prevPage">«</a>
|
|
</li>
|
|
</ul>
|
|
<ul data-bind="foreach: listHelper.pages">
|
|
<li data-bind="css: { active: $data.number === $root.listHelper.currentPage(), disabled: $data.number === -1 }">
|
|
<a href="#" data-bind="text: $data.text, click: function() { $root.listHelper.changePage($data.number); }"></a>
|
|
</li>
|
|
</ul>
|
|
<ul>
|
|
<li data-bind="css: {disabled: listHelper.currentPage() === listHelper.lastPage()}">
|
|
<a href="#" data-bind="click: listHelper.nextPage">»</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button class="btn" data-dismiss="modal" aria-hidden="true">{{ _('Cancel') }}</button>
|
|
<button class="btn btn-primary" data-bind="click: saveData">{{ _('Save') }}</button>
|
|
</div>
|
|
</div>
|