Commit 8f350d39 by Samuel Padgett

Use Patternfly toast notifications for DataService errors

parent 23923bd9
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
"hopscotch": "~0.2.7", "hopscotch": "~0.2.7",
"jquery": "~2.1.4", "jquery": "~2.1.4",
"lodash": "~3.10.1", "lodash": "~3.10.1",
"messenger": "~1.4.1",
"patternfly": "~3.21.0", "patternfly": "~3.21.0",
"uri.js": "~1.18.0" "uri.js": "~1.18.0"
}, },
......
//
// Default messenger included here instead of including messenger.css
// -------------------------------------------------
ul.messenger.messenger-theme-flat {
margin: 0;
padding: 0;
opacity: 1;
.transition(all .2s ease .2s);
> li {
list-style: none;
margin: 0;
padding: 0;
&.messenger-shown {
}
}
.messenger-message {
.clearfix();
&.messenger-hidden {
display: none;
}
.messenger-phrase, .messenger-actions a {
// padding-right: 5px;
}
.messenger-actions {
float: right;
a {
cursor: pointer;
text-decoration: underline;
}
}
ul, ol {
margin: 10px 18px 0;
}
}
&.messenger-fixed {
position: fixed;
z-index: 10000;
.messenger-message {
min-width: 0;
.box-sizing(border-box);
}
.message .messenger-actions {
float: left;
}
&.messenger-on-top {
top: 20px;
}
&.messenger-on-bottom {
bottom: 20px;
}
&.messenger-on-top, &.messenger-on-bottom {
left: 50%;
width: 800px;
margin-left: -400px;
&.messenger-on-right {
right: 20px;
left: auto;
}
&.messenger-on-left {
left: 20px;
margin-left: 0px;
}
}
&.messenger-on-right, &.messenger-on-left {
width: 90%;
.messenger-actions {
float: left;
}
}
@media (min-width: @screen-sm-min) {
&.messenger-on-right {
width: 45%;
}
}
@media (min-width: @screen-lg-min) {
&.messenger-on-right {
width: 35%;
}
}
&.messenger-empty.messenger-fixed.messenger-on-bottom.messenger-on-right {
display: block;
opacity: 0;
bottom: 20%;
}
}
.messenger-spinner {
display: none;
}
.messenger-clickable {
cursor: pointer;
}
}
//
// Messenger Flat Theme modifications
// -------------------------------------------------
ul.messenger-theme-flat {
background-color: transparent;
&.messenger-empty {
display: none;
}
}
@insetBackgroundColor: darken(@gray-darker, 10%);
ul.messenger-theme-flat .messenger-message {
box-shadow: 0 0 6px rgba(0,0,0,.175), inset 0px 1px rgba(255, 255, 255, 0.13), inset 50px 0px 0px @insetBackgroundColor !important;
border-radius: 0 !important;
position: relative;
border: 0px;
margin-bottom: 0px;
font-size: @font-size-base;
background: @gray-darker;
color: #f0f0f0;
font-weight: 500;
padding: 10px 30px 10px 65px;
line-height: 27px;
&:before,
.messenger-message-inner:before {
font-size: 20px;
position: absolute;
left: 15px;
top: 50%;
margin-top: -10px;
font-family: 'PatternFlyIcons-webfont';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.messenger-close {
line-height: 30px;
}
}
ul.messenger-theme-flat .messenger-message .messenger-actions a {
text-decoration: none;
color: #aaaaaa;
background: lighten(@gray-darker, 5%);
}
ul.messenger-theme-flat {
.messenger-message.alert-error {
&:before {
content: @pficon-var-error-circle-o;
color: @brand-danger;
display: inline-block;
}
.messenger-message-inner:before {
background-color: transparent;
}
}
.messenger-message.alert-warning {
&:before {
content: @pficon-var-warning-triangle-o;
color: @brand-warning;
display: inline-block;
left: 14px;
margin-top: -11px;
}
}
.messenger-message.alert-success .messenger-message-inner:before {
color: @brand-success;
content: @pficon-var-ok;
display: inline-block;
background-color: transparent;
}
.messenger-message.alert-info .messenger-message-inner:before {
color: @brand-info;
content: @pficon-var-info;
display: inline-block;
background-color: transparent;
}
}
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
@import "_core.less"; @import "_core.less";
@import "_forms.less"; @import "_forms.less";
@import "_guided-tour.less"; @import "_guided-tour.less";
@import "_messages.less";
@import "_mixins.less"; @import "_mixins.less";
@import "_notifications.less"; @import "_notifications.less";
@import "_ui-select.less"; @import "_ui-select.less";
......
...@@ -1001,7 +1001,7 @@ angular.module('openshiftCommonServices') ...@@ -1001,7 +1001,7 @@ angular.module('openshiftCommonServices')
/* jshint eqeqeq: false, unused: false, expr: true */ /* jshint eqeqeq: false, unused: false, expr: true */
angular.module('openshiftCommonServices') angular.module('openshiftCommonServices')
.factory('DataService', function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Notification, Logger, $timeout, base64, base64util) { .factory('DataService', function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Logger, $timeout, base64, base64util) {
function Data(array) { function Data(array) {
this._data = {}; this._data = {};
...@@ -1405,7 +1405,12 @@ angular.module('openshiftCommonServices') ...@@ -1405,7 +1405,12 @@ angular.module('openshiftCommonServices')
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
} }
deferred.reject({ deferred.reject({
data: data, data: data,
...@@ -1945,7 +1950,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -1945,7 +1950,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
}); });
} }
...@@ -1971,7 +1981,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -1971,7 +1981,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
} }
}; };
...@@ -2156,12 +2171,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -2156,12 +2171,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (this._isTooManyWebsocketRetries(key)) { if (this._isTooManyWebsocketRetries(key)) {
// Show an error notication unless disabled in opts. // Show an error notication unless disabled in opts.
if (_.get(opts, 'errorNotification', true)) { if (_.get(opts, 'errorNotification', true)) {
Notification.error("Server connection interrupted.", { // Use `$rootScope.$emit` instead of NotificationsService directly
id: "websocket_retry_halted", // so that DataService doesn't add a dependency on `openshiftCommonUI`
mustDismiss: true, $rootScope.$emit('addNotification', {
actions: { id: 'websocket_retry_halted',
refresh: {label: "Refresh", action: function() { window.location.reload(); }} type: 'error',
message: 'Server connection interrupted.',
links: [{
label: 'Refresh',
onClick: function() {
window.location.reload();
} }
}]
}); });
} }
return; return;
...@@ -2634,68 +2655,6 @@ angular.module('openshiftCommonServices') ...@@ -2634,68 +2655,6 @@ angular.module('openshiftCommonServices')
}; };
}); });
;'use strict'; ;'use strict';
/* jshint unused: false */
angular.module('openshiftCommonServices')
.factory('Notification', function($rootScope) {
function Notification() {
this.messenger = Messenger({
extraClasses: 'messenger-fixed messenger-on-bottom messenger-on-right',
theme: 'flat',
messageDefaults: {
showCloseButton: true,
hideAfter: 10
}
});
var self = this;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
self.clear();
});
}
// Opts:
// id - if an id is passed only one message with this id will ever be shown
// mustDismiss - the user must explicitly dismiss the message, it will not auto-hide
Notification.prototype.notify = function(type, message, opts) {
opts = opts || {};
var notifyOpts = {
type: type,
// TODO report this issue upstream to messenger, they don't handle messages with invalid html
// they should be escaping it
message: $('<div/>').text(message).html(),
id: opts.id,
actions: opts.actions
};
if (opts.mustDismiss) {
notifyOpts.hideAfter = false;
}
this.messenger.post(notifyOpts);
};
Notification.prototype.success = function(message, opts) {
this.notify("success", message, opts);
};
Notification.prototype.info = function(message, opts) {
this.notify("info", message, opts);
};
Notification.prototype.error = function(message, opts) {
this.notify("error", message, opts);
};
Notification.prototype.warning = function(message, opts) {
this.notify("warning", message, opts);
};
Notification.prototype.clear = function() {
this.messenger.hideAll();
};
return new Notification();
});
;'use strict';
angular.module('openshiftCommonServices') angular.module('openshiftCommonServices')
.factory('ProjectsService', .factory('ProjectsService',
......
...@@ -1446,7 +1446,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -1446,7 +1446,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
this.dismissDelay = 8000; this.dismissDelay = 8000;
this.autoDismissTypes = ['info', 'success']; this.autoDismissTypes = ['info', 'success'];
this.$get = function() { this.$get = function($rootScope) {
var notifications = []; var notifications = [];
var dismissDelay = this.dismissDelay; var dismissDelay = this.dismissDelay;
var autoDismissTypes = this.autoDismissTypes; var autoDismissTypes = this.autoDismissTypes;
...@@ -1459,9 +1459,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -1459,9 +1459,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
return 'hide/notification/' + namespace + '/' + notificationID; return 'hide/notification/' + namespace + '/' + notificationID;
}; };
var addNotification = function (notification, notificationID, namespace) { var addNotification = function (notification) {
if (notificationID && isNotificationPermanentlyHidden(notificationID, namespace)) { if (isNotificationPermanentlyHidden(notification) || isNotificationVisible(notification)) {
notification.hidden = true; return;
} }
notifications.push(notification); notifications.push(notification);
...@@ -1475,8 +1475,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -1475,8 +1475,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
_.take(notifications, 0); _.take(notifications, 0);
}; };
var isNotificationPermanentlyHidden = function (notificationID, namespace) { var isNotificationPermanentlyHidden = function (notification) {
var key = notificationHiddenKey(notificationID, namespace); if (!notification.id) {
return false;
}
var key = notificationHiddenKey(notification.id, notification.namespace);
return localStorage.getItem(key) === 'true'; return localStorage.getItem(key) === 'true';
}; };
...@@ -1485,12 +1489,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -1485,12 +1489,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
localStorage.setItem(key, 'true'); localStorage.setItem(key, 'true');
}; };
// Is there a visible toast notification with the same ID right now?
var isNotificationVisible = function (notification) {
if (!notification.id) {
return false;
}
return _.some(notifications, function(next) {
return !next.hidden && notification.id === next.id;
});
};
var isAutoDismiss = function(notification) { var isAutoDismiss = function(notification) {
return _.find(autoDismissTypes, function(type) { return _.find(autoDismissTypes, function(type) {
return type === notification.type; return type === notification.type;
}); });
}; };
// Also handle `addNotification` events on $rootScope, which is used by DataService.
$rootScope.$on('addNotification', function(event, data) {
addNotification(data);
});
return { return {
addNotification: addNotification, addNotification: addNotification,
getNotifications: getNotifications, getNotifications: getNotifications,
......
...@@ -171,176 +171,6 @@ div.hopscotch-bubble .hopscotch-nav-button.next { ...@@ -171,176 +171,6 @@ div.hopscotch-bubble .hopscotch-nav-button.next {
div.hopscotch-bubble .hopscotch-nav-button.prev { div.hopscotch-bubble .hopscotch-nav-button.prev {
color: #030303; color: #030303;
} }
ul.messenger.messenger-theme-flat {
margin: 0;
padding: 0;
opacity: 1;
-webkit-transition: all 0.2s ease 0.2s;
-o-transition: all 0.2s ease 0.2s;
transition: all 0.2s ease 0.2s;
}
ul.messenger.messenger-theme-flat > li {
list-style: none;
margin: 0;
padding: 0;
}
ul.messenger.messenger-theme-flat .messenger-message:before,
ul.messenger.messenger-theme-flat .messenger-message:after {
content: " ";
display: table;
}
ul.messenger.messenger-theme-flat .messenger-message:after {
clear: both;
}
ul.messenger.messenger-theme-flat .messenger-message.messenger-hidden {
display: none;
}
ul.messenger.messenger-theme-flat .messenger-message .messenger-actions {
float: right;
}
ul.messenger.messenger-theme-flat .messenger-message .messenger-actions a {
cursor: pointer;
text-decoration: underline;
}
ul.messenger.messenger-theme-flat .messenger-message ul,
ul.messenger.messenger-theme-flat .messenger-message ol {
margin: 10px 18px 0;
}
ul.messenger.messenger-theme-flat.messenger-fixed {
position: fixed;
z-index: 10000;
}
ul.messenger.messenger-theme-flat.messenger-fixed .messenger-message {
min-width: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
ul.messenger.messenger-theme-flat.messenger-fixed .message .messenger-actions {
float: left;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-top {
top: 20px;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-bottom {
bottom: 20px;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-top,
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-bottom {
left: 50%;
width: 800px;
margin-left: -400px;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-top.messenger-on-right,
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-bottom.messenger-on-right {
right: 20px;
left: auto;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-top.messenger-on-left,
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-bottom.messenger-on-left {
left: 20px;
margin-left: 0px;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-right,
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-left {
width: 90%;
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-right .messenger-actions,
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-left .messenger-actions {
float: left;
}
@media (min-width: 768px) {
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-right {
width: 45%;
}
}
@media (min-width: 1200px) {
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-on-right {
width: 35%;
}
}
ul.messenger.messenger-theme-flat.messenger-fixed.messenger-empty.messenger-fixed.messenger-on-bottom.messenger-on-right {
display: block;
opacity: 0;
bottom: 20%;
}
ul.messenger.messenger-theme-flat .messenger-spinner {
display: none;
}
ul.messenger.messenger-theme-flat .messenger-clickable {
cursor: pointer;
}
ul.messenger-theme-flat {
background-color: transparent;
}
ul.messenger-theme-flat.messenger-empty {
display: none;
}
ul.messenger-theme-flat .messenger-message {
box-shadow: 0 0 6px rgba(0, 0, 0, 0.175), inset 0px 1px rgba(255, 255, 255, 0.13), inset 50px 0px 0px #0c0c0c !important;
border-radius: 0 !important;
position: relative;
border: 0px;
margin-bottom: 0px;
font-size: 12px;
background: #252525;
color: #f0f0f0;
font-weight: 500;
padding: 10px 30px 10px 65px;
line-height: 27px;
}
ul.messenger-theme-flat .messenger-message:before,
ul.messenger-theme-flat .messenger-message .messenger-message-inner:before {
font-size: 20px;
position: absolute;
left: 15px;
top: 50%;
margin-top: -10px;
font-family: 'PatternFlyIcons-webfont';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
ul.messenger-theme-flat .messenger-message .messenger-close {
line-height: 30px;
}
ul.messenger-theme-flat .messenger-message .messenger-actions a {
text-decoration: none;
color: #aaaaaa;
background: #323232;
}
ul.messenger-theme-flat .messenger-message.alert-error:before {
content: "\e61d";
color: #cc0000;
display: inline-block;
}
ul.messenger-theme-flat .messenger-message.alert-error .messenger-message-inner:before {
background-color: transparent;
}
ul.messenger-theme-flat .messenger-message.alert-warning:before {
content: "\e61c";
color: #ec7a08;
display: inline-block;
left: 14px;
margin-top: -11px;
}
ul.messenger-theme-flat .messenger-message.alert-success .messenger-message-inner:before {
color: #3f9c35;
content: "\e602";
display: inline-block;
background-color: transparent;
}
ul.messenger-theme-flat .messenger-message.alert-info .messenger-message-inner:before {
color: #00659c;
content: "\e604";
display: inline-block;
background-color: transparent;
}
.word-break { .word-break {
word-wrap: break-word; word-wrap: break-word;
word-break: break-word; word-break: break-word;
......
...@@ -2347,7 +2347,7 @@ angular.module('openshiftCommonServices') ...@@ -2347,7 +2347,7 @@ angular.module('openshiftCommonServices')
/* jshint eqeqeq: false, unused: false, expr: true */ /* jshint eqeqeq: false, unused: false, expr: true */
angular.module('openshiftCommonServices') angular.module('openshiftCommonServices')
.factory('DataService', ["$cacheFactory", "$http", "$ws", "$rootScope", "$q", "API_CFG", "APIService", "Notification", "Logger", "$timeout", "base64", "base64util", function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Notification, Logger, $timeout, base64, base64util) { .factory('DataService', ["$cacheFactory", "$http", "$ws", "$rootScope", "$q", "API_CFG", "APIService", "Logger", "$timeout", "base64", "base64util", function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Logger, $timeout, base64, base64util) {
function Data(array) { function Data(array) {
this._data = {}; this._data = {};
...@@ -2751,7 +2751,12 @@ angular.module('openshiftCommonServices') ...@@ -2751,7 +2751,12 @@ angular.module('openshiftCommonServices')
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
} }
deferred.reject({ deferred.reject({
data: data, data: data,
...@@ -3291,7 +3296,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -3291,7 +3296,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
}); });
} }
...@@ -3317,7 +3327,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -3317,7 +3327,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
} }
}; };
...@@ -3502,12 +3517,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -3502,12 +3517,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (this._isTooManyWebsocketRetries(key)) { if (this._isTooManyWebsocketRetries(key)) {
// Show an error notication unless disabled in opts. // Show an error notication unless disabled in opts.
if (_.get(opts, 'errorNotification', true)) { if (_.get(opts, 'errorNotification', true)) {
Notification.error("Server connection interrupted.", { // Use `$rootScope.$emit` instead of NotificationsService directly
id: "websocket_retry_halted", // so that DataService doesn't add a dependency on `openshiftCommonUI`
mustDismiss: true, $rootScope.$emit('addNotification', {
actions: { id: 'websocket_retry_halted',
refresh: {label: "Refresh", action: function() { window.location.reload(); }} type: 'error',
} message: 'Server connection interrupted.',
links: [{
label: 'Refresh',
onClick: function() {
window.location.reload();
}
}]
}); });
} }
return; return;
...@@ -3980,68 +4001,6 @@ angular.module('openshiftCommonServices') ...@@ -3980,68 +4001,6 @@ angular.module('openshiftCommonServices')
}]; }];
}); });
;'use strict'; ;'use strict';
/* jshint unused: false */
angular.module('openshiftCommonServices')
.factory('Notification', ["$rootScope", function($rootScope) {
function Notification() {
this.messenger = Messenger({
extraClasses: 'messenger-fixed messenger-on-bottom messenger-on-right',
theme: 'flat',
messageDefaults: {
showCloseButton: true,
hideAfter: 10
}
});
var self = this;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
self.clear();
});
}
// Opts:
// id - if an id is passed only one message with this id will ever be shown
// mustDismiss - the user must explicitly dismiss the message, it will not auto-hide
Notification.prototype.notify = function(type, message, opts) {
opts = opts || {};
var notifyOpts = {
type: type,
// TODO report this issue upstream to messenger, they don't handle messages with invalid html
// they should be escaping it
message: $('<div/>').text(message).html(),
id: opts.id,
actions: opts.actions
};
if (opts.mustDismiss) {
notifyOpts.hideAfter = false;
}
this.messenger.post(notifyOpts);
};
Notification.prototype.success = function(message, opts) {
this.notify("success", message, opts);
};
Notification.prototype.info = function(message, opts) {
this.notify("info", message, opts);
};
Notification.prototype.error = function(message, opts) {
this.notify("error", message, opts);
};
Notification.prototype.warning = function(message, opts) {
this.notify("warning", message, opts);
};
Notification.prototype.clear = function() {
this.messenger.hideAll();
};
return new Notification();
}]);
;'use strict';
angular.module('openshiftCommonServices') angular.module('openshiftCommonServices')
.factory('ProjectsService', .factory('ProjectsService',
...@@ -4573,7 +4532,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4573,7 +4532,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
this.dismissDelay = 8000; this.dismissDelay = 8000;
this.autoDismissTypes = ['info', 'success']; this.autoDismissTypes = ['info', 'success'];
this.$get = function() { this.$get = ["$rootScope", function($rootScope) {
var notifications = []; var notifications = [];
var dismissDelay = this.dismissDelay; var dismissDelay = this.dismissDelay;
var autoDismissTypes = this.autoDismissTypes; var autoDismissTypes = this.autoDismissTypes;
...@@ -4586,9 +4545,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4586,9 +4545,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
return 'hide/notification/' + namespace + '/' + notificationID; return 'hide/notification/' + namespace + '/' + notificationID;
}; };
var addNotification = function (notification, notificationID, namespace) { var addNotification = function (notification) {
if (notificationID && isNotificationPermanentlyHidden(notificationID, namespace)) { if (isNotificationPermanentlyHidden(notification) || isNotificationVisible(notification)) {
notification.hidden = true; return;
} }
notifications.push(notification); notifications.push(notification);
...@@ -4602,8 +4561,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4602,8 +4561,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
_.take(notifications, 0); _.take(notifications, 0);
}; };
var isNotificationPermanentlyHidden = function (notificationID, namespace) { var isNotificationPermanentlyHidden = function (notification) {
var key = notificationHiddenKey(notificationID, namespace); if (!notification.id) {
return false;
}
var key = notificationHiddenKey(notification.id, notification.namespace);
return localStorage.getItem(key) === 'true'; return localStorage.getItem(key) === 'true';
}; };
...@@ -4612,12 +4575,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4612,12 +4575,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
localStorage.setItem(key, 'true'); localStorage.setItem(key, 'true');
}; };
// Is there a visible toast notification with the same ID right now?
var isNotificationVisible = function (notification) {
if (!notification.id) {
return false;
}
return _.some(notifications, function(next) {
return !next.hidden && notification.id === next.id;
});
};
var isAutoDismiss = function(notification) { var isAutoDismiss = function(notification) {
return _.find(autoDismissTypes, function(type) { return _.find(autoDismissTypes, function(type) {
return type === notification.type; return type === notification.type;
}); });
}; };
// Also handle `addNotification` events on $rootScope, which is used by DataService.
$rootScope.$on('addNotification', function(event, data) {
addNotification(data);
});
return { return {
addNotification: addNotification, addNotification: addNotification,
getNotifications: getNotifications, getNotifications: getNotifications,
...@@ -4628,7 +4607,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4628,7 +4607,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
dismissDelay: dismissDelay, dismissDelay: dismissDelay,
autoDismissTypes: autoDismissTypes autoDismissTypes: autoDismissTypes
}; };
}; }];
this.setDismissDelay = function(delayInMs) { this.setDismissDelay = function(delayInMs) {
this.dismissDelay = delayInMs; this.dismissDelay = delayInMs;
......
...@@ -976,7 +976,7 @@ return data; ...@@ -976,7 +976,7 @@ return data;
}), angular.module("openshiftCommonServices").factory("Constants", function() { }), angular.module("openshiftCommonServices").factory("Constants", function() {
var constants = _.clone(window.OPENSHIFT_CONSTANTS || {}), version = _.clone(window.OPENSHIFT_VERSION || {}); var constants = _.clone(window.OPENSHIFT_CONSTANTS || {}), version = _.clone(window.OPENSHIFT_VERSION || {});
return constants.VERSION = version, constants; return constants.VERSION = version, constants;
}), angular.module("openshiftCommonServices").factory("DataService", [ "$cacheFactory", "$http", "$ws", "$rootScope", "$q", "API_CFG", "APIService", "Notification", "Logger", "$timeout", "base64", "base64util", function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Notification, Logger, $timeout, base64, base64util) { }), angular.module("openshiftCommonServices").factory("DataService", [ "$cacheFactory", "$http", "$ws", "$rootScope", "$q", "API_CFG", "APIService", "Logger", "$timeout", "base64", "base64util", function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Logger, $timeout, base64, base64util) {
function Data(array) { function Data(array) {
this._data = {}, this._objectsByAttribute(array, "metadata.name", this._data); this._data = {}, this._objectsByAttribute(array, "metadata.name", this._data);
} }
...@@ -1156,7 +1156,10 @@ self._isImmutable(resource) && (existingImmutableData ? existingImmutableData.up ...@@ -1156,7 +1156,10 @@ self._isImmutable(resource) && (existingImmutableData ? existingImmutableData.up
}).error(function(data, status, headers, config) { }).error(function(data, status, headers, config) {
if (opts.errorNotification !== !1) { if (opts.errorNotification !== !1) {
var msg = "Failed to get " + resource + "/" + name; var msg = "Failed to get " + resource + "/" + name;
0 !== status && (msg += " (" + status + ")"), Notification.error(msg); 0 !== status && (msg += " (" + status + ")"), $rootScope.$emit("addNotification", {
type:"error",
message:msg
});
} }
deferred.reject({ deferred.reject({
data:data, data:data,
...@@ -1365,7 +1368,10 @@ self._listInFlight(key, !1); ...@@ -1365,7 +1368,10 @@ self._listInFlight(key, !1);
var deferred = self._listDeferred(key); var deferred = self._listDeferred(key);
if (delete self._listDeferredMap[key], deferred.reject(data, status, headers, config), _.get(opts, "errorNotification", !0)) { if (delete self._listDeferredMap[key], deferred.reject(data, status, headers, config), _.get(opts, "errorNotification", !0)) {
var msg = "Failed to list " + resource; var msg = "Failed to list " + resource;
0 !== status && (msg += " (" + status + ")"), Notification.error(msg); 0 !== status && (msg += " (" + status + ")"), $rootScope.$emit("addNotification", {
type:"error",
message:msg
});
} }
}); });
}) :$http({ }) :$http({
...@@ -1379,7 +1385,10 @@ self._listInFlight(key, !1); ...@@ -1379,7 +1385,10 @@ self._listInFlight(key, !1);
var deferred = self._listDeferred(key); var deferred = self._listDeferred(key);
if (delete self._listDeferredMap[key], deferred.reject(data, status, headers, config), _.get(opts, "errorNotification", !0)) { if (delete self._listDeferredMap[key], deferred.reject(data, status, headers, config), _.get(opts, "errorNotification", !0)) {
var msg = "Failed to list " + resource; var msg = "Failed to list " + resource;
0 !== status && (msg += " (" + status + ")"), Notification.error(msg); 0 !== status && (msg += " (" + status + ")"), $rootScope.$emit("addNotification", {
type:"error",
message:msg
});
} }
}); });
}, DataService.prototype._listOpComplete = function(key, resource, context, opts, data) { }, DataService.prototype._listOpComplete = function(key, resource, context, opts, data) {
...@@ -1444,17 +1453,16 @@ if (eventWS !== registeredWS) return void Logger.log("Skipping reopen, eventWS d ...@@ -1444,17 +1453,16 @@ if (eventWS !== registeredWS) return void Logger.log("Skipping reopen, eventWS d
if (this._watchInFlight(key, !1), eventWS.shouldClose) return void Logger.log("Skipping reopen, eventWS was explicitly closed", eventWS); if (this._watchInFlight(key, !1), eventWS.shouldClose) return void Logger.log("Skipping reopen, eventWS was explicitly closed", eventWS);
if (event.wasClean) return void Logger.log("Skipping reopen, clean close", event); if (event.wasClean) return void Logger.log("Skipping reopen, clean close", event);
if (!this._watchCallbacks(key).has()) return void Logger.log("Skipping reopen, no listeners registered for resource/context", resource, context); if (!this._watchCallbacks(key).has()) return void Logger.log("Skipping reopen, no listeners registered for resource/context", resource, context);
if (this._isTooManyWebsocketRetries(key)) return void (_.get(opts, "errorNotification", !0) && Notification.error("Server connection interrupted.", { if (this._isTooManyWebsocketRetries(key)) return void (_.get(opts, "errorNotification", !0) && $rootScope.$emit("addNotification", {
id:"websocket_retry_halted", id:"websocket_retry_halted",
mustDismiss:!0, type:"error",
actions:{ message:"Server connection interrupted.",
refresh:{ links:[ {
label:"Refresh", label:"Refresh",
action:function() { onClick:function() {
window.location.reload(); window.location.reload();
} }
} } ]
}
})); }));
if (this._addWebsocketEvent(key, "close"), eventWS.shouldRelist) { if (this._addWebsocketEvent(key, "close"), eventWS.shouldRelist) {
Logger.log("Relisting for resource/context", resource, context); Logger.log("Relisting for resource/context", resource, context);
...@@ -1703,42 +1711,7 @@ token ? (authLogger.log("LocalStorageUserStore.setToken", token, ttl), localStor ...@@ -1703,42 +1711,7 @@ token ? (authLogger.log("LocalStorageUserStore.setToken", token, ttl), localStor
} }
}; };
} ]; } ];
}), angular.module("openshiftCommonServices").factory("Notification", [ "$rootScope", function($rootScope) { }), angular.module("openshiftCommonServices").factory("ProjectsService", [ "$location", "$q", "AuthService", "DataService", "annotationNameFilter", "AuthorizationService", function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService) {
function Notification() {
this.messenger = Messenger({
extraClasses:"messenger-fixed messenger-on-bottom messenger-on-right",
theme:"flat",
messageDefaults:{
showCloseButton:!0,
hideAfter:10
}
});
var self = this;
$rootScope.$on("$routeChangeStart", function(event, next, current) {
self.clear();
});
}
return Notification.prototype.notify = function(type, message, opts) {
opts = opts || {};
var notifyOpts = {
type:type,
message:$("<div/>").text(message).html(),
id:opts.id,
actions:opts.actions
};
opts.mustDismiss && (notifyOpts.hideAfter = !1), this.messenger.post(notifyOpts);
}, Notification.prototype.success = function(message, opts) {
this.notify("success", message, opts);
}, Notification.prototype.info = function(message, opts) {
this.notify("info", message, opts);
}, Notification.prototype.error = function(message, opts) {
this.notify("error", message, opts);
}, Notification.prototype.warning = function(message, opts) {
this.notify("warning", message, opts);
}, Notification.prototype.clear = function() {
this.messenger.hideAll();
}, new Notification();
} ]), angular.module("openshiftCommonServices").factory("ProjectsService", [ "$location", "$q", "AuthService", "DataService", "annotationNameFilter", "AuthorizationService", function($location, $q, AuthService, DataService, annotationNameFilter, AuthorizationService) {
var cleanEditableAnnotations = function(resource) { var cleanEditableAnnotations = function(resource) {
var paths = [ annotationNameFilter("description"), annotationNameFilter("displayName") ]; var paths = [ annotationNameFilter("description"), annotationNameFilter("displayName") ];
return _.each(paths, function(path) { return _.each(paths, function(path) {
...@@ -1993,27 +1966,34 @@ startTour:startTour, ...@@ -1993,27 +1966,34 @@ startTour:startTour,
cancelTour:cancelTour cancelTour:cancelTour
}; };
}), angular.module("openshiftCommonUI").provider("NotificationsService", function() { }), angular.module("openshiftCommonUI").provider("NotificationsService", function() {
this.dismissDelay = 8e3, this.autoDismissTypes = [ "info", "success" ], this.$get = function() { this.dismissDelay = 8e3, this.autoDismissTypes = [ "info", "success" ], this.$get = [ "$rootScope", function($rootScope) {
var notifications = [], dismissDelay = this.dismissDelay, autoDismissTypes = this.autoDismissTypes, notificationHiddenKey = function(notificationID, namespace) { var notifications = [], dismissDelay = this.dismissDelay, autoDismissTypes = this.autoDismissTypes, notificationHiddenKey = function(notificationID, namespace) {
return namespace ? "hide/notification/" + namespace + "/" + notificationID :"hide/notification/" + notificationID; return namespace ? "hide/notification/" + namespace + "/" + notificationID :"hide/notification/" + notificationID;
}, addNotification = function(notification, notificationID, namespace) { }, addNotification = function(notification) {
notificationID && isNotificationPermanentlyHidden(notificationID, namespace) && (notification.hidden = !0), notifications.push(notification); isNotificationPermanentlyHidden(notification) || isNotificationVisible(notification) || notifications.push(notification);
}, getNotifications = function() { }, getNotifications = function() {
return notifications; return notifications;
}, clearNotifications = function() { }, clearNotifications = function() {
_.take(notifications, 0); _.take(notifications, 0);
}, isNotificationPermanentlyHidden = function(notificationID, namespace) { }, isNotificationPermanentlyHidden = function(notification) {
var key = notificationHiddenKey(notificationID, namespace); if (!notification.id) return !1;
var key = notificationHiddenKey(notification.id, notification.namespace);
return "true" === localStorage.getItem(key); return "true" === localStorage.getItem(key);
}, permanentlyHideNotification = function(notificationID, namespace) { }, permanentlyHideNotification = function(notificationID, namespace) {
var key = notificationHiddenKey(notificationID, namespace); var key = notificationHiddenKey(notificationID, namespace);
localStorage.setItem(key, "true"); localStorage.setItem(key, "true");
}, isNotificationVisible = function(notification) {
return notification.id ? _.some(notifications, function(next) {
return !next.hidden && notification.id === next.id;
}) :!1;
}, isAutoDismiss = function(notification) { }, isAutoDismiss = function(notification) {
return _.find(autoDismissTypes, function(type) { return _.find(autoDismissTypes, function(type) {
return type === notification.type; return type === notification.type;
}); });
}; };
return { return $rootScope.$on("addNotification", function(event, data) {
addNotification(data);
}), {
addNotification:addNotification, addNotification:addNotification,
getNotifications:getNotifications, getNotifications:getNotifications,
clearNotifications:clearNotifications, clearNotifications:clearNotifications,
...@@ -2023,7 +2003,7 @@ isAutoDismiss:isAutoDismiss, ...@@ -2023,7 +2003,7 @@ isAutoDismiss:isAutoDismiss,
dismissDelay:dismissDelay, dismissDelay:dismissDelay,
autoDismissTypes:autoDismissTypes autoDismissTypes:autoDismissTypes
}; };
}, this.setDismissDelay = function(delayInMs) { } ], this.setDismissDelay = function(delayInMs) {
this.dismissDelay = delayInMs; this.dismissDelay = delayInMs;
}, this.setAutoDismissTypes = function(arrayOfTypes) { }, this.setAutoDismissTypes = function(arrayOfTypes) {
this.autoDismissTypes = arrayOfTypes; this.autoDismissTypes = arrayOfTypes;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
/* jshint eqeqeq: false, unused: false, expr: true */ /* jshint eqeqeq: false, unused: false, expr: true */
angular.module('openshiftCommonServices') angular.module('openshiftCommonServices')
.factory('DataService', function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Notification, Logger, $timeout, base64, base64util) { .factory('DataService', function($cacheFactory, $http, $ws, $rootScope, $q, API_CFG, APIService, Logger, $timeout, base64, base64util) {
function Data(array) { function Data(array) {
this._data = {}; this._data = {};
...@@ -406,7 +406,12 @@ angular.module('openshiftCommonServices') ...@@ -406,7 +406,12 @@ angular.module('openshiftCommonServices')
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
} }
deferred.reject({ deferred.reject({
data: data, data: data,
...@@ -946,7 +951,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -946,7 +951,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
}); });
} }
...@@ -972,7 +982,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -972,7 +982,12 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (status !== 0) { if (status !== 0) {
msg += " (" + status + ")"; msg += " (" + status + ")";
} }
Notification.error(msg); // Use `$rootScope.$emit` instead of NotificationsService directly
// so that DataService doesn't add a dependency on `openshiftCommonUI`
$rootScope.$emit('addNotification', {
type: 'error',
message: msg
});
}); });
} }
}; };
...@@ -1157,12 +1172,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR ...@@ -1157,12 +1172,18 @@ DataService.prototype.createStream = function(resource, name, context, opts, isR
if (this._isTooManyWebsocketRetries(key)) { if (this._isTooManyWebsocketRetries(key)) {
// Show an error notication unless disabled in opts. // Show an error notication unless disabled in opts.
if (_.get(opts, 'errorNotification', true)) { if (_.get(opts, 'errorNotification', true)) {
Notification.error("Server connection interrupted.", { // Use `$rootScope.$emit` instead of NotificationsService directly
id: "websocket_retry_halted", // so that DataService doesn't add a dependency on `openshiftCommonUI`
mustDismiss: true, $rootScope.$emit('addNotification', {
actions: { id: 'websocket_retry_halted',
refresh: {label: "Refresh", action: function() { window.location.reload(); }} type: 'error',
} message: 'Server connection interrupted.',
links: [{
label: 'Refresh',
onClick: function() {
window.location.reload();
}
}]
}); });
} }
return; return;
......
'use strict';
/* jshint unused: false */
angular.module('openshiftCommonServices')
.factory('Notification', function($rootScope) {
function Notification() {
this.messenger = Messenger({
extraClasses: 'messenger-fixed messenger-on-bottom messenger-on-right',
theme: 'flat',
messageDefaults: {
showCloseButton: true,
hideAfter: 10
}
});
var self = this;
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
self.clear();
});
}
// Opts:
// id - if an id is passed only one message with this id will ever be shown
// mustDismiss - the user must explicitly dismiss the message, it will not auto-hide
Notification.prototype.notify = function(type, message, opts) {
opts = opts || {};
var notifyOpts = {
type: type,
// TODO report this issue upstream to messenger, they don't handle messages with invalid html
// they should be escaping it
message: $('<div/>').text(message).html(),
id: opts.id,
actions: opts.actions
};
if (opts.mustDismiss) {
notifyOpts.hideAfter = false;
}
this.messenger.post(notifyOpts);
};
Notification.prototype.success = function(message, opts) {
this.notify("success", message, opts);
};
Notification.prototype.info = function(message, opts) {
this.notify("info", message, opts);
};
Notification.prototype.error = function(message, opts) {
this.notify("error", message, opts);
};
Notification.prototype.warning = function(message, opts) {
this.notify("warning", message, opts);
};
Notification.prototype.clear = function() {
this.messenger.hideAll();
};
return new Notification();
});
//
// Default messenger included here instead of including messenger.css
// -------------------------------------------------
ul.messenger.messenger-theme-flat {
margin: 0;
padding: 0;
opacity: 1;
.transition(all .2s ease .2s);
> li {
list-style: none;
margin: 0;
padding: 0;
&.messenger-shown {
}
}
.messenger-message {
.clearfix();
&.messenger-hidden {
display: none;
}
.messenger-phrase, .messenger-actions a {
// padding-right: 5px;
}
.messenger-actions {
float: right;
a {
cursor: pointer;
text-decoration: underline;
}
}
ul, ol {
margin: 10px 18px 0;
}
}
&.messenger-fixed {
position: fixed;
z-index: 10000;
.messenger-message {
min-width: 0;
.box-sizing(border-box);
}
.message .messenger-actions {
float: left;
}
&.messenger-on-top {
top: 20px;
}
&.messenger-on-bottom {
bottom: 20px;
}
&.messenger-on-top, &.messenger-on-bottom {
left: 50%;
width: 800px;
margin-left: -400px;
&.messenger-on-right {
right: 20px;
left: auto;
}
&.messenger-on-left {
left: 20px;
margin-left: 0px;
}
}
&.messenger-on-right, &.messenger-on-left {
width: 90%;
.messenger-actions {
float: left;
}
}
@media (min-width: @screen-sm-min) {
&.messenger-on-right {
width: 45%;
}
}
@media (min-width: @screen-lg-min) {
&.messenger-on-right {
width: 35%;
}
}
&.messenger-empty.messenger-fixed.messenger-on-bottom.messenger-on-right {
display: block;
opacity: 0;
bottom: 20%;
}
}
.messenger-spinner {
display: none;
}
.messenger-clickable {
cursor: pointer;
}
}
//
// Messenger Flat Theme modifications
// -------------------------------------------------
ul.messenger-theme-flat {
background-color: transparent;
&.messenger-empty {
display: none;
}
}
@insetBackgroundColor: darken(@gray-darker, 10%);
ul.messenger-theme-flat .messenger-message {
box-shadow: 0 0 6px rgba(0,0,0,.175), inset 0px 1px rgba(255, 255, 255, 0.13), inset 50px 0px 0px @insetBackgroundColor !important;
border-radius: 0 !important;
position: relative;
border: 0px;
margin-bottom: 0px;
font-size: @font-size-base;
background: @gray-darker;
color: #f0f0f0;
font-weight: 500;
padding: 10px 30px 10px 65px;
line-height: 27px;
&:before,
.messenger-message-inner:before {
font-size: 20px;
position: absolute;
left: 15px;
top: 50%;
margin-top: -10px;
font-family: 'PatternFlyIcons-webfont';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.messenger-close {
line-height: 30px;
}
}
ul.messenger-theme-flat .messenger-message .messenger-actions a {
text-decoration: none;
color: #aaaaaa;
background: lighten(@gray-darker, 5%);
}
ul.messenger-theme-flat {
.messenger-message.alert-error {
&:before {
content: @pficon-var-error-circle-o;
color: @brand-danger;
display: inline-block;
}
.messenger-message-inner:before {
background-color: transparent;
}
}
.messenger-message.alert-warning {
&:before {
content: @pficon-var-warning-triangle-o;
color: @brand-warning;
display: inline-block;
left: 14px;
margin-top: -11px;
}
}
.messenger-message.alert-success .messenger-message-inner:before {
color: @brand-success;
content: @pficon-var-ok;
display: inline-block;
background-color: transparent;
}
.messenger-message.alert-info .messenger-message-inner:before {
color: @brand-info;
content: @pficon-var-info;
display: inline-block;
background-color: transparent;
}
}
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
@import "_core.less"; @import "_core.less";
@import "_forms.less"; @import "_forms.less";
@import "_guided-tour.less"; @import "_guided-tour.less";
@import "_messages.less";
@import "_mixins.less"; @import "_mixins.less";
@import "_notifications.less"; @import "_notifications.less";
@import "_ui-select.less"; @import "_ui-select.less";
......
...@@ -4,7 +4,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -4,7 +4,7 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
this.dismissDelay = 8000; this.dismissDelay = 8000;
this.autoDismissTypes = ['info', 'success']; this.autoDismissTypes = ['info', 'success'];
this.$get = function() { this.$get = function($rootScope) {
var notifications = []; var notifications = [];
var dismissDelay = this.dismissDelay; var dismissDelay = this.dismissDelay;
var autoDismissTypes = this.autoDismissTypes; var autoDismissTypes = this.autoDismissTypes;
...@@ -17,9 +17,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -17,9 +17,9 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
return 'hide/notification/' + namespace + '/' + notificationID; return 'hide/notification/' + namespace + '/' + notificationID;
}; };
var addNotification = function (notification, notificationID, namespace) { var addNotification = function (notification) {
if (notificationID && isNotificationPermanentlyHidden(notificationID, namespace)) { if (isNotificationPermanentlyHidden(notification) || isNotificationVisible(notification)) {
notification.hidden = true; return;
} }
notifications.push(notification); notifications.push(notification);
...@@ -33,8 +33,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -33,8 +33,12 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
_.take(notifications, 0); _.take(notifications, 0);
}; };
var isNotificationPermanentlyHidden = function (notificationID, namespace) { var isNotificationPermanentlyHidden = function (notification) {
var key = notificationHiddenKey(notificationID, namespace); if (!notification.id) {
return false;
}
var key = notificationHiddenKey(notification.id, notification.namespace);
return localStorage.getItem(key) === 'true'; return localStorage.getItem(key) === 'true';
}; };
...@@ -43,12 +47,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function() ...@@ -43,12 +47,28 @@ angular.module('openshiftCommonUI').provider('NotificationsService', function()
localStorage.setItem(key, 'true'); localStorage.setItem(key, 'true');
}; };
// Is there a visible toast notification with the same ID right now?
var isNotificationVisible = function (notification) {
if (!notification.id) {
return false;
}
return _.some(notifications, function(next) {
return !next.hidden && notification.id === next.id;
});
};
var isAutoDismiss = function(notification) { var isAutoDismiss = function(notification) {
return _.find(autoDismissTypes, function(type) { return _.find(autoDismissTypes, function(type) {
return type === notification.type; return type === notification.type;
}); });
}; };
// Also handle `addNotification` events on $rootScope, which is used by DataService.
$rootScope.$on('addNotification', function(event, data) {
addNotification(data);
});
return { return {
addNotification: addNotification, addNotification: addNotification,
getNotifications: getNotifications, getNotifications: getNotifications,
......
...@@ -22,7 +22,6 @@ module.exports = function(config) { ...@@ -22,7 +22,6 @@ module.exports = function(config) {
'bower_components/angular-mocks/angular-mocks.js', 'bower_components/angular-mocks/angular-mocks.js',
"bower_components/angular-sanitize/angular-sanitize.js", "bower_components/angular-sanitize/angular-sanitize.js",
"bower_components/js-logger/src/logger.js", "bower_components/js-logger/src/logger.js",
"bower_components/messenger/build/js/messenger.js",
"bower_components/angular-utf8-base64/angular-utf8-base64.js", "bower_components/angular-utf8-base64/angular-utf8-base64.js",
"bower_components/uri.js/src/URI.js", "bower_components/uri.js/src/URI.js",
"bower_components/uri.js/src/URITemplate.js", "bower_components/uri.js/src/URITemplate.js",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment