@geops/rvf-mobility-web-component 0.1.60 → 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.
Files changed (73) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +1 -0
  3. package/docutils.js +103 -4
  4. package/fonts/source-sans-3/source-sans-3-v15-latin-500.ttf +0 -0
  5. package/fonts/source-sans-3/source-sans-3-v15-latin-500.woff2 +0 -0
  6. package/fonts/source-sans-3/source-sans-3-v15-latin-600.ttf +0 -0
  7. package/fonts/source-sans-3/source-sans-3-v15-latin-600.woff2 +0 -0
  8. package/fonts/source-sans-3/source-sans-3-v15-latin-700.ttf +0 -0
  9. package/fonts/source-sans-3/source-sans-3-v15-latin-700.woff2 +0 -0
  10. package/fonts/source-sans-3/source-sans-3-v15-latin-regular.ttf +0 -0
  11. package/fonts/source-sans-3/source-sans-3-v15-latin-regular.woff2 +0 -0
  12. package/index.html +28 -94
  13. package/index.js +235 -224
  14. package/notifications.html +144 -0
  15. package/package.json +2 -2
  16. package/search.html +24 -65
  17. package/src/FeatureDetails/FeatureDetails.tsx +20 -6
  18. package/src/FeaturesInfosListener/FeaturesInfosListener.tsx +2 -0
  19. package/src/LayerTree/TreeItem/TreeItem.tsx +2 -2
  20. package/src/LayerTreeMenu/LayerTreeMenu.tsx +19 -3
  21. package/src/LayoutState/LayoutState.tsx +17 -0
  22. package/src/LinesNetworkPlanDetails/LinesNetworkPlanDetails.tsx +34 -21
  23. package/src/LinesNetworkPlanLayer/LinesNetworkPlanLayer.tsx +3 -6
  24. package/src/LinesNetworkPlanLayerHighlight/LinesNetworkPlanLayerHighlight.tsx +88 -0
  25. package/src/LinesNetworkPlanLayerHighlight/index.tsx +1 -0
  26. package/src/MapDispatchEvents/MapDispatchEvents.tsx +6 -4
  27. package/src/MapLayout/MapLayout.tsx +2 -2
  28. package/src/MapsetLayer/MapsetLayer.tsx +116 -0
  29. package/src/MapsetLayer/index.tsx +1 -0
  30. package/src/MobilityMap/MobilityMap.tsx +27 -5
  31. package/src/MobilityMap/MobilityMapAttributes.test.ts +38 -0
  32. package/src/MobilityMap/MobilityMapAttributes.ts +99 -22
  33. package/src/MobilityMap/MobilityMapEvents.ts +53 -0
  34. package/src/MobilityNotifications/MobilityNotifications.tsx +93 -0
  35. package/src/MobilityNotifications/MobilityNotificationsAttributes.test.ts +21 -0
  36. package/src/MobilityNotifications/MobilityNotificationsAttributes.ts +46 -0
  37. package/src/MobilityNotifications/index.ts +2 -0
  38. package/src/MobilitySearch/MobilitySearchEvents.ts +21 -0
  39. package/src/NotificationDetails/NotificationDetails.tsx +74 -251
  40. package/src/OverlayContent/OverlayContent.tsx +1 -1
  41. package/src/OverlayDetails/OverlayDetails.tsx +4 -2
  42. package/src/OverlayFooter/OverlayFooter.tsx +3 -2
  43. package/src/RealtimeLayer/RealtimeLayer.tsx +36 -7
  44. package/src/RouteScheduleFooter/RouteScheduleFooter.tsx +1 -2
  45. package/src/RvfFeatureDetails/RvfFeatureDetails.tsx +2 -2
  46. package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +2 -0
  47. package/src/RvfFeatureDetails/RvfNotificationDetails/RvfNotificationDetails.tsx +12 -453
  48. package/src/RvfFeatureDetails/RvfSellingPointDetails/RvfSellingPointDetails.tsx +20 -17
  49. package/src/RvfFeatureDetails/RvfSharedMobilityDetail/RvfSharedMobilityDetails.tsx +93 -36
  50. package/src/RvfLink/RvfLink.tsx +5 -2
  51. package/src/RvfMobilityMap/RvfMobilityMap.tsx +28 -11
  52. package/src/RvfSelectedFeatureHighlightLayer/RvfSelectedFeatureHighlightLayer.tsx +9 -5
  53. package/src/RvfSingleClickListener/RvfSingleClickListener.tsx +3 -1
  54. package/src/SituationDetails/SituationDetails.tsx +324 -0
  55. package/src/SituationDetails/index.ts +1 -0
  56. package/src/index.tsx +16 -0
  57. package/src/indexDoc.ts +25 -3
  58. package/src/ui/Checkbox/Checkbox.tsx +2 -2
  59. package/src/ui/Link/Link.tsx +49 -0
  60. package/src/ui/Link/index.tsx +1 -0
  61. package/src/ui/Select/Select.tsx +2 -2
  62. package/src/utils/constants.ts +37 -0
  63. package/src/utils/exportPdf.ts +3 -1
  64. package/src/utils/highlightLinesNetworkPlan.ts +25 -0
  65. package/src/utils/hooks/useI18n.tsx +6 -4
  66. package/src/utils/hooks/useInitialPermalink.tsx +9 -2
  67. package/src/utils/hooks/useMapContext.tsx +9 -0
  68. package/src/utils/sharingGraphqlUtils.ts +1 -1
  69. package/src/utils/translations.ts +12 -1
  70. package/tailwind.config.mjs +3 -1
  71. package/src/ShareMenu/PermalinkButton/PermalinkButton.tsx +0 -62
  72. package/src/ShareMenu/PermalinkButton/index.tsx +0 -1
  73. 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
+ >&gt;&gt; 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.60",
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
- <h2 class="text-xl font-bold">Attributes</h2>
68
- <div id="attributes"></div>
69
- <h2 class="text-xl font-bold">Events</h2>
70
- <div id="events"></div>
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
- /* Attributes */
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
- layer === linesNetworkPlanLayer &&
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 && layer === notificationsLayer && (
52
- <NotificationDetails className={contentClassName} feature={feature} />
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 RvfRadioButton from "../../RvfRadioButton";
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
- // <RvfRadioButton
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 = HTMLAttributes<HTMLDivElement> &
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(props: LayerTreeMenuProps) {
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 new URLSearchParams(window.location.search).get("runs") === "true";
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
- if (source?.url) {
70
- void fetchInfos(source?.url);
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(ORIGINAL_LINE_ID_PROP);
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(ORIGINAL_LINE_ID_PROP) === id;
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(ORIGINAL_LINE_ID_PROP);
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.log(e);
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 || !lineInfos) {
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].runs <
141
- lineInfosByOperator[operatorNameB].runs
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={"flex justify-between gap-2"}
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, source }) => {
18
+ layersFilter: ({ metadata }) => {
19
19
  return (
20
- metadata?.["geops.filter"] === "lnp" ||
21
- metadata?.["general.filter"] === "lnp" ||
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,