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
- 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
  • Loading branch information
benjaminapetersen committed Aug 25, 2017
1 parent cf0278b commit 03fac47
Show file tree
Hide file tree
Showing 24 changed files with 1,187 additions and 42 deletions.
6 changes: 6 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
<!-- Add your site or application content here -->

<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 @@ -190,6 +192,7 @@ <h1>JavaScript Required</h1>

<script src="scripts/constants.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/services/browserStore.js"></script>
<script src="scripts/services/discovery.js"></script>
<script src="scripts/services/applicationGenerator.js"></script>
<script src="scripts/services/navigate.js"></script>
Expand Down Expand Up @@ -233,6 +236,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 @@ -391,6 +395,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
56 changes: 55 additions & 1 deletion app/scripts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ 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: [],

// Currently disables watch on events used by the drawer
DISABLE_GLOBAL_EVENT_WATCH: false,
ENABLE_TECH_PREVIEW_FEATURE: {
// Enable the new landing page and service catalog experience
service_catalog_landing_page: false,
Expand Down Expand Up @@ -139,6 +140,59 @@ 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 }
// or perhaps this, where an event may apply to multiple resources
// (though reuse of events is not super common, this could be overkill):
// Failed: {
// resources: [{ group: 'apps', resource: 'deployments' }],
// 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,
BackOff: true,
Unhealthy: true,
// Image/Pod
Pulling: true,
Pulled: 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
114 changes: 114 additions & 0 deletions app/scripts/directives/notifications/notificationCounter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
'use strict';
(function() {

angular
.module('openshiftConsole')
.component('notificationCounter', {
templateUrl: 'views/directives/notifications/notification-counter.html',
bindings: {},
controller: [
'$filter',
'$routeParams',
'$rootScope',
'AuthService',
'Constants',
NotificationCounter
]
});

function NotificationCounter($filter, $routeParams, $rootScope, AuthService, Constants) {

var counter = this;
var DISABLE_GLOBAL_EVENT_WATCH = _.get(Constants, 'DISABLE_GLOBAL_EVENT_WATCH');
var LIMIT_WATCHES = $filter('isIE')() || $filter('isEdge')();

counter.hide = 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 notificationListeners = [];

var watchNotificationDrawerCount = function(projectName, cb) {
if(!projectName) {
return;
}
notificationListeners.push($rootScope.$on('NotificationDrawerWrapper.count', cb));
};

var deregisterNotificationListeners = function() {
_.each(notificationListeners, function(listener) {
listener && listener();
});
notificationListeners = [];
};

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

var hideIfNoProject = function(projectName) {
if(!projectName) {
counter.hide = true;
} else {
counter.hide = false;
}
};

counter.onClick = function() {
$rootScope.$emit('NotificationDrawerWrapper.toggle');
};

var drawerCountCallback = function(event, newCount) {
// NOTE: unread !== seen. We do not automatically mark
// notifications unread when the drawer is closed.
if(newCount) {
counter.showUnreadNotificationsIndicator = true;
} else {
counter.showUnreadNotificationsIndicator = false;
}
};

var projectChanged = function(next, current) {
return _.get(next, 'params.project') !== _.get(current, 'params.project');
};

var reset = function() {
watchNotificationDrawerCount($routeParams.project, drawerCountCallback);
hideIfNoProject($routeParams.project);
};

var initWatches = function() {
reset();
rootScopeWatches.push($rootScope.$on("$routeChangeSuccess", function (evt, next, current) {
if(projectChanged(next, current)) {
reset();
}
}));

rootScopeWatches.push($rootScope.$on('NotificationDrawerWrapper.onMarkAllRead', function() {
counter.showUnreadNotificationsIndicator = false;
}));
};

counter.$onInit = function() {
if(DISABLE_GLOBAL_EVENT_WATCH || LIMIT_WATCHES) {
counter.hide = true;
return;
}
if (AuthService.isLoggedIn()) {
initWatches();
} else {
AuthService.onUserChanged(initWatches);
}
};

counter.$onDestroy = function() {
deregisterNotificationListeners();
deregisterRootScopeWatches();
};
}
})();
Loading

0 comments on commit 03fac47

Please sign in to comment.