diff --git a/Duplicati/Server/webroot/ngax/index.html b/Duplicati/Server/webroot/ngax/index.html index 2a600f88a..78210eb4e 100644 --- a/Duplicati/Server/webroot/ngax/index.html +++ b/Duplicati/Server/webroot/ngax/index.html @@ -52,6 +52,7 @@ + diff --git a/Duplicati/Server/webroot/ngax/scripts/app.js b/Duplicati/Server/webroot/ngax/scripts/app.js index 0ba03b316..fdac05020 100644 --- a/Duplicati/Server/webroot/ngax/scripts/app.js +++ b/Duplicati/Server/webroot/ngax/scripts/app.js @@ -3,7 +3,8 @@ var backupApp = angular.module( [ 'ngRoute', 'btford.modal', - 'dotjem.angular.tree' + 'dotjem.angular.tree', + 'ngSanitize' ] ); diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js index 35df581cf..a1b3c9a25 100644 --- a/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js +++ b/Duplicati/Server/webroot/ngax/scripts/controllers/RestoreController.js @@ -38,193 +38,212 @@ backupApp.controller('RestoreController', function ($scope, $routeParams, $locat for(var t in dateBuckets) if (stamp >= dateBuckets[t].stamp) - return dateBuckets[t].text; + return dateBuckets[t].text; return dt.getFullYear() + ''; }; - $scope.HideEditUri = function() { - $scope.EditUriState = false; - }; + $scope.HideEditUri = function() { + $scope.EditUriState = false; + }; - $scope.doConnect = function() { - $scope.connecting = true; - $scope.ConnectionProgress = 'Registering temporary backup ...'; + $scope.doConnect = function() { + $scope.connecting = true; + $scope.ConnectionProgress = 'Registering temporary backup ...'; - var opts = {}; - var obj = {'Backup': {'TargetURL': $scope.TargetURL } }; + var opts = {}; + var obj = {'Backup': {'TargetURL': $scope.TargetURL } }; - if (($scope.EncryptionPassphrase || '') == '') - opts['--no-encryption'] = 'true'; - else - opts['passphrase'] = $scope.EncryptionPassphrase; + if (($scope.EncryptionPassphrase || '') == '') + opts['--no-encryption'] = 'true'; + else + opts['passphrase'] = $scope.EncryptionPassphrase; - if (!AppUtils.parse_extra_options($scope.ExtendedOptions, opts)) - return false; + if (!AppUtils.parse_extra_options($scope.ExtendedOptions, opts)) + return false; - obj.Backup.Settings = []; - for(var k in opts) { - obj.Backup.Settings.push({ - Name: k, - Value: opts[k] - }); - } + obj.Backup.Settings = []; + for(var k in opts) { + obj.Backup.Settings.push({ + Name: k, + Value: opts[k] + }); + } - AppService.post('/backups?temporary=true', obj, {'headers': {'Content-Type': 'application/json'}}).then( - function(resp) { - $scope.ConnectionProgress = 'Listing backup dates ...'; - $scope.BackupID = resp.data.ID; - $scope.fetchBackupTimes(); - }, function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + AppService.post('/backups?temporary=true', obj, {'headers': {'Content-Type': 'application/json'}}).then( + function(resp) { + $scope.ConnectionProgress = 'Listing backup dates ...'; + $scope.BackupID = resp.data.ID; + $scope.fetchBackupTimes(); + }, function(resp) { + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; - $scope.connecting = false; - $scope.ConnectionProgress = ''; - alert('Failed to connect: ' + message); - } - ); - }; + $scope.connecting = false; + $scope.ConnectionProgress = ''; + alert('Failed to connect: ' + message); + } + ); + }; - $scope.fetchBackupTimes = function() { - AppService.get('/backup/' + $scope.BackupID + '/filesets').then( - function(resp) { - $scope.Filesets = resp.data; + $scope.fetchBackupTimes = function() { + AppService.get('/backup/' + $scope.BackupID + '/filesets').then( + function(resp) { + $scope.Filesets = resp.data; - for(var n in filesetStamps) - delete filesetStamps[n]; + for(var n in filesetStamps) + delete filesetStamps[n]; - for(var n in $scope.Filesets) { - var item = $scope.Filesets[n]; - item.DisplayLabel = item.Version + ': ' + AppUtils.toDisplayDateAndTime(AppUtils.parseDate(item.Time)); - item.GroupLabel = n == 0 ? 'Latests' : createGroupLabel(AppUtils.parseDate(item.Time)); + for(var n in $scope.Filesets) { + var item = $scope.Filesets[n]; + item.DisplayLabel = item.Version + ': ' + AppUtils.toDisplayDateAndTime(AppUtils.parseDate(item.Time)); + item.GroupLabel = n == 0 ? 'Latests' : createGroupLabel(AppUtils.parseDate(item.Time)); - filesetStamps[item.Version + ''] = item.Time; - } + filesetStamps[item.Version + ''] = item.Time; + } - $scope.RestoreVersion = 0; - $scope.restore_step = 1; - $scope.connecting = false; - $scope.ConnectionProgress = ''; + $scope.RestoreVersion = 0; + $scope.restore_step = 1; + $scope.connecting = false; + $scope.ConnectionProgress = ''; - $scope.fetchPathInformation(); - }, + $scope.fetchPathInformation(); + }, - function(resp) { - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + function(resp) { + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; - $scope.connecting = false; - $scope.ConnectionProgress = ''; - alert('Failed to connect: ' + message); - } - ); - }; + $scope.connecting = false; + $scope.ConnectionProgress = ''; + alert('Failed to connect: ' + message); + } + ); + }; - $scope.fetchPathInformation = function() { - var version = $scope.RestoreVersion + ''; + $scope.fetchPathInformation = function() { + var version = $scope.RestoreVersion + ''; - if (inProgress[version] || $scope.restore_step != 1) - return; + if (inProgress[version] || $scope.restore_step != 1) + return; - if (filesetsBuilt[version] == null) { - if ($scope.isTemporaryBackup && filesetsRepaired[version] == null) { - $scope.connecting = true; - $scope.ConnectionProgress = 'Fetching path information ...'; - inProgress[version] = true; + if (filesetsBuilt[version] == null) { + if ($scope.isTemporaryBackup && filesetsRepaired[version] == null) { + $scope.connecting = true; + $scope.ConnectionProgress = 'Fetching path information ...'; + inProgress[version] = true; - AppService.post('/backup/' + $scope.BackupID + '/repairupdate', { 'only-paths': true, 'time': filesetStamps[version + '']}).then( - function(resp) { + AppService.post('/backup/' + $scope.BackupID + '/repairupdate', { 'only-paths': true, 'time': filesetStamps[version + '']}).then( + function(resp) { - var taskid = resp.data.ID; - inProgress[version] = taskid; - $scope.taskid = taskid; + var taskid = resp.data.ID; + inProgress[version] = taskid; + $scope.taskid = taskid; - ServerStatus.callWhenTaskCompletes(taskid, function() { + ServerStatus.callWhenTaskCompletes(taskid, function() { - AppService.get('/task/' + taskid).then(function(resp) { - delete inProgress[version]; - $scope.connecting = false; - $scope.ConnectionProgress = ''; + AppService.get('/task/' + taskid).then(function(resp) { + delete inProgress[version]; + $scope.connecting = false; + $scope.ConnectionProgress = ''; - if (resp.data.Status == 'Completed') - { - filesetsRepaired[version] = true; - $scope.fetchPathInformation(); - } - else - { - alert('Failed to fetch path information: ' + resp.data.ErrorMessage); - } + if (resp.data.Status == 'Completed') + { + filesetsRepaired[version] = true; + $scope.fetchPathInformation(); + } + else + { + alert('Failed to fetch path information: ' + resp.data.ErrorMessage); + } - }, function(resp) { - delete inProgress[version]; - $scope.connecting = false; - $scope.ConnectionProgress = ''; + }, function(resp) { + delete inProgress[version]; + $scope.connecting = false; + $scope.ConnectionProgress = ''; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; - alert('Failed to fetch path information: ' + message); - }); - }); - }, - function(resp) { - delete inProgress[version]; + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; + alert('Failed to fetch path information: ' + message); + }); + }); + }, + function(resp) { + delete inProgress[version]; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; - $scope.connecting = false; - $scope.ConnectionProgress = ''; - alert('Failed to connect: ' + message); - } - ); + $scope.connecting = false; + $scope.ConnectionProgress = ''; + alert('Failed to connect: ' + message); + } + ); - } else { - var stamp = filesetStamps[version]; - $scope.connecting = true; - $scope.ConnectionProgress = 'Fetching path information ...'; - inProgress[version] = true; + } else { + var stamp = filesetStamps[version]; + $scope.connecting = true; + $scope.ConnectionProgress = 'Fetching path information ...'; + inProgress[version] = true; - AppService.get('/backup/' + $scope.BackupID + '/files/*?prefix-only=true&folder-contents=false&time=' + encodeURIComponent(stamp)).then( - function(resp) { - delete inProgress[version]; - $scope.connecting = false; - $scope.ConnectionProgress = ''; + AppService.get('/backup/' + $scope.BackupID + '/files/*?prefix-only=true&folder-contents=false&time=' + encodeURIComponent(stamp)).then( + function(resp) { + delete inProgress[version]; + $scope.connecting = false; + $scope.ConnectionProgress = ''; - filesetsBuilt[version] = resp.data.Files; - $scope.Paths = filesetsBuilt[version]; - }, - function(resp) { - delete inProgress[version]; - var message = resp.statusText; - if (resp.data != null && resp.data.Message != null) - message = resp.data.Message; + filesetsBuilt[version] = resp.data.Files; + $scope.Paths = filesetsBuilt[version]; + }, + function(resp) { + delete inProgress[version]; + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; - $scope.connecting = false; - $scope.ConnectionProgress = ''; - alert('Failed to connect: ' + message); - } - ); - } + $scope.connecting = false; + $scope.ConnectionProgress = ''; + alert('Failed to connect: ' + message); + } + ); + } - } else { - $scope.Paths = filesetsBuilt[version]; - } - }; + } else { + $scope.Paths = filesetsBuilt[version]; + } + }; - $scope.$watch('RestoreVersion', function() { $scope.fetchPathInformation(); }); + $scope.$watch('RestoreVersion', function() { $scope.fetchPathInformation(); }); - $scope.onClickNext = function() { - var results = $scope.treedata.allSelected(); - if (results.length == 0) { - alert('No items to restore, please select one or more items'); - return; - } - } + $scope.onClickNext = function() { + var results = $scope.treedata.allSelected(); + if (results.length == 0) { + alert('No items to restore, please select one or more items'); + return; + } + }; + + $scope.doSearch = function() { + var stamp = filesetStamps[$scope.RestoreVersion + '']; + + AppService.get('/backup/' + $scope.BackupID + '/files/*' + $scope.SearchFilter + '*?prefix-only=false&time=' + encodeURIComponent(stamp)).then( + function(resp) { + //alert(resp.data.Files); + }, + function(resp) { + var message = resp.statusText; + if (resp.data != null && resp.data.Message != null) + message = resp.data.Message; + + $scope.connecting = false; + $scope.ConnectionProgress = ''; + alert('Failed to connect: ' + message); + } + ); + }; }); \ No newline at end of file diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/restoreFilePicker.js b/Duplicati/Server/webroot/ngax/scripts/directives/restoreFilePicker.js index 1810c2759..e6f446ce9 100644 --- a/Duplicati/Server/webroot/ngax/scripts/directives/restoreFilePicker.js +++ b/Duplicati/Server/webroot/ngax/scripts/directives/restoreFilePicker.js @@ -8,7 +8,8 @@ backupApp.directive('restoreFilePicker', function() { ngBackupId: '=', ngTimestamp: '=', treedata: '=', - ngSelected: '=' + ngSelected: '=', + ngSearchFilter: '=' }, templateUrl: 'templates/restorefilepicker.html', diff --git a/Duplicati/Server/webroot/ngax/scripts/filters/highlight.js b/Duplicati/Server/webroot/ngax/scripts/filters/highlight.js new file mode 100644 index 000000000..847bdd497 --- /dev/null +++ b/Duplicati/Server/webroot/ngax/scripts/filters/highlight.js @@ -0,0 +1,16 @@ +// From https://stackoverflow.com/questions/23285196/highlight-search-result-using-angular-js-and-ui-utils +backupApp.filter('highlight', function () { + return function (text, search, caseSensitive) { + if (text && (search || angular.isNumber(search))) { + text = text.toString(); + search = search.toString(); + if (caseSensitive) { + return text.split(search).join('' + search + ''); + } else { + return text.replace(new RegExp(search, 'gi'), '$&'); + } + } else { + return text; + } + }; +}); \ No newline at end of file diff --git a/Duplicati/Server/webroot/ngax/styles/styles2.css b/Duplicati/Server/webroot/ngax/styles/styles2.css index 890805005..b259d9984 100644 --- a/Duplicati/Server/webroot/ngax/styles/styles2.css +++ b/Duplicati/Server/webroot/ngax/styles/styles2.css @@ -334,5 +334,10 @@ body .container .body .content .tasks .tasklist a.action-link { padding-top: 2px; } +.ui-match { + font-weight: bold; + color: darkgreen; +} + diff --git a/Duplicati/Server/webroot/ngax/templates/restore.html b/Duplicati/Server/webroot/ngax/templates/restore.html index 92d295044..e0d400e0c 100644 --- a/Duplicati/Server/webroot/ngax/templates/restore.html +++ b/Duplicati/Server/webroot/ngax/templates/restore.html @@ -6,10 +6,10 @@

Restore files

-
- - -
+
+ + +
@@ -38,9 +38,14 @@
- - + + +
Continue Back diff --git a/Duplicati/Server/webroot/ngax/templates/restorefilepicker.html b/Duplicati/Server/webroot/ngax/templates/restorefilepicker.html index 0e305f3eb..86675d3ad 100644 --- a/Duplicati/Server/webroot/ngax/templates/restorefilepicker.html +++ b/Duplicati/Server/webroot/ngax/templates/restorefilepicker.html @@ -5,7 +5,7 @@ - {{ node.text }} +