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

geosolutions-it / MapStore2 / 15633115676

13 Jun 2025 11:08AM UTC coverage: 77.044% (-0.006%) from 77.05%
15633115676

push

github

web-flow
Revert "#11153: Persist Swipe Layer state after map refresh (#11158) (#11202)" (#11204)

This reverts commit 644bb7b52.

30818 of 47862 branches covered (64.39%)

38294 of 49704 relevant lines covered (77.04%)

36.32 hits per line

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

73.33
/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 assign from 'object-assign';
13
import PropTypes from 'prop-types';
14
import React from 'react';
15

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

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

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

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

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

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

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

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

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

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

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

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

143
    /**
144
     * Check if the canvas is tainted, so if it is allowed to export images
145
     * from it.
146
     */
147
    isTainted = (canvas) => {
2✔
148
        if (canvas) {
1!
149
            let ctx = canvas.getContext("2d");
×
150
            try {
×
151
                // try to generate a small image
152
                ctx.getImageData(0, 0, 1, 1);
×
153
                return false;
×
154
            } catch (err) {
155
                // check the error code for tainted resources
156
                return err.code === 18;
×
157
            }
158
        }
159
        return false;
1✔
160
    };
161
}
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

© 2026 Coveralls, Inc