Skip to content

Commit

Permalink
#9318: Print plugin - Ability to rotate the map (#9427)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsuren1 authored Sep 20, 2023
1 parent 287c7ce commit ebe2484
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 7 deletions.
10 changes: 8 additions & 2 deletions web/client/components/map/openlayers/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ class OpenlayersMap extends React.Component {
}, 0);
}

if (this.map && ((this.props.projection !== newProps.projection) || this.haveResolutionsChanged(newProps)) || this.props.limits !== newProps.limits) {
if (this.props.projection !== newProps.projection || this.props.limits !== newProps.limits) {
if (this.map && ((this.props.projection !== newProps.projection) || this.haveResolutionsChanged(newProps)) || this.haveRotationChanged(newProps) || this.props.limits !== newProps.limits) {
if (this.props.projection !== newProps.projection || this.props.limits !== newProps.limits || this.haveRotationChanged(newProps)) {
let mapProjection = newProps.projection;
const center = reproject([
newProps.center.x,
Expand Down Expand Up @@ -502,6 +502,12 @@ class OpenlayersMap extends React.Component {
return !isEqual(resolutions, newResolutions);
};

haveRotationChanged = (newProps) => {
const rotation = this.props.mapOptions && this.props.mapOptions.view ? this.props.mapOptions.view.rotation : undefined;
const newRotation = newProps.mapOptions && newProps.mapOptions.view ? newProps.mapOptions.view.rotation : undefined;
return !isEqual(rotation, newRotation);
};

createView = (center, zoom, projection, options, limits = {}) => {
// limit has a crs defined
const extent = limits.restrictedExtent && limits.crs && reprojectBbox(limits.restrictedExtent, limits.crs, normalizeSRS(projection));
Expand Down
77 changes: 77 additions & 0 deletions web/client/components/map/openlayers/__tests__/Map-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,83 @@ describe('OpenlayersMap', () => {
expect( map.haveResolutionsChanged(testProps({mapOptions: {view: {resolutions: [100, 50, 25]}}})) ).toBe(true);
});

it('check result of "haveRotationChanged()" when receiving new props', () => {
let map = ReactDOM.render(
<OpenlayersMap
center={{y: 43.9, x: 10.3}}
zoom={11.6}
measurement={{}}
/>
, document.getElementById("map"));

let origProps = assign({}, map.props);
function testProps(newProps) {
// update original props with newProps
return assign({}, origProps, newProps);
}

map = ReactDOM.render(
<OpenlayersMap
center={{y: 43.9, x: 10.3}}
zoom={11.6}
measurement={{}}
mapOptions={undefined}
/>
, document.getElementById("map"));

expect(map.haveRotationChanged(testProps({mapOptions: undefined}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: undefined}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 0}}}))).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 20}}}))).toBe(true);

map = ReactDOM.render(
<OpenlayersMap
center={{y: 43.9, x: 10.3}}
zoom={11.6}
measurement={{}}
mapOptions={{}}
/>
, document.getElementById("map"));
expect(map.haveRotationChanged(testProps({mapOptions: undefined}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: undefined}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 0}}}))).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 20}}}))).toBe(true);

map = ReactDOM.render(
<OpenlayersMap
center={{y: 43.9, x: 10.3}}
zoom={11.6}
measurement={{}}
mapOptions={{view: {}}}
/>
, document.getElementById("map"));
expect(map.haveRotationChanged(testProps({mapOptions: undefined}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: undefined}}}))).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 0}}}))).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 20}}}))).toBe(true);
map = ReactDOM.render(
<OpenlayersMap
center={{y: 43.9, x: 10.3}}
zoom={11.6}
measurement={{}}
mapOptions={{view: {rotation: 1}}}
maxExtent= {[-180, -90, 180, 80]}
/>
, document.getElementById("map"));
expect(map.haveRotationChanged(testProps({mapOptions: undefined})) ).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {}})) ).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {}}})) ).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: undefined}}})) ).toBe(true);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 1}}})) ).toBe(false);
expect(map.haveRotationChanged(testProps({mapOptions: {view: {rotation: 20}}})) ).toBe(true);
});

