@geops/rvf-mobility-web-component 0.1.56 → 0.1.58
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 +31 -0
- package/docutils.js +1 -1
- package/global.d.ts +1 -0
- package/iframe.html +15 -0
- package/index.html +2 -1
- package/index.js +278 -330
- package/package.json +16 -17
- package/src/{RvfExportMenu/RvfExportMenu.tsx → ExportMenu/ExportMenu.tsx} +11 -11
- package/src/ExportMenu/index.tsx +1 -0
- package/src/{RvfExportMenuButton/RvfExportMenuButton.tsx → ExportMenuButton/ExportMenuButton.tsx} +5 -5
- package/src/ExportMenuButton/index.tsx +1 -0
- package/src/FeatureDetails/FeatureDetails.tsx +57 -0
- package/src/FeatureDetails/index.ts +1 -0
- package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +73 -0
- package/src/FeaturesInfosListener/index.tsx +1 -0
- package/src/GeolocationButton/GeolocationButton.tsx +0 -1
- package/src/LayerTree/LayerTree.tsx +58 -0
- package/src/LayerTree/TreeItem/TreeItem.tsx +151 -0
- package/src/LayerTree/TreeItem/index.tsx +1 -0
- package/src/LayerTree/index.tsx +1 -0
- package/src/LayerTree/layersTreeContext.ts +4 -0
- package/src/LayerTree/layersTreeReducer.ts +158 -0
- package/src/{RvfLayerTreeButton/RvfLayerTreeButton.tsx → LayerTreeButton/LayerTreeButton.tsx} +5 -5
- package/src/LayerTreeButton/index.tsx +1 -0
- package/src/{RvfTopics/RvfTopics.tsx → LayerTreeMenu/LayerTreeMenu.tsx} +17 -13
- package/src/LayerTreeMenu/index.tsx +1 -0
- package/src/LayoutState/LayoutState.tsx +277 -0
- package/src/LayoutState/index.tsx +1 -0
- package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +292 -0
- package/src/LinesNetworkPlanDetails/index.tsx +1 -0
- package/src/{RvfLineNetworkPlanLayer/RvfLineNetworkPlanLayer.tsx → LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx} +7 -9
- package/src/LinesNetworkPlanLayer/index.tsx +1 -0
- package/src/MobilityMap/MobilityMap.tsx +274 -60
- package/src/MobilityMap/MobilityMapAttributes.ts +27 -43
- package/src/NotificationDetails/NotificationDetails.tsx +468 -0
- package/src/NotificationDetails/index.ts +1 -0
- package/src/{NotificationLayer/NotificationLayer.tsx → NotificationsLayer/NotificationsLayer.tsx} +9 -4
- package/src/NotificationsLayer/index.tsx +1 -0
- package/src/Overlay/Overlay.tsx +1 -6
- package/src/OverlayContent/OverlayContent.tsx +87 -0
- package/src/OverlayContent/index.ts +1 -0
- package/src/OverlayDetails/OverlayDetails.tsx +47 -0
- package/src/OverlayDetails/index.ts +1 -0
- package/src/OverlayDetailsFooter/OverlayDetailsFooter.tsx +51 -0
- package/src/OverlayDetailsFooter/index.tsx +1 -0
- package/src/OverlayDetailsHeader/OverlayDetailsHeader.tsx +35 -0
- package/src/OverlayDetailsHeader/index.ts +1 -0
- package/src/OverlayFooter/OverlayFooter.tsx +41 -0
- package/src/OverlayFooter/index.tsx +1 -0
- package/src/OverlayHeader/OverlayHeader.tsx +44 -0
- package/src/OverlayHeader/index.tsx +1 -0
- package/src/PermalinkInput/PermalinkInput.tsx +28 -0
- package/src/PermalinkInput/index.tsx +1 -0
- package/src/RouteSchedule/RouteSchedule.tsx +22 -18
- package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +22 -50
- package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +108 -104
- package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +189 -154
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +12 -14
- package/src/RvfFeatureDetailsTitle/RvfFeatureDetailsTitle.tsx +5 -5
- package/src/RvfMainLinkButton/RvfMainLinkButton.tsx +62 -0
- package/src/RvfMainLinkButton/index.tsx +1 -0
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +182 -394
- package/src/RvfOverlayContent/RvfOverlayContent.tsx +2 -2
- package/src/RvfPoisLayer/RvfPoisLayer.tsx +2 -2
- package/src/RvfSearch/RvfSearch.tsx +1 -1
- package/src/RvfSellingPointsLayer/RvfSellingPointsLayer.tsx +2 -2
- package/src/RvfSharedMobilityLayerGroup/RvfSharedMobilityLayerGroup.tsx +23 -23
- package/src/RvfTarifZonenLayer/RvfTarifZonenLayer.tsx +2 -2
- package/src/Search/Search.tsx +11 -2
- package/src/{RvfSearchButton/RvfSearchButton.tsx → SearchButton/SearchButton.tsx} +5 -5
- package/src/SearchButton/index.tsx +1 -0
- package/src/ShadowOverflow/ShadowOverflow.tsx +20 -0
- package/src/ShadowOverflow/index.tsx +1 -0
- package/src/{RvfShare/RvfPermalinkButton/RvfPermalinkButton.tsx → ShareMenu/PermalinkButton/PermalinkButton.tsx} +4 -4
- package/src/ShareMenu/PermalinkButton/index.tsx +1 -0
- package/src/{RvfShare/RvfShare.tsx → ShareMenu/ShareMenu.tsx} +9 -11
- package/src/ShareMenu/index.tsx +1 -0
- package/src/{RvfShareMenuButton/RvfShareMenuButton.tsx → ShareMenuButton/ShareMenuButton.tsx} +6 -6
- package/src/ShareMenuButton/index.tsx +1 -0
- package/src/SingleClickListener/SingleClickListener.tsx +55 -113
- package/src/SingleClickListener/index.tsx +1 -1
- package/src/Station/Station.tsx +10 -3
- package/src/StationsLayer/StationsLayer.tsx +0 -1
- package/src/StopsSearch/StopsSearch.tsx +3 -4
- package/src/StopsSearch/index.tsx +2 -1
- package/src/WindowMessageListener/WindowMessageListener.tsx +7 -1
- package/src/{RvfZoomButtons/RvfZoomButtons.tsx → ZoomButtons/ZoomButtons.tsx} +9 -12
- package/src/ZoomButtons/index.tsx +1 -0
- package/src/icons/Geolocation/airport-14-svgrepo-com.svg +41 -0
- package/src/ui/Button/Button.tsx +9 -2
- package/src/ui/Checkbox/Checkbox.tsx +32 -0
- package/src/ui/Checkbox/index.tsx +1 -0
- package/src/ui/IconButton/IconButton.tsx +24 -4
- package/src/ui/Input/Input.tsx +17 -0
- package/src/ui/Input/index.tsx +1 -0
- package/src/ui/InputCopy/InputCopy.tsx +86 -0
- package/src/ui/InputCopy/index.tsx +1 -0
- package/src/ui/Select/Select.tsx +24 -0
- package/src/ui/Select/index.tsx +1 -0
- package/src/utils/constants.ts +43 -42
- package/src/utils/hooks/useInitialLayersVisiblity.tsx +1 -1
- package/src/utils/hooks/useLayerConfig.tsx +2 -2
- package/src/utils/hooks/useLayersConfig.tsx +3 -3
- package/src/utils/hooks/useMapContext.tsx +67 -8
- package/src/utils/hooks/useRvfContext.tsx +0 -44
- package/src/NotificationLayer/index.tsx +0 -1
- package/src/RvfEmbedNavigation/DragPanWarning.ts +0 -124
- package/src/RvfEmbedNavigation/RvfEmbedNavigation.tsx +0 -51
- package/src/RvfEmbedNavigation/index.js +0 -1
- package/src/RvfExportMenu/index.tsx +0 -1
- package/src/RvfExportMenuButton/index.tsx +0 -1
- package/src/RvfFloatingMenu/RvfFloatingMenu.tsx +0 -44
- package/src/RvfFloatingMenu/index.tsx +0 -1
- package/src/RvfLayerTreeButton/index.tsx +0 -1
- package/src/RvfLineNetworkPlanLayer/index.tsx +0 -1
- package/src/RvfPermalink/RvfPermalink.tsx +0 -18
- package/src/RvfPermalink/index.tsx +0 -1
- package/src/RvfSearchButton/index.tsx +0 -1
- package/src/RvfShare/RvfPermalinkButton/index.tsx +0 -1
- package/src/RvfShare/index.tsx +0 -1
- package/src/RvfShareMenuButton/index.tsx +0 -1
- package/src/RvfTopics/index.tsx +0 -1
- package/src/RvfZoomButtons/index.tsx +0 -1
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type AffectedTimeIntervalType,
|
|
3
|
+
type PublicationType,
|
|
4
|
+
type SituationType,
|
|
5
|
+
type TextualContentType,
|
|
6
|
+
} from "mobility-toolbox-js/types";
|
|
7
|
+
import { useEffect, useState } from "preact/hooks";
|
|
8
|
+
import { twMerge } from "tailwind-merge";
|
|
9
|
+
|
|
1
10
|
import Warning from "../../icons/Warning";
|
|
11
|
+
import ShadowOverflow from "../../ShadowOverflow";
|
|
2
12
|
import getBgColor from "../../utils/getBgColor";
|
|
3
13
|
import useI18n from "../../utils/hooks/useI18n";
|
|
14
|
+
import useMapContext from "../../utils/hooks/useMapContext";
|
|
4
15
|
|
|
5
|
-
import type {
|
|
6
|
-
AffectedTimeIntervalType,
|
|
7
|
-
PublicationType,
|
|
8
|
-
SituationType,
|
|
9
|
-
TextualContentType,
|
|
10
|
-
} from "mobility-toolbox-js/types";
|
|
16
|
+
import type { RealtimeLine, RealtimeMot } from "mobility-toolbox-js/types";
|
|
11
17
|
import type { Feature } from "ol";
|
|
12
18
|
|
|
13
19
|
const toShortDate = (date: Date, showTime, showYear?: boolean) => {
|
|
@@ -28,34 +34,36 @@ const toShortDate = (date: Date, showTime, showYear?: boolean) => {
|
|
|
28
34
|
.replace(/\.$/, "");
|
|
29
35
|
};
|
|
30
36
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return res.json();
|
|
35
|
-
})
|
|
36
|
-
.then((data) => {
|
|
37
|
-
rvfLines = data;
|
|
38
|
-
})
|
|
39
|
-
.catch((err) => {
|
|
40
|
-
// eslint-disable-next-line no-console
|
|
41
|
-
console.error("Failed to fetch RVF lines", err);
|
|
42
|
-
});
|
|
43
|
-
const getLine = (name) => {
|
|
44
|
-
if (rvfLines) {
|
|
45
|
-
const line = rvfLines.find((linee) => {
|
|
37
|
+
const getLine = (name: string, lines: NotificationLine[]): NotificationLine => {
|
|
38
|
+
if (lines?.length) {
|
|
39
|
+
const line = lines.find((linee) => {
|
|
46
40
|
return linee.name === name;
|
|
47
41
|
});
|
|
48
42
|
if (line) {
|
|
49
43
|
return line;
|
|
50
44
|
}
|
|
51
45
|
}
|
|
52
|
-
return { mot: "bus", name };
|
|
46
|
+
return { mot: "bus", name } as NotificationLine;
|
|
53
47
|
};
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
49
|
+
export type NotificationLine = {
|
|
50
|
+
mot?: RealtimeMot;
|
|
51
|
+
operator_name?: string;
|
|
52
|
+
short_name?: string;
|
|
53
|
+
tags?: string[];
|
|
54
|
+
} & RealtimeLine;
|
|
55
|
+
|
|
56
|
+
function NotificationDetails({
|
|
57
|
+
className,
|
|
58
|
+
feature,
|
|
59
|
+
...props
|
|
60
|
+
}: {
|
|
61
|
+
className?: string;
|
|
62
|
+
feature: Feature;
|
|
63
|
+
}) {
|
|
58
64
|
const { t } = useI18n();
|
|
65
|
+
const { notificationtenant } = useMapContext();
|
|
66
|
+
const [lines, setLines] = useState<NotificationLine[]>([]);
|
|
59
67
|
const {
|
|
60
68
|
affected_products: affectedProducts,
|
|
61
69
|
affected_time_intervals: timeIntervals,
|
|
@@ -73,6 +81,29 @@ function RvfNotificationDetails({ feature }: { feature: Feature }) {
|
|
|
73
81
|
summary_de: summary,
|
|
74
82
|
} = feature.getProperties();
|
|
75
83
|
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
const abortController = new AbortController();
|
|
86
|
+
if (!notificationtenant) {
|
|
87
|
+
setLines([]);
|
|
88
|
+
}
|
|
89
|
+
fetch(
|
|
90
|
+
`https://tralis-tracker-api.geops.io/api/lines/${notificationtenant}/`,
|
|
91
|
+
)
|
|
92
|
+
.then((res) => {
|
|
93
|
+
return res.json();
|
|
94
|
+
})
|
|
95
|
+
.then((data) => {
|
|
96
|
+
setLines(data);
|
|
97
|
+
})
|
|
98
|
+
.catch((err) => {
|
|
99
|
+
// eslint-disable-next-line no-console
|
|
100
|
+
console.error("Failed to fetch lines", err);
|
|
101
|
+
});
|
|
102
|
+
return () => {
|
|
103
|
+
abortController?.abort();
|
|
104
|
+
};
|
|
105
|
+
}, [notificationtenant]);
|
|
106
|
+
|
|
76
107
|
// "title_de": "",
|
|
77
108
|
// "title_fr": "",
|
|
78
109
|
// "title_it": "",
|
|
@@ -146,12 +177,12 @@ function RvfNotificationDetails({ feature }: { feature: Feature }) {
|
|
|
146
177
|
{!!products?.length && (
|
|
147
178
|
<div className="flex flex-wrap gap-2">
|
|
148
179
|
{products?.map(({ name }) => {
|
|
149
|
-
const line = getLine(name);
|
|
180
|
+
const line = getLine(name, lines);
|
|
150
181
|
return (
|
|
151
182
|
<>
|
|
152
183
|
<div
|
|
153
184
|
className={
|
|
154
|
-
"
|
|
185
|
+
"w-fit rounded-md bg-black px-[12px] py-[9px] leading-none font-bold text-white"
|
|
155
186
|
}
|
|
156
187
|
key={name}
|
|
157
188
|
style={{
|
|
@@ -289,145 +320,149 @@ function RvfNotificationDetails({ feature }: { feature: Feature }) {
|
|
|
289
320
|
}
|
|
290
321
|
|
|
291
322
|
return (
|
|
292
|
-
<
|
|
293
|
-
|
|
294
|
-
(
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
323
|
+
<ShadowOverflow {...props} className={twMerge("px-4 text-base", className)}>
|
|
324
|
+
<div>
|
|
325
|
+
{publicationsToDisplay?.map(
|
|
326
|
+
({
|
|
327
|
+
id,
|
|
328
|
+
publicationLines,
|
|
329
|
+
publicationStops,
|
|
330
|
+
textualContentLarge,
|
|
331
|
+
textualContentMedium,
|
|
332
|
+
textualContentSmall,
|
|
333
|
+
}) => {
|
|
334
|
+
// Get the textual content in German
|
|
335
|
+
textualContent = (
|
|
336
|
+
textualContentLarge ||
|
|
337
|
+
textualContentMedium ||
|
|
338
|
+
textualContentSmall
|
|
339
|
+
)?.de;
|
|
308
340
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
341
|
+
const pubLines =
|
|
342
|
+
publicationLines?.flatMap((publication) => {
|
|
343
|
+
return (
|
|
344
|
+
publication.lines?.map(({ name }) => {
|
|
345
|
+
return name;
|
|
346
|
+
}) || []
|
|
347
|
+
);
|
|
348
|
+
}) || [];
|
|
317
349
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
350
|
+
const stations = publicationStops.map((publication) => {
|
|
351
|
+
return publication?.name || "";
|
|
352
|
+
});
|
|
321
353
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
354
|
+
return (
|
|
355
|
+
<div className={"text-base"} key={id}>
|
|
356
|
+
<div className="text-xs uppercase">{reasonsToDisplay}</div>
|
|
357
|
+
<h3 className="space-x-2 text-lg font-bold text-balance">
|
|
358
|
+
<span
|
|
359
|
+
className={"line-height-[1.3] inline-block align-middle"}
|
|
360
|
+
>
|
|
361
|
+
<Warning />
|
|
362
|
+
</span>
|
|
363
|
+
<span
|
|
364
|
+
dangerouslySetInnerHTML={{
|
|
365
|
+
__html: textualContent?.summary,
|
|
366
|
+
}}
|
|
367
|
+
></span>
|
|
368
|
+
</h3>
|
|
369
|
+
<hr className="my-1" />
|
|
336
370
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
371
|
+
{timeIntervalsToDisplay?.map(
|
|
372
|
+
({
|
|
373
|
+
dailyEndTime,
|
|
374
|
+
dailyStartTime,
|
|
375
|
+
endTime,
|
|
376
|
+
startTime,
|
|
377
|
+
}: AffectedTimeIntervalType) => {
|
|
378
|
+
const hasDailyTime = dailyEndTime && dailyStartTime;
|
|
379
|
+
const isStartCurrentYear =
|
|
380
|
+
new Date().getFullYear() ===
|
|
381
|
+
new Date(startTime).getFullYear();
|
|
382
|
+
const isEndCurrentYear =
|
|
383
|
+
new Date().getFullYear() ===
|
|
384
|
+
new Date(endTime).getFullYear();
|
|
385
|
+
const isEndInfinite = endTime.includes("2500");
|
|
352
386
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
387
|
+
return (
|
|
388
|
+
<div
|
|
389
|
+
className="text-sm font-bold text-balance"
|
|
390
|
+
key={startTime}
|
|
391
|
+
>
|
|
392
|
+
<span>
|
|
393
|
+
{`von ${toShortDate(new Date(startTime), !hasDailyTime, !isStartCurrentYear)}`}
|
|
394
|
+
{!isEndInfinite &&
|
|
395
|
+
` bis ${toShortDate(new Date(endTime), !hasDailyTime, !isEndCurrentYear)}`}
|
|
396
|
+
</span>
|
|
397
|
+
{hasDailyTime && (
|
|
398
|
+
<span>{` (täglich von ${dailyStartTime} bis ${dailyEndTime})`}</span>
|
|
399
|
+
)}
|
|
400
|
+
</div>
|
|
401
|
+
);
|
|
402
|
+
},
|
|
403
|
+
)}
|
|
404
|
+
<div
|
|
405
|
+
className="mt-4"
|
|
406
|
+
dangerouslySetInnerHTML={{
|
|
407
|
+
__html:
|
|
408
|
+
textualContent?.description || "Keine Details verfügbar",
|
|
409
|
+
}}
|
|
410
|
+
/>
|
|
411
|
+
{!!pubLines?.length && (
|
|
412
|
+
<div>
|
|
413
|
+
<br />
|
|
414
|
+
<div className={"font-bold"}>Betroffene Lines:</div>
|
|
415
|
+
<div className={"flex flex-wrap gap-1 text-sm"}>
|
|
416
|
+
{pubLines?.map((name) => {
|
|
417
|
+
return (
|
|
418
|
+
<div
|
|
419
|
+
className={
|
|
420
|
+
"bg-red rounded-md px-2 py-1 font-bold text-white"
|
|
421
|
+
}
|
|
422
|
+
key={name}
|
|
423
|
+
>
|
|
424
|
+
{name}
|
|
425
|
+
</div>
|
|
426
|
+
);
|
|
427
|
+
})}
|
|
366
428
|
</div>
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
)}
|
|
370
|
-
<div
|
|
371
|
-
className="mt-4"
|
|
372
|
-
dangerouslySetInnerHTML={{
|
|
373
|
-
__html:
|
|
374
|
-
textualContent?.description || "Keine Details verfügbar",
|
|
375
|
-
}}
|
|
376
|
-
/>
|
|
377
|
-
{!!lines?.length && (
|
|
429
|
+
</div>
|
|
430
|
+
)}
|
|
378
431
|
<div>
|
|
379
432
|
<br />
|
|
380
|
-
<div className={"font-bold"}>Betroffene
|
|
433
|
+
<div className={"font-bold"}>Betroffene Haltestellen:</div>
|
|
381
434
|
<div className={"flex flex-wrap gap-1 text-sm"}>
|
|
382
|
-
{
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
435
|
+
{stations?.length ? (
|
|
436
|
+
stations.map((name) => {
|
|
437
|
+
return (
|
|
438
|
+
<div
|
|
439
|
+
className={
|
|
440
|
+
"bg-red rounded-md px-2 py-1 font-bold text-white"
|
|
441
|
+
}
|
|
442
|
+
key={name}
|
|
443
|
+
>
|
|
444
|
+
{name}
|
|
445
|
+
</div>
|
|
446
|
+
);
|
|
447
|
+
})
|
|
448
|
+
) : (
|
|
449
|
+
<div
|
|
450
|
+
className={
|
|
451
|
+
"bg-red rounded-md px-2 py-1 font-bold text-white"
|
|
452
|
+
}
|
|
453
|
+
>
|
|
454
|
+
Alle Bahnhöfe auf dieser Strecke
|
|
455
|
+
</div>
|
|
456
|
+
)}
|
|
394
457
|
</div>
|
|
395
458
|
</div>
|
|
396
|
-
)}
|
|
397
|
-
<div>
|
|
398
|
-
<br />
|
|
399
|
-
<div className={"font-bold"}>Betroffene Haltestellen:</div>
|
|
400
|
-
<div className={"flex flex-wrap gap-1 text-sm"}>
|
|
401
|
-
{stations?.length ? (
|
|
402
|
-
stations.map((name) => {
|
|
403
|
-
return (
|
|
404
|
-
<div
|
|
405
|
-
className={
|
|
406
|
-
"bg-red rounded-md px-2 py-1 font-bold text-white"
|
|
407
|
-
}
|
|
408
|
-
key={name}
|
|
409
|
-
>
|
|
410
|
-
{name}
|
|
411
|
-
</div>
|
|
412
|
-
);
|
|
413
|
-
})
|
|
414
|
-
) : (
|
|
415
|
-
<div
|
|
416
|
-
className={
|
|
417
|
-
"bg-red rounded-md px-2 py-1 font-bold text-white"
|
|
418
|
-
}
|
|
419
|
-
>
|
|
420
|
-
Alle Bahnhöfe auf dieser Strecke
|
|
421
|
-
</div>
|
|
422
|
-
)}
|
|
423
|
-
</div>
|
|
424
459
|
</div>
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
</
|
|
460
|
+
);
|
|
461
|
+
},
|
|
462
|
+
)}
|
|
463
|
+
</div>
|
|
464
|
+
</ShadowOverflow>
|
|
430
465
|
);
|
|
431
466
|
}
|
|
432
467
|
|
|
433
|
-
export default
|
|
468
|
+
export default NotificationDetails;
|
|
@@ -9,36 +9,34 @@ import StationDetails from "./StationDetails";
|
|
|
9
9
|
import type { Feature } from "ol";
|
|
10
10
|
|
|
11
11
|
export interface RvfSharedMobilityDetailsProps {
|
|
12
|
-
|
|
12
|
+
feature: Feature;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
function RvfSharedMobilityDetails({
|
|
16
|
-
selectedFeature,
|
|
17
|
-
}: RvfSharedMobilityDetailsProps) {
|
|
15
|
+
function RvfSharedMobilityDetails({ feature }: RvfSharedMobilityDetailsProps) {
|
|
18
16
|
const [features, setFeatures] = useState([]);
|
|
19
|
-
const isStationDetails = !!
|
|
20
|
-
const isFloatingVehicle = !!
|
|
21
|
-
const isCluster = !!
|
|
17
|
+
const isStationDetails = !!feature.get("station_id");
|
|
18
|
+
const isFloatingVehicle = !!feature.get("vehicle_id");
|
|
19
|
+
const isCluster = !!feature.get("cluster_id");
|
|
22
20
|
|
|
23
21
|
useEffect(() => {
|
|
24
22
|
if (isCluster) {
|
|
25
|
-
setFeatures(
|
|
23
|
+
setFeatures(feature.get("features"));
|
|
26
24
|
} else {
|
|
27
|
-
setFeatures([
|
|
25
|
+
setFeatures([feature]);
|
|
28
26
|
}
|
|
29
|
-
}, [
|
|
27
|
+
}, [feature, isFloatingVehicle, isCluster]);
|
|
30
28
|
|
|
31
29
|
const featuresByFeedId: Record<string, Feature[]> = useMemo(() => {
|
|
32
30
|
const featuresByFeedIdd = {};
|
|
33
31
|
if (isStationDetails) {
|
|
34
32
|
return null;
|
|
35
33
|
}
|
|
36
|
-
features.forEach((
|
|
37
|
-
const feedId =
|
|
34
|
+
features.forEach((featuree) => {
|
|
35
|
+
const feedId = featuree.get("feed_id");
|
|
38
36
|
if (featuresByFeedIdd[feedId]) {
|
|
39
|
-
featuresByFeedIdd[feedId].push(
|
|
37
|
+
featuresByFeedIdd[feedId].push(featuree);
|
|
40
38
|
} else {
|
|
41
|
-
featuresByFeedIdd[feedId] = [
|
|
39
|
+
featuresByFeedIdd[feedId] = [featuree];
|
|
42
40
|
}
|
|
43
41
|
});
|
|
44
42
|
return featuresByFeedIdd;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { icons } from "../utils/addSourceAndLayers";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
LAYERS_NAMES,
|
|
4
|
+
LAYERS_TITLES,
|
|
5
5
|
TITLE_BY_CATEGORY,
|
|
6
6
|
TITLE_BY_FEED_ID,
|
|
7
7
|
} from "../utils/constants";
|
|
@@ -22,8 +22,8 @@ function RvfFeatureDetailsTitle({ feature }: { feature: Feature }) {
|
|
|
22
22
|
line_id: lineId,
|
|
23
23
|
tickets,
|
|
24
24
|
} = selectedFeature.getProperties();
|
|
25
|
-
const layerConfigLinienNetz = useLayerConfig(
|
|
26
|
-
const layerConfigMeldungen = useLayerConfig(
|
|
25
|
+
const layerConfigLinienNetz = useLayerConfig(LAYERS_NAMES.linesnetworkplan);
|
|
26
|
+
const layerConfigMeldungen = useLayerConfig(LAYERS_NAMES.notifications);
|
|
27
27
|
|
|
28
28
|
// moco export v1
|
|
29
29
|
if (disruptionType) {
|
|
@@ -73,7 +73,7 @@ function RvfFeatureDetailsTitle({ feature }: { feature: Feature }) {
|
|
|
73
73
|
return layerConfigLinienNetz.title;
|
|
74
74
|
}
|
|
75
75
|
if (tickets) {
|
|
76
|
-
return
|
|
76
|
+
return LAYERS_TITLES.verkaufsstellen;
|
|
77
77
|
}
|
|
78
78
|
return defaultTitle;
|
|
79
79
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { unByKey } from "ol/Observable";
|
|
2
|
+
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
3
|
+
import { LiaMapSolid } from "react-icons/lia";
|
|
4
|
+
import { twMerge } from "tailwind-merge";
|
|
5
|
+
|
|
6
|
+
import IconButton from "../ui/IconButton";
|
|
7
|
+
import useMapContext from "../utils/hooks/useMapContext";
|
|
8
|
+
|
|
9
|
+
import type { PreactDOMAttributes } from "preact";
|
|
10
|
+
|
|
11
|
+
function RvfMainLinkButton({
|
|
12
|
+
className,
|
|
13
|
+
...props
|
|
14
|
+
}: { className?: string } & PreactDOMAttributes) {
|
|
15
|
+
const { mainlink, mainlinktitle, map } = useMapContext();
|
|
16
|
+
const [x, setX] = useState(0);
|
|
17
|
+
const [y, setY] = useState(0);
|
|
18
|
+
const [z, setZ] = useState(0);
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const update = (evt) => {
|
|
22
|
+
const center = evt.map?.getView()?.getCenter();
|
|
23
|
+
if (center) {
|
|
24
|
+
setX(center[0]);
|
|
25
|
+
setY(center[1]);
|
|
26
|
+
}
|
|
27
|
+
const zoom = evt.map?.getView()?.getZoom();
|
|
28
|
+
if (zoom) {
|
|
29
|
+
setZ(zoom);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
update({ map });
|
|
33
|
+
const key = map?.on("moveend", update);
|
|
34
|
+
return () => {
|
|
35
|
+
unByKey(key);
|
|
36
|
+
};
|
|
37
|
+
}, [map]);
|
|
38
|
+
|
|
39
|
+
const href = useMemo(() => {
|
|
40
|
+
return mainlink
|
|
41
|
+
? mainlink
|
|
42
|
+
.replace("{{x}}", x.toFixed(4))
|
|
43
|
+
.replace("{{y}}", y.toFixed(4))
|
|
44
|
+
.replace("{{z}}", z.toFixed(2))
|
|
45
|
+
: "#";
|
|
46
|
+
}, [mainlink, x, y, z]);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<IconButton
|
|
50
|
+
className={twMerge("rounded-xl border-3 border-white", className)}
|
|
51
|
+
href={href}
|
|
52
|
+
target="_blank"
|
|
53
|
+
theme="primary"
|
|
54
|
+
title={mainlinktitle}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
<LiaMapSolid />
|
|
58
|
+
</IconButton>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export default RvfMainLinkButton;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from "./RvfMainLinkButton";
|