-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Fix #1884. Add cookie policy notification - Add Notification system - Add cookie policy epic to show the cookie policy notification * add missing dependency * Add documentation * last doc fixes * Removed early optimization and simplified reducers
- Loading branch information
1 parent
553146b
commit 2fadbf1
Showing
20 changed files
with
535 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/* | ||
* Copyright 2017, GeoSolutions Sas. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
var expect = require('expect'); | ||
var { | ||
SHOW_NOTIFICATION, | ||
HIDE_NOTIFICATION, | ||
CLEAR_NOTIFICATIONS, | ||
show, | ||
success, | ||
warning, | ||
error, | ||
info, | ||
hide, | ||
clear | ||
} = require('../notifications'); | ||
|
||
describe('Test correctness of the notifications actions', () => { | ||
|
||
it('show', () => { | ||
const action = show({title: "test"}); | ||
expect(action.type).toBe(SHOW_NOTIFICATION); | ||
expect(action.title).toBe('test'); | ||
expect(action.level).toBe('success'); | ||
expect(action.uid).toExist(); | ||
}); | ||
it('hide', () => { | ||
const action = hide("1234"); | ||
expect(action.type).toBe(HIDE_NOTIFICATION); | ||
expect(action.uid).toBe('1234'); | ||
}); | ||
it('clear', () => { | ||
const action = clear(); | ||
expect(action.type).toBe(CLEAR_NOTIFICATIONS); | ||
}); | ||
it('success', () => { | ||
const action = success({title: "test"}); | ||
expect(action.type).toBe(SHOW_NOTIFICATION); | ||
expect(action.title).toBe('test'); | ||
expect(action.level).toBe('success'); | ||
expect(action.uid).toExist(); | ||
}); | ||
it('warning', () => { | ||
const action = warning({title: "test"}); | ||
expect(action.type).toBe(SHOW_NOTIFICATION); | ||
expect(action.title).toBe('test'); | ||
expect(action.level).toBe('warning'); | ||
expect(action.uid).toExist(); | ||
}); | ||
it('error', () => { | ||
const action = error({title: "test"}); | ||
expect(action.type).toBe(SHOW_NOTIFICATION); | ||
expect(action.title).toBe('test'); | ||
expect(action.level).toBe('error'); | ||
expect(action.uid).toExist(); | ||
}); | ||
it('info', () => { | ||
const action = info({title: "test"}); | ||
expect(action.type).toBe(SHOW_NOTIFICATION); | ||
expect(action.title).toBe('test'); | ||
expect(action.level).toBe('info'); | ||
expect(action.uid).toExist(); | ||
}); | ||
|
||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
const SHOW_NOTIFICATION = 'SHOW_NOTIFICATION'; | ||
const HIDE_NOTIFICATION = 'HIDE_NOTIFICATION'; | ||
const CLEAR_NOTIFICATIONS = 'CLEAR_NOTIFICATIONS'; | ||
/** | ||
* Show a notification | ||
* @memberof actions.notifications | ||
* @param {Object} [opts={}] the notification configuration. [Here the compete ref](https://github.com/igorprado/react-notification-system#creating-a-notification) | ||
* ``` | ||
* { | ||
* title: "title.translation.path" // or the message directly | ||
* message: "message.translation.path" // or the message directly | ||
* uid: "1234" // a unique identifier (if not present, current time is used), | ||
* action: { | ||
* label: "label.translation.path" // or the message directly | ||
* } | ||
* } | ||
* ``` | ||
* @param {String} [level='success'] The level of the notification. (one of "success"|"warning"|"info"|"error") | ||
* @return {object} action of type `SHOW_NOTIFICATION` | ||
*/ | ||
function show(opts = {}, level = 'success') { | ||
return { | ||
type: SHOW_NOTIFICATION, | ||
...opts, | ||
uid: opts.uid || Date.now(), | ||
level | ||
}; | ||
} | ||
|
||
/** | ||
* Hides (removes) the notification with the id provided | ||
* @memberof actions.notifications | ||
* @param {string|number} uid the identifier | ||
* @returns {object} action of type `HIDE_NOTIFICATION` | ||
*/ | ||
function hide(uid) { | ||
return { | ||
type: HIDE_NOTIFICATION, | ||
uid | ||
}; | ||
} | ||
|
||
/** | ||
* Show a success notification. {@see actions.notifications.show} | ||
* @memberof actions.notifications | ||
* @param {object} opts notification opts | ||
* @returns {object} action of type `HIDE_NOTIFICATION` | ||
*/ | ||
function success(opts) { | ||
return show(opts, 'success'); | ||
} | ||
/** | ||
* Show a error notification. {@see actions.notifications.show} | ||
* @memberof actions.notifications | ||
* @param {object} opts notification opts | ||
* @returns {object} action of type `HIDE_NOTIFICATION` | ||
*/ | ||
function error(opts) { | ||
return show(opts, 'error'); | ||
} | ||
|
||
/** | ||
* Show a warning notification. {@see actions.notifications.show} | ||
* @memberof actions.notifications | ||
* @param {object} opts notification opts | ||
* @returns {object} action of type `HIDE_NOTIFICATION` | ||
*/ | ||
function warning(opts) { | ||
return show(opts, 'warning'); | ||
} | ||
|
||
/** | ||
* Show a info notification. {@see actions.notifications.show} | ||
* @memberof actions.notifications | ||
* @param {object} opts notification opts | ||
* @returns {object} action of type `HIDE_NOTIFICATION` | ||
*/ | ||
function info(opts) { | ||
return show(opts, 'info'); | ||
} | ||
|
||
/** | ||
* Clear all the notifications | ||
* @memberof actions.notifications | ||
* @returns {object} action of type `CLEAR_NOTIFICATIONS` | ||
*/ | ||
function clear() { | ||
return { | ||
type: CLEAR_NOTIFICATIONS | ||
}; | ||
} | ||
|
||
/** | ||
* actions for notifications | ||
* @name notifications | ||
* @memberof actions | ||
*/ | ||
module.exports = { | ||
SHOW_NOTIFICATION, | ||
HIDE_NOTIFICATION, | ||
CLEAR_NOTIFICATIONS, | ||
show, | ||
success, | ||
warning, | ||
error, | ||
info, | ||
hide, | ||
clear | ||
}; |
88 changes: 88 additions & 0 deletions
88
web/client/components/notifications/NotificationContainer.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright 2017, GeoSolutions Sas. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
const React = require('react'); | ||
const NotificationSystem = require('react-notification-system'); | ||
var LocaleUtils = require('../../utils/LocaleUtils'); | ||
/** | ||
* Container for Notifications. Allows to display notifications by passing | ||
* them in the notification property | ||
* @class | ||
* @memberof components.notifications | ||
* @prop {object[]} notifications the notifications. Each element have this form | ||
* ``` | ||
* { | ||
* title: "title.translation.path" // or the message directly | ||
* message: "message.translation.path" // or the message directly | ||
* uid: "1234" // a unique identifier (if not present, current time is used), | ||
* action: { | ||
* label: "label.translation.path" // or the message directly | ||
* } | ||
* } | ||
* ``` | ||
* @see https://github.com/igorprado/react-notification-system#creating-a-notification for othe options | ||
* @example | ||
* <NotificationContainer notifications={[{uid: 1, title: "notification", level: "success"}]} />; | ||
*/ | ||
const NotificationContainer = React.createClass({ | ||
propTypes: { | ||
notifications: React.PropTypes.array, | ||
onRemove: React.PropTypes.func | ||
}, | ||
contextTypes: { | ||
messages: React.PropTypes.object | ||
}, | ||
getDefaultProps() { | ||
return { | ||
notifications: [], | ||
onRemove: () => {} | ||
}; | ||
}, | ||
componentDidMount() { | ||
this.updateNotifications(this.props.notifications); | ||
}, | ||
componentDidUpdate() { | ||
const {notifications} = this.props || []; | ||
this.updateNotifications(notifications); | ||
}, | ||
render() { | ||
const {notifications, onRemove, ...rest} = this.props; | ||
return (<NotificationSystem ref="notify" { ...rest } />); | ||
}, | ||
system() { | ||
return this.refs.notify; | ||
}, | ||
updateNotifications(notifications) { | ||
const notificationIds = notifications.map(notification => notification.uid); | ||
const systemNotifications = this.system().state.notifications || []; | ||
// Get all active notifications from react-notification-system | ||
// and remove all where uid is not found in the reducer | ||
systemNotifications.forEach(notification => { | ||
if (notificationIds.indexOf(notification.uid) < 0) { | ||
this.system().removeNotification(notification.uid); | ||
} | ||
}); | ||
notifications.forEach(notification => { | ||
if (systemNotifications.indexOf(notification.uid) < 0) { | ||
this.system().addNotification({ | ||
...notification, | ||
title: LocaleUtils.getMessageById(this.context.messages, notification.title) || notification.title, | ||
message: LocaleUtils.getMessageById(this.context.messages, notification.message) || notification.message, | ||
action: notification.action && { | ||
label: LocaleUtils.getMessageById(this.context.messages, notification.action.label) || notification.action.label | ||
}, | ||
onRemove: () => { | ||
this.props.onRemove(notification.uid); | ||
if (notification.onRemove) notification.onRemove(); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
module.exports = NotificationContainer; |
69 changes: 69 additions & 0 deletions
69
web/client/components/notifications/__tests__/NotificationContainer-test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Copyright 2017, GeoSolutions Sas. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
const React = require('react'); | ||
const ReactDOM = require('react-dom'); | ||
const NotificationContainer = require('../NotificationContainer.jsx'); | ||
const expect = require('expect'); | ||
|
||
const TestUtils = require('react-addons-test-utils'); | ||
const N1 = { | ||
uid: "1", | ||
title: "test 1", | ||
message: "test 1", | ||
autodismiss: 0, | ||
level: "success" | ||
}; | ||
|
||
const N2 = { | ||
uid: "2", | ||
title: "test 2", | ||
message: "test 2", | ||
autodismiss: 0, | ||
level: "success" | ||
}; | ||
|
||
describe('NotificationContainer tests', () => { | ||
beforeEach((done) => { | ||
document.body.innerHTML = '<div id="container"></div>'; | ||
setTimeout(done); | ||
}); | ||
|
||
afterEach((done) => { | ||
ReactDOM.unmountComponentAtNode(document.getElementById("container")); | ||
document.body.innerHTML = ''; | ||
setTimeout(done); | ||
}); | ||
// test DEFAULTS | ||
it('creates the component with defaults', () => { | ||
const item = ReactDOM.render(<NotificationContainer />, document.getElementById("container")); | ||
expect(item).toExist(); | ||
|
||
}); | ||
it('creates the component with notifications', () => { | ||
const item = ReactDOM.render(<NotificationContainer notifications={[N1]} />, document.getElementById("container")); | ||
expect(item).toExist(); | ||
let elems = TestUtils.scryRenderedDOMComponentsWithClass(item, "notifications-tr"); | ||
expect(elems.length).toBe(1); | ||
}); | ||
it('update notifications', () => { | ||
let item = ReactDOM.render(<NotificationContainer notifications={[N1]} />, document.getElementById("container")); | ||
expect(item).toExist(); | ||
let elems = TestUtils.scryRenderedDOMComponentsWithClass(item, "notification"); | ||
expect(elems.length).toBe(1); | ||
|
||
// add notification | ||
item = ReactDOM.render(<NotificationContainer notifications={[N1, N2]} />, document.getElementById("container")); | ||
elems = TestUtils.scryRenderedDOMComponentsWithClass(item, "notification"); | ||
expect(elems.length).toBe(2); | ||
|
||
// remove notification | ||
item = ReactDOM.render(<NotificationContainer notifications={[N2]} />, document.getElementById("container")); | ||
elems = TestUtils.scryRenderedDOMComponentsWithClass(item, "notification").filter( (e) => e.className.indexOf("notification-hidden") < 0); | ||
expect(elems.length).toBe(1); | ||
}); | ||
}); |
Oops, something went wrong.