@geops/rvf-mobility-web-component 0.1.12 → 0.1.13
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/CHANGELOG.md +17 -0
- package/index.html +1 -1
- package/index.js +192 -176
- package/input.css +2 -8
- package/package.json +14 -14
- package/scripts/build.mjs +0 -1
- package/scripts/dev.mjs +2 -1
- package/src/RouteSchedule/RouteSchedule.tsx +3 -1
- package/src/RouteStop/RouteStop.tsx +1 -1
- package/src/RvfButton/RvfButton.tsx +2 -2
- package/src/RvfCheckbox/RvfCheckbox.tsx +2 -1
- package/src/RvfExportMenu/RvfExportMenu.tsx +25 -13
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +2 -2
- package/src/RvfIconButton/RvfIconButton.tsx +1 -1
- package/src/RvfLayerTree/RvfLayerTree.tsx +5 -9
- package/src/RvfLayerTree/TreeItem/TreeItem.tsx +19 -9
- package/src/RvfLayerTree/layersTreeReducer.ts +1 -0
- package/src/RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx +7 -0
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +84 -24
- package/src/RvfPoisLayer/RvfPoisLayer.tsx +6 -0
- package/src/RvfRadioButton/RvfRadioButton.tsx +1 -1
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +9 -5
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +87 -50
- package/src/RvfSingleClickListener/RvfSingleClickListener.tsx +10 -2
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +7 -0
- package/src/RvfTopics/RvfTopics.tsx +21 -24
- package/src/utils/constants.ts +2 -0
- package/src/utils/createMobiDataBwWfsLayer.ts +28 -20
- package/src/utils/createSharedMobilityLayer.ts +24 -13
- package/src/utils/exportPdf.ts +11 -0
- package/src/utils/getAllLayers.ts +25 -0
- package/src/utils/hooks/useRvfContext.tsx +33 -0
- package/tailwind.config.mjs +30 -30
- package/src/FloatingMenu/FloatingMenu.tsx +0 -42
- package/src/FloatingMenu/index.tsx +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Options } from "ol/layer/Group";
|
|
2
2
|
|
|
3
|
+
import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
|
|
3
4
|
import { Feature } from "ol";
|
|
4
5
|
import { Point } from "ol/geom";
|
|
5
6
|
import { Group, Vector } from "ol/layer";
|
|
@@ -9,70 +10,102 @@ import { memo } from "preact/compat";
|
|
|
9
10
|
import { useEffect, useMemo } from "preact/hooks";
|
|
10
11
|
|
|
11
12
|
import createMobiDataBwWfsLayer from "../utils/createMobiDataBwWfsLayer";
|
|
12
|
-
import
|
|
13
|
+
import createFreeFloatMobilityLayer from "../utils/createSharedMobilityLayer";
|
|
13
14
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
15
|
+
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
export type GroupOptions = Options & Record<string, unknown>;
|
|
18
|
+
|
|
19
|
+
function RvfSharedMobilityLayerGroup(props: GroupOptions) {
|
|
20
|
+
const { baseLayer, map } = useMapContext();
|
|
21
|
+
const { setSharedMobilityLayerGroup } = useRvfContext();
|
|
17
22
|
|
|
18
23
|
const group = useMemo(() => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
);
|
|
23
|
-
sharingStationsBicycle.set("title", "Stations Bicycle");
|
|
24
|
-
|
|
25
|
-
const sharingStationsCar = createMobiDataBwWfsLayer(
|
|
26
|
-
"sharing_stations_car",
|
|
27
|
-
"green",
|
|
28
|
-
);
|
|
29
|
-
sharingStationsCar.set("title", "Stations Car");
|
|
30
|
-
|
|
31
|
-
const sharingStationsCargoBicycle = createMobiDataBwWfsLayer(
|
|
32
|
-
"sharing_stations_cargo_bicycle",
|
|
33
|
-
"green",
|
|
34
|
-
);
|
|
35
|
-
sharingStationsCargoBicycle.set("title", "Stations Cargo Bicycle");
|
|
36
|
-
|
|
37
|
-
const sharingStationsScooterStanding = createMobiDataBwWfsLayer(
|
|
38
|
-
"sharing_stations_scooters_standing",
|
|
39
|
-
"purple",
|
|
40
|
-
);
|
|
41
|
-
sharingStationsScooterStanding.set("title", "Stations Scooter");
|
|
42
|
-
|
|
43
|
-
const sharingVehicles = createSharedMobilityLayer(
|
|
44
|
-
"sharing_vehicles",
|
|
45
|
-
"green",
|
|
46
|
-
);
|
|
47
|
-
sharingVehicles.set("title", "Free Floating");
|
|
24
|
+
if (!baseLayer) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
48
27
|
|
|
49
|
-
|
|
28
|
+
const sharingBicycle = new Group({
|
|
29
|
+
layers: [
|
|
30
|
+
new MaplibreStyleLayer({
|
|
31
|
+
isQueryable: true,
|
|
32
|
+
layersFilter: ({ metadata }) => {
|
|
33
|
+
return metadata?.["rvf.filter"] === "bike";
|
|
34
|
+
},
|
|
35
|
+
maplibreLayer: baseLayer,
|
|
36
|
+
}),
|
|
37
|
+
createMobiDataBwWfsLayer("sharing_stations_bicycle", "green"),
|
|
38
|
+
createFreeFloatMobilityLayer("sharing_vehicles", "green", "bike"),
|
|
39
|
+
],
|
|
40
|
+
title: "Fahrrad",
|
|
41
|
+
} as GroupOptions);
|
|
42
|
+
|
|
43
|
+
const sharingCar = new Group({
|
|
44
|
+
layers: [
|
|
45
|
+
new MaplibreStyleLayer({
|
|
46
|
+
isQueryable: true,
|
|
47
|
+
layersFilter: ({ metadata }) => {
|
|
48
|
+
return metadata?.["rvf.filter"] === "car";
|
|
49
|
+
},
|
|
50
|
+
maplibreLayer: baseLayer,
|
|
51
|
+
}),
|
|
52
|
+
createMobiDataBwWfsLayer("sharing_stations_car", "green"),
|
|
53
|
+
createFreeFloatMobilityLayer("sharing_vehicles", "green", "car"),
|
|
54
|
+
],
|
|
55
|
+
title: "Auto",
|
|
56
|
+
} as GroupOptions);
|
|
57
|
+
|
|
58
|
+
const sharingCargoBicycle = new Group({
|
|
50
59
|
layers: [
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
60
|
+
new MaplibreStyleLayer({
|
|
61
|
+
isQueryable: true,
|
|
62
|
+
layersFilter: ({ metadata }) => {
|
|
63
|
+
return metadata?.["rvf.filter"] === "cargo_bike";
|
|
64
|
+
},
|
|
65
|
+
maplibreLayer: baseLayer,
|
|
66
|
+
}),
|
|
67
|
+
createMobiDataBwWfsLayer("sharing_stations_cargo_bicycle", "green"),
|
|
68
|
+
createFreeFloatMobilityLayer("sharing_vehicles", "green", "cargo_bike"),
|
|
56
69
|
],
|
|
70
|
+
title: "Cargobike",
|
|
71
|
+
} as GroupOptions);
|
|
72
|
+
|
|
73
|
+
const sharingScooter = new Group({
|
|
74
|
+
layers: [
|
|
75
|
+
new MaplibreStyleLayer({
|
|
76
|
+
isQueryable: true,
|
|
77
|
+
layersFilter: ({ metadata }) => {
|
|
78
|
+
return metadata?.["rvf.filter"] === "hitchhiking";
|
|
79
|
+
},
|
|
80
|
+
maplibreLayer: baseLayer,
|
|
81
|
+
}),
|
|
82
|
+
createMobiDataBwWfsLayer("sharing_stations_scooters_standing", "green"),
|
|
83
|
+
createFreeFloatMobilityLayer("sharing_vehicles", "green", "scooter"),
|
|
84
|
+
],
|
|
85
|
+
title: "E-Roller",
|
|
86
|
+
} as GroupOptions);
|
|
87
|
+
|
|
88
|
+
return new Group({
|
|
89
|
+
layers: [sharingBicycle, sharingCar, sharingCargoBicycle, sharingScooter],
|
|
57
90
|
...props,
|
|
58
91
|
});
|
|
59
|
-
}, [props]);
|
|
92
|
+
}, [baseLayer, props]);
|
|
60
93
|
|
|
61
94
|
// Reload features every minute
|
|
62
95
|
useEffect(() => {
|
|
63
96
|
const interval = window.setInterval(() => {
|
|
64
|
-
group.getLayers().forEach((layer:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// For cluster source
|
|
71
|
-
(
|
|
97
|
+
group.getLayers().forEach((layer: Group) => {
|
|
98
|
+
layer.getLayers().forEach((layer: MaplibreStyleLayer | Vector) => {
|
|
99
|
+
const source = layer.getSource();
|
|
100
|
+
source?.refresh();
|
|
101
|
+
|
|
102
|
+
// For cluster source
|
|
72
103
|
(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
104
|
+
(source as Cluster<Feature<Point>>)?.getSource?.() as VectorSource<
|
|
105
|
+
Feature<Point>
|
|
106
|
+
>
|
|
107
|
+
)?.refresh();
|
|
108
|
+
});
|
|
76
109
|
});
|
|
77
110
|
}, 60000);
|
|
78
111
|
return () => {
|
|
@@ -80,6 +113,10 @@ function RvfSharedMobilityLayerGroup(props: Options & Record<string, unknown>) {
|
|
|
80
113
|
};
|
|
81
114
|
}, [group]);
|
|
82
115
|
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
setSharedMobilityLayerGroup(group);
|
|
118
|
+
}, [group, setSharedMobilityLayerGroup]);
|
|
119
|
+
|
|
83
120
|
useEffect(() => {
|
|
84
121
|
if (!map || !group) {
|
|
85
122
|
return;
|
|
@@ -110,8 +110,16 @@ function SingleClickListener() {
|
|
|
110
110
|
setSelectedFeature(null);
|
|
111
111
|
setSelectedFeatures([]);
|
|
112
112
|
} else {
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
const feats = [];
|
|
114
|
+
features.forEach((feature) => {
|
|
115
|
+
if (feature.get("features")) {
|
|
116
|
+
feats.push(...feature.get("features"));
|
|
117
|
+
} else {
|
|
118
|
+
feats.push(feature);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
setSelectedFeatures(feats);
|
|
122
|
+
setSelectedFeature(feats[0]);
|
|
115
123
|
}
|
|
116
124
|
},
|
|
117
125
|
[
|
|
@@ -4,15 +4,18 @@ import { memo } from "preact/compat";
|
|
|
4
4
|
import { useEffect, useMemo } from "preact/hooks";
|
|
5
5
|
|
|
6
6
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
7
|
+
import useRvfContext from "../utils/hooks/useRvfContext";
|
|
7
8
|
|
|
8
9
|
function RvfTarifZonenLayer(props: MaplibreStyleLayerOptions) {
|
|
9
10
|
const { baseLayer, map } = useMapContext();
|
|
11
|
+
const { setTarifZonenLayer } = useRvfContext();
|
|
10
12
|
|
|
11
13
|
const layer = useMemo(() => {
|
|
12
14
|
if (!baseLayer) {
|
|
13
15
|
return null;
|
|
14
16
|
}
|
|
15
17
|
return new MaplibreStyleLayer({
|
|
18
|
+
isQueryable: false,
|
|
16
19
|
layersFilter: ({ metadata, source, "source-layer": sourceLayer }) => {
|
|
17
20
|
return (
|
|
18
21
|
metadata?.["rvf.filter"] === "tarifzonen" ||
|
|
@@ -24,6 +27,10 @@ function RvfTarifZonenLayer(props: MaplibreStyleLayerOptions) {
|
|
|
24
27
|
});
|
|
25
28
|
}, [baseLayer, props]);
|
|
26
29
|
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setTarifZonenLayer(layer);
|
|
32
|
+
}, [layer, setTarifZonenLayer]);
|
|
33
|
+
|
|
27
34
|
useEffect(() => {
|
|
28
35
|
if (!map || !layer) {
|
|
29
36
|
return;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { getUid } from "ol";
|
|
1
2
|
import { Group } from "ol/layer";
|
|
3
|
+
import BaseLayer from "ol/layer/Base";
|
|
2
4
|
import { JSX, PreactDOMAttributes } from "preact";
|
|
3
5
|
import { memo } from "preact/compat";
|
|
4
6
|
|
|
@@ -9,36 +11,31 @@ import useMapContext from "../utils/hooks/useMapContext";
|
|
|
9
11
|
export type RvfTopicsProps = {} & JSX.HTMLAttributes<HTMLDivElement> &
|
|
10
12
|
PreactDOMAttributes;
|
|
11
13
|
|
|
14
|
+
const getConfigForLayer = (layer: BaseLayer) => {
|
|
15
|
+
return {
|
|
16
|
+
childItems:
|
|
17
|
+
(layer as Group)
|
|
18
|
+
?.getLayers?.()
|
|
19
|
+
.getArray()
|
|
20
|
+
.map((subLayer) => {
|
|
21
|
+
return getConfigForLayer(subLayer);
|
|
22
|
+
}) || [],
|
|
23
|
+
id: getUid(layer),
|
|
24
|
+
isControlChecked: layer.getVisible(),
|
|
25
|
+
layer,
|
|
26
|
+
selectionType: SelectionType.CHECKBOX,
|
|
27
|
+
title: layer.get("title"),
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
12
31
|
function RvfTopics(props: RvfTopicsProps) {
|
|
13
32
|
const { map } = useMapContext();
|
|
33
|
+
|
|
14
34
|
const layers = map
|
|
15
35
|
.getLayers()
|
|
16
36
|
.getArray()
|
|
17
|
-
.filter((layer) => {
|
|
18
|
-
return !layer.get("isNotInLayerTree");
|
|
19
|
-
})
|
|
20
37
|
.map((layer) => {
|
|
21
|
-
return
|
|
22
|
-
childItems:
|
|
23
|
-
(layer as Group)
|
|
24
|
-
?.getLayers?.()
|
|
25
|
-
.getArray()
|
|
26
|
-
.map((subLayer) => {
|
|
27
|
-
return {
|
|
28
|
-
childItems: [],
|
|
29
|
-
id: (Math.random() + 1).toString(36).substring(7),
|
|
30
|
-
isControlChecked: subLayer.getVisible(),
|
|
31
|
-
layer: subLayer,
|
|
32
|
-
selectionType: SelectionType.CHECKBOX,
|
|
33
|
-
title: subLayer.get("title"),
|
|
34
|
-
};
|
|
35
|
-
}) || [],
|
|
36
|
-
id: (Math.random() + 1).toString(36).substring(7),
|
|
37
|
-
isControlChecked: layer.getVisible(),
|
|
38
|
-
layer,
|
|
39
|
-
selectionType: SelectionType.CHECKBOX,
|
|
40
|
-
title: layer.get("title"),
|
|
41
|
-
};
|
|
38
|
+
return getConfigForLayer(layer);
|
|
42
39
|
});
|
|
43
40
|
|
|
44
41
|
return <RvfLayerTree layers={layers} {...props} />;
|
package/src/utils/constants.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { bbox as bboxStrategy } from "ol/loadingstrategy.js";
|
|
|
6
6
|
import { Vector } from "ol/source";
|
|
7
7
|
import { Circle, Fill, Stroke, Style, Text } from "ol/style";
|
|
8
8
|
|
|
9
|
+
import { LAYER_PROP_IS_EXPORTING } from "./constants";
|
|
10
|
+
|
|
9
11
|
function createMobiDataBwWfsLayer(
|
|
10
12
|
name: string,
|
|
11
13
|
color: string,
|
|
@@ -33,6 +35,7 @@ function createMobiDataBwWfsLayer(
|
|
|
33
35
|
);
|
|
34
36
|
},
|
|
35
37
|
});
|
|
38
|
+
|
|
36
39
|
const style = new Style({
|
|
37
40
|
image: new Circle({
|
|
38
41
|
declutterMode: "declutter",
|
|
@@ -59,26 +62,6 @@ function createMobiDataBwWfsLayer(
|
|
|
59
62
|
}),
|
|
60
63
|
});
|
|
61
64
|
|
|
62
|
-
const styleFunction = (feature) => {
|
|
63
|
-
const clone = style.clone();
|
|
64
|
-
clone.getText().setText(feature.get("num_vehicles_available")?.toString());
|
|
65
|
-
const isFreeFloat = !feature.get("num_vehicles_available")?.toString();
|
|
66
|
-
if (isFreeFloat) {
|
|
67
|
-
(clone.getImage() as Circle).setRadius(6);
|
|
68
|
-
}
|
|
69
|
-
clone.setZIndex(parseInt(getUid(feature), 10));
|
|
70
|
-
return [
|
|
71
|
-
clone,
|
|
72
|
-
// new Style({
|
|
73
|
-
// text: new Text({
|
|
74
|
-
// fill: new Fill({ color: color }),
|
|
75
|
-
// offsetY: 15,
|
|
76
|
-
// stroke: new Stroke({ color: "white", width: 2 }),
|
|
77
|
-
// text: feature.get("form_factor") || name,
|
|
78
|
-
// }),
|
|
79
|
-
// }),
|
|
80
|
-
];
|
|
81
|
-
};
|
|
82
65
|
const layer = new VectorLayer({
|
|
83
66
|
// @ts-expect-error - custom properties
|
|
84
67
|
isQueryable: true,
|
|
@@ -110,6 +93,31 @@ function createMobiDataBwWfsLayer(
|
|
|
110
93
|
// },
|
|
111
94
|
});
|
|
112
95
|
|
|
96
|
+
const styleFunction = (feature: Feature) => {
|
|
97
|
+
if (layer.get(LAYER_PROP_IS_EXPORTING)) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const clone = style.clone();
|
|
101
|
+
|
|
102
|
+
clone.getText().setText(feature.get("num_vehicles_available")?.toString());
|
|
103
|
+
const isFreeFloat = !feature.get("num_vehicles_available")?.toString();
|
|
104
|
+
if (isFreeFloat) {
|
|
105
|
+
(clone.getImage() as Circle).setRadius(6);
|
|
106
|
+
}
|
|
107
|
+
clone.setZIndex(parseInt(getUid(feature), 10));
|
|
108
|
+
return [
|
|
109
|
+
clone,
|
|
110
|
+
// new Style({
|
|
111
|
+
// text: new Text({
|
|
112
|
+
// fill: new Fill({ color: color }),
|
|
113
|
+
// offsetY: 15,
|
|
114
|
+
// stroke: new Stroke({ color: "white", width: 2 }),
|
|
115
|
+
// text: feature.get("form_factor") || name,
|
|
116
|
+
// }),
|
|
117
|
+
// }),
|
|
118
|
+
];
|
|
119
|
+
};
|
|
120
|
+
|
|
113
121
|
source.on("addfeature", function (event) {
|
|
114
122
|
const feature = event.feature;
|
|
115
123
|
feature.setStyle(styleFunction);
|
|
@@ -14,6 +14,7 @@ import car from "../icons/Car/verkehrstraeger-auto-2px-white.svg";
|
|
|
14
14
|
import cargoBicycle from "../icons/CargoBicycle/verkehrstraeger-lastenrad-2px-white.svg";
|
|
15
15
|
// @ts-expect-error - load svg as data url
|
|
16
16
|
import scooter from "../icons/Scooter/scooter.svg";
|
|
17
|
+
import { LAYER_PROP_IS_EXPORTING } from "./constants";
|
|
17
18
|
|
|
18
19
|
const iconByFormFactor = {
|
|
19
20
|
bicycle,
|
|
@@ -25,6 +26,7 @@ const iconByFormFactor = {
|
|
|
25
26
|
function createSharedMobilityLayer(
|
|
26
27
|
name: string,
|
|
27
28
|
color: string,
|
|
29
|
+
formFactor: string,
|
|
28
30
|
layerOptions: Options = {
|
|
29
31
|
minZoom: 17.99,
|
|
30
32
|
},
|
|
@@ -54,21 +56,27 @@ function createSharedMobilityLayer(
|
|
|
54
56
|
xhr.onerror = onError;
|
|
55
57
|
xhr.onload = function () {
|
|
56
58
|
if (xhr.status == 200) {
|
|
57
|
-
const features = source
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (vehicleId) {
|
|
64
|
-
feature.setId(vehicleId);
|
|
65
|
-
const featuresToRemove = source.getFeatures().filter((feat) => {
|
|
66
|
-
return feat.getId() === feature.getId();
|
|
67
|
-
});
|
|
68
|
-
source.removeFeatures(featuresToRemove);
|
|
59
|
+
const features = source
|
|
60
|
+
.getFormat()
|
|
61
|
+
.readFeatures(xhr.responseText)
|
|
62
|
+
?.filter((feature) => {
|
|
63
|
+
if (formFactor) {
|
|
64
|
+
return feature.get("form_factor") === formFactor;
|
|
69
65
|
}
|
|
66
|
+
return true;
|
|
70
67
|
});
|
|
71
|
-
|
|
68
|
+
features?.forEach((feature) => {
|
|
69
|
+
// The WFS returns everytime a different id for the same vehicle, so we set the vehicle_id as id.
|
|
70
|
+
// and remove the previous feature with the same id.
|
|
71
|
+
const vehicleId = feature.get("vehicle_id");
|
|
72
|
+
if (vehicleId) {
|
|
73
|
+
feature.setId(vehicleId);
|
|
74
|
+
const featuresToRemove = source.getFeatures().filter((feat) => {
|
|
75
|
+
return feat.getId() === feature.getId();
|
|
76
|
+
});
|
|
77
|
+
source.removeFeatures(featuresToRemove);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
72
80
|
source.addFeatures(features);
|
|
73
81
|
success(features);
|
|
74
82
|
} else {
|
|
@@ -135,6 +143,9 @@ function createSharedMobilityLayer(
|
|
|
135
143
|
});
|
|
136
144
|
|
|
137
145
|
const styleFunction = (feature) => {
|
|
146
|
+
if (layer.get(LAYER_PROP_IS_EXPORTING)) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
138
149
|
const clone = style.clone();
|
|
139
150
|
|
|
140
151
|
clone.getText().setText(feature.get("features").length);
|
package/src/utils/exportPdf.ts
CHANGED
|
@@ -526,6 +526,8 @@ export interface CopyrightExportOptions {
|
|
|
526
526
|
|
|
527
527
|
export interface MapExportOptions {
|
|
528
528
|
copyrightOptions?: CopyrightExportOptions;
|
|
529
|
+
onAfter?: (map: Map, layers: BaseLayer[]) => void;
|
|
530
|
+
onBefore?: (map: Map, layers: BaseLayer[]) => void;
|
|
529
531
|
pixelRatio?: number;
|
|
530
532
|
text?: string;
|
|
531
533
|
useCopyright?: boolean;
|
|
@@ -539,11 +541,14 @@ async function exportPdf(
|
|
|
539
541
|
mapExportOptions: MapExportOptions = {},
|
|
540
542
|
): Promise<boolean> {
|
|
541
543
|
const {
|
|
544
|
+
onAfter,
|
|
545
|
+
onBefore,
|
|
542
546
|
pixelRatio = 3,
|
|
543
547
|
useCopyright = true,
|
|
544
548
|
useMaxExtent = false,
|
|
545
549
|
usePlaceholder = true,
|
|
546
550
|
} = mapExportOptions;
|
|
551
|
+
|
|
547
552
|
const format = formatOptions?.format || "A4";
|
|
548
553
|
const sizePt = sizesByFormat72Dpi[format as string] || (format as number[]);
|
|
549
554
|
const size = sizePt.map((n) => {
|
|
@@ -590,6 +595,9 @@ async function exportPdf(
|
|
|
590
595
|
|
|
591
596
|
map.getLayers().clear();
|
|
592
597
|
|
|
598
|
+
// Hide/show some layer before export
|
|
599
|
+
onBefore?.(map, layers);
|
|
600
|
+
|
|
593
601
|
// Creates a new map with proper size and extent
|
|
594
602
|
const mapToExport = await createMapToExport(map, layers, extent, size, {
|
|
595
603
|
pixelRatio: pixelRatio,
|
|
@@ -612,6 +620,9 @@ async function exportPdf(
|
|
|
612
620
|
|
|
613
621
|
document.body.style.overflow = "auto";
|
|
614
622
|
|
|
623
|
+
// Undo what you have done on onBefore
|
|
624
|
+
onAfter?.(map, layers);
|
|
625
|
+
|
|
615
626
|
// Reset map to previous state
|
|
616
627
|
map.setLayers(layers);
|
|
617
628
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Collection } from "ol";
|
|
2
|
+
import BaseLayer from "ol/layer/Base";
|
|
3
|
+
import Group from "ol/layer/Group";
|
|
4
|
+
|
|
5
|
+
const getAllLayers = (
|
|
6
|
+
layersOrLayerGroup: BaseLayer[] | Collection<BaseLayer> | Group,
|
|
7
|
+
) => {
|
|
8
|
+
const allLayers = [];
|
|
9
|
+
function addLayersFrom(layers: BaseLayer[] | Collection<BaseLayer>) {
|
|
10
|
+
layers.forEach(function (layer) {
|
|
11
|
+
if (layer instanceof Group) {
|
|
12
|
+
addLayersFrom((layer as Group).getLayers());
|
|
13
|
+
} else {
|
|
14
|
+
allLayers.push(layer);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
addLayersFrom(
|
|
19
|
+
(layersOrLayerGroup as Group)?.getLayers?.() ||
|
|
20
|
+
(layersOrLayerGroup as BaseLayer[] | Collection<BaseLayer>),
|
|
21
|
+
);
|
|
22
|
+
return allLayers;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default getAllLayers;
|
|
@@ -1,29 +1,62 @@
|
|
|
1
|
+
import { MaplibreStyleLayer } from "mobility-toolbox-js/ol";
|
|
1
2
|
import { Feature } from "ol";
|
|
3
|
+
import { Group } from "ol/layer";
|
|
2
4
|
import { createContext } from "preact";
|
|
3
5
|
import { useContext } from "preact/hooks";
|
|
4
6
|
|
|
5
7
|
export interface RvfContextType {
|
|
6
8
|
isExportMenuOpen: boolean;
|
|
9
|
+
lineNetworkPlanLayer: MaplibreStyleLayer;
|
|
10
|
+
poisLayer: MaplibreStyleLayer;
|
|
7
11
|
selectedFeature: Feature;
|
|
8
12
|
selectedFeatures: Feature[];
|
|
13
|
+
sellingPointsLayer: MaplibreStyleLayer;
|
|
9
14
|
setIsExportMenuOpen: (isOpen: boolean) => void;
|
|
15
|
+
setLineNetworkPlanLayer: (layer: MaplibreStyleLayer) => void;
|
|
16
|
+
setPoisLayer: (layer: MaplibreStyleLayer) => void;
|
|
10
17
|
setSelectedFeature: (feature: Feature) => void;
|
|
11
18
|
setSelectedFeatures: (features: Feature[]) => void;
|
|
19
|
+
setSellingPointsLayer: (layer: MaplibreStyleLayer) => void;
|
|
20
|
+
setSharedMobilityLayerGroup: (group: Group) => void;
|
|
21
|
+
setTarifZonenLayer: (layer: MaplibreStyleLayer) => void;
|
|
22
|
+
sharedMobilityLayerGroup: Group;
|
|
23
|
+
tarifZonenLayer: MaplibreStyleLayer;
|
|
12
24
|
}
|
|
13
25
|
|
|
14
26
|
export const RvfContext = createContext<RvfContextType>({
|
|
15
27
|
isExportMenuOpen: false,
|
|
28
|
+
lineNetworkPlanLayer: null,
|
|
29
|
+
poisLayer: null,
|
|
16
30
|
selectedFeature: null,
|
|
17
31
|
selectedFeatures: [],
|
|
32
|
+
sellingPointsLayer: null,
|
|
18
33
|
setIsExportMenuOpen: () => {
|
|
19
34
|
console.warn("setIsExportMenuOpen is not implemented");
|
|
20
35
|
},
|
|
36
|
+
setLineNetworkPlanLayer: () => {
|
|
37
|
+
console.warn("setLineNetworkPlanLayer is not implemented");
|
|
38
|
+
},
|
|
39
|
+
setPoisLayer: () => {
|
|
40
|
+
console.warn("setPoisLayer is not implemented");
|
|
41
|
+
},
|
|
42
|
+
|
|
21
43
|
setSelectedFeature: () => {
|
|
22
44
|
console.warn("setSelectedFeature is not implemented");
|
|
23
45
|
},
|
|
24
46
|
setSelectedFeatures: () => {
|
|
25
47
|
console.warn("setSelectedFeatures is not implemented");
|
|
26
48
|
},
|
|
49
|
+
setSellingPointsLayer: () => {
|
|
50
|
+
console.warn("setSellingPointsLayer is not implemented");
|
|
51
|
+
},
|
|
52
|
+
setSharedMobilityLayerGroup: () => {
|
|
53
|
+
console.warn("setSharedMobilityLayerGroup is not implemented");
|
|
54
|
+
},
|
|
55
|
+
setTarifZonenLayer: () => {
|
|
56
|
+
console.warn("setTarifZonenLayer is not implemented");
|
|
57
|
+
},
|
|
58
|
+
sharedMobilityLayerGroup: null,
|
|
59
|
+
tarifZonenLayer: null,
|
|
27
60
|
});
|
|
28
61
|
|
|
29
62
|
const useRvfContext = (): RvfContextType => {
|
package/tailwind.config.mjs
CHANGED
|
@@ -11,13 +11,13 @@ const getClamp = (min, max) => {
|
|
|
11
11
|
min +
|
|
12
12
|
"px + (" +
|
|
13
13
|
max +
|
|
14
|
-
"-" +
|
|
14
|
+
" - " +
|
|
15
15
|
min +
|
|
16
|
-
") * (
|
|
16
|
+
") * (100cqw - " +
|
|
17
17
|
minScreenSize +
|
|
18
|
-
"px)/( " +
|
|
18
|
+
"px) / ( " +
|
|
19
19
|
maxScreenSize +
|
|
20
|
-
"-" +
|
|
20
|
+
" - " +
|
|
21
21
|
minScreenSize +
|
|
22
22
|
")), " +
|
|
23
23
|
max +
|
|
@@ -25,6 +25,28 @@ const getClamp = (min, max) => {
|
|
|
25
25
|
);
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
+
// const getClamp = (min, max) => {
|
|
29
|
+
// return (
|
|
30
|
+
// "clamp(" +
|
|
31
|
+
// min +
|
|
32
|
+
// "px, calc(" +
|
|
33
|
+
// min +
|
|
34
|
+
// "px + (" +
|
|
35
|
+
// max +
|
|
36
|
+
// "-" +
|
|
37
|
+
// min +
|
|
38
|
+
// ") * (100vw - " +
|
|
39
|
+
// minScreenSize +
|
|
40
|
+
// "px)/( " +
|
|
41
|
+
// maxScreenSize +
|
|
42
|
+
// "-" +
|
|
43
|
+
// minScreenSize +
|
|
44
|
+
// ")), " +
|
|
45
|
+
// max +
|
|
46
|
+
// "px )"
|
|
47
|
+
// );
|
|
48
|
+
// };
|
|
49
|
+
|
|
28
50
|
export default {
|
|
29
51
|
plugins: [containerQueries],
|
|
30
52
|
theme: {
|
|
@@ -39,33 +61,10 @@ export default {
|
|
|
39
61
|
ultradarkgray: "#2D2D2C", // another grey with no name
|
|
40
62
|
ultralightgrey: "#F5F5F5", // ultralight grey
|
|
41
63
|
},
|
|
42
|
-
height: {
|
|
43
|
-
innerControl: "12px",
|
|
44
|
-
inputControl: "20px",
|
|
45
|
-
},
|
|
46
|
-
margin: {
|
|
47
|
-
"4px": "4px",
|
|
48
|
-
"7px": "7px",
|
|
49
|
-
},
|
|
50
|
-
maxHeight: {
|
|
51
|
-
button: "40px",
|
|
52
|
-
},
|
|
53
|
-
maxWidth: {
|
|
54
|
-
button: "40px",
|
|
55
|
-
},
|
|
56
|
-
padding: {
|
|
57
|
-
1.75: "7px",
|
|
58
|
-
},
|
|
59
|
-
screens: {
|
|
60
|
-
large: "993px",
|
|
61
|
-
medium: "577px",
|
|
62
|
-
},
|
|
63
64
|
width: {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
largeMenu: "350px",
|
|
68
|
-
mediumMenu: "300px",
|
|
65
|
+
10: "40px", // for Route Schedule
|
|
66
|
+
8: "32px", // for Route Schedule
|
|
67
|
+
9: "36px", // for Route Schedule
|
|
69
68
|
},
|
|
70
69
|
},
|
|
71
70
|
fontFamily: {
|
|
@@ -84,6 +83,7 @@ export default {
|
|
|
84
83
|
lg: getClamp(19, 25), // H4
|
|
85
84
|
sm: getClamp(13, 15), // small
|
|
86
85
|
xl: getClamp(24, 31), // h3
|
|
86
|
+
xs: getClamp(13, 15), // small
|
|
87
87
|
},
|
|
88
88
|
},
|
|
89
89
|
};
|