@geops/rvf-mobility-web-component 0.1.33 → 0.1.34
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 +8 -0
- package/index.js +155 -150
- package/package.json +1 -1
- package/src/RouteIcon/RouteIcon.tsx +6 -3
- package/src/RouteStopProgress/RouteStopProgress.tsx +12 -7
- package/src/RvfFeatureDetails/RvfLineNetworkDetails/RvfLineNetworkDetails.tsx +158 -23
- package/src/utils/getFeatureInformationTitle.ts +3 -2
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.34",
|
|
6
6
|
"homepage": "https://rvf-mobility-web-component-geops.vercel.app/",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "index.js",
|
|
@@ -34,7 +34,7 @@ function RouteIcon({
|
|
|
34
34
|
departure?.line ||
|
|
35
35
|
stopSequence?.line ||
|
|
36
36
|
trajectory?.properties?.line;
|
|
37
|
-
const type = stopSequence?.type || trajectory?.type;
|
|
37
|
+
const type = lineToUse?.type || stopSequence?.type || trajectory?.type;
|
|
38
38
|
const backgroundColor = getMainColorForVehicle(
|
|
39
39
|
line || departure || stopSequence || trajectory,
|
|
40
40
|
);
|
|
@@ -46,7 +46,10 @@ function RouteIcon({
|
|
|
46
46
|
|
|
47
47
|
const fontSize = fontSizesByNbLetters[text.length] || 12;
|
|
48
48
|
const font = getTextFontForVehicle(fontSize, text);
|
|
49
|
-
|
|
49
|
+
|
|
50
|
+
// RealtimeIcon only for stopsequence for now
|
|
51
|
+
const hasRealtime = stopSequence?.has_realtime_journey === true;
|
|
52
|
+
const showNoRealtimeIcon = !!stopSequence;
|
|
50
53
|
const isCancelled = stopSequence?.stations[0]?.state === "JOURNEY_CANCELLED";
|
|
51
54
|
|
|
52
55
|
if (borderColor === backgroundColor) {
|
|
@@ -67,7 +70,7 @@ function RouteIcon({
|
|
|
67
70
|
>
|
|
68
71
|
{children || text}
|
|
69
72
|
|
|
70
|
-
{!isCancelled && !hasRealtime && (
|
|
73
|
+
{showNoRealtimeIcon && !isCancelled && !hasRealtime && (
|
|
71
74
|
<NoRealtime className={"absolute -left-2 -top-2"} />
|
|
72
75
|
)}
|
|
73
76
|
</span>
|
|
@@ -6,11 +6,16 @@ import useMapContext from "../utils/hooks/useMapContext";
|
|
|
6
6
|
import useRouteStop from "../utils/hooks/useRouteStop";
|
|
7
7
|
|
|
8
8
|
export type RouteStopProgressProps = {
|
|
9
|
+
lineColor?: string;
|
|
9
10
|
svgProps?: JSX.HTMLAttributes<SVGElement> & PreactDOMAttributes;
|
|
10
11
|
} & JSX.HTMLAttributes<HTMLDivElement> &
|
|
11
12
|
PreactDOMAttributes;
|
|
12
13
|
|
|
13
|
-
function RouteStopProgress({
|
|
14
|
+
function RouteStopProgress({
|
|
15
|
+
lineColor,
|
|
16
|
+
svgProps,
|
|
17
|
+
...props
|
|
18
|
+
}: RouteStopProgressProps) {
|
|
14
19
|
const { stopSequence } = useMapContext();
|
|
15
20
|
const { invertColor, status } = useRouteStop();
|
|
16
21
|
const { isBoarding, isFirst, isLast, isLeft, isPassed, progress } = status;
|
|
@@ -19,16 +24,16 @@ function RouteStopProgress({ svgProps, ...props }: RouteStopProgressProps) {
|
|
|
19
24
|
const yDone = `${progress}%`;
|
|
20
25
|
|
|
21
26
|
const greyColor = "rgb(156, 163, 175)";
|
|
22
|
-
const
|
|
27
|
+
const lineColorr = lineColor || getMainColorForVehicle(stopSequence);
|
|
23
28
|
|
|
24
|
-
let colorScheme = isPassed ? greyColor :
|
|
25
|
-
let invertColorScheme = isPassed ?
|
|
29
|
+
let colorScheme = isPassed ? greyColor : lineColorr;
|
|
30
|
+
let invertColorScheme = isPassed ? lineColorr : greyColor;
|
|
26
31
|
let progressDoneColor = greyColor;
|
|
27
32
|
|
|
28
33
|
if (invertColor) {
|
|
29
|
-
colorScheme = isPassed ?
|
|
30
|
-
invertColorScheme = isPassed ? greyColor :
|
|
31
|
-
progressDoneColor =
|
|
34
|
+
colorScheme = isPassed ? lineColorr : greyColor;
|
|
35
|
+
invertColorScheme = isPassed ? greyColor : lineColorr;
|
|
36
|
+
progressDoneColor = lineColorr;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
const circleColor =
|
|
@@ -1,9 +1,35 @@
|
|
|
1
|
+
import { RealtimeLine } from "mobility-toolbox-js/types";
|
|
1
2
|
import { Feature } from "ol";
|
|
2
3
|
import { useEffect, useMemo, useState } from "preact/hooks";
|
|
3
4
|
|
|
5
|
+
import ArrowDown from "../../icons/ArrowDown";
|
|
6
|
+
import ArrowUp from "../../icons/ArrowUp";
|
|
7
|
+
import RouteIcon from "../../RouteIcon";
|
|
8
|
+
import RouteStopProgress from "../../RouteStopProgress";
|
|
4
9
|
import useMapContext from "../../utils/hooks/useMapContext";
|
|
10
|
+
import { RouteStopContext } from "../../utils/hooks/useRouteStop";
|
|
5
11
|
|
|
6
12
|
let cacheLineInfosById = null;
|
|
13
|
+
let cacheStopInfosById = null;
|
|
14
|
+
|
|
15
|
+
interface LineInfo {
|
|
16
|
+
color: string;
|
|
17
|
+
external_id: string;
|
|
18
|
+
id: string;
|
|
19
|
+
long_name: string;
|
|
20
|
+
mot: string;
|
|
21
|
+
operator_name: string;
|
|
22
|
+
short_name: string;
|
|
23
|
+
text_color: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface StopInfo {
|
|
27
|
+
external_id: string;
|
|
28
|
+
importance: number;
|
|
29
|
+
long_name: string;
|
|
30
|
+
short_name: string;
|
|
31
|
+
visibility_level: number;
|
|
32
|
+
}
|
|
7
33
|
|
|
8
34
|
function RvfLineNetworkDetails({
|
|
9
35
|
feature,
|
|
@@ -13,7 +39,11 @@ function RvfLineNetworkDetails({
|
|
|
13
39
|
features: Feature[];
|
|
14
40
|
}) {
|
|
15
41
|
const { apikey, mapsurl } = useMapContext();
|
|
16
|
-
const [lineInfos, setLineInfos] = useState(null);
|
|
42
|
+
const [lineInfos, setLineInfos] = useState<LineInfo[]>(null);
|
|
43
|
+
const [stopInfos, setStopInfos] = useState<StopInfo[]>(null);
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
45
|
+
const [stopInfosOpenId, setStopInfosOpenId] = useState<string>(null);
|
|
46
|
+
|
|
17
47
|
useEffect(() => {
|
|
18
48
|
const fetchInfos = async () => {
|
|
19
49
|
if (!cacheLineInfosById) {
|
|
@@ -22,15 +52,16 @@ function RvfLineNetworkDetails({
|
|
|
22
52
|
);
|
|
23
53
|
const data = await response.json();
|
|
24
54
|
cacheLineInfosById = data["geops.lnp.lines"];
|
|
55
|
+
cacheStopInfosById = data["geops.lnp.stops"];
|
|
25
56
|
}
|
|
26
57
|
setLineInfos(cacheLineInfosById);
|
|
58
|
+
setStopInfos(cacheStopInfosById);
|
|
27
59
|
};
|
|
28
60
|
fetchInfos();
|
|
29
61
|
}, [apikey, mapsurl]);
|
|
30
62
|
|
|
31
|
-
const
|
|
63
|
+
const lineInfosByOperator: Record<string, LineInfo[]> = useMemo(() => {
|
|
32
64
|
const byOperators = {};
|
|
33
|
-
|
|
34
65
|
[
|
|
35
66
|
...new Set(
|
|
36
67
|
features.map((f) => {
|
|
@@ -46,51 +77,155 @@ function RvfLineNetworkDetails({
|
|
|
46
77
|
if (!byOperators[operatorName]) {
|
|
47
78
|
byOperators[operatorName] = [];
|
|
48
79
|
}
|
|
80
|
+
lineInfos[id].id = id;
|
|
49
81
|
byOperators[operatorName].push(lineInfos[id]);
|
|
50
82
|
});
|
|
51
83
|
|
|
52
84
|
return byOperators;
|
|
53
85
|
}, [features, lineInfos]);
|
|
54
86
|
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
88
|
+
const stopInfoIdsByLineId: Record<string, string[]> = useMemo(() => {
|
|
89
|
+
const byLineId = {};
|
|
90
|
+
features.forEach((f) => {
|
|
91
|
+
const lineId = f.get("original_line_id");
|
|
92
|
+
if (lineId && !byLineId[lineId]) {
|
|
93
|
+
try {
|
|
94
|
+
byLineId[lineId] = JSON.parse(f.get("stop_ids"));
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.log(e);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
return byLineId;
|
|
102
|
+
}, [features]);
|
|
103
|
+
|
|
55
104
|
if (!feature || !lineInfos) {
|
|
56
105
|
return null;
|
|
57
106
|
}
|
|
58
107
|
|
|
59
108
|
return (
|
|
60
109
|
<div className="flex flex-col gap-4">
|
|
61
|
-
{Object.entries(
|
|
62
|
-
(
|
|
63
|
-
|
|
64
|
-
<div
|
|
65
|
-
|
|
66
|
-
|
|
110
|
+
{Object.entries(lineInfosByOperator).map(([operatorName, linesInfos]) => {
|
|
111
|
+
return (
|
|
112
|
+
<div className={"flex flex-col gap-2"} key={operatorName}>
|
|
113
|
+
<div>{operatorName}</div>
|
|
114
|
+
{linesInfos
|
|
115
|
+
.sort((a, b) => {
|
|
116
|
+
return a.short_name?.localeCompare(b.short_name);
|
|
117
|
+
})
|
|
118
|
+
.map((lineInfo) => {
|
|
67
119
|
const {
|
|
120
|
+
color: backgroundColor,
|
|
121
|
+
id,
|
|
68
122
|
// color,
|
|
69
123
|
// external_id,
|
|
70
|
-
long_name
|
|
124
|
+
long_name,
|
|
125
|
+
mot,
|
|
71
126
|
short_name: shortName,
|
|
72
|
-
|
|
127
|
+
text_color: textColor,
|
|
73
128
|
} = lineInfo;
|
|
129
|
+
let longName = long_name;
|
|
130
|
+
|
|
131
|
+
let stops = null;
|
|
132
|
+
//stopInfoIdsByLineId?.[id] || null;
|
|
133
|
+
if (!stops?.length) {
|
|
134
|
+
stops = null;
|
|
135
|
+
}
|
|
136
|
+
console.log("stops", stops, longName);
|
|
137
|
+
if (!longName && stops) {
|
|
138
|
+
const names = stops.map((stopId) => {
|
|
139
|
+
return stopInfos[stopId].short_name;
|
|
140
|
+
});
|
|
141
|
+
console.log("stops", names);
|
|
142
|
+
|
|
143
|
+
longName = [
|
|
144
|
+
...new Set([names[0], names[names.length - 1]]),
|
|
145
|
+
].join(" - ");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Build a line object
|
|
149
|
+
const line: { type: string } & RealtimeLine = {
|
|
150
|
+
color: null,
|
|
151
|
+
id: null,
|
|
152
|
+
name: shortName,
|
|
153
|
+
stroke: null,
|
|
154
|
+
text_color: null,
|
|
155
|
+
type: mot,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
if (textColor) {
|
|
159
|
+
line.text_color = "#" + textColor;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (backgroundColor) {
|
|
163
|
+
line.color = "#" + backgroundColor;
|
|
164
|
+
}
|
|
74
165
|
|
|
75
166
|
return (
|
|
76
|
-
<div
|
|
77
|
-
<div
|
|
167
|
+
<div key={shortName}>
|
|
168
|
+
<div
|
|
169
|
+
className={
|
|
170
|
+
"flex w-full items-center justify-between gap-2"
|
|
171
|
+
}
|
|
172
|
+
// onClick={() => {
|
|
173
|
+
// setStopInfosOpenId(stopInfosOpenId === id ? null : id);
|
|
174
|
+
// }}
|
|
175
|
+
>
|
|
176
|
+
<div>
|
|
177
|
+
<RouteIcon line={line}></RouteIcon>
|
|
178
|
+
</div>
|
|
179
|
+
{!!longName && (
|
|
180
|
+
<div className={"flex-1 text-left"}>{longName}</div>
|
|
181
|
+
)}
|
|
182
|
+
{!!stops && (
|
|
183
|
+
<button className={"shrink-0"}>
|
|
184
|
+
{stopInfosOpenId === id ? <ArrowUp /> : <ArrowDown />}
|
|
185
|
+
</button>
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
{!!stops && (
|
|
78
189
|
<div
|
|
79
|
-
className={
|
|
80
|
-
"rounded-md bg-red px-[12px] py-[9px] font-bold leading-none text-white"
|
|
81
|
-
}
|
|
190
|
+
className={`${stopInfosOpenId === id ? "" : "hidden"}`}
|
|
82
191
|
>
|
|
83
|
-
{
|
|
192
|
+
{stops?.map((stopId, index, arr) => {
|
|
193
|
+
const stop = stopInfos[stopId];
|
|
194
|
+
return (
|
|
195
|
+
<div
|
|
196
|
+
className={"flex items-center gap-2"}
|
|
197
|
+
key={stopId}
|
|
198
|
+
>
|
|
199
|
+
<RouteStopContext.Provider
|
|
200
|
+
value={{
|
|
201
|
+
index,
|
|
202
|
+
status: {
|
|
203
|
+
isFirst: !index,
|
|
204
|
+
isLast: index === arr.length - 1,
|
|
205
|
+
isLeft: false,
|
|
206
|
+
isPassed: false,
|
|
207
|
+
progress: !index ? 50 : 0,
|
|
208
|
+
},
|
|
209
|
+
stop,
|
|
210
|
+
}}
|
|
211
|
+
>
|
|
212
|
+
<RouteStopProgress
|
|
213
|
+
className="relative flex size-8 shrink-0 items-center justify-center"
|
|
214
|
+
lineColor={line.color}
|
|
215
|
+
/>
|
|
216
|
+
<div>{stop.short_name}</div>
|
|
217
|
+
</RouteStopContext.Provider>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
})}
|
|
84
221
|
</div>
|
|
85
|
-
|
|
86
|
-
<div>{longName}</div>
|
|
222
|
+
)}
|
|
87
223
|
</div>
|
|
88
224
|
);
|
|
89
225
|
})}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)}
|
|
226
|
+
</div>
|
|
227
|
+
);
|
|
228
|
+
})}
|
|
94
229
|
</div>
|
|
95
230
|
);
|
|
96
231
|
}
|
|
@@ -15,9 +15,10 @@ const getFeatureInformationTitle = (feature: Feature) => {
|
|
|
15
15
|
category,
|
|
16
16
|
disruption_type: disruptionType,
|
|
17
17
|
feed_id: feedId,
|
|
18
|
-
|
|
18
|
+
line_id: lineId,
|
|
19
19
|
tickets,
|
|
20
20
|
} = selectedFeature.getProperties();
|
|
21
|
+
console.log(selectedFeature.getProperties());
|
|
21
22
|
|
|
22
23
|
if (disruptionType) {
|
|
23
24
|
return "MOCO Meldung";
|
|
@@ -29,7 +30,7 @@ const getFeatureInformationTitle = (feature: Feature) => {
|
|
|
29
30
|
return TITLE_BY_FEED_ID[feedId] || defaultTitle;
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
if (
|
|
33
|
+
if (lineId) {
|
|
33
34
|
return RVF_LAYERS_TITLES.liniennetz;
|
|
34
35
|
}
|
|
35
36
|
if (tickets) {
|