Skip to content

Commit 2fb7ef6

Browse files
Add notification-drawer to show curated list of events to user
- Show events that pass the white list in OPENSHIFT_CONSTANTS.EVENTS_TO_SHOW - Internal Notifications coming in next iteration - Add patternfly.notifications - add notification counter to top bar - add notification event service - add drawer-wrapper as a proxy to pf-notification-drawer - need our own controller for filtering, etc - Update event system to use $rootScope.$emit rather than a custom service - add sessionStorage cache to keep track of read/unread state - Debounce watch in notification service based on work recently done in DataService to support - Update web-common to 0.0.43, includes DataService.watch() flag - Add FEATURE_FLAG.global_event_watch_for_notification_drawer - kill switch in case watching events is too expensive - would still allow internal notifications to appear in drawer - Add link to events page, update index.html - Migrate EVENTS_TO_SHOW map out of EventsService into Constants - Add naviateEventInvolvedObjectURL filter for drawer & events - Update Events service to track read, cleared, namespace SessionStorage, etc - Animate w/a fade-out when a notification is cleared to ensure user notices the subtle change - Add BrowserStorage service - auto namespace openshift- on all Local & Session storage keys - Add links to objects in event-sidebar - Disabled in IE & Edge due to insufficient watches
1 parent cf0278b commit 2fb7ef6

23 files changed

+1229
-93
lines changed

Diff for: app/index.html

+6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
<!-- Add your site or application content here -->
4343

4444
<toast-notifications></toast-notifications>
45+
<notification-drawer-wrapper></notification-drawer-wrapper>
46+
4547
<div ng-view>
4648
<!-- Include default simple nav and shaded background as a placeholder until API discovery finishes -->
4749
<nav class="navbar navbar-pf-alt top-header" role="navigation">
@@ -190,6 +192,7 @@ <h1>JavaScript Required</h1>
190192

191193
<script src="scripts/constants.js"></script>
192194
<script src="scripts/app.js"></script>
195+
<script src="scripts/services/browserStore.js"></script>
193196
<script src="scripts/services/discovery.js"></script>
194197
<script src="scripts/services/applicationGenerator.js"></script>
195198
<script src="scripts/services/navigate.js"></script>
@@ -233,6 +236,7 @@ <h1>JavaScript Required</h1>
233236
<script src="scripts/services/listRowUtils.js"></script>
234237
<script src="scripts/services/ownerReferences.js"></script>
235238
<script src="scripts/controllers/landingPage.js"></script>
239+
<script src="scripts/services/events.js"></script>
236240
<script src="scripts/controllers/projects.js"></script>
237241
<script src="scripts/controllers/pods.js"></script>
238242
<script src="scripts/controllers/pod.js"></script>
@@ -391,6 +395,8 @@ <h1>JavaScript Required</h1>
391395
<script src="scripts/directives/affix.js"></script>
392396
<script src="scripts/directives/editEnvironmentVariables.js"></script>
393397
<script src="scripts/directives/initContainersSummary.js"></script>
398+
<script src="scripts/directives/notifications/notificationCounter.js"></script>
399+
<script src="scripts/directives/notifications/notificationDrawerWrapper.js"></script>
394400
<script src="scripts/filters/date.js"></script>
395401
<script src="scripts/filters/resources.js"></script>
396402
<script src="scripts/filters/canI.js"></script>

Diff for: app/scripts/app.js

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ angular
2222
'patternfly.charts',
2323
'patternfly.navigation',
2424
'patternfly.sort',
25+
'patternfly.notification',
2526
'openshiftConsoleTemplates',
2627
'ui.ace',
2728
'extension-registry',

Diff for: app/scripts/constants.js

+55-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
8484

8585
// This blacklist hides certain kinds from the "Other Resources" page because they are unpersisted, disallowed for most end users, or not supported by openshift but exist in kubernetes
8686
AVAILABLE_KINDS_BLACKLIST: [],
87-
87+
// Currently disables watch on events used by the drawer
88+
DISABLE_GLOBAL_EVENT_WATCH: false,
8889
ENABLE_TECH_PREVIEW_FEATURE: {
8990
// Enable the new landing page and service catalog experience
9091
service_catalog_landing_page: false,
@@ -139,6 +140,59 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
139140
{resource: 'services', group: ''},
140141
{resource: 'statefulsets', group: 'apps'}
141142
],
143+
// TODO:
144+
// This map can drive both the drawer & toast messages by
145+
// updating it to the following format:
146+
// { drawer: true, toast: true }
147+
// or perhaps this, where an event may apply to multiple resources
148+
// (though reuse of events is not super common, this could be overkill):
149+
// Failed: {
150+
// resources: [{ group: 'apps', resource: 'deployments' }],
151+
// drawer: true,
152+
// toast: true
153+
// }
154+
// TODO: Also consider an API_OBJECTS_TO_IGNORE
155+
// map that can blacklist some, for example, if FailedCreate
156+
// applies to many but we don't want to see all.
157+
EVENTS_TO_SHOW: {
158+
// CRUD events that apply to more than one api object
159+
FailedCreate: true,
160+
FailedDelete: true,
161+
FailedUpdate: true,
162+
// Build
163+
BuildStarted: true,
164+
BuildCompleted: true,
165+
BuildFailed: true,
166+
BuildCancelled: true,
167+
// BuildConfig
168+
//
169+
// Deployment
170+
Failed: true,
171+
ScalingReplicaSet: true,
172+
DeploymentCancelled: true,
173+
// DeploymentConfig
174+
DeploymentCreated: true,
175+
DeploymentCreationFailed: true,
176+
// Pod
177+
FailedSync: true,
178+
BackOff: true,
179+
Unhealthy: true,
180+
// Image/Pod
181+
Pulling: true,
182+
Pulled: true,
183+
// SuccessfulDelete: true,
184+
// Cron
185+
//
186+
// PodAutoscaler
187+
SuccessfulRescale: true,
188+
FailedRescale: true,
189+
// Service
190+
LoadBalancerUpdateFailed: true,
191+
// PVC
192+
VolumeDeleted: true,
193+
FailedBinding: true,
194+
ProvisioningFailed: true
195+
},
142196

