• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 19710972030

26 Nov 2025 03:38PM UTC coverage: 76.665% (-0.3%) from 76.929%
19710972030

Pull #11119

github

web-flow
Fix maven publish (#11739)
Pull Request #11119: Layer Selection Plugin on ArcGIS, WFS & WMS layers

32272 of 50209 branches covered (64.28%)

3 of 3 new or added lines in 2 files covered. (100.0%)

3018 existing lines in 249 files now uncovered.

40157 of 52380 relevant lines covered (76.66%)

37.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.78
/web/client/components/map/openlayers/snapshot/GrabMap.jsx
1
/**
2
 * Copyright 2015, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import './snapshotMapStyle.css';
10
import '../../../map/openlayers/plugins/index';
11

12
import PropTypes from 'prop-types';
13
import React from 'react';
14

15
import ConfigUtils from '../../../../utils/ConfigUtils';
16
import {
17
    Feature,
18
    LLayer,
19
    LMap
20
} from '../index';
21

22
/**
23
 * GrabMap for OpenLayers map generate a fake-map, hidden, and waits for the
24
 * layer loading end to generate the snapshot from the canvas.
25
 * In order to avoid cross origin issues, the allowTaint property have to be set
26
 * to false if you are not sure that the items come from the same orgin.
27
 */
28
export default class GrabOlMap extends React.Component {
29
    static propTypes = {
1✔
30
        id: PropTypes.node,
31
        config: ConfigUtils.PropTypes.config,
32
        layers: PropTypes.array,
33
        snapstate: PropTypes.object,
34
        active: PropTypes.bool,
35
        onSnapshotReady: PropTypes.func,
36
        onStatusChange: PropTypes.func,
37
        onSnapshotError: PropTypes.func,
38
        allowTaint: PropTypes.bool
39
    };
40

41
    static defaultProps = {
1✔
42
        config: null,
43
        layers: [],
44
        snapstate: {state: "DISABLED"},
45
        active: false,
46
        onSnapshotReady: () => {},
47
        onStatusChange: () => {},
48
        onSnapshotError: () => {}
49
    };
50

51
    renderLayers = (layers) => {
2✔
52
        if (layers) {
1!
53
            let projection = this.props.config.projection || 'EPSG:3857';
1!
54
            let me = this; // TODO find the reason why the arrow function doesn't get this object
1✔
55
            return layers.map((layer, index) => {
1✔
56
                var options = Object.assign({}, layer, {srs: projection}, layer.type === "wms" ? {forceProxy: !this.props.allowTaint} : {});
2!
57
                return (<LLayer type={layer.type} position={index} key={layer.id || layer.name} options={options}>
2✔
58
                    {me.renderLayerContent(layer)}
59
                </LLayer>);
60
            });
61
        }
UNCOV
62
        return null;
×
63
    };
64

65
    renderLayerContent = (layer) => {
2✔
66
        if (layer.features && layer.type === "vector") {
2✔
67
            // TODO remove this DIV. What container can be used for this component.
68
            return layer.features.map( (feature) => {
1✔
69
                return (<Feature
1✔
70
                    key={feature.id}
71
                    type={feature.type}
72
                    geometry={feature.geometry}/>);
73
            });
74
        }
75
        return null;
1✔
76
    };
77

78
    shouldComponentUpdate(nextProps) {
79
        return nextProps.active || nextProps.active !== this.props.active;
1!
80
    }
81

82
    componentDidUpdate() {
83
        if (!this.props.active) {
1!
UNCOV
84
            this.props.onStatusChange("DISABLED");
×
85
            if (this.props.snapstate.error) {
×
86
                this.props.onSnapshotError(null);
×
87
            }
88
        }
89
    }
90

91
    render() {
92
        return this.props.active ?
3✔
93
            <LMap id={"snapshot_hidden_map-" + this.props.id}
94
                className="snapshot_hidden_map"
95
                style={{
96
                    width: this.props.config && this.props.config.size ? this.props.config.size.width : "100%",
3!
97
                    height: this.props.config && this.props.config.size ? this.props.config.size.height : "100%"
3!
98
                }}
99
                center={this.props.config.center}
100
                zoom={this.props.config.zoom}
101
                mapStateSource={this.props.config.mapStateSource}
102
                projection={this.props.config.projection || 'EPSG:3857'}
1!
103
                zoomControl={false}
104
                onLayerLoading={this.layerLoading}
105
                onLayerLoad={this.layerLoad}
106
                ref={"snapMap"}
107
            >
108
                {this.renderLayers(this.props.layers)}
109
            </LMap>
110
            : null;
111
    }
112

113
    layerLoad = () => {
2✔
114
        this.toLoad--;
3✔
115
        if (this.toLoad === 0) {
3✔
116
            let map = this.refs.snapMap ? this.refs.snapMap.map : null;
1!
117
            if (map) {
1!
118
                map.once('postrender', (e) => setTimeout( () => {
1✔
119
                    let canvas = e.map && e.map.getTargetElement() && e.map.getTargetElement().getElementsByTagName("canvas")[0];
1!
120
                    if (canvas) {
1!
UNCOV
121
                        this.createSnapshot(canvas);
×
122
                    }
123
                }, 500));
124
                // map.once('postcompose', (e) => setTimeout( () => this.createSnapshot(e.context.canvas), 100));
125
            }
126
        }
127
    };
128

129
    layerLoading = () => {
2✔
130
        if (this.props.snapstate.state !== "SHOTING") {
1!
131
            this.props.onStatusChange("SHOTING");
1✔
132

133
        }
134
        this.toLoad = this.toLoad ? this.toLoad : 0;
1!
135
        this.toLoad++;
1✔
136
    };
137

138
    createSnapshot = (canvas) => {
2✔
139
        this.props.onSnapshotReady(canvas, null, null, null, this.isTainted(canvas));
1✔
140
    };
141

142
    /**
143
     * Check if the canvas is tainted, so if it is allowed to export images
144
     * from it.
145
     */
146
    isTainted = (canvas) => {
2✔
147
        if (canvas) {
1!
UNCOV
148
            let ctx = canvas.getContext("2d");
×
149
            try {
×
150
                // try to generate a small image
UNCOV
151
                ctx.getImageData(0, 0, 1, 1);
×
152
                return false;
×
153
            } catch (err) {
154
                // check the error code for tainted resources
UNCOV
155
                return err.code === 18;
×
156
            }
157
        }
158
        return false;
1✔
159
    };
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc