This adds booleans to the /system/version response to advice the GUI whether the running version is a candidate release or not. (We could parse it from the version string, but why duplicate the logic.) Additionally the settings dialog locks down the upgrade and usage reporting options on candidate releases. This matches the current behavior, it just makes it obvious what actually *can* be chosen.
336 lines
17 KiB
HTML
336 lines
17 KiB
HTML
<modal id="settings" status="default" icon="fas fa-cog" heading="{{'Settings' | translate}}" large="yes" closeable="yes">
|
|
<div class="modal-body">
|
|
<form role="form" name="settingsEditor">
|
|
<ul class="nav nav-tabs">
|
|
<li class="active"><a data-toggle="tab" href="#settings-general"><span class="fas fa-cog"></span> <span translate>General</span></a></li>
|
|
<li><a data-toggle="tab" href="#settings-gui"><span class="fas fa-desktop"></span> <span translate>GUI</span></a></li>
|
|
<li><a data-toggle="tab" href="#settings-connections"><span class="fas fa-sitemap"></span> <span translate>Connections</span></a></li>
|
|
<li>
|
|
<a data-toggle="tab" href="#settings-ignored-devices">
|
|
<span class="fas fa-laptop"></span>
|
|
|
|
<span translate>Ignored Devices</span>
|
|
|
|
<span class="badge">{{ tmpRemoteIgnoredDevices.length }}</span>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a data-toggle="tab" href="#settings-ignored-folders">
|
|
<span class="fas fa-folder"></span>
|
|
|
|
<span translate>Ignored Folders</span>
|
|
|
|
<span class="badge">{{ ignoredFoldersCountTmpConfig() }}</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
<div class="tab-content">
|
|
<div id="settings-general" class="tab-pane in active">
|
|
<div class="form-group">
|
|
<label translate for="DeviceName">Device Name</label>
|
|
<input id="DeviceName" class="form-control" type="text" ng-model="tmpOptions.deviceName" />
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-horizontal">
|
|
<div class="form-group" ng-class="{'has-error': settingsEditor.minHomeDiskFree.$invalid && settingsEditor.minHomeDiskFree.$dirty}">
|
|
<label class="col-xs-12" for="minHomeDiskFree"><span translate>Minimum Free Disk Space</span></label><br />
|
|
<div class="col-xs-9"><input name="minHomeDiskFree" id="minHomeDiskFree" class="form-control" type="number" ng-model="tmpOptions.minHomeDiskFree.value" required="" aria-required="true" min="0" step="0.01" /></div>
|
|
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="tmpOptions.minHomeDiskFree.unit">
|
|
<option value="%">%</option>
|
|
<option value="kB">kB</option>
|
|
<option value="MB">MB</option>
|
|
<option value="GB">GB</option>
|
|
<option value="TB">TB</option>
|
|
</select></div>
|
|
<p class="col-xs-12 help-block">
|
|
<span translate ng-show="settingsEditor.minHomeDiskFree.$invalid">Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
|
|
<span translate ng-hide="settingsEditor.minHomeDiskFree.$invalid">This setting controls the free space required on the home (i.e., index database) disk.</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate>API Key</label>
|
|
<div class="input-group">
|
|
<input type="text" readonly class="text-monospace form-control" value="{{tmpGUI.apiKey || '-'}}" />
|
|
<span class="input-group-btn">
|
|
<button type="button" class="btn btn-default btn-secondary" ng-click="setAPIKey(tmpGUI)">
|
|
<span class="fas fa-redo"></span> <span translate>Generate</span>
|
|
</button>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate for="urVersion">Anonymous Usage Reporting</label> (<a href="" translate data-toggle="modal" data-target="#urPreview">Preview</a>)
|
|
<div ng-if="tmpOptions.upgrades != 'candidate' && !version.isCandidate">
|
|
<select class="form-control" id="urVersion" ng-model="tmpOptions._urAcceptedStr">
|
|
<option ng-repeat="n in urVersions()" value="{{n}}">{{'Version' | translate}} {{n}}</option>
|
|
<!-- 1 does not exist, as we did not support incremental formats back then. -->
|
|
<option value="0" translate>Undecided (will prompt)</option>
|
|
<option value="-1" translate>Disabled</option>
|
|
</select>
|
|
</div>
|
|
<p class="help-block" ng-if="tmpOptions.upgrades == 'candidate' || version.isCandidate"">
|
|
<span translate>Usage reporting is always enabled for candidate releases.</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate>Automatic upgrades</label> <a href="https://docs.syncthing.net/users/releases.html" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a>
|
|
<select class="form-control" ng-model="tmpOptions.upgrades" ng-if="upgradeInfo">
|
|
<option ng-if="!version.isCandidate" value="none" translate>No upgrades</option>
|
|
<option value="stable" translate>Stable releases only</option>
|
|
<option value="candidate" translate>Stable releases and release candidates</option>
|
|
</select>
|
|
<p class="help-block" ng-if="!upgradeInfo">
|
|
<span translate>Unavailable/Disabled by administrator or maintainer</span>
|
|
</p>
|
|
<p class="help-block" ng-if="version.isCandidate"">
|
|
<span translate>Automatic upgrades are always enabled for candidate releases.</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label translate for="urVersion">Default Folder Path</label>
|
|
<input id="DefaultFolderPath" class="form-control" type="text" ng-model="tmpOptions.defaultFolderPath" />
|
|
<p class="help-block">
|
|
<span translate translate-value-tilde="{{system.tilde}}">
|
|
Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-gui" class="tab-pane">
|
|
<div class="form-group" ng-class="{'has-error': settingsEditor.Address.$invalid && settingsEditor.Address.$dirty}">
|
|
<label translate for="Address">GUI Listen Address</label> <a href="https://docs.syncthing.net/users/guilisten.html" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a>
|
|
<p class="text-warning" ng-show="system.guiAddressOverridden">
|
|
<span class="fas fa-exclamation-triangle"></span>
|
|
<span translate>The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.</span>
|
|
</p>
|
|
<input id="Address" name="Address" class="form-control" type="text" ng-model="tmpGUI.address" ng-pattern="/^(/.*)|(.*:0*((102[4-9])|(10[3-9][0-9])|(1[1-9][0-9][0-9])|([2-9][0-9][0-9][0-9])|([1-6]\d{4})))$/" />
|
|
<p class="help-block" ng-show="settingsEditor.Address.$invalid" translate>
|
|
Enter a non-privileged port number (1024 - 65535).
|
|
</p>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate for="User">GUI Authentication User</label>
|
|
<input id="User" class="form-control" type="text" ng-model="tmpGUI.user" />
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate for="Password">GUI Authentication Password</label>
|
|
<input id="Password" class="form-control" type="password" ng-model="tmpGUI.password" ng-trim="false" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="UseTLS" type="checkbox" ng-model="tmpGUI.useTLS" /> <span translate>Use HTTPS for GUI</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="StartBrowser" type="checkbox" ng-model="tmpOptions.startBrowser" /> <span translate>Start Browser</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate>GUI Theme</label>
|
|
<select class="form-control" ng-model="tmpGUI.theme" ng-if="themes.length > 1">
|
|
<option ng-repeat="theme in themes.sort()" value="{{ theme }}">
|
|
{{ themeName(theme) }}
|
|
</option>
|
|
</select>
|
|
<p class="help-block" ng-if="themes.length < 2">
|
|
<span translate>Unavailable</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-connections" class="tab-pane">
|
|
<div class="form-group">
|
|
<label translate for="ListenAddressesStr">Sync Protocol Listen Addresses</label> <a href="https://docs.syncthing.net/users/config.html#listen-addresses" target="_blank"><span class="fas fa-question-circle"></span> <span translate>Help</span></a>
|
|
<input id="ListenAddressesStr" class="form-control" type="text" ng-model="tmpOptions._listenAddressesStr" />
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxRecvKbps.$invalid && settingsEditor.MaxRecvKbps.$dirty}">
|
|
<label translate for="MaxRecvKbps">Incoming Rate Limit (KiB/s)</label>
|
|
<input id="MaxRecvKbps" name="MaxRecvKbps" class="form-control" type="number" ng-model="tmpOptions.maxRecvKbps" min="0" />
|
|
<p class="help-block">
|
|
<span translate ng-if="settingsEditor.MaxRecvKbps.$error.min && settingsEditor.MaxRecvKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxSendKbps.$invalid && settingsEditor.MaxSendKbps.$dirty}">
|
|
<label translate for="MaxSendKbps">Outgoing Rate Limit (KiB/s)</label>
|
|
<input id="MaxSendKbps" name="MaxSendKbps" class="form-control" type="number" ng-model="tmpOptions.maxSendKbps" min="0" />
|
|
<p class="help-block">
|
|
<span translate ng-if="settingsEditor.MaxSendKbps.$error.min && settingsEditor.MaxSendKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="NATEnabled" type="checkbox" ng-model="tmpOptions.natEnabled" /> <span translate>Enable NAT traversal</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="LocalAnnEnabled" type="checkbox" ng-model="tmpOptions.localAnnounceEnabled" /> <span translate>Local Discovery</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="GlobalAnnEnabled" type="checkbox" ng-model="tmpOptions.globalAnnounceEnabled" /> <span translate>Global Discovery</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<div class="checkbox">
|
|
<label>
|
|
<input id="RelaysEnabled" type="checkbox" ng-model="tmpOptions.relaysEnabled" /> <span translate>Enable Relaying</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="form-group">
|
|
<label translate for="GlobalAnnServersStr">Global Discovery Servers</label>
|
|
<input ng-disabled="!tmpOptions.globalAnnounceEnabled" id="GlobalAnnServersStr" class="form-control" type="text" ng-model="tmpOptions._globalAnnounceServersStr" />
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-ignored-devices" class="tab-pane">
|
|
<div class="form-group">
|
|
<span ng-if="tmpRemoteIgnoredDevices.length === 0" translate>You have no ignored devices.</span>
|
|
<div class="table-responsive" ng-if="tmpRemoteIgnoredDevices.length > 0">
|
|
<table class="table-condensed table-striped table" style="table-layout: auto;">
|
|
<thead>
|
|
<tr>
|
|
<th translate>Ignored at</th>
|
|
<th translate>Device</th>
|
|
<th translate>Address</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="ignoredDevice in tmpRemoteIgnoredDevices">
|
|
<td class="no-overflow-ellipse">{{ ignoredDevice.time | date:"yyyy-MM-dd HH:mm:ss" }}</td>
|
|
<td>
|
|
<span ng-if="!ignoredDevice.name">{{ ignoredDevice.deviceID }}</span>
|
|
<span tooltip data-original-title="{{ ignoredDevice.deviceID }}" ng-if="ignoredDevice.name">{{ ignoredDevice.name }}</span>
|
|
</td>
|
|
<td class="no-overflow-ellipse">{{ ignoredDevice.address }}</td>
|
|
<td>
|
|
<a href="" ng-click="unignoreDeviceFromTemporaryConfig(ignoredDevice)">
|
|
<span class="fas fa-times"></span> <span translate>Unignore</span>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="settings-ignored-folders" class="tab-pane">
|
|
<div class="form-group">
|
|
<span ng-if="ignoredFoldersCountTmpConfig() === 0" translate>You have no ignored folders.</span>
|
|
<div class="table-responsive" ng-if="ignoredFoldersCountTmpConfig() > 0">
|
|
<table class="table-condensed table-striped table" style="table-layout: auto;">
|
|
<thead>
|
|
<tr>
|
|
<th translate>Ignored at</th>
|
|
<th translate>Folder</th>
|
|
<th translate>Device</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody ng-repeat-start="device in tmpDevices">
|
|
<tr ng-repeat="ignoredFolder in device.ignoredFolders">
|
|
<td class="no-overflow-ellipse">{{ ignoredFolder.time | date:"yyyy-MM-dd HH:mm:ss" }}</td>
|
|
<td>{{ folderLabel(ignoredFolder.id) }}</td>
|
|
<td>
|
|
<span tooltip data-original-title="{{ device.deviceID }}">{{ friendlyNameFromID(device.deviceID) }}</span>
|
|
</td>
|
|
<td>
|
|
<a href="" ng-click="unignoreFolderFromTemporaryConfig(device.deviceID, ignoredFolder.id)">
|
|
<span class="fas fa-times"></span> <span translate>Unignore</span>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot ng-repeat-end></tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-primary btn-sm" ng-click="saveSettings()">
|
|
<span class="fas fa-check"></span> <span translate>Save</span>
|
|
</button>
|
|
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
|
<span class="fas fa-times"></span> <span translate>Close</span>
|
|
</button>
|
|
</div>
|
|
|
|
</modal>
|