-
Notifications
You must be signed in to change notification settings - Fork 410
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #2031 Trigger notification if a map is an old one asking for updating it #2039
Changes from 4 commits
61d6432
15414ae
fd24737
10b7fff
95b8140
c528849
607dc51
32f9105
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -90,6 +90,15 @@ function clear() { | |
}; | ||
} | ||
|
||
/** | ||
* Dispatch a custom action on callback | ||
* @memberof actions.notifications | ||
* @returns {object} action | ||
*/ | ||
function dispatchAction(action) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure this is needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's needed because we need to send custom action when the notification button has been toggled |
||
return action; | ||
} | ||
|
||
/** | ||
* actions for notifications | ||
* @name notifications | ||
|
@@ -105,5 +114,6 @@ module.exports = { | |
error, | ||
info, | ||
hide, | ||
clear | ||
clear, | ||
dispatchAction | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ const AuthenticationAPI = require('../api/GeoStoreDAO'); | |
const SecurityUtils = require('../utils/SecurityUtils'); | ||
|
||
const {loadMaps} = require('./maps'); | ||
const {loadMapInfo} = require('./config'); | ||
const ConfigUtils = require('../utils/ConfigUtils'); | ||
|
||
const LOGIN_SUBMIT = 'LOGIN_SUBMIT'; | ||
|
@@ -67,10 +68,15 @@ function logoutWithReload() { | |
} | ||
|
||
function login(username, password) { | ||
return (dispatch) => { | ||
AuthenticationAPI.login(username, password).then((response) => { | ||
return (dispatch, state) => { | ||
return AuthenticationAPI.login(username, password).then((response) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This refreshes can go easily in an epic. Doing it here can cause unwanted side effects. You should monitor the login/logout actions to reload MapInfo, until you change page. |
||
dispatch(loginSuccess(response, username, password, AuthenticationAPI.authProviderName)); | ||
dispatch(loadMaps(false, ConfigUtils.getDefaults().initialMapFilter || "*")); | ||
let s = state(); | ||
let id = s.map && s.map.present && s.map.present.mapId; | ||
if (id) { | ||
dispatch(loadMapInfo(ConfigUtils.getConfigProp("geoStoreUrl") + "extjs/resource/" + id, id)); | ||
} | ||
}).catch((e) => { | ||
dispatch(loginFail(e)); | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
const PropTypes = require('prop-types'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For new files, let's move this in the right place, please. |
||
/* | ||
* 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 {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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* 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 {SHOW_NOTIFICATION} = require('../../actions/notifications'); | ||
|
||
const {manageAutoMapUpdate} = require('../automapupdate'); | ||
const rootEpic = combineEpics(manageAutoMapUpdate); | ||
const epicMiddleware = createEpicMiddleware(rootEpic); | ||
const mockStore = configureMockStore([epicMiddleware]); | ||
|
||
describe('autorefresh Epics', () => { | ||
let store; | ||
beforeEach(() => { | ||
store = mockStore(); | ||
}); | ||
|
||
afterEach(() => { | ||
epicMiddleware.replaceEpic(rootEpic); | ||
}); | ||
|
||
it('refreshes 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('refreshes map without login', (done) => { | ||
|
||
let configuration = configureMap({ | ||
version: 2 | ||
}, "id"); | ||
|
||
let information = mapInfoLoaded({ | ||
canEdit: true | ||
}, "id"); | ||
|
||
store.dispatch(configuration); | ||
store.dispatch(information); | ||
|
||
setTimeout( () => { | ||
try { | ||
const actions = store.getActions(); | ||
expect(actions.length).toBe(2); | ||
} catch (e) { | ||
return done(e); | ||
} | ||
done(); | ||
}, 500); | ||
|
||
}); | ||
}); |
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 Rx = require('rxjs'); | ||
const {refreshLayers, LAYERS_REFRESHED, LAYERS_REFRESH_ERROR} = require('../actions/layers'); | ||
const {MAP_CONFIG_LOADED, MAP_INFO_LOADED} = require('../actions/config'); | ||
const {warning, success} = require('../actions/notifications'); | ||
const {toggleControl} = require('../actions/controls'); | ||
|
||
/** | ||
* When map has been loaded, it sends a notification if the version is less than 2 and users has write permission. | ||
* @param {external:Observable} action$ manages `MAP_CONFIG_LOADED` and `MAP_INFO_LOADED`. | ||
* @memberof epics.automapupdate | ||
* @return {external:Observable} | ||
*/ | ||
|
||
const manageAutoMapUpdate = action$ => | ||
action$.ofType(MAP_CONFIG_LOADED) | ||
.switchMap((mapConfigLoaded) => | ||
action$.ofType(MAP_INFO_LOADED) | ||
.switchMap((mapInfoLoaded) => { | ||
const version = mapConfigLoaded.config && mapConfigLoaded.config.version || 1; | ||
const canEdit = mapInfoLoaded.info && mapInfoLoaded.info.canEdit || false; | ||
let layers = mapConfigLoaded.config && mapConfigLoaded.config.map && mapConfigLoaded.config.map.layers && mapConfigLoaded.config.map.layers.filter((l) => l.type === 'wms' && l.group !== 'background') || []; | ||
const options = {bbox: true, search: true, dimensions: true, title: true}; | ||
return version < 2 && canEdit ? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change title to false |
||
Rx.Observable.of(warning({ | ||
title: "notification.warning", | ||
message: "notification.updateOldMap", | ||
action: { | ||
label: "notification.update", | ||
dispatch: refreshLayers(layers, options) | ||
}, | ||
autoDismiss: 12, | ||
position: "tc" | ||
})).concat( | ||
action$.ofType(LAYERS_REFRESHED, LAYERS_REFRESH_ERROR) | ||
.bufferCount(layers.length) | ||
.switchMap((refreshed) => { | ||
const errors = refreshed.filter((l) => l.type === LAYERS_REFRESH_ERROR); | ||
const notification = errors.length > 0 ? | ||
warning({ | ||
title: "notification.warning", | ||
message: "notification.warningSaveUpdatedMap", | ||
autoDismiss: 6, | ||
position: "tc" | ||
}) | ||
: | ||
success({ | ||
title: "notification.success", | ||
message: "notification.saveUpdatedMap", | ||
autoDismiss: 6, | ||
position: "tc" | ||
}); | ||
return Rx.Observable.of(notification, toggleControl('save')); | ||
})) | ||
: Rx.Observable.empty(); | ||
})); | ||
|
||
/** | ||
* Epics for update old map | ||
* @name epics.automapupdate | ||
* @type {Object} | ||
*/ | ||
|
||
module.exports = { | ||
manageAutoMapUpdate | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pass simple object. The thunks will be removed in the next future.