-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathHandicapStopFinder.js
More file actions
127 lines (109 loc) · 3.46 KB
/
Copy pathHandicapStopFinder.js
File metadata and controls
127 lines (109 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import React from "react";
import { fromLonLat } from "ol/proj";
import MapboxStyleLayer from "../../layers/MapboxStyleLayer";
import Search from "../Search";
import { HANDICAP_SOURCE } from "../../utils/constants";
import StopSearchResult from "../../components/StopSearchResult";
class HandicapStopFinder extends Search {
constructor() {
super();
this.onIdle = this.onIdle.bind(this);
}
setApiKey(apiKey) {
this.apiKey = apiKey;
}
search(value) {
if (this.abortController) {
this.abortController.abort();
}
this.abortController = new AbortController();
const { signal } = this.abortController;
return fetch(
`${this.stopsUrl}/?&q=${encodeURIComponent(value)}&key=${this.apiKey}&limit=50`,
{
signal,
},
)
.then((data) => data.json())
.then((featureCollection) => {
return featureCollection?.features || [];
})
.catch(() => {
return [];
});
}
render(item) {
return <StopSearchResult properties={item?.properties} />;
}
// eslint-disable-next-line class-methods-use-this
value(item) {
return item.properties.name;
}
openPopup(item, map) {
const { layerService } = this.props;
const layer = layerService.getLayer("ch.sbb.netzkarte.stationen");
if (!layer) {
return;
}
this.map = map;
this.popupItem = item;
// We try to display the overlay only when the stations layer is ready and has all the stations loaded.
if (layer.ready) {
this.onIdle();
} else {
// disable map interactions to avoid clicking on wrong station
this.map.getInteractions().forEach((interaction) => {
interaction.setActive(false);
});
layer.once("datarendered", this.onIdle);
}
}
onIdle() {
if (!this.popupItem) {
return;
}
const { layerService, dispatchSetFeatureInfo } = this.props;
const { mbMap } = layerService.getLayer("ch.sbb.handicap.data");
if (
mbMap.getSource(HANDICAP_SOURCE) &&
mbMap.isSourceLoaded(HANDICAP_SOURCE)
) {
mbMap.off("idle", this.onIdle);
} else {
return;
}
const styleLayers = mbMap?.getStyle()?.layers;
// We get feature infos only for layer that use the source 'ch.sbb.handicap'.
const infoLayers = layerService.getLayersAsFlatArray().filter((layer) => {
const { visible, styleLayersFilter } = layer;
if (!visible || !styleLayers || !styleLayersFilter) {
return false;
}
const sourceIds = styleLayers
.filter(styleLayersFilter)
.map(({ source }) => source);
return (
layer instanceof MapboxStyleLayer && sourceIds.includes(HANDICAP_SOURCE)
);
});
// Here we simulate a click, it's the best way to get the proper popup informations.
// The only drawback is that if the station is not rendered there is no popup.
const coordinates = fromLonLat(this.popupItem.geometry.coordinates);
const infos = infoLayers
.map((layer) => layer.getFeatureInfoAtCoordinate(coordinates))
.filter((i) => i);
Promise.all(infos).then((featInfos) => {
this.featureInfos = featInfos.filter(({ features }) => features.length);
dispatchSetFeatureInfo(this.featureInfos);
});
// reactivate map interactions
this.map.getInteractions().forEach((interaction) => {
interaction.setActive(true);
});
}
clearPopup() {
this.popupItem = null;
return this.featureInfos;
}
}
export default HandicapStopFinder;