Skip to content

Commit

Permalink
[Backport 2024.01.xx] - #10322: Fix scale selector to make it compati…
Browse files Browse the repository at this point in the history
…ble with different projections (#10344) (#10452)

* #10418: Share tool - the 'Add place mark and zoom to sharing link' option is not applied correctly (#10419)

* #10322: Fix scale selector to make it compatible with different projections (#10344)

* #10322: Fix scale selector to make it compatible with different projections
Description:
- fix the bug by using the updated scaleZoom value instead of the projected value

* #10322: Fix scale selector to make it compatible with different projections
Description:
- add helpful comment

* #10322: Fix scale selector to make it compatible with different projections
Description:
- fix not compatablity projections issue
- add unit tests

* #10322: Fix scale selector to make it compatible with different projections
Description:
- resolve review comments related to unit tests [replace async/await with then + remove unnecessary async/await]

* #10322: Fix scale selector to make it compatible with different projections
Description:
- fix issues of not consistent map print scales with the current map view

* #10322: Fix scale selector to make it compatible with different projections
Description:
- fix FE issue

* Fixed preview

* #10322: Fix scale selector to make it compatible with different projections
Description:
- resolve FE failure due to changes

---------

Co-authored-by: Lorenzo Natali <[email protected]>

---------

Co-authored-by: Lorenzo Natali <[email protected]>
  • Loading branch information
mahmoudadel54 and offtherailz authored Jul 3, 2024
1 parent 59ea05b commit 8529d7d
Show file tree
Hide file tree
Showing 12 changed files with 250 additions and 83 deletions.
15 changes: 15 additions & 0 deletions web/client/actions/__tests__/print-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,21 @@ describe('Test correctness of the print actions', () => {
expect(retVal.projection).toBe('EPSG:4326');
expect(retVal.currentLocale).toBe('en-US');
});
it('configurePrintMap with useFixedScales', () => {
const retVal = configurePrintMap({x: 1, y: 1}, 5, 6, 2.0, [], 'EPSG:4326', 'en-US', true);
expect(retVal).toExist();
expect(retVal.type).toBe(CONFIGURE_PRINT_MAP);
expect(retVal.center).toExist();
expect(retVal.center.x).toBe(1);
expect(retVal.zoom).toBe(5);
expect(retVal.scaleZoom).toBe(6);
expect(retVal.scale).toBe(2.0);
expect(retVal.layers).toExist();
expect(retVal.layers.length).toBe(0);
expect(retVal.projection).toBe('EPSG:4326');
expect(retVal.currentLocale).toBe('en-US');
expect(retVal.useFixedScales).toBe(true);
});

it('changePrintZoomLevel', () => {
const retVal = changePrintZoomLevel(5, 10000);
Expand Down
5 changes: 3 additions & 2 deletions web/client/actions/print.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function printTransformerAdded(name) {
};
}

export function configurePrintMap(center, zoom, scaleZoom, scale, layers, projection, currentLocale) {
export function configurePrintMap(center, zoom, scaleZoom, scale, layers, projection, currentLocale, useFixedScales) {
return {
type: CONFIGURE_PRINT_MAP,
center,
Expand All @@ -141,7 +141,8 @@ export function configurePrintMap(center, zoom, scaleZoom, scale, layers, projec
scale,
layers,
projection,
currentLocale
currentLocale,
useFixedScales
};
}

Expand Down
27 changes: 17 additions & 10 deletions web/client/components/print/MapPreview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import PropTypes from 'prop-types';
import React from 'react';
import { Glyphicon } from 'react-bootstrap';

import { getMapZoom, getResolutionMultiplier } from '../../utils/PrintUtils';
import { getResolutionMultiplier } from '../../utils/PrintUtils';
import ScaleBox from '../mapcontrols/scale/ScaleBox';
import Button from '../misc/Button';
import isNil from 'lodash/isNil';
import isEmpty from 'lodash/isEmpty';
import { MapLibraries } from '../../utils/MapTypeUtils';
import { get } from 'ol/proj';

let PMap;
let Layer;
Expand Down Expand Up @@ -83,23 +84,28 @@ class MapPreview extends React.Component {
}
});
}

componentWillUnmount() {
this._isMounted = false;
}

getRatio = () => {
if (this.props.width && this.props.layoutSize && this.props.resolutions) {
if (this.props.width && this.props.layoutSize ) {
return getResolutionMultiplier(this.props.layoutSize.width, this.props.width, this.props.printRatio);
}
return 1;
};

getResolutions = () => {
if (this.props.width && this.props.layoutSize && this.props.resolutions) {
return this.props.resolutions.map((resolution) => resolution * this.getRatio());
getResolutions = (srs) => {
// cache resolutions
const projection = get(srs);
const metersPerUnit = projection.getMetersPerUnit();
const scaleToResolution = s => s * 0.28E-3 / metersPerUnit;
const previewResolutions = this.props.useFixedScales && this.props.scales
? this.props.scales.map(s => scaleToResolution(s)) : this.props.resolutions;
if (this.props.width && this.props.layoutSize && previewResolutions) {
return previewResolutions.map((resolution) => resolution * this.getRatio());
}
return this.props.resolutions;
return previewResolutions;
};

renderLayerContent = (layer, projection) => {
Expand Down Expand Up @@ -134,14 +140,15 @@ class MapPreview extends React.Component {
width: this.props.width + "px",
height: this.props.height + "px"
});
const resolutions = this.getResolutions();
const projection = this.props.map && this.props.map.projection || 'EPSG:3857';
const resolutions = this.getResolutions(projection);
let mapOptions = !isEmpty(resolutions) || !isNil(this.props.rotation) ? {
view: {
...(!isEmpty(resolutions) && {resolutions}),
rotation: !isNil(this.props.rotation) ? Number(this.props.rotation) : 0
}
} : {};
const projection = this.props.map && this.props.map.projection || 'EPSG:3857';

return this.props.map && this.props.map.center ?

<div className="print-map-preview"><PMap
Expand All @@ -152,7 +159,7 @@ class MapPreview extends React.Component {
interactive={false}
onMapViewChanges={this.props.onMapViewChanges}
zoomControl={false}
zoom={this.props.useFixedScales && this.props.scales ? getMapZoom(this.props.map.scaleZoom, this.props.scales) : this.props.map.zoom}
zoom={this.props.useFixedScales ? this.props.map.scaleZoom : this.props.map.zoom}
center={this.props.map.center}
id="print_preview"
registerHooks={false}
Expand Down
2 changes: 1 addition & 1 deletion web/client/components/print/__tests__/MapPreview-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ describe("Test the MapPreview component", () => {
scales={[100, 1000, 10000, 100000]}
onLoadingMapPlugins={(loading) => {
if (!loading) {
expect(cmp.refs.mappa.props.zoom).toBe(13);
expect(cmp.refs.mappa.props.zoom).toBe(3);
done();
}
}}
Expand Down
54 changes: 27 additions & 27 deletions web/client/plugins/Print.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ import { layersSelector } from '../selectors/layers';
import { currentLocaleSelector } from '../selectors/locale';
import { mapSelector, scalesSelector } from '../selectors/map';
import { mapTypeSelector } from '../selectors/maptype';
import { normalizeSRS, reprojectBbox, convertDegreesToRadian } from '../utils/CoordinatesUtils';
import { normalizeSRS, convertDegreesToRadian } from '../utils/CoordinatesUtils';
import { getMessageById } from '../utils/LocaleUtils';
import { defaultGetZoomForExtent, getResolutions, mapUpdated, dpi2dpu, DEFAULT_SCREEN_DPI } from '../utils/MapUtils';
import { defaultGetZoomForExtent, getResolutions, mapUpdated, dpi2dpu, DEFAULT_SCREEN_DPI, getScales, reprojectZoom } from '../utils/MapUtils';
import { isInsideResolutionsLimits } from '../utils/LayersUtils';
import { has, includes } from 'lodash';
import {additionalLayersSelector} from "../selectors/additionallayers";
Expand Down Expand Up @@ -289,7 +289,8 @@ export default {
overrideOptions: PropTypes.object,
items: PropTypes.array,
addPrintParameter: PropTypes.func,
printingService: PropTypes.object
printingService: PropTypes.object,
printMap: PropTypes.object
};

static contextTypes = {
Expand Down Expand Up @@ -340,7 +341,8 @@ export default {
currentLocale: 'en-US',
overrideOptions: {},
items: [],
printingService: getDefaultPrintingService()
printingService: getDefaultPrintingService(),
printMap: {}
};

state = {
Expand Down Expand Up @@ -569,34 +571,30 @@ export default {
const {
map: newMap,
capabilities,
minZoom,
configurePrintMap: configurePrintMapProp,
useFixedScales,
getZoomForExtent,
maxZoom,
currentLocale,
scales: scalesProp,
layers
layers,
printMap,
printSpec
} = props || this.props;
if (newMap && newMap.bbox && capabilities) {
const bbox = reprojectBbox([
newMap.bbox.bounds.minx,
newMap.bbox.bounds.miny,
newMap.bbox.bounds.maxx,
newMap.bbox.bounds.maxy
], newMap.bbox.crs, newMap.projection);
const mapSize = this.getMapSize();
const selectedPrintProjection = (printSpec && printSpec?.params?.projection) || (printSpec && printSpec?.projection) || (printMap && printMap.projection) || 'EPSG:3857';
const printSrs = normalizeSRS(selectedPrintProjection);
const mapProjection = newMap.projection;
const mapSrs = normalizeSRS(mapProjection);
const zoom = reprojectZoom(newMap.zoom, mapSrs, printSrs);
const scales = getPrintScales(capabilities);
const printMapScales = getScales(printSrs);
const scaleZoom = getNearestZoom(zoom, scales, printMapScales);
if (useFixedScales) {
const mapZoom = getZoomForExtent(bbox, mapSize, minZoom, maxZoom);
const scales = getPrintScales(capabilities);
const scaleZoom = getNearestZoom(newMap.zoom, scales);
const scale = scales[scaleZoom];
configurePrintMapProp(newMap.center, mapZoom, scaleZoom, scale,
layers, newMap.projection, currentLocale);
configurePrintMapProp(newMap.center, zoom, scaleZoom, scale,
layers, newMap.projection, currentLocale, useFixedScales);
} else {
const scale = scalesProp[newMap.zoom];
configurePrintMapProp(newMap.center, newMap.zoom, newMap.zoom, scale,
layers, newMap.projection, currentLocale);
const scale = printMapScales[zoom];
configurePrintMapProp(newMap.center, zoom, scaleZoom, scale,
layers, newMap.projection, currentLocale, useFixedScales);
}
}
};
Expand Down Expand Up @@ -629,8 +627,9 @@ export default {
scalesSelector,
(state) => state.browser && (!state.browser.ie || state.browser.ie11),
currentLocaleSelector,
mapTypeSelector
], (open, capabilities, printSpec, pdfUrl, error, map, layers, additionalLayers, scales, usePreview, currentLocale, mapType) => ({
mapTypeSelector,
(state) => state.print.map
], (open, capabilities, printSpec, pdfUrl, error, map, layers, additionalLayers, scales, usePreview, currentLocale, mapType, printMap) => ({
open,
capabilities,
printSpec,
Expand All @@ -650,7 +649,8 @@ export default {
scales,
usePreview,
currentLocale,
mapType
mapType,
printMap
}));

const PrintPlugin = connect(selector, {
Expand Down
84 changes: 84 additions & 0 deletions web/client/plugins/__tests__/Print-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,90 @@ describe('Print Plugin', () => {
});
});

it('test configuration with useFixedScales and enableScalebox = true', (done) => {
const printingService = {
getMapConfiguration() {
return {
layers: [],
center: {
x: 0,
y: 0,
crs: "EPSG:4326"
}
};
},
validate() { return {};}
};
getPrintPlugin({
state: {...initialState,
print: {...initialState.print,
capabilities: {...initialState.print.capabilities,
scales: [1000000, 500000, 100000].map(value => ({name: value, value}))}
}}
}).then(({ Plugin }) => {
try {
ReactDOM.render(<Plugin
projectionOptions={{
"projections": [{"name": "UTM32N", "value": "EPSG:23032"}, {"name": "EPSG:3857", "value": "EPSG:3857"}, {"name": "EPSG:4326", "value": "EPSG:4326"}]
}}
printingService={printingService}
useFixedScales mapPreviewOptions={{
enableScalebox: true
}}/>, document.getElementById("container"));
const comp = document.getElementById("container");
ReactTestUtils.act(() => new Promise((resolve) => resolve(comp))).then(()=>{
expect(comp).toExist();
const scaleBoxComp = document.querySelector("#mappreview-scalebox select");
expect(scaleBoxComp).toExist();
done();
});
} catch (ex) {
done(ex);
}
});
});
it('test configuration with useFixedScales and enableScalebox = false', (done) => {
const printingService = {
getMapConfiguration() {
return {
layers: [],
center: {
x: 0,
y: 0,
crs: "EPSG:4326"
}
};
},
validate() { return {};}
};
getPrintPlugin({
state: {...initialState,
print: {...initialState.print,
capabilities: {...initialState.print.capabilities,
scales: [1000000, 500000, 100000].map(value => ({name: value, value}))}
}}
}).then(({ Plugin }) => {
try {
ReactDOM.render(<Plugin
projectionOptions={{
"projections": [{"name": "UTM32N", "value": "EPSG:23032"}, {"name": "EPSG:3857", "value": "EPSG:3857"}, {"name": "EPSG:4326", "value": "EPSG:4326"}]
}}
printingService={printingService}
useFixedScales mapPreviewOptions={{
enableScalebox: false
}}/>, document.getElementById("container"));
const comp = document.getElementById("container");
ReactTestUtils.act(() => new Promise((resolve) => resolve(comp))).then(()=>{
expect(comp).toExist();
const scaleBoxComp = document.querySelector("#mappreview-scalebox select");
expect(scaleBoxComp).toNotExist();
done();
});
} catch (ex) {
done(ex);
}
});
});
it('default configuration with not allowed layers', (done) => {
getPrintPlugin({
layers: [{visibility: true, type: "bing"}]
Expand Down
51 changes: 28 additions & 23 deletions web/client/plugins/__tests__/print/Projection-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const initialState = {
map: {
scale: 1784,
scaleZoom: 2,
projection: "EPSG:3857"
projection: "EPSG:3857",
zoom: 3
},
capabilities: {
createURL: "http://fakeservice",
Expand Down Expand Up @@ -121,16 +122,18 @@ describe('PrintProjection Plugin', () => {
it('map transformer with user chosen crs', (done) => {
getPrintProjectionPlugin().then(({ Plugin, store }) => {
try {
ReactDOM.render(<Plugin projections={[{"name": "Mercator", "value": "EPSG:3857"}, {"name": "WGS84", "value": "EPSG:4326"}]}/>, document.getElementById("container"));
const combo = getByXPath("//select");
ReactTestUtils.Simulate.change(combo, {
target: {
value: "EPSG:4326"
}
});
callMapTransformer(store.getState(), (map) => {
expect(map.projection).toBe('EPSG:4326');
done();
const comp = ReactDOM.render(<Plugin projections={[{"name": "Mercator", "value": "EPSG:3857"}, {"name": "WGS84", "value": "EPSG:4326"}]}/>, document.getElementById("container"));
ReactTestUtils.act(() => new Promise((resolve) => resolve(comp))).then(() => {
const combo = getByXPath("//select");
ReactTestUtils.Simulate.change(combo, {
target: {
value: "EPSG:4326"
}
});
callMapTransformer(store.getState(), (map) => {
expect(map.projection).toBe('EPSG:4326');
done();
});
});
} catch (ex) {
done(ex);
Expand All @@ -141,18 +144,20 @@ describe('PrintProjection Plugin', () => {
it('validator without allowPreview', (done) => {
getPrintProjectionPlugin().then(({ Plugin, store }) => {
try {
ReactDOM.render(<Plugin projections={[{"name": "Mercator", "value": "EPSG:3857"}, {"name": "WGS84", "value": "EPSG:4326"}]}/>, document.getElementById("container"));
const combo = getByXPath("//select");
ReactTestUtils.Simulate.change(combo, {
target: {
value: "EPSG:4326"
}
});
callValidator(store.getState(), (validation) => {
expect(validation).toExist();
expect(validation.valid).toBe(false);
expect(validation.errors.length).toBe(1);
done();
const comp = ReactDOM.render(<Plugin projections={[{"name": "Mercator", "value": "EPSG:3857"}, {"name": "WGS84", "value": "EPSG:4326"}]}/>, document.getElementById("container"));
ReactTestUtils.act(() => new Promise((resolve) => resolve(comp))).then(() => {
const combo = getByXPath("//select");
ReactTestUtils.Simulate.change(combo, {
target: {
value: "EPSG:4326"
}
});
callValidator(store.getState(), (validation) => {
expect(validation).toExist();
expect(validation.valid).toBe(false);
expect(validation.errors.length).toBe(1);
done();
});
});
} catch (ex) {
done(ex);
Expand Down
Loading

0 comments on commit 8529d7d

Please sign in to comment.