143197
// href's will be prefixed with /project/{{projectName}} unless they are absolute URLs
144198
PROJECT_NAVIGATION: [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
'use strict';
2+
(function() {
3+
4+
angular
5+
.module('openshiftConsole')
6+
.component('notificationCounter', {
7+
templateUrl: 'views/directives/notifications/notification-counter.html',
8+
bindings: {},
9+
controller: [
10+
'$filter',
11+
'$routeParams',
12+
'$rootScope',
13+
'Constants',
14+
NotificationCounter
15+
]
16+
});
17+
18+
function NotificationCounter($filter, $routeParams, $rootScope, Constants) {
19+
20+
var counter = this;
21+
var DISABLE_GLOBAL_EVENT_WATCH = _.get(Constants, 'DISABLE_GLOBAL_EVENT_WATCH');
22+
var LIMIT_WATCHES = $filter('isIE')() || $filter('isEdge')();
23+
24+
counter.hide = true;
25+
26+
var rootScopeWatches = [];
27+
// this one is treated separately from the rootScopeWatches as
28+
// it may need to be updated outside of the lifecycle of init/destroy
29+
var notificationListeners = [];
30+
31+
var watchNotificationDrawerCount = function(projectName, cb) {
32+
if(!projectName) {
33+
return;
34+
}
35+
notificationListeners.push($rootScope.$on('NotificationDrawerWrapper.count', cb));
36+
};
37+
38+
var deregisterNotificationListeners = function() {
39+
_.each(notificationListeners, function(listener) {
40+
listener && listener();
41+
});
42+
notificationListeners = [];
43+
};
44+
45+
var deregisterRootScopeWatches = function() {
46+
_.each(rootScopeWatches, function(deregister) {
47+
deregister();
48+
});
49+
rootScopeWatches = [];
50+
};
51+
52+
var hideIfNoProject = function(projectName) {
53+
if(!projectName) {
54+
counter.hide = true;
55+
} else {
56+
counter.hide = false;
57+
}
58+
};
59+
60+
counter.onClick = function() {
61+
$rootScope.$emit('NotificationDrawerWrapper.toggle');
62+
};
63+
64+
var drawerCountCallback = function(event, newCount) {
65+
// NOTE: unread !== seen. We do not automatically mark
66+
// notifications unread when the drawer is closed.
67+
if(newCount) {
68+
counter.showUnreadNotificationsIndicator = true;
69+
} else {
70+
counter.showUnreadNotificationsIndicator = false;
71+
}
72+
};
73+
74+
var projectChanged = function(next, current) {
75+
return _.get(next, 'params.project') !== _.get(current, 'params.project');
76+
};
77+
78+
var reset = function() {
79+
watchNotificationDrawerCount($routeParams.project, drawerCountCallback);
80+
hideIfNoProject($routeParams.project);
81+
};
82+
83+
var initWatches = function() {
84+
reset();
85+
rootScopeWatches.push($rootScope.$on("$routeChangeSuccess", function (evt, next, current) {
86+
if(projectChanged(next, current)) {
87+
reset();
88+
}
89+
}));
90+
91+
rootScopeWatches.push($rootScope.$on('NotificationDrawerWrapper.onMarkAllRead', function() {
92+
counter.showUnreadNotificationsIndicator = false;
93+
}));
94+
};
95+
96+
counter.$onInit = function() {
97+
if(DISABLE_GLOBAL_EVENT_WATCH || LIMIT_WATCHES) {
98+
counter.hide = true;
99+
return;
100+
}
101+
initWatches();
102+
};
103+
104+
counter.$onDestroy = function() {
105+
deregisterNotificationListeners();
106+
deregisterRootScopeWatches();
107+
};
108+
}
109+
})();

0 commit comments

Comments
 (0)