Adds a very simple way to group up folders to help with organising from the GUI. Signed-off-by: Ben Norcombe <bennorcombe@pm.me>
This commit is contained in:
+18
-8
@@ -381,9 +381,13 @@
|
||||
|
||||
<div class="col-md-6" aria-labelledby="folder_list" role="region" >
|
||||
<h3 id="folder_list"><span translate>Folders</span><span ng-if="folderList().length > 1"> ({{folderList().length}})</span></h3>
|
||||
<div class="panel-group" id="folders">
|
||||
<div class="panel panel-default" ng-repeat="folder in folderList()">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#folders" data-target="#folder-{{$index}}" aria-expanded="false">
|
||||
<div ng-repeat="(folderGroupName, groupedFolders) in foldersGrouped">
|
||||
<h4 ng-if="folderGroupName !== ''">{{ folderGroupName }}
|
||||
<span ng-if="groupedFolders.length > 1 && folderGroupName.length > 0"> ({{groupedFolders.length}})</span>
|
||||
</h4>
|
||||
<div class="panel-group" id="folders-{{ $index }}">
|
||||
<div class="panel panel-default" ng-repeat="folder in groupedFolders">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#folders-{{$index}}" data-target="#folder-{{$parent.$index}}-{{$index}}" aria-expanded="false">
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'syncing'" ng-attr-style="width: {{syncPercentage(folder.id) | percent}}"></div>
|
||||
<div class="panel-progress" ng-show="folderStatus(folder) == 'scanning' && scanProgress[folder.id] != undefined" ng-attr-style="width: {{scanPercentage(folder.id) | percent}}"></div>
|
||||
<h4 class="panel-title">
|
||||
@@ -406,7 +410,7 @@
|
||||
</div>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="folder-{{$index}}" class="panel-collapse collapse">
|
||||
<div id="folder-{{$parent.$index}}-{{$index}}" class="panel-collapse collapse">
|
||||
<div class="panel-body less-padding">
|
||||
<table class="table table-condensed table-striped table-auto">
|
||||
<tbody>
|
||||
@@ -643,6 +647,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllFoldersPause(true)" ng-if="isAtleastOneFolderPausedStateSetTo(false)">
|
||||
<span class="fas fa-pause"></span> <span translate>Pause All</span>
|
||||
@@ -770,9 +775,13 @@
|
||||
|
||||
<!-- Remote devices -->
|
||||
<h3><span translate>Remote Devices</span> <span ng-if="otherDevices().length > 1"> ({{otherDevices().length}})</span></h3>
|
||||
<div class="panel-group" id="devices">
|
||||
<div class="panel panel-default" ng-repeat="deviceCfg in otherDevices()">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#devices" data-target="#device-{{$index}}" aria-expanded="false">
|
||||
<div ng-repeat="(deviceGroupName, groupedDevices) in devicesGrouped">
|
||||
<h4>{{ deviceGroupName }}
|
||||
<span ng-if="groupedDevices.length > 1 && deviceGroupName.length > 0"> ({{groupedDevices.length}})</span>
|
||||
</h4>
|
||||
<div class="panel-group" id="devices-{{ $index }}">
|
||||
<div class="panel panel-default" ng-repeat="deviceCfg in groupedDevices">
|
||||
<button class="btn panel-heading" data-toggle="collapse" data-parent="#devices-{{ $parent.$index }}" data-target="#device-{{$parent.$index}}-{{$index}}" aria-expanded="false">
|
||||
<div class="panel-progress" ng-show="deviceStatus(deviceCfg) == 'syncing'" ng-attr-style="width: {{completion[deviceCfg.deviceID]._total | percent}}"></div>
|
||||
<h4 class="panel-title">
|
||||
<identicon class="panel-icon" data-value="deviceCfg.deviceID"></identicon>
|
||||
@@ -789,7 +798,7 @@
|
||||
<div class="panel-title-text">{{deviceName(deviceCfg)}}</div>
|
||||
</h4>
|
||||
</button>
|
||||
<div id="device-{{$index}}" class="panel-collapse collapse">
|
||||
<div id="device-{{$parent.$index}}-{{$index}}" class="panel-collapse collapse">
|
||||
<div class="panel-body less-padding">
|
||||
<table class="table table-condensed table-striped table-auto">
|
||||
<tbody>
|
||||
@@ -979,6 +988,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAllDevicesPause(true)" ng-if="isAtleastOneDevicePausedStateSetTo(false)">
|
||||
|
||||
@@ -81,12 +81,14 @@ angular.module('syncthing.core')
|
||||
$scope.model = {};
|
||||
$scope.myID = '';
|
||||
$scope.devices = {};
|
||||
$scope.devicesGrouped = {};
|
||||
$scope.discoveryCache = {};
|
||||
$scope.protocolChanged = false;
|
||||
$scope.reportData = {};
|
||||
$scope.reportDataPreview = '';
|
||||
$scope.reportPreview = false;
|
||||
$scope.folders = {};
|
||||
$scope.foldersGrouped = {};
|
||||
$scope.seenError = '';
|
||||
$scope.upgradeInfo = null;
|
||||
$scope.deviceStats = {};
|
||||
@@ -559,21 +561,44 @@ angular.module('syncthing.core')
|
||||
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
||||
|
||||
$scope.devices = deviceMap($scope.config.devices);
|
||||
$scope.devicesGrouped = {};
|
||||
for (var id in $scope.devices) {
|
||||
$scope.completion[id] = {
|
||||
_total: 100,
|
||||
_needBytes: 0,
|
||||
_needItems: 0
|
||||
};
|
||||
|
||||
if ($scope.devicesGrouped[$scope.devices[id].group] === undefined) {
|
||||
$scope.devicesGrouped[$scope.devices[id].group] = [];
|
||||
}
|
||||
$scope.devicesGrouped[$scope.devices[id].group].push($scope.devices[id]);
|
||||
};
|
||||
|
||||
$scope.folders = folderMap($scope.config.folders);
|
||||
$scope.foldersGrouped = {};
|
||||
Object.keys($scope.folders).forEach(function (folder) {
|
||||
refreshFolder(folder);
|
||||
$scope.folders[folder].devices.forEach(function (deviceCfg) {
|
||||
refreshCompletion(deviceCfg.deviceID, folder);
|
||||
});
|
||||
|
||||
if ($scope.foldersGrouped[$scope.folders[folder].group] === undefined) {
|
||||
$scope.foldersGrouped[$scope.folders[folder].group] = [];
|
||||
}
|
||||
$scope.foldersGrouped[$scope.folders[folder].group].push($scope.folders[folder]);
|
||||
});
|
||||
|
||||
// Sort with blank group first if any then alphabetically
|
||||
const blankSort = (a, b) => {
|
||||
if (a[0] === "" && b[0] !== "") return -1;
|
||||
if (b[0] === "" && a[0] !== "") return 1;
|
||||
return a[0].localeCompare(b[0]);
|
||||
};
|
||||
|
||||
$scope.foldersGrouped = Object.fromEntries(Object.entries($scope.foldersGrouped).sort(blankSort));
|
||||
$scope.devicesGrouped = Object.fromEntries(Object.entries($scope.devicesGrouped).sort(blankSort));
|
||||
|
||||
refreshNoAuthWarning();
|
||||
setDefaultTheme();
|
||||
|
||||
|
||||
@@ -57,6 +57,16 @@
|
||||
<p translate ng-if="currentDevice.deviceID == myID" class="help-block">Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.</p>
|
||||
<p translate ng-if="currentDevice.deviceID != myID" class="help-block">Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.</p>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': deviceEditor.deviceGroup.$invalid && deviceEditor.deviceGroup.$dirty && !editingDeviceDefaults()}">
|
||||
<label for="deviceGroup"><span translate>Device Group</span></label>
|
||||
<input name="deviceGroup" id="deviceGroup" class="form-control" type="text" ng-model="currentDevice.group" value="{{currentDevice.group}}" list="device-group-list"/>
|
||||
<datalist id="device-group-list">
|
||||
<option ng-repeat="(group, device) in devicesGrouped" value="{{group}}" />
|
||||
</datalist>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="deviceEditor.deviceGroup.$valid || deviceEditor.deviceGroup.$pristine">Optional group for the device. Can be different on each device.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="!editingDeviceDefaults()" id="device-sharing" class="tab-pane">
|
||||
<div class="row">
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
<span translate ng-if="folderEditor.folderLabel.$valid || folderEditor.folderLabel.$pristine">Optional descriptive label for the folder. Can be different on each device.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group" ng-class="{'has-error': folderEditor.folderGroup.$invalid && folderEditor.folderGroup.$dirty && !editingFolderDefaults()}">
|
||||
<label for="folderGroup"><span translate>Folder Group</span></label>
|
||||
<input name="folderGroup" id="folderGroup" class="form-control" type="text" ng-model="currentFolder.group" value="{{currentFolder.group}}" list="folder-group-list"/>
|
||||
<datalist id="folder-group-list">
|
||||
<option ng-repeat="(group, folders) in foldersGrouped" value="{{group}}" />
|
||||
</datalist>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.folderGroup.$valid || folderEditor.folderGroup.$pristine">Optional group for the folder. Can be different on each device.</span>
|
||||
</p>
|
||||
</div>
|
||||
<div ng-if="!editingFolderDefaults()" class="form-group" ng-class="{'has-error': folderEditor.folderID.$invalid && folderEditor.folderID.$dirty}">
|
||||
<label for="folderID"><span translate>Folder ID</span></label>
|
||||
<input name="folderID" ng-readonly="has(['existing', 'new-pending'], currentFolder._editing)" id="folderID" class="form-control" type="text" ng-model="currentFolder.id" required="" aria-required="true" unique-folder value="{{currentFolder.id}}" />
|
||||
|
||||
@@ -36,6 +36,7 @@ type DeviceConfiguration struct {
|
||||
Untrusted bool `json:"untrusted" xml:"untrusted"`
|
||||
RemoteGUIPort int `json:"remoteGUIPort" xml:"remoteGUIPort"`
|
||||
RawNumConnections int `json:"numConnections" xml:"numConnections"`
|
||||
Group string `json:"group" xml:"group,attr,omitempty"`
|
||||
}
|
||||
|
||||
func (cfg DeviceConfiguration) Copy() DeviceConfiguration {
|
||||
|
||||
@@ -54,6 +54,7 @@ type FolderConfiguration struct {
|
||||
Path string `json:"path" xml:"path,attr"`
|
||||
Type FolderType `json:"type" xml:"type,attr"`
|
||||
Devices []FolderDeviceConfiguration `json:"devices" xml:"device"`
|
||||
Group string `json:"group" xml:"group,attr,omitempty" restart:"false"`
|
||||
RescanIntervalS int `json:"rescanIntervalS" xml:"rescanIntervalS,attr" default:"3600"`
|
||||
FSWatcherEnabled bool `json:"fsWatcherEnabled" xml:"fsWatcherEnabled,attr" default:"true"`
|
||||
FSWatcherDelayS float64 `json:"fsWatcherDelayS" xml:"fsWatcherDelayS,attr" default:"10"`
|
||||
|
||||
Reference in New Issue
Block a user