@geops/rvf-mobility-web-component 0.1.61 → 0.1.62
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 +45 -0
- package/README.md +1 -0
- package/docutils.js +103 -4
- package/fonts/source-sans-3/source-sans-3-v15-latin-500.ttf +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-500.woff2 +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-600.ttf +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-600.woff2 +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-700.ttf +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-700.woff2 +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-regular.ttf +0 -0
- package/fonts/source-sans-3/source-sans-3-v15-latin-regular.woff2 +0 -0
- package/index.html +27 -97
- package/index.js +235 -224
- package/notifications.html +144 -0
- package/package.json +2 -2
- package/search.html +24 -65
- package/src/FeatureDetails/FeatureDetails.tsx +20 -6
- package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +2 -0
- package/src/LayerTree/TreeItem/TreeItem.tsx +2 -2
- package/src/LayerTreeMenu/LayerTreeMenu.tsx +19 -3
- package/src/LayoutState/LayoutState.tsx +17 -0
- package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +34 -21
- package/src/LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx +3 -6
- package/src/LinesNetworkPlanLayerHighlight/LinesNetworkPlanLayerHighlight.tsx +88 -0
- package/src/LinesNetworkPlanLayerHighlight/index.tsx +1 -0
- package/src/MapDispatchEvents/MapDispatchEvents.tsx +6 -4
- package/src/MapLayout/MapLayout.tsx +2 -2
- package/src/MapsetLayer/MapsetLayer.tsx +116 -0
- package/src/MapsetLayer/index.tsx +1 -0
- package/src/MobilityMap/MobilityMap.tsx +27 -5
- package/src/MobilityMap/MobilityMapAttributes.test.ts +38 -0
- package/src/MobilityMap/MobilityMapAttributes.ts +99 -22
- package/src/MobilityMap/MobilityMapEvents.ts +53 -0
- package/src/MobilityNotifications/MobilityNotifications.tsx +93 -0
- package/src/MobilityNotifications/MobilityNotificationsAttributes.test.ts +21 -0
- package/src/MobilityNotifications/MobilityNotificationsAttributes.ts +46 -0
- package/src/MobilityNotifications/index.ts +2 -0
- package/src/MobilitySearch/MobilitySearchEvents.ts +21 -0
- package/src/NotificationDetails/NotificationDetails.tsx +74 -251
- package/src/OverlayContent/OverlayContent.tsx +1 -1
- package/src/OverlayDetails/OverlayDetails.tsx +4 -2
- package/src/OverlayFooter/OverlayFooter.tsx +3 -2
- package/src/RealtimeLayer/RealtimeLayer.tsx +36 -7
- package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +1 -2
- package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +2 -2
- package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +2 -0
- package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +12 -453
- package/src/RvfFeatureDetails/RvfSellingPointDetails/RvfSellingPointDetails.tsx +20 -17
- package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +93 -36
- package/src/RvfLink/RvfLink.tsx +5 -2
- package/src/RvfMobilityMap/RvfMobilityMap.tsx +27 -9
- package/src/RvfSelectedFeatureHighlightLayer/RvfSelectedFeatureHighlightLayer.tsx +9 -5
- package/src/RvfSingleClickListener/RvfSingleClickListener.tsx +3 -1
- package/src/SituationDetails/SituationDetails.tsx +324 -0
- package/src/SituationDetails/index.ts +1 -0
- package/src/index.tsx +16 -0
- package/src/indexDoc.ts +25 -3
- package/src/ui/Checkbox/Checkbox.tsx +2 -2
- package/src/ui/Link/Link.tsx +49 -0
- package/src/ui/Link/index.tsx +1 -0
- package/src/ui/Select/Select.tsx +2 -2
- package/src/utils/constants.ts +37 -0
- package/src/utils/exportPdf.ts +3 -1
- package/src/utils/highlightLinesNetworkPlan.ts +25 -0
- package/src/utils/hooks/useI18n.tsx +6 -4
- package/src/utils/hooks/useMapContext.tsx +9 -0
- package/src/utils/sharingGraphqlUtils.ts +1 -1
- package/src/utils/translations.ts +12 -1
- package/tailwind.config.mjs +3 -1
- package/src/ShareMenu/PermalinkButton/PermalinkButton.tsx +0 -62
- package/src/ShareMenu/PermalinkButton/index.tsx +0 -1
- package/src/icons/Geolocation/airport-14-svgrepo-com.svg +0 -41
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Mobility Web Component</title>
|
|
6
|
+
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
|
7
|
+
<meta
|
|
8
|
+
name="viewport"
|
|
9
|
+
content="initial-scale=1,maximum-scale=1,user-scalable=no"
|
|
10
|
+
/>
|
|
11
|
+
<link rel="stylesheet" href="https://use.typekit.net/orf1mlq.css" />
|
|
12
|
+
|
|
13
|
+
<!-- font sgenutz in rvf.de/-->
|
|
14
|
+
<style>
|
|
15
|
+
@font-face {
|
|
16
|
+
font-display: swap;
|
|
17
|
+
font-family: "Source Sans 3";
|
|
18
|
+
font-style: normal;
|
|
19
|
+
font-weight: 400;
|
|
20
|
+
src:
|
|
21
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-regular.woff2")
|
|
22
|
+
format("woff2"),
|
|
23
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-regular.ttf")
|
|
24
|
+
format("truetype");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@font-face {
|
|
28
|
+
font-display: swap;
|
|
29
|
+
font-family: "Source Sans 3";
|
|
30
|
+
font-style: normal;
|
|
31
|
+
font-weight: 500;
|
|
32
|
+
src:
|
|
33
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-500.woff2")
|
|
34
|
+
format("woff2"),
|
|
35
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-500.ttf")
|
|
36
|
+
format("truetype");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@font-face {
|
|
40
|
+
font-display: swap;
|
|
41
|
+
font-family: "Source Sans 3";
|
|
42
|
+
font-style: normal;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
src:
|
|
45
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-600.woff2")
|
|
46
|
+
format("woff2"),
|
|
47
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-600.ttf")
|
|
48
|
+
format("truetype");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@font-face {
|
|
52
|
+
font-display: swap;
|
|
53
|
+
font-family: "Source Sans 3";
|
|
54
|
+
font-style: normal;
|
|
55
|
+
font-weight: 700;
|
|
56
|
+
src:
|
|
57
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-700.woff2")
|
|
58
|
+
format("woff2"),
|
|
59
|
+
url("fonts/source-sans-3/source-sans-3-v15-latin-700.ttf")
|
|
60
|
+
format("truetype");
|
|
61
|
+
}
|
|
62
|
+
</style>
|
|
63
|
+
|
|
64
|
+
<script type="text/javascript">
|
|
65
|
+
if (/localhost/.test(window.location.hostname)) {
|
|
66
|
+
new EventSource("/esbuild").addEventListener("change", () => {
|
|
67
|
+
location.reload();
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
<script type="module" src="./index.js"></script>
|
|
72
|
+
<script type="module" src="./indexDoc.js"></script>
|
|
73
|
+
<script src="./docutils.js"></script>
|
|
74
|
+
<link rel="stylesheet" type="text/css" href="./output.css" />
|
|
75
|
+
<style>
|
|
76
|
+
::-webkit-scrollbar {
|
|
77
|
+
width: 3px;
|
|
78
|
+
height: 3px;
|
|
79
|
+
}
|
|
80
|
+
a {
|
|
81
|
+
text-decoration: underline;
|
|
82
|
+
}
|
|
83
|
+
</style>
|
|
84
|
+
</head>
|
|
85
|
+
<body class="p-8">
|
|
86
|
+
<!-- tailwind hack to add class used in docutils -->
|
|
87
|
+
<div
|
|
88
|
+
class="flex w-full table-auto gap-4 border bg-black p-2 px-4 py-2 text-white hover:bg-gray-700"
|
|
89
|
+
style="display: none"
|
|
90
|
+
></div>
|
|
91
|
+
<div id="doc" style="display: none" class="mx-auto max-w-4xl space-y-4">
|
|
92
|
+
<h1 class="flex gap-4">
|
|
93
|
+
<img src="./Logo.svg" />Mobility Notifications Web Component
|
|
94
|
+
</h1>
|
|
95
|
+
<p>This is a demo of the Mobility Notifications Web Component.</p>
|
|
96
|
+
<h2>Usage example</h2>
|
|
97
|
+
<pre
|
|
98
|
+
id="code"
|
|
99
|
+
class="overflow-auto rounded bg-slate-800 p-4 text-slate-200"
|
|
100
|
+
></pre>
|
|
101
|
+
|
|
102
|
+
<geops-mobility-notifications
|
|
103
|
+
id="notifications"
|
|
104
|
+
class="block w-full"
|
|
105
|
+
></geops-mobility-notifications>
|
|
106
|
+
|
|
107
|
+
<br />
|
|
108
|
+
<div id="attributesDoc">
|
|
109
|
+
<h2 class="text-xl font-bold">Attributes</h2>
|
|
110
|
+
<div id="attributes"></div>
|
|
111
|
+
</div>
|
|
112
|
+
<div id="eventsDoc">
|
|
113
|
+
<h2 class="text-xl font-bold">Events</h2>
|
|
114
|
+
<pre class="rounded bg-slate-800 p-4 text-slate-200">
|
|
115
|
+
document.getElementById('notifications').addEventListener('mwc:attribute', (event) => {
|
|
116
|
+
console.log('Display last data received:', event.data);
|
|
117
|
+
});</pre
|
|
118
|
+
>
|
|
119
|
+
<div id="events"></div>
|
|
120
|
+
</div>
|
|
121
|
+
<br />
|
|
122
|
+
<br />
|
|
123
|
+
<h1 class="text-xl font-bold">More mobility web components</h1>
|
|
124
|
+
<p>
|
|
125
|
+
<a href="index.html" target="_blank"
|
|
126
|
+
>>> Usage example Map Component</a
|
|
127
|
+
>
|
|
128
|
+
</p>
|
|
129
|
+
</div>
|
|
130
|
+
<br />
|
|
131
|
+
<br />
|
|
132
|
+
<script type="text/javascript">
|
|
133
|
+
const pkgSrc = "https://www.unpkg.com/@geops/rvf-mobility-web-component";
|
|
134
|
+
const wc = document.querySelector("geops-mobility-notifications");
|
|
135
|
+
|
|
136
|
+
window.addEventListener("load", () => {
|
|
137
|
+
const attributes = window.MobilityNotificationsAttributes || {};
|
|
138
|
+
const events = window.MobilityNotificationsEvents || {};
|
|
139
|
+
|
|
140
|
+
onLoad(wc, attributes, events, pkgSrc);
|
|
141
|
+
});
|
|
142
|
+
</script>
|
|
143
|
+
</body>
|
|
144
|
+
</html>
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@geops/rvf-mobility-web-component",
|
|
3
3
|
"license": "UNLICENSED",
|
|
4
4
|
"description": "Web components for rvf in the domains of mobility and logistics.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.62",
|
|
6
6
|
"homepage": "https://rvf-mobility-web-component-geops.vercel.app/",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"jspdf": "^3.0.3",
|
|
13
13
|
"lodash.debounce": "^4.0.8",
|
|
14
14
|
"maplibre-gl": "^5.8.0",
|
|
15
|
-
"mobility-toolbox-js": "3.4.0",
|
|
15
|
+
"mobility-toolbox-js": "3.4.4-beta.0",
|
|
16
16
|
"ol": "^10.6.1",
|
|
17
17
|
"preact": "^10.27.2",
|
|
18
18
|
"preact-custom-element": "^4.5.1",
|
package/search.html
CHANGED
|
@@ -58,16 +58,26 @@
|
|
|
58
58
|
<pre id="code" class="bg-slate-800 text-slate-200 p-4 rounded"></pre>
|
|
59
59
|
|
|
60
60
|
<geops-mobility-search
|
|
61
|
+
id="search"
|
|
61
62
|
class="max-w-3xl block border"
|
|
62
63
|
limit="5"
|
|
63
64
|
mots="rail,bus"
|
|
64
65
|
></geops-mobility-search>
|
|
65
66
|
|
|
66
67
|
<br />
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
<div id="attributesDoc">
|
|
69
|
+
<h2 class="text-xl font-bold">Attributes</h2>
|
|
70
|
+
<div id="attributes"></div>
|
|
71
|
+
</div>
|
|
72
|
+
<div id="eventsDoc">
|
|
73
|
+
<h2 class="text-xl font-bold">Events</h2>
|
|
74
|
+
<pre class="rounded bg-slate-800 p-4 text-slate-200">
|
|
75
|
+
document.getElementById('search').addEventListener('mwc:attribute', (event) => {
|
|
76
|
+
console.log('Display last data received:', event.data);
|
|
77
|
+
});</pre
|
|
78
|
+
>
|
|
79
|
+
<div id="events"></div>
|
|
80
|
+
</div>
|
|
71
81
|
<br />
|
|
72
82
|
<br />
|
|
73
83
|
<h1 class="text-xl font-bold">More mobility web components</h1>
|
|
@@ -85,6 +95,15 @@
|
|
|
85
95
|
|
|
86
96
|
window.addEventListener("load", () => {
|
|
87
97
|
|
|
98
|
+
const attributes = window.MobilitySearchAttributes;
|
|
99
|
+
const events = window.MobilitySearchEvents;
|
|
100
|
+
const descriptionByEvent = {
|
|
101
|
+
"mwc:stopssearchselect":
|
|
102
|
+
"Only when search attribute is 'true'. Event fired when a stop is selected in the stops search results. The event data contains the selected stop.",
|
|
103
|
+
"mwc:attribute":
|
|
104
|
+
"Event fired when an web component's attribute is changed. The event data contains the list of all attributes and their values.",
|
|
105
|
+
};
|
|
106
|
+
|
|
88
107
|
// Add special parameters
|
|
89
108
|
window.MobilityMapAttributes.fullscreen = {
|
|
90
109
|
type: "boolean",
|
|
@@ -93,67 +112,7 @@
|
|
|
93
112
|
reload: true,
|
|
94
113
|
};
|
|
95
114
|
|
|
96
|
-
|
|
97
|
-
const attrs = Object.keys(MobilitySearchAttributes);
|
|
98
|
-
const booleanAttrs = Object.entries(MobilitySearchAttributes)
|
|
99
|
-
.filter(([, attr]) => attr.type === "boolean")
|
|
100
|
-
.map(([key]) => key);
|
|
101
|
-
const booleanTrueByDefault = booleanAttrs.filter(
|
|
102
|
-
(key) => MobilitySearchAttributes[key].defaultValue === "true",
|
|
103
|
-
);
|
|
104
|
-
const reloadAttrs = Object.entries(MobilitySearchAttributes)
|
|
105
|
-
.filter(([key, attr]) => !!attr.reload)
|
|
106
|
-
.map(([key]) => key);
|
|
107
|
-
|
|
108
|
-
const descriptionByAttr = Object.entries(MobilitySearchAttributes).reduce((acc, [key, attr]) => {
|
|
109
|
-
acc[key] = attr.description;
|
|
110
|
-
return acc;
|
|
111
|
-
}, {});
|
|
112
|
-
|
|
113
|
-
/* Events */
|
|
114
|
-
const events = [
|
|
115
|
-
"mwc:stopssearchselect",
|
|
116
|
-
"mwc:attribute",
|
|
117
|
-
];
|
|
118
|
-
const descriptionByEvent = {
|
|
119
|
-
"mwc:stopssearchselect":
|
|
120
|
-
"Only when search attribute is 'true'. Event fired when a stop is selected in the stops search results. The event data contains the selected stop.",
|
|
121
|
-
"mwc:attribute":
|
|
122
|
-
"Event fired when an web component's attribute is changed. The event data contains the list of all attributes and their values.",
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
document.querySelector("#attributes").innerHTML =
|
|
126
|
-
generateAttributesTable(
|
|
127
|
-
wc,
|
|
128
|
-
attrs,
|
|
129
|
-
booleanAttrs,
|
|
130
|
-
booleanTrueByDefault,
|
|
131
|
-
descriptionByAttr,
|
|
132
|
-
reloadAttrs,
|
|
133
|
-
);
|
|
134
|
-
document.querySelector("#events").innerHTML = generateEventsTable(
|
|
135
|
-
wc,
|
|
136
|
-
events,
|
|
137
|
-
descriptionByEvent,
|
|
138
|
-
);
|
|
139
|
-
document.querySelector("#code").innerHTML = generateCodeText(
|
|
140
|
-
wc,
|
|
141
|
-
attrs,
|
|
142
|
-
pkgSrc,
|
|
143
|
-
);
|
|
144
|
-
wc.addEventListener("mwc:attribute", (event) => {
|
|
145
|
-
document.querySelector("#code").innerHTML = generateCodeText(
|
|
146
|
-
wc,
|
|
147
|
-
attrs,
|
|
148
|
-
pkgSrc,
|
|
149
|
-
);
|
|
150
|
-
});
|
|
151
|
-
applyPermalinkParameters(wc);
|
|
152
|
-
events.forEach((eventName) => {
|
|
153
|
-
wc.addEventListener(eventName, (event) => {
|
|
154
|
-
console.log(`${eventName} event`, event);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
115
|
+
onLoad(wc, attributes, events, pkgSrc);
|
|
157
116
|
});
|
|
158
117
|
</script>
|
|
159
118
|
</body>
|
|
@@ -38,19 +38,33 @@ function FeatureDetails({ feature, featuresInfo, layer }: FeatureDetailsProps) {
|
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<>
|
|
41
|
-
{feature && layer === realtimeLayer && trainId && <RouteSchedule />}
|
|
42
|
-
{feature && layer === stationsLayer && tenant && stationId && <Station />}
|
|
43
41
|
{feature &&
|
|
44
|
-
|
|
42
|
+
!!realtimeLayer &&
|
|
43
|
+
!!layer &&
|
|
44
|
+
layer.get("name") === realtimeLayer.get("name") &&
|
|
45
|
+
trainId && <RouteSchedule />}
|
|
46
|
+
{feature &&
|
|
47
|
+
!!stationsLayer &&
|
|
48
|
+
!!layer &&
|
|
49
|
+
layer.get("name") === stationsLayer.get("name") &&
|
|
50
|
+
tenant &&
|
|
51
|
+
stationId && <Station />}
|
|
52
|
+
{feature &&
|
|
53
|
+
!!linesNetworkPlanLayer &&
|
|
54
|
+
!!layer &&
|
|
55
|
+
layer.get("name") === linesNetworkPlanLayer.get("name") &&
|
|
45
56
|
featuresInfo?.features?.length && (
|
|
46
57
|
<LinesNetworkPlanDetails
|
|
47
58
|
className={contentClassName}
|
|
48
59
|
features={featuresInfo?.features || []}
|
|
49
60
|
/>
|
|
50
61
|
)}
|
|
51
|
-
{feature &&
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
{feature &&
|
|
63
|
+
!!notificationsLayer &&
|
|
64
|
+
!!layer &&
|
|
65
|
+
layer.get("name") === notificationsLayer.get("name") && (
|
|
66
|
+
<NotificationDetails className={contentClassName} feature={feature} />
|
|
67
|
+
)}
|
|
54
68
|
</>
|
|
55
69
|
);
|
|
56
70
|
}
|
|
@@ -7,6 +7,7 @@ import useMapContext from "../utils/hooks/useMapContext";
|
|
|
7
7
|
*/
|
|
8
8
|
function FeaturesInfosListener() {
|
|
9
9
|
const {
|
|
10
|
+
baseLayer,
|
|
10
11
|
featuresInfos,
|
|
11
12
|
featuresInfosHovered,
|
|
12
13
|
realtimeLayer,
|
|
@@ -58,6 +59,7 @@ function FeaturesInfosListener() {
|
|
|
58
59
|
setSelectedFeature(realtimeFeature || stationFeature || features[0]);
|
|
59
60
|
}
|
|
60
61
|
}, [
|
|
62
|
+
baseLayer?.mapLibreMap,
|
|
61
63
|
featuresInfos,
|
|
62
64
|
realtimeLayer,
|
|
63
65
|
setSelectedFeature,
|
|
@@ -6,7 +6,7 @@ import ArrowUp from "../../icons/ArrowUp";
|
|
|
6
6
|
import minusGrey from "../../icons/Minus/minus.svg";
|
|
7
7
|
import Checkbox from "../../ui/Checkbox";
|
|
8
8
|
import useI18n from "../../utils/hooks/useI18n";
|
|
9
|
-
// import
|
|
9
|
+
// import RadioButton from "../../RadioButton";
|
|
10
10
|
import { LayersTreeDispatchContext } from "../layersTreeContext";
|
|
11
11
|
|
|
12
12
|
import type BaseLayer from "ol/layer/Base";
|
|
@@ -112,7 +112,7 @@ function TreeItem({
|
|
|
112
112
|
<>
|
|
113
113
|
<div className={twMerge("flex items-center gap-2 py-2", className)}>
|
|
114
114
|
{selectionType === SelectionType.RADIO ? null : (
|
|
115
|
-
// <
|
|
115
|
+
// <RadioButton
|
|
116
116
|
// checked={isControlChecked}
|
|
117
117
|
// id={inputId}
|
|
118
118
|
// onChange={handleSelectionChange}
|
|
@@ -5,6 +5,7 @@ import { memo, useEffect, useMemo, useState } from "preact/compat";
|
|
|
5
5
|
|
|
6
6
|
import LayerTree from "../LayerTree";
|
|
7
7
|
import { SelectionType } from "../LayerTree/TreeItem";
|
|
8
|
+
import { LAYER_TREE_ORDER } from "../utils/constants";
|
|
8
9
|
import useLayersConfig from "../utils/hooks/useLayersConfig";
|
|
9
10
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
10
11
|
|
|
@@ -25,7 +26,9 @@ export interface LayerTreeConfig {
|
|
|
25
26
|
title: string;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
export type LayerTreeMenuProps =
|
|
29
|
+
export type LayerTreeMenuProps = {
|
|
30
|
+
order: string[];
|
|
31
|
+
} & HTMLAttributes<HTMLDivElement> &
|
|
29
32
|
Partial<LayerTreeProps> &
|
|
30
33
|
PreactDOMAttributes;
|
|
31
34
|
|
|
@@ -58,7 +61,10 @@ const getConfigForLayer = (
|
|
|
58
61
|
};
|
|
59
62
|
};
|
|
60
63
|
|
|
61
|
-
function LayerTreeMenu(
|
|
64
|
+
function LayerTreeMenu({
|
|
65
|
+
order = LAYER_TREE_ORDER,
|
|
66
|
+
...props
|
|
67
|
+
}: LayerTreeMenuProps) {
|
|
62
68
|
const { map } = useMapContext();
|
|
63
69
|
const [revision, setRevision] = useState(0);
|
|
64
70
|
const layersConfig = useLayersConfig();
|
|
@@ -68,11 +74,21 @@ function LayerTreeMenu(props: LayerTreeMenuProps) {
|
|
|
68
74
|
map
|
|
69
75
|
?.getLayers()
|
|
70
76
|
.getArray()
|
|
77
|
+
.sort((a, b) => {
|
|
78
|
+
if (
|
|
79
|
+
order &&
|
|
80
|
+
order.indexOf(a.get("name")) > order.indexOf(b.get("name"))
|
|
81
|
+
) {
|
|
82
|
+
return 1;
|
|
83
|
+
} else {
|
|
84
|
+
return -1;
|
|
85
|
+
}
|
|
86
|
+
})
|
|
71
87
|
.map((layer) => {
|
|
72
88
|
return getConfigForLayer(layer, revision, layersConfig);
|
|
73
89
|
}) || [];
|
|
74
90
|
return config;
|
|
75
|
-
}, [layersConfig, map, revision]);
|
|
91
|
+
}, [layersConfig, map, order, revision]);
|
|
76
92
|
|
|
77
93
|
// Force update of config when a layers`s visibility changes progammatically
|
|
78
94
|
useEffect(() => {
|
|
@@ -21,6 +21,7 @@ function LayoutState() {
|
|
|
21
21
|
isShareMenuOpen,
|
|
22
22
|
layertree,
|
|
23
23
|
lnp,
|
|
24
|
+
mapset,
|
|
24
25
|
notification,
|
|
25
26
|
permalink,
|
|
26
27
|
previewNotifications,
|
|
@@ -33,6 +34,7 @@ function LayoutState() {
|
|
|
33
34
|
setHasGeolocation,
|
|
34
35
|
setHasLayerTree,
|
|
35
36
|
setHasLnp,
|
|
37
|
+
setHasMapset,
|
|
36
38
|
setHasNotification,
|
|
37
39
|
setHasPermalink,
|
|
38
40
|
setHasPrint,
|
|
@@ -47,6 +49,7 @@ function LayoutState() {
|
|
|
47
49
|
setIsOverlayOpen,
|
|
48
50
|
setIsSearchOpen,
|
|
49
51
|
setIsShareMenuOpen,
|
|
52
|
+
setLinesIds,
|
|
50
53
|
setStationId,
|
|
51
54
|
setTrainId,
|
|
52
55
|
share,
|
|
@@ -68,6 +71,10 @@ function LayoutState() {
|
|
|
68
71
|
setHasNotification(notification === "true" || !!previewNotifications);
|
|
69
72
|
}, [notification, previewNotifications, setHasNotification]);
|
|
70
73
|
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
setHasMapset(mapset === "true");
|
|
76
|
+
}, [mapset, setHasMapset]);
|
|
77
|
+
|
|
71
78
|
useEffect(() => {
|
|
72
79
|
setHasGeolocation(geolocation === "true");
|
|
73
80
|
}, [geolocation, setHasGeolocation]);
|
|
@@ -116,6 +123,7 @@ function LayoutState() {
|
|
|
116
123
|
setStationId(null);
|
|
117
124
|
setTrainId(null);
|
|
118
125
|
setFeaturesInfos(null);
|
|
126
|
+
setLinesIds(null);
|
|
119
127
|
}
|
|
120
128
|
}, [
|
|
121
129
|
isSearchOpen,
|
|
@@ -123,6 +131,7 @@ function LayoutState() {
|
|
|
123
131
|
setIsExportMenuOpen,
|
|
124
132
|
setIsLayerTreeOpen,
|
|
125
133
|
setIsShareMenuOpen,
|
|
134
|
+
setLinesIds,
|
|
126
135
|
setStationId,
|
|
127
136
|
setTrainId,
|
|
128
137
|
]);
|
|
@@ -135,6 +144,7 @@ function LayoutState() {
|
|
|
135
144
|
setStationId(null);
|
|
136
145
|
setTrainId(null);
|
|
137
146
|
setFeaturesInfos(null);
|
|
147
|
+
setLinesIds(null);
|
|
138
148
|
}
|
|
139
149
|
}, [
|
|
140
150
|
isShareMenuOpen,
|
|
@@ -142,6 +152,7 @@ function LayoutState() {
|
|
|
142
152
|
setIsExportMenuOpen,
|
|
143
153
|
setIsLayerTreeOpen,
|
|
144
154
|
setIsSearchOpen,
|
|
155
|
+
setLinesIds,
|
|
145
156
|
setStationId,
|
|
146
157
|
setTrainId,
|
|
147
158
|
]);
|
|
@@ -154,6 +165,7 @@ function LayoutState() {
|
|
|
154
165
|
setFeaturesInfos(null);
|
|
155
166
|
setTrainId(null);
|
|
156
167
|
setStationId(null);
|
|
168
|
+
setLinesIds(null);
|
|
157
169
|
setIsShareMenuOpen(false);
|
|
158
170
|
}
|
|
159
171
|
}, [
|
|
@@ -163,6 +175,7 @@ function LayoutState() {
|
|
|
163
175
|
setIsLayerTreeOpen,
|
|
164
176
|
setIsSearchOpen,
|
|
165
177
|
setIsShareMenuOpen,
|
|
178
|
+
setLinesIds,
|
|
166
179
|
setStationId,
|
|
167
180
|
setTrainId,
|
|
168
181
|
]);
|
|
@@ -174,6 +187,7 @@ function LayoutState() {
|
|
|
174
187
|
setIsSearchOpen(false);
|
|
175
188
|
setFeaturesInfos(null);
|
|
176
189
|
setTrainId(null);
|
|
190
|
+
setLinesIds(null);
|
|
177
191
|
setIsShareMenuOpen(false);
|
|
178
192
|
setStationId(null);
|
|
179
193
|
}
|
|
@@ -184,6 +198,7 @@ function LayoutState() {
|
|
|
184
198
|
setIsLayerTreeOpen,
|
|
185
199
|
setIsSearchOpen,
|
|
186
200
|
setIsShareMenuOpen,
|
|
201
|
+
setLinesIds,
|
|
187
202
|
setStationId,
|
|
188
203
|
setTrainId,
|
|
189
204
|
]);
|
|
@@ -217,6 +232,7 @@ function LayoutState() {
|
|
|
217
232
|
setIsSearchOpen(false);
|
|
218
233
|
setTrainId(null);
|
|
219
234
|
setIsShareMenuOpen(false);
|
|
235
|
+
setLinesIds(null);
|
|
220
236
|
}
|
|
221
237
|
}, [
|
|
222
238
|
setFeaturesInfos,
|
|
@@ -224,6 +240,7 @@ function LayoutState() {
|
|
|
224
240
|
setIsLayerTreeOpen,
|
|
225
241
|
setIsSearchOpen,
|
|
226
242
|
setIsShareMenuOpen,
|
|
243
|
+
setLinesIds,
|
|
227
244
|
setTrainId,
|
|
228
245
|
stationId,
|
|
229
246
|
]);
|
|
@@ -3,8 +3,15 @@ import { twMerge } from "tailwind-merge";
|
|
|
3
3
|
|
|
4
4
|
import RouteIcon from "../RouteIcon";
|
|
5
5
|
import ShadowOverflow from "../ShadowOverflow";
|
|
6
|
+
import {
|
|
7
|
+
LNP_LINE_ID_PROP,
|
|
8
|
+
LNP_MD_LINES,
|
|
9
|
+
LNP_MD_STOPS,
|
|
10
|
+
LNP_SOURCE_ID,
|
|
11
|
+
} from "../utils/constants";
|
|
6
12
|
import useMapContext from "../utils/hooks/useMapContext";
|
|
7
13
|
|
|
14
|
+
import type { VectorTileSource } from "maplibre-gl";
|
|
8
15
|
import type { RealtimeLine } from "mobility-toolbox-js/types";
|
|
9
16
|
import type { Feature } from "ol";
|
|
10
17
|
import type { PreactDOMAttributes } from "preact";
|
|
@@ -32,11 +39,7 @@ interface StopInfo {
|
|
|
32
39
|
visibility_level: number;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
const LNP_SOURCE_ID = "network_plans";
|
|
36
|
-
const LNP_MD_LINES = "geops.lnp.lines";
|
|
37
|
-
const LNP_MD_STOPS = "geops.lnp.stops";
|
|
38
42
|
const RUNS_PROP = "runs";
|
|
39
|
-
const ORIGINAL_LINE_ID_PROP = "original_line_id";
|
|
40
43
|
|
|
41
44
|
function LinesNetworkPlanDetails({
|
|
42
45
|
className,
|
|
@@ -50,7 +53,9 @@ function LinesNetworkPlanDetails({
|
|
|
50
53
|
const [stopInfosOpenId, setStopInfosOpenId] = useState<string>(null);
|
|
51
54
|
|
|
52
55
|
const isRunsDisplay = useMemo(() => {
|
|
53
|
-
return
|
|
56
|
+
return (
|
|
57
|
+
new URLSearchParams(window.location.search).get(RUNS_PROP) === "true"
|
|
58
|
+
);
|
|
54
59
|
}, []);
|
|
55
60
|
|
|
56
61
|
useEffect(() => {
|
|
@@ -62,12 +67,21 @@ function LinesNetworkPlanDetails({
|
|
|
62
67
|
const data = await response.json();
|
|
63
68
|
cacheLineInfosById = data[LNP_MD_LINES];
|
|
64
69
|
cacheStopInfosById = data[LNP_MD_STOPS];
|
|
70
|
+
if (!cacheLineInfosById) {
|
|
71
|
+
// eslint-disable-next-line no-console
|
|
72
|
+
console.warn("No lines informations found from ", url);
|
|
73
|
+
}
|
|
74
|
+
if (!cacheStopInfosById) {
|
|
75
|
+
// eslint-disable-next-line no-console
|
|
76
|
+
console.warn("No stops informations found from ", url);
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
79
|
setLineInfos(cacheLineInfosById);
|
|
67
80
|
setStopInfos(cacheStopInfosById);
|
|
68
81
|
};
|
|
69
|
-
|
|
70
|
-
|
|
82
|
+
const url = (source as VectorTileSource)?.url;
|
|
83
|
+
if (url) {
|
|
84
|
+
void fetchInfos(url);
|
|
71
85
|
}
|
|
72
86
|
return () => {
|
|
73
87
|
abortController?.abort();
|
|
@@ -80,7 +94,7 @@ function LinesNetworkPlanDetails({
|
|
|
80
94
|
[
|
|
81
95
|
...new Set(
|
|
82
96
|
features.map((f) => {
|
|
83
|
-
return f.get(
|
|
97
|
+
return f.get(LNP_LINE_ID_PROP);
|
|
84
98
|
}),
|
|
85
99
|
),
|
|
86
100
|
]
|
|
@@ -97,7 +111,7 @@ function LinesNetworkPlanDetails({
|
|
|
97
111
|
|
|
98
112
|
const runs = features
|
|
99
113
|
.filter((f) => {
|
|
100
|
-
return f.get(
|
|
114
|
+
return f.get(LNP_LINE_ID_PROP) === id;
|
|
101
115
|
})
|
|
102
116
|
.reduce((acc, featuree) => {
|
|
103
117
|
return acc + featuree.get(RUNS_PROP);
|
|
@@ -115,12 +129,13 @@ function LinesNetworkPlanDetails({
|
|
|
115
129
|
const stopInfoIdsByLineId: Record<string, string[]> = useMemo(() => {
|
|
116
130
|
const byLineId = {};
|
|
117
131
|
features.forEach((f) => {
|
|
118
|
-
const lineId = f.get(
|
|
132
|
+
const lineId = f.get(LNP_LINE_ID_PROP);
|
|
119
133
|
if (lineId && !byLineId[lineId] && f.get("stop_ids")) {
|
|
120
134
|
try {
|
|
121
135
|
byLineId[lineId] = JSON.parse(f.get("stop_ids"));
|
|
122
136
|
} catch (e) {
|
|
123
|
-
console
|
|
137
|
+
// eslint-disable-next-line no-console
|
|
138
|
+
console.warn("Impossible to parse stop_ids", e);
|
|
124
139
|
}
|
|
125
140
|
}
|
|
126
141
|
});
|
|
@@ -128,7 +143,7 @@ function LinesNetworkPlanDetails({
|
|
|
128
143
|
return byLineId;
|
|
129
144
|
}, [features]);
|
|
130
145
|
|
|
131
|
-
if (!features?.length
|
|
146
|
+
if (!features?.length) {
|
|
132
147
|
return null;
|
|
133
148
|
}
|
|
134
149
|
|
|
@@ -137,8 +152,8 @@ function LinesNetworkPlanDetails({
|
|
|
137
152
|
<div className="space-y-4">
|
|
138
153
|
{Object.entries(lineInfosByOperator)
|
|
139
154
|
.sort(([operatorNameA], [operatorNameB]) => {
|
|
140
|
-
return lineInfosByOperator[operatorNameA]
|
|
141
|
-
lineInfosByOperator[operatorNameB]
|
|
155
|
+
return lineInfosByOperator[operatorNameA][RUNS_PROP] <
|
|
156
|
+
lineInfosByOperator[operatorNameB][RUNS_PROP]
|
|
142
157
|
? 1
|
|
143
158
|
: -1;
|
|
144
159
|
})
|
|
@@ -162,7 +177,7 @@ function LinesNetworkPlanDetails({
|
|
|
162
177
|
short_name: shortName,
|
|
163
178
|
text_color: textColor,
|
|
164
179
|
} = lineInfo;
|
|
165
|
-
let longName = long_name;
|
|
180
|
+
let longName = long_name || shortName;
|
|
166
181
|
|
|
167
182
|
let stops = null;
|
|
168
183
|
//stopInfoIdsByLineId?.[id] || null;
|
|
@@ -208,7 +223,9 @@ function LinesNetworkPlanDetails({
|
|
|
208
223
|
key={shortName}
|
|
209
224
|
>
|
|
210
225
|
<div
|
|
211
|
-
className={
|
|
226
|
+
className={
|
|
227
|
+
"flex items-center justify-between gap-2"
|
|
228
|
+
}
|
|
212
229
|
// onClick={() => {
|
|
213
230
|
// setStopInfosOpenId(stopInfosOpenId === id ? null : id);
|
|
214
231
|
// }}
|
|
@@ -217,11 +234,7 @@ function LinesNetworkPlanDetails({
|
|
|
217
234
|
<RouteIcon line={line}></RouteIcon>
|
|
218
235
|
</div>
|
|
219
236
|
{!!longName && (
|
|
220
|
-
<div
|
|
221
|
-
className={
|
|
222
|
-
"flex-1 text-left *:before:content-['_–'] *:first:font-semibold *:first:before:!content-[_p] *:last:font-semibold *:last:before:!content-[_p]"
|
|
223
|
-
}
|
|
224
|
-
>
|
|
237
|
+
<div className={"flex-1 text-left"}>
|
|
225
238
|
{longName.split("-").map((name) => {
|
|
226
239
|
return <div key={name}>{name}</div>;
|
|
227
240
|
})}
|
|
@@ -15,13 +15,10 @@ function LinesNetworkPlanLayer(props: MaplibreStyleLayerOptions) {
|
|
|
15
15
|
return null;
|
|
16
16
|
}
|
|
17
17
|
return new MaplibreStyleLayer({
|
|
18
|
-
layersFilter: ({ metadata
|
|
18
|
+
layersFilter: ({ metadata }) => {
|
|
19
19
|
return (
|
|
20
|
-
metadata?.["
|
|
21
|
-
metadata?.["
|
|
22
|
-
metadata?.["rvf.filter"] === "netzplan_lines" ||
|
|
23
|
-
metadata?.["rvf.filter"] === "netzplan_stations" ||
|
|
24
|
-
source === "network_plans"
|
|
20
|
+
metadata?.["rvf.filter"]?.startsWith("netzplan") &&
|
|
21
|
+
!metadata?.["rvf.filter"]?.startsWith("netzplan_call")
|
|
25
22
|
);
|
|
26
23
|
},
|
|
27
24
|
maplibreLayer: baseLayer,
|