@geops/rvf-mobility-web-component 0.1.23 → 0.1.24

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.23",
5
+ "version": "0.1.24",
6
6
  "homepage": "https://rvf-mobility-web-component-geops.vercel.app/",
7
7
  "type": "module",
8
8
  "main": "index.js",
@@ -9,12 +9,12 @@ export type RvfFeatureDetailsProps = JSX.HTMLAttributes<HTMLDivElement> &
9
9
  PreactDOMAttributes;
10
10
 
11
11
  const getIsSharedMobility = (selectedFeature): boolean => {
12
- const id =
13
- selectedFeature.getId() || selectedFeature.get("features")[0].getId();
14
- if (typeof id === "number") {
15
- return !!selectedFeature.get("category");
16
- } else if (typeof id === "string") {
17
- return id.includes("sharing_stations") || id.includes("Vehicle");
12
+ if (
13
+ selectedFeature.get("station_id") ||
14
+ selectedFeature.get("vehicle_id") ||
15
+ selectedFeature.get("cluster_id")
16
+ ) {
17
+ return true;
18
18
  }
19
19
  };
20
20
 
@@ -2,15 +2,7 @@ import { Feature } from "ol";
2
2
  import { useEffect, useMemo, useState } from "preact/hooks";
3
3
  import { Fragment } from "preact/jsx-runtime";
4
4
 
5
- import callBike from "../../logos/callabike_logo.png";
6
- import flinkster from "../../logos/flinkster_logo.png";
7
- import grueneFlotteLogo from "../../logos/gruene_flotte_logo.png";
8
- import lastenVeloLogo from "../../logos/lasten_velo_freiburg.png";
9
- import freloLogo from "../../logos/logo_frelo_web_rgb.png";
10
- import naturEnergieLogo from "../../logos/natur_energie_logo.png";
11
- import yoioLogo from "../../logos/yoio_logo.png";
12
- import zeusLogo from "../../logos/zeus_logo.png";
13
- import { API_REQUEST_FEATURE_TYPE } from "../../utils/constants";
5
+ import { PROVIDER_LOGOS_BY_FEED_ID } from "../../utils/constants";
14
6
  import FloatingVehiclesDetails from "./FloatingVehiclesDetails";
15
7
  import StationDetails from "./StationDetails";
16
8
 
@@ -18,89 +10,21 @@ export interface RvfSharedMobilityDetailsProps {
18
10
  selectedFeature: Feature;
19
11
  }
20
12
 
21
- const logos = {
22
- callabike_ice: callBike,
23
- flinkster_carsharing: flinkster,
24
- "gruene-flotte_freiburg": grueneFlotteLogo,
25
- lastenvelo_fr: lastenVeloLogo,
26
- naturenergie_sharing: naturEnergieLogo,
27
- nextbike_df: freloLogo,
28
- yoio_freiburg: yoioLogo,
29
- zeus_freiburg: zeusLogo,
30
- };
31
-
32
13
  function RvfSharedMobilityDetails({
33
14
  selectedFeature,
34
15
  }: RvfSharedMobilityDetailsProps) {
35
16
  const [features, setFeatures] = useState([]);
36
- const isStationDetails =
37
- !!selectedFeature.get("categories") ||
38
- !selectedFeature.get("features")?.length;
39
- const isFloatingVehicle = !!selectedFeature.get("features")?.length;
17
+ const isStationDetails = !!selectedFeature.get("station_id");
18
+ const isFloatingVehicle = !!selectedFeature.get("vehicle_id");
19
+ const isCluster = !!selectedFeature.get("cluster_id");
40
20
 
41
21
  useEffect(() => {
42
- const extent = selectedFeature.getGeometry().getExtent();
43
- extent[0] = extent[0] - 2;
44
- extent[1] = extent[1] - 2;
45
- extent[2] = extent[2] + 2;
46
- extent[3] = extent[3] + 2;
47
- const categoryName = selectedFeature.get("category")?.toLowerCase();
48
- let featureType;
49
- let abortController;
50
-
51
- if (categoryName) {
52
- if (categoryName === "bike sharing") {
53
- featureType = API_REQUEST_FEATURE_TYPE.stations.bike;
54
- } else if (categoryName === "car sharing") {
55
- featureType = API_REQUEST_FEATURE_TYPE.stations.car;
56
- } else if (categoryName === "cargo bike sharing") {
57
- featureType = API_REQUEST_FEATURE_TYPE.stations.cargoBike;
58
- }
59
- abortController = new AbortController();
60
-
61
- fetch(createRequestLink(featureType, extent), {
62
- signal: new AbortController().signal,
63
- })
64
- .then((res) => {
65
- return res.json();
66
- })
67
- .then((data) => {
68
- if (data.features?.[0].properties) {
69
- selectedFeature.setProperties(data.features[0].properties);
70
- }
71
- setFeatures([selectedFeature]);
72
- })
73
- .catch((err) => {
74
- console.error(err);
75
- });
22
+ if (isCluster) {
23
+ setFeatures(selectedFeature.get("features"));
76
24
  } else {
77
- if (isFloatingVehicle) {
78
- setFeatures(selectedFeature.get("features"));
79
- } else {
80
- setFeatures([selectedFeature]);
81
- }
25
+ setFeatures([selectedFeature]);
82
26
  }
83
- return () => {
84
- abortController?.abort();
85
- };
86
- }, [selectedFeature, isFloatingVehicle]);
87
-
88
- const createRequestLink = (name, extent) => {
89
- return (
90
- "https://api.mobidata-bw.de/geoserver/MobiData-BW/" +
91
- name +
92
- "/ows" +
93
- "?service=WFS&" +
94
- "version=1.1.0&request=GetFeature&typename=" +
95
- "MobiData-BW:" +
96
- name +
97
- "&" +
98
- "outputFormat=application/json&srsname=EPSG:3857&" +
99
- "bbox=" +
100
- extent.join(",") +
101
- ",EPSG:3857"
102
- );
103
- };
27
+ }, [selectedFeature, isFloatingVehicle, isCluster]);
104
28
 
105
29
  const featuresByFeedId: Record<string, Feature[]> = useMemo(() => {
106
30
  const featuresByFeedId = {};
@@ -125,14 +49,14 @@ function RvfSharedMobilityDetails({
125
49
  <img
126
50
  alt="logo"
127
51
  className="max-w-24"
128
- src={logos[features[0]?.get("feed_id")]}
52
+ src={PROVIDER_LOGOS_BY_FEED_ID[features[0]?.get("feed_id")]}
129
53
  />
130
54
  {features.length && isStationDetails && (
131
55
  <StationDetails feature={features[0]} />
132
56
  )}
133
57
  </>
134
58
  )}
135
- {isFloatingVehicle &&
59
+ {(isFloatingVehicle || isCluster) &&
136
60
  featuresByFeedId &&
137
61
  Object.entries(featuresByFeedId).map(([key, feats]) => {
138
62
  return (
@@ -140,7 +64,7 @@ function RvfSharedMobilityDetails({
140
64
  <img
141
65
  alt="logo"
142
66
  className="max-w-24"
143
- src={logos[feats[0]?.get("feed_id")]}
67
+ src={PROVIDER_LOGOS_BY_FEED_ID[feats[0]?.get("feed_id")]}
144
68
  />
145
69
  <FloatingVehiclesDetails features={feats} />
146
70
  </Fragment>
@@ -1,162 +1,13 @@
1
- import { gql, GraphQLClient } from "graphql-request";
2
1
  import { Feature } from "ol";
3
2
  import { useEffect, useMemo, useState } from "preact/hooks";
4
3
 
5
4
  import RvfLink from "../../../RvfLink";
6
5
  import getLinkByDevice from "../../../utils/getLinkByDevice";
6
+ import { fetchSharingStation } from "../../../utils/sharingGraphqlUtils";
7
7
  export interface StationDetailsProps {
8
8
  feature: Feature;
9
9
  }
10
10
 
11
- const document = gql`
12
- query station($id: String!) {
13
- station(id: $id) {
14
- name {
15
- translation {
16
- language
17
- value
18
- }
19
- }
20
- shortName {
21
- translation {
22
- language
23
- value
24
- }
25
- }
26
- lat
27
- lon
28
- region {
29
- id
30
- }
31
- rentalUris {
32
- android
33
- ios
34
- web
35
- }
36
- isVirtualStation
37
- rentalMethods
38
- parkingHoop
39
- parkingType
40
- contactPhone
41
- address
42
- rentalMethods
43
- capacity
44
- vehicleTypesAvailable {
45
- count
46
- vehicleType {
47
- id
48
- formFactor
49
- riderCapacity
50
- cargoVolumeCapacity
51
- cargoLoadCapacity
52
- propulsionType
53
- ecoLabels {
54
- countryCode
55
- ecoSticker
56
- }
57
- maxRangeMeters
58
- name {
59
- translation {
60
- language
61
- value
62
- }
63
- }
64
- description {
65
- translation {
66
- language
67
- value
68
- }
69
- }
70
- vehicleAccessories
71
- gCO2km
72
- vehicleImage
73
- make
74
- model
75
- color
76
- wheelCount
77
- maxPermittedSpeed
78
- ratedPower
79
- defaultReserveTime
80
- returnConstraint
81
- vehicleAssets {
82
- iconUrl
83
- iconUrlDark
84
- iconLastModified
85
- }
86
- defaultReserveTime
87
- defaultPricingPlan {
88
- id
89
- url
90
- currency
91
- isTaxable
92
- description {
93
- translation {
94
- language
95
- value
96
- }
97
- }
98
- perKmPricing {
99
- start
100
- rate
101
- interval
102
- end
103
- }
104
- perMinPricing {
105
- start
106
- rate
107
- interval
108
- end
109
- }
110
- surgePricing
111
- }
112
- }
113
- count
114
- }
115
- vehicleDocksCapacity {
116
- vehicleTypes {
117
- id
118
- }
119
- count
120
- }
121
- numVehiclesAvailable
122
- numDocksDisabled
123
- numVehiclesDisabled
124
- numDocksAvailable
125
- isInstalled
126
- isRenting
127
- isReturning
128
- pricingPlans {
129
- id
130
- url
131
- currency
132
- isTaxable
133
- description {
134
- translation {
135
- language
136
- value
137
- }
138
- }
139
- perKmPricing {
140
- start
141
- rate
142
- interval
143
- end
144
- }
145
- perMinPricing {
146
- start
147
- rate
148
- interval
149
- end
150
- }
151
- surgePricing
152
- }
153
- }
154
- }
155
- `;
156
- const client = new GraphQLClient("https://api.mobidata-bw.de/sharing/graphql", {
157
- method: "GET",
158
- });
159
-
160
11
  function StationDetails({ feature }: StationDetailsProps) {
161
12
  const [data, setData] = useState(null);
162
13
  const link = useMemo(() => {
@@ -167,15 +18,8 @@ function StationDetails({ feature }: StationDetailsProps) {
167
18
  const stationId = feature.get("station_id");
168
19
  if (stationId) {
169
20
  const fetchData = async () => {
170
- const { station }: { station: unknown } = await client.request(
171
- document,
172
- {
173
- __operation: "station",
174
- id: feature.get("station_id"),
175
- },
176
- );
21
+ const station = await fetchSharingStation(feature.get("station_id"));
177
22
  setData(station);
178
- // console.log(station);
179
23
  };
180
24
  fetchData();
181
25
  }
@@ -42,7 +42,7 @@ import RvfPoisLayer from "../RvfPoisLayer";
42
42
  import RvfSelectedFeatureHighlightLayer from "../RvfSelectedFeatureHighlightLayer";
43
43
  import RvfSellingPointsLayer from "../RvfSellingPointsLayer";
44
44
  import RvfShare from "../RvfShare";
45
- import RvfSharedMobilityLayerGroup from "../RvfSharedMobilityLayerGroup";
45
+ import RvfSharedMobilityLayerGroup2 from "../RvfSharedMobilityLayerGroup2";
46
46
  import RvfShareMenuButton from "../RvfShareMenuButton";
47
47
  import RvfTarifZonenLayer from "../RvfTarifZonenLayer";
48
48
  import Topics from "../RvfTopics";
@@ -55,7 +55,10 @@ import StationsLayer from "../StationsLayer";
55
55
  // @ts-expect-error bad type definition
56
56
  import tailwind from "../style.css";
57
57
  import { RVF_EXTENT_3857, RVF_LAYERS_TITLES } from "../utils/constants";
58
+ import getBgColor from "../utils/getBgColor";
58
59
  import getFeatureInformationTitle from "../utils/getFeatureInformationTitle";
60
+ import { getRadius } from "../utils/getRadius";
61
+ import getTextColor from "../utils/getTextColor";
59
62
  import { I18nContext } from "../utils/hooks/useI18n";
60
63
  import useInitialLayersVisiblity from "../utils/hooks/useInitialLayersVisiblity";
61
64
  import { MapContext } from "../utils/hooks/useMapContext";
@@ -63,10 +66,12 @@ import { RvfContext } from "../utils/hooks/useRvfContext";
63
66
  import useUpdatePermalink from "../utils/hooks/useUpdatePermalink";
64
67
  import i18n from "../utils/i18n";
65
68
  import MobilityEvent from "../utils/MobilityEvent";
69
+ import realtimeRVFStyle from "../utils/realtimeRVFStyle";
66
70
  // @ts-expect-error bad type definition
67
71
  import style from "./index.css";
68
72
 
69
73
  export type RvfMobilityMapProps = {
74
+ details: string;
70
75
  layers: string; // list of visible layers on load
71
76
  layertree: string;
72
77
  print: string;
@@ -89,11 +94,23 @@ const styleProps = {
89
94
  const scrollableHandlerProps = {
90
95
  style: { width: "calc(100% - 60px)" },
91
96
  };
97
+ const realtimeLayerProps = {
98
+ bboxParameters: {
99
+ line_tags: "RVF",
100
+ },
101
+ style: realtimeRVFStyle,
102
+ styleOptions: {
103
+ getBgColor: getBgColor,
104
+ getRadius: getRadius,
105
+ getTextColor: getTextColor,
106
+ },
107
+ };
92
108
 
93
109
  function RvfMobilityMap({
94
110
  apikey = "5cc87b12d7c5370001c1d655820abcc37dfd4d968d7bab5b2a74a935",
95
111
  baselayer = "de.rvf",
96
112
  center = null,
113
+ details = "true",
97
114
  extent = bbox,
98
115
  geolocation = "true",
99
116
  layers = null,
@@ -114,7 +131,7 @@ function RvfMobilityMap({
114
131
  search = "false",
115
132
  share = "true",
116
133
  stopsurl = "https://api.geops.io/stops/v1/",
117
- tenant = null,
134
+ tenant = "de-gtfs-de",
118
135
  toolbar = "true",
119
136
  zoom = null,
120
137
  }: RvfMobilityMapProps) {
@@ -176,6 +193,10 @@ function RvfMobilityMap({
176
193
  return print === "true";
177
194
  }, [print]);
178
195
 
196
+ const hasDetails = useMemo(() => {
197
+ return details === "true";
198
+ }, [details]);
199
+
179
200
  // Apply initial visibility of layers
180
201
  useInitialLayersVisiblity(map, layers);
181
202
 
@@ -265,6 +286,7 @@ function RvfMobilityMap({
265
286
  new MobilityEvent<RvfMobilityMapProps>("mwc:attribute", {
266
287
  baselayer,
267
288
  center,
289
+ details,
268
290
  extent,
269
291
  geolocation,
270
292
  layers,
@@ -312,6 +334,7 @@ function RvfMobilityMap({
312
334
  maxextent,
313
335
  print,
314
336
  share,
337
+ details,
315
338
  ]);
316
339
 
317
340
  const rvfContextValue = useMemo(() => {
@@ -462,7 +485,10 @@ function RvfMobilityMap({
462
485
  <RvfSelectedFeatureHighlightLayer />
463
486
 
464
487
  {hasRealtime && (
465
- <RealtimeLayer title={RVF_LAYERS_TITLES.echtzeit} />
488
+ <RealtimeLayer
489
+ title={RVF_LAYERS_TITLES.echtzeit}
490
+ {...realtimeLayerProps}
491
+ />
466
492
  )}
467
493
  {
468
494
  <StationsLayer
@@ -474,16 +500,16 @@ function RvfMobilityMap({
474
500
  {hasNotification && <NotificationLayer />}
475
501
  <RvfTarifZonenLayer title={RVF_LAYERS_TITLES.tarifzonen} />
476
502
  <RvfSellingPointsLayer
477
- isQueryable
503
+ isQueryable={false}
478
504
  title={RVF_LAYERS_TITLES.verkaufsstellen}
479
505
  />
480
506
  <RvfLineNetworkPlanLayer
481
- isQueryable
507
+ isQueryable={false}
482
508
  minZoom={10}
483
509
  title={RVF_LAYERS_TITLES.liniennetz}
484
510
  />
485
511
  <RvfPoisLayer title={RVF_LAYERS_TITLES.pois} />
486
- <RvfSharedMobilityLayerGroup
512
+ <RvfSharedMobilityLayerGroup2
487
513
  title={RVF_LAYERS_TITLES.sharedMobility}
488
514
  />
489
515
 
@@ -546,7 +572,7 @@ function RvfMobilityMap({
546
572
  <Station className="relative flex flex-col overflow-y-auto overflow-x-hidden p-2" />
547
573
  </>
548
574
  )}
549
- {selectedFeature && (
575
+ {hasDetails && selectedFeature && (
550
576
  <>
551
577
  <RvfOverlayHeader
552
578
  onClose={() => {
@@ -35,7 +35,6 @@ function SingleClickListener() {
35
35
  feature.setStyle(null);
36
36
  layer.getSource().addFeature(feature);
37
37
  if (vectorTileFeature) {
38
- console.log(vectorTileFeature);
39
38
  baseLayer?.mapLibreMap.setFeatureState(vectorTileFeature, {
40
39
  hover: true,
41
40
  });