diff --git a/project/custom/templates/.gitignore b/project/custom/templates/.gitignore index 65f026e062..045b9dffa4 100644 --- a/project/custom/templates/.gitignore +++ b/project/custom/templates/.gitignore @@ -1,4 +1,5 @@ node_modules/ +libs/Cesium/ dist/ target/ *.sublime-* diff --git a/project/standard/templates/.gitignore b/project/standard/templates/.gitignore index 65f026e062..045b9dffa4 100644 --- a/project/standard/templates/.gitignore +++ b/project/standard/templates/.gitignore @@ -1,4 +1,5 @@ node_modules/ +libs/Cesium/ dist/ target/ *.sublime-* diff --git a/web/client/components/map/openlayers/DrawSupport.jsx b/web/client/components/map/openlayers/DrawSupport.jsx index 94b7833f08..170cecc15f 100644 --- a/web/client/components/map/openlayers/DrawSupport.jsx +++ b/web/client/components/map/openlayers/DrawSupport.jsx @@ -695,8 +695,8 @@ class DrawSupport extends React.Component { previousFtIndex = i; } return f.getProperties().canEdit; - })[0]; - const previousCoords = previousFt.getGeometry() && previousFt.getGeometry().getCoordinates && previousFt.getGeometry().getCoordinates() || []; + })[0] || null; + const previousCoords = previousFt && previousFt.getGeometry() && previousFt.getGeometry().getCoordinates && previousFt.getGeometry().getCoordinates() || []; let actualCoords = []; let olFt; let newDrawMethod = newProps.drawMethod; @@ -717,39 +717,39 @@ class DrawSupport extends React.Component { actualCoords = [[e.coordinate]]; } olFt = this.getNewFeature(newDrawMethod, actualCoords); - olFt.setProperties(omit(previousFt.getProperties(), "geometry")); + olFt.setProperties(omit(previousFt && previousFt.getProperties() || {}, "geometry")); break; } case "LineString": { actualCoords = previousCoords.length ? [...previousCoords, e.coordinate] : [e.coordinate]; olFt = this.getNewFeature(newDrawMethod, actualCoords); - olFt.setProperties(omit(previousFt.getProperties(), "geometry")); + olFt.setProperties(omit(previousFt && previousFt.getProperties() || {}, "geometry")); } break; case "Circle": { newDrawMethod = "Polygon"; - const radius = previousFt.getProperties() && previousFt.getProperties().radius || 10000; - let center = e.coordinate; // || previousFt.getProperties() && previousFt.getProperties().center; + const radius = previousFt && previousFt.getProperties() && previousFt.getProperties().radius || 10000; + let center = e.coordinate; const coords = this.polygonCoordsFromCircle(center, 100); olFt = this.getNewFeature(newDrawMethod, coords); // TODO verify center is projected in 4326 and is an array center = reproject(center, this.getMapCrs(), "EPSG:4326", false); - olFt.setProperties(omit(previousFt.getProperties(), "geometry")); + olFt.setProperties(omit(previousFt && previousFt.getProperties() || {}, "geometry")); olFt.setProperties({isCircle: true, radius, center: [center.x, center.y]}); break; } case "Text": { newDrawMethod = "Point"; olFt = this.getNewFeature(newDrawMethod, e.coordinate); - olFt.setProperties(omit(previousFt.getProperties(), "geometry")); - olFt.setProperties({isText: true, valueText: previousFt.getProperties() && previousFt.getProperties().valueText || newProps.options.defaultTextAnnotation || "New" }); + olFt.setProperties(omit(previousFt && previousFt.getProperties() || {}, "geometry")); + olFt.setProperties({isText: true, valueText: previousFt && previousFt.getProperties() && previousFt.getProperties().valueText || newProps.options.defaultTextAnnotation || "New" }); break; } // point default: { actualCoords = e.coordinate; olFt = this.getNewFeature(newDrawMethod, actualCoords); - olFt.setProperties(omit(previousFt.getProperties(), "geometry")); + olFt.setProperties(omit(previousFt && previousFt.getProperties() || {}, "geometry")); } } @@ -770,9 +770,7 @@ class DrawSupport extends React.Component { this.props.onDrawingFeatures([ft]); olFt = transformPolygonToCircle(olFt, this.getMapCrs()); - if (previousFeatures && previousFeatures.length) { - previousFeatures[previousFtIndex] = olFt; - } + previousFeatures[previousFtIndex] = olFt; this.drawSource = new ol.source.Vector({ features: previousFeatures }); diff --git a/web/client/components/map/openlayers/VectorStyle.js b/web/client/components/map/openlayers/VectorStyle.js index ec51973c44..e873d6f456 100644 --- a/web/client/components/map/openlayers/VectorStyle.js +++ b/web/client/components/map/openlayers/VectorStyle.js @@ -123,9 +123,9 @@ const STYLE_TEXT = { fontStyle: 'normal', fontSize: '14', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: "14px FontAwesome", + font: "14px Arial", textAlign: 'center', color: '#000000', opacity: 1 diff --git a/web/client/components/mapcontrols/annotations/AnnotationsEditor.jsx b/web/client/components/mapcontrols/annotations/AnnotationsEditor.jsx index 38cdf9075f..d835d3b552 100644 --- a/web/client/components/mapcontrols/annotations/AnnotationsEditor.jsx +++ b/web/client/components/mapcontrols/annotations/AnnotationsEditor.jsx @@ -101,6 +101,7 @@ const bbox = require('@turf/bbox'); * @prop {function} onDownload triggered when the user exports * @prop {boolean} coordinateEditorEnabled triggered when the user zooms to an annotation * @prop {object} selected Feature containing the geometry and the properties used for the coordinated editor + * @prop {object} aeronauticalOptions options for aeronautical format (seconds decimals and step) * @prop {number} maxZoom max zoome the for annotation (default 18) * @prop {function} onDeleteFeature triggered when user click on trash icon of the coordinate editor * @prop {number} width of the annotation panel @@ -177,6 +178,7 @@ class AnnotationsEditor extends React.Component { onDownload: PropTypes.func, onChangeFormat: PropTypes.func, format: PropTypes.string, + aeronauticalOptions: PropTypes.object, onDeleteFeature: PropTypes.func }; @@ -549,6 +551,7 @@ class AnnotationsEditor extends React.Component { : ; diff --git a/web/client/components/mapcontrols/annotations/CoordinatesEditor.jsx b/web/client/components/mapcontrols/annotations/CoordinatesEditor.jsx index d5b67ffed6..a9e114dccc 100644 --- a/web/client/components/mapcontrols/annotations/CoordinatesEditor.jsx +++ b/web/client/components/mapcontrols/annotations/CoordinatesEditor.jsx @@ -40,6 +40,7 @@ class CoordinateEditor extends React.Component { onChangeText: PropTypes.func, onChangeFormat: PropTypes.func, format: PropTypes.string, + aeronauticalOptions: PropTypes.object, componentsValidation: PropTypes.object, transitionProps: PropTypes.object, properties: PropTypes.object, @@ -214,6 +215,7 @@ class CoordinateEditor extends React.Component { {this.props.components.map((component, idx) => {}} onChangeRadius={this.props.onChangeRadius} + aeronauticalOptions={this.props.aeronauticalOptions} onChangeFormat={this.props.onChangeFormat} format={this.props.format} onHighlightPoint={this.props.onHighlightPoint} diff --git a/web/client/components/mapcontrols/annotations/editors/AeronauticalCoordinateEditor.jsx b/web/client/components/mapcontrols/annotations/editors/AeronauticalCoordinateEditor.jsx index 161574e40a..6b49c498f3 100644 --- a/web/client/components/mapcontrols/annotations/editors/AeronauticalCoordinateEditor.jsx +++ b/web/client/components/mapcontrols/annotations/editors/AeronauticalCoordinateEditor.jsx @@ -12,7 +12,7 @@ const decimalToAeronautical = require('../enhancers/decimalToAeronautical'); const coordinateTypePreset = require('../enhancers/coordinateTypePreset'); const tempAeronauticalValue = require('../enhancers/tempAeronauticalValue'); -class CoordinateEntry extends React.Component { +class AeronauticalCoordinateEditor extends React.Component { static propTypes = { idx: PropTypes.number, @@ -22,13 +22,20 @@ class CoordinateEntry extends React.Component { seconds: PropTypes.number, directions: PropTypes.array, direction: PropTypes.string, + aeronauticalOptions: PropTypes.object, coordinate: PropTypes.string, onChange: PropTypes.func }; static defaultProps = { coordinate: "lat", maxDegrees: 90, - directions: ["N", "S"] + directions: ["N", "S"], + aeronauticalOptions: { + seconds: { + decimals: 4, + step: 0.0001 + } + } } onChange = (part, newValue) => { @@ -93,6 +100,7 @@ class CoordinateEntry extends React.Component { width: 0, height: 0 }; + const {step: stepSeconds} = this.props.aeronauticalOptions.seconds; return ( this.onChange("seconds", parseFloat(e.target.value))} - step={1} + step={stepSeconds} max={60} min={-1} - style={{ width: 65, ...inputStyle, ...secondsInvalidStyle}} + style={{ width: 80, ...inputStyle, ...secondsInvalidStyle}} type="number" /> @@ -137,7 +145,6 @@ class CoordinateEntry extends React.Component { onChange={e => this.onChange("direction", e.target.value)} style={{ width: 65 }}> {this.props.directions.map((d) => )} - ); @@ -163,4 +170,4 @@ module.exports = compose( coordinateTypePreset, decimalToAeronautical, tempAeronauticalValue -)(CoordinateEntry); +)(AeronauticalCoordinateEditor); diff --git a/web/client/components/mapcontrols/annotations/enhancers/__tests__/decimalToAeronautical-test.js b/web/client/components/mapcontrols/annotations/enhancers/__tests__/decimalToAeronautical-test.js index f3941a94ed..1696e4b1ff 100644 --- a/web/client/components/mapcontrols/annotations/enhancers/__tests__/decimalToAeronautical-test.js +++ b/web/client/components/mapcontrols/annotations/enhancers/__tests__/decimalToAeronautical-test.js @@ -38,6 +38,22 @@ describe("test the Annotations enahncers", () => { coordinate="lon" />), document.getElementById("container")); }); + it('decimalToAeronautical conversion to 4 decimals as seconds', (done) => { + const Sink = decimalToAeronautical(createSink( props => { + expect(props).toExist(); + expect(props.degrees).toBe(1); + expect(props.minutes).toBe(33); + expect(props.seconds).toBe(18.9193); + done(); + })); + ReactDOM.render((), document.getElementById("container")); + }); it('decimalToAeronautical conversion correctly step on minutes and seconds', (done) => { // 13.3333333333 should be 13 degrees, 20 minutes const Sink = decimalToAeronautical(createSink(props => { diff --git a/web/client/components/mapcontrols/annotations/enhancers/decimalToAeronautical.js b/web/client/components/mapcontrols/annotations/enhancers/decimalToAeronautical.js index 89728d4de1..71f23fbad5 100644 --- a/web/client/components/mapcontrols/annotations/enhancers/decimalToAeronautical.js +++ b/web/client/components/mapcontrols/annotations/enhancers/decimalToAeronautical.js @@ -1,12 +1,13 @@ const {compose, withHandlers, withProps} = require('recompose'); +const {round} = require('lodash'); -const convertDDToDMS = (D, lng) => { +const convertDDToDMS = (D, lng, {seconds} = {seconds: {decimals: 4}}) => { let d = parseInt(D, 10); let minFloat = Math.abs((D - d) * 60); let m = Math.floor(minFloat); let secFloat = (minFloat - m) * 60; - let s = Math.round(secFloat); + let s = round(secFloat, seconds.decimals); d = Math.abs(d); if (s === 60) { @@ -29,10 +30,11 @@ const convertDDToDMS = (D, lng) => { module.exports = compose( withProps(({ value, - coordinate + coordinate, + aeronauticalOptions }) => { return { - ...convertDDToDMS(value, coordinate === "lon") + ...convertDDToDMS(value, coordinate === "lon", aeronauticalOptions) }; }), withHandlers({ @@ -42,7 +44,9 @@ module.exports = compose( } // conversion dmsToDD let dd = degrees + minutes / 60 + seconds / (60 * 60); - if (direction === 'S' || direction === 'W') { + + // this change is needed you have 0 as degrees and a negative minutes or seconds i.e direction swapping side is caused by minutes or seconds being negative + if (dd > 0 && (direction === 'S' || direction === 'W') || dd < 0 && (direction === 'N' || direction === 'E')) { dd = dd * -1; } // Don't do anything for N or E diff --git a/web/client/components/style/TextStyler.jsx b/web/client/components/style/TextStyler.jsx index dd54eba1d9..78b930ff20 100644 --- a/web/client/components/style/TextStyler.jsx +++ b/web/client/components/style/TextStyler.jsx @@ -44,13 +44,13 @@ class TextStyler extends React.Component { fontWeightValues: [{value: "normal"}, {value: "bold"}], alignValues: [{value: "start", label: "left"}, {value: "center", label: "center"}, {value: "end", label: "right"}], fontStyleValues: [{value: "normal"}, {value: "italic"}], - fontFamilyValues: [{value: "Arial"}, {value: "FontAwesome"}, {value: "Courier"}], + fontFamilyValues: [{value: "Arial"}, {value: "Helvetica"}, {value: "sans-serif"}, {value: "Courier"}], shapeStyle: {}, setStyleParameter: () => {} }; state = { - fontFamily: "FontAwesome" + fontFamily: "Arial" }; render() { @@ -98,7 +98,7 @@ class TextStyler extends React.Component { { let fontFamily = e.value ? e.value : e; if (fontFamily === "") { - fontFamily = "FontAwesome"; + fontFamily = "Arial"; } this.setState({fontFamily}); const font = createFont({...style, fontFamily}); diff --git a/web/client/epics/annotations.js b/web/client/epics/annotations.js index 1d31ef6af4..02de1eca83 100644 --- a/web/client/epics/annotations.js +++ b/web/client/epics/annotations.js @@ -491,15 +491,21 @@ module.exports = (viewer) => ({ selected = set("geometry.coordinates", [selected.geometry.coordinates].filter(validateCoordsArray)[0] || [], selected); selected = set("geometry.type", "Point", selected); let selectedIndex = findIndex(feature.features, (f) => f.properties.id === selected.properties.id); - if (selected.properties.isValidFeature) { + if (validateCoordsArray(selected.geometry.coordinates) ) { + // if it has at least the coords valid draw the small circle for the text, + // text will be drawn if present if (selectedIndex === -1) { feature = set(`features`, feature.features.concat([selected]), feature); } else { feature = set(`features[${selectedIndex}]`, selected, feature); } } else { + // if coords ar not valid do not draw anything + selected = set("geometry", null, selected); if (selectedIndex !== -1) { - feature = set(`features`, feature.features.filter((f, i) => i !== selectedIndex ), feature); + feature = set(`features[${selectedIndex}]`, selected, feature); + } else { + feature = set(`features`, feature.features.concat([selected]), feature); } } const action = changeDrawingStatus("drawOrEdit", "Text", "annotations", [feature], { diff --git a/web/client/reducers/__tests__/annotations-test.js b/web/client/reducers/__tests__/annotations-test.js index 73e2709851..50a4dd08ae 100644 --- a/web/client/reducers/__tests__/annotations-test.js +++ b/web/client/reducers/__tests__/annotations-test.js @@ -929,6 +929,7 @@ describe('Test the annotations reducer', () => { }, changeText(text, components)); expect(state.editing.features[0].properties.valueText).toBe(text); expect(state.selected.properties.valueText).toBe(text); + expect(state.selected.properties.isValidFeature).toBe(true); expect(state.selected.properties.canEdit).toBe(true); expect(state.selected.geometry.coordinates[0]).toBe(1); expect(state.selected.geometry.coordinates[1]).toBe(0); @@ -1014,6 +1015,7 @@ describe('Test the annotations reducer', () => { }, changeRadius(radius, components)); expect(state.editing.features[0].properties.radius).toBe(radius); expect(state.selected.properties.radius).toBe(radius); + expect(state.selected.properties.isValidFeature).toBe(true); expect(state.selected.properties.canEdit).toBe(true); expect(state.selected.geometry.coordinates[0]).toBe(1); expect(state.selected.geometry.coordinates[1]).toBe(0); diff --git a/web/client/reducers/__tests__/mapInfo-test.js b/web/client/reducers/__tests__/mapInfo-test.js index 5f457e2da1..843aa56a9c 100644 --- a/web/client/reducers/__tests__/mapInfo-test.js +++ b/web/client/reducers/__tests__/mapInfo-test.js @@ -1356,9 +1356,9 @@ describe('Test the mapInfo reducer', () => { fontStyle: 'normal', fontSize: '14', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: '14px FontAwesome', + font: '14px Arial', textAlign: 'center', color: '#000000', opacity: 1 diff --git a/web/client/reducers/annotations.js b/web/client/reducers/annotations.js index a75498a310..806d7dec51 100644 --- a/web/client/reducers/annotations.js +++ b/web/client/reducers/annotations.js @@ -229,7 +229,7 @@ function annotations(state = { validationErrors: {} }, action) { selected = set("properties.isValidFeature", validateFeature({ properties: selected.properties, components: getComponents({coordinates: action.components[0] || [], type: "Circle"}), - type: selected.geometry.type + type: "Circle" }), selected); selected = set("properties.center", action.components[0], selected); selected = set("geometry.coordinates", action.components[0], selected); @@ -271,7 +271,7 @@ function annotations(state = { validationErrors: {} }, action) { selected = set("properties.isValidFeature", validateFeature({ properties: selected.properties, components: getComponents({coordinates: action.components[0] || [], type: "Text"}), - type: selected.geometry.type + type: "Text" }), selected); selected = set("properties.isText", true, selected); selected = set("geometry.coordinates", action.components[0] || [[]], selected); diff --git a/web/client/selectors/__tests__/annotations-test.js b/web/client/selectors/__tests__/annotations-test.js index a8782528f6..f7b6b1c7fe 100644 --- a/web/client/selectors/__tests__/annotations-test.js +++ b/web/client/selectors/__tests__/annotations-test.js @@ -30,6 +30,7 @@ const { errorsSelector, configSelector, annotationsInfoSelector, + aeronauticalOptionsSelector, annotationSelector, annotationsListSelector } = require("../annotations"); @@ -244,7 +245,7 @@ const state = { } }, Text: { - font: '14px FontAwesome', + font: '14px Arial', color: '#1726E6', weight: 1, opacity: 1 @@ -284,9 +285,9 @@ const state = { fontStyle: 'normal', fontSize: '21', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: 'normal normal 21px FontAwesome', + font: 'normal normal 21px Arial', textAlign: 'center', color: '#A424C0', opacity: 1 @@ -380,9 +381,9 @@ const state = { fontStyle: 'normal', fontSize: '21', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: 'normal normal 21px FontAwesome', + font: 'normal normal 21px Arial', textAlign: 'center', color: '#A424C0', opacity: 1 @@ -401,9 +402,9 @@ const state = { fontStyle: 'normal', fontSize: '21', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: 'normal normal 21px FontAwesome', + font: 'normal normal 21px Arial', textAlign: 'center', color: '#A424C0', opacity: 1 @@ -521,17 +522,27 @@ describe('Test annotations selectors', () => { expect(retVal.removing).toBe(null); expect(retVal.filter).toBe(''); + }); + it('test aeronauticalOptionsSelector', () => { + const retVal = aeronauticalOptionsSelector(state); + expect(retVal).toBe(undefined); + + }); + it('test aeronauticalOptionsSelector with true value', () => { + const retVal = aeronauticalOptionsSelector({annotations: {aeronauticalOptions: true}}); + expect(retVal).toBe(true); + }); it('test annotationsInfoSelector', () => { const retVal = annotationsInfoSelector(state); - expect(Object.keys(retVal).length).toBe(23); + expect(Object.keys(retVal).length).toBe(24); const params = ["closing", "config", "drawing", "drawingText", "errors", "editing", "coordinateEditorEnabled", "editedFields", "mode", "removing", "selected", "featureType", "showUnsavedChangesModal", "showUnsavedStyleModal", "showUnsavedGeometryModal", "showDeleteFeatureModal", "stylerType", "styling", "unsavedChanges", "unsavedStyle", - "unsavedGeometry", "format", "mouseHoverEvents" ]; + "unsavedGeometry", "format", "mouseHoverEvents", "aeronauticalOptions" ]; Object.keys(retVal).forEach(r => { expect(params.indexOf(r) !== -1).toBe(true); }); diff --git a/web/client/selectors/annotations.js b/web/client/selectors/annotations.js index a509a8b3df..9a05050de9 100644 --- a/web/client/selectors/annotations.js +++ b/web/client/selectors/annotations.js @@ -20,6 +20,7 @@ const annotationsLayerSelector = createSelector([ const removingSelector = (state) => get(state, "annotations.removing"); const formatSelector = (state) => get(state, "annotations.format"); +const aeronauticalOptionsSelector = (state) => get(state, "annotations.aeronauticalOptions"); const showUnsavedChangesModalSelector = (state) => get(state, "annotations.showUnsavedChangesModal", false); const showUnsavedStyleModalSelector = (state) => get(state, "annotations.showUnsavedStyleModal", false); const showUnsavedGeometryModalSelector = (state) => get(state, "annotations.showUnsavedGeometryModal", false); @@ -46,6 +47,7 @@ const annotationsInfoSelector = (state) => (assign({}, { mouseHoverEvents: isMapInfoOpen(state), closing: closingSelector(state), format: formatSelector(state), + aeronauticalOptions: aeronauticalOptionsSelector(state), config: configSelector(state), drawing: drawingSelector(state), drawingText: drawingTextSelector(state), @@ -78,6 +80,7 @@ const annotationsListSelector = createSelector([ annotationsLayerSelector ], (info, annotations, layer) => (assign({}, { format: annotations.format, + aeronauticalOptions: annotations.aeronauticalOptions, removing: annotations.removing, showUnsavedChangesModal: annotations.showUnsavedChangesModal, showUnsavedGeometryModal: annotations.showUnsavedGeometryModal, @@ -103,6 +106,7 @@ const annotationSelector = createSelector([annotationsListSelector], (annotation module.exports = { annotationsLayerSelector, annotationsInfoSelector, + aeronauticalOptionsSelector, annotationsSelector, annotationsListSelector, annotationSelector, diff --git a/web/client/test-resources/Annotation.json b/web/client/test-resources/Annotation.json index 4909d41e21..45f6996395 100644 --- a/web/client/test-resources/Annotation.json +++ b/web/client/test-resources/Annotation.json @@ -2311,8 +2311,8 @@ }, "Text": { "color": "#000000", - "font": "14px FontAwesome", - "fontFamily": "FontAwesome", + "font": "14px Arial", + "fontFamily": "Arial", "fontSize": "14", "fontSizeUom": "px", "fontStyle": "normal", @@ -2324,4 +2324,4 @@ "type": "GeometryCollection" }, "type": "Feature" -} \ No newline at end of file +} diff --git a/web/client/utils/AnnotationsUtils.js b/web/client/utils/AnnotationsUtils.js index 3d173ee985..3d85636234 100644 --- a/web/client/utils/AnnotationsUtils.js +++ b/web/client/utils/AnnotationsUtils.js @@ -32,9 +32,9 @@ const STYLE_TEXT = { fontStyle: 'normal', fontSize: '14', fontSizeUom: 'px', - fontFamily: 'FontAwesome', + fontFamily: 'Arial', fontWeight: 'normal', - font: "14px FontAwesome", + font: "14px Arial", textAlign: 'center', color: '#000000', opacity: 1 @@ -273,7 +273,7 @@ const AnnotationsUtils = { * it converts some props of a CSS-font into a shorhand form * @return {string} a CSS-font */ - createFont: ({fontSize = "14", fontSizeUom = "px", fontFamily = "FontAwesome", fontStyle = "normal", fontWeight = "normal"} = {}) => { + createFont: ({fontSize = "14", fontSizeUom = "px", fontFamily = "Arial", fontStyle = "normal", fontWeight = "normal"} = {}) => { return `${fontStyle} ${fontWeight} ${fontSize}${fontSizeUom} ${fontFamily}`; }, /** diff --git a/web/client/utils/PrintUtils.js b/web/client/utils/PrintUtils.js index 259a06139d..6c8cb7ec80 100644 --- a/web/client/utils/PrintUtils.js +++ b/web/client/utils/PrintUtils.js @@ -239,11 +239,16 @@ const PrintUtils = { "opacity": layer.opacity || 1.0, styleProperty: "ms_style", styles: { - 1: PrintUtils.toOpenLayers2Style(layer, layer.style) + 1: PrintUtils.toOpenLayers2Style(layer, layer.style), + "Polygon": PrintUtils.toOpenLayers2Style(layer, layer.style, "Polygon"), + "LineString": PrintUtils.toOpenLayers2Style(layer, layer.style, "LineString"), + "Point": PrintUtils.toOpenLayers2Style(layer, layer.style, "Point"), + "FeatureCollection": PrintUtils.toOpenLayers2Style(layer, layer.style, "FeatureCollection") }, geoJson: CoordinatesUtils.reprojectGeoJson({ type: "FeatureCollection", - features: layer.id === "annotations" && AnnotationsUtils.annotationsToPrint(layer.features) || layer.features.map( f => ({...f, properties: {...f.properties, ms_style: 1}})) + features: layer.id === "annotations" && AnnotationsUtils.annotationsToPrint(layer.features) || + layer.features.map( f => ({...f, properties: {...f.properties, ms_style: f && f.geometry && f.geometry.type && f.geometry.type.replace("Multi", "") || 1}})) }, "EPSG:4326", spec.projection) @@ -339,9 +344,9 @@ const PrintUtils = { * Useful for print (Or generic Openlayers 2 conversion style) * http://dev.openlayers.org/docs/files/OpenLayers/Feature/Vector-js.html#OpenLayers.Feature.Vector.OpenLayers.Feature.Vector.style */ - toOpenLayers2Style: function(layer, style) { + toOpenLayers2Style: function(layer, style, styleType) { if (!style) { - return PrintUtils.getOlDefaultStyle(layer); + return PrintUtils.getOlDefaultStyle(layer, styleType); } // commented the available options. return { @@ -376,8 +381,8 @@ const PrintUtils = { * Provides the default style for * each vector type. */ - getOlDefaultStyle(layer) { - switch (getGeomType(layer)) { + getOlDefaultStyle(layer, styleType) { + switch (styleType || getGeomType(layer)) { case 'Polygon': case 'MultiPolygon': { return { diff --git a/web/client/utils/__tests__/AnnotationsUtils-test.js b/web/client/utils/__tests__/AnnotationsUtils-test.js index 6ea68fc5e7..0c5f24ada8 100644 --- a/web/client/utils/__tests__/AnnotationsUtils-test.js +++ b/web/client/utils/__tests__/AnnotationsUtils-test.js @@ -139,12 +139,12 @@ describe('Test the AnnotationsUtils', () => { expect(textParams.length).toBe(9); const {font, color, opacity, fontStyle, fontSize, fontSizeUom, textAlign, fontFamily, fontWeight} = DEFAULT_ANNOTATIONS_STYLES.Text; - expect(font).toBe("14px FontAwesome"); + expect(font).toBe("14px Arial"); expect(color).toBe("#000000"); expect(fontStyle).toBe("normal"); expect(fontWeight).toBe("normal"); expect(fontSize).toBe("14"); - expect(fontFamily).toBe("FontAwesome"); + expect(fontFamily).toBe("Arial"); expect(fontSizeUom).toBe("px"); expect(textAlign).toBe("center"); expect(opacity).toBe(1); @@ -250,16 +250,14 @@ describe('Test the AnnotationsUtils', () => { }); it('create font with values', () => { // with defaults - expect(createFont({})).toBe("normal normal 14px FontAwesome"); - + expect(createFont({})).toBe("normal normal 14px Arial"); // with values expect(createFont({fontFamily: "Courier"})).toBe("normal normal 14px Courier"); - expect(createFont({fontSize: "30"})).toBe("normal normal 30px FontAwesome"); - expect(createFont({fontSizeUom: "em"})).toBe("normal normal 14em FontAwesome"); - expect(createFont({fontStyle: "italic"})).toBe("italic normal 14px FontAwesome"); - expect(createFont({fontWeight: "bold"})).toBe("normal bold 14px FontAwesome"); + expect(createFont({fontSize: "30"})).toBe("normal normal 30px Arial"); + expect(createFont({fontSizeUom: "em"})).toBe("normal normal 14em Arial"); + expect(createFont({fontStyle: "italic"})).toBe("italic normal 14px Arial"); + expect(createFont({fontWeight: "bold"})).toBe("normal bold 14px Arial"); }); - it('circlesToMultiPolygon', () => { const {geometry, properties, style} = feature; const f = circlesToMultiPolygon(geometry, properties, style.Circle); @@ -269,7 +267,6 @@ describe('Test the AnnotationsUtils', () => { expect(f.properties).toExist(); expect(f.properties.ms_style).toExist(); expect(f.properties.ms_style.strokeColor).toBe(style.Circle.color); - }); it('fromCircleToPolygon', () => { const {geometry, properties} = circle1; diff --git a/web/client/utils/__tests__/PrintUtils-test.js b/web/client/utils/__tests__/PrintUtils-test.js index 08dc2b8e1a..e97ea58a0f 100644 --- a/web/client/utils/__tests__/PrintUtils-test.js +++ b/web/client/utils/__tests__/PrintUtils-test.js @@ -14,7 +14,20 @@ const layer = { type: "wms", params: {myparam: "myvalue"} }; - +const featurePoint = { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -112.50042920000001, + 42.22829164089942 + ] + }, + "properties": { + "serial_num": "12C324776" + }, + "id": 0 +}; const vectorLayer = { "type": "vector", "visibility": true, @@ -22,22 +35,7 @@ const vectorLayer = { "id": "web2014all_mv__14", "name": "web2014all_mv", "hideLoading": true, - "features": [ - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -112.50042920000001, - 42.22829164089942 - ] - }, - "properties": { - "serial_num": "12C324776" - }, - "id": 0 - } - ], + "features": [ featurePoint ], "style": { "weight": 3, "radius": 10, @@ -47,6 +45,13 @@ const vectorLayer = { "fillColor": "rgb(0, 0, 255)" } }; +let vector2 = {...vectorLayer}; +delete vector2.style; +let vectorWithFtCollInside = {...vectorLayer, features: [{ + type: "FeatureCollection", + features: [featurePoint] +}]}; + const mapFishVectorLayer = { "type": "Vector", "name": "web2014all_mv", @@ -148,6 +153,35 @@ describe('PrintUtils', () => { expect(specs).toExist(); expect(specs.length).toBe(1); }); + it('toOpenLayers2Style for vector layer wich contains a FeatureCollection using the default style', () => { + const style = PrintUtils.toOpenLayers2Style(vectorWithFtCollInside, null, "FeatureCollection"); + expect(style).toExist(); + + expect(style.strokeColor).toBe("#0000FF"); + expect(style.strokeOpacity).toBe(1); + expect(style.strokeWidth).toBe(1); + expect(style.pointRadius).toBe(5); + expect(style.fillColor).toBe("#0000FF"); + expect(style.fillOpacity).toBe(0.1); + }); + it('toOpenLayers2Style for vector layer using a default LineString style', () => { + const style = PrintUtils.toOpenLayers2Style(vector2, null, "LineString"); + expect(style).toExist(); + expect(style.strokeColor).toBe("#0000FF"); + expect(style.strokeOpacity).toBe(1); + expect(style.strokeWidth).toBe(3); + }); + it('toOpenLayers2Style for vector layer using a default MultiPolygon style', () => { + const style = PrintUtils.toOpenLayers2Style(vector2, null, "MultiPolygon"); + expect(style).toExist(); + expect(style.strokeColor).toBe("#0000FF"); + expect(style.fillColor).toBe("#0000FF"); + expect(style.fillOpacity).toBe(0.1); + expect(style.strokeOpacity).toBe(1); + expect(style.strokeLinecap).toBe("round"); + expect(style.strokeDashstyle).toBe("dash"); + expect(style.strokeWidth).toBe(3); + }); it('wms layer generation for legend includes scale', () => { const specs = PrintUtils.getMapfishLayersSpecification([layer], testSpec, 'legend'); expect(specs).toExist();