diff --git a/Duplicati/Server/webroot/ngax/index.html b/Duplicati/Server/webroot/ngax/index.html index 2c671cf24..34b89e4f2 100644 --- a/Duplicati/Server/webroot/ngax/index.html +++ b/Duplicati/Server/webroot/ngax/index.html @@ -42,6 +42,7 @@ + @@ -71,6 +72,7 @@ + @@ -157,6 +159,8 @@ + +
diff --git a/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js b/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js new file mode 100644 index 000000000..ec35268bf --- /dev/null +++ b/Duplicati/Server/webroot/ngax/scripts/directives/notificationArea.js @@ -0,0 +1,53 @@ +backupApp.directive('notificationArea', function() { + return { + restrict: 'E', + templateUrl: 'templates/notificationarea.html', + controller: function($scope, $location, $timeout, NotificationService, ServerStatus, AppService, AppUtils) { + $scope.Notifications = NotificationService.watch($scope); + $scope.state = ServerStatus.watch($scope); + + $scope.doDismiss = function(id) { + AppService.delete('/notification/' + id); + }; + + $scope.doShowLog = function(backupid) { + AppService.get('/backup/' + backupid + '/isactive').then( + function() { + $location.path('/log/' + backupid); + }, + + function(resp) { + + if (resp.status == 404) { + if ((parseInt(backupid) + '') != backupid) + alert('The backup was temporary and does not exist anymore, so the log data is lost'); + else + alert('The backup is missing, has it been delete?'); + } else { + AppUtils.connectionError('Failed to find backup: ', resp); + } + + } + ); + }; + + $scope.doInstallUpdate = function(id) { + AppService.post('/updates/install'); + }; + + $scope.doActivateUpdate = function() { + AppService.post('/updates/activate').then(function() {}, AppUtils.connectionError('Activate failed: ')); + }; + + $scope.doShowUpdate = function(id) { + $location.path('/updatechangelog'); + }; + + $scope.doDownloadBugreport = function(item) { + var id = item.Action.substr('bug-report:created:'.length); + item.DownloadLink = AppService.get_bugreport_url(id); + document.getElementById('notification-download-iframe').src = item.DownloadLink; + }; + } + } +}); \ No newline at end of file diff --git a/Duplicati/Server/webroot/ngax/scripts/services/NotificationService.js b/Duplicati/Server/webroot/ngax/scripts/services/NotificationService.js new file mode 100644 index 000000000..7962e0554 --- /dev/null +++ b/Duplicati/Server/webroot/ngax/scripts/services/NotificationService.js @@ -0,0 +1,85 @@ +backupApp.service('NotificationService', function($rootScope, $timeout, AppService, ServerStatus) { + + // Track repeated refresh requests + var isRefreshing = false; + var needsRefresh = false; + + var notifications = []; + + this.notifications = notifications; + + function refresh_notifications() { + + if (isRefreshing) { + needsRefresh = true; + return; + } + + needsRefresh = false; + isRefreshing = true; + + AppService.get('/notifications').then( + function(resp) { + + var idmap = {}; + for(var n in resp.data) + idmap[resp.data[n].ID] = resp.data[n]; + + // Sync map and list + for (var i = notifications.length - 1; i >= 0; i--) + if (!idmap[notifications[i].ID]) + notifications.splice(i, 1); + else + delete idmap[notifications[i].ID]; + + // Then add all new items + for (var n in idmap) + notifications.push(idmap[n]); + + notifications.sort(function(a, b) { + if (a.ID < b.ID) + return -1; + else if (a.ID > b.ID) + return 1; + else + return 0; + }); + + $rootScope.$broadcast('notificationschanged'); + + isRefreshing = false; + if (needsRefresh) + refresh_notifications(); + + }, + function(resp) { + isRefreshing = false; + } + ); + }; + + this.watch = function(scope, m) { + scope.$on('notificationschanged', function() { + $timeout(function() { + if (m) m(); + scope.$digest(); + }); + }); + + if (m) $timeout(m); + return notifications; + } + + var first = ServerStatus.state.lastNotificationUpdateId == -1; + $rootScope.$on('serverstatechanged.lastNotificationUpdateId', function() { + // We always refresh, so no need to use the initial event + if (first) + first = false; + else + refresh_notifications(); + }); + + this.refresh_notifications = refresh_notifications; + + refresh_notifications(); +}); \ 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 de85586b7..dab44c66e 100644 --- a/Duplicati/Server/webroot/ngax/styles/styles2.css +++ b/Duplicati/Server/webroot/ngax/styles/styles2.css @@ -503,3 +503,69 @@ div.blocker { .themelink { margin-left: 20px; } + +ul.notification { + position: absolute; + bottom: 0px; + left: 0px; + right: 0px; + margin: auto; + width: 300px; +} + +.notification .title { + border: 1px solid #65b1dd; + background-color: #65b1dd; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + padding: 2px; + padding-left: 5px; + padding-right: 5px; + font-weight: bold; + color: lightgray; + width: 100%; + text-align: center; + clear: both; +} + +.notification .content { + background-color: white; + border: 1px solid #65b1dd; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; + padding: 2px; + padding-left: 5px; + padding-right: 5px; + padding-bottom: 30px; + width: 100%; +} + +.notification .message { + width: 100%; + color: black; +} + +.notification .button { + padding: 2px 10px; +} + + +.notification .error .title, .notification .error .content, .notification .error .button { + border-color: red; +} + +.notification .error .title, .notification .error .button { + background-color: red; +} + +.notification .warning .title, .notification .warning .button { + background-color: orange; +} + +.notification .warning .title, .notification .warning .content, .notification .warning .button { + border-color: orange; +} diff --git a/Duplicati/Server/webroot/ngax/templates/notificationarea.html b/Duplicati/Server/webroot/ngax/templates/notificationarea.html new file mode 100644 index 000000000..07f8ba3ae --- /dev/null +++ b/Duplicati/Server/webroot/ngax/templates/notificationarea.html @@ -0,0 +1,58 @@ + + + \ No newline at end of file