forked from geosolutions-it/MapStore2
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix geosolutions-it#1884. Add cookie policy notification
- Add Notification system - Add cookie policy epic to show the cookie policy notification
- Loading branch information
1 parent
9278b8b
commit e4c076a
Showing
16 changed files
with
428 additions
and
5 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
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,51 @@ | ||
const SHOW_NOTIFICATION = 'SHOW_NOTIFICATION'; | ||
const HIDE_NOTIFICATION = 'HIDE_NOTIFICATION'; | ||
const CLEAR_NOTIFICATIONS = 'CLEAR_NOTIFICATIONS'; | ||
|
||
function show(opts = {}, level = 'success') { | ||
return { | ||
type: SHOW_NOTIFICATION, | ||
...opts, | ||
uid: opts.uid || Date.now(), | ||
level | ||
}; | ||
} | ||
function hide(uid) { | ||
return { | ||
type: HIDE_NOTIFICATION, | ||
uid | ||
}; | ||
} | ||
function success(opts) { | ||
return show(opts, 'success'); | ||
} | ||
|
||
function error(opts) { | ||
return show(opts, 'error'); | ||
} | ||
|
||
function warning(opts) { | ||
return show(opts, 'warning'); | ||
} | ||
|
||
function info(opts) { | ||
return show(opts, 'info'); | ||
} | ||
|
||
function clear() { | ||
return { | ||
type: CLEAR_NOTIFICATIONS | ||
}; | ||
} | ||
module.exports = { | ||
SHOW_NOTIFICATION, | ||
HIDE_NOTIFICATION, | ||
CLEAR_NOTIFICATIONS, | ||
show, | ||
success, | ||
warning, | ||
error, | ||
info, | ||
hide, | ||
clear | ||
}; |
72 changes: 72 additions & 0 deletions
72
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,72 @@ | ||
/* | ||
* 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'); | ||
|
||
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); | ||
}, | ||
shouldComponentUpdate(nextProps) { | ||
return this.props !== nextProps; | ||
}, | ||
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); | ||
}); | ||
}); |
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,58 @@ | ||
/* | ||
* 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 {info, HIDE_NOTIFICATION} = require('../actions/notifications'); | ||
const Rx = require('rxjs'); | ||
const {head} = require('lodash'); | ||
import { UPDATE_LOCATION } from 'react-router-redux'; | ||
|
||
|
||
const COOKIE_NOTIFICATION_ID = "cookiesPolicyNotification"; | ||
const cookieNotificationSelector = (state) => state && state.notifications && head(state.notifications.filter( n => n.uid === COOKIE_NOTIFICATION_ID)); | ||
|
||
/** | ||
* Show the cookie policy notification | ||
* @param {external:Observable} action$ triggers on "UPDATE_LOCATION" | ||
* @param {object} store the store, to get current notifications | ||
* @memberof epics.cookies | ||
* @return {external:Observable} the steam of actions to trigger to display the noitification. | ||
*/ | ||
const cookiePolicyChecker = (action$, store) => | ||
action$.ofType(UPDATE_LOCATION) | ||
.take(1) | ||
.filter( () => !localStorage.getItem("cookies-policy-approved") && !cookieNotificationSelector(store.getState())) | ||
.switchMap(() => | ||
Rx.Observable.of(info({ | ||
uid: COOKIE_NOTIFICATION_ID, | ||
title: "cookiesPolicyNotification.title", | ||
message: "cookiesPolicyNotification.message", | ||
action: { | ||
label: "cookiesPolicyNotification.confirm" | ||
}, | ||
autoDismiss: 0, | ||
position: "bl" | ||
})) | ||
); | ||
|
||
const cookiePolicyDismiss = (action$) => | ||
action$.ofType(HIDE_NOTIFICATION) | ||
.switchMap( (action) => { | ||
if (action.uid === COOKIE_NOTIFICATION_ID ) { | ||
localStorage.setItem("cookies-policy-approved", true); | ||
} | ||
return Rx.Observable.empty(); | ||
}); | ||
|
||
/** | ||
* Epics for cookies policy informations | ||
* @name epics.cookies | ||
* @type {Object} | ||
*/ | ||
module.exports = { | ||
cookiePolicyChecker, | ||
cookiePolicyDismiss | ||
}; |
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,21 @@ | ||
/** | ||
* Copyright 2016, 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 {hide} = require('../actions/notifications'); | ||
const {connect} = require('react-redux'); | ||
|
||
|
||
module.exports = { | ||
NotificationsPlugin: connect( | ||
(state) => ({ notifications: state && state.notifications}), | ||
{onRemove: hide} | ||
)(require('../components/notifications/NotificationContainer')), | ||
reducers: { | ||
notifications: require('../reducers/notifications') | ||
} | ||
}; |
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
Oops, something went wrong.