Skip to content

Commit

Permalink
Receive only tree selector for ignore patterns
Browse files Browse the repository at this point in the history
  • Loading branch information
p0l0us committed Sep 26, 2023
1 parent 8619a03 commit 3e73d13
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 22 deletions.
10 changes: 10 additions & 0 deletions gui/default/assets/css/tree.css
Expand Up @@ -10,6 +10,11 @@
.fancytree-container {
cursor: pointer;
width: 100%;
list-style-type: none;
}

.fancytree-container ul {
list-style-type: none;
}

.fancytree-hide {
Expand All @@ -33,10 +38,15 @@
.fancytree-expander,
.fancytree-icon {
margin-top: 4px;
margin-left: 10px;
vertical-align: top;
width: 16px;
}

.fancytree-helper-indeterminate-cb:before {
content: "\f14a";
}

.fancytree-childcounter {
background: #777;
border-radius: 10px;
Expand Down
109 changes: 109 additions & 0 deletions gui/default/syncthing/core/syncthingController.js
Expand Up @@ -62,6 +62,10 @@ angular.module('syncthing.core')
defaultLines: [],
saved: false,
};
$scope.folderGlobalItems = {
data: [],
error: null,
};
resetRemoteNeed();

try {
Expand Down Expand Up @@ -2099,6 +2103,8 @@ angular.module('syncthing.core')
window.location.hash = "";
$scope.currentFolder = {};
$scope.ignores = {};
$scope.folderGlobalItems = {};
destroyFolderGlobalTree();
});
});
showModal('#editFolder');
Expand Down Expand Up @@ -2198,6 +2204,7 @@ angular.module('syncthing.core')
$scope.currentFolder = angular.copy(folderCfg);
$scope.currentFolder._editing = "existing";
editFolderLoadIgnores();
editFolderLoadFolderGlobalItems();
editFolder(initialTab);
};

Expand Down Expand Up @@ -2227,6 +2234,108 @@ angular.module('syncthing.core')
}, $scope.emitHTTPError);
}

function editFolderLoadingFolderGlobalItems() {
$scope.folderGlobalItems.data = [];
$scope.folderGlobalItems.error = null;
}
function editFolderGetFolderGlobalItems() {
return $http.get(urlbase + '/db/browse?folder=' + encodeURIComponent($scope.currentFolder.id))
.then(function (r) {
return r.data;
}, function (response) {
$scope.folderGlobalItems.error = $translate.instant("Failed to load folder global tree.");
return $q.reject(response);
});
}

function editFolderLoadFolderGlobalItems() {
editFolderLoadingFolderGlobalItems();
return editFolderGetFolderGlobalItems().then(function (data) {
if (!data) {
return;
}
editFolderInitFolderGlobalItems(data, data.error);
}, $scope.emitHTTPError);
}

function editFolderInitFolderGlobalItems(data, error) {
setFolderGlobalItemsData(data);
$scope.folderGlobalItems.error = error;
}

function setFolderGlobalItemsData(data) {
$scope.folderGlobalItems.data = data || [];
}

$scope.setIgnoresGlobalTree = function (value) {
console.log("setIgnoreGlobalTree | value: ", value, $scope.currentFolder.ignoresGlobalTree);

if ($scope.currentFolder.ignoresGlobalTree)
initFolderGlobalTree();
else
destroyFolderGlobalTree();
}

function initFolderGlobalTree() {
const formatGlobalTreeNodes = function (data, parentKey, parentIgnored = true) {
console.log("initFolderGlobalTree", "data", data);
var result = [];
var ignores = ignoresArray();
ignores = ignores[ignores.length - 1] == "**" ? ignores.slice(0, -1) : ignores;
$.each(data, function (index, node) {
const isFolder = node.type == "FILE_INFO_TYPE_DIRECTORY";
const key = parentKey + "/" + node.name;
const found = ignores.find(function (ignoreKey) {
return key == ignoreKey.slice(1);
});
const ignored = parentIgnored && !found;
console.log("initFolderGlobalTree", "key", key, "ignored ", ignored, "parentIgnored", parentIgnored, "found", found, !found, "isFolder", isFolder, "node.children", node.children);
result.push({
children: isFolder && node.children?.length > 0 ? formatGlobalTreeNodes(node.children, key, ignored) : [],
key: key,
title: node.name,
folder: isFolder,
selected: !ignored
});
});
return result;
}

$scope.folderGlobalTree = $("#folderGlobalTree").fancytree({
extensions: ["glyph"],
glyph: {
preset: "awesome5",
},
checkbox: true,
checkboxAutoHide: true,
quicksearch: true,
selectMode: 3,
debugLevel: 1,
select: function (event, data) {
console.log("const rootNode = $scope.folderGlobalTree.getRootNode();");
const rootNode = $scope.folderGlobalTree.getRootNode();
const generatedIgnorePatterns = ["**"];
$.each(rootNode.getSelectedNodes(), function (_, node) {
if (node.parent == rootNode || !node.parent.selected)
generatedIgnorePatterns.unshift("!" + node.key);
});
setIgnoresText(generatedIgnorePatterns);
$scope.$apply();
},
source: function () {
return formatGlobalTreeNodes($scope.folderGlobalItems.data, "");
}
}).fancytree("getTree");
}

