Skip to content

Commit 20f535b

Browse files
Add pfToastNotification and pfToastNotificationList Directives
1 parent 3a718a6 commit 20f535b

File tree

8 files changed

+1005
-21
lines changed

8 files changed

+1005
-21
lines changed

src/notification/notification.js

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ angular.module('patternfly.notification').provider('Notifications', function ()
8383
'use strict';
8484

8585
// time (in ms) the notifications are shown
86-
this.delay = 5000;
86+
this.delay = 8000;
8787
this.verbose = true;
8888
this.notifications = {};
8989
this.persist = {'error': true, 'httpError': true};
@@ -108,18 +108,6 @@ angular.module('patternfly.notification').provider('Notifications', function ()
108108
var verbose = this.verbose;
109109
var persist = this.persist;
110110

111-
var scheduleMessagePop = function () {
112-
$timeout(function () {
113-
var i;
114-
115-
for (i = 0; i < $rootScope.notifications.data.length; i++) {
116-
if (!$rootScope.notifications.data[i].isPersistent) {
117-
$rootScope.notifications.data.splice(i, 1);
118-
}
119-
}
120-
}, delay);
121-
};
122-
123111
var modes = {
124112
info: { type: 'info', header: 'Info!', log: 'info'},
125113
success: { type: 'success', header: 'Success!', log: 'info'},
@@ -138,21 +126,41 @@ angular.module('patternfly.notification').provider('Notifications', function ()
138126
$rootScope.notifications.data = [];
139127
}
140128

141-
notifications.message = function (type, header, message, isPersistent) {
142-
$rootScope.notifications.data.push({
129+
notifications.message = function (type, header, message, isPersistent, closeCallback, actionTitle, actionCallback, menuActions) {
130+
var notification = {
143131
type : type,
144132
header: header,
145133
message : message,
146-
isPersistent: isPersistent
147-
});
134+
isPersistent: isPersistent,
135+
closeCallback: closeCallback,
136+
actionTitle: actionTitle,
137+
actionCallback: actionCallback,
138+
menuActions: menuActions
139+
};
148140

149-
scheduleMessagePop();
150-
};
141+
notification.show = true;
142+
$rootScope.notifications.data.push(notification);
151143

144+
if (!notification.isPersistent) {
145+
notification.viewing = false;
146+
$timeout(function () {
147+
notification.show = false;
148+
if (!notification.viewing) {
149+
notifications.remove(notification);
150+
}
151+
}, delay);
152+
}
153+
};
152154

153155
function createNotifyMethod (mode) {
154-
return function (message) {
155-
notifications.message(modes[mode].type, modes[mode].header, message, persist[mode]);
156+
return function (message, header, persistent, closeCallback, actionTitle, actionCallback, menuActions) {
157+
if (angular.isUndefined(header)) {
158+
header = modes[mode].header;
159+
}
160+
if (angular.isUndefined(persistent)) {
161+
persistent = persist[mode];
162+
}
163+
notifications.message(modes[mode].type, header, message, persistent, closeCallback, actionTitle, actionCallback, menuActions);
156164
if (verbose) {
157165
$log[modes[mode].log](message);
158166
}
@@ -172,6 +180,23 @@ angular.module('patternfly.notification').provider('Notifications', function ()
172180
}
173181
};
174182

183+
notifications.remove = function (notification) {
184+
notifications.removeIndex($rootScope.notifications.data.indexOf(notification));
185+
};
186+
187+
notifications.removeIndex = function (index) {
188+
$rootScope.notifications.remove(index);
189+
};
190+
191+
notifications.setViewing = function (notification, viewing) {
192+
notification.viewing = viewing;
193+
if (!viewing && !notification.show) {
194+
notifications.remove(notification);
195+
}
196+
};
197+
198+
notifications.data = $rootScope.notifications.data;
199+
175200
return notifications;
176201
}];
177202

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/**
2+
* @ngdoc directive
3+
* @name patternfly.notification.directive:pfToastNotificationList
4+
* @restrict A
5+
* @scope
6+
*
7+
* @param {Array} notifications The list of current notifcations to display. Each notification should have the following (see pfToastNotification):
8+
* <ul style='list-style-type: none'>
9+
* <li>.type - (String) The type of the notification message. Allowed value is one of these: 'success','info','danger', 'warning'
10+
* <li>.header - (String) The header to display for the notification (optional)
11+
* <li>.message - (String) The main text message of the notification.
12+
* <li>.actionTitle Text to show for the primary action, optional.
13+
* <li>.actionCallback (function(this notification)) Function to invoke when primary action is selected, optional
14+
* <li>.menuActions Optional list of actions to place in the kebab menu:<br/>
15+
* <ul style='list-style-type: none'>
16+
* <li>.name - (String) The name of the action, displayed on the button
17+
* <li>.actionFn - (function(action, this notification)) Function to invoke when the action selected
18+
* <li>.isDisabled - (Boolean) set to true to disable the action
19+
* <li>.isSeparator - (Boolean) set to true if this is a placehodler for a separator rather than an action
20+
* </ul>
21+
* <li>.isPersistent Flag to show close button for the notification even if showClose is false.
22+
* </ul>
23+
* @param {Boolean} showClose Flag to show the close button on all notifications (not shown if the notification has menu actions)
24+
* @param {function} closeCallback (function(data)) Function to invoke when closes a toast notification
25+
* @param {function} updateViewing (function(boolean, data)) Function to invoke when user is viewing/not-viewing (hovering on) a toast notification
26+
*
27+
* @description
28+
* Using this directive displayes a list of toast notifications
29+
*
30+
* @example
31+
<example module="patternfly.notification">
32+
33+
<file name="index.html">
34+
<div ng-controller="ToastNotificationListDemoCtrl" >
35+
<div pf-toast-notification-list notifications="notifications" show-close="showClose" close-callback="handleClose" update-viewing="updateViewing"></div>
36+
<div class="row example-container">
37+
<div class="col-md-12">
38+
<form class="form-horizontal">
39+
<div class="form-group">
40+
<label class="col-sm-3 control-label" for="type">Show Close buttons:</label>
41+
<div class="col-sm-1">
42+
<input type="checkbox" ng-model="showClose"/>
43+
</div>
44+
</div>
45+
<div class="form-group">
46+
<label class="col-sm-2 control-label" for="type">Type:</label>
47+
<div class="col-sm-10">
48+
<select pf-select ng-model="type" id="type" ng-options="o as o for o in types"></select>
49+
</div>
50+
</div>
51+
<div class="form-group">
52+
<label class="col-sm-2 control-label" for="header">Header:</label>
53+
<div class="col-sm-10">
54+
<input type="text" class="form-control" ng-model="header" id="header"/>
55+
</div>
56+
</div>
57+
<div class="form-group">
58+
<label class="col-sm-2 control-label" for="message">Message:</label>
59+
<div class="col-sm-10">
60+
<input type="text" class="form-control" ng-model="message" id="message"/>
61+
</div>
62+
</div>
63+
<div class="form-group">
64+
<label class="col-sm-2 control-label" for="message">Primary Action:</label>
65+
<div class="col-sm-10">
66+
<input type="text" class="form-control" ng-model="primaryAction" id="primaryAction"/>
67+
</div>
68+
</div>
69+
<div class="form-group">
70+
<label class="col-sm-2 control-label" for="type">Persistent:</label>
71+
<div class="col-sm-1">
72+
<input type="checkbox" ng-model="persistent"/>
73+
</div>
74+
<label class="col-sm-2 control-label" for="type">Show Menu:</label>
75+
<div class="col-sm-2">
76+
<input type="checkbox" ng-model="showMenu"/>
77+
</div>
78+
</div>
79+
<div class="form-group">
80+
<div class="col-sm-12">
81+
<button ng-click="notify()">Add notification - Click me several times</button>
82+
</div>
83+
</div>
84+
</form>
85+
</div>
86+
<div class="col-md-12">
87+
<label class="actions-label">Actions: </label>
88+
</div>
89+
<div class="col-md-12">
90+
<textarea rows="3" class="col-md-12">{{actionText}}</textarea>
91+
</div>
92+
</div>
93+
</div>
94+
</file>
95+
96+
<file name="script.js">
97+
angular.module('patternfly.notification').controller( 'ToastNotificationListDemoCtrl', function( $scope, $rootScope, Notifications ) {
98+
$scope.message = 'Default Message.';
99+
100+
var typeMap = { 'Info': 'info',
101+
'Success': 'success',
102+
'Warning': 'warning',
103+
'Danger': 'danger' };
104+
105+
$scope.types = Object.keys(typeMap);
106+
107+
$scope.type = $scope.types[0];
108+
$scope.header = 'Default header.';
109+
$scope.message = 'Default notification message.';
110+
$scope.showClose = false;
111+
$scope.persistent = false;
112+
113+
$scope.primaryAction = '';
114+
115+
$scope.showMenu = false;
116+
var performAction = function (menuAction, data) {
117+
$scope.actionText += menuAction.name + ": " + data.message + '\n';
118+
};
119+
$scope.menuActions = [
120+
{
121+
name: 'Action',
122+
title: 'Perform an action',
123+
actionFn: performAction
124+
},
125+
{
126+
name: 'Another Action',
127+
title: 'Do something else',
128+
actionFn: performAction
129+
},
130+
{
131+
name: 'Disabled Action',
132+
title: 'Unavailable action',
133+
actionFn: performAction,
134+
isDisabled: true
135+
},
136+
{
137+
name: 'Something Else',
138+
title: '',
139+
actionFn: performAction
140+
},
141+
{
142+
isSeparator: true
143+
},
144+
{
145+
name: 'Grouped Action 1',
146+
title: 'Do something',
147+
actionFn: performAction
148+
},
149+
{
150+
name: 'Grouped Action 2',
151+
title: 'Do something similar',
152+
actionFn: performAction
153+
}
154+
];
155+
156+
$scope.actionText = "";
157+
158+
$scope.handleAction = function (data) {
159+
$scope.actionText = $scope.primaryAction + ": " + data.message + '\n' + $scope.actionText;
160+
};
161+
$scope.handleClose = function (data) {
162+
$scope.actionText = "Closed: " + data.message + '\n'+ $scope.actionText;
163+
Notifications.remove(data);
164+
};
165+
$scope.updateViewing = function (viewing, data) {
166+
Notifications.setViewing(data, viewing);
167+
};
168+
169+
$scope.notify = function () {
170+
Notifications.message (
171+
typeMap[$scope.type],
172+
$scope.header,
173+
$scope.message,
174+
$scope.persistent,
175+
$scope.handleClose,
176+
$scope.primaryAction,
177+
$scope.handleAction,
178+
($scope.showMenu ? $scope.menuActions : undefined)
179+
);
180+
}
181+
182+
$scope.notifications = Notifications.data;
183+
});
184+
</file>
185+
186+
</example>
187+
*/
188+
angular.module('patternfly.notification').directive('pfToastNotificationList', function () {
189+
'use strict';
190+
191+
return {
192+
restrict: 'A',
193+
scope: {
194+
notifications: '=',
195+
showClose: '=?',
196+
closeCallback: '=?',
197+
updateViewing: '=?'
198+
},
199+
templateUrl: 'notification/toast-notification-list.html',
200+
controller: function ($scope) {
201+
$scope.handleClose = function (notification) {
202+
if (angular.isFunction($scope.closeCallback)) {
203+
$scope.closeCallback(notification);
204+
}
205+
};
206+
$scope.handleViewingChange = function (isViewing, notification) {
207+
if (angular.isFunction($scope.updateViewing)) {
208+
$scope.updateViewing(isViewing, notification);
209+
}
210+
};
211+
}
212+
};
213+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<div class="toast-notification-list-pf" data-ng-show="notifications.length > 0">
2+
<div ng-repeat="notification in notifications">
3+
<div pf-toast-notification notification-type="{{notification.type}}"
4+
header="{{notification.header}}"
5+
message="{{notification.message}}"
6+
show-close="{{(showClose || notification.isPersistent === true) && !(notification.menuActions && notification.menuActions.length > 0)}}"
7+
close-callback="handleClose"
8+
action-title="{{notification.actionTitle}}"
9+
action-callback="notification.actionCallback"
10+
menu-actions="notification.menuActions"
11+
update-viewing="handleViewingChange"
12+
data="notification">
13+
</div>
14+
</div>
15+
</div>

0 commit comments

Comments
 (0)