Skip to content
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 #3617. Add feature zoomTo and highlight to Identify #3635

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion web/client/actions/__tests__/mapInfo-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ var {
toggleMapInfoState,
updateCenterToMarker,
TOGGLE_SHOW_COORD_EDITOR, toggleShowCoordinateEditor,
CHANGE_FORMAT, changeFormat
CHANGE_FORMAT, changeFormat,
CHANGE_PAGE, changePage,
TOGGLE_HIGHLIGHT_FEATURE, toggleHighlightFeature
} = require('../mapInfo');

describe('Test correctness of the map actions', () => {
Expand Down Expand Up @@ -119,4 +121,18 @@ describe('Test correctness of the map actions', () => {
expect(retval.type).toBe(CHANGE_FORMAT);
expect(retval.format).toBe(format);
});
it('toggleHighlightFeature', () => {
const retVal = toggleHighlightFeature(true);
expect(retVal).toExist();
expect(retVal.type).toBe(TOGGLE_HIGHLIGHT_FEATURE);
expect(toggleHighlightFeature().enabled).toBeFalsy();
expect(toggleHighlightFeature(true).enabled).toBe(true);
});
it('changePage', () => {
const retVal = changePage(true);
expect(retVal).toExist();
expect(retVal.type).toBe(CHANGE_PAGE);
expect(changePage().index).toBeFalsy();
expect(changePage(1).index).toBe(1);
});
});
23 changes: 23 additions & 0 deletions web/client/actions/mapInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ const GET_VECTOR_INFO = 'GET_VECTOR_INFO';
const NO_QUERYABLE_LAYERS = 'NO_QUERYABLE_LAYERS';
const CLEAR_WARNING = 'CLEAR_WARNING';
const FEATURE_INFO_CLICK = 'FEATURE_INFO_CLICK';
const TOGGLE_HIGHLIGHT_FEATURE = "IDENTIFY:TOGGLE_HIGHLIGHT_FEATURE";
const TOGGLE_MAPINFO_STATE = 'TOGGLE_MAPINFO_STATE';
const UPDATE_CENTER_TO_MARKER = 'UPDATE_CENTER_TO_MARKER';
const CHANGE_PAGE = 'IDENTIFY:CHANGE_PAGE';
const CLOSE_IDENTIFY = 'IDENTIFY:CLOSE_IDENTIFY';
const CHANGE_FORMAT = 'IDENTIFY:CHANGE_FORMAT';
const TOGGLE_SHOW_COORD_EDITOR = 'IDENTIFY:TOGGLE_SHOW_COORD_EDITOR';
Expand Down Expand Up @@ -193,6 +195,25 @@ function featureInfoClick(point, layer) {
};
}

function toggleHighlightFeature(enabled) {
return {
type: TOGGLE_HIGHLIGHT_FEATURE,
enabled
};
}

/**
* Changes the current page of the feature info.
* The index is relative only to valid responses, excluding invalid.(see validResponsesSelector)
* @param {number} index index of the page
*/
function changePage(index) {
return {
type: CHANGE_PAGE,
index
};
}

