From 2d3583fb44a799c2fd2eae48cf92e5bec2ef153e Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Thu, 3 May 2018 11:46:02 -0400 Subject: [PATCH 1/6] Add button to enable desktop notifications --- static/js/pages/user-view.js | 47 ++++++++++++++++++++++ static/js/services/notification-service.js | 32 +++++++++++++++ static/partials/user-view.html | 17 ++++++++ 3 files changed, 96 insertions(+) diff --git a/static/js/pages/user-view.js b/static/js/pages/user-view.js index 4bd387e2d..338b2e25c 100644 --- a/static/js/pages/user-view.js +++ b/static/js/pages/user-view.js @@ -184,5 +184,52 @@ $scope.showBilling = function() { $scope.showBillingCounter++; }; + + + $scope.notificationsPermissionsEnabled = Notification + && Notification.permission === 'granted' + && localStorage.getItem('quay.enabledDesktopNotifications') === 'on'; + + $scope.desktopNotificationsPermissionIsDisabled = () => Notification.permission === 'denied'; + + $scope.toggleDesktopNotifications = () => { + if (!Notification) { // unsupported in IE & some older browsers, we'll just tell the user it's not available + bootbox.dialog({ + "message": 'Desktop Notifications unsupported in this browser', + "title": 'Unsupported Option', + "buttons": { + "close": { + "label": "Close", + "className": "btn-primary" + } + } + }); + + return; + } + + if (localStorage.getItem('quay.enabledDesktopNotifications') === 'on') { + localStorage.setItem('quay.enabledDesktopNotifications', 'off'); + localStorage.removeItem('quay.notifications.mostRecentTimestamp'); + $scope.notificationsPermissionsEnabled = false; + } else { + if (Notification.permission === 'default') { + Notification.requestPermission() + .then((newPermission) => { + if (newPermission === 'granted') { + localStorage.setItem('quay.enabledDesktopNotifications', 'on'); + $scope.notificationsPermissionsEnabled = true; + } else { + $scope.notificationsPermissionsEnabled = false; + } + }); + } else if (Notification.permission === 'granted') { + localStorage.setItem('quay.enabledDesktopNotifications', 'on'); + localStorage.setItem('quay.notifications.mostRecentTimestamp', new Date().getTime().toString()); + $scope.notificationsPermissionsEnabled = true; + } + } + }; + } })(); \ No newline at end of file diff --git a/static/js/services/notification-service.js b/static/js/services/notification-service.js index ff337542e..323a11e3c 100644 --- a/static/js/services/notification-service.js +++ b/static/js/services/notification-service.js @@ -266,6 +266,11 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P notificationService.notifications = resp['notifications']; notificationService.additionalNotifications = resp['additional']; notificationService.notificationClasses = notificationService.getClasses(notificationService.notifications); + + if (notificationService.notifications.length > 0 && localStorage.getItem('quay.enabledDesktopNotifications') === 'on') { + console.log(notificationService); + notificationService.sendBrowserNotifications(); + } }); if (Features.APP_SPECIFIC_TOKENS) { @@ -277,6 +282,33 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P }); } }; + + notificationService.sendBrowserNotifications = () => { + let mostRecentTimestamp = parseInt(localStorage.getItem('quay.notifications.mostRecentTimestamp'), 10); + if (!mostRecentTimestamp) { + mostRecentTimestamp = new Date(notificationService.notifications[0].created).getTime(); + } + + + const newNotifications = notificationService.notifications + .filter(obj => new Date(obj.created).getTime() > mostRecentTimestamp); + + if (newNotifications.length > 0) { + let message = 'You have unread notifications'; + if (newNotifications.length === 1) { + message = notificationService.getMessage(newNotifications[0]); + } + + new Notification(message, { + icon: 'http://quay.io/static/img/quay-logo.png', + image: 'http://quay.io/static/img/quay-logo.png', + }); + + const newTimestamp = new Date(newNotifications[0].created).getTime(); + localStorage.setItem('quay.notifications.mostRecentTimestamp', newTimestamp.toString()); + } + }; + notificationService.reset = function() { $interval.cancel(pollTimerHandle); pollTimerHandle = $interval(notificationService.update, 5 * 60 * 1000 /* five minutes */); diff --git a/static/partials/user-view.html b/static/partials/user-view.html index 93c341d2e..4441934e8 100644 --- a/static/partials/user-view.html +++ b/static/partials/user-view.html @@ -170,6 +170,23 @@ Individual account + + Desktop Notifications: + + Enable Desktop Notifications: + + + Note: Desktop notifications have been disabled in your browser. + + + From 6fe579119b163e002b959847f355140c29ff907b Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Fri, 4 May 2018 17:11:47 -0400 Subject: [PATCH 2/6] Use cookie service and small cleanup for pr --- static/js/pages/user-view.js | 22 +++++++++++----------- static/js/services/notification-service.js | 15 +++++++-------- static/partials/user-view.html | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-) diff --git a/static/js/pages/user-view.js b/static/js/pages/user-view.js index 338b2e25c..ec78f24b7 100644 --- a/static/js/pages/user-view.js +++ b/static/js/pages/user-view.js @@ -10,7 +10,7 @@ }) }]); - function UserViewCtrl($scope, $routeParams, $timeout, ApiService, UserService, UIService, AvatarService, Config, ExternalLoginService) { + function UserViewCtrl($scope, $routeParams, $timeout, ApiService, UserService, UIService, AvatarService, Config, ExternalLoginService, CookieService) { var username = $routeParams.username; $scope.Config = Config; @@ -186,14 +186,14 @@ }; - $scope.notificationsPermissionsEnabled = Notification + $scope.notificationsPermissionsEnabled = window['Notification'] && Notification.permission === 'granted' - && localStorage.getItem('quay.enabledDesktopNotifications') === 'on'; + && CookieService.get('quay.enabledDesktopNotifications') === 'on'; - $scope.desktopNotificationsPermissionIsDisabled = () => Notification.permission === 'denied'; + $scope.desktopNotificationsPermissionIsDisabled = () => window['Notification'] && Notification.permission === 'denied'; $scope.toggleDesktopNotifications = () => { - if (!Notification) { // unsupported in IE & some older browsers, we'll just tell the user it's not available + if (!window['Notification']) { // unsupported in IE & some older browsers, we'll just tell the user it's not available bootbox.dialog({ "message": 'Desktop Notifications unsupported in this browser', "title": 'Unsupported Option', @@ -208,24 +208,24 @@ return; } - if (localStorage.getItem('quay.enabledDesktopNotifications') === 'on') { - localStorage.setItem('quay.enabledDesktopNotifications', 'off'); - localStorage.removeItem('quay.notifications.mostRecentTimestamp'); + if (CookieService.get('quay.enabledDesktopNotifications') === 'on') { + CookieService.putPermanent('quay.enabledDesktopNotifications', 'off'); + CookieService.clear('quay.notifications.mostRecentTimestamp'); $scope.notificationsPermissionsEnabled = false; } else { if (Notification.permission === 'default') { Notification.requestPermission() .then((newPermission) => { if (newPermission === 'granted') { - localStorage.setItem('quay.enabledDesktopNotifications', 'on'); + CookieService.putPermanent('quay.enabledDesktopNotifications', 'on'); $scope.notificationsPermissionsEnabled = true; } else { $scope.notificationsPermissionsEnabled = false; } }); } else if (Notification.permission === 'granted') { - localStorage.setItem('quay.enabledDesktopNotifications', 'on'); - localStorage.setItem('quay.notifications.mostRecentTimestamp', new Date().getTime().toString()); + CookieService.putPermanent('quay.enabledDesktopNotifications', 'on'); + CookieService.putPermanent('quay.notifications.mostRecentTimestamp', new Date().getTime().toString()); $scope.notificationsPermissionsEnabled = true; } } diff --git a/static/js/services/notification-service.js b/static/js/services/notification-service.js index 323a11e3c..94c0b8bad 100644 --- a/static/js/services/notification-service.js +++ b/static/js/services/notification-service.js @@ -3,9 +3,9 @@ * in the sidebar) and provides helper methods for working with them. */ angular.module('quay').factory('NotificationService', - ['$rootScope', '$interval', 'UserService', 'ApiService', 'StringBuilderService', 'PlanService', 'UserService', 'Features', 'Config', '$location', 'VulnerabilityService', + ['$rootScope', '$interval', 'UserService', 'ApiService', 'StringBuilderService', 'PlanService', 'CookieService', 'Features', 'Config', '$location', 'VulnerabilityService', -function($rootScope, $interval, UserService, ApiService, StringBuilderService, PlanService, UserService, Features, Config, $location, VulnerabilityService) { +function($rootScope, $interval, UserService, ApiService, StringBuilderService, PlanService, CookieService, Features, Config, $location, VulnerabilityService) { var notificationService = { 'user': null, 'notifications': [], @@ -267,8 +267,7 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P notificationService.additionalNotifications = resp['additional']; notificationService.notificationClasses = notificationService.getClasses(notificationService.notifications); - if (notificationService.notifications.length > 0 && localStorage.getItem('quay.enabledDesktopNotifications') === 'on') { - console.log(notificationService); + if (notificationService.notifications.length > 0 && CookieService.get('quay.enabledDesktopNotifications') === 'on') { notificationService.sendBrowserNotifications(); } }); @@ -284,7 +283,7 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P }; notificationService.sendBrowserNotifications = () => { - let mostRecentTimestamp = parseInt(localStorage.getItem('quay.notifications.mostRecentTimestamp'), 10); + let mostRecentTimestamp = parseInt(CookieService.get('quay.notifications.mostRecentTimestamp'), 10); if (!mostRecentTimestamp) { mostRecentTimestamp = new Date(notificationService.notifications[0].created).getTime(); } @@ -300,12 +299,12 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P } new Notification(message, { - icon: 'http://quay.io/static/img/quay-logo.png', - image: 'http://quay.io/static/img/quay-logo.png', + icon: window.location.origin + '/static/img/quay-logo.png', + image: window.location.origin + '/static/img/quay-logo.png', }); const newTimestamp = new Date(newNotifications[0].created).getTime(); - localStorage.setItem('quay.notifications.mostRecentTimestamp', newTimestamp.toString()); + CookieService.putPermanent('quay.notifications.mostRecentTimestamp', newTimestamp.toString()); } }; diff --git a/static/partials/user-view.html b/static/partials/user-view.html index 4441934e8..9e3a90dc3 100644 --- a/static/partials/user-view.html +++ b/static/partials/user-view.html @@ -183,7 +183,7 @@ Note: Desktop notifications have been disabled in your browser. + >Note: Desktop notifications have been disabled, or are unavailable, in your browser. From 84ad1d83e19ecc38523b0b17c347366591a52712 Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Mon, 7 May 2018 11:11:33 -0400 Subject: [PATCH 3/6] Add support for Enterprise logos in notifications --- static/js/services/features-config.js | 6 +++++- static/js/services/notification-service.js | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/static/js/services/features-config.js b/static/js/services/features-config.js index c3cb99817..d4a68f32a 100644 --- a/static/js/services/features-config.js +++ b/static/js/services/features-config.js @@ -71,8 +71,12 @@ angular.module('quay').factory('Config', ['Features', function(Features) { return value; }; - config.getEnterpriseLogo = function() { + config.getEnterpriseLogo = function(defaultValue) { if (!config.ENTERPRISE_LOGO_URL) { + if (defaultValue) { + return defaultValue; + } + if (Features.BILLING) { return '/static/img/quay-horizontal-color.svg'; } else { diff --git a/static/js/services/notification-service.js b/static/js/services/notification-service.js index 94c0b8bad..73d70d227 100644 --- a/static/js/services/notification-service.js +++ b/static/js/services/notification-service.js @@ -288,7 +288,6 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P mostRecentTimestamp = new Date(notificationService.notifications[0].created).getTime(); } - const newNotifications = notificationService.notifications .filter(obj => new Date(obj.created).getTime() > mostRecentTimestamp); @@ -299,8 +298,9 @@ function($rootScope, $interval, UserService, ApiService, StringBuilderService, P } new Notification(message, { - icon: window.location.origin + '/static/img/quay-logo.png', - image: window.location.origin + '/static/img/quay-logo.png', + // Chrome doesn't display SVGs for notifications, so we'll use a default if we don't have an enterprise logo + icon: window.location.origin + Config.getEnterpriseLogo('/static/img/quay-logo.png'), + image: window.location.origin + Config.getEnterpriseLogo('/static/img/quay-logo.png'), }); const newTimestamp = new Date(newNotifications[0].created).getTime(); From 7b28f745f7fcb5cca498b21abc5f0e60601e161c Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Mon, 7 May 2018 12:47:29 -0400 Subject: [PATCH 4/6] Update naming of optional parameter --- static/js/services/features-config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/js/services/features-config.js b/static/js/services/features-config.js index d4a68f32a..734b06963 100644 --- a/static/js/services/features-config.js +++ b/static/js/services/features-config.js @@ -71,10 +71,10 @@ angular.module('quay').factory('Config', ['Features', function(Features) { return value; }; - config.getEnterpriseLogo = function(defaultValue) { + config.getEnterpriseLogo = function(opt_defaultValue) { if (!config.ENTERPRISE_LOGO_URL) { - if (defaultValue) { - return defaultValue; + if (opt_defaultValue) { + return opt_defaultValue; } if (Features.BILLING) { From 3a25a7c9e657845caa54de9930e8451251826ae2 Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Tue, 8 May 2018 10:39:10 -0400 Subject: [PATCH 5/6] remove useless props in button --- static/js/pages/user-view.js | 1 + static/partials/user-view.html | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/static/js/pages/user-view.js b/static/js/pages/user-view.js index ec78f24b7..33b31e74b 100644 --- a/static/js/pages/user-view.js +++ b/static/js/pages/user-view.js @@ -218,6 +218,7 @@ .then((newPermission) => { if (newPermission === 'granted') { CookieService.putPermanent('quay.enabledDesktopNotifications', 'on'); + CookieService.putPermanent('quay.notifications.mostRecentTimestamp', new Date().getTime().toString()); $scope.notificationsPermissionsEnabled = true; } else { $scope.notificationsPermissionsEnabled = false; diff --git a/static/partials/user-view.html b/static/partials/user-view.html index 9e3a90dc3..2e48b09e7 100644 --- a/static/partials/user-view.html +++ b/static/partials/user-view.html @@ -174,9 +174,8 @@ Desktop Notifications: Enable Desktop Notifications: - From 5e80e5423ca1a3ddb81623b9cbaa09842ce81bdf Mon Sep 17 00:00:00 2001 From: Sam Chow Date: Tue, 8 May 2018 12:02:52 -0400 Subject: [PATCH 6/6] add button class --- static/partials/user-view.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/static/partials/user-view.html b/static/partials/user-view.html index 2e48b09e7..1ced21c45 100644 --- a/static/partials/user-view.html +++ b/static/partials/user-view.html @@ -174,7 +174,8 @@ Desktop Notifications: Enable Desktop Notifications: -