Skip to content

Commit

Permalink
Fix #2031 Trigger notification if a map is an old one asking for upda…
Browse files Browse the repository at this point in the history
…ting it (#2039)

* Added AutoMapUpdate plugin

* Added auto update map on login

* Added epic to update map info on login

* Set false to title on map update

* Added map version to state
  • Loading branch information
allyoucanmap authored and mbarto committed Jul 27, 2017
1 parent 6a5154e commit cda33c9
Show file tree
Hide file tree
Showing 31 changed files with 537 additions and 24 deletions.
2 changes: 2 additions & 0 deletions docma-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"web/client/reducers/search.js",

"web/client/epics/index.jsdoc",
"web/client/epics/automapupdate.js",
"web/client/epics/cookies.js",
"web/client/epics/fullscreen.js",
"web/client/epics/globeswitcher.js",
Expand All @@ -158,6 +159,7 @@
"jsapi": "web/client/jsapi/MapStore2.js",
"plugins": [
"web/client/plugins/index.jsdoc",
"web/client/plugins/AutoMapUpdate.jsx",
"web/client/plugins/BackgroundSelector.jsx",
"web/client/plugins/BackgroundSwitcher.jsx",
"web/client/plugins/DrawerMenu.jsx",
Expand Down
12 changes: 11 additions & 1 deletion web/client/actions/__tests__/map-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var {
CHANGE_MAP_STYLE,
CHANGE_ROTATION,
CREATION_ERROR_LAYER,
UPDATE_VERSION,
creationError,
changeMapView,
clickOnMap,
Expand All @@ -25,7 +26,8 @@ var {
changeMapCrs,
changeMapScales,
changeMapStyle,
changeRotation
changeRotation,
updateVersion
} = require('../map');

describe('Test correctness of the map actions', () => {
Expand Down Expand Up @@ -121,4 +123,12 @@ describe('Test correctness of the map actions', () => {
expect(retval.rotation).toEqual(angle);
expect(retval.mapStateSource).toEqual(mapStateSource);
});

it('updateVersion', () => {
const version = 2;
const retval = updateVersion(version);
expect(retval).toExist();
expect(retval.type).toEqual(UPDATE_VERSION);
expect(retval.version).toEqual(2);
});
});
12 changes: 11 additions & 1 deletion web/client/actions/__tests__/notifications-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ var {
error,
info,
hide,
clear
clear,
dispatchAction
} = require('../notifications');

describe('Test correctness of the notifications actions', () => {
Expand Down Expand Up @@ -66,6 +67,15 @@ describe('Test correctness of the notifications actions', () => {
expect(action.level).toBe('info');
expect(action.uid).toExist();
});
it('dispatchAction', () => {
const customAction = () => {
return {
type: 'CUSTOM_ACTION'
};
};
const action = dispatchAction(customAction());
expect(action.type).toBe('CUSTOM_ACTION');
});


});
2 changes: 1 addition & 1 deletion web/client/actions/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,4 @@ function loadMapInfo(url, mapId) {
}
module.exports = {MAP_CONFIG_LOADED, MAP_CONFIG_LOAD_ERROR,
MAP_INFO_LOAD_START, MAP_INFO_LOADED, MAP_INFO_LOAD_ERROR,
loadMapConfig, loadMapInfo, configureMap, configureError};
loadMapConfig, loadMapInfo, configureMap, configureError, mapInfoLoaded};
12 changes: 11 additions & 1 deletion web/client/actions/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const CHANGE_MAP_SCALES = 'CHANGE_MAP_SCALES';
const CHANGE_MAP_STYLE = 'CHANGE_MAP_STYLE';
const CHANGE_ROTATION = 'CHANGE_ROTATION';
const CREATION_ERROR_LAYER = 'CREATION_ERROR_LAYER';
const UPDATE_VERSION = 'UPDATE_VERSION';

function creationError(options) {
return {
Expand Down Expand Up @@ -113,6 +114,13 @@ function changeMapStyle(style, mapStateSource) {
mapStateSource
};
}
function updateVersion(version) {
return {
type: UPDATE_VERSION,
version
};
}

module.exports = {
CHANGE_MAP_VIEW,
CLICK_ON_MAP,
Expand All @@ -126,6 +134,7 @@ module.exports = {
CHANGE_ROTATION,
ZOOM_TO_POINT,
CREATION_ERROR_LAYER,
UPDATE_VERSION,
changeMapView,
clickOnMap,
changeMousePointer,
Expand All @@ -137,5 +146,6 @@ module.exports = {
changeMapStyle,
changeRotation,
zoomToPoint,
creationError
creationError,
updateVersion
};
12 changes: 11 additions & 1 deletion web/client/actions/notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ function clear() {
};
}

/**
* Dispatch a custom action on callback
* @memberof actions.notifications
* @returns {object} action
*/
function dispatchAction(action) {
return action;
}

/**
* actions for notifications
* @name notifications
Expand All @@ -105,5 +114,6 @@ module.exports = {
error,
info,
hide,
clear
clear,
dispatchAction
};
2 changes: 1 addition & 1 deletion web/client/actions/security.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function logoutWithReload() {

function login(username, password) {
return (dispatch) => {
AuthenticationAPI.login(username, password).then((response) => {
return AuthenticationAPI.login(username, password).then((response) => {
dispatch(loginSuccess(response, username, password, AuthenticationAPI.authProviderName));
dispatch(loadMaps(false, ConfigUtils.getDefaults().initialMapFilter || "*"));
}).catch((e) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* 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 PropTypes = require('prop-types');
const {ProgressBar, Col, Row} = require('react-bootstrap');
const Message = require('../../../../components/I18N/Message');
require('./css/overlayprogressbar.css');

class OverlayProgressBar extends React.Component {
static propTypes = {
loading: PropTypes.bool,
count: PropTypes.number,
length: PropTypes.number,
label: PropTypes.string,
unit: PropTypes.string
};

static defaultProps = {
loading: false,
count: 0,
length: 0,
label: 'autorefresh.updating',
unit: 'autorefresh.layers'
};

render() {
return this.props.loading ? (
<div className="overlay-spinner-container">
<div>
<Row>
<Col xs={12} className="text-center overlay-spinner-label"><h3><Message msgId={this.props.label}/></h3></Col>
</Row>
<Row>
<Col xs={12}><ProgressBar active now={100 * this.props.count / this.props.length} /></Col>
</Row>
<Row>
<Col xs={12} className="text-center overlay-spinner-label"><h3>{this.props.count + ' '} <Message msgId="autorefresh.of"/>{ ' ' + this.props.length + ' '}<Message msgId={this.props.unit}/></h3></Col>
</Row>
</div>
</div>
) : null;
}
}

module.exports = OverlayProgressBar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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 expect = require('expect');

const React = require('react');
const ReactDOM = require('react-dom');
const OverlayProgressBar = require('../OverlayProgressBar');

describe("test the OverlayProgressBar", () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});

afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';
setTimeout(done);
});

it('test OverlayProgressBar starts loading', () => {
const overlayProgressBar = ReactDOM.render(<OverlayProgressBar loading/>, document.getElementById("container"));
expect(overlayProgressBar).toExist();
const node = ReactDOM.findDOMNode(overlayProgressBar);
expect(node.children.length).toBe(1);
});

it('test OverlayProgressBar stops loading', () => {
const overlayProgressBar = ReactDOM.render(<OverlayProgressBar loading={false}/>, document.getElementById("container"));
expect(overlayProgressBar).toExist();
const node = ReactDOM.findDOMNode(overlayProgressBar);
expect(node).toBe(null);
});

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.overlay-spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9998;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}

.overlay-spinner-container > div {
width: 80%;
}

.overlay-spinner-label {
color: #fff;
}
9 changes: 6 additions & 3 deletions web/client/components/notifications/NotificationContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ var LocaleUtils = require('../../utils/LocaleUtils');
class NotificationContainer extends React.Component {
static propTypes = {
notifications: PropTypes.array,
onRemove: PropTypes.func
onRemove: PropTypes.func,
onDispatch: PropTypes.func
};

static contextTypes = {
Expand All @@ -43,7 +44,8 @@ class NotificationContainer extends React.Component {

static defaultProps = {
notifications: [],
onRemove: () => {}
onRemove: () => {},
onDispatch: () => {}
};

componentDidMount() {
Expand Down Expand Up @@ -81,7 +83,8 @@ class NotificationContainer extends React.Component {
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
label: LocaleUtils.getMessageById(this.context.messages, notification.action.label) || notification.action.label,
callback: notification.action.dispatch ? () => { this.props.onDispatch(notification.action.dispatch); } : notification.action.callback
},
onRemove: () => {
this.props.onRemove(notification.uid);
Expand Down
75 changes: 75 additions & 0 deletions web/client/epics/__tests__/automapupdate-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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');

const configureMockStore = require('redux-mock-store').default;
const {createEpicMiddleware, combineEpics } = require('redux-observable');
const {configureMap, mapInfoLoaded} = require('../../actions/config');
const {loginSuccess} = require('../../actions/security');
const {SHOW_NOTIFICATION} = require('../../actions/notifications');

const {manageAutoMapUpdate, updateMapInfoOnLogin} = require('../automapupdate');
const rootEpic = combineEpics(manageAutoMapUpdate, updateMapInfoOnLogin);
const epicMiddleware = createEpicMiddleware(rootEpic);
const mockStore = configureMockStore([epicMiddleware]);

describe('automapupdate Epics', () => {
let store;
beforeEach(() => {
store = mockStore();
});

afterEach(() => {
epicMiddleware.replaceEpic(rootEpic);
});

it('update map', (done) => {

let configuration = configureMap({}, "id");

let information = mapInfoLoaded({
canEdit: true
}, "id");

store.dispatch(configuration);
store.dispatch(information);

setTimeout( () => {
try {
const actions = store.getActions();
expect(actions.length).toBe(3);
expect(actions[2].type).toBe(SHOW_NOTIFICATION);
} catch (e) {
return done(e);
}
done();
}, 500);

});

it('update map info on login success no id', (done) => {

let login = loginSuccess("userDetails", "username", "password", "authProvider");
let configuration = configureMap({}, "id");

store.dispatch(configuration);
store.dispatch(login);

setTimeout( () => {
try {
const actions = store.getActions();
expect(actions.length).toBe(2);
} catch (e) {
return done(e);
}
done();
}, 500);

});
});
Loading

0 comments on commit cda33c9

Please sign in to comment.