@geops/rvf-mobility-web-component 0.1.76 → 0.1.77

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/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.76",
5
+ "version": "0.1.77",
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.9.0",
15
- "mobility-toolbox-js": "3.4.6-beta.1",
15
+ "mobility-toolbox-js": "3.4.6-beta.6",
16
16
  "ol": "^10.6.1",
17
17
  "preact": "^10.27.2",
18
18
  "preact-custom-element": "^4.5.1",
@@ -87,6 +87,7 @@ function MobilityMap(props: MobilityMapProps) {
87
87
  const [stationId, setStationId] = useState<RealtimeStationId>();
88
88
  const [trainId, setTrainId] = useState<RealtimeTrainId>();
89
89
  const [linesIds, setLinesIds] = useState<string[]>();
90
+ const [notificationId, setNotificationId] = useState<string>();
90
91
 
91
92
  const [featuresInfos, setFeaturesInfos] = useState<
92
93
  LayerGetFeatureInfoResponse[]
@@ -141,6 +142,7 @@ function MobilityMap(props: MobilityMapProps) {
141
142
  linesNetworkPlanLayer,
142
143
  map,
143
144
  mapsetLayer,
145
+ notificationId,
144
146
  notificationsLayer,
145
147
  permalinkUrlSearchParams,
146
148
  previewNotifications,
@@ -175,6 +177,7 @@ function MobilityMap(props: MobilityMapProps) {
175
177
  setLinesNetworkPlanLayer,
176
178
  setMap,
177
179
  setMapsetLayer,
180
+ setNotificationId,
178
181
  setNotificationsLayer,
179
182
  setPermalinkUrlSearchParams,
180
183
  setPreviewNotifications,
@@ -222,6 +225,7 @@ function MobilityMap(props: MobilityMapProps) {
222
225
  linesNetworkPlanLayer,
223
226
  map,
224
227
  mapsetLayer,
228
+ notificationId,
225
229
  notificationsLayer,
226
230
  permalinkUrlSearchParams,
227
231
  previewNotifications,
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  type AffectedTimeIntervalType,
3
3
  type PublicationType,
4
- type SituationType,
5
4
  type TextualContentType,
6
5
  } from "mobility-toolbox-js/types";
7
6
  import { twMerge } from "tailwind-merge";
@@ -10,6 +9,7 @@ import Warning from "../icons/Warning";
10
9
  import ShadowOverflow from "../ShadowOverflow";
11
10
  import Link from "../ui/Link";
12
11
  import useI18n from "../utils/hooks/useI18n";
12
+ import useMocoSituation from "../utils/hooks/useMocoSituation";
13
13
 
14
14
  import type {
15
15
  MultilingualTextualContentType,
@@ -64,30 +64,8 @@ function NotificationDetails({
64
64
  feature: Feature;
65
65
  }) {
66
66
  const { locale, t } = useI18n();
67
- const { situation } = feature.getProperties();
68
-
69
- // useEffect(() => {
70
- // const abortController = new AbortController();
71
- // if (!notificationtenant) {
72
- // setLines([]);
73
- // }
74
- // fetch(
75
- // `https://tralis-tracker-api.geops.io/api/lines/${notificationtenant}/`,
76
- // )
77
- // .then((res) => {
78
- // return res.json();
79
- // })
80
- // .then((data) => {
81
- // setLines(data);
82
- // })
83
- // .catch((err) => {
84
- // // eslint-disable-next-line no-console
85
- // console.error("Failed to fetch lines", err);
86
- // });
87
- // return () => {
88
- // abortController?.abort();
89
- // };
90
- // }, [notificationtenant]);
67
+ const { situationId } = feature.getProperties();
68
+ const situationParsed = useMocoSituation(situationId);
91
69
 
92
70
  // moco export v2
93
71
  let textualContentMultilingual: Partial<MultilingualTextualContentType> = {};
@@ -96,41 +74,36 @@ function NotificationDetails({
96
74
  let publicationsToDisplay: PublicationType[] = [];
97
75
  let reasonsToDisplay: string[] = [];
98
76
 
99
- try {
100
- const situationParsed: SituationType = JSON.parse(situation) || {};
101
- const publicationsArr: PublicationType[] =
102
- situationParsed?.publications || [];
77
+ // const situationParsed: SituationType = JSON.parse(situation) || {};
78
+ const publicationsArr: PublicationType[] =
79
+ situationParsed?.publications || [];
103
80
 
104
- // Find the current publication(s) at the current date
105
- publicationsToDisplay =
106
- publicationsArr?.filter(({ publicationWindows }) => {
107
- return publicationWindows.find(({ endTime, startTime }) => {
108
- const now = new Date();
109
- const startT = new Date(startTime);
110
- const endT = new Date(endTime);
111
- return startT <= now && now <= endT;
112
- });
113
- }) || [];
81
+ // Find the current publication(s) at the current date
82
+ publicationsToDisplay =
83
+ publicationsArr?.filter(({ publicationWindows }) => {
84
+ return publicationWindows.find(({ endTime, startTime }) => {
85
+ const now = new Date();
86
+ const startT = new Date(startTime);
87
+ const endT = new Date(endTime);
88
+ return startT <= now && now <= endT;
89
+ });
90
+ }) || [];
114
91
 
115
- // Display the current and next affected time intervals not the one in the past
116
- timeIntervalsToDisplay =
117
- (situationParsed?.affectedTimeIntervals || []).filter(
118
- ({ endTime, startTime }) => {
119
- const now = new Date();
120
- const startT = new Date(startTime);
121
- const endT = new Date(endTime);
122
- return (startT <= now && now <= endT) || now < startT;
123
- },
124
- ) || [];
92
+ // Display the current and next affected time intervals not the one in the past
93
+ timeIntervalsToDisplay =
94
+ (situationParsed?.affectedTimeIntervals || []).filter(
95
+ ({ endTime, startTime }) => {
96
+ const now = new Date();
97
+ const startT = new Date(startTime);
98
+ const endT = new Date(endTime);
99
+ return (startT <= now && now <= endT) || now < startT;
100
+ },
101
+ ) || [];
125
102
 
126
- // Display the reasons
127
- reasonsToDisplay = (situationParsed?.reasons || []).map(({ name }) => {
128
- return name;
129
- });
130
- } catch (e) {
131
- // eslint-disable-next-line no-console
132
- console.error("Failed to parse publications", e);
133
- }
103
+ // Display the reasons
104
+ reasonsToDisplay = (situationParsed?.reasons || []).map(({ name }) => {
105
+ return name;
106
+ });
134
107
 
135
108
  return (
136
109
  <ShadowOverflow {...props} className={twMerge("px-4 text-base", className)}>
@@ -0,0 +1,91 @@
1
+ import {
2
+ getFeatureCollectionToRenderFromSituation,
3
+ MocoLayer,
4
+ } from "mobility-toolbox-js/ol";
5
+ import { unByKey } from "ol/Observable";
6
+
7
+ import type { GeoJSONSource } from "maplibre-gl";
8
+ import type { MocoNotificationFeatureCollectionToRender } from "mobility-toolbox-js/ol";
9
+ import type { Map } from "ol";
10
+
11
+ export const MOCO_SOURCE_ID = "moco";
12
+ export const MOCO_MD_LAYER_FILTER = "moco";
13
+ class MocoLayer2 extends MocoLayer {
14
+ constructor(options) {
15
+ super(options);
16
+ }
17
+
18
+ attachToMap(map: Map): void {
19
+ super.attachToMap(map);
20
+ unByKey(this.olEventsKeys);
21
+ }
22
+
23
+ getDataByGraph(
24
+ data: MocoNotificationFeatureCollectionToRender,
25
+ ): MocoNotificationFeatureCollectionToRender {
26
+ // const zoom = this.getMapInternal()?.getView()?.getZoom();
27
+ // const graphs = (
28
+ // this.maplibreLayer?.mapLibreMap?.getStyle() as MapsStyleSpecification
29
+ // ).metadata?.graphs;
30
+
31
+ // const graph = getGraphByZoom(zoom, graphs);
32
+ const newData: MocoNotificationFeatureCollectionToRender = {
33
+ features: (data?.features || []).filter((feature) => {
34
+ delete feature.properties?.publicationStops;
35
+ delete feature.properties?.publicationLines;
36
+ delete feature.properties?.publication;
37
+ delete feature.properties?.situation;
38
+ return (
39
+ feature.properties?.graph === "osm" ||
40
+ // feature.properties?.graph === "np_topo4" ||
41
+ // feature.properties?.graph === "np_topo5" ||
42
+ // feature.properties?.graph === "np_topo6" //||
43
+ feature.properties?.graph === "np_topo7" ||
44
+ feature.properties?.graph === "np_topo8" ||
45
+ feature.properties?.graph === "np_topo9" ||
46
+ feature.properties?.graph === "np_topo10" ||
47
+ feature.properties?.graph === "np_topo11" ||
48
+ feature.properties?.graph === "np_topo12" ||
49
+ feature.properties?.graph === "np_topo13" ||
50
+ feature.properties?.graph === "np_topo14" ||
51
+ feature.properties?.graph === "np_topo15"
52
+ );
53
+ }),
54
+ type: "FeatureCollection",
55
+ };
56
+ return newData;
57
+ }
58
+ /**
59
+ * This function updates the GeoJSON source data, with the current situations available in this.situations.
60
+ * @returns
61
+ */
62
+ async updateData(): Promise<boolean | undefined> {
63
+ if (this.loadAll) {
64
+ const situations = await this.loadData();
65
+ // We don't use the setter here to avoid infinite loop
66
+ this.set("situations", situations ?? []);
67
+ }
68
+ const source = this.maplibreLayer?.mapLibreMap?.getSource(MOCO_SOURCE_ID);
69
+ if (!source) {
70
+ // eslint-disable-next-line no-console
71
+ console.warn("MocoLayer: No source found for id : ", MOCO_SOURCE_ID);
72
+ return Promise.reject(new Error("No source found"));
73
+ }
74
+
75
+ const data = {
76
+ features: (this.situations ?? []).flatMap((situation) => {
77
+ return getFeatureCollectionToRenderFromSituation(situation).features;
78
+ }),
79
+ type: "FeatureCollection",
80
+ } as MocoNotificationFeatureCollectionToRender;
81
+ // this.#dataInternal = data;
82
+
83
+ // Apply new data to the source
84
+ console.log(this.getDataByGraph(data));
85
+ // console.log(JSON.stringify(this.getDataByGraph(data)));
86
+ (source as GeoJSONSource).setData(this.getDataByGraph(data));
87
+ return Promise.resolve(true);
88
+ }
89
+ }
90
+
91
+ export default MocoLayer2;
@@ -1,12 +1,10 @@
1
- import { MocoLayer } from "mobility-toolbox-js/ol";
1
+ import { MocoLayer, type MocoLayerOptions } from "mobility-toolbox-js/ol";
2
2
  import { memo } from "preact/compat";
3
3
  import { useEffect, useMemo } from "preact/hooks";
4
4
 
5
5
  import { LAYER_NAME_NOTIFICATIONS } from "../utils/constants";
6
6
  import useMapContext from "../utils/hooks/useMapContext";
7
7
 
8
- import type { MocoLayerOptions } from "mobility-toolbox-js/ol";
9
-
10
8
  function NotificationsLayer(props?: Partial<MocoLayerOptions>) {
11
9
  const {
12
10
  apikey,
@@ -1,8 +1,8 @@
1
- import { type SituationType } from "mobility-toolbox-js/types";
2
1
  import { twMerge } from "tailwind-merge";
3
2
 
4
3
  import ShadowOverflow from "../../ShadowOverflow";
5
4
  import SituationDetails from "../../SituationDetails";
5
+ import useMocoSituation from "../../utils/hooks/useMocoSituation";
6
6
 
7
7
  import type { Feature } from "ol";
8
8
 
@@ -20,17 +20,8 @@ function NotificationDetails({
20
20
  timeIntervalClassName?: string;
21
21
  toggleable?: boolean;
22
22
  }) {
23
- const { situation } = feature.getProperties();
24
-
25
- // moco export v2
26
- let situationParsed: Partial<SituationType> = {};
27
-
28
- try {
29
- situationParsed = JSON.parse(situation) || {};
30
- } catch (e) {
31
- // eslint-disable-next-line no-console
32
- console.error("Failed to parse publications", e);
33
- }
23
+ const { situationId } = feature.getProperties();
24
+ const situationParsed = useMocoSituation(situationId);
34
25
 
35
26
  return (
36
27
  <ShadowOverflow {...props} className={twMerge("px-4 text-base", className)}>
@@ -0,0 +1,54 @@
1
+ import { useEffect, useMemo, useState } from "preact/hooks";
2
+
3
+ import useMapContext from "./useMapContext";
4
+
5
+ import type { MocoAPI } from "mobility-toolbox-js/maplibre";
6
+ import type {
7
+ MocoExportParameters,
8
+ SituationType,
9
+ } from "mobility-toolbox-js/types";
10
+
11
+ function useMocoSituation(situationId?: string, params?: MocoExportParameters) {
12
+ const { lang, notificationsLayer } = useMapContext();
13
+ const [situation, setSituation] = useState<SituationType>();
14
+
15
+ const api: MocoAPI | undefined = useMemo(() => {
16
+ return notificationsLayer?.api;
17
+ }, [notificationsLayer]);
18
+
19
+ useEffect(() => {
20
+ const abortController = new AbortController();
21
+ api
22
+ ?.exportById(situationId, {
23
+ contentLarge: true,
24
+ contentMedium: true,
25
+ contentSmall: true,
26
+ includeGeoms: false,
27
+ includeLines: true,
28
+ includeStops: true,
29
+ [lang]: true,
30
+ limit: 1,
31
+ ...(params || {}),
32
+ })
33
+ .then((response) => {
34
+ setSituation(response);
35
+ })
36
+ .catch((err) => {
37
+ // 20: AbortError
38
+ if (err.code !== 20) {
39
+ setSituation(undefined);
40
+ // eslint-disable-next-line no-console
41
+ console.error("Failed to fetch situation", err);
42
+ return;
43
+ }
44
+ });
45
+
46
+ return () => {
47
+ abortController.abort();
48
+ };
49
+ }, [api, situationId, params, lang]);
50
+
51
+ return situation;
52
+ }
53
+
54
+ export default useMocoSituation;