From 166ceea586c5d027daebc2bbb761b6f79d438fc9 Mon Sep 17 00:00:00 2001 From: Kenneth Skovhede Date: Fri, 24 Jun 2016 14:25:47 +0200 Subject: [PATCH] Added case-insensitive handling for size dropdowns. Added extended parsing to support --exclude-file-attributes where parts of the option is in the UI, and other parts are in advanced options. This fixes #1643 --- .../controllers/EditBackupController.js | 63 +++++++++++++++---- .../scripts/directives/parseAdvancedOption.js | 20 +++++- .../scripts/directives/parseSizeNumber.js | 20 +++++- .../webroot/ngax/templates/addoredit.html | 15 +++-- .../ngax/templates/advancedoptionseditor.html | 4 +- 5 files changed, 96 insertions(+), 26 deletions(-) diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js index ffeba30e8..65ee84aa7 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js @@ -165,16 +165,6 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo if (!$scope.ExcludeLargeFiles) delete opts['--skip-files-larger-than']; - if (($scope.ExcludeAttributes || []).length > 0) { - opts['--exclude-files-attributes'] = $scope.ExcludeAttributes.join(','); - - while (opts['--exclude-files-attributes'].indexOf(',') == 0) - opts['--exclude-files-attributes'] = opts['--exclude-files-attributes'].substr(1); - - if (opts['--exclude-files-attributes'] == '') - delete opts['--exclude-files-attributes']; - } - var encryptionEnabled = true; if ((opts['encryption-module'] || '').length == 0) { opts['--no-encryption'] = 'true'; @@ -184,6 +174,24 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo if (!AppUtils.parse_extra_options(scope.ExtendedOptions, opts)) return false; + var exclattr = ($scope.ExcludeAttributes || []).concat((opts['--exclude-files-attributes'] || '').split(',')); + var exclmap = { '': true }; + + // Remove duplicates + for (var i = exclattr.length - 1; i >= 0; i--) { + exclattr[i] = (exclattr[i] || '').trim(); + var cmp = exclattr[i].toLowerCase(); + if (exclmap[cmp]) + exclattr.splice(i, 1); + else + exclmap[cmp] = true; + } + + if (exclattr.length == 0) + delete opts['--exclude-files-attributes']; + else + opts['--exclude-files-attributes'] = exclattr.join(',') + if (($scope.Backup.Name || '').trim().length == 0) { DialogService.dialog('Missing name', 'You must enter a name for the backup'); $scope.CurrentStep = 0; @@ -411,7 +419,38 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo $scope.ExcludeLargeFiles = (extopts['--skip-files-larger-than'] || '').trim().length > 0; if ($scope.ExcludeLargeFiles) $scope.Options['--skip-files-larger-than'] = extopts['--skip-files-larger-than']; - $scope.ExcludeAttributes = (extopts['--exclude-files-attributes'] || '').split(','); + + var exclattr = (extopts['--exclude-files-attributes'] || '').split(','); + var dispattr = []; + var dispmap = {}; + + for (var i = exclattr.length - 1; i >= 0; i--) { + var cmp = (exclattr[i] || '').trim().toLowerCase(); + + // Remove empty entries + if (cmp.length == 0) { + exclattr.splice(i, 1); + continue; + } + + for (var j = scope.fileAttributes.length - 1; j >= 0; j--) { + if (scope.fileAttributes[j].value == cmp) { + // Remote duplicates + if (dispmap[cmp] == null) { + dispattr.push(scope.fileAttributes[j].value); + dispmap[cmp] = true; + } + exclattr.splice(i, 1); + break; + } + } + } + + $scope.ExcludeAttributes = dispattr; + if (exclattr.length == 0) + delete extopts['--exclude-files-attributes']; + else + extopts['--exclude-files-attributes'] = exclattr.join(','); $scope.RepeatPasshrase = $scope.Options['passphrase']; @@ -426,7 +465,7 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo $scope.KeepType = 'versions'; } - var delopts = ['--skip-files-larger-than', '--exclude-files-attributes', '--no-encryption'] + var delopts = ['--skip-files-larger-than', '--no-encryption'] for(var n in delopts) delete extopts[delopts[n]]; diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/parseAdvancedOption.js b/Duplicati/Server/webroot/ngax/scripts/directives/parseAdvancedOption.js index 49a146e5f..a8140d67c 100644 --- a/Duplicati/Server/webroot/ngax/scripts/directives/parseAdvancedOption.js +++ b/Duplicati/Server/webroot/ngax/scripts/directives/parseAdvancedOption.js @@ -167,6 +167,9 @@ backupApp.directive('parseAdvancedOptionSizeNumber', function(AppUtils) { return { restrict: 'A', require: ['ngModel'], + scope: { + parseAdvancedOptionSizeNumber: '@' + }, link: function(scope, element, attr, ctrl) { var name = null; @@ -192,7 +195,12 @@ backupApp.directive('parseAdvancedOptionSizeNumber', function(AppUtils) { } else { - multiplier = parts[1]; + if (scope.parseAdvancedOptionSizeNumber == 'uppercase') + multiplier = parts[1].toUpperCase(); + else if (scope.parseAdvancedOptionSizeNumber == 'lowercase') + multiplier = parts[1].toLowerCase(); + else + multiplier = parts[1]; return parseInt(parts[0], 10); } } @@ -211,6 +219,9 @@ backupApp.directive('parseAdvancedOptionSizeMultiplier', function(AppUtils) { return { restrict: 'A', require: ['ngModel'], + scope: { + parseAdvancedOptionSizeMultiplier: '@' + }, link: function(scope, element, attr, ctrl) { var name = null; @@ -237,7 +248,12 @@ backupApp.directive('parseAdvancedOptionSizeMultiplier', function(AppUtils) { else { number = parseInt(parts[0]); - return parts[1]; + if (scope.parseAdvancedOptionSizeMultiplier == 'uppercase') + return parts[1].toUpperCase(); + else if (scope.parseAdvancedOptionSizeMultiplier == 'lowercase') + return parts[1].toLowerCase(); + else + return parts[1]; } } else diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/parseSizeNumber.js b/Duplicati/Server/webroot/ngax/scripts/directives/parseSizeNumber.js index c04504e57..07409b9e6 100644 --- a/Duplicati/Server/webroot/ngax/scripts/directives/parseSizeNumber.js +++ b/Duplicati/Server/webroot/ngax/scripts/directives/parseSizeNumber.js @@ -2,6 +2,9 @@ backupApp.directive('parseSizeNumber', function(AppUtils) { return { restrict: 'A', require: ['ngModel'], + scope: { + parseSizeNumber: '@' + }, link: function(scope, element, attr, ctrl) { var multiplier = null; @@ -17,7 +20,12 @@ backupApp.directive('parseSizeNumber', function(AppUtils) { return null; } - multiplier = parts[1]; + if (scope.parseSizeNumber == 'uppercase') + multiplier = parts[1].toUpperCase(); + else if (scope.parseSizeNumber == 'lowercase') + multiplier = parts[1].toLowerCase(); + else + multiplier = parts[1]; return parts[0]; }); @@ -28,6 +36,9 @@ backupApp.directive('parseSizeNumber', function(AppUtils) { backupApp.directive('parseSizeMultiplier', function(AppUtils) { return { restrict: 'A', + scope: { + parseSizeMultiplier: '@' + }, require: ['ngModel'], link: function(scope, element, attr, ctrl) { @@ -45,7 +56,12 @@ backupApp.directive('parseSizeMultiplier', function(AppUtils) { } number = parts[0]; - return parts[1]; + if (scope.parseSizeMultiplier == 'uppercase') + return parts[1].toUpperCase(); + else if (scope.parseSizeMultiplier == 'lowercase') + return parts[1].toLowerCase(); + else + return parts[1]; }); } }; diff --git a/Duplicati/Server/webroot/ngax/templates/addoredit.html b/Duplicati/Server/webroot/ngax/templates/addoredit.html index 9a34d68d6..775ab16e9 100755 --- a/Duplicati/Server/webroot/ngax/templates/addoredit.html +++ b/Duplicati/Server/webroot/ngax/templates/addoredit.html @@ -152,8 +152,8 @@ - - + @@ -219,12 +219,11 @@

General options

- - + + + +
diff --git a/Duplicati/Server/webroot/ngax/templates/advancedoptionseditor.html b/Duplicati/Server/webroot/ngax/templates/advancedoptionseditor.html index 59c5a93a5..aef38a1aa 100644 --- a/Duplicati/Server/webroot/ngax/templates/advancedoptionseditor.html +++ b/Duplicati/Server/webroot/ngax/templates/advancedoptionseditor.html @@ -11,8 +11,8 @@
- - +