@geops/rvf-mobility-web-component 0.1.83 → 0.1.84
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 +33 -0
- package/index.js +206 -187
- package/package.json +2 -2
- package/src/Departure/Departure.tsx +6 -3
- package/src/FeatureDetails/FeatureDetails.tsx +4 -4
- package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +22 -0
- package/src/LayerTreeMenu/LayerTreeMenu.tsx +12 -4
- package/src/LayoutState/LayoutState.tsx +144 -63
- package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +2 -2
- package/src/LinesNetworkPlanLayerHighlight/LinesNetworkPlanLayerHighlight.tsx +2 -40
- package/src/MapLayout/MapLayout.tsx +2 -7
- package/src/MobilityMap/MobilityMap.tsx +1 -6
- package/src/MobilityMap/MobilityMapAttributes.ts +28 -7
- package/src/NotificationDetails/NotificationDetails.tsx +21 -22
- package/src/NotificationsLayer/NotificationsLayer.tsx +47 -3
- package/src/OverlayDetails/OverlayDetails.tsx +5 -0
- package/src/RealtimeLayer/RealtimeLayer.tsx +44 -50
- package/src/RouteIcon/RouteIcon.tsx +25 -14
- package/src/RouteSchedule/RouteSchedule.tsx +14 -11
- package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +6 -3
- package/src/RouteScheduleHeader/RouteScheduleHeader.tsx +8 -2
- package/src/RouteStop/RouteStop.tsx +14 -29
- package/src/RouteStopPlatform/RouteStopPlatform.tsx +1 -3
- package/src/RouteStopProgress/RouteStopProgress.tsx +11 -18
- package/src/RouteStopStation/RouteStopStation.tsx +3 -3
- package/src/RvfRealtimeLayer/RvfRealtimeLayer.tsx +16 -3
- package/src/RvfSearch/RvfSearch.tsx +5 -4
- package/src/Search/Search.tsx +41 -20
- package/src/Search/SearchBase.tsx +169 -0
- package/src/Search/SearchHeadless.tsx +79 -0
- package/src/Search/index.tsx +2 -0
- package/src/SearchLinesResult/SearchLinesResult.tsx +43 -0
- package/src/SearchLinesResult/index.tsx +1 -0
- package/src/SearchLinesResults/SearchLinesResults.tsx +106 -0
- package/src/SearchLinesResults/index.tsx +1 -0
- package/src/SearchLnpStopsResult/SearchLnpStopsResult.tsx +42 -0
- package/src/SearchLnpStopsResult/index.tsx +1 -0
- package/src/SearchLnpStopsResults/SearchLnpStopsResults.tsx +106 -0
- package/src/SearchLnpStopsResults/index.tsx +1 -0
- package/src/SearchResult/SearchResult.tsx +25 -0
- package/src/SearchResult/index.tsx +1 -0
- package/src/SearchResults/SearchResults.tsx +81 -0
- package/src/SearchResults/index.tsx +1 -0
- package/src/SearchResultsHeader/SearchResultsHeader.tsx +36 -0
- package/src/SearchResultsHeader/index.tsx +1 -0
- package/src/SearchStopsResult/SearchStopsResult.tsx +43 -0
- package/src/SearchStopsResult/index.tsx +1 -0
- package/src/SearchStopsResults/SearchStopsResults.tsx +101 -0
- package/src/SearchStopsResults/index.tsx +1 -0
- package/src/SearchTrainsResult/SearchTrainsResult.tsx +42 -0
- package/src/SearchTrainsResult/index.tsx +1 -0
- package/src/SearchTrainsResults/SearchTrainsResults.tsx +109 -0
- package/src/SearchTrainsResults/index.tsx +1 -0
- package/src/SingleClickListener/SingleClickListener.tsx +38 -2
- package/src/Station/Station.tsx +23 -48
- package/src/StationHeader/StationHeader.tsx +3 -3
- package/src/StationsLayer/StationsLayer.tsx +9 -1
- package/src/StopsSearch/StopsSearch.tsx +2 -2
- package/src/ui/InputSearch/InputSearch.tsx +105 -0
- package/src/ui/InputSearch/index.tsx +1 -0
- package/src/utils/centerOnVehicle.ts +9 -2
- package/src/utils/constants.ts +8 -1
- package/src/utils/fullTrajectoryStyle.ts +4 -7
- package/src/utils/getBgColor.ts +4 -2
- package/src/utils/getDelayColorForVehicle.test.ts +21 -11
- package/src/utils/getDelayColorForVehicle.ts +7 -5
- package/src/utils/getDelayTextForVehicle.test.ts +12 -12
- package/src/utils/getDelayTextForVehicle.ts +4 -0
- package/src/utils/getMainColorForVehicle.ts +11 -4
- package/src/utils/getRadius.ts +9 -3
- package/src/utils/getTextColor.ts +1 -1
- package/src/utils/getTextColorForVehicle.ts +29 -0
- package/src/utils/getTextFontForVehicle.test.ts +1 -1
- package/src/utils/getTextFontForVehicle.tsx +11 -3
- package/src/utils/getTextForVehicle.ts +7 -1
- package/src/utils/hooks/useFit.tsx +69 -0
- package/src/utils/hooks/useFitOnFeatures.tsx +77 -0
- package/src/utils/hooks/useLayersConfig.tsx +3 -0
- package/src/utils/hooks/useLnp.tsx +39 -5
- package/src/utils/hooks/useMapContext.tsx +2 -5
- package/src/utils/hooks/useRealtimeDepartures.tsx +45 -0
- package/src/utils/hooks/useRealtimeRenderedTrajectory.tsx +42 -0
- package/src/utils/hooks/useRealtimeStation.tsx +39 -0
- package/src/utils/hooks/useRealtimeStopSequences.tsx +43 -0
- package/src/utils/hooks/useRealtimeTrainsByRouteIdentifier.tsx +71 -0
- package/src/utils/hooks/useRouteStop.tsx +7 -1
- package/src/utils/hooks/useSearchLines.tsx +34 -0
- package/src/utils/hooks/useSearchLnpStops.tsx +38 -0
- package/src/utils/hooks/useSearchStops.tsx +85 -0
- package/src/utils/hooks/useSearchTrains.tsx +83 -0
- package/src/utils/realtimeRVFStyle.ts +38 -30
- package/src/utils/translations.ts +17 -0
- package/tash +58 -0
- package/src/utils/centerOnStation.ts +0 -18
- package/src/utils/getDelayFontForVehicle.test.ts +0 -7
- package/src/utils/getDelayFontForVehicle.tsx +0 -8
- package/src/utils/hooks/useStation.tsx +0 -22
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { createContext } from "preact";
|
|
2
2
|
import { useContext } from "preact/hooks";
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
RealtimeStation,
|
|
6
|
+
RealtimeStop,
|
|
7
|
+
RealtimeStopSequence,
|
|
8
|
+
} from "mobility-toolbox-js/types";
|
|
5
9
|
|
|
6
10
|
import type { StopStatus } from "../getStopStatus";
|
|
7
11
|
|
|
@@ -13,6 +17,7 @@ export interface RouteStopContextType {
|
|
|
13
17
|
stop?: {
|
|
14
18
|
platform?: string;
|
|
15
19
|
} & RealtimeStop;
|
|
20
|
+
stopSequence?: RealtimeStopSequence;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
export const RouteStopContext = createContext({
|
|
@@ -21,6 +26,7 @@ export const RouteStopContext = createContext({
|
|
|
21
26
|
station: null,
|
|
22
27
|
status: null,
|
|
23
28
|
stop: null,
|
|
29
|
+
stopSequence: null,
|
|
24
30
|
} as RouteStopContextType);
|
|
25
31
|
|
|
26
32
|
const useRouteStop = (): RouteStopContextType => {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { useMemo } from "preact/hooks";
|
|
2
|
+
|
|
3
|
+
import { useLnpLinesInfos } from "./useLnp";
|
|
4
|
+
import useMapContext from "./useMapContext";
|
|
5
|
+
|
|
6
|
+
import type { LnpLineInfo } from "./useLnp";
|
|
7
|
+
import type { SearchResponse } from "./useSearchStops";
|
|
8
|
+
|
|
9
|
+
function useSearchLines(query: string): SearchResponse<LnpLineInfo> {
|
|
10
|
+
const { hasLnp } = useMapContext();
|
|
11
|
+
const linesInfos = useLnpLinesInfos();
|
|
12
|
+
|
|
13
|
+
const results = useMemo(() => {
|
|
14
|
+
if (!query || !linesInfos || !hasLnp) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
return Object.values(linesInfos || {}).filter((line: LnpLineInfo) => {
|
|
18
|
+
return (
|
|
19
|
+
line?.short_name?.toLowerCase().includes(query.toLowerCase()) ||
|
|
20
|
+
line?.long_name?.toLowerCase().includes(query.toLowerCase()) ||
|
|
21
|
+
line?.id?.toLowerCase().includes(query.toLowerCase()) ||
|
|
22
|
+
line?.external_id?.toLowerCase().includes(query.toLowerCase()) ||
|
|
23
|
+
line?.mot?.toLowerCase().includes(query.toLowerCase())
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
}, [hasLnp, linesInfos, query]);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
isLoading: false,
|
|
30
|
+
results: results || [],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default useSearchLines;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useMemo } from "preact/hooks";
|
|
2
|
+
|
|
3
|
+
import { useLnpStopsInfos } from "./useLnp";
|
|
4
|
+
import useMapContext from "./useMapContext";
|
|
5
|
+
|
|
6
|
+
import type { LnpStopInfo } from "./useLnp";
|
|
7
|
+
import type { SearchResponse } from "./useSearchStops";
|
|
8
|
+
|
|
9
|
+
function useSearchLnpStops(query: string): SearchResponse<LnpStopInfo> {
|
|
10
|
+
const { hasLnp } = useMapContext();
|
|
11
|
+
const infos = useLnpStopsInfos();
|
|
12
|
+
|
|
13
|
+
const results = useMemo(() => {
|
|
14
|
+
if (!query || !infos || !hasLnp) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
return Object.values(infos || {}).filter((item: LnpStopInfo) => {
|
|
18
|
+
return (
|
|
19
|
+
item?.short_name?.toLowerCase().includes(query.toLowerCase()) ||
|
|
20
|
+
item?.long_name?.toLowerCase().includes(query.toLowerCase()) ||
|
|
21
|
+
item?.external_id?.toLowerCase().includes(query.toLowerCase()) ||
|
|
22
|
+
item?.codes?.find((code) => {
|
|
23
|
+
return (
|
|
24
|
+
code.toLowerCase() === query.toLowerCase() ||
|
|
25
|
+
code.split(":")[1]?.toLowerCase() === query.toLowerCase()
|
|
26
|
+
);
|
|
27
|
+
})
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
}, [hasLnp, infos, query]);
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
isLoading: false,
|
|
34
|
+
results: results || [],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default useSearchLnpStops;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import debounce from "lodash.debounce";
|
|
2
|
+
import { StopsAPI } from "mobility-toolbox-js/ol";
|
|
3
|
+
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
4
|
+
|
|
5
|
+
import { MAX_EXTENT_4326 } from "../constants";
|
|
6
|
+
|
|
7
|
+
import useMapContext from "./useMapContext";
|
|
8
|
+
|
|
9
|
+
import type { StopsParameters, StopsResponse } from "mobility-toolbox-js/types";
|
|
10
|
+
|
|
11
|
+
export type StopsFeature = StopsResponse["features"][0];
|
|
12
|
+
|
|
13
|
+
export interface SearchResponse<T> {
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
results: T[] | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* This hook launch a request to the Stops API.
|
|
20
|
+
*
|
|
21
|
+
* @param query
|
|
22
|
+
*/
|
|
23
|
+
function useSearchStops(
|
|
24
|
+
query: string,
|
|
25
|
+
params?: Partial<StopsParameters>,
|
|
26
|
+
): SearchResponse<StopsFeature> {
|
|
27
|
+
const { apikey, mots, stopsurl } = useMapContext();
|
|
28
|
+
const [results, setResults] = useState<StopsFeature[] | undefined>();
|
|
29
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
30
|
+
|
|
31
|
+
const api: StopsAPI = useMemo(() => {
|
|
32
|
+
if (!apikey || !stopsurl) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return new StopsAPI({ apiKey: apikey, url: stopsurl });
|
|
36
|
+
}, [apikey, stopsurl]);
|
|
37
|
+
|
|
38
|
+
const debouncedSearch = useMemo(() => {
|
|
39
|
+
let abortCtrl: AbortController | undefined;
|
|
40
|
+
|
|
41
|
+
return debounce((q) => {
|
|
42
|
+
abortCtrl?.abort();
|
|
43
|
+
abortCtrl = new AbortController();
|
|
44
|
+
|
|
45
|
+
const reqParams = {
|
|
46
|
+
bbox: MAX_EXTENT_4326?.join(","),
|
|
47
|
+
mots,
|
|
48
|
+
q,
|
|
49
|
+
...(params ?? {}),
|
|
50
|
+
} as StopsParameters;
|
|
51
|
+
|
|
52
|
+
setIsLoading(true);
|
|
53
|
+
api
|
|
54
|
+
.search(reqParams, { signal: abortCtrl.signal })
|
|
55
|
+
.then((res: StopsResponse) => {
|
|
56
|
+
setResults(res.features);
|
|
57
|
+
setIsLoading(false);
|
|
58
|
+
})
|
|
59
|
+
.catch((e) => {
|
|
60
|
+
// AbortError is expected
|
|
61
|
+
if (e.code !== 20) {
|
|
62
|
+
// eslint-disable-next-line no-console
|
|
63
|
+
console.error("Failed to fetch stations", e);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
setIsLoading(false);
|
|
67
|
+
});
|
|
68
|
+
}, 150);
|
|
69
|
+
}, [api, mots, params]);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!query || !api) {
|
|
73
|
+
setResults([]);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
debouncedSearch(query);
|
|
77
|
+
}, [api, debouncedSearch, query]);
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
isLoading,
|
|
81
|
+
results: results || [],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default useSearchStops;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import debounce from "lodash.debounce";
|
|
2
|
+
import { RealtimeRestAPI } from "mobility-toolbox-js/ol";
|
|
3
|
+
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
4
|
+
|
|
5
|
+
import useMapContext from "./useMapContext";
|
|
6
|
+
|
|
7
|
+
import type { RealtimeRouteIdentifierMatch } from "mobility-toolbox-js/types";
|
|
8
|
+
|
|
9
|
+
import type { SearchResponse } from "./useSearchStops";
|
|
10
|
+
|
|
11
|
+
function useSearchTrains(
|
|
12
|
+
query: string,
|
|
13
|
+
): SearchResponse<RealtimeRouteIdentifierMatch> {
|
|
14
|
+
const { apikey, hasRealtime, realtimeresturl, realtimetenant, tenant } =
|
|
15
|
+
useMapContext();
|
|
16
|
+
|
|
17
|
+
const [results, setResults] = useState<
|
|
18
|
+
RealtimeRouteIdentifierMatch[] | undefined
|
|
19
|
+
>();
|
|
20
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
21
|
+
|
|
22
|
+
const tenantMemo = useMemo(() => {
|
|
23
|
+
return realtimetenant || tenant;
|
|
24
|
+
}, [realtimetenant, tenant]);
|
|
25
|
+
|
|
26
|
+
const api = useMemo(() => {
|
|
27
|
+
if (!apikey || !tenantMemo || !hasRealtime) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return new RealtimeRestAPI({
|
|
31
|
+
apiKey: apikey,
|
|
32
|
+
tenant: tenantMemo,
|
|
33
|
+
url: realtimeresturl,
|
|
34
|
+
});
|
|
35
|
+
}, [apikey, tenantMemo, hasRealtime, realtimeresturl]);
|
|
36
|
+
|
|
37
|
+
const debouncedSearch = useMemo(() => {
|
|
38
|
+
let abortCtrl: AbortController | undefined;
|
|
39
|
+
|
|
40
|
+
return debounce((q?: string) => {
|
|
41
|
+
abortCtrl?.abort();
|
|
42
|
+
abortCtrl = new AbortController();
|
|
43
|
+
|
|
44
|
+
setIsLoading(true);
|
|
45
|
+
api
|
|
46
|
+
.trainsByRouteIdentifier(
|
|
47
|
+
{
|
|
48
|
+
exact_match: false,
|
|
49
|
+
query: q,
|
|
50
|
+
},
|
|
51
|
+
{ signal: abortCtrl.signal },
|
|
52
|
+
)
|
|
53
|
+
.then((res) => {
|
|
54
|
+
setResults(res.matches);
|
|
55
|
+
setIsLoading(false);
|
|
56
|
+
})
|
|
57
|
+
.catch((e) => {
|
|
58
|
+
// AbortError is expected
|
|
59
|
+
if (e.code !== 20) {
|
|
60
|
+
// eslint-disable-next-line no-console
|
|
61
|
+
console.error("Failed to fetch trains by route identifier", e);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
setIsLoading(false);
|
|
65
|
+
});
|
|
66
|
+
}, 150);
|
|
67
|
+
}, [api]);
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (!query || !api) {
|
|
71
|
+
setResults([]);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
debouncedSearch(query);
|
|
75
|
+
}, [api, debouncedSearch, query]);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
isLoading,
|
|
79
|
+
results: results || [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default useSearchTrains;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createCanvas } from "mobility-toolbox-js/ol";
|
|
2
2
|
|
|
3
|
-
// @ts-expect-error - svg loaded as dataurl
|
|
4
3
|
import noRealtime from "../icons/NoRealtime/norealtime.svg";
|
|
5
4
|
|
|
6
5
|
import type {
|
|
@@ -174,6 +173,8 @@ const cacheText: StyleCache = {};
|
|
|
174
173
|
* @private
|
|
175
174
|
*/
|
|
176
175
|
export const getTextCanvas = (
|
|
176
|
+
trajectory: RealtimeTrajectory,
|
|
177
|
+
viewState: ViewState,
|
|
177
178
|
text: string,
|
|
178
179
|
origin: number,
|
|
179
180
|
textSize: number,
|
|
@@ -181,7 +182,12 @@ export const getTextCanvas = (
|
|
|
181
182
|
strokeColor: string,
|
|
182
183
|
hasStroke: boolean,
|
|
183
184
|
pixelRatio: number,
|
|
184
|
-
getTextFont: (
|
|
185
|
+
getTextFont: (
|
|
186
|
+
trajectory: RealtimeTrajectory,
|
|
187
|
+
viewState: ViewState,
|
|
188
|
+
fontSize: number,
|
|
189
|
+
text?: string,
|
|
190
|
+
) => string,
|
|
185
191
|
) => {
|
|
186
192
|
const key = `${text}, ${origin}, ${textSize}, ${fillColor},${strokeColor}, ${hasStroke}, ${pixelRatio}`;
|
|
187
193
|
if (!cacheText[key]) {
|
|
@@ -197,7 +203,7 @@ export const getTextCanvas = (
|
|
|
197
203
|
ctx.save();
|
|
198
204
|
ctx.textBaseline = "middle";
|
|
199
205
|
ctx.textAlign = "center";
|
|
200
|
-
ctx.font = getTextFont(textSize + 2, text);
|
|
206
|
+
ctx.font = getTextFont(trajectory, viewState, textSize + 2, text);
|
|
201
207
|
ctx.strokeStyle = strokeColor;
|
|
202
208
|
ctx.strokeText(text, origin, origin);
|
|
203
209
|
ctx.restore();
|
|
@@ -207,7 +213,7 @@ export const getTextCanvas = (
|
|
|
207
213
|
ctx.textBaseline = "middle";
|
|
208
214
|
ctx.textAlign = "center";
|
|
209
215
|
ctx.fillStyle = fillColor;
|
|
210
|
-
ctx.font = getTextFont(textSize, text);
|
|
216
|
+
ctx.font = getTextFont(trajectory, viewState, textSize, text);
|
|
211
217
|
ctx.strokeStyle = strokeColor;
|
|
212
218
|
ctx.strokeText(text, origin, origin);
|
|
213
219
|
ctx.fillText(text, origin, origin);
|
|
@@ -237,13 +243,13 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
237
243
|
const {
|
|
238
244
|
delayDisplay = 300000,
|
|
239
245
|
delayOutlineColor = "#000",
|
|
240
|
-
|
|
246
|
+
getColor = () => {
|
|
241
247
|
return "#000";
|
|
242
248
|
},
|
|
243
249
|
getDelayColor = () => {
|
|
244
250
|
return "#000";
|
|
245
251
|
},
|
|
246
|
-
getDelayFont = (fontSize: number) => {
|
|
252
|
+
getDelayFont = (traj, viewStat, fontSize: number) => {
|
|
247
253
|
return `bold ${fontSize}px arial, sans-serif`;
|
|
248
254
|
},
|
|
249
255
|
getDelayText = () => {
|
|
@@ -258,13 +264,13 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
258
264
|
getRadius = () => {
|
|
259
265
|
return 0;
|
|
260
266
|
},
|
|
261
|
-
getText = (
|
|
262
|
-
return
|
|
267
|
+
getText = (traj: RealtimeTrajectory) => {
|
|
268
|
+
return traj?.properties?.line?.name || "I";
|
|
263
269
|
},
|
|
264
270
|
getTextColor = () => {
|
|
265
271
|
return "#000";
|
|
266
272
|
},
|
|
267
|
-
getTextFont = (fontSize: number) => {
|
|
273
|
+
getTextFont = (traj, viewStat, fontSize: number) => {
|
|
268
274
|
return `bold ${fontSize}px arial, sans-serif`;
|
|
269
275
|
},
|
|
270
276
|
getTextSize = () => {
|
|
@@ -275,8 +281,8 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
275
281
|
useDelayStyle,
|
|
276
282
|
} = options;
|
|
277
283
|
|
|
278
|
-
const { pixelRatio = 1
|
|
279
|
-
|
|
284
|
+
const { pixelRatio = 1 } = viewState;
|
|
285
|
+
const { type } = trajectory.properties;
|
|
280
286
|
const {
|
|
281
287
|
delay,
|
|
282
288
|
has_realtime_journey: hasRealtimeJourney,
|
|
@@ -287,22 +293,16 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
287
293
|
} = trajectory.properties;
|
|
288
294
|
let { color, name, text_color: textColor } = line || {};
|
|
289
295
|
|
|
290
|
-
name = getText(
|
|
296
|
+
name = getText(trajectory, viewState);
|
|
291
297
|
|
|
292
298
|
const cancelled = state === "JOURNEY_CANCELLED";
|
|
293
299
|
|
|
294
|
-
if (!type) {
|
|
295
|
-
type = "Rail";
|
|
296
|
-
}
|
|
297
|
-
|
|
298
300
|
if (!name) {
|
|
299
301
|
name = "I";
|
|
300
302
|
}
|
|
301
303
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
// }
|
|
305
|
-
color = getBgColor(type, line);
|
|
304
|
+
textColor = getTextColor(trajectory, viewState);
|
|
305
|
+
color = getColor(trajectory, viewState);
|
|
306
306
|
|
|
307
307
|
if (color && !color.startsWith("#")) {
|
|
308
308
|
color = `#${color}`;
|
|
@@ -312,12 +312,11 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
312
312
|
textColor = `#${textColor}`;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
-
const z = Math.min(Math.floor(zoom || 1), 16);
|
|
316
315
|
const hover = !!(hoverVehicleId && hoverVehicleId === id);
|
|
317
316
|
const selected = !!(selectedVehicleId && selectedVehicleId === id);
|
|
318
317
|
|
|
319
318
|
// Calcul the radius of the circle
|
|
320
|
-
let radius = getRadius(
|
|
319
|
+
let radius = getRadius(trajectory, viewState) * pixelRatio;
|
|
321
320
|
const isDisplayStrokeAndDelay =
|
|
322
321
|
radius >= getMaxRadiusForStrokeAndDelay() * pixelRatio;
|
|
323
322
|
|
|
@@ -362,7 +361,7 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
362
361
|
delayBg = getDelayBgCanvas(
|
|
363
362
|
origin,
|
|
364
363
|
radiusDelay,
|
|
365
|
-
getDelayColor(delay, cancelled),
|
|
364
|
+
getDelayColor(trajectory, viewState, delay, cancelled),
|
|
366
365
|
);
|
|
367
366
|
}
|
|
368
367
|
|
|
@@ -379,14 +378,19 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
379
378
|
cancelled ? 19 : 14,
|
|
380
379
|
Math.min(cancelled ? 19 : 17, radius * 1.2),
|
|
381
380
|
) * pixelRatio;
|
|
382
|
-
const text = getDelayText(delay, cancelled);
|
|
381
|
+
const text = getDelayText(trajectory, viewState, delay, cancelled);
|
|
383
382
|
|
|
384
383
|
if (text) {
|
|
385
384
|
delayText = getDelayTextCanvas(
|
|
386
385
|
text,
|
|
387
386
|
fontSize,
|
|
388
|
-
getDelayFont(
|
|
389
|
-
|
|
387
|
+
getDelayFont(
|
|
388
|
+
trajectory,
|
|
389
|
+
viewState,
|
|
390
|
+
hover || viewState.zoom >= 13 ? fontSize : 0,
|
|
391
|
+
text,
|
|
392
|
+
), // Only display delay labels on zoom 13+
|
|
393
|
+
getDelayColor(trajectory, viewState, delay, cancelled, true),
|
|
390
394
|
delayOutlineColor,
|
|
391
395
|
pixelRatio,
|
|
392
396
|
);
|
|
@@ -398,9 +402,9 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
398
402
|
// Draw colored circle with black border
|
|
399
403
|
let circleFillColor;
|
|
400
404
|
if (useDelayStyle) {
|
|
401
|
-
circleFillColor = getDelayColor(delay, cancelled);
|
|
405
|
+
circleFillColor = getDelayColor(trajectory, viewState, delay, cancelled);
|
|
402
406
|
} else {
|
|
403
|
-
circleFillColor = color ||
|
|
407
|
+
circleFillColor = color || getColor(trajectory, viewState);
|
|
404
408
|
}
|
|
405
409
|
|
|
406
410
|
const hasStroke = isDisplayStrokeAndDelay || hover || selected;
|
|
@@ -460,14 +464,16 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
460
464
|
if (isDisplayText) {
|
|
461
465
|
const fontSize2 = Math.max(radius, 10);
|
|
462
466
|
const textSize = getTextSize(
|
|
467
|
+
trajectory,
|
|
468
|
+
viewState,
|
|
463
469
|
ctx,
|
|
464
470
|
markerSize,
|
|
465
471
|
name,
|
|
466
472
|
fontSize2,
|
|
467
|
-
getTextFont,
|
|
473
|
+
getTextFont(trajectory, viewState, fontSize2, name),
|
|
468
474
|
);
|
|
469
475
|
const textColor2 = !useDelayStyle
|
|
470
|
-
? textColor || getTextColor(
|
|
476
|
+
? textColor || getTextColor(trajectory, viewState)
|
|
471
477
|
: "#000000";
|
|
472
478
|
const hasStroke2 =
|
|
473
479
|
!!useDelayStyle &&
|
|
@@ -475,6 +481,8 @@ const realtimeRVFStyle: RealtimeStyleFunction = (
|
|
|
475
481
|
operatorProvidesRealtime === "yes";
|
|
476
482
|
|
|
477
483
|
circleText = getTextCanvas(
|
|
484
|
+
trajectory,
|
|
485
|
+
viewState,
|
|
478
486
|
name,
|
|
479
487
|
origin,
|
|
480
488
|
textSize,
|
|
@@ -53,7 +53,12 @@ const translations: Translations = {
|
|
|
53
53
|
print_menu_title: "Drucken",
|
|
54
54
|
reason: "Grund",
|
|
55
55
|
recommendation: "Empfehlung",
|
|
56
|
+
search_input_cancel: "Eingabe löschen",
|
|
57
|
+
search_lines_results: "Linien",
|
|
56
58
|
search_menu_title: "Suchen",
|
|
59
|
+
search_placeholder: "Haltestelle, Linie, Fährte suchen",
|
|
60
|
+
search_stops_results: "Haltestellen",
|
|
61
|
+
search_trains_results: "Fährte",
|
|
57
62
|
share_email_send: "E-Mail senden",
|
|
58
63
|
share_image_save: "Bild speichern",
|
|
59
64
|
share_menu_title: "Teilen",
|
|
@@ -107,7 +112,11 @@ const translations: Translations = {
|
|
|
107
112
|
print_menu_title: "Print",
|
|
108
113
|
reason: "Reason",
|
|
109
114
|
recommendation: "Recommendation",
|
|
115
|
+
search_lines_results: "Lines",
|
|
110
116
|
search_menu_title: "Search",
|
|
117
|
+
search_placeholder: "Search stop, line, route",
|
|
118
|
+
search_stops_results: "Stops",
|
|
119
|
+
search_trains_results: "Routes",
|
|
111
120
|
share_email_send: "Send email",
|
|
112
121
|
share_image_save: "Save image",
|
|
113
122
|
share_menu_title: "Share",
|
|
@@ -161,7 +170,11 @@ const translations: Translations = {
|
|
|
161
170
|
print_menu_title: "Imprimer",
|
|
162
171
|
reason: "Raison",
|
|
163
172
|
recommendation: "Recommandation",
|
|
173
|
+
search_lines_results: "Lignes",
|
|
164
174
|
search_menu_title: "Rechercher",
|
|
175
|
+
search_placeholder: "Rechercher un arrêt, une ligne, une route",
|
|
176
|
+
search_stops_results: "Arrêts",
|
|
177
|
+
search_trains_results: "Trajets",
|
|
165
178
|
share_email_send: "Envoyer un email",
|
|
166
179
|
share_image_save: "Enregistrer l'image",
|
|
167
180
|
share_menu_title: "Partager",
|
|
@@ -215,7 +228,11 @@ const translations: Translations = {
|
|
|
215
228
|
print_menu_title: "Stampa",
|
|
216
229
|
reason: "Motivo",
|
|
217
230
|
recommendation: "Raccomandazione",
|
|
231
|
+
search_lines_results: "Linee",
|
|
218
232
|
search_menu_title: "Cerca",
|
|
233
|
+
search_placeholder: "Cerca fermata, linea, percorso",
|
|
234
|
+
search_stops_results: "Fermate",
|
|
235
|
+
search_trains_results: "Percorsi",
|
|
219
236
|
share_email_send: "Invia email",
|
|
220
237
|
share_image_save: "Salva immagine",
|
|
221
238
|
share_menu_title: "Condividi",
|
package/tash
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[1mdiff --git a/src/MobilityMap/MobilityMapAttributes.ts b/src/MobilityMap/MobilityMapAttributes.ts[m
|
|
2
|
+
[1mindex 25279ab..b1c1d8e 100644[m
|
|
3
|
+
[1m--- a/src/MobilityMap/MobilityMapAttributes.ts[m
|
|
4
|
+
[1m+++ b/src/MobilityMap/MobilityMapAttributes.ts[m
|
|
5
|
+
[36m@@ -171,7 +171,7 @@[m [mwhere:[m
|
|
6
|
+
},[m
|
|
7
|
+
lineid: {[m
|
|
8
|
+
description: `An id or a short/long name of a line to highlight. <br/>Ex: S1`,[m
|
|
9
|
+
[31m- public: true,[m
|
|
10
|
+
[32m+[m[32m public: false,[m
|
|
11
|
+
},[m
|
|
12
|
+
lnp: {[m
|
|
13
|
+
defaultValue: "true",[m
|
|
14
|
+
[36m@@ -197,7 +197,7 @@[m [mwhere:[m
|
|
15
|
+
mapsetplanid: {[m
|
|
16
|
+
description:[m
|
|
17
|
+
"An id of the mapset plan to display. Mostly for debugging purposes.",[m
|
|
18
|
+
[31m- public: true,[m
|
|
19
|
+
[32m+[m[32m public: false,[m
|
|
20
|
+
},[m
|
|
21
|
+
mapsettags: {[m
|
|
22
|
+
description: `The ${geopsMapsetApiLink} tags to get the plans from.`,[m
|
|
23
|
+
[36m@@ -210,7 +210,7 @@[m [mwhere:[m
|
|
24
|
+
},[m
|
|
25
|
+
mapsettimestamp: {[m
|
|
26
|
+
description: `The ${geopsMapsetApiLink} timestamp used to load valid standard plan. If not defined it will use the current time.`,[m
|
|
27
|
+
[31m- public: true,[m
|
|
28
|
+
[32m+[m[32m public: false,[m
|
|
29
|
+
},[m
|
|
30
|
+
mapseturl: {[m
|
|
31
|
+
defaultValue: "https://editor.mapset.io/api/v1/",[m
|
|
32
|
+
[36m@@ -256,7 +256,7 @@[m [mwhere:[m
|
|
33
|
+
},[m
|
|
34
|
+
notificationid: {[m
|
|
35
|
+
description: `An id of a notification to show details of.`,[m
|
|
36
|
+
[31m- public: true,[m
|
|
37
|
+
[32m+[m[32m public: false,[m
|
|
38
|
+
},[m
|
|
39
|
+
notificationtenant: {[m
|
|
40
|
+
defaultValue: "rvf",[m
|
|
41
|
+
[36m@@ -342,7 +342,7 @@[m [mwhere:[m
|
|
42
|
+
},[m
|
|
43
|
+
stationid: {[m
|
|
44
|
+
description: `An id or a short/long name of a station to show details of.`,[m
|
|
45
|
+
[31m- public: true,[m
|
|
46
|
+
[32m+[m[32m public: false,[m
|
|
47
|
+
},[m
|
|
48
|
+
stopsurl: {[m
|
|
49
|
+
defaultValue: "https://api.geops.io/stops/v1/",[m
|
|
50
|
+
[36m@@ -361,7 +361,7 @@[m [mwhere:[m
|
|
51
|
+
},[m
|
|
52
|
+
trainid: {[m
|
|
53
|
+
description: `An id of a route to highlight on the map and to show details of.`,[m
|
|
54
|
+
[31m- public: true,[m
|
|
55
|
+
[32m+[m[32m public: false,[m
|
|
56
|
+
},[m
|
|
57
|
+
zoom: {[m
|
|
58
|
+
description: "The zoom level of the map.",[m
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { fromLonLat } from "ol/proj";
|
|
2
|
-
|
|
3
|
-
import type { Map } from "ol";
|
|
4
|
-
|
|
5
|
-
import type { StationFeature } from "../StopsSearch";
|
|
6
|
-
|
|
7
|
-
const centerOnStation = (selectedStation: StationFeature, map: Map) => {
|
|
8
|
-
const center = selectedStation?.geometry?.coordinates;
|
|
9
|
-
if (center) {
|
|
10
|
-
map?.getView()?.animate({
|
|
11
|
-
center: fromLonLat(center),
|
|
12
|
-
duration: 500,
|
|
13
|
-
zoom: 16,
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default centerOnStation;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { createContext } from "preact";
|
|
2
|
-
import { useContext } from "preact/hooks";
|
|
3
|
-
|
|
4
|
-
import type { RealtimeStation } from "mobility-toolbox-js/types";
|
|
5
|
-
|
|
6
|
-
export interface StationContextType {
|
|
7
|
-
station?: RealtimeStation;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const StationContext = createContext({
|
|
11
|
-
station: null,
|
|
12
|
-
} as StationContextType);
|
|
13
|
-
|
|
14
|
-
const useRouteStop = (): StationContextType => {
|
|
15
|
-
const context = useContext<StationContextType>(StationContext);
|
|
16
|
-
if (!context) {
|
|
17
|
-
throw new Error("useRouteStop must be used within a ContextProvider");
|
|
18
|
-
}
|
|
19
|
-
return context;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default useRouteStop;
|