function destroyFolderGlobalTree() {
console.log('destroyFolderGlobalTree', $scope.folderGlobalTree);
if ($scope.folderGlobalTree) {
$scope.folderGlobalTree.destroy();
$scope.folderGlobalTree = null;
}
}

$scope.editFolderDefaults = function() {
$q.all([
$http.get(urlbase + '/config/defaults/folder').then(function (response) {
Expand Down
55 changes: 33 additions & 22 deletions gui/default/syncthing/folder/editFolderModalView.html
Expand Up @@ -165,29 +165,40 @@
<p translate class="help-block">Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.</p>
</div>
<div ng-switch-default>
<p translate>Enter ignore patterns, one per line.</p>
<div ng-class="{'has-error': ignores.error != null}">
<textarea class="form-control" name="ignoresText" rows="5" ng-model="ignores.text" ng-disabled="ignores.disabled"></textarea>
<p class="help-block" ng-if="ignores.error">
{{ignores.error}}
</p>
<div ng-if="currentFolder.type == 'receiveonly'">
<input type="checkbox" ng-model="currentFolder.ignoresGlobalTree" ng-change="setIgnoresGlobalTree()" ng-disabled="ignores.disabled">&nbsp;<span translate>Use tree selector</span>
<hr ng-if="currentFolder.ignoresGlobalTree"/>
<p ng-if="currentFolder.ignoresGlobalTree" translate>Select files to download.</p>
<div ng-show="currentFolder.ignoresGlobalTree" ng-disabled="ignores.disabled">
<div id="folderGlobalTree"></div>
</div>
<hr/>
</div>
<div>
<p ng-if="!currentFolder.ignoresGlobalTree" translate>Enter ignore patterns, one per line.</p>
<div ng-class="{'has-error': ignores.error != null}">
<textarea class="form-control" name="ignoresText" rows="5" ng-model="ignores.text" ng-readonly="currentFolder.ignoresGlobalTree" ng-disabled="ignores.disabled"></textarea>
<p class="help-block" ng-if="ignores.error">
{{ignores.error}}
</p>
</div>
<hr />
<p class="small"><span translate>Quick guide to supported patterns</span> (<a href="{{docsURL('users/ignoring')}}" target="_blank" translate>full documentation</a>):</p>
<dl class="dl-horizontal dl-narrow small">
<dt><code>(?d)</code></dt>
<dd><b><span translate>Prefix indicating that the file can be deleted if preventing directory removal</span></b></dd>
<dt><code>(?i)</code></dt>
<dd><span translate>Prefix indicating that the pattern should be matched without case sensitivity</span></dd>
<dt><code>!</code></dt>
<dd><span translate>Inversion of the given condition (i.e. do not exclude)</span></dd>
<dt><code>*</code></dt>
<dd><span translate>Single level wildcard (matches within a directory only)</span></dd>
<dt><code>**</code></dt>
<dd><span translate>Multi level wildcard (matches multiple directory levels)</span></dd>
<dt><code>//</code></dt>
<dd><span translate>Comment, when used at the start of a line</span></dd>
</dl>
</div>
<hr />
<p class="small"><span translate>Quick guide to supported patterns</span> (<a href="{{docsURL('users/ignoring')}}" target="_blank" translate>full documentation</a>):</p>
<dl class="dl-horizontal dl-narrow small">
<dt><code>(?d)</code></dt>
<dd><b><span translate>Prefix indicating that the file can be deleted if preventing directory removal</span></b></dd>
<dt><code>(?i)</code></dt>
<dd><span translate>Prefix indicating that the pattern should be matched without case sensitivity</span></dd>
<dt><code>!</code></dt>
<dd><span translate>Inversion of the given condition (i.e. do not exclude)</span></dd>
<dt><code>*</code></dt>
<dd><span translate>Single level wildcard (matches within a directory only)</span></dd>
<dt><code>**</code></dt>
<dd><span translate>Multi level wildcard (matches multiple directory levels)</span></dd>
<dt><code>//</code></dt>
<dd><span translate>Comment, when used at the start of a line</span></dd>
</dl>
<div ng-if="!editingFolderDefaults()">
<hr />
<span translate translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Editing {%path%}.</span>
Expand Down

0 comments on commit 3e73d13

Please sign in to comment.