Skip to content

Commit

Permalink
Add notification-drawer to show curated list of events to user
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
benjaminapetersen committed Aug 7, 2017
1 parent 3130e60 commit 52a0764
Show file tree
Hide file tree
Showing 15 changed files with 647 additions and 7 deletions.
7 changes: 6 additions & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
<body class="console-os">
<!-- Add your site or application content here -->

<toast-notifications></toast-notifications>
<toast-notifications></toast-notifications>
<notification-drawer-wrapper></notification-drawer-wrapper>

<div ng-view>
<!-- Include default simple nav and shaded background as a placeholder until API discovery finishes -->
<nav class="navbar navbar-pf-alt top-header" role="navigation">
Expand Down Expand Up @@ -232,6 +234,7 @@ <h1>JavaScript Required</h1>
<script src="scripts/services/listRowUtils.js"></script>
<script src="scripts/services/ownerReferences.js"></script>
<script src="scripts/controllers/landingPage.js"></script>
<script src="scripts/services/events.js"></script>
<script src="scripts/controllers/projects.js"></script>
<script src="scripts/controllers/pods.js"></script>
<script src="scripts/controllers/pod.js"></script>
Expand Down Expand Up @@ -389,6 +392,8 @@ <h1>JavaScript Required</h1>
<script src="scripts/directives/affix.js"></script>
<script src="scripts/directives/editEnvironmentVariables.js"></script>
<script src="scripts/directives/initContainersSummary.js"></script>
<script src="scripts/directives/notifications/notificationCounter.js"></script>
<script src="scripts/directives/notifications/notificationDrawerWrapper.js"></script>
<script src="scripts/filters/date.js"></script>
<script src="scripts/filters/resources.js"></script>
<script src="scripts/filters/canI.js"></script>
Expand Down
1 change: 1 addition & 0 deletions app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ angular
'patternfly.charts',
'patternfly.navigation',
'patternfly.sort',
'patternfly.notification',
'openshiftConsoleTemplates',
'ui.ace',
'extension-registry',
Expand Down
47 changes: 46 additions & 1 deletion app/scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {

// 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
AVAILABLE_KINDS_BLACKLIST: [],

// Kill switches for features that are not in tech-preview
FEATURE_FLAGS: {
// The long running watch on events may be extremely expensive.
global_event_watch_for_notification_drawer: true
},
ENABLE_TECH_PREVIEW_FEATURE: {
// Enable the new landing page and service catalog experience
service_catalog_landing_page: false,
Expand Down Expand Up @@ -139,6 +143,47 @@ angular.extend(window.OPENSHIFT_CONSTANTS, {
{resource: 'services', group: ''},
{resource: 'statefulsets', group: 'apps'}
],
// TODO:
// This map can drive both the drawer & toast messages by
// updating it to the following format:
// { drawer: true, toast: true }
// TODO: Also consider an API_OBJECTS_TO_IGNORE
// map that can blacklist some, for example, if FailedCreate
// applies to many but we don't want to see all.
EVENTS_TO_SHOW: {
// CRUD events that apply to more than one api object
FailedCreate: true,
FailedDelete: true,
FailedUpdate: true,
// Build
BuildStarted: true,
BuildCompleted: true,
BuildFailed: true,
BuildCancelled: true,
// BuildConfig
//
// Deployment
Failed: true,
ScalingReplicaSet: true,
DeploymentCancelled: true,
// DeploymentConfig
DeploymentCreated: true,
DeploymentCreationFailed: true,
// Pod
FailedSync: true,
// SuccessfulDelete: true,
// Cron
//
// PodAutoscaler
SuccessfulRescale: true,
FailedRescale: true,
// Service
LoadBalancerUpdateFailed: true,
// PVC
VolumeDeleted: true,
FailedBinding: true,
ProvisioningFailed: true
},

// href's will be prefixed with /project/{{projectName}} unless they are absolute URLs
PROJECT_NAVIGATION: [
Expand Down
98 changes: 98 additions & 0 deletions app/scripts/directives/notifications/notificationCounter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use strict';

angular
.module('openshiftConsole')
.component('notificationCounter', {
templateUrl: 'views/directives/notifications/notification-counter.html',
bindings: {},
controller: [
'$routeParams',
'$rootScope',
'Constants',
'DataService',
function($routeParams, $rootScope, Constants, DataService) {
var ENABLE_EVENT_WATCH = _.get(Constants, 'FEATURE_FLAGS.global_event_watch_for_notification_drawer');
var counter = this;
var drawerHidden = true;

var rootScopeWatches = [];
// this one is treated separately from the rootScopeWatches as
// it may need to be updated outside of the lifecycle of init/destroy
var notificationListener;

var eventsWatcher;

var deregisterEventsWatch = function() {
if(eventsWatcher) {
DataService.unwatch(eventsWatcher);
}
};

var watchEvents = function(projectName, cb) {
if(projectName && ENABLE_EVENT_WATCH) {
eventsWatcher = DataService.watch('events', {namespace: projectName}, _.debounce(cb, 50), { skipDigest: true });
}
};

var watchNotifications = function(projectName, cb) {
if(!projectName) {
return;
}
notificationListener = $rootScope.$on('NotificationsService.onNotificationAdded', cb);
};

var deregisterNotificationListener = function() {
notificationListener && notificationListener();
};

var deregisterRootScopeWatches = function() {
_.each(rootScopeWatches, function(deregister) {
deregister();
});
};

// TODO: since the current IMPL of the drawer doesn't support a "global"
// empty state, need to hide the bell icon entirely if there are no messages
// for a project. Otherwise, you open to get a blank panel. Thats not ideal.
var toggleVisibility = function(projectName) {
if(!projectName) {
counter.hide = true;
}
counter.showNewNotificationIndicator = true;
};

counter.onClick = function() {
drawerHidden = !drawerHidden;
counter.showNewNotificationIndicator = false;
$rootScope.$emit('notification-drawer:show', {
drawerHidden: drawerHidden
});
};

var genericEventCallback = function() {
counter.showNewNotificationIndicator = true;
};

var reset = function() {
deregisterEventsWatch();
deregisterNotificationListener();
watchEvents($routeParams.project, genericEventCallback);
watchNotifications($routeParams.project, genericEventCallback);
toggleVisibility($routeParams.project);
};

counter.$onInit = function() {
reset();
rootScopeWatches.push($rootScope.$on("$routeChangeSuccess", function () {
reset();
}));
};

counter.$onDestroy = function() {
deregisterEventsWatch();
deregisterNotificationListener();
deregisterRootScopeWatches();
};
}
]
});
Loading

0 comments on commit 52a0764

Please sign in to comment.