const closeIdentify = () => ({
type: CLOSE_IDENTIFY
});
Expand Down Expand Up @@ -231,6 +252,8 @@ module.exports = {
NO_QUERYABLE_LAYERS,
CLEAR_WARNING,
FEATURE_INFO_CLICK,
TOGGLE_HIGHLIGHT_FEATURE, toggleHighlightFeature,
CHANGE_PAGE, changePage,
TOGGLE_MAPINFO_STATE,
UPDATE_CENTER_TO_MARKER,
CLOSE_IDENTIFY,
Expand Down
6 changes: 1 addition & 5 deletions web/client/components/data/identify/IdentifyContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ const React = require('react');
const {Row, Col} = require('react-bootstrap');
const Toolbar = require('../../misc/toolbar/Toolbar');
const Message = require('../../I18N/Message');
const MapInfoUtils = require('../../../utils/MapInfoUtils');
const DockablePanel = require('../../misc/panels/DockablePanel');
const GeocodeViewer = require('./GeocodeViewer');
const ResizableModal = require('../../misc/ResizableModal');
Expand Down Expand Up @@ -42,7 +41,7 @@ module.exports = props => {
position,
size,
fluid,
validator = MapInfoUtils.getValidator,
validResponses = [],
viewer = () => null,
getButtons = () => [],
showFullscreen,
Expand Down Expand Up @@ -76,9 +75,6 @@ module.exports = props => {
/* the following formula apply the converion */
lngCorrected = lngCorrected - 360 * Math.floor(lngCorrected / 360 + 0.5);
}

const validatorFormat = validator(format);
const validResponses = validatorFormat.getValidResponses(responses);
const Viewer = viewer;
const buttons = getButtons({...props, lngCorrected, validResponses, latlng});
const missingResponses = requests.length - responses.length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
const React = require('react');
const expect = require('expect');
const ReactDOM = require('react-dom');
const {defaultViewerHandlers, switchControlledDefaultViewer, defaultViewerDefaultProps} = require('../defaultViewer');
const {defaultViewerHandlers, defaultViewerDefaultProps} = require('../defaultViewer');
const TestUtils = require('react-dom/test-utils');

describe("test defaultViewer enhancers", () => {
Expand All @@ -30,32 +30,17 @@ describe("test defaultViewer enhancers", () => {
expect(testComponent.innerHTML).toBe('text/plain');
});

it('test switchControlledDefaultViewer', () => {
const Component = switchControlledDefaultViewer(({index = 0, setIndex = () => {}}) => <div id="test-component" onClick={() => setIndex(2)}>{index}</div>);
ReactDOM.render(<Component header />, document.getElementById("container"));
let testComponent = document.getElementById('test-component');
expect(testComponent.innerHTML).toBe('0');
TestUtils.Simulate.click(testComponent);
expect(testComponent.innerHTML).toBe('2');

ReactDOM.render(<Component />, document.getElementById("container"));
testComponent = document.getElementById('test-component');
expect(testComponent.innerHTML).toBe('0');
TestUtils.Simulate.click(testComponent);
expect(testComponent.innerHTML).toBe('0');
});

it('test defaultViewerHanlders onNext', done => {
const Component = defaultViewerHandlers(({onNext = () => {}, index = 0}) =>
<span>
<div id="test-component-next" onClick={() => onNext()}>{index}</div>
</span>
);

ReactDOM.render(<Component index={0} setIndex={index => {
ReactDOM.render(<Component validResponses={[{dummy: "dummy response"}]} index={0} setIndex={index => {
expect(index).toBe(0);
done();
}} validator={() => ({getValidResponses: (responses) => responses})} format="text/plain" responses={[{}]}/>, document.getElementById("container"));
}} />, document.getElementById("container"));

const testComponentNext = document.getElementById('test-component-next');
TestUtils.Simulate.click(testComponentNext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
const React = require('react');
const expect = require('expect');
const ReactDOM = require('react-dom');
const {identifyLifecycle, switchControlledIdentify} = require('../identify');
const {identifyLifecycle} = require('../identify');
const TestUtils = require('react-dom/test-utils');

describe("test identify enhancers", () => {
Expand All @@ -23,28 +23,7 @@ describe("test identify enhancers", () => {
setTimeout(done);
});

it('test switchControlledIdentify', () => {
const Component = switchControlledIdentify(({index = 0, setIndex = () => {}}) => <div id="test-component" onClick={() => setIndex(2)}>{index}</div>);
ReactDOM.render(<Component />, document.getElementById("container"));
let testComponent = document.getElementById('test-component');
expect(testComponent.innerHTML).toBe('0');
TestUtils.Simulate.click(testComponent);
expect(testComponent.innerHTML).toBe('2');

ReactDOM.render(<Component viewerOptions={{header: true}}/>, document.getElementById("container"));
testComponent = document.getElementById('test-component');
expect(testComponent.innerHTML).toBe('0');
TestUtils.Simulate.click(testComponent);
expect(testComponent.innerHTML).toBe('0');

ReactDOM.render(<Component viewerOptions={{}}/>, document.getElementById("container"));
testComponent = document.getElementById('test-component');
expect(testComponent.innerHTML).toBe('0');
TestUtils.Simulate.click(testComponent);
expect(testComponent.innerHTML).toBe('2');
});

it('test switchControlledIdentify component changes mousepointer on enable / disable', () => {
it('test identifyLifecycle component changes mousepointer on enable / disable', () => {

const Component = identifyLifecycle(() => <div id="test-component"></div>);

Expand All @@ -70,7 +49,7 @@ describe("test identify enhancers", () => {
expect(spyMousePointer.calls.length).toEqual(2);
});

it("test switchControlledIdentify component doesn't need reset current index when requests are the same", () => {
it("test identifyLifecycle component doesn't need reset current index when requests are the same", () => {
const Component = identifyLifecycle(() => <div id="test-component"></div>);
const testHandlers = {
setIndex: () => {}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2019, 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 {createSink} = require('recompose');
const expect = require('expect');
const zoomToFeatureHandler = require('../zoomToFeatureHandler');

const SAMPLE_FEATURES = [
{
"type": "Feature",
"id": "",
"geometry": null,
"properties": {
"GRAY_INDEX": 336
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2.4609375,
55.27911529201561
],
[
3.515625,
45.1510532655634
],
[
12.83203125,
45.089035564831036
],
[
12.568359375,
55.3791104480105
],
[
2.4609375,
55.27911529201561
]
]
]
}
}
];

describe('zoomToFeatureHandler enhancer', () => {
beforeEach((done) => {
document.body.innerHTML = '<div id="container"></div>';
setTimeout(done);
});
afterEach((done) => {
ReactDOM.unmountComponentAtNode(document.getElementById("container"));
document.body.innerHTML = '';
setTimeout(done);
});
it('zoomToFeatureHandler rendering with defaults', (done) => {
const Sink = zoomToFeatureHandler(createSink( props => {
expect(props.zoomToFeature).toExist();
done();
}));
ReactDOM.render(<Sink />, document.getElementById("container"));
});
it('callback to zoomToExtent', () => {
const actions = {
zoomToExtent: () => {}
};
const spy = expect.spyOn(actions, 'zoomToExtent');

const Sink = zoomToFeatureHandler(createSink( props => {
props.zoomToFeature();
}));
ReactDOM.render(<Sink
zoomToExtent={actions.zoomToExtent}
currentFeatureCrs="EPSG:3857"
currentFeature={SAMPLE_FEATURES}/>, document.getElementById("container"));
expect(spy).toHaveBeenCalled();
expect(spy.calls[0].arguments[0]).toBeAn(Array);
expect(spy.calls[0].arguments[1]).toBe("EPSG:3857");
});
it('not zoom if at least one geometry is not available', () => {
const actions = {
zoomToExtent: () => { }
};
const spy = expect.spyOn(actions, 'zoomToExtent');

const Sink = zoomToFeatureHandler(createSink(props => {
props.zoomToFeature();
}));
ReactDOM.render(<Sink
zoomToExtent={actions.zoomToExtent}
currentFeatureCrs="EPSG:3857"
currentFeature={[SAMPLE_FEATURES[0]]} />, document.getElementById("container"));
expect(spy).toNotHaveBeenCalled();

});
});
19 changes: 3 additions & 16 deletions web/client/components/data/identify/enhancers/defaultViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/

const {withState, withHandlers, branch, defaultProps} = require('recompose');
const {withHandlers, defaultProps} = require('recompose');
const MapInfoUtils = require('../../../../utils/MapInfoUtils');

/**
Expand All @@ -17,27 +17,15 @@ const MapInfoUtils = require('../../../../utils/MapInfoUtils');
* @class
*/
const defaultViewerHandlers = withHandlers({
onNext: ({index = 0, setIndex = () => {}, responses, format, validator}) => () => {
setIndex(Math.min(validator(format).getValidResponses(responses).length - 1, index + 1));
onNext: ({index = 0, setIndex = () => {}, validResponses = []}) => () => {
setIndex(Math.min(validResponses.length - 1, index + 1));
},
onPrevious: ({index, setIndex = () => {}}) => () => {
setIndex(Math.max(0, index - 1));
}
});


/**
* Enhancer to enable set index only if Component has header
* @memberof enhancers.switchControlledDefaultViewer
* @class
*/
const switchControlledDefaultViewer = branch(
({header}) => header,
withState(
'index', 'setIndex', 0
)
);

/**
* Set the default props of DefaultViewer
* @memberof enhancers.defaultViewerDefaultProps
Expand All @@ -50,6 +38,5 @@ const defaultViewerDefaultProps = defaultProps({

module.exports = {
defaultViewerHandlers,
switchControlledDefaultViewer,
defaultViewerDefaultProps
};
17 changes: 2 additions & 15 deletions web/client/components/data/identify/enhancers/identify.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,10 @@
* LICENSE file in the root directory of this source tree.
*/

const {lifecycle, withHandlers, branch, withState, compose} = require('recompose');
const {lifecycle, withHandlers, compose} = require('recompose');
const {set} = require('../../../../utils/ImmutableUtils');
const {isEqual, isNil} = require('lodash');

/**
* Enhancer to enable set index only if Component has not header in viewerOptions props
* @memberof enhancers.switchControlledIdentify
* @class
*/
const switchControlledIdentify = branch(
({viewerOptions}) => !viewerOptions || (viewerOptions && !viewerOptions.header),
withState(
'index', 'setIndex', 0
)
);

/**
* Enhancer to enable set index only if Component has header
* - needsRefresh: check if current selected point if different of next point, if so return true
Expand Down Expand Up @@ -118,6 +106,5 @@ const identifyLifecycle = compose(
);

module.exports = {
identifyLifecycle,
switchControlledIdentify
identifyLifecycle
};
Loading