it('check if the map has "auto" cursor as default', () => {
const map = ReactDOM.render(
<OpenlayersMap
Expand Down
9 changes: 8 additions & 1 deletion web/client/components/print/MapPreview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { getMapZoom, 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';

let PMap;
Expand All @@ -40,6 +41,7 @@ class MapPreview extends React.Component {
layout: PropTypes.string,
layoutSize: PropTypes.object,
useFixedScales: PropTypes.bool,
rotation: PropTypes.number,
env: PropTypes.object,
onLoadingMapPlugins: PropTypes.func
};
Expand Down Expand Up @@ -133,7 +135,12 @@ class MapPreview extends React.Component {
height: this.props.height + "px"
});
const resolutions = this.getResolutions();
const mapOptions = resolutions ? {view: {resolutions}} : {};
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 ?

Expand Down
4 changes: 3 additions & 1 deletion web/client/plugins/Print.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import './print/print.css';

import head from 'lodash/head';
import castArray from "lodash/castArray";
import isNil from "lodash/isNil";
import assign from 'object-assign';
import PropTypes from 'prop-types';
import React from 'react';
Expand All @@ -28,7 +29,7 @@ import { layersSelector } from '../selectors/layers';
import { currentLocaleSelector } from '../selectors/locale';
import { mapSelector, scalesSelector } from '../selectors/map';
import { mapTypeSelector } from '../selectors/maptype';
import { normalizeSRS, reprojectBbox } from '../utils/CoordinatesUtils';
import { normalizeSRS, reprojectBbox, convertDegreesToRadian } from '../utils/CoordinatesUtils';
import { getMessageById } from '../utils/LocaleUtils';
import { defaultGetZoomForExtent, getResolutions, mapUpdated, dpi2dpu, DEFAULT_SCREEN_DPI } from '../utils/MapUtils';
import { isInsideResolutionsLimits } from '../utils/LayersUtils';
Expand Down Expand Up @@ -449,6 +450,7 @@ export default {
notAllowedLayers: this.isBackgroundIgnored(this.props.layers, map?.projection),
actionConfig: this.props.submitConfig,
validations: this.props.printingService.validate(),
rotation: !isNil(this.props.printSpec.rotation) ? convertDegreesToRadian(Number(this.props.printSpec.rotation)) : 0,
actions: {
print: this.print,
addParameter: this.addParameter
Expand Down
1 change: 1 addition & 0 deletions web/client/plugins/__tests__/Print-test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function expectDefaultItems() {
expect(getByXPath("//*[text()='print.description']")).toExist();
expect(getByXPath("//*[text()='print.outputFormat']")).toExist();
expect(getByXPath("//*[text()='print.projection']")).toExist();
expect(getByXPath("//*[text()='print.rotation']")).toExist();
expect(document.getElementById("print_preview")).toExist();
expect(getByXPath("//*[text()='print.sheetsize']")).toExist();
expect(getByXPath("//*[text()='print.alternatives.legend']")).toExist();
Expand Down
17 changes: 16 additions & 1 deletion web/client/plugins/print/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ export const Projection = connect((state) => ({
onChangeParameter: setPrintParameter
})(ProjectionComp);

export const Rotation = connect((state) => ({
spec: state.print?.spec || {},
additionalProperty: false,
property: "rotation",
path: "",
type: "number",
label: "print.rotation"
}), {
onChangeParameter: setPrintParameter
})(TextInput);

export const Layout = connect((state) => ({
spec: state.print?.spec || {},
layouts: state?.print?.capabilities?.layouts || []
Expand Down Expand Up @@ -189,13 +200,17 @@ export const standardItems = {
"projections": [{"name": "EPSG:3857", "value": "EPSG:3857"}, {"name": "EPSG:4326", "value": "EPSG:4326"}]
},
position: 4
}, {
id: "rotation",
plugin: Rotation,
position: 5
}, {
id: "overlayLayers",
plugin: AdditionalLayers,
cfg: {
enabled: false
},
position: 5
position: 6
}],
"left-panel-accordion": [{
id: "layout",
Expand Down
3 changes: 2 additions & 1 deletion web/client/reducers/print.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const initialSpec = {
resolution: 96,
name: '',
description: '',
outputFormat: "pdf"
outputFormat: "pdf",
rotation: 0
};

const getSheetName = (name = '') => {
Expand Down
10 changes: 10 additions & 0 deletions web/client/themes/default/less/print.less
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,14 @@
border-width: 1px;
border-style: solid;
}
#print_preview {
.ol-rotate {
background-color: transparent;
button{
&.ol-rotate-reset{
display: none; //hide rotate button on map-preview
}
}
}
}
}
1 change: 1 addition & 0 deletions web/client/translations/data.de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@
"iconsSize": "Symbolgröße:",
"dpi": "dpi:"
},
"rotation": "Rotation",
"layoutWarning": "Layout nicht erlaubt",
"scale": "Maßstab",
"includeScale": "in Druck einschließen",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@
"iconsSize": "Icons size:",
"dpi": "Dpi:"
},
"rotation": "Rotation",
"layoutWarning": "Not allowed layout",
"scale": "Scale",
"includeScale": "Include in print",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@
"iconsSize": "Tamaño de los iconos:",
"dpi": "ppp:"
},
"rotation": "Rotation",
"layoutWarning": "Lienzo no permitido",
"scale": "escala",
"includeScale": "incluir en la impresión",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@
"iconsSize": "Taille d'icône :",
"dpi": "Ppp :"
},
"rotation": "Rotation",
"layoutWarning": "Mise en page non permise",
"scale": "échelle",
"includeScale": "inclure dans l'impression",
Expand Down
1 change: 1 addition & 0 deletions web/client/translations/data.it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@
"iconsSize": "Dimensione icone:",
"dpi": "Dpi:"
},
"rotation": "Rotation",
"layoutWarning": "Layout non consentito",
"scale": "Scala",
"includeScale": "Includi nella stampa",
Expand Down
3 changes: 2 additions & 1 deletion web/client/utils/PrintUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { printSpecificationSelector } from "../selectors/print";
import assign from 'object-assign';
import sortBy from "lodash/sortBy";
import head from "lodash/head";
import isNil from "lodash/isNil";

import { getGridGeoJson } from "./grids/MapGridsUtils";

Expand Down Expand Up @@ -261,7 +262,7 @@ export const getMapfishPrintSpecification = (rawSpec, state) => {
projectedCenter.y
],
"scale": reprojectedScale,
"rotation": 0
"rotation": !isNil(spec.rotation) ? -Number(spec.rotation) : 0 // negate the rotation value to match rotation in map preview and printed output
}
],
"legends": PrintUtils.getMapfishLayersSpecification(spec.layers, projectedSpec, state, 'legend'),
Expand Down

0 comments on commit ebe2484

Please sign in to comment.