Archived
Merge pull request #1703 from AudriusButkevicius/page
Add pagination to Out of sync item list (fixes #1509)
This commit is contained in:
commit
ff984425a3
7 files changed
+712
-90
No files matched your search
+20
-6
@@ -111,7 +111,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
||||
getRestMux.HandleFunc("/rest/db/completion", withModel(m, restGetDBCompletion)) // device folder
|
||||
getRestMux.HandleFunc("/rest/db/file", withModel(m, restGetDBFile)) // folder file
|
||||
getRestMux.HandleFunc("/rest/db/ignores", withModel(m, restGetDBIgnores)) // folder
|
||||
getRestMux.HandleFunc("/rest/db/need", withModel(m, restGetDBNeed)) // folder
|
||||
getRestMux.HandleFunc("/rest/db/need", withModel(m, restGetDBNeed)) // folder [perpage] [page]
|
||||
getRestMux.HandleFunc("/rest/db/status", withModel(m, restGetDBStatus)) // folder
|
||||
getRestMux.HandleFunc("/rest/db/browse", withModel(m, restGetDBBrowse)) // folder [prefix] [dirsonly] [levels]
|
||||
getRestMux.HandleFunc("/rest/events", restGetEvents) // since [limit]
|
||||
@@ -133,7 +133,7 @@ func startGUI(cfg config.GUIConfiguration, assetDir string, m *model.Model) erro
|
||||
|
||||
// The POST handlers
|
||||
postRestMux := http.NewServeMux()
|
||||
postRestMux.HandleFunc("/rest/db/prio", withModel(m, restPostDBPrio)) // folder file
|
||||
postRestMux.HandleFunc("/rest/db/prio", withModel(m, restPostDBPrio)) // folder file [perpage] [page]
|
||||
postRestMux.HandleFunc("/rest/db/ignores", withModel(m, restPostDBIgnores)) // folder
|
||||
postRestMux.HandleFunc("/rest/db/override", withModel(m, restPostDBOverride)) // folder
|
||||
postRestMux.HandleFunc("/rest/db/scan", withModel(m, restPostDBScan)) // folder [sub...]
|
||||
@@ -379,15 +379,29 @@ func restPostDBOverride(m *model.Model, w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
func restGetDBNeed(m *model.Model, w http.ResponseWriter, r *http.Request) {
|
||||
var qs = r.URL.Query()
|
||||
var folder = qs.Get("folder")
|
||||
qs := r.URL.Query()
|
||||
|
||||
folder := qs.Get("folder")
|
||||
|
||||
page, err := strconv.Atoi(qs.Get("page"))
|
||||
if err != nil || page < 1 {
|
||||
page = 1
|
||||
}
|
||||
perpage, err := strconv.Atoi(qs.Get("perpage"))
|
||||
if err != nil || perpage < 1 {
|
||||
perpage = 1 << 16
|
||||
}
|
||||
|
||||
progress, queued, rest, total := m.NeedFolderFiles(folder, page, perpage)
|
||||
|
||||
progress, queued, rest := m.NeedFolderFiles(folder, 100)
|
||||
// Convert the struct to a more loose structure, and inject the size.
|
||||
output := map[string][]jsonDBFileInfo{
|
||||
output := map[string]interface{}{
|
||||
"progress": toNeedSlice(progress),
|
||||
"queued": toNeedSlice(queued),
|
||||
"rest": toNeedSlice(rest),
|
||||
"total": total,
|
||||
"page": page,
|
||||
"perpage": perpage,
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
|
||||
+26
-17
@@ -967,10 +967,22 @@
|
||||
<hr/>
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<tr ng-repeat="f in needed.progress" ng-init="a = needAction(f)">
|
||||
<td class="small-data"><span class="glyphicon glyphicon-{{needIcons[a]}}"></span> {{needActions[a]}}</td>
|
||||
<td title="{{f.name}}">{{f.name | basename}}</td>
|
||||
<td ng-if="a == 'sync' && progress[neededFolder] && progress[neededFolder][f.name]">
|
||||
|
||||
<tr dir-paginate="f in needed | itemsPerPage: neededPageSize" current-page="neededCurrentPage" total-items="neededTotal">
|
||||
<!-- Icon -->
|
||||
<td class="small-data"><span class="glyphicon glyphicon-{{needIcons[f.action]}}"></span> {{needActions[f.action]}}</td>
|
||||
|
||||
<!-- Name -->
|
||||
<td ng-if="f.type != 'queued'" title="{{f.name}}">{{f.name | basename}}</td>
|
||||
<td ng-if="f.type == 'queued'">
|
||||
<a href="" ng-click="bumpFile(neededFolder, f.name)" title="{{'Move to top of queue' | translate}}">
|
||||
<span class="glyphicon glyphicon-eject"></span>
|
||||
</a>
|
||||
<span title="{{f.name}}"> {{f.name | basename}}</span>
|
||||
</td>
|
||||
|
||||
<!-- Size/Progress -->
|
||||
<td ng-if="f.type == 'progress' && f.action == 'sync' && progress[neededFolder] && progress[neededFolder][f.name]">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: {{progress[neededFolder][f.name].reused}}%"></div>
|
||||
<div class="progress-bar" style="width: {{progress[neededFolder][f.name].copiedFromOrigin}}%"></div>
|
||||
@@ -982,24 +994,20 @@
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-right small-data" ng-if="a != 'sync' || !progress[neededFolder] || !progress[neededFolder][f.name]">
|
||||
<td class="text-right small-data" ng-if="f.type != 'progress' || f.action != 'sync' || !progress[neededFolder] || !progress[neededFolder][f.name]">
|
||||
<span ng-if="f.size > 0">{{f.size | binary}}B</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="f in needed.queued" ng-init="a = needAction(f)">
|
||||
<td class="small-data"><span class="glyphicon glyphicon-{{needIcons[a]}}"></span> {{needActions[a]}}</td>
|
||||
<td><a href="" ng-if="$index != 0" ng-click="bumpFile(neededFolder, f.name)" title="{{'Move to top of queue' | translate}}"><span class="glyphicon glyphicon-eject"></span></a><span ng-if="$index != 0"> </span><span title="{{f.name}}">{{f.name | basename}}</span></td>
|
||||
<td class="text-right small-data">
|
||||
<span ng-if="f.size > 0">{{f.size | binary}}B</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-repeat="f in needed.rest" ng-init="a = needAction(f)">
|
||||
<td class="small-data"><span class="glyphicon glyphicon-{{needIcons[a]}}"></span> {{needActions[a]}}</td>
|
||||
<td title="{{f.name}}">{{f.name | basename}}</td>
|
||||
<td class="text-right small-data"><span ng-if="f.size > 0">{{f.size | binary}}B</span></td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<dir-pagination-controls on-page-change="neededPageChanged(newPageNumber)"></dir-pagination-controls>
|
||||
<ul class="pagination pull-right">
|
||||
<li ng-repeat="option in [10, 20, 30, 50, 100]" ng-class="{ active: neededPageSize == option }">
|
||||
<a href="#" ng-click="neededChangePageSize(option)">{{option}}</a>
|
||||
<li>
|
||||
</ul>
|
||||
<div class="clearfix">
|
||||
</modal>
|
||||
|
||||
<!-- About modal -->
|
||||
@@ -1087,6 +1095,7 @@
|
||||
<script src="vendor/angular/angular.min.js"></script>
|
||||
<script src="vendor/angular/angular-translate.min.js"></script>
|
||||
<script src="vendor/angular/angular-translate-loader.min.js"></script>
|
||||
<script src="vendor/angular/angular-dirPagination.js"></script>
|
||||
<script src="vendor/jquery/jquery-2.0.3.min.js"></script>
|
||||
<script src="vendor/bootstrap/js/bootstrap.min.js"></script>
|
||||
<!-- / vendor scripts -->
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
/*global $: false, angular: false, console: false, validLangs: false */
|
||||
|
||||
var syncthing = angular.module('syncthing', [
|
||||
'angularUtils.directives.dirPagination',
|
||||
'pascalprecht.translate',
|
||||
|
||||
'syncthing.core'
|
||||
|
||||
@@ -40,6 +40,10 @@ angular.module('syncthing.core')
|
||||
$scope.folderStats = {};
|
||||
$scope.progress = {};
|
||||
$scope.version = {};
|
||||
$scope.needed = [];
|
||||
$scope.neededTotal = 0;
|
||||
$scope.neededCurrentPage = 1;
|
||||
$scope.neededPageSize = 10;
|
||||
|
||||
$(window).bind('beforeunload', function () {
|
||||
navigatingAway = true;
|
||||
@@ -415,14 +419,63 @@ angular.module('syncthing.core')
|
||||
}
|
||||
|
||||
function refreshNeed(folder) {
|
||||
$http.get(urlbase + "/db/need?folder=" + encodeURIComponent(folder)).success(function (data) {
|
||||
var url = urlbase + "/db/need?folder=" + encodeURIComponent(folder);
|
||||
url += "&page=" + $scope.neededCurrentPage;
|
||||
url += "&perpage=" + $scope.neededPageSize;
|
||||
$http.get(url).success(function (data) {
|
||||
if ($scope.neededFolder == folder) {
|
||||
console.log("refreshNeed", folder, data);
|
||||
$scope.needed = data;
|
||||
parseNeeded(data);
|
||||
}
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
|
||||
function needAction(file) {
|
||||
var fDelete = 4096;
|
||||
var fDirectory = 16384;
|
||||
|
||||
if ((file.flags & (fDelete + fDirectory)) === fDelete + fDirectory) {
|
||||
return 'rmdir';
|
||||
} else if ((file.flags & fDelete) === fDelete) {
|
||||
return 'rm';
|
||||
} else if ((file.flags & fDirectory) === fDirectory) {
|
||||
return 'touch';
|
||||
} else {
|
||||
return 'sync';
|
||||
}
|
||||
};
|
||||
|
||||
function parseNeeded(data) {
|
||||
var merged = [];
|
||||
data.progress.forEach(function (item) {
|
||||
item.type = "progress";
|
||||
item.action = needAction(item);
|
||||
merged.push(item);
|
||||
});
|
||||
data.queued.forEach(function (item) {
|
||||
item.type = "queued";
|
||||
item.action = needAction(item);
|
||||
merged.push(item);
|
||||
});
|
||||
data.rest.forEach(function (item) {
|
||||
item.type = "rest";
|
||||
item.action = needAction(item);
|
||||
merged.push(item);
|
||||
});
|
||||
$scope.needed = merged;
|
||||
$scope.neededTotal = data.total;
|
||||
}
|
||||
|
||||
$scope.neededPageChanged = function (page) {
|
||||
$scope.neededCurrentPage = page;
|
||||
refreshNeed($scope.neededFolder);
|
||||
};
|
||||
|
||||
$scope.neededChangePageSize = function (perpage) {
|
||||
$scope.neededPageSize = perpage;
|
||||
refreshNeed($scope.neededFolder);
|
||||
}
|
||||
|
||||
var refreshDeviceStats = debounce(function () {
|
||||
$http.get(urlbase + "/stats/device").success(function (data) {
|
||||
$scope.deviceStats = data;
|
||||
@@ -1181,24 +1234,11 @@ angular.module('syncthing.core')
|
||||
$('#needed').modal().on('hidden.bs.modal', function () {
|
||||
$scope.neededFolder = undefined;
|
||||
$scope.needed = undefined;
|
||||
$scope.neededTotal = 0;
|
||||
$scope.neededCurrentPage = 1;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.needAction = function (file) {
|
||||
var fDelete = 4096;
|
||||
var fDirectory = 16384;
|
||||
|
||||
if ((file.flags & (fDelete + fDirectory)) === fDelete + fDirectory) {
|
||||
return 'rmdir';
|
||||
} else if ((file.flags & fDelete) === fDelete) {
|
||||
return 'rm';
|
||||
} else if ((file.flags & fDirectory) === fDirectory) {
|
||||
return 'touch';
|
||||
} else {
|
||||
return 'sync';
|
||||
}
|
||||
};
|
||||
|
||||
$scope.override = function (folder) {
|
||||
$http.post(urlbase + "/db/override?folder=" + encodeURIComponent(folder));
|
||||
};
|
||||
@@ -1220,10 +1260,14 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.bumpFile = function (folder, file) {
|
||||
$http.post(urlbase + "/db/prio?folder=" + encodeURIComponent(folder) + "&file=" + encodeURIComponent(file)).success(function (data) {
|
||||
var url = urlbase + "/db/prio?folder=" + encodeURIComponent(folder) + "&file=" + encodeURIComponent(file);
|
||||
// In order to get the right view of data in the response.
|
||||
url += "&page=" + $scope.neededCurrentPage;
|
||||
url += "&perpage=" + $scope.neededPageSize;
|
||||
$http.post(url).success(function (data) {
|
||||
if ($scope.neededFolder == folder) {
|
||||
console.log("bumpFile", folder, data);
|
||||
$scope.needed = data;
|
||||
parseNeeded(data);
|
||||
}
|
||||
}).error($scope.emitHTTPError);
|
||||
};
|
||||
|
||||
+520
@@ -0,0 +1,520 @@
|
||||
/**
|
||||
* dirPagination - AngularJS module for paginating (almost) anything.
|
||||
*
|
||||
*
|
||||
* Credits
|
||||
* =======
|
||||
*
|
||||
* Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ
|
||||
* for the idea on how to dynamically invoke the ng-repeat directive.
|
||||
*
|
||||
* I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:
|
||||
* https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
|
||||
*
|
||||
* Copyright 2014 Michael Bromley <michael@michaelbromley.co.uk>
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
* Config
|
||||
*/
|
||||
var moduleName = 'angularUtils.directives.dirPagination';
|
||||
var DEFAULT_ID = '__default';
|
||||
|
||||
/**
|
||||
* Module
|
||||
*/
|
||||
var module;
|
||||
try {
|
||||
module = angular.module(moduleName);
|
||||
} catch(err) {
|
||||
// named module does not exist, so create one
|
||||
module = angular.module(moduleName, []);
|
||||
}
|
||||
|
||||
module
|
||||
.directive('dirPaginate', ['$compile', '$parse', 'paginationService', dirPaginateDirective])
|
||||
.directive('dirPaginateNoCompile', noCompileDirective)
|
||||
.directive('dirPaginationControls', ['paginationService', 'paginationTemplate', dirPaginationControlsDirective])
|
||||
.filter('itemsPerPage', ['paginationService', itemsPerPageFilter])
|
||||
.service('paginationService', paginationService)
|
||||
.provider('paginationTemplate', paginationTemplateProvider)
|
||||
.run(['$templateCache',dirPaginationControlsTemplateInstaller]);
|
||||
|
||||
function dirPaginateDirective($compile, $parse, paginationService) {
|
||||
|
||||
return {
|
||||
terminal: true,
|
||||
multiElement: true,
|
||||
compile: dirPaginationCompileFn
|
||||
};
|
||||
|
||||
function dirPaginationCompileFn(tElement, tAttrs){
|
||||
|
||||
var expression = tAttrs.dirPaginate;
|
||||
// regex taken directly from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L211
|
||||
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
|
||||
|
||||
var filterPattern = /\|\s*itemsPerPage\s*:[^|]*/;
|
||||
if (match[2].match(filterPattern) === null) {
|
||||
throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
|
||||
}
|
||||
var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');
|
||||
var collectionGetter = $parse(itemsPerPageFilterRemoved);
|
||||
|
||||
addNoCompileAttributes(tElement);
|
||||
|
||||
// If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any
|
||||
// dir-pagination-controls directives that may be looking for this ID.
|
||||
var rawId = tAttrs.paginationId || DEFAULT_ID;
|
||||
paginationService.registerInstance(rawId);
|
||||
|
||||
return function dirPaginationLinkFn(scope, element, attrs){
|
||||
|
||||
// Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
|
||||
// potentially register a new ID if it evaluates to a different value than the rawId.
|
||||
var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
|
||||
paginationService.registerInstance(paginationId);
|
||||
|
||||
var repeatExpression = getRepeatExpression(expression, paginationId);
|
||||
addNgRepeatToElement(element, attrs, repeatExpression);
|
||||
|
||||
removeTemporaryAttributes(element);
|
||||
var compiled = $compile(element);
|
||||
|
||||
var currentPageGetter = makeCurrentPageGetterFn(scope, attrs, paginationId);
|
||||
paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);
|
||||
|
||||
if (typeof attrs.totalItems !== 'undefined') {
|
||||
paginationService.setAsyncModeTrue(paginationId);
|
||||
scope.$watch(function() {
|
||||
return $parse(attrs.totalItems)(scope);
|
||||
}, function (result) {
|
||||
if (0 <= result) {
|
||||
paginationService.setCollectionLength(paginationId, result);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
scope.$watchCollection(function() {
|
||||
return collectionGetter(scope);
|
||||
}, function(collection) {
|
||||
if (collection) {
|
||||
paginationService.setCollectionLength(paginationId, collection.length);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Delegate to the link function returned by the new compilation of the ng-repeat
|
||||
compiled(scope);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If a pagination id has been specified, we need to check that it is present as the second argument passed to
|
||||
* the itemsPerPage filter. If it is not there, we add it and return the modified expression.
|
||||
*
|
||||
* @param expression
|
||||
* @param paginationId
|
||||
* @returns {*}
|
||||
*/
|
||||
function getRepeatExpression(expression, paginationId) {
|
||||
var repeatExpression,
|
||||
idDefinedInFilter = !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);
|
||||
|
||||
if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
|
||||
repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:[^|]*)/, "$1 : '" + paginationId + "'");
|
||||
} else {
|
||||
repeatExpression = expression;
|
||||
}
|
||||
|
||||
return repeatExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the ng-repeat directive to the element. In the case of multi-element (-start, -end) it adds the
|
||||
* appropriate multi-element ng-repeat to the first and last element in the range.
|
||||
* @param element
|
||||
* @param attrs
|
||||
* @param repeatExpression
|
||||
*/
|
||||
function addNgRepeatToElement(element, attrs, repeatExpression) {
|
||||
if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {
|
||||
// using multiElement mode (dir-paginate-start, dir-paginate-end)
|
||||
attrs.$set('ngRepeatStart', repeatExpression);
|
||||
element.eq(element.length - 1).attr('ng-repeat-end', true);
|
||||
} else {
|
||||
attrs.$set('ngRepeat', repeatExpression);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the dir-paginate-no-compile directive to each element in the tElement range.
|
||||
* @param tElement
|
||||
*/
|
||||
function addNoCompileAttributes(tElement) {
|
||||
angular.forEach(tElement, function(el) {
|
||||
if (el.nodeType === Node.ELEMENT_NODE) {
|
||||
angular.element(el).attr('dir-paginate-no-compile', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the variations on dir-paginate (data-, -start, -end) and the dir-paginate-no-compile directives.
|
||||
* @param element
|
||||
*/
|
||||
function removeTemporaryAttributes(element) {
|
||||
angular.forEach(element, function(el) {
|
||||
if (el.nodeType === Node.ELEMENT_NODE) {
|
||||
angular.element(el).removeAttr('dir-paginate-no-compile');
|
||||
}
|
||||
});
|
||||
element.eq(0).removeAttr('dir-paginate-start').removeAttr('dir-paginate').removeAttr('data-dir-paginate-start').removeAttr('data-dir-paginate');
|
||||
element.eq(element.length - 1).removeAttr('dir-paginate-end').removeAttr('data-dir-paginate-end');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a getter function for the current-page attribute, using the expression provided or a default value if
|
||||
* no current-page expression was specified.
|
||||
*
|
||||
* @param scope
|
||||
* @param attrs
|
||||
* @param paginationId
|
||||
* @returns {*}
|
||||
*/
|
||||
function makeCurrentPageGetterFn(scope, attrs, paginationId) {
|
||||
var currentPageGetter;
|
||||
if (attrs.currentPage) {
|
||||
currentPageGetter = $parse(attrs.currentPage);
|
||||
} else {
|
||||
// if the current-page attribute was not set, we'll make our own
|
||||
var defaultCurrentPage = paginationId + '__currentPage';
|
||||
scope[defaultCurrentPage] = 1;
|
||||
currentPageGetter = $parse(defaultCurrentPage);
|
||||
}
|
||||
return currentPageGetter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a helper directive that allows correct compilation when in multi-element mode (ie dir-paginate-start, dir-paginate-end).
|
||||
* It is dynamically added to all elements in the dir-paginate compile function, and it prevents further compilation of
|
||||
* any inner directives. It is then removed in the link function, and all inner directives are then manually compiled.
|
||||
*/
|
||||
function noCompileDirective() {
|
||||
return {
|
||||
priority: 5000,
|
||||
terminal: true
|
||||
};
|
||||
}
|
||||
|
||||
function dirPaginationControlsTemplateInstaller($templateCache) {
|
||||
$templateCache.put('angularUtils.directives.dirPagination.template', '<ul class="pagination" ng-if="1 < pages.length"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(1)">«</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="" ng-click="setCurrent(pagination.current - 1)">‹</a></li><li ng-repeat="pageNumber in pages track by $index" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' }"><a href="" ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.current + 1)">›</a></li><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="" ng-click="setCurrent(pagination.last)">»</a></li></ul>');
|
||||
}
|
||||
|
||||
function dirPaginationControlsDirective(paginationService, paginationTemplate) {
|
||||
|
||||
var numberRegex = /^\d+$/;
|
||||
|
||||
return {
|
||||
restrict: 'AE',
|
||||
templateUrl: function(elem, attrs) {
|
||||
return attrs.templateUrl || paginationTemplate.getPath();
|
||||
},
|
||||
scope: {
|
||||
maxSize: '=?',
|
||||
onPageChange: '&?',
|
||||
paginationId: '=?'
|
||||
},
|
||||
link: dirPaginationControlsLinkFn
|
||||
};
|
||||
|
||||
function dirPaginationControlsLinkFn(scope, element, attrs) {
|
||||
|
||||
// rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
|
||||
// not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is
|
||||
// no corresponding dir-paginate directive and wrongly throwing an exception.
|
||||
var rawId = attrs.paginationId || DEFAULT_ID;
|
||||
var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;
|
||||
|
||||
if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
|
||||
var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
|
||||
throw 'pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive.';
|
||||
}
|
||||
|
||||
if (!scope.maxSize) { scope.maxSize = 9; }
|
||||
scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
|
||||
scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;
|
||||
|
||||
var paginationRange = Math.max(scope.maxSize, 5);
|
||||
scope.pages = [];
|
||||
scope.pagination = {
|
||||
last: 1,
|
||||
current: 1
|
||||
};
|
||||
scope.range = {
|
||||
lower: 1,
|
||||
upper: 1,
|
||||
total: 1
|
||||
};
|
||||
|
||||
scope.$watch(function() {
|
||||
return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
|
||||
}, function(length) {
|
||||
if (0 < length) {
|
||||
generatePagination();
|
||||
}
|
||||
});
|
||||
|
||||
scope.$watch(function() {
|
||||
return (paginationService.getItemsPerPage(paginationId));
|
||||
}, function(current, previous) {
|
||||
if (current != previous && typeof previous !== 'undefined') {
|
||||
goToPage(scope.pagination.current);
|
||||
}
|
||||
});
|
||||
|
||||
scope.$watch(function() {
|
||||
return paginationService.getCurrentPage(paginationId);
|
||||
}, function(currentPage, previousPage) {
|
||||
if (currentPage != previousPage) {
|
||||
goToPage(currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
scope.setCurrent = function(num) {
|
||||
if (isValidPageNumber(num)) {
|
||||
num = parseInt(num, 10);
|
||||
paginationService.setCurrentPage(paginationId, num);
|
||||
}
|
||||
};
|
||||
|
||||
function goToPage(num) {
|
||||
if (isValidPageNumber(num)) {
|
||||
scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
|
||||
scope.pagination.current = num;
|
||||
updateRangeValues();
|
||||
|
||||
// if a callback has been set, then call it with the page number as an argument
|
||||
if (scope.onPageChange) {
|
||||
scope.onPageChange({ newPageNumber : num });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generatePagination() {
|
||||
var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
|
||||
|
||||
scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
|
||||
scope.pagination.current = page;
|
||||
scope.pagination.last = scope.pages[scope.pages.length - 1];
|
||||
if (scope.pagination.last < scope.pagination.current) {
|
||||
scope.setCurrent(scope.pagination.last);
|
||||
} else {
|
||||
updateRangeValues();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination
|
||||
* template to display the current page range, e.g. "showing 21 - 40 of 144 results";
|
||||
*/
|
||||
function updateRangeValues() {
|
||||
var currentPage = paginationService.getCurrentPage(paginationId),
|
||||
itemsPerPage = paginationService.getItemsPerPage(paginationId),
|
||||
totalItems = paginationService.getCollectionLength(paginationId);
|
||||
|
||||
scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
|
||||
scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
|
||||
scope.range.total = totalItems;
|
||||
}
|
||||
|
||||
function isValidPageNumber(num) {
|
||||
return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array of page numbers (or the '...' string) which is used in an ng-repeat to generate the
|
||||
* links used in pagination
|
||||
*
|
||||
* @param currentPage
|
||||
* @param rowsPerPage
|
||||
* @param paginationRange
|
||||
* @param collectionLength
|
||||
* @returns {Array}
|
||||
*/
|
||||
function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
|
||||
var pages = [];
|
||||
var totalPages = Math.ceil(collectionLength / rowsPerPage);
|
||||
var halfWay = Math.ceil(paginationRange / 2);
|
||||
var position;
|
||||
|
||||
if (currentPage <= halfWay) {
|
||||
position = 'start';
|
||||
} else if (totalPages - halfWay < currentPage) {
|
||||
position = 'end';
|
||||
} else {
|
||||
position = 'middle';
|
||||
}
|
||||
|
||||
var ellipsesNeeded = paginationRange < totalPages;
|
||||
var i = 1;
|
||||
while (i <= totalPages && i <= paginationRange) {
|
||||
var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);
|
||||
|
||||
var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
|
||||
var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
|
||||
if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
|
||||
pages.push('...');
|
||||
} else {
|
||||
pages.push(pageNumber);
|
||||
}
|
||||
i ++;
|
||||
}
|
||||
return pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.
|
||||
*
|
||||
* @param i
|
||||
* @param currentPage
|
||||
* @param paginationRange
|
||||
* @param totalPages
|
||||
* @returns {*}
|
||||
*/
|
||||
function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
|
||||
var halfWay = Math.ceil(paginationRange/2);
|
||||
if (i === paginationRange) {
|
||||
return totalPages;
|
||||
} else if (i === 1) {
|
||||
return i;
|
||||
} else if (paginationRange < totalPages) {
|
||||
if (totalPages - halfWay < currentPage) {
|
||||
return totalPages - paginationRange + i;
|
||||
} else if (halfWay < currentPage) {
|
||||
return currentPage - halfWay + i;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This filter slices the collection into pages based on the current page number and number of items per page.
|
||||
* @param paginationService
|
||||
* @returns {Function}
|
||||
*/
|
||||
function itemsPerPageFilter(paginationService) {
|
||||
|
||||
return function(collection, itemsPerPage, paginationId) {
|
||||
if (typeof (paginationId) === 'undefined') {
|
||||
paginationId = DEFAULT_ID;
|
||||
}
|
||||
if (!paginationService.isRegistered(paginationId)) {
|
||||
throw 'pagination directive: the itemsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';
|
||||
}
|
||||
var end;
|
||||
var start;
|
||||
if (collection instanceof Array) {
|
||||
itemsPerPage = parseInt(itemsPerPage) || 9999999999;
|
||||
if (paginationService.isAsyncMode(paginationId)) {
|
||||
start = 0;
|
||||
} else {
|
||||
start = (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;
|
||||
}
|
||||
end = start + itemsPerPage;
|
||||
paginationService.setItemsPerPage(paginationId, itemsPerPage);
|
||||
|
||||
return collection.slice(start, end);
|
||||
} else {
|
||||
return collection;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This service allows the various parts of the module to communicate and stay in sync.
|
||||
*/
|
||||
function paginationService() {
|
||||
|
||||
var instances = {};
|
||||
var lastRegisteredInstance;
|
||||
|
||||
this.registerInstance = function(instanceId) {
|
||||
if (typeof instances[instanceId] === 'undefined') {
|
||||
instances[instanceId] = {
|
||||
asyncMode: false
|
||||
};
|
||||
lastRegisteredInstance = instanceId;
|
||||
}
|
||||
};
|
||||
|
||||
this.isRegistered = function(instanceId) {
|
||||
return (typeof instances[instanceId] !== 'undefined');
|
||||
};
|
||||
|
||||
this.getLastInstanceId = function() {
|
||||
return lastRegisteredInstance;
|
||||
};
|
||||
|
||||
this.setCurrentPageParser = function(instanceId, val, scope) {
|
||||
instances[instanceId].currentPageParser = val;
|
||||
instances[instanceId].context = scope;
|
||||
};
|
||||
this.setCurrentPage = function(instanceId, val) {
|
||||
instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);
|
||||
};
|
||||
this.getCurrentPage = function(instanceId) {
|
||||
var parser = instances[instanceId].currentPageParser;
|
||||
return parser ? parser(instances[instanceId].context) : 1;
|
||||
};
|
||||
|
||||
this.setItemsPerPage = function(instanceId, val) {
|
||||
instances[instanceId].itemsPerPage = val;
|
||||
};
|
||||
this.getItemsPerPage = function(instanceId) {
|
||||
return instances[instanceId].itemsPerPage;
|
||||
};
|
||||
|
||||
this.setCollectionLength = function(instanceId, val) {
|
||||
instances[instanceId].collectionLength = val;
|
||||
};
|
||||
this.getCollectionLength = function(instanceId) {
|
||||
return instances[instanceId].collectionLength;
|
||||
};
|
||||
|
||||
this.setAsyncModeTrue = function(instanceId) {
|
||||
instances[instanceId].asyncMode = true;
|
||||
};
|
||||
|
||||
this.isAsyncMode = function(instanceId) {
|
||||
return instances[instanceId].asyncMode;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This provider allows global configuration of the template path used by the dir-pagination-controls directive.
|
||||
*/
|
||||
function paginationTemplateProvider() {
|
||||
|
||||
var templatePath = 'angularUtils.directives.dirPagination.template';
|
||||
|
||||
this.setPath = function(path) {
|
||||
templatePath = path;
|
||||
};
|
||||
|
||||
this.$get = function() {
|
||||
return {
|
||||
getPath: function() {
|
||||
return templatePath;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
})();
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
AssetsBuildDate = "Sat, 25 Apr 2015 06:53:34 GMT"
|
||||
AssetsBuildDate = "Sat, 25 Apr 2015 21:53:52 GMT"
|
||||
)
|
||||
|
||||
func Assets() map[string][]byte {
|
||||
var assets = make(map[string][]byte, 61)
|
||||
var assets = make(map[string][]byte, 62)
|
||||
|
||||
assets["assets/css/overrides.css"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5xXXW/buBJ996+Ym+ICra8lf8ROWgc32CLAYhdoi2Lbl0XRB0qkLW4oUiCpOM6i/32HFCnLspwGG8CxNeIczgzPHJLT8Wg6hTtV7TXfFhZe372BxWy+hK8Fgy97mduCyy28r22htElxsBv/teAGvqha5wx9KYNflS4BbabO/mK5BavAIoBlujSgNv7ho3riQhD4XGeC5w7mA8+ZNGwCDyks0lkKv2+AQI7BtD6fP8COGJDKAuXGap7VllHYcVvgAJxxwwWbOLA/VQ05kaAySzh+SQbEQmFttZ5Oy2buVOntFDGnONs0HY3G09EoU3QPf48A/ypCKWabZMpaVa7helY93vg3GyVtsiElF/s1XPzGxAOzPCfwidXsYgKtYQLvNSdiAoZIkxim+eZm9GM0KuYTKBb4ucTPEj+rMOUx8B9EsB3ZI+K/mKMW/2thS6K3XCZWVWuYpytW+hFpRSQTSaXVVjNjwtiM5PdbrWpJ1/DqcvnuLc2apAvmKLGGy1gFwTb4OGseKmW45UqugWRGCVyWxu7nDGNwySpBMLNMqPy+G4PlVrBY9hZJM0Esf4hI7NEm6oHpjVC7NTAheGW4aV4e7AWnlEkPzvEHlkjJgNzOz6XgkiUhjOcm3XFqCyyaK1m3CK3BA51YD+E8cMMzwZpk84Ll95l6HFgWz62jMVxWtf1m9xX7/0U0XnyfQKoJ5erotbdcfI8kEopgMBI5fwPTMTaiqRm8ms/fXQNS3FddVS7ENo7HJCTqnfyQfvHCgEXbBDHpRRt6s5YFI65t4AShv/w/pc38DPBW7KuiAxzqqMMirIbdnmfXIIE6KWinY6G+qB3YG1dXV80gT8xSSWUqkrOhTv7IpFATlDxJcvy+UxJzJQb7+g5Vk+NCfGI7bOoWJAATZE6Cs1Oni/TWulRurcYfSIOTt066zr/dKGXPv22R6bPIg29bZBolRGnKdMPrA6GE2qqjBTtoRyO07bN3TFaRaENL5gFxB0ikSrJaCBYXxxuN3WOIrjeaAMJwDFrU5QvUoEQ2Bb5fx5bukSyaD3Lp0JXGILfZ68Xl1QQWy5n7N39z062K69XadGS0zR7pDstojSVaoHHRELqTAZJEppRYctwBQZEbhe8lMp9Fo+crEXzrKurSuXmuHq50uAnmKCr3/cq52sJ/eFkpbYm0Hdbibhx1o+CWJZ7VzmGnSdXZRHdBRJaz2ZE37e3BTWZOas7NR1NTEiGSTlUGp0YX79HncfBprJidqnHCDX9k1PkMu7RhnqrHT3esM8H9UjLKCbw+aPL11XX1+KYb3vk43B8q/kZp1JIMz0JQFbhGxp3AsDhq5/erTDNyb3CdQSgURs3wCIA+Auk5NQXR4UTVIo6hoZ1J3f4Rrb0ENFa/yexHwxnykBHd9EuIDiPzcSDzmiObF+iIGZe6L+Oj6Xg8whhQRGufmWHCibEgcluTLRs5gEPdWsYv384OdRt/i8OTxv073EJKtaqo2smkdNi3WJxOHUPfrGb/vWltYWt1bIy5vhT9BBgpH5vdV+x05ZfX7w4ZnIWLdfOquVodMF8SmlXbbXvyarvS8Cdc0/myh/Wc22lhGpdAg0wTSQeCPjpDnmQzv+pHEODwC1JVMTm4hrdATqdCNKeljlbNr8XqqPzxuOAvAGfEIchsvBAEyaJ4xlCaP2HliHBPkmiNrUbt8dFp2R6UznrQIT2/in6hET7HAztWwjSNhBcnvFw5JUDJaRoi7Z3r+7H/bHdt3f1es9E+1qhCnR2kmfr509zQya/dllx/eR0vNGNhg4tB4/6Q3XMbrPhVS3cDaRDwzPU0/ObE6PF36kXoi7PoiyH0Rbht9eIXfALO2Jm0VZce+Q/bta8rd5xDezJrb2q48HinVlhncMzH46jf64CyB7wzGxgfKeDhNH+0dXRutt0gOmQeaDS/AYYxXed2oY1FzuSHPvoHAAD//wEAAP//p0Lgt0IQAAA=")
|
||||
|
||||
@@ -19,7 +19,7 @@ func Assets() map[string][]byte {
|
||||
|
||||
assets["assets/img/favicon.png"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
|
||||
assets["assets/img/logo-horizontal.svg"], _ = base64.StdEncoding.DecodeString("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")
|
||||
assets["assets/img/logo-horizontal.svg"], _ = base64.StdEncoding.DecodeString("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")
|
||||
|
||||
assets["assets/lang/README-FIRST.txt"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/zTPwW3kMAyF4buqeAUsrPveBkgJ0wBHom0FMimIdBx3H2KCnCXiff+jd6yts6EJfG+G2iYX13mDJoNOV2wsPMm5LvhQiDrKTrLFq9zQNfnOx4Knoqj4bK/TGT5JrJM3FfuH0ZmMsTNV6BdPuKaE3X3Y/5yv61re/9vK30vRI4+pn6GwPLLdUgImW07pEXvnqEExHFQZKnj+HeJqEfP6NR+xXKj3G+PsnWvkRUhAjdO7d0k/AAAA//8BAAD//4mINmn7AAAA")
|
||||
|
||||
@@ -75,15 +75,15 @@ func Assets() map[string][]byte {
|
||||
|
||||
assets["assets/lang/valid-langs.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/ypLLFIoS8zJTPFJzEsvVrBViFZKSlXSUUpKBxLJiSCiGEikgMRSc0BEHpjQdXcC0SC5tCIgkVEKJDJLgEQOiMhLAhEg9Xkg9QUgVkGJrlMQhA4IAdJFIC3FZUCiBGRCaTaQqMrQdfaD0CHhSrFcAAAAAP//AQAA//+S0NbanwAAAA==")
|
||||
|
||||
assets["index.html"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["index.html"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
|
||||
assets["modal.html"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/3yTUW+bMBDH3/cpbjwsrVRCW/UpSzptkSZN6qRK7csejX2AV2Mj+0jHEN99h2EsrdI9JDbmfnf3/5/ZKn0AaUQIu6R2ShgohMIESOTaKvy1S9KrBGyZCiKfKkEizYV8Ut41u6TvGXUB4ROQbxE2sAokSMsVDMMr6gm73AmvIvXFOYPCnkX6fAy+fQewfZ+mvGQZ7F3TeV1WBGf7c7i+vLqBxwrhobOSKm1L+NxS5XxYx/CJeax0gAfXeonMK4SvztfAZ6HNf6IkIAfESQh9HcAV8eG7+62NEXDf5kbLKdGdlmgDXsBhDdfryzV8K0CA5JYW6v4OnkUA6wiUDuR13hIqeNZUcQDXLLTBiyndD9eCFBZcTkLzYhEEQUXUbLKsnuqvnS8zzppxvWwUlabRkNfDSZUWxpXR2vm8X01vTLnagBG+xMnMU7R0ltDS/P5URIU8fQ/CoKfpP+37caZtGIaFY7K6eQmSJoNHARwSGlbNjepil2gunfwlStM11XgCy46rjMtYY5uN4HGmvo/Zh+Ff+ay6WURkrOJtRblTXfSLvLBBmlbh2+TcbbyWycs8hXN8c44t4JkTa6CuwV0yPSxMThb4lyosRGso7kOdQPwU+MrUesnMiqNT/zHHY+0OuFjzAevQfJyoqMoIwtv92PQcsc2mfk4oXbbzZl7+AAAA//8BAAD//53P618IBAAA")
|
||||
|
||||
assets["scripts/syncthing/app.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5RXbXPUNhD+fr9iM8NgO9z5LpS+5QhTmpBCm5CUSyk0kw+yLfsUZMuV5EsCk//eleTXxBmKBzh7tbvP6tkXifkc9kV5I1m21uDvB/B0sfMMztYUVjdFrNesyOBlpddCqnAyn+MfXGQKVqKSMUXbhMKhkDmgTFXRJY01aAEaHWgqcwUitR/H4jPjnMBpFXEWGzdHLKaFolPYhPA0XITwJgUCMQbT2pwewRVRUAgNCVNasqjSNIErpteogIgp43RqnH0UFcSkABFpwvCnoEA0rLUud+fz3GGHQmZz9DlHtHk4mUzm25eKs0JDJMWVonIXtKwwoFgUmhUVbb5LXinz133DNrKwnXEREQ6PdiEl3OyCFFnFiWy/0YkSnLbfG8JZcoRaqhYZP5MNkaBaovcaL2EukopT32vXvCmcTwAfryQqJryUNF7rUEtSKE409aYTt9xahLGQ1JtcBEsHU0keEYTdA09Spb2llWYVe0+lYqLAhaLiHLX7LoqUZX5aocCo+I8MpadSbFhC5RQetfid7EhgeHRF5QYT3IgD+GLDG9iHCU1JxbUKr5VMX1OCsrcktyF+mO2v3h3OzsQnWmCoX7HdF+ITo43tVywx4xRrt9SmpstKrXv7a+I0j6S6kkVP4ISqxMyavLZGjSy4o2sew3Gz3hHdSMK13bTyg3PvetbyPts4Te9iec8hS8Hf6rI2hmmeQV7vBHDf6S1QU5HGd89w657lQ2iJiKucFjrkmHxDSigpFyTxTcMEI3j3JDXZDd7QpFO/dQu3pqjNC7Y+Nz1DMmz4IgGDz5myMTiN+yUaVoquNKrEhzg+1JEwKfC7jWFrpex6FzyiFNVqbgDsPzNsskZJValTCi8VJmoY1WgLhOjs5YYwTiJOnYbyu6lQs/Sg6YGrd7fue1jbBs1CIgm/nJ0cnOwCvcbd4gSupxOnG8rbQlWAlS9A0ZJKpANfLIivgsmkLeaEGtm+yEsiqU+mEDU5N8Whb0qKw5mEhWm1rT1stqrATmQFTTx4/BhqhWhUoV89xlvt5nmtHkxGCmK2s7zbkLXZi9qsrohJ59Xt4c2B9dx8jHR249vZtt5b8xc98+XktsdSKjim5SGWSMgSi82S/4+KJi+syRjSMSl93vgyIyXHrv5SNwMPUyFfkbg/x2QfOD/HoZdcmEHQtU8PPB+DPMID18/7mBwdnNcTCRHBN0IMG8/bvA/H3VDNzxEz6O+Vh0pI7Q/IG0bCh5EkNGY5npWmTaZ4Og3CSVjGtJoaJVX3nSEfVWEP624xQv2iicb+OAe4qWOi12HKhZC+feUicy8kstBBAHNoV3YWQR20QW7Mc3LtL2yMMKs9D7fmwuzvDudSIvIVXmuKzOe06G+OTc0oxH435xme/fGaSIPlLXaefvfs+x9+/OnnBYli7KxszS4/8bwQ5b9S6WpzdX3z+eWv+wevDn97/eb3P46O356c/vludfbX+78/fPxn5vXyx9DhYgkMaxXh8eXJkyFpNoAnew793O5TCuxnx46LH4/MbfCtRoheMryazWAnCC5Gqtx5HLLA1Ku81Dcn9uroi+iyT0PX3zZg2/fmetdp9bzbW9UIqjmD7tZVhNvA0WckU7xjMt1H1SynotJ4p5OZctdBHKxTK1ea5GWTHNTI8LpZV5/tERysEmkdv1E4DWWSeoCKYSGucH3WOV4O5qNVfT4Ir3nqENERHg1n7sO34G476NRY947e+oh/yI27+vXX7CQz2xs79O2C2WfHef9pa9fwEJKy5Dd+S6NhdeROUK+bSzAqjIbUuwe4NNfMNwUwSnrn1/yXoXNYo+CPvbr0Vtp0DPK0HKQRT2H+VlyhxlZN4jB3jfRbE3eHmG8l8iskjhZBk0vXJx3Dd/ur6d6aeVT4DwAA//8BAAD//5c0CnM9DgAA")
|
||||
assets["scripts/syncthing/app.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5RXbXPUthN/f59iM8NgO9z5Lvz59yFHmNKEFNqEpFyg0ExeyLbsU5AtV5IvCUy+e1eSHxNnKB7g7NXub1e/fZCYz2FflDeSZWsN/n4ATxc7z+BsTWF1U8R6zYoMXlZ6LaQKJ/M5/sFFpmAlKhlTtE0oHAqZA8pUFV3SWIMWoBFAU5krEKn9OBZfGOcETquIs9jAHLGYFopOYRPC03ARwpsUCMQYTGtzegRXREEhNCRMacmiStMErpheowJ6TBmnUwP2SVQQkwJEpAnDn4IC0bDWutydz3PnOxQymyPmHL3Nw8lkMt++VJwVGiIprhSVu6BlhQHFotCsqGjzXfJKmb/uG7aRhe2Mi4hweLQLKeFmF6TIKk5k+40gSnDafm8IZ8kRaqlaZHAmGyJBtUTvNShhLpKKU99r17wpnE8AH69Wea8ZV2HCJDLONtS+npKMFUQzUXhTp1wSFRNeotJah1qSQnGiKa665RY+jIWk3uQiWLqYKskjgjHugSep0t7SSrOKfaBSIT4uFBXnqN2HKFKW+WmFAqPiPzL8n0qxYQmVU3jU+u9kRwLDoysqN1gNjTiArza8gX2Y0JRUXKvwWsn0NSUoe0tyG+LH2f7q3eHsTHymBYb6Ddt9IT4z2th+wxLLg2Khl9o0QFmpdW9/TZzmkVRXsugJnFCVWAamCFqjRhbc0TWP4bhZ74huJOHablr5wbl3PWt5n22cpnexvAfIUvC3uqyN+TTPIK93ArgPegvUlK/B7hlu3bN8yFsi4iqnhQ45Jt+QEkrKBUl8013BiL97kprsxt/QpFO/dQu3pqjNC84JbrqHZDgdigSMf86UjcFp3C/RsFJ0pVElPsRZo46ESYHfbQxbK2XXu9iWSlGt5saB/WdWt6B5VJU6pfBSYaKGUY22QIhgLzeEcRJx6jSU342QmqUHTQ9cvbt138PaNt6sSyThl7OTg5NdoNe4WxzX9SjjdEN5W6gKsPIFKFpSiXTgi3Xiq2AyaYs5oUa2L/KSSOqTKURNzk1x6JuS4iQnYWFabWsPm60qsBNZQRMPHj+GWiEaVehXj0GrYZ7X6sFkpCBmO8u7DVmbvajN6oqYdKhuD28OLHLzMdLZDbazbdFb8xc98+XktsdSKjim5SGWSMgS65sl/90rmrywJmOejknp8wbLjJQcu/pr3Qw8TIV8ReL+HJN9x/k5Dr3kwgyCrn16zvMxl0d4Ovt53ydHgPN6IqFH8I0Qw8bDOe+7426o5ufoM+jvlYdKSO0PyBtGwoeRJDRmOR6spk2meDoNwklYxrSaGiVV950hH1VhD+tuMUL9oonG/jgA3NQx0esw5UJI375ykbkXElnXQQBzaFd2FkEdtPHcmOfk2l/YGGFWIw+35sLs7w7nUiLyFd6BiszntOhvjk3NKMR+N+cZXhTiNZHGl7fYefq/Z///4ceffl6QKMbOytbs8jPPC1H+I5WuNlfXN19e/rp/8Orwt9dvfv/j6Pjtyemf71Zn7z/89fHT3zOvlz+GgIslMKxVdI8vT54MSbMBPNlz3s/tPqXAfnbsuPjxyNwG32qEiJLhPW4GO0FwMVLlDnHIAlOv8lLfnNh7pi+iyz4NXX/bgG3fm7tgp9VDt1ewEa/mDLpbVxFuA0efkUzxQsp036tmORWVxgugzJS7O+JgnVq50iQvm+SgRoZ307r6bI/gYJVI6/iNwmkok9QDVAwLcYXrsw54OZiPVvX5ILzmqUNEIDwaztyHb5277SCose4dvfUR/xCMu/r11+wkM9sbO/Ttgtlnx3n/aWvX8BCSsuQ3fkujYXXkTlCvmxszKoyG1LsHuDTXzDcFMEp6h2v+f9EB1l7wx15deittOgZ5Wg7SiKcwfyuuUGOrJnGYu0b6vYm7Q8z3EvkNEkeLoMml65OO4bv91XRvzTwq/AsAAP//AQAA//8u6xJaag4AAA==")
|
||||
|
||||
assets["scripts/syncthing/core/controllers/eventController.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/7RUQYvbPBC951fMtyzY4XO9SaGnkPbQ7sKeeuiWHkoPij22BbIUNNKGUPLfO5ITr+M4bCmtLnFGM2/ePD3pWVgocePr+2fUjmANlVCEq9lM6NorYfPWlF5hmtBeF66Rus4LYzGZz4AXf2tnjVJo0yRCfOwDSQaV5xppNKS3VJgtZnDbOLedw89YHVbiCYGclYVLuOsp3OXnSpCLsExMe6VWfUIgHnYfP/HWYlAZNsgXBRI96DBPz6EUTgxbh3V3B98a1PDlNB1YJCcsS7FrpEJwDYIyHN/yUGGfJ9bYIUoCqcdwW2tqxqBYubFmR2iBk8m0CFslXGVsS9zGeasJBLxdLCAlqYvYbAzXoCjREjSCYIPMtFKeGixhJ10Te3RIzKvEgDXPui1tIAycjwGfGqa9ESQLodQeWhQ6cBUugg2m6zvyNOgyELrsUrhuDLrjXG0ciML5CMsnwBpUXp33lxWk/02dQ1horbEPujun1cV2N+d5/DA7+3t0zS220qXJ18fPmo+MvbqaXbA4euc9LKaoROX4oO5F0aQvDsJgxan8E+rgKl1LC4tVJqPY3qZObyLoTQbxN5fl6cvtw4Xpvq9I0kkwFT1T4gJvAuow/x1lh/cxcPoehVKoa3bcG1j+OAfpL+i4nMccnQlb7Em2aLwb6D2lYXxB8hpd6q1iHyP8D8ldHIs+xGu0TjjUtZ5PipMf34e0fyeu5EVHpkdfjgXK4B3ftpfgYfQIHctefYIuTFtVk679OwopyW3Wy+TfKrNcXJXmD9i9xmqSTTD0LwAAAP//AQAA//8bMA983gYAAA==")
|
||||
|
||||
assets["scripts/syncthing/core/controllers/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
assets["scripts/syncthing/core/controllers/syncthingController.js"], _ = base64.StdEncoding.DecodeString("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 truncated
|
||||
|
||||
assets["scripts/syncthing/core/directives/identiconDirective.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/5xVTVPbMBC951dsZwp2GkcOdHpJ6s4wDMxwgENz6IEyHVdWYk0VKSPLcSnkv3clJ8F2FL50wUj79r2V3m5SOS9FqslCZaVgYVDcS2pyLueEKs2Cfg9wkYxrRg1fYQDPmDScKhlEcBt8rLjMVIXfsxKBXEkIN3t9eHBgu1aphmI1v5lCAkFuzHIcx1VVkeozUXoen45GoxjPg0lvB9nlu9oShqtUlCyCgv9jzeQNAkyfKVouEEGoZqlhF4LZ/26moeOPILA8/ck+OlelyC65EN+x1DODqZ5K0qqKgCrRpbVLM1NqCR+2dZNlqgt2JU2tl9A81ecqY2fGpoGBzQOf6ioiOBn14QhOO4LWh/Rdc62Vfq9Cy2nZ4PjYqUiSBBY8ywQ7R+RLChaOGyMvlW5xP0/rSIeObwgnL9Y5e/sLWJj152te38bZ5/eopYYUDHmN5r9Lg1b/i7YO69eyp1PnuwEER13/HMDfW7x983fiK56ZHHNswW/B5ozPc+MD76Hxaki6XDKZnedcZKFFvOxHG+XZVdX+Jl6hz00b3/lTW8kdrVZnu0gq0qLAGhtDqSPcmS+p/zw+wpf26e5uEuzDEcQurh2yk4kx16nJCWVc1I0UY9vWlm4h+AzqzvdbFQ8wVT0ajJpiLXIe9olmS5FSFsa3P3/8uos5FuV9rBn2nvNUAqOJvW74WquGwUC3h+4ezLV84+JdT36D4ckEhsMDvdWsqjsin5ryOaSj92A8xfkJmzPv9ZQ+2uYEc1PL00vNtT546j/Z323vrHsd+9UDcjV/ktEI2Rw/dDAFWoaaMQQXQdT2OlVLNj5kOgQkQVtNGy64/DNuTFyXLgJWj9AI0m3fFb6r34RtBkkoWdX44XapSN0U3cnSa3+t7zDgPwAAAP//AQAA//9afsjulQgAAA==")
|
||||
|
||||
@@ -111,6 +111,8 @@ func Assets() map[string][]byte {
|
||||
|
||||
assets["scripts/syncthing/core/services/localeService.js"], _ = base64.StdEncoding.DecodeString("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")
|
||||
|
||||
assets["vendor/angular/angular-dirPagination.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/8w8a3PbRpLf/SvGOlUIWhQp+ZKqix72am1lS1u2z2c7u3clKQ4IDkmsQADBAJK1sv77dc8DmCdIydncoVIxBcx09/T0exqYPHv2hDwjs7R6Hy/SPK7TIie75CRfNFlc/fUjWRWzJqNkXlSklCPyBYnibFWwekji/LZewp0xQBH/kVcVnaU1w5/H4pIPXsd5SjPyKZ42NE/iA7Ks65IdTCaLqmhKNl4UxSKj46RYTWaTFVtMYkEF/Pvjf5X//O3sf9K3k+o/rnf//e/7//3DdfJXBIqE1UtK0hmNCdC+LG5IXZDZbR6v0iTOsluS5tfFFeWj8sVuRUsa17himtTpNZWUkzMyLaqquKEzEpMECIJVF3OSpTllsEy8O6c3JK7rKp02NcCKV/BkXhUrDlqy7Ocz8ueiqFldxSUpq+IfgOUA4beLTetlM+WrlOvbbdLJVM2ZTLNiOlnFrKbVhFXJpGz3Rfs5/gdT3C7K2ypdLGvyfG//e/I2TZYxMPnPQFZGb8nRStz4k/x3Ku4D+nFz9QIATJ48ieZNniDUaEjunjwhcHGxwAsR5PN0If+a8H+v40rKxTvgATkmA7mSn+s0Y+OWtfxnJ1eDw3b269OfTn5+8+nz2Wuc/fnzjM7jJqthhI3+LccTQC8A1tUt0E3kJQX2mEiaxuJG1BE8FNPuSRLXyTKiVTXU5k8mfGdnCtCsgF3Oi5rQLymrR4QVJKlAgkA6cvoArCNyfqkwi1WutKXB1fEtGnR8owOYONgGcSnTDP8YbJdxxfivTh4+0uo6TfCmNvO1gnc5XIfkXfGqRZCr3+38ddOBAJCSuioyxqn10aXd/ERXZSZW5oXhpXueZqAR0SCt6Yq9pziNBpHpg37iE3VQTIyLvFOde9pEUOdrsDNV5F+Me/O9nKDBqJo8gv2s5YhXcbKEuV4+KChnOavBkOEipH4ohfXudqSEZUSEqPgWpRQdr4rWTZUTTQe4VtFqBZOyA9Cvho6MZyvQ1fQ0oyua177nkoADe3/53Z/yduz9YUeFZ036nKiW+EakPgEbzIbaCpRVoF/KijKGUI7lMM0ESXOhKXpFF/QLqeMrmkuHAO6CW/SwtVb/ggl2bHW+mLQKAn984K4GBv7bm+f7+w61KzQ/QGhH9Zjfiia/XLBn0fkFu/h4ufNyeMF20hz+192JXh7A3+Aukiv4d3prPBy+hNnbk+Ghyx+hRO/Bh9EKWTS5+ApjdW2BPw/Of/l6+WxiMiudk4gTd/78UlJpABuiryd5k2VDS464LC3BseomoHO/B9x5Xhh6fTGQlIKgsZpMKWG0Hg9Miu6d1bla/4Guimsw5cekpR3cfxaD8hvUg3kaDA8dgEkBWseF8i8UxwEcoVFREJXN9Xg2a23riQodWCvM9nCQybM5BlWAP2sgqmGElTRJ5ymsQo/BivxsNiI3FEU4RfnjbGzyXYoTQdZnujJAvANRGsCqgd42ZJrSnM7TGqMcwGjTATu022HbTaRR6naOARAAvIpvcYeyorjCyFAAB1xnr8cOQ6v45mzWqaa+GPL1qxYVmHvhmK+xWjU3jTlsJ4dsc1MaNr9leZPmV2BWWFKUYCGpMi6xz7ZIlrzD2BLXDHxfxteUxEkCHMZ4E/n5K4f1Kz5N4hzCTiCwLNCC8x3V9mMB7MMBfJrBhS68hJDTR0NZ1EBnygPbdu9jkkNoCsEUqClsqJIBTlkMy57PaQWzpFDBEgRmzrSxgwV3yiCqFfvY2bahYOAQt8992repG26sgezQ3RYuVtzOnurGf0HrD9bdqNuAEbHA2lBRbaX5/lRIXY1MGRk5aH3kVdwsoCcvqri61UwAbS2Ab0nSgyLvifLn2hT/nKbCXUab1NqrFfi2V/b9TuzlStZww90msMca1PcoHFVk2iaHGgiduah4qEfvUt+WFC0RF6K6gIjnDI0seQp+ZdDkkCFAJjYb+NxLkMYTdpsnkEHQTxCi2KLkg8IpHG/fCAenp0W+0WKDuY0xFKSjXqmHH9v9qLNNEQgRRFV9qJBLe+TomKwfGuTIq9alvaH5ol5amyYh+8nlJPsX4plxDzaV0QCNOp87kh7Ecds5b8rpqJu4jtmbjcTrMbzuoI8z/vz3YbvXc70G07FARyRdVQbOr5M9wVEwNtNbUSUBZyJsjgjWQC2N4omDQVkr7x7cd39qxLUpPl7PeNSjcZGkM/CwDAIL8JNtBMQDnpwCobAMyJuSK+GOweVBwIFmGJ1czDi1jELIAg61WjRoNAE4Y3ymjpZXjrRYTsadY6RHQMXMH0ZVlCMHv4D3sRwkxRAhQCIvIjQtktew6Aj/BHYiXmkDPQ91MTEeC5SM3D3T5EEWRfBqN/RB3s8SbZ9DHbkWe/ZaGOSzXMS/4GuePnUzmSicYYj/D51EBTXPCCLQA2gFo+++I08d9D4F9YQFGoEqEegjcTgZka3tfXJABltkxwyKdsjWYMsW9ZDN6yXFzmt8MawNYBOdOpnNWKjqqQyBDClA4IUoJzHjZU+e4e/KpyTahWisgshnl+YgMKgBEraOLy7LqiirFO2MOb8jQKKdpxUTapRB9qyoUBFxBSk2HfvURozzPOGO13Pf5lu/3jwu7LP2G+VXzjnfuxyDGWujPl40U1kVFUwd8Ng5PCGu413fLJ/Eg6VvGGZheoEGzRMlkQtjRIx7uLVuIMwDmm3wZtFAFTQ+cgK88a89XYkX/U2xRPo6skv2h2OEjnCldCAJABfrSZsqlo++9aTdP0R7DCblxa50dqYu0ThZ2mKskvywPKsR66Wyr4ZgsUXVpyATPwWqtMJZGwJRb5VGCO44x3gZgnFe0XkHf4xP35y+PX336fO7/3x9GoqEFFbaao3a3gD//Btt7g7/a7iJrRPlF7Fh4MFSbqUZEUl/ix60ANUJ7Jhhz9AObbTTbDOj5NnD9Xngml2k/1ebKCg/6d3KB20iXppd2OtBIU1dcID9KGQr+0fZ5K8xWkFq0XqtI4iP2USgX/EzJgZR8ULk8q0oqfKdTLARNu3qRiPpAbhz7+INeXQxIwVWi+RxmyoyznXEeWFC1oDcxFo5ck2EyzOBBzjqbw96H1Hq8IS+TtnCrYMLn6MN9KmTrxhjFAn0+Rs6O3Dv6bxn7/kGYcIC7hDTlUGWca6QoqlIcZN7q0ZSFjTOAaVWpDv4/Fkjd+BqO+fxuQvqEmDtu8N7mOPCCPpuvFQxILxrYvy9c7D8CYvUKSrYkmYlkKD5c0wq4ywrbhikthXeNvLhm6Wo3ppBrgizUsuNhCKtsaLjjKeZer8C+HuR4sJfyhgxFVQY7kw5KKUDI+7KIDwHlb3ms+ZNhdmrlc4r3FiWTvNcXzwbS4pqXGQlD1AkcqNsIJAhjTYISLqpmL+K84avSVUI1LKF/ra66545GyUgucumRkCmUVRpfXtAftjb2zNTVPPwspMF4/w9dOIYOH2NzENbnT7zybhsIBrdqCViXHfHx4OjJiMJ5EPseKvTvy1MntL58dY+OUK1BAjCGW29OMpS9XBaNPkM4go81GB8igR0B4tj8RQryQeaVivrA+EB2Sf3AAvUoKIASU5Ok6vjra7KG+0Pt158l8W/NcXh0SR+cTTJUh2/XJ84VfmXEOCZit4YqWJeskQKwFlJ3zWrKUgoSDHnIOEnp1jt2k7zGf1i0hsLIxCitoM3spam0MCgi8F4PL4YbLgwOREWc3enA7q//915rd3lmffjOL8jOF/5Oe8RyD+SSJzCqbOImzTZi8HwARags0VOedfX7GH0VKBnzfkufuA9Bsdk8svFbGd7cuj0XdxZDo2BN0/qAzI4OR3YVk1g+rkCw6blAXSlzi29pSeORZ5MdBCw6uAuYgzR5vu4Xka21zUp4f7+wINtFX/5mP4THg2OXw7csmGRo4t+tcSEGMZ85xujxx4CTh8l6JKcPhOxf+KEVzf+btDYMzFwNEzunCN7cawtfCaewWsnvzMZY8sSunagnmqHveM2GilybFjELLGOQRl4pMEDPgxDWFnkMwzujSCgi1uWMbNJw2jwltaikI68Aooi2OWxPCpGrDmDzACcudBdMs2K5GooQ4lcBEO8LKjHFfyI3+0JEM0zoOfNSiQhsayeAyKXtM1WhXTcVEW+yG5FIwmOBWrpl4SWtVlrJ2afgf9EOngk7Tn4FgdVNoQN4DpZw1P3jChlH+RxN52Zp5O8yL1mgmh58Kk8b4aZvYWsTUTzfeX0IXlJBhC2oqq5Je7BEO7iE0/Mv7apR3uiJAVRdJQB/CTOUUSnoDd4OnOT1suiqT0i70PjtgS5XBcbKM0SMIsYN4A5Px5aKYUYYHpZrbEzZfLoQeZx5kBkpzzchHwGSwfb2I0RGCvC00MPesN/9mA3xvUjt4aCB4khzfR0iXWs/oB2GrC/BY+ALIsM5o3ID0Mf7SLGOibnl4GnaiOPPbKL3vuA7LtuQcYH8Cx0utjhqCTdHvDFDa288JuyDDzhx/kevB7Em3QOSIfsBhXoe3vPjIc88IK8zTv1TDvB6ut10M/C5cFzoI64BylHeAReCwqZHza6tujswIFjdGqB/wrWhdffwwApVSPu2dKi8YZQvBdAhqdPj9uhaKRl10p7a8NulUXxqeB02jqhwuA/gIt++esKKZvKkFZ76dgYKotprOSlJo2doSkGv8JVs41Z1GUNYCHaVUCwHqI3ZX+Ls3T2vk3M+OAQqfCMF9AqRs8gMYE/R2R/L9Dbsa6zymoZQbxrV20tumsKUDz83ZZqmnvNFlB2UlXxrVj8I+xcYFJYw0e20+rt7/Jlnchb/5ymnMGqONS/YSzPIl8LG16iPhsTLONNscLQtbBgQZZXxBJeMKt5pKOiJCpTRWxdgcBWtax4ceAuiVXouVRff5I7OrrDFp9ukyEWQKn1tRPh5TYf3fLine truncated
|
||||
|
||||
assets["vendor/angular/angular-translate-loader.min.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/0SPsW4iMRCG+3sKM0I6W7L8AKCrTtw16ZIOURh7nDXx2pvxLAQtvHucJZBuPP413/fb/DomS6YvfkwoYbDV2TQQuo4Nk801WUZQJljHhc4Slo/tM1uO7l9MWJ+K9Uigt7B8Bw3LjnkAHcbsOJYsrd6riZBHyuKxdGqKQS7c5bJwphFD/JjHOoY2Ku6onETGk9gQFZLwt4zJ598sUoOJOsNF+KJrkYu4XRCFxO2AqAO6GCL6Baj10ZLwf6zxGJCkWn/L7OU0Ulpt7wLamTc867vEzhxKzBJA6R65K34F/zcvoAdLtq8rgKtqSeewVvlTVk3eENaSjtgeLYJzgUfg9n9Ax3LGtYj2TaD0seL1ulPrX58AAAD//wEAAP//1rAncZcBAAA=")
|
||||
|
||||
assets["vendor/angular/angular-translate.min.js"], _ = base64.StdEncoding.DecodeString("H4sIAAAJbogA/6Ra61fcxpL/fv8KoeND1KER4M3uh5mIWS5gww22iSFx9szO5rSk1mNGIw2ShkdA//tWtVqtN7ZzP9ho+lnv+lVJBz/u/EP7UWOxv41Yup+nLM4ilnNtX7t/a741D+Hh7eHRT/uH/7V/+B+4NMjzzeTgwA/zYGubTrI+uGaZw6LrlDtBftA7CfecJpunNPSDXDMcIs7TptpV6PA446724fIWFh38Q24114m7jbihb8S5G3Guqc7T6VyPfX1BzHQbG3P9TWPG28ZOHiaxwcjzPUs122Jmlicp8/kv/Mkg1KkHDDJ1Zo7p89ywyYyZ24wb1U8yqWgJs5s8DWPfYCYQ4vE05e4VTooTqn3DkxPHzPA4Wi769lN3d187tlgQ+o2iInBAch+6PDVacgKp3dx++nzy/vzPX87/Z0Bu1KEu5dSjPg1oSJd0RSO6pjFN6MZ6LuidNV/Q1GI0w4fc2jmiW0tXN+w7UcJWOr3HiQdLN3X6aKlLyjuY9RDGbvJgxuw+9BkoZZryfJsCEWYkuX15YaadJg8ZT68aQ9lTlvN1c2TbWqED49kmCnND34fHZRLGhv6nTgr6ZDVZ9ZLUKM0EmHCtSqhR8sBTh6ECCOXWIfWsOzPisZ8HU++YT/neHrHNzTYLjP6WuzlfEDINPcM2gT/++MkzXHK8f0RK7jSGc04pA39akRBoYazJ0RCltrQcM2DZp4f4Ok02PM2fjAANo3dhQCxrkHS8R/9Rh9nAzCJwNgOI2N01QvX7kMII7la/A8knjBNqLF9eQtzhW848WNCaof51PhE8Vkz6RYGcrPDoUhEgfqlfbSUvOT7a3X3tzNX8cCGOneHThBX0r4b6qE2egcMdtru7Y1f3bpDpcgQn+/6mKNzM2aLgUca1etEne8md3MAp8vIi/oKx197GH3Meu2KcnmCYqDjKgzArpvi/cj6gMbP+omJMeMNpxLLsI1vzlglWRjEztuBNuJpMtsUUhXfSYhY9sjQP6ZZTG0hEy4WoBk8OUirMiaMpMcK65sNRlYHFwEBpj+eAzE6MgGJAjx2Ww2K4kJOJ4Vm2VNdM1/fs0pkeyN7DHp9wWs3t7nKwI1fYSnMZdeb+wtL/e6LvefjDW1hBLTZHyoy57mWc83STlIIbklAmHY4IIRWlYMHtP/AsA6d/l6Rrlo+cog6pNrXWNUPj+GkYPQa3DxG7krqst9ywOMzDv/jvLNpyMEa4y38a2pq3t/YSwIj12Mp6bLmzYYgfk/xdso1ByG7oYKQdvPhrm664l1fyf3XhZ8z0HU197eARtmLFVvwNB4mLR05K1EmJPMljUWQzZ/WaZP+p2BAu+c+RwwfizMzg1s4hZBUMJo3Ef5Km7AnmwVU4xnlIO4T29tsw75YWbxNJN5+5GAZd6TRgVC1qMNyVERHjE4TAiOQB5E4t5g/aeZomLQxwLXGB5iTbyI1/yDUPArHWkO4tsyOuQUDRMBsDfJpoP+h7bE//oY7kXmWs1e9STKcjYkLAcJ+ErnZIJuEs3EsnqWSmBmnWqfKZ39LoKmFA5Ki5wqJyRZM1tU2nz9s0grzRcN2bHJhz3oURz/7O2b3tOmWN03tHYpKSh0bA/NqCoP1cdGLDVQLY7aaUwCtBS65oktPc2QxQp0myCvnfOrK1VW9JrnNaLa+gHbOkMqEg8MLHEVMIlTuyRiwPswys/7Y2wgsWuxFAu8R/hYvRba3I/srZTTZH1w0xsuzF+esky0+T9SaM4JChLQCJd1qbXA7JZB3GQl7joR79CqqXGgGG2bt6esYMMnk0lGPaCrHOngBsTpzmjSn3QwDQ6ck9CyP08upCcL9s2HhBY3fAqw1Ry7FURLqTB76BqsmCmiICUVL9TRgjpEhSfE6TJL9xAIHgj7tmpQH4IqR3JWMP9JGe0XOrrL9WgOBrxZ1xj22jbjKm7zB4vsda5AL/u7RaJ/MO/KuiroTdI1UAnONiKeD1JO+CPF1UD9SQjVkA7DaCRMBmINUsie65MYf7F6SoNHEp6THzgMeGRwEGuViVrcOMF9SH6gK8p6ougmN/6kN1IUM/cADwqcZLdyakLKgm5Fk9h7CL+l7MQUVZTSjSp2A+BoPrIMmsoZIUwXrZL8zs2cXcXkwuAK4hnn5EIiGhKCt8EGpKRYXBrIu5A9UT5quSC4lSrX8ZLnXI9NHiCOH5nnU0OaQqqRVVzmBFbbbL2bLH228tAYaVnCk+oZ2B76rHyVcXw5MS/r86tl4ZgmNh3lZKcY+dqQNKQWaBVcC5qtxwJOH7RwX9ZcjbYyHweUzZQpahmg6VVVIOM5q0hiEUXrVNE3wuNN/wNVZQjRgdgGXzm63jAFwFXwDlPIhWw2W72wG2do7jIk1ww6uBBrB6zpzAeE/bIngPem/tKMg4Aeexi5HzQxeGgKEI5KF/TLSqktdW/EnLNtwJvZC7JayAZAlB0tSnpffVZiqFN3DxVbkH0nCal0HgkJZBIyJGp0xb02e4FNN/12Gcyqmfi+krlyj5duOIA/G2I0in1UPpUOJCtQixp6hxYGPCITKY2SqElHTTHGMz4L1BFUgipQ5aGhhfjCgQ+LGlNyC4/drRuLryGPR3sDXjQQbqgNAdEQteXnaEAZI+5Dyt8CUkR01aJwLJAIAk1dZlttXwNKKBUWTiYc3zIHF3AGgOZLvz0XoKQPP4pAHOn6lytau/rNcDcyWTjEzdhksAgPOaFqHIcl8ja3wSyXo/d/GqVoq7dHmco7OAQywsMALhJR97mWnAbzbdyh+rkdq6RHuj1irU+Bcw0nEROP0vg5lgiBTSBRoiaRhoNVQoU2oeWNBPY62LPrEf4arO3T559rss2MBCUw3YmVPkuGaoRMcNH2IYRa9yW5EMCqjK7IFCrujmdUK4Hu24+BZKTeXWPnXgFV3yrEGyulRRuPfX9r1wXXlv0BAXZp+f2yk2tFwk6pMRyk19HQa1yppRokrkvxps70huntZrHXD7sjcGty7LxSvpDkti2JBYpmUdt2NZq1m9cUUm9Q9bntEcqSQY1EL/3BU6Ly/0hlj2S5Y969rw5WLqvbwYnvVZsoJDpK5H6U3neJWafzXOjg9nZ5NHWo4X9HZs6efe0t86Gquoq1FiYHmzDQCoyYaGFp+9n/PF5FwG0KDvoJWQA2QP+2UAM1ZmtrWzPDUO6VsyuzTU77dE3Fmq21cgx1cwSI0BBGra4ApyvNTKEgDdu91dpVSGaMGDSFUDudmNYC4csCt/2K7kjHCyX2TKaw/ULqQM4PdhWf5bEvStQRn+3pPhpC+gb5ePQMa+dSvFBLxayKTiUSTMy9d6eA3oTi9H+8Rq1RZXvdq3gguVZwLaj7dRhE9iQjSzohYLpC5+AEhZ1fDUObanNmDei7kLYWsBHiafrA8G/gVFXopXVJfy1VblcapJRcXMu79Da9nJKqnCIgIkakMJASH2zKrUc2Yd4hVgRJske1WyPq7LRlshD5LSARBbBZEePh2H5CUunZbR9alhC45A/BD+ZXcumhk+gHvMvCDSXgp0MP06Iv06/fQrJghYnpCbcVUPyO5axyXl8CtI/tuAYRP2g7U3MAWsv0IfbIBF2ixGBgR/imn4EhBUq2VyHiOz7sD6e1wNngRXBu0iST5rNiyuQcEgB5/L/SULaqMjN5bg4Kv70DoGmqsK6Uoim81UTeiQanEiyh6ealUThguY2wVHcMU4FVX1wwja0uwbzYeBtUD8usIy0EbZY1sIrkJ3ktlrLsr9ofAQQHhY1uFheRxMAwgPflnNY0wIMCbA+WoIsU3ZsBgCJl38zVoWC3wh8eAnLo94zrVqgHZBaSGCsmKqjkNNOwzjLGdx881AibGAWQw66EYvLzWk/y0GNYQxdxuvC8Vb26F+Ui2h5wLy1CFd1Z2D1XE4DUFMkJLmIcRORYmBv0vUVQGiYvh1JX4KUJ72c+MN8lAfJ6JrVKC9u7tWLw489QPbTrVeYfvaWlfv+lxC1HvoGDhIYEpykBzH0xg4EAZyZ63nsTCRzfwOdKNvK0HpO1b+tOGJp+GMCHBGZP0u5Uzo0MqI2Clnq0phEb62B03AXwNb5UP5F7JXgQmsrvTvtizKjA19LkBS7YzUakkpQ/4C/P1RG/Ifx1+mX2Se+yKz25eF0splsfiury08hn3PJ+Nr7Uv8AKMBOwY/wCi7kbpb7tehnkBbpZ71zOH2DXcn/VLwuVCKdEbeAjtYqtjYx1JCjPgaak1D/9kN749/PsD/gZecP+ai4UXMIF9HRo3d7AIbl73b697zQHXs4WcRM/wf1k+YalM6dTXUOhEOKcrOzkhVPJAhXNzxPe9auWrfO00UWC9tFgFc9L590a9h4FyGg69yMI5+l4mAz5UhoPMJjv7x/Z+3n08+3lyd3J7/eXUCP3H8O052QxjLQ0h9evtTn8Yv0YPv2J7+xhHZVzxuWJrxTuO+WxTjh0GVWOAPoOnQySf6yblOM9wxwaZceeSkIUpV1Po12UJF2aw3MqkQS3NxyxJmYxPV1qVlAxI1ky3MXdx+uDLXLIdEc1B/pHSPV+3vHYT1+8ya2hWNRIKwm5ZxzVK2ztAzI/NNYmc87Ui7ZcLNd9WX9edFMmgxquvk5WWndpYzlXVmDhQqwgEJwJJNxBxuHPzf/2Z7L/DvzYGPW6EON1Fd4BDoUGSYpLMqfLQpk1HlFq6wcC9khMHtpTbauxl+tSNvNt88CKk2nLHT4hyQH0W82KAe0zahss+wbjlqg6gGQsDXLv1j5wMfQVXV3tFP9IiQvfr3f5KF5eDrEpX4MF5GJOrGyxjiZUcemKbiuq48+qm/JIM8Z8WQfWG/eAuTtIIKFrn4nVqdFq0qLTpN3YgvfFojhK7KcGyXWd8DFDAMoUUPYijxNhyn3MPBzcAAdCgswfeB8P6KqQFQYiLine truncated
|
||||
|
||||
+74
-42
@@ -375,53 +375,71 @@ func (m *Model) NeedSize(folder string) (nfiles int, bytes int64) {
|
||||
return
|
||||
}
|
||||
|
||||
// NeedFiles returns the list of currently needed files in progress, queued,
|
||||
// and to be queued on next puller iteration. Also takes a soft cap which is
|
||||
// only respected when adding files from the model rather than the runner queue.
|
||||
func (m *Model) NeedFolderFiles(folder string, max int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated) {
|
||||
// NeedFiles returns paginated list of currently needed files in progress, queued,
|
||||
// and to be queued on next puller iteration, as well as the total number of
|
||||
// files currently needed.
|
||||
func (m *Model) NeedFolderFiles(folder string, page, perpage int) ([]db.FileInfoTruncated, []db.FileInfoTruncated, []db.FileInfoTruncated, int) {
|
||||
m.fmut.RLock()
|
||||
defer m.fmut.RUnlock()
|
||||
|
||||
if rf, ok := m.folderFiles[folder]; ok {
|
||||
var progress, queued, rest []db.FileInfoTruncated
|
||||
var seen map[string]bool
|
||||
total := 0
|
||||
|
||||
runner, ok := m.folderRunners[folder]
|
||||
if ok {
|
||||
progressNames, queuedNames := runner.Jobs()
|
||||
|
||||
progress = make([]db.FileInfoTruncated, len(progressNames))
|
||||
queued = make([]db.FileInfoTruncated, len(queuedNames))
|
||||
seen = make(map[string]bool, len(progressNames)+len(queuedNames))
|
||||
|
||||
for i, name := range progressNames {
|
||||
if f, ok := rf.GetGlobalTruncated(name); ok {
|
||||
progress[i] = f
|
||||
seen[name] = true
|
||||
}
|
||||
}
|
||||
|
||||
for i, name := range queuedNames {
|
||||
if f, ok := rf.GetGlobalTruncated(name); ok {
|
||||
queued[i] = f
|
||||
seen[name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
left := max - len(progress) - len(queued)
|
||||
if max < 1 || left > 0 {
|
||||
rf.WithNeedTruncated(protocol.LocalDeviceID, func(f db.FileIntf) bool {
|
||||
left--
|
||||
ft := f.(db.FileInfoTruncated)
|
||||
if !seen[ft.Name] {
|
||||
rest = append(rest, ft)
|
||||
}
|
||||
return max < 1 || left > 0
|
||||
})
|
||||
}
|
||||
return progress, queued, rest
|
||||
rf, ok := m.folderFiles[folder]
|
||||
if !ok {
|
||||
return nil, nil, nil, 0
|
||||
}
|
||||
return nil, nil, nil
|
||||
|
||||
var progress, queued, rest []db.FileInfoTruncated
|
||||
var seen map[string]struct{}
|
||||
|
||||
skip := (page - 1) * perpage
|
||||
get := perpage
|
||||
|
||||
runner, ok := m.folderRunners[folder]
|
||||
if ok {
|
||||
allProgressNames, allQueuedNames := runner.Jobs()
|
||||
|
||||
var progressNames, queuedNames []string
|
||||
progressNames, skip, get = getChunk(allProgressNames, skip, get)
|
||||
queuedNames, skip, get = getChunk(allQueuedNames, skip, get)
|
||||
|
||||
progress = make([]db.FileInfoTruncated, len(progressNames))
|
||||
queued = make([]db.FileInfoTruncated, len(queuedNames))
|
||||
seen = make(map[string]struct{}, len(progressNames)+len(queuedNames))
|
||||
|
||||
for i, name := range progressNames {
|
||||
if f, ok := rf.GetGlobalTruncated(name); ok {
|
||||
progress[i] = f
|
||||
seen[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for i, name := range queuedNames {
|
||||
if f, ok := rf.GetGlobalTruncated(name); ok {
|
||||
queued[i] = f
|
||||
seen[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rest = make([]db.FileInfoTruncated, 0, perpage)
|
||||
rf.WithNeedTruncated(protocol.LocalDeviceID, func(f db.FileIntf) bool {
|
||||
total++
|
||||
if skip > 0 {
|
||||
skip--
|
||||
return true
|
||||
}
|
||||
if get > 0 {
|
||||
ft := f.(db.FileInfoTruncated)
|
||||
if _, ok := seen[ft.Name]; !ok {
|
||||
rest = append(rest, ft)
|
||||
get--
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return progress, queued, rest, total
|
||||
}
|
||||
|
||||
// Index is called when a new device is connected and we receive their full index.
|
||||
@@ -1616,3 +1634,17 @@ func symlinkInvalid(isLink bool) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Skips `skip` elements and retrieves up to `get` elements from a given slice.
|
||||
// Returns the resulting slice, plus how much elements are left to skip or
|
||||
// copy to satisfy the values which were provided, given the slice is not
|
||||
// big enough.
|
||||
func getChunk(data []string, skip, get int) ([]string, int, int) {
|
||||
l := len(data)
|
||||
if l <= skip {
|
||||
return []string{}, skip - l, get
|
||||
} else if l < skip+get {
|
||||
return data[skip:l], 0, get - (l - skip)
|
||||
}
|
||||
return data[skip : skip+get], 0, 0
|
||||
}
|
||||
Reference in new issue
Block a user