react-spatial 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/conventional-pr-title.yml +21 -0
- package/.github/workflows/main.yml +28 -0
- package/.husky/commit-msg +4 -0
- package/.husky/post-checkout +4 -0
- package/.husky/post-merge +4 -0
- package/.husky/post-rebase +4 -0
- package/.husky/pre-commit +4 -0
- package/.nvmrc +1 -0
- package/.whitesource +8 -0
- package/CHANGELOG.md +54 -0
- package/DEVELOP.md +113 -0
- package/README.md +1 -1
- package/__mocks__/mapbox-gl.js +11 -0
- package/__mocks__/resize-observer-polyfill.js +9 -0
- package/babel.config.js +3 -0
- package/commitlint.config.js +1 -0
- package/data/topic1.js +119 -0
- package/data/topic2.js +28 -0
- package/doc/README.md +21 -0
- package/doc/doc-config.json +4 -0
- package/netlify.toml +3 -0
- package/package.json +30 -41
- package/pull_request_template.md +16 -0
- package/renovate.json +4 -0
- package/scripts/read-pkg-json.js +17 -0
- package/src/components/BaseLayerSwitcher/BaseLayerSwitcher.js +322 -0
- package/src/components/BaseLayerSwitcher/BaseLayerSwitcher.test.js +69 -0
- package/src/components/BaseLayerSwitcher/README.md +61 -0
- package/src/components/BaseLayerSwitcher/__snapshots__/BaseLayerSwitcher.test.js.snap +88 -0
- package/src/components/BaseLayerSwitcher/index.js +1 -0
- package/src/components/BasicMap/BasicMap.js +413 -0
- package/src/components/BasicMap/BasicMap.test.js +281 -0
- package/src/components/BasicMap/README.md +18 -0
- package/src/components/BasicMap/index.js +1 -0
- package/{components → src/components}/CanvasSaveButton/CanvasSaveButton.js +320 -93
- package/src/components/CanvasSaveButton/CanvasSaveButton.test.js +148 -0
- package/src/components/CanvasSaveButton/README.md +76 -0
- package/src/components/CanvasSaveButton/__snapshots__/CanvasSaveButton.test.js.snap +76 -0
- package/src/components/CanvasSaveButton/index.js +1 -0
- package/src/components/Copyright/Copyright.js +89 -0
- package/src/components/Copyright/Copyright.test.js +134 -0
- package/src/components/Copyright/README.md +36 -0
- package/src/components/Copyright/index.js +1 -0
- package/src/components/FeatureExportButton/FeatureExportButton.js +118 -0
- package/src/components/FeatureExportButton/FeatureExportButton.test.js +417 -0
- package/src/components/FeatureExportButton/README.md +76 -0
- package/src/components/FeatureExportButton/__snapshots__/FeatureExportButton.test.js.snap +67 -0
- package/src/components/FeatureExportButton/index.js +1 -0
- package/src/components/FitExtent/FitExtent.js +62 -0
- package/src/components/FitExtent/FitExtent.test.js +48 -0
- package/src/components/FitExtent/README.md +34 -0
- package/src/components/FitExtent/__snapshots__/FitExtent.test.js.snap +13 -0
- package/src/components/FitExtent/index.js +1 -0
- package/{components → src/components}/Geolocation/Geolocation.js +144 -61
- package/src/components/Geolocation/Geolocation.test.js +267 -0
- package/src/components/Geolocation/README.md +25 -0
- package/src/components/Geolocation/__snapshots__/Geolocation.test.js.snap +92 -0
- package/src/components/Geolocation/index.js +1 -0
- package/src/components/LayerTree/LayerTree.js +487 -0
- package/src/components/LayerTree/LayerTree.test.js +337 -0
- package/src/components/LayerTree/README.md +92 -0
- package/src/components/LayerTree/__snapshots__/LayerTree.test.js.snap +1746 -0
- package/src/components/LayerTree/index.js +1 -0
- package/src/components/MousePosition/MousePosition.js +175 -0
- package/src/components/MousePosition/MousePosition.test.js +132 -0
- package/src/components/MousePosition/README.md +50 -0
- package/src/components/MousePosition/__snapshots__/MousePosition.test.js.snap +76 -0
- package/src/components/MousePosition/index.js +1 -0
- package/src/components/NorthArrow/NorthArrow.js +75 -0
- package/src/components/NorthArrow/NorthArrow.test.js +104 -0
- package/src/components/NorthArrow/README.md +59 -0
- package/src/components/NorthArrow/__snapshots__/NorthArrow.test.js.snap +117 -0
- package/src/components/NorthArrow/index.js +1 -0
- package/src/components/Overlay/Overlay.js +176 -0
- package/src/components/Overlay/Overlay.test.js +149 -0
- package/src/components/Overlay/README.md +59 -0
- package/src/components/Overlay/__snapshots__/Overlay.test.js.snap +9 -0
- package/src/components/Overlay/index.js +1 -0
- package/src/components/Permalink/Permalink.js +326 -0
- package/src/components/Permalink/Permalink.test.js +285 -0
- package/src/components/Permalink/README.md +105 -0
- package/src/components/Permalink/index.js +1 -0
- package/{components → src/components}/Popup/Popup.js +165 -55
- package/src/components/Popup/Popup.test.js +307 -0
- package/src/components/Popup/README.md +93 -0
- package/src/components/Popup/__snapshots__/Popup.test.js.snap +180 -0
- package/src/components/Popup/index.js +1 -0
- package/src/components/README.md +41 -0
- package/{components → src/components}/ResizeHandler/ResizeHandler.js +50 -15
- package/src/components/ResizeHandler/ResizeHandler.test.js +344 -0
- package/src/components/ResizeHandler/index.js +1 -0
- package/src/components/RouteSchedule/README.md +118 -0
- package/src/components/RouteSchedule/RouteSchedule.js +364 -0
- package/src/components/RouteSchedule/RouteSchedule.test.js +113 -0
- package/src/components/RouteSchedule/__snapshots__/RouteSchedule.test.js.snap +248 -0
- package/src/components/RouteSchedule/index.js +1 -0
- package/src/components/ScaleLine/README.md +29 -0
- package/src/components/ScaleLine/ScaleLine.js +50 -0
- package/src/components/ScaleLine/ScaleLine.test.js +30 -0
- package/src/components/ScaleLine/__snapshots__/ScaleLine.test.js.snap +7 -0
- package/src/components/ScaleLine/index.js +1 -0
- package/src/components/StopsFinder/README.md +50 -0
- package/src/components/StopsFinder/StopsFinder.js +284 -0
- package/src/components/StopsFinder/StopsFinder.test.js +17 -0
- package/src/components/StopsFinder/StopsFinderOption.js +61 -0
- package/src/components/StopsFinder/__snapshots__/StopsFinder.test.js.snap +133 -0
- package/src/components/StopsFinder/index.js +1 -0
- package/src/components/Zoom/README.md +25 -0
- package/src/components/Zoom/Zoom.js +180 -0
- package/src/components/Zoom/Zoom.test.js +141 -0
- package/src/components/Zoom/__snapshots__/Zoom.test.js.snap +201 -0
- package/src/components/Zoom/index.js +1 -0
- package/{propTypes.js → src/propTypes.js} +16 -12
- package/{setupTests.js → src/setupTests.js} +1 -1
- package/src/styleguidist/ComponentsList.js +52 -0
- package/src/styleguidist/StyleGuide.js +277 -0
- package/src/styleguidist/styleguidist.css +38 -0
- package/src/utils/GlobalsForOle.js +99 -0
- package/src/utils/KML.js +594 -0
- package/src/utils/KML.test.js +337 -0
- package/src/utils/KMLFormat.js +100 -0
- package/src/utils/KMLFormat.test.js +50 -0
- package/{utils → src/utils}/Styles.js +20 -14
- package/src/utils/__snapshots__/KML.test.js.snap.KML-readFeatures()-and-writeFeatures()-should-read-and-write-lineDash-and-fillPattern-style-for-polygon.canvas-image.png +0 -0
- package/src/utils/__snapshots__/getPolygonPattern.test.js.snap.getPolygonPattern()-render-pattern-2-(cross)-color-and-(light-blue)-opacity.canvas-image.png +0 -0
- package/src/utils/__snapshots__/getPolygonPattern.test.js.snap.getPolygonPattern()-render-pattern-3-(diagonal-line-from-bottom-left-tot-top-right)-with-color-(light-blue)-and-opacity.canvas-image.png +0 -0
- package/src/utils/__snapshots__/getPolygonPattern.test.js.snap.getPolygonPattern()-render-pattern-4-(diagonal-line-from-top-left-to-bottom-right)-with-color-(light-blue)-and-opacity.canvas-image.png +0 -0
- package/{utils → src/utils}/getPolygonPattern.js +34 -6
- package/src/utils/getPolygonPattern.test.js +61 -0
- package/{utils → src/utils}/timeUtils.js +22 -5
- package/src/utils/timeUtils.test.js +30 -0
- package/styleguide.config.js +251 -0
- package/components/BaseLayerSwitcher/BaseLayerSwitcher.js +0 -231
- package/components/BaseLayerSwitcher/BaseLayerSwitcher.js.map +0 -7
- package/components/BaseLayerSwitcher/index.js +0 -1
- package/components/BaseLayerSwitcher/index.js.map +0 -7
- package/components/BasicMap/BasicMap.js +0 -278
- package/components/BasicMap/BasicMap.js.map +0 -7
- package/components/BasicMap/index.js +0 -1
- package/components/BasicMap/index.js.map +0 -7
- package/components/CanvasSaveButton/CanvasSaveButton.js.map +0 -7
- package/components/CanvasSaveButton/index.js +0 -1
- package/components/CanvasSaveButton/index.js.map +0 -7
- package/components/Copyright/Copyright.js +0 -55
- package/components/Copyright/Copyright.js.map +0 -7
- package/components/Copyright/index.js +0 -1
- package/components/Copyright/index.js.map +0 -7
- package/components/FeatureExportButton/FeatureExportButton.js +0 -62
- package/components/FeatureExportButton/FeatureExportButton.js.map +0 -7
- package/components/FeatureExportButton/index.js +0 -1
- package/components/FeatureExportButton/index.js.map +0 -7
- package/components/FitExtent/FitExtent.js +0 -32
- package/components/FitExtent/FitExtent.js.map +0 -7
- package/components/FitExtent/index.js +0 -1
- package/components/FitExtent/index.js.map +0 -7
- package/components/Geolocation/Geolocation.js.map +0 -7
- package/components/Geolocation/index.js +0 -1
- package/components/Geolocation/index.js.map +0 -7
- package/components/LayerTree/LayerTree.js +0 -278
- package/components/LayerTree/LayerTree.js.map +0 -7
- package/components/LayerTree/index.js +0 -1
- package/components/LayerTree/index.js.map +0 -7
- package/components/MousePosition/MousePosition.js +0 -110
- package/components/MousePosition/MousePosition.js.map +0 -7
- package/components/MousePosition/index.js +0 -1
- package/components/MousePosition/index.js.map +0 -7
- package/components/NorthArrow/NorthArrow.js +0 -43
- package/components/NorthArrow/NorthArrow.js.map +0 -7
- package/components/NorthArrow/index.js +0 -1
- package/components/NorthArrow/index.js.map +0 -7
- package/components/Overlay/Overlay.js +0 -122
- package/components/Overlay/Overlay.js.map +0 -7
- package/components/Overlay/index.js +0 -1
- package/components/Overlay/index.js.map +0 -7
- package/components/Permalink/Permalink.js +0 -206
- package/components/Permalink/Permalink.js.map +0 -7
- package/components/Permalink/index.js +0 -1
- package/components/Permalink/index.js.map +0 -7
- package/components/Popup/Popup.js.map +0 -7
- package/components/Popup/index.js +0 -1
- package/components/Popup/index.js.map +0 -7
- package/components/ResizeHandler/ResizeHandler.js.map +0 -7
- package/components/ResizeHandler/index.js +0 -1
- package/components/ResizeHandler/index.js.map +0 -7
- package/components/RouteSchedule/RouteSchedule.js +0 -220
- package/components/RouteSchedule/RouteSchedule.js.map +0 -7
- package/components/RouteSchedule/index.js +0 -1
- package/components/RouteSchedule/index.js.map +0 -7
- package/components/ScaleLine/ScaleLine.js +0 -32
- package/components/ScaleLine/ScaleLine.js.map +0 -7
- package/components/ScaleLine/index.js +0 -1
- package/components/ScaleLine/index.js.map +0 -7
- package/components/StopsFinder/StopsFinder.js +0 -210
- package/components/StopsFinder/StopsFinder.js.map +0 -7
- package/components/StopsFinder/StopsFinderOption.js +0 -50
- package/components/StopsFinder/StopsFinderOption.js.map +0 -7
- package/components/StopsFinder/index.js +0 -1
- package/components/StopsFinder/index.js.map +0 -7
- package/components/Zoom/Zoom.js +0 -120
- package/components/Zoom/Zoom.js.map +0 -7
- package/components/Zoom/index.js +0 -1
- package/components/Zoom/index.js.map +0 -7
- package/propTypes.js.map +0 -7
- package/setupTests.js.map +0 -7
- package/utils/GlobalsForOle.js +0 -94
- package/utils/GlobalsForOle.js.map +0 -7
- package/utils/KML.js +0 -412
- package/utils/KML.js.map +0 -7
- package/utils/KMLFormat.js +0 -69
- package/utils/KMLFormat.js.map +0 -7
- package/utils/Styles.js.map +0 -7
- package/utils/getPolygonPattern.js.map +0 -7
- package/utils/timeUtils.js.map +0 -7
- /package/{components → src/components}/BaseLayerSwitcher/BaseLayerSwitcher.md.scss +0 -0
- /package/{components → src/components}/BaseLayerSwitcher/BaseLayerSwitcher.scss +0 -0
- /package/{components → src/components}/BasicMap/BasicMap.md.scss +0 -0
- /package/{components → src/components}/CanvasSaveButton/CanvasSaveButton.md.scss +0 -0
- /package/{components → src/components}/Copyright/Copyright.md.scss +0 -0
- /package/{components → src/components}/FeatureExportButton/FeatureExportButton.md.scss +0 -0
- /package/{components → src/components}/FitExtent/FitExtent.md.scss +0 -0
- /package/{components → src/components}/Geolocation/Geolocation.md.scss +0 -0
- /package/{components → src/components}/Geolocation/Geolocation.scss +0 -0
- /package/{components → src/components}/LayerTree/LayerTree.md.scss +0 -0
- /package/{components → src/components}/LayerTree/LayerTree.scss +0 -0
- /package/{components → src/components}/MousePosition/MousePosition.md.scss +0 -0
- /package/{components → src/components}/NorthArrow/NorthArrow.scss +0 -0
- /package/{components → src/components}/Overlay/Overlay.md.scss +0 -0
- /package/{components → src/components}/Overlay/Overlay.scss +0 -0
- /package/{components → src/components}/Permalink/Permalink.md.scss +0 -0
- /package/{components → src/components}/Popup/Popup.md.scss +0 -0
- /package/{components → src/components}/Popup/Popup.scss +0 -0
- /package/{components → src/components}/RouteSchedule/RouteSchedule.md.scss +0 -0
- /package/{components → src/components}/RouteSchedule/RouteSchedule.scss +0 -0
- /package/{components → src/components}/ScaleLine/ScaleLine.scss +0 -0
- /package/{components → src/components}/Zoom/Zoom.md.scss +0 -0
- /package/{components → src/components}/Zoom/Zoom.scss +0 -0
- /package/{images → src/images}/RouteSchedule/firstStation.png +0 -0
- /package/{images → src/images}/RouteSchedule/lastStation.png +0 -0
- /package/{images → src/images}/RouteSchedule/line.png +0 -0
- /package/{images → src/images}/RouteSchedule/station.png +0 -0
- /package/{images → src/images}/baselayer/baselayer.basebright.png +0 -0
- /package/{images → src/images}/baselayer/baselayer.osm.png +0 -0
- /package/{images → src/images}/baselayer/baselayer.travic.png +0 -0
- /package/{images → src/images}/baselayer/open.topo.map.png +0 -0
- /package/{images → src/images}/baselayer/osm.baselayer.hot.png +0 -0
- /package/{images → src/images}/baselayer/osm.baselayer.png +0 -0
- /package/{images → src/images}/favicon.png +0 -0
- /package/{images → src/images}/geops_logo.png +0 -0
- /package/{images → src/images}/geops_logo.svg +0 -0
- /package/{images → src/images}/geops_qr.png +0 -0
- /package/{images → src/images}/mots/bus_poi-blue-01.svg +0 -0
- /package/{images → src/images}/mots/bus_poi-grey-01.svg +0 -0
- /package/{images → src/images}/mots/bus_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/bus_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/bus_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/bus_square-grey-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_poi-blue-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_poi-grey-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/cable_car_square-grey-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_poi-blue-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_poi-grey-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/ferry_square-grey-01.svg +0 -0
- /package/{images → src/images}/mots/funicular_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/funicular_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/funicular_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/gondola_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/rail_poi-blue-01.svg +0 -0
- /package/{images → src/images}/mots/rail_poi-grey-01.svg +0 -0
- /package/{images → src/images}/mots/rail_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/rail_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/rail_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/rail_square-grey-01.svg +0 -0
- /package/{images → src/images}/mots/subway_round blue-01.svg +0 -0
- /package/{images → src/images}/mots/subway_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/tram_poi-blue-01.svg +0 -0
- /package/{images → src/images}/mots/tram_poi-grey-01.svg +0 -0
- /package/{images → src/images}/mots/tram_round-blue-01.svg +0 -0
- /package/{images → src/images}/mots/tram_round-grey-01.svg +0 -0
- /package/{images → src/images}/mots/tram_square-blue-01.svg +0 -0
- /package/{images → src/images}/mots/tram_square-grey-01.svg +0 -0
- /package/{images → src/images}/northArrow.svg +0 -0
- /package/{images → src/images}/northArrow.url.svg +0 -0
- /package/{images → src/images}/northArrowCircle.svg +0 -0
- /package/{images → src/images}/northArrowCircle.url.svg +0 -0
- /package/{themes → src/themes}/README.md +0 -0
- /package/{themes → src/themes}/default/components.scss +0 -0
- /package/{themes → src/themes}/default/examples.scss +0 -0
- /package/{themes → src/themes}/default/index.scss +0 -0
- /package/{themes → src/themes}/default/mixins.scss +0 -0
- /package/{themes → src/themes}/default/variables.scss +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import 'jest-canvas-mock';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import renderer from 'react-test-renderer';
|
|
4
|
+
import { configure, shallow } from 'enzyme';
|
|
5
|
+
import Adapter from '@cfaester/enzyme-adapter-react-18';
|
|
6
|
+
import Map from 'ol/Map';
|
|
7
|
+
import View from 'ol/View';
|
|
8
|
+
import { TiImage } from 'react-icons/ti';
|
|
9
|
+
import RenderEvent from 'ol/render/Event';
|
|
10
|
+
import CanvasSaveButton from './CanvasSaveButton';
|
|
11
|
+
|
|
12
|
+
configure({ adapter: new Adapter() });
|
|
13
|
+
|
|
14
|
+
describe('CanvasSaveButton', () => {
|
|
15
|
+
let olMap;
|
|
16
|
+
const conf = {
|
|
17
|
+
title: 'Karte als Bild speichern.',
|
|
18
|
+
icon: <TiImage focusable={false} />,
|
|
19
|
+
className: 'ta-example',
|
|
20
|
+
saveFormat: 'image/jpeg',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
const target = document.createElement('div');
|
|
25
|
+
document.body.appendChild(target);
|
|
26
|
+
target.style.width = '100px';
|
|
27
|
+
target.style.height = '100px';
|
|
28
|
+
olMap = new Map({
|
|
29
|
+
target,
|
|
30
|
+
controls: [],
|
|
31
|
+
view: new View({
|
|
32
|
+
center: [0, 0],
|
|
33
|
+
zoom: 0,
|
|
34
|
+
}),
|
|
35
|
+
});
|
|
36
|
+
olMap.getView().setCenter([1000, 1000]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterEach(() => {
|
|
40
|
+
if (olMap.getTargetElement()) {
|
|
41
|
+
document.body.removeChild(olMap.getTargetElement());
|
|
42
|
+
}
|
|
43
|
+
olMap.setTarget(null);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('should match snapshot.', () => {
|
|
47
|
+
const component = renderer.create(
|
|
48
|
+
<CanvasSaveButton format={conf.saveFormat} map={olMap}>
|
|
49
|
+
{conf.icon}
|
|
50
|
+
</CanvasSaveButton>,
|
|
51
|
+
);
|
|
52
|
+
const tree = component.toJSON();
|
|
53
|
+
expect(tree).toMatchSnapshot();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('should match snapshot with a different attributes', () => {
|
|
57
|
+
const component = renderer.create(
|
|
58
|
+
// eslint-disable-next-line jsx-a11y/tabindex-no-positive
|
|
59
|
+
<CanvasSaveButton title={conf.title} className="foo" tabIndex="1">
|
|
60
|
+
{conf.icon}
|
|
61
|
+
</CanvasSaveButton>,
|
|
62
|
+
);
|
|
63
|
+
const tree = component.toJSON();
|
|
64
|
+
expect(tree).toMatchSnapshot();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('should call onSaveBefore then download then onSaveEnd function on click.', async () => {
|
|
68
|
+
const saveStart = jest.fn((m) => {
|
|
69
|
+
return Promise.resolve(m);
|
|
70
|
+
});
|
|
71
|
+
const saveEnd = jest.fn();
|
|
72
|
+
const wrapper = shallow(
|
|
73
|
+
<CanvasSaveButton
|
|
74
|
+
className="ta-example"
|
|
75
|
+
map={olMap}
|
|
76
|
+
format={conf.saveFormat}
|
|
77
|
+
onSaveStart={saveStart}
|
|
78
|
+
onSaveEnd={saveEnd}
|
|
79
|
+
extraData={{
|
|
80
|
+
copyright: {
|
|
81
|
+
text: () => {
|
|
82
|
+
return (
|
|
83
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
84
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
85
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
86
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
87
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
88
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)' +
|
|
89
|
+
'contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)'
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
{conf.icon}
|
|
96
|
+
</CanvasSaveButton>,
|
|
97
|
+
);
|
|
98
|
+
const link = document.createElement('a');
|
|
99
|
+
link.click = jest.fn();
|
|
100
|
+
const div = document.createElement('div');
|
|
101
|
+
const canvas = document.createElement('canvas');
|
|
102
|
+
canvas.toBlob = jest.fn((callback) => {
|
|
103
|
+
return callback();
|
|
104
|
+
});
|
|
105
|
+
global.URL.createObjectURL = jest.fn(() => {
|
|
106
|
+
return 'fooblob';
|
|
107
|
+
});
|
|
108
|
+
// We use a spy here to be able to correctly restore the initial function
|
|
109
|
+
const spy3 = jest
|
|
110
|
+
.spyOn(global.document, 'createElement')
|
|
111
|
+
.mockImplementation((elt) => {
|
|
112
|
+
if (elt === 'canvas') {
|
|
113
|
+
return canvas;
|
|
114
|
+
}
|
|
115
|
+
if (elt === 'div') {
|
|
116
|
+
return div;
|
|
117
|
+
}
|
|
118
|
+
if (elt === 'a') {
|
|
119
|
+
return link;
|
|
120
|
+
}
|
|
121
|
+
return {};
|
|
122
|
+
});
|
|
123
|
+
const spy = jest.spyOn(CanvasSaveButton.prototype, 'createCanvasImage');
|
|
124
|
+
const spy2 = jest.spyOn(CanvasSaveButton.prototype, 'downloadCanvasImage');
|
|
125
|
+
jest
|
|
126
|
+
.spyOn(olMap.getTargetElement(), 'getElementsByTagName')
|
|
127
|
+
.mockReturnValue([canvas]);
|
|
128
|
+
await wrapper.find('.ta-example').simulate('click');
|
|
129
|
+
await olMap.dispatchEvent(
|
|
130
|
+
new RenderEvent('rendercomplete', undefined, undefined, {
|
|
131
|
+
canvas,
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
await window.setTimeout(() => {
|
|
135
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
136
|
+
expect(saveStart).toHaveBeenCalledTimes(1);
|
|
137
|
+
expect(saveEnd).toHaveBeenCalledTimes(1);
|
|
138
|
+
expect(spy2.mock.calls[0][0]).toBe(canvas);
|
|
139
|
+
expect(spy2.mock.calls[0][0].toBlob).toHaveBeenCalledTimes(1);
|
|
140
|
+
expect(link.href).toBe('http://localhost/fooblob');
|
|
141
|
+
expect(link.download).toBe('.jpg');
|
|
142
|
+
expect(link.click).toHaveBeenCalledTimes(1);
|
|
143
|
+
spy.mockRestore();
|
|
144
|
+
spy2.mockRestore();
|
|
145
|
+
spy3.mockRestore();
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
The following example demonstrates the use of CanvasSaveButton.
|
|
2
|
+
|
|
3
|
+
```jsx
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import { TiImage } from 'react-icons/ti';
|
|
6
|
+
import { geopsTheme, Header, Footer } from '@geops/geops-ui';
|
|
7
|
+
import { ThemeProvider } from '@material-ui/core/styles';
|
|
8
|
+
import Button from '@material-ui/core/Button';
|
|
9
|
+
import { Layer } from 'mobility-toolbox-js/ol';
|
|
10
|
+
import Tile from 'ol/layer/Tile';
|
|
11
|
+
import OSM from 'ol/source/OSM';
|
|
12
|
+
import Map from 'ol/Map';
|
|
13
|
+
import { toDegrees } from 'ol/math';
|
|
14
|
+
import CanvasSaveButton from 'react-spatial/components/CanvasSaveButton';
|
|
15
|
+
import BasicMap from 'react-spatial/components/BasicMap';
|
|
16
|
+
import geopsLogo from 'react-spatial/images/geops_logo.png';
|
|
17
|
+
import qrCode from 'react-spatial/images/geops_qr.png';
|
|
18
|
+
|
|
19
|
+
const map = new Map({ controls: [] });
|
|
20
|
+
|
|
21
|
+
const layers = [
|
|
22
|
+
new Layer({
|
|
23
|
+
olLayer: new Tile({
|
|
24
|
+
source: new OSM(),
|
|
25
|
+
}),
|
|
26
|
+
copyrights: '© layer-copyright',
|
|
27
|
+
}),
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
function CanvasSaveButtonExample() {
|
|
31
|
+
return (
|
|
32
|
+
<ThemeProvider theme={geopsTheme}>
|
|
33
|
+
<div className="rs-canvas-save-button-example">
|
|
34
|
+
<BasicMap
|
|
35
|
+
map={map}
|
|
36
|
+
layers={layers}
|
|
37
|
+
center={[874105.13, 6106172.77]}
|
|
38
|
+
zoom={10}
|
|
39
|
+
tabIndex={0}
|
|
40
|
+
/>
|
|
41
|
+
<CanvasSaveButton
|
|
42
|
+
map={map}
|
|
43
|
+
extraData={{
|
|
44
|
+
copyright: {
|
|
45
|
+
text: () => {
|
|
46
|
+
return layers[0].copyrights;
|
|
47
|
+
},
|
|
48
|
+
background: true,
|
|
49
|
+
},
|
|
50
|
+
northArrow: {
|
|
51
|
+
rotation: () => {
|
|
52
|
+
return toDegrees(map.getView().getRotation());
|
|
53
|
+
},
|
|
54
|
+
circled: true,
|
|
55
|
+
},
|
|
56
|
+
logo: {
|
|
57
|
+
src: geopsLogo,
|
|
58
|
+
height: 22,
|
|
59
|
+
width: 84,
|
|
60
|
+
},
|
|
61
|
+
qrCode: {
|
|
62
|
+
src: qrCode,
|
|
63
|
+
height: 50,
|
|
64
|
+
width: 50,
|
|
65
|
+
},
|
|
66
|
+
}}
|
|
67
|
+
>
|
|
68
|
+
<Button>Export Map</Button>
|
|
69
|
+
</CanvasSaveButton>
|
|
70
|
+
</div>
|
|
71
|
+
</ThemeProvider>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
<CanvasSaveButtonExample />;
|
|
76
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`CanvasSaveButton should match snapshot with a different attributes 1`] = `
|
|
4
|
+
<div
|
|
5
|
+
className="foo"
|
|
6
|
+
onClick={[Function]}
|
|
7
|
+
onKeyPress={[Function]}
|
|
8
|
+
role="button"
|
|
9
|
+
tabIndex="1"
|
|
10
|
+
title="Karte als Bild speichern."
|
|
11
|
+
>
|
|
12
|
+
<svg
|
|
13
|
+
baseProfile="tiny"
|
|
14
|
+
fill="currentColor"
|
|
15
|
+
focusable={false}
|
|
16
|
+
height="1em"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
strokeWidth="0"
|
|
19
|
+
style={
|
|
20
|
+
{
|
|
21
|
+
"color": undefined,
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
version="1.2"
|
|
25
|
+
viewBox="0 0 24 24"
|
|
26
|
+
width="1em"
|
|
27
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
+
>
|
|
29
|
+
<circle
|
|
30
|
+
cx="8.5"
|
|
31
|
+
cy="8.5"
|
|
32
|
+
r="2.5"
|
|
33
|
+
/>
|
|
34
|
+
<path
|
|
35
|
+
d="M16 10c-2 0-3 3-4.5 3s-1.499-1-3.5-1c-2 0-3.001 4-3.001 4h14.001s-1-6-3-6zM20 3h-16c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2v-12c0-1.103-.897-2-2-2zm0 14h-16v-12h16v12z"
|
|
36
|
+
/>
|
|
37
|
+
</svg>
|
|
38
|
+
</div>
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
exports[`CanvasSaveButton should match snapshot. 1`] = `
|
|
42
|
+
<div
|
|
43
|
+
className="rs-canvas-save-button"
|
|
44
|
+
onClick={[Function]}
|
|
45
|
+
onKeyPress={[Function]}
|
|
46
|
+
role="button"
|
|
47
|
+
tabIndex={0}
|
|
48
|
+
>
|
|
49
|
+
<svg
|
|
50
|
+
baseProfile="tiny"
|
|
51
|
+
fill="currentColor"
|
|
52
|
+
focusable={false}
|
|
53
|
+
height="1em"
|
|
54
|
+
stroke="currentColor"
|
|
55
|
+
strokeWidth="0"
|
|
56
|
+
style={
|
|
57
|
+
{
|
|
58
|
+
"color": undefined,
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
version="1.2"
|
|
62
|
+
viewBox="0 0 24 24"
|
|
63
|
+
width="1em"
|
|
64
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
65
|
+
>
|
|
66
|
+
<circle
|
|
67
|
+
cx="8.5"
|
|
68
|
+
cy="8.5"
|
|
69
|
+
r="2.5"
|
|
70
|
+
/>
|
|
71
|
+
<path
|
|
72
|
+
d="M16 10c-2 0-3 3-4.5 3s-1.499-1-3.5-1c-2 0-3.001 4-3.001 4h14.001s-1-6-3-6zM20 3h-16c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2v-12c0-1.103-.897-2-2-2zm0 14h-16v-12h16v12z"
|
|
73
|
+
/>
|
|
74
|
+
</svg>
|
|
75
|
+
</div>
|
|
76
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './CanvasSaveButton';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { useMemo, useEffect, useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { Map } from 'ol';
|
|
4
|
+
import { CopyrightControl } from 'mobility-toolbox-js/ol';
|
|
5
|
+
|
|
6
|
+
const propTypes = {
|
|
7
|
+
/**
|
|
8
|
+
* A map.
|
|
9
|
+
*/
|
|
10
|
+
map: PropTypes.instanceOf(Map).isRequired,
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Format function. Called with an array of copyrights from visible layers
|
|
14
|
+
* and returns the copyright.
|
|
15
|
+
*/
|
|
16
|
+
format: PropTypes.func,
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* CSS class of th root element
|
|
20
|
+
*/
|
|
21
|
+
className: PropTypes.string,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaultProps = {
|
|
25
|
+
format: (copyrights) => {
|
|
26
|
+
return copyrights.join(' | ');
|
|
27
|
+
},
|
|
28
|
+
className: 'rs-copyright',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The Copyright component uses the
|
|
33
|
+
* [mobility-toolbox-js CopyrightControl](https://mobility-toolbox-js.geops.io/api/class/src/mapbox/controls/CopyrightControl%20js~CopyrightControl%20html-offset-anchor)
|
|
34
|
+
* to render the layer copyrights.
|
|
35
|
+
*/
|
|
36
|
+
function Copyright({ map, format, ...other }) {
|
|
37
|
+
const [copyrights, setCopyrights] = useState([]);
|
|
38
|
+
|
|
39
|
+
const control = useMemo(
|
|
40
|
+
() => {
|
|
41
|
+
return new CopyrightControl({
|
|
42
|
+
target: document.createElement('div'),
|
|
43
|
+
element: document.createElement('div'),
|
|
44
|
+
render() {
|
|
45
|
+
// eslint-disable-next-line react/no-this-in-sfc
|
|
46
|
+
const newCopyrights = this.getCopyrights();
|
|
47
|
+
if (copyrights.toString() !== newCopyrights.toString()) {
|
|
48
|
+
setCopyrights(newCopyrights);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
+
[],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Ensure the control is not associated to the wrong map
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (!control) {
|
|
60
|
+
return () => {};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
control.map = map;
|
|
64
|
+
|
|
65
|
+
return () => {
|
|
66
|
+
control.map = null;
|
|
67
|
+
};
|
|
68
|
+
}, [map, control]);
|
|
69
|
+
|
|
70
|
+
if (!control || !control.getCopyrights().length) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
77
|
+
{...other}
|
|
78
|
+
// eslint-disable-next-line react/no-danger
|
|
79
|
+
dangerouslySetInnerHTML={{
|
|
80
|
+
__html: format(copyrights) || '',
|
|
81
|
+
}}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Copyright.propTypes = propTypes;
|
|
87
|
+
Copyright.defaultProps = defaultProps;
|
|
88
|
+
|
|
89
|
+
export default React.memo(Copyright);
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import 'jest-canvas-mock';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { configure, mount } from 'enzyme';
|
|
4
|
+
import Adapter from '@cfaester/enzyme-adapter-react-18';
|
|
5
|
+
import { act } from 'react-dom/test-utils';
|
|
6
|
+
import { Map, View } from 'ol';
|
|
7
|
+
import Tile from 'ol/Tile';
|
|
8
|
+
import TileLayer from 'ol/layer/Tile';
|
|
9
|
+
import TileSource from 'ol/source/Tile';
|
|
10
|
+
import { createXYZ } from 'ol/tilegrid';
|
|
11
|
+
import { Layer } from 'mobility-toolbox-js/ol';
|
|
12
|
+
import Copyright from './Copyright';
|
|
13
|
+
|
|
14
|
+
configure({ adapter: new Adapter() });
|
|
15
|
+
|
|
16
|
+
const image = new Image();
|
|
17
|
+
image.width = 256;
|
|
18
|
+
image.height = 256;
|
|
19
|
+
|
|
20
|
+
const tileLoadFunction = () => {
|
|
21
|
+
const tile = new Tile([0, 0, -1], 2 /* LOADED */);
|
|
22
|
+
tile.getImage = () => {
|
|
23
|
+
return image;
|
|
24
|
+
};
|
|
25
|
+
return tile;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const getOLTileLayer = () => {
|
|
29
|
+
const layer = new TileLayer({
|
|
30
|
+
source: new TileSource({
|
|
31
|
+
projection: 'EPSG:3857',
|
|
32
|
+
tileGrid: createXYZ(),
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
layer.getSource().getTile = tileLoadFunction;
|
|
36
|
+
return layer;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const getLayer = (copyrights, visible = true) => {
|
|
40
|
+
return new Layer({
|
|
41
|
+
visible,
|
|
42
|
+
copyrights,
|
|
43
|
+
olLayer: getOLTileLayer(),
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
let layers;
|
|
48
|
+
let map;
|
|
49
|
+
|
|
50
|
+
describe('Copyright', () => {
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
const target = document.createElement('div');
|
|
53
|
+
document.body.appendChild(target);
|
|
54
|
+
layers = [getLayer('bar'), getLayer('foo', false)];
|
|
55
|
+
map = new Map({
|
|
56
|
+
target,
|
|
57
|
+
view: new View({
|
|
58
|
+
center: [0, 0],
|
|
59
|
+
zoom: 0,
|
|
60
|
+
}),
|
|
61
|
+
layers: layers.map((layer) => {
|
|
62
|
+
return layer.olLayer;
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
map.setSize([200, 200]);
|
|
66
|
+
layers.forEach((layer) => {
|
|
67
|
+
layer.attachToMap(map);
|
|
68
|
+
});
|
|
69
|
+
act(() => {
|
|
70
|
+
map.renderSync();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
afterEach(() => {
|
|
75
|
+
layers.forEach((layer) => {
|
|
76
|
+
layer.detachFromMap(map);
|
|
77
|
+
});
|
|
78
|
+
map.setTarget(null);
|
|
79
|
+
map = null;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('is empty if no layers are visible', () => {
|
|
83
|
+
const component = mount(<Copyright map={map} />);
|
|
84
|
+
expect(component.html()).toBe(null);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('displays one copyright', () => {
|
|
88
|
+
const wrapper = mount(<Copyright map={map} />);
|
|
89
|
+
act(() => {
|
|
90
|
+
map.renderSync();
|
|
91
|
+
});
|
|
92
|
+
wrapper.update();
|
|
93
|
+
expect(wrapper.text()).toBe('bar');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('displays 2 copyrights', () => {
|
|
97
|
+
const wrapper = mount(<Copyright map={map} />);
|
|
98
|
+
layers[0].visible = true;
|
|
99
|
+
layers[1].visible = true;
|
|
100
|
+
act(() => {
|
|
101
|
+
map.renderSync();
|
|
102
|
+
});
|
|
103
|
+
wrapper.update();
|
|
104
|
+
expect(wrapper.text()).toBe('bar | foo');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test('displays a copyright using a custom format', () => {
|
|
108
|
+
const wrapper = mount(
|
|
109
|
+
<Copyright
|
|
110
|
+
map={map}
|
|
111
|
+
format={(copyrights) => {
|
|
112
|
+
return `Number of copyrights: ${copyrights.length}`;
|
|
113
|
+
}}
|
|
114
|
+
/>,
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
act(() => {
|
|
118
|
+
map.renderSync();
|
|
119
|
+
});
|
|
120
|
+
wrapper.update();
|
|
121
|
+
|
|
122
|
+
expect(wrapper.text()).toBe('Number of copyrights: 1');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('set a custom className', () => {
|
|
126
|
+
const wrapper = mount(<Copyright map={map} className="foo" />);
|
|
127
|
+
expect(wrapper.find('.foo').length).toBe(1);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test('set a custom attribute to the root element', () => {
|
|
131
|
+
const wrapper = mount(<Copyright map={map} foo="bar" />);
|
|
132
|
+
expect(wrapper.find('[foo]').length).toBe(1);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
The following example demonstrates the use of Copyright.
|
|
2
|
+
|
|
3
|
+
```js
|
|
4
|
+
import React from 'react';
|
|
5
|
+
import Map from 'ol/Map';
|
|
6
|
+
import Tile from 'ol/layer/Tile';
|
|
7
|
+
import OSM from 'ol/source/OSM';
|
|
8
|
+
import { defaults } from 'ol/control';
|
|
9
|
+
import { Layer, MapboxLayer } from 'mobility-toolbox-js/ol';
|
|
10
|
+
import BasicMap from 'react-spatial/components/BasicMap';
|
|
11
|
+
import Copyright from 'react-spatial/components/Copyright';
|
|
12
|
+
|
|
13
|
+
const map = new Map({
|
|
14
|
+
controls: defaults({
|
|
15
|
+
attribution: false,
|
|
16
|
+
}),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const layers = [
|
|
20
|
+
new MapboxLayer({
|
|
21
|
+
url: `https://maps.geops.io/styles/base_bright_v2/style.json?key=${window.apiKey}`,
|
|
22
|
+
}),
|
|
23
|
+
new Layer({
|
|
24
|
+
copyrights: '© My custom copyright for OSM Contributors',
|
|
25
|
+
olLayer: new Tile({
|
|
26
|
+
source: new OSM(),
|
|
27
|
+
}),
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
30
|
+
window.layers = layers;
|
|
31
|
+
|
|
32
|
+
<div className="rs-copyright-example">
|
|
33
|
+
<BasicMap map={map} layers={layers} tabIndex={0} />
|
|
34
|
+
<Copyright map={map} />
|
|
35
|
+
</div>;
|
|
36
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Copyright';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import KMLFormat from 'ol/format/KML';
|
|
4
|
+
import { Layer } from 'mobility-toolbox-js/ol';
|
|
5
|
+
import KML from '../../utils/KML';
|
|
6
|
+
|
|
7
|
+
const propTypes = {
|
|
8
|
+
/**
|
|
9
|
+
* Children content of the Feature export button.
|
|
10
|
+
*/
|
|
11
|
+
children: PropTypes.node,
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Format to export features (function).
|
|
15
|
+
* Supported formats: https://openlayers.org/en/latest/apidoc/module-ol_format_Feature-FeatureFormat.html
|
|
16
|
+
*/
|
|
17
|
+
format: PropTypes.func,
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An existing [mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers),
|
|
21
|
+
* using a valid [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html)
|
|
22
|
+
*/
|
|
23
|
+
layer: PropTypes.instanceOf(Layer).isRequired,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Map projection.
|
|
27
|
+
*/
|
|
28
|
+
projection: PropTypes.string,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const defaultProps = {
|
|
32
|
+
children: null,
|
|
33
|
+
format: KMLFormat,
|
|
34
|
+
projection: 'EPSG:3857',
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The FeatureExportButton component creates a button that exports feature geometries
|
|
39
|
+
* from a [[mobility-toolbox-js Layer](https://mobility-toolbox-js.geops.io/api/identifiers%20html#ol-layers)]
|
|
40
|
+
* containing an [ol/layer/Vector](https://openlayers.org/en/latest/apidoc/module-ol_layer_Vector-VectorLayer.html)
|
|
41
|
+
* with a [ol/source/Vector](https://openlayers.org/en/latest/apidoc/module-ol_source_Vector.html) on click.<br>
|
|
42
|
+
* The default export format is KML, which supports the features' style export.<br>
|
|
43
|
+
* Other formats do not always support style export (See specific format specs).
|
|
44
|
+
*/
|
|
45
|
+
class FeatureExportButton extends PureComponent {
|
|
46
|
+
static createFeatureString(layer, projection, format) {
|
|
47
|
+
if (format === KMLFormat) {
|
|
48
|
+
return KML.writeFeatures(layer, projection);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line new-cap
|
|
52
|
+
return new format().writeFeatures(layer.olLayer.getSource().getFeatures(), {
|
|
53
|
+
featureProjection: projection,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static exportFeatures(layer, projection, format) {
|
|
58
|
+
const now = new Date()
|
|
59
|
+
.toJSON()
|
|
60
|
+
.slice(0, 20)
|
|
61
|
+
.replace(/[.:T-]+/g, '');
|
|
62
|
+
const featString = this.createFeatureString(layer, projection, format);
|
|
63
|
+
|
|
64
|
+
const formatString = featString
|
|
65
|
+
? featString.match(/<(\w+)\s+\w+.*?>/)[1]
|
|
66
|
+
: 'xml';
|
|
67
|
+
|
|
68
|
+
const fileName = `exported_features_${now}.${formatString}`;
|
|
69
|
+
const charset = document.characterSet || 'UTF-8';
|
|
70
|
+
const type = `${
|
|
71
|
+
formatString === 'kml'
|
|
72
|
+
? 'data:application/vnd.google-earth.kml+xml'
|
|
73
|
+
: 'data:text/xml'
|
|
74
|
+
};charset=${charset}`;
|
|
75
|
+
|
|
76
|
+
if (featString) {
|
|
77
|
+
if (window.navigator.msSaveBlob) {
|
|
78
|
+
// ie 11 and higher
|
|
79
|
+
window.navigator.msSaveBlob(new Blob([featString], { type }), fileName);
|
|
80
|
+
} else {
|
|
81
|
+
const link = document.createElement('a');
|
|
82
|
+
link.download = fileName;
|
|
83
|
+
link.href = `${type},${encodeURIComponent(featString)}`;
|
|
84
|
+
link.click();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
render() {
|
|
90
|
+
const { children, layer, projection, format, ...other } = this.props;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<div
|
|
94
|
+
role="button"
|
|
95
|
+
className="rs-feature-export-button"
|
|
96
|
+
tabIndex={0}
|
|
97
|
+
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
98
|
+
{...other}
|
|
99
|
+
onClick={() => {
|
|
100
|
+
return FeatureExportButton.exportFeatures(layer, projection, format);
|
|
101
|
+
}}
|
|
102
|
+
onKeyPress={(evt) => {
|
|
103
|
+
return (
|
|
104
|
+
evt.which === 13 &&
|
|
105
|
+
FeatureExportButton.exportFeatures(layer, projection, format)
|
|
106
|
+
);
|
|
107
|
+
}}
|
|
108
|
+
>
|
|
109
|
+
{children}
|
|
110
|
+
</div>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
FeatureExportButton.propTypes = propTypes;
|
|
116
|
+
FeatureExportButton.defaultProps = defaultProps;
|
|
117
|
+
|
|
118
|
+
export default FeatureExportButton;
|