@opentripplanner/vehicle-rental-overlay 1.4.0 → 1.4.3-alpha.1
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/esm/DefaultMarkers/index.js +3 -2
- package/esm/DefaultMarkers/index.js.map +1 -1
- package/esm/index.js +62 -24
- package/esm/index.js.map +1 -1
- package/i18n/en-US.yml +3 -0
- package/i18n/fr.yml +3 -0
- package/lib/DefaultMarkers/index.js +3 -3
- package/lib/DefaultMarkers/index.js.map +1 -1
- package/lib/index.js +61 -24
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/DefaultMarkers/index.js +3 -2
- package/src/VehicleRentalOverlay.story.js +9 -5
- package/src/index.js +73 -29
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { divIcon } from "leaflet";
|
|
2
2
|
import memoize from "lodash.memoize";
|
|
3
|
-
import coreUtils from "@opentripplanner/core-utils";
|
|
4
3
|
import PropTypes from "prop-types";
|
|
5
4
|
import React from "react";
|
|
6
5
|
import ReactDOMServer from "react-dom/server";
|
|
@@ -21,7 +20,9 @@ var templatePropTypes = {
|
|
|
21
20
|
children: PropTypes.node,
|
|
22
21
|
|
|
23
22
|
/** The rental vehicle or station to render. */
|
|
24
|
-
entity: coreUtils.types.stationType.isRequired,
|
|
23
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
24
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
25
|
+
entity: PropTypes.object.isRequired,
|
|
25
26
|
|
|
26
27
|
/** leaflet attribute to control tabindex value for keyboaryd-only / SR users */
|
|
27
28
|
keyboard: PropTypes.bool
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/DefaultMarkers/index.js"],"names":["divIcon","memoize","
|
|
1
|
+
{"version":3,"sources":["../../src/DefaultMarkers/index.js"],"names":["divIcon","memoize","PropTypes","React","ReactDOMServer","CircleMarker","Marker","floatingBikeIcon","hubIcons","Styled","templatePropTypes","children","node","entity","object","isRequired","keyboard","bool","templateDefaultProps","SharedBikeCircle","dockStrokeColor","fillColor","pixels","strokeColor","GeneratedMarker","station","newStrokeColor","isFloatingBike","y","x","propTypes","defaultProps","HubAndFloatingBike","icon","capacity","bikesAvailable","spacesAvailable","pctFull","i","Math","round","getStationMarkerByColor","color","className","iconSize","popupAnchor","html","renderToStaticMarkup","GenericMarker","markerIcon"],"mappings":"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","sourcesContent":["import { divIcon } from \"leaflet\";\nimport memoize from \"lodash.memoize\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport ReactDOMServer from \"react-dom/server\";\nimport { CircleMarker, Marker } from \"react-leaflet\";\n\nimport { floatingBikeIcon, hubIcons } from \"../bike-icons\";\nimport * as Styled from \"../styled\";\n\n/**\n * This file contains default marker types for rental vehicles,\n * that can be used when defining the VehicleRentalOverlay's symbol prop:\n * - SharedBikeCircle\n * - GenericMarker\n * - HubAndFloatingBike\n */\n\n// Prop types reused across components.\nconst templatePropTypes = {\n /** The children of the component. */\n children: PropTypes.node,\n /** The rental vehicle or station to render. */\n // entity: coreUtils.types.stationType.isRequired,\n // eslint-disable-next-line react/forbid-prop-types\n entity: PropTypes.object.isRequired,\n /** leaflet attribute to control tabindex value for keyboaryd-only / SR users */\n keyboard: PropTypes.bool\n};\nconst templateDefaultProps = {\n children: null,\n keyboard: false\n};\n\n/**\n * Renders a shared bike or shared bike dock as a circle\n * with predefined colors and size.\n */\nexport const SharedBikeCircle = ({\n dockStrokeColor,\n fillColor = \"gray\",\n pixels,\n strokeColor\n}) => {\n const GeneratedMarker = ({ children, keyboard, entity: station }) => {\n let newStrokeColor = strokeColor || fillColor;\n\n if (!station.isFloatingBike) {\n newStrokeColor = dockStrokeColor || strokeColor;\n }\n\n return (\n <CircleMarker\n center={[station.y, station.x]}\n color={newStrokeColor}\n fillColor={fillColor}\n fillOpacity={1}\n keyboard={keyboard}\n radius={pixels - (station.isFloatingBike ? 1 : 0)}\n weight={1}\n >\n {children}\n </CircleMarker>\n );\n };\n\n GeneratedMarker.propTypes = templatePropTypes;\n GeneratedMarker.defaultProps = templateDefaultProps;\n return GeneratedMarker;\n};\n\n/**\n * A component that renders rental bike entities\n * either as a bike or a bike dock (or hub, showing spaces available).\n */\nexport const HubAndFloatingBike = ({ children, keyboard, entity: station }) => {\n let icon;\n if (station.isFloatingBike) {\n icon = floatingBikeIcon;\n } else {\n const capacity = station.bikesAvailable + station.spacesAvailable;\n if (capacity === 0) return null;\n const pctFull = station.bikesAvailable / capacity;\n const i = Math.round(pctFull * 9);\n icon = hubIcons[i];\n }\n return (\n <Marker icon={icon} keyboard={keyboard} position={[station.y, station.x]}>\n {children}\n </Marker>\n );\n};\nHubAndFloatingBike.propTypes = templatePropTypes;\nHubAndFloatingBike.defaultProps = templateDefaultProps;\n\n/**\n * Creates and caches a leaflet element icon based on color.\n */\nconst getStationMarkerByColor = memoize(color =>\n divIcon({\n className: \"\",\n iconSize: [11, 16],\n popupAnchor: [0, -6],\n html: ReactDOMServer.renderToStaticMarkup(\n <Styled.StationMarker color={color} />\n )\n })\n);\n\n/**\n * Helper function to create a leaflet Marker component to render entities\n * using fixed fill color.\n * Usage: GenericMarker({ fillColor: \"#F204B5\" })\n */\nexport const GenericMarker = ({ fillColor = \"gray\" }) => {\n const markerIcon = getStationMarkerByColor(fillColor);\n\n const GeneratedMarker = ({ children, keyboard, entity: station }) => (\n <Marker\n icon={markerIcon}\n keyboard={keyboard}\n position={[station.y, station.x]}\n >\n {children}\n </Marker>\n );\n GeneratedMarker.propTypes = templatePropTypes;\n GeneratedMarker.defaultProps = templateDefaultProps;\n return GeneratedMarker;\n};\n"],"file":"index.js"}
|
package/esm/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import FromToLocationPicker from "@opentripplanner/from-to-location-picker";
|
|
|
15
15
|
import ZoomBasedMarkers from "@opentripplanner/zoom-based-markers";
|
|
16
16
|
import PropTypes from "prop-types";
|
|
17
17
|
import React from "react";
|
|
18
|
-
import { FormattedMessage } from "react-intl";
|
|
18
|
+
import { FormattedMessage, injectIntl } from "react-intl";
|
|
19
19
|
import { FeatureGroup, MapLayer, Popup, withLeaflet } from "react-leaflet";
|
|
20
20
|
import { GenericMarker, HubAndFloatingBike, SharedBikeCircle } from "./DefaultMarkers"; // Load the default messages.
|
|
21
21
|
|
|
@@ -25,12 +25,55 @@ import defaultEnglishMessages from "../i18n/en-US.yml"; // HACK: We should flatt
|
|
|
25
25
|
// - the yaml loader for jest returns messages with flattened ids.
|
|
26
26
|
|
|
27
27
|
var defaultMessages = flatten(defaultEnglishMessages);
|
|
28
|
+
|
|
29
|
+
function makeDefaultGetStationName(intl) {
|
|
30
|
+
return function defaultGetStationName(configCompanies, station) {
|
|
31
|
+
var stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(station.networks, configCompanies);
|
|
32
|
+
var stationName = station.name || station.id; // If the station name or id is a giant UUID (with more than 3 "-" characters)
|
|
33
|
+
// best not to show that at all and instead use the network name.
|
|
34
|
+
|
|
35
|
+
if ((stationName.match(/-/g) || []).length > 3) {
|
|
36
|
+
stationName = stationNetworks;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (station.isFloatingBike) {
|
|
40
|
+
stationName = intl.formatMessage({
|
|
41
|
+
defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingBike"],
|
|
42
|
+
description: "Popup title for a free-floating bike",
|
|
43
|
+
id: "otpUi.VehicleRentalOverlay.floatingBike"
|
|
44
|
+
}, {
|
|
45
|
+
name: stationName
|
|
46
|
+
});
|
|
47
|
+
} else if (station.isFloatingCar) {
|
|
48
|
+
stationName = intl.formatMessage({
|
|
49
|
+
defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingCar"],
|
|
50
|
+
description: "Popup title for a free-floating car",
|
|
51
|
+
id: "otpUi.VehicleRentalOverlay.floatingCar"
|
|
52
|
+
}, {
|
|
53
|
+
company: stationNetworks,
|
|
54
|
+
name: stationName
|
|
55
|
+
});
|
|
56
|
+
} else if (station.isFloatingVehicle) {
|
|
57
|
+
// assumes that all floating vehicles are E-scooters
|
|
58
|
+
stationName = intl.formatMessage({
|
|
59
|
+
defaultMessage: defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingEScooter"],
|
|
60
|
+
description: "Popup title for a free-floating e-scooter",
|
|
61
|
+
id: "otpUi.VehicleRentalOverlay.floatingEScooter"
|
|
62
|
+
}, {
|
|
63
|
+
company: stationNetworks
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return stationName;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
28
70
|
/**
|
|
29
71
|
* This vehicle rental overlay can be used to render vehicle rentals of various
|
|
30
72
|
* types. This layer can be configured to show different styles of markers at
|
|
31
73
|
* different zoom levels.
|
|
32
74
|
*/
|
|
33
75
|
|
|
76
|
+
|
|
34
77
|
var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
35
78
|
_inherits(VehicleRentalOverlay, _MapLayer);
|
|
36
79
|
|
|
@@ -54,7 +97,7 @@ var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
|
54
97
|
};
|
|
55
98
|
|
|
56
99
|
SymbolWrapper.propTypes = {
|
|
57
|
-
entity: coreUtils.types.stationType.isRequired,
|
|
100
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
58
101
|
zoom: PropTypes.number.isRequired
|
|
59
102
|
};
|
|
60
103
|
return SymbolWrapper;
|
|
@@ -113,8 +156,10 @@ var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
|
113
156
|
var _this$props = _this.props,
|
|
114
157
|
configCompanies = _this$props.configCompanies,
|
|
115
158
|
getStationName = _this$props.getStationName,
|
|
159
|
+
intl = _this$props.intl,
|
|
116
160
|
setLocation = _this$props.setLocation;
|
|
117
|
-
var
|
|
161
|
+
var getStationNameFunc = getStationName || makeDefaultGetStationName(intl);
|
|
162
|
+
var stationName = getStationNameFunc(configCompanies, station);
|
|
118
163
|
var location = {
|
|
119
164
|
lat: station.y,
|
|
120
165
|
lon: station.x,
|
|
@@ -142,7 +187,7 @@ var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
|
142
187
|
};
|
|
143
188
|
|
|
144
189
|
_this.state = {
|
|
145
|
-
zoom:
|
|
190
|
+
zoom: null
|
|
146
191
|
};
|
|
147
192
|
return _this;
|
|
148
193
|
}
|
|
@@ -193,8 +238,12 @@ var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
|
193
238
|
*/
|
|
194
239
|
function componentDidMount() {
|
|
195
240
|
var _this$props2 = this.props,
|
|
241
|
+
leaflet = _this$props2.leaflet,
|
|
196
242
|
registerOverlay = _this$props2.registerOverlay,
|
|
197
243
|
visible = _this$props2.visible;
|
|
244
|
+
this.setState({
|
|
245
|
+
zoom: leaflet.map.getZoom()
|
|
246
|
+
});
|
|
198
247
|
if (visible) this.startRefreshing();
|
|
199
248
|
|
|
200
249
|
if (typeof registerOverlay === "function") {
|
|
@@ -217,9 +266,11 @@ var VehicleRentalOverlay = /*#__PURE__*/function (_MapLayer) {
|
|
|
217
266
|
value: function render() {
|
|
218
267
|
var _this$props3 = this.props,
|
|
219
268
|
companies = _this$props3.companies,
|
|
269
|
+
leaflet = _this$props3.leaflet,
|
|
220
270
|
mapSymbols = _this$props3.mapSymbols,
|
|
221
271
|
stations = _this$props3.stations;
|
|
222
|
-
var zoom = this.state.zoom
|
|
272
|
+
var _this$state$zoom = this.state.zoom,
|
|
273
|
+
zoom = _this$state$zoom === void 0 ? leaflet.map.getZoom() : _this$state$zoom; // Render an empty FeatureGroup if the rental vehicles should not be visible
|
|
223
274
|
// on the map. Otherwise previous stations may still be shown due to some
|
|
224
275
|
// react-leaflet internals, maybe? Also, do not return null because that will
|
|
225
276
|
// prevent the overlay from appearing in the layer controls.
|
|
@@ -256,7 +307,8 @@ VehicleRentalOverlay.props = {
|
|
|
256
307
|
/**
|
|
257
308
|
* The entire companies config array.
|
|
258
309
|
*/
|
|
259
|
-
configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
|
|
310
|
+
// configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
|
|
311
|
+
// .isRequired,
|
|
260
312
|
|
|
261
313
|
/**
|
|
262
314
|
* A list of companies that are applicable to just this instance of the
|
|
@@ -275,7 +327,7 @@ VehicleRentalOverlay.props = {
|
|
|
275
327
|
* A configuration of what map markers or symbols to show at various
|
|
276
328
|
* zoom levels.
|
|
277
329
|
*/
|
|
278
|
-
mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
330
|
+
// mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
279
331
|
|
|
280
332
|
/**
|
|
281
333
|
* If specified, a function that will be triggered every 30 seconds whenever this layer is
|
|
@@ -305,7 +357,7 @@ VehicleRentalOverlay.props = {
|
|
|
305
357
|
/**
|
|
306
358
|
* A list of the vehicle rental stations specific to this overlay instance.
|
|
307
359
|
*/
|
|
308
|
-
stations: PropTypes.arrayOf(coreUtils.types.stationType),
|
|
360
|
+
// stations: PropTypes.arrayOf(coreUtils.types.stationType),
|
|
309
361
|
|
|
310
362
|
/**
|
|
311
363
|
* Whether the overlay is currently visible.
|
|
@@ -313,21 +365,7 @@ VehicleRentalOverlay.props = {
|
|
|
313
365
|
visible: PropTypes.bool
|
|
314
366
|
};
|
|
315
367
|
VehicleRentalOverlay.defaultProps = {
|
|
316
|
-
getStationName:
|
|
317
|
-
var stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(station.networks, configCompanies);
|
|
318
|
-
var stationName = station.name || station.id;
|
|
319
|
-
|
|
320
|
-
if (station.isFloatingBike) {
|
|
321
|
-
stationName = "Free-floating bike: ".concat(stationName);
|
|
322
|
-
} else if (station.isFloatingCar) {
|
|
323
|
-
stationName = "".concat(stationNetworks, " ").concat(stationName);
|
|
324
|
-
} else if (station.isFloatingVehicle) {
|
|
325
|
-
// assumes that all floating vehicles are E-scooters
|
|
326
|
-
stationName = "".concat(stationNetworks, " E-scooter");
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
return stationName;
|
|
330
|
-
},
|
|
368
|
+
getStationName: null,
|
|
331
369
|
mapSymbols: [{
|
|
332
370
|
zoom: 0,
|
|
333
371
|
symbol: GenericMarker
|
|
@@ -336,5 +374,5 @@ VehicleRentalOverlay.defaultProps = {
|
|
|
336
374
|
stations: [],
|
|
337
375
|
visible: false
|
|
338
376
|
};
|
|
339
|
-
export default withLeaflet(VehicleRentalOverlay);
|
|
377
|
+
export default withLeaflet(injectIntl(VehicleRentalOverlay));
|
|
340
378
|
//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["flatten","Styled","BaseMapStyled","coreUtils","FromToLocationPicker","ZoomBasedMarkers","PropTypes","React","FormattedMessage","FeatureGroup","MapLayer","Popup","withLeaflet","GenericMarker","HubAndFloatingBike","SharedBikeCircle","defaultEnglishMessages","defaultMessages","VehicleRentalOverlay","props","renderSymbolWithPopup","Symbol","SymbolWrapper","station","entity","zoom","renderPopupForStation","bikesAvailable","undefined","isFloatingBike","propTypes","types","stationType","isRequired","number","convertToZoomMarkerSymbols","mapSymbols","map","mapSymbol","symbol","type","minZoom","onOverlayAdded","startRefreshing","onOverlayRemoved","stopRefreshing","onViewportChanged","viewport","newZoom","state","setState","stationIsHub","configCompanies","getStationName","setLocation","stationName","location","lat","y","lon","x","name","value","spacesAvailable","leaflet","getZoom","refreshVehicles","refreshTimer","setInterval","clearInterval","registerOverlay","visible","companies","stations","filteredStations","filter","networks","includes","length","symbols","arrayOf","companyType","string","func","vehicleRentalMapOverlaySymbolsType","bool","defaultProps","stationNetworks","itinerary","getCompaniesLabelFromNetworks","id","isFloatingCar","isFloatingVehicle"],"mappings":"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","sourcesContent":["import flatten from \"flat\";\nimport { Styled as BaseMapStyled } from \"@opentripplanner/base-map\";\nimport coreUtils from \"@opentripplanner/core-utils\";\nimport FromToLocationPicker from \"@opentripplanner/from-to-location-picker\";\nimport ZoomBasedMarkers from \"@opentripplanner/zoom-based-markers\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport { FormattedMessage } from \"react-intl\";\nimport { FeatureGroup, MapLayer, Popup, withLeaflet } from \"react-leaflet\";\n\nimport {\n GenericMarker,\n HubAndFloatingBike,\n SharedBikeCircle\n} from \"./DefaultMarkers\";\n\n// Load the default messages.\nimport defaultEnglishMessages from \"../i18n/en-US.yml\";\n\n// HACK: We should flatten the messages loaded above because\n// the YAML loaders behave differently between webpack and our version of jest:\n// - the yaml loader for webpack returns a nested object,\n// - the yaml loader for jest returns messages with flattened ids.\nconst defaultMessages = flatten(defaultEnglishMessages);\n\n/**\n * This vehicle rental overlay can be used to render vehicle rentals of various\n * types. This layer can be configured to show different styles of markers at\n * different zoom levels.\n */\nclass VehicleRentalOverlay extends MapLayer {\n constructor(props) {\n super(props);\n this.state = {\n zoom: props.leaflet.map.getZoom()\n };\n }\n\n /**\n * This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.\n * It creates a component that inserts a popup\n * as a child of the specified symbol from the mapSymbols prop.\n */\n renderSymbolWithPopup = Symbol => {\n const SymbolWrapper = ({ entity: station, zoom }) => (\n <Symbol entity={station} zoom={zoom}>\n {this.renderPopupForStation(\n station,\n station.bikesAvailable !== undefined && !station.isFloatingBike\n )}\n </Symbol>\n );\n SymbolWrapper.propTypes = {\n entity: coreUtils.types.stationType.isRequired,\n zoom: PropTypes.number.isRequired\n };\n\n return SymbolWrapper;\n };\n\n /**\n * Convert map symbols to zoomBasedSymbolType.\n */\n convertToZoomMarkerSymbols = mapSymbols =>\n mapSymbols.map(mapSymbol => {\n // If mapSymbol uses zoomBasedSymbolType, use it as is.\n if (mapSymbol.symbol) {\n return mapSymbol;\n }\n\n // Otherwise, convert into zoomBasedType (no support for symbols by type).\n let symbol;\n switch (mapSymbol.type) {\n case \"circle\":\n symbol = SharedBikeCircle(mapSymbol);\n break;\n case \"hubAndFloatingBike\":\n symbol = HubAndFloatingBike;\n break;\n default:\n symbol = GenericMarker(mapSymbol);\n }\n\n return {\n minZoom: mapSymbol.minZoom,\n symbol\n };\n });\n\n createLeafletElement() {}\n\n updateLeafletElement() {}\n\n startRefreshing() {\n const { refreshVehicles } = this.props;\n\n // Create the timer only if refreshVehicles is a valid function.\n if (typeof refreshVehicles === \"function\") {\n // initial station retrieval\n refreshVehicles();\n\n // set up timer to refresh stations periodically\n this.refreshTimer = setInterval(() => {\n refreshVehicles();\n }, 30000); // defaults to every 30 sec. TODO: make this configurable?\n }\n }\n\n stopRefreshing() {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n }\n\n /**\n * When the layer is added (or toggled on, or its visibility becomes true),\n * start refreshing vehicle positions.\n */\n onOverlayAdded = () => {\n this.startRefreshing();\n };\n\n /**\n * When the layer is removed (or toggled off, or its visibility becomes false),\n * stop refreshing vehicle positions.\n */\n onOverlayRemoved = () => {\n this.stopRefreshing();\n };\n\n /**\n * Listen to changes on the BaseMap's center or zoom.\n * @param viewport The viewport data. See https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js for details.\n */\n onViewportChanged = viewport => {\n const { zoom: newZoom } = viewport;\n if (this.state.zoom !== newZoom) {\n this.setState({ zoom: newZoom });\n }\n };\n\n /**\n * Upon mounting, see whether the vehicles should be fetched,\n * and also call the register overlay prop that the\n * @opentripplanner/base-map package has injected to listen to zoom/position changes.\n */\n componentDidMount() {\n const { registerOverlay, visible } = this.props;\n if (visible) this.startRefreshing();\n if (typeof registerOverlay === \"function\") {\n registerOverlay(this);\n }\n }\n\n componentWillUnmount() {\n this.stopRefreshing();\n }\n\n /**\n * Render some popup html for a station. This contains custom logic for\n * displaying rental vehicles in the TriMet MOD website that might not be\n * applicable to other regions.\n */\n renderPopupForStation = (station, stationIsHub = false) => {\n const { configCompanies, getStationName, setLocation } = this.props;\n const stationName = getStationName(configCompanies, station);\n const location = {\n lat: station.y,\n lon: station.x,\n name: stationName\n };\n return (\n <Popup>\n <BaseMapStyled.MapOverlayPopup>\n <BaseMapStyled.PopupTitle>{stationName}</BaseMapStyled.PopupTitle>\n\n {/* render dock info if it is available */}\n {stationIsHub && (\n <BaseMapStyled.PopupRow>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableBikes\"]\n }\n description=\"Label text for the number of bikes available\"\n id=\"otpUi.VehicleRentalOverlay.availableBikes\"\n values={{ value: station.bikesAvailable }}\n />\n </div>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableDocks\"]\n }\n description=\"Label text for the number of docks available\"\n id=\"otpUi.VehicleRentalOverlay.availableDocks\"\n values={{ value: station.spacesAvailable }}\n />\n </div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <FromToLocationPicker\n label\n location={location}\n setLocation={setLocation}\n />\n </BaseMapStyled.PopupRow>\n </BaseMapStyled.MapOverlayPopup>\n </Popup>\n );\n };\n\n render() {\n const { companies, mapSymbols, stations } = this.props;\n const { zoom } = this.state;\n // Render an empty FeatureGroup if the rental vehicles should not be visible\n // on the map. Otherwise previous stations may still be shown due to some\n // react-leaflet internals, maybe? Also, do not return null because that will\n // prevent the overlay from appearing in the layer controls.\n\n let filteredStations = stations;\n if (companies) {\n filteredStations = stations.filter(\n station =>\n station.networks.filter(value => companies.includes(value)).length > 0\n );\n }\n\n if (!filteredStations || filteredStations.length === 0) {\n return <FeatureGroup />;\n }\n\n // Convert map symbols for this overlay to zoomBasedSymbolType.\n const symbols = this.convertToZoomMarkerSymbols(mapSymbols);\n\n return (\n <FeatureGroup>\n <ZoomBasedMarkers\n entities={filteredStations}\n symbols={symbols}\n symbolTransform={this.renderSymbolWithPopup}\n zoom={zoom}\n />\n </FeatureGroup>\n );\n }\n}\n\nVehicleRentalOverlay.props = {\n /**\n * The entire companies config array.\n */\n configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)\n .isRequired,\n /**\n * A list of companies that are applicable to just this instance of the\n * overlay.\n */\n companies: PropTypes.arrayOf(PropTypes.string.isRequired),\n /**\n * An optional custom function to create a string name of a particular vehicle\n * rental station. This function takes two arguments of the configCompanies\n * prop and a vehicle rental station. The function must return a string.\n */\n getStationName: PropTypes.func,\n /**\n * A configuration of what map markers or symbols to show at various\n * zoom levels.\n */\n mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,\n /**\n * If specified, a function that will be triggered every 30 seconds whenever this layer is\n * visible.\n */\n refreshVehicles: PropTypes.func,\n /**\n * A callback for when a user clicks on setting this stop as either the from\n * or to location of a new search.\n *\n * This will be dispatched with the following argument:\n *\n * ```js\n * {\n * location: {\n * lat: number,\n * lon: number,\n * name: string\n * },\n * locationType: \"from\" or \"to\"\n * }\n * ```\n */\n setLocation: PropTypes.func.isRequired,\n /**\n * A list of the vehicle rental stations specific to this overlay instance.\n */\n stations: PropTypes.arrayOf(coreUtils.types.stationType),\n /**\n * Whether the overlay is currently visible.\n */\n visible: PropTypes.bool\n};\n\nVehicleRentalOverlay.defaultProps = {\n getStationName: (configCompanies, station) => {\n const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(\n station.networks,\n configCompanies\n );\n let stationName = station.name || station.id;\n if (station.isFloatingBike) {\n stationName = `Free-floating bike: ${stationName}`;\n } else if (station.isFloatingCar) {\n stationName = `${stationNetworks} ${stationName}`;\n } else if (station.isFloatingVehicle) {\n // assumes that all floating vehicles are E-scooters\n stationName = `${stationNetworks} E-scooter`;\n }\n return stationName;\n },\n mapSymbols: [\n {\n zoom: 0,\n symbol: GenericMarker\n }\n ],\n refreshVehicles: null,\n stations: [],\n visible: false\n};\n\nexport default withLeaflet(VehicleRentalOverlay);\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["flatten","Styled","BaseMapStyled","coreUtils","FromToLocationPicker","ZoomBasedMarkers","PropTypes","React","FormattedMessage","injectIntl","FeatureGroup","MapLayer","Popup","withLeaflet","GenericMarker","HubAndFloatingBike","SharedBikeCircle","defaultEnglishMessages","defaultMessages","makeDefaultGetStationName","intl","defaultGetStationName","configCompanies","station","stationNetworks","itinerary","getCompaniesLabelFromNetworks","networks","stationName","name","id","match","length","isFloatingBike","formatMessage","defaultMessage","description","isFloatingCar","company","isFloatingVehicle","VehicleRentalOverlay","props","renderSymbolWithPopup","Symbol","SymbolWrapper","entity","zoom","renderPopupForStation","bikesAvailable","undefined","propTypes","number","isRequired","convertToZoomMarkerSymbols","mapSymbols","map","mapSymbol","symbol","type","minZoom","onOverlayAdded","startRefreshing","onOverlayRemoved","stopRefreshing","onViewportChanged","viewport","newZoom","state","setState","stationIsHub","getStationName","setLocation","getStationNameFunc","location","lat","y","lon","x","value","spacesAvailable","refreshVehicles","refreshTimer","setInterval","clearInterval","leaflet","registerOverlay","visible","getZoom","companies","stations","filteredStations","filter","includes","symbols","arrayOf","string","func","bool","defaultProps"],"mappings":"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","sourcesContent":["import flatten from \"flat\";\nimport { Styled as BaseMapStyled } from \"@opentripplanner/base-map\";\nimport coreUtils from \"@opentripplanner/core-utils\";\nimport FromToLocationPicker from \"@opentripplanner/from-to-location-picker\";\nimport ZoomBasedMarkers from \"@opentripplanner/zoom-based-markers\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport { FormattedMessage, injectIntl } from \"react-intl\";\nimport { FeatureGroup, MapLayer, Popup, withLeaflet } from \"react-leaflet\";\n\nimport {\n GenericMarker,\n HubAndFloatingBike,\n SharedBikeCircle\n} from \"./DefaultMarkers\";\n\n// Load the default messages.\nimport defaultEnglishMessages from \"../i18n/en-US.yml\";\n\n// HACK: We should flatten the messages loaded above because\n// the YAML loaders behave differently between webpack and our version of jest:\n// - the yaml loader for webpack returns a nested object,\n// - the yaml loader for jest returns messages with flattened ids.\nconst defaultMessages = flatten(defaultEnglishMessages);\n\nfunction makeDefaultGetStationName(intl) {\n return function defaultGetStationName(configCompanies, station) {\n const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(\n station.networks,\n configCompanies\n );\n let stationName = station.name || station.id;\n // If the station name or id is a giant UUID (with more than 3 \"-\" characters)\n // best not to show that at all and instead use the network name.\n if ((stationName.match(/-/g) || []).length > 3) {\n stationName = stationNetworks;\n }\n\n if (station.isFloatingBike) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingBike\"],\n description: \"Popup title for a free-floating bike\",\n id: \"otpUi.VehicleRentalOverlay.floatingBike\"\n },\n { name: stationName }\n );\n } else if (station.isFloatingCar) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingCar\"],\n description: \"Popup title for a free-floating car\",\n id: \"otpUi.VehicleRentalOverlay.floatingCar\"\n },\n {\n company: stationNetworks,\n name: stationName\n }\n );\n } else if (station.isFloatingVehicle) {\n // assumes that all floating vehicles are E-scooters\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\n \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n ],\n description: \"Popup title for a free-floating e-scooter\",\n id: \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n },\n { company: stationNetworks }\n );\n }\n return stationName;\n };\n}\n\n/**\n * This vehicle rental overlay can be used to render vehicle rentals of various\n * types. This layer can be configured to show different styles of markers at\n * different zoom levels.\n */\nclass VehicleRentalOverlay extends MapLayer {\n constructor(props) {\n super(props);\n this.state = {\n zoom: null\n };\n }\n\n /**\n * This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.\n * It creates a component that inserts a popup\n * as a child of the specified symbol from the mapSymbols prop.\n */\n renderSymbolWithPopup = Symbol => {\n const SymbolWrapper = ({ entity: station, zoom }) => (\n <Symbol entity={station} zoom={zoom}>\n {this.renderPopupForStation(\n station,\n station.bikesAvailable !== undefined && !station.isFloatingBike\n )}\n </Symbol>\n );\n SymbolWrapper.propTypes = {\n // entity: coreUtils.types.stationType.isRequired,\n zoom: PropTypes.number.isRequired\n };\n\n return SymbolWrapper;\n };\n\n /**\n * Convert map symbols to zoomBasedSymbolType.\n */\n convertToZoomMarkerSymbols = mapSymbols =>\n mapSymbols.map(mapSymbol => {\n // If mapSymbol uses zoomBasedSymbolType, use it as is.\n if (mapSymbol.symbol) {\n return mapSymbol;\n }\n\n // Otherwise, convert into zoomBasedType (no support for symbols by type).\n let symbol;\n switch (mapSymbol.type) {\n case \"circle\":\n symbol = SharedBikeCircle(mapSymbol);\n break;\n case \"hubAndFloatingBike\":\n symbol = HubAndFloatingBike;\n break;\n default:\n symbol = GenericMarker(mapSymbol);\n }\n\n return {\n minZoom: mapSymbol.minZoom,\n symbol\n };\n });\n\n createLeafletElement() {}\n\n updateLeafletElement() {}\n\n startRefreshing() {\n const { refreshVehicles } = this.props;\n\n // Create the timer only if refreshVehicles is a valid function.\n if (typeof refreshVehicles === \"function\") {\n // initial station retrieval\n refreshVehicles();\n\n // set up timer to refresh stations periodically\n this.refreshTimer = setInterval(() => {\n refreshVehicles();\n }, 30000); // defaults to every 30 sec. TODO: make this configurable?\n }\n }\n\n stopRefreshing() {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n }\n\n /**\n * When the layer is added (or toggled on, or its visibility becomes true),\n * start refreshing vehicle positions.\n */\n onOverlayAdded = () => {\n this.startRefreshing();\n };\n\n /**\n * When the layer is removed (or toggled off, or its visibility becomes false),\n * stop refreshing vehicle positions.\n */\n onOverlayRemoved = () => {\n this.stopRefreshing();\n };\n\n /**\n * Listen to changes on the BaseMap's center or zoom.\n * @param viewport The viewport data. See https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js for details.\n */\n onViewportChanged = viewport => {\n const { zoom: newZoom } = viewport;\n if (this.state.zoom !== newZoom) {\n this.setState({ zoom: newZoom });\n }\n };\n\n /**\n * Upon mounting, see whether the vehicles should be fetched,\n * and also call the register overlay prop that the\n * @opentripplanner/base-map package has injected to listen to zoom/position changes.\n */\n componentDidMount() {\n const { leaflet, registerOverlay, visible } = this.props;\n this.setState({\n zoom: leaflet.map.getZoom()\n });\n if (visible) this.startRefreshing();\n if (typeof registerOverlay === \"function\") {\n registerOverlay(this);\n }\n }\n\n componentWillUnmount() {\n this.stopRefreshing();\n }\n\n /**\n * Render some popup html for a station. This contains custom logic for\n * displaying rental vehicles in the TriMet MOD website that might not be\n * applicable to other regions.\n */\n renderPopupForStation = (station, stationIsHub = false) => {\n const { configCompanies, getStationName, intl, setLocation } = this.props;\n const getStationNameFunc =\n getStationName || makeDefaultGetStationName(intl);\n const stationName = getStationNameFunc(configCompanies, station);\n const location = {\n lat: station.y,\n lon: station.x,\n name: stationName\n };\n return (\n <Popup>\n <BaseMapStyled.MapOverlayPopup>\n <BaseMapStyled.PopupTitle>{stationName}</BaseMapStyled.PopupTitle>\n\n {/* render dock info if it is available */}\n {stationIsHub && (\n <BaseMapStyled.PopupRow>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableBikes\"]\n }\n description=\"Label text for the number of bikes available\"\n id=\"otpUi.VehicleRentalOverlay.availableBikes\"\n values={{ value: station.bikesAvailable }}\n />\n </div>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableDocks\"]\n }\n description=\"Label text for the number of docks available\"\n id=\"otpUi.VehicleRentalOverlay.availableDocks\"\n values={{ value: station.spacesAvailable }}\n />\n </div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <FromToLocationPicker\n label\n location={location}\n setLocation={setLocation}\n />\n </BaseMapStyled.PopupRow>\n </BaseMapStyled.MapOverlayPopup>\n </Popup>\n );\n };\n\n render() {\n const { companies, leaflet, mapSymbols, stations } = this.props;\n const { zoom = leaflet.map.getZoom() } = this.state;\n // Render an empty FeatureGroup if the rental vehicles should not be visible\n // on the map. Otherwise previous stations may still be shown due to some\n // react-leaflet internals, maybe? Also, do not return null because that will\n // prevent the overlay from appearing in the layer controls.\n\n let filteredStations = stations;\n if (companies) {\n filteredStations = stations.filter(\n station =>\n station.networks.filter(value => companies.includes(value)).length > 0\n );\n }\n\n if (!filteredStations || filteredStations.length === 0) {\n return <FeatureGroup />;\n }\n\n // Convert map symbols for this overlay to zoomBasedSymbolType.\n const symbols = this.convertToZoomMarkerSymbols(mapSymbols);\n\n return (\n <FeatureGroup>\n <ZoomBasedMarkers\n entities={filteredStations}\n symbols={symbols}\n symbolTransform={this.renderSymbolWithPopup}\n zoom={zoom}\n />\n </FeatureGroup>\n );\n }\n}\n\nVehicleRentalOverlay.props = {\n /**\n * The entire companies config array.\n */\n // configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)\n // .isRequired,\n /**\n * A list of companies that are applicable to just this instance of the\n * overlay.\n */\n companies: PropTypes.arrayOf(PropTypes.string.isRequired),\n /**\n * An optional custom function to create a string name of a particular vehicle\n * rental station. This function takes two arguments of the configCompanies\n * prop and a vehicle rental station. The function must return a string.\n */\n getStationName: PropTypes.func,\n /**\n * A configuration of what map markers or symbols to show at various\n * zoom levels.\n */\n // mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,\n /**\n * If specified, a function that will be triggered every 30 seconds whenever this layer is\n * visible.\n */\n refreshVehicles: PropTypes.func,\n /**\n * A callback for when a user clicks on setting this stop as either the from\n * or to location of a new search.\n *\n * This will be dispatched with the following argument:\n *\n * ```js\n * {\n * location: {\n * lat: number,\n * lon: number,\n * name: string\n * },\n * locationType: \"from\" or \"to\"\n * }\n * ```\n */\n setLocation: PropTypes.func.isRequired,\n /**\n * A list of the vehicle rental stations specific to this overlay instance.\n */\n // stations: PropTypes.arrayOf(coreUtils.types.stationType),\n /**\n * Whether the overlay is currently visible.\n */\n visible: PropTypes.bool\n};\n\nVehicleRentalOverlay.defaultProps = {\n getStationName: null,\n mapSymbols: [\n {\n zoom: 0,\n symbol: GenericMarker\n }\n ],\n refreshVehicles: null,\n stations: [],\n visible: false\n};\n\nexport default withLeaflet(injectIntl(VehicleRentalOverlay));\n"],"file":"index.js"}
|
package/i18n/en-US.yml
CHANGED
|
@@ -12,3 +12,6 @@ otpUi:
|
|
|
12
12
|
VehicleRentalOverlay:
|
|
13
13
|
availableBikes: "Available bikes: {value}"
|
|
14
14
|
availableDocks: "Available docks: {value}"
|
|
15
|
+
floatingBike: "Free-floating bike: {name}"
|
|
16
|
+
floatingCar: "{company} {name}" # as in "CarCompany Veh1234a"
|
|
17
|
+
floatingEScooter: "{company} E-scooter"
|
package/i18n/fr.yml
CHANGED
|
@@ -12,3 +12,6 @@ otpUi:
|
|
|
12
12
|
VehicleRentalOverlay:
|
|
13
13
|
availableBikes: "Vélos disponibles : {value}"
|
|
14
14
|
availableDocks: "Bornes disponibles : {value}"
|
|
15
|
+
floatingBike: "Vélo flottant : {name}"
|
|
16
|
+
floatingCar: "{company} {name}" # as in "CarCompany Veh1234a"
|
|
17
|
+
floatingEScooter: "Trottinette {company}"
|
|
@@ -11,8 +11,6 @@ var _leaflet = require("leaflet");
|
|
|
11
11
|
|
|
12
12
|
var _lodash = _interopRequireDefault(require("lodash.memoize"));
|
|
13
13
|
|
|
14
|
-
var _coreUtils = _interopRequireDefault(require("@opentripplanner/core-utils"));
|
|
15
|
-
|
|
16
14
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
17
15
|
|
|
18
16
|
var _react = _interopRequireDefault(require("react"));
|
|
@@ -42,7 +40,9 @@ const templatePropTypes = {
|
|
|
42
40
|
children: _propTypes.default.node,
|
|
43
41
|
|
|
44
42
|
/** The rental vehicle or station to render. */
|
|
45
|
-
entity:
|
|
43
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
44
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
45
|
+
entity: _propTypes.default.object.isRequired,
|
|
46
46
|
|
|
47
47
|
/** leaflet attribute to control tabindex value for keyboaryd-only / SR users */
|
|
48
48
|
keyboard: _propTypes.default.bool
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/DefaultMarkers/index.js"],"names":["templatePropTypes","children","PropTypes","node","entity","
|
|
1
|
+
{"version":3,"sources":["../../src/DefaultMarkers/index.js"],"names":["templatePropTypes","children","PropTypes","node","entity","object","isRequired","keyboard","bool","templateDefaultProps","SharedBikeCircle","dockStrokeColor","fillColor","pixels","strokeColor","GeneratedMarker","station","newStrokeColor","isFloatingBike","y","x","propTypes","defaultProps","HubAndFloatingBike","icon","floatingBikeIcon","capacity","bikesAvailable","spacesAvailable","pctFull","i","Math","round","hubIcons","getStationMarkerByColor","color","className","iconSize","popupAnchor","html","ReactDOMServer","renderToStaticMarkup","GenericMarker","markerIcon"],"mappings":"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","sourcesContent":["import { divIcon } from \"leaflet\";\nimport memoize from \"lodash.memoize\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport ReactDOMServer from \"react-dom/server\";\nimport { CircleMarker, Marker } from \"react-leaflet\";\n\nimport { floatingBikeIcon, hubIcons } from \"../bike-icons\";\nimport * as Styled from \"../styled\";\n\n/**\n * This file contains default marker types for rental vehicles,\n * that can be used when defining the VehicleRentalOverlay's symbol prop:\n * - SharedBikeCircle\n * - GenericMarker\n * - HubAndFloatingBike\n */\n\n// Prop types reused across components.\nconst templatePropTypes = {\n /** The children of the component. */\n children: PropTypes.node,\n /** The rental vehicle or station to render. */\n // entity: coreUtils.types.stationType.isRequired,\n // eslint-disable-next-line react/forbid-prop-types\n entity: PropTypes.object.isRequired,\n /** leaflet attribute to control tabindex value for keyboaryd-only / SR users */\n keyboard: PropTypes.bool\n};\nconst templateDefaultProps = {\n children: null,\n keyboard: false\n};\n\n/**\n * Renders a shared bike or shared bike dock as a circle\n * with predefined colors and size.\n */\nexport const SharedBikeCircle = ({\n dockStrokeColor,\n fillColor = \"gray\",\n pixels,\n strokeColor\n}) => {\n const GeneratedMarker = ({ children, keyboard, entity: station }) => {\n let newStrokeColor = strokeColor || fillColor;\n\n if (!station.isFloatingBike) {\n newStrokeColor = dockStrokeColor || strokeColor;\n }\n\n return (\n <CircleMarker\n center={[station.y, station.x]}\n color={newStrokeColor}\n fillColor={fillColor}\n fillOpacity={1}\n keyboard={keyboard}\n radius={pixels - (station.isFloatingBike ? 1 : 0)}\n weight={1}\n >\n {children}\n </CircleMarker>\n );\n };\n\n GeneratedMarker.propTypes = templatePropTypes;\n GeneratedMarker.defaultProps = templateDefaultProps;\n return GeneratedMarker;\n};\n\n/**\n * A component that renders rental bike entities\n * either as a bike or a bike dock (or hub, showing spaces available).\n */\nexport const HubAndFloatingBike = ({ children, keyboard, entity: station }) => {\n let icon;\n if (station.isFloatingBike) {\n icon = floatingBikeIcon;\n } else {\n const capacity = station.bikesAvailable + station.spacesAvailable;\n if (capacity === 0) return null;\n const pctFull = station.bikesAvailable / capacity;\n const i = Math.round(pctFull * 9);\n icon = hubIcons[i];\n }\n return (\n <Marker icon={icon} keyboard={keyboard} position={[station.y, station.x]}>\n {children}\n </Marker>\n );\n};\nHubAndFloatingBike.propTypes = templatePropTypes;\nHubAndFloatingBike.defaultProps = templateDefaultProps;\n\n/**\n * Creates and caches a leaflet element icon based on color.\n */\nconst getStationMarkerByColor = memoize(color =>\n divIcon({\n className: \"\",\n iconSize: [11, 16],\n popupAnchor: [0, -6],\n html: ReactDOMServer.renderToStaticMarkup(\n <Styled.StationMarker color={color} />\n )\n })\n);\n\n/**\n * Helper function to create a leaflet Marker component to render entities\n * using fixed fill color.\n * Usage: GenericMarker({ fillColor: \"#F204B5\" })\n */\nexport const GenericMarker = ({ fillColor = \"gray\" }) => {\n const markerIcon = getStationMarkerByColor(fillColor);\n\n const GeneratedMarker = ({ children, keyboard, entity: station }) => (\n <Marker\n icon={markerIcon}\n keyboard={keyboard}\n position={[station.y, station.x]}\n >\n {children}\n </Marker>\n );\n GeneratedMarker.propTypes = templatePropTypes;\n GeneratedMarker.defaultProps = templateDefaultProps;\n return GeneratedMarker;\n};\n"],"file":"index.js"}
|
package/lib/index.js
CHANGED
|
@@ -35,12 +35,56 @@ var _enUS = _interopRequireDefault(require("../i18n/en-US.yml"));
|
|
|
35
35
|
// - the yaml loader for webpack returns a nested object,
|
|
36
36
|
// - the yaml loader for jest returns messages with flattened ids.
|
|
37
37
|
const defaultMessages = (0, _flat.default)(_enUS.default);
|
|
38
|
+
|
|
39
|
+
function makeDefaultGetStationName(intl) {
|
|
40
|
+
return function defaultGetStationName(configCompanies, station) {
|
|
41
|
+
const stationNetworks = _coreUtils.default.itinerary.getCompaniesLabelFromNetworks(station.networks, configCompanies);
|
|
42
|
+
|
|
43
|
+
let stationName = station.name || station.id; // If the station name or id is a giant UUID (with more than 3 "-" characters)
|
|
44
|
+
// best not to show that at all and instead use the network name.
|
|
45
|
+
|
|
46
|
+
if ((stationName.match(/-/g) || []).length > 3) {
|
|
47
|
+
stationName = stationNetworks;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (station.isFloatingBike) {
|
|
51
|
+
stationName = intl.formatMessage({
|
|
52
|
+
defaultMessage: _enUS.default["otpUi.VehicleRentalOverlay.floatingBike"],
|
|
53
|
+
description: "Popup title for a free-floating bike",
|
|
54
|
+
id: "otpUi.VehicleRentalOverlay.floatingBike"
|
|
55
|
+
}, {
|
|
56
|
+
name: stationName
|
|
57
|
+
});
|
|
58
|
+
} else if (station.isFloatingCar) {
|
|
59
|
+
stationName = intl.formatMessage({
|
|
60
|
+
defaultMessage: _enUS.default["otpUi.VehicleRentalOverlay.floatingCar"],
|
|
61
|
+
description: "Popup title for a free-floating car",
|
|
62
|
+
id: "otpUi.VehicleRentalOverlay.floatingCar"
|
|
63
|
+
}, {
|
|
64
|
+
company: stationNetworks,
|
|
65
|
+
name: stationName
|
|
66
|
+
});
|
|
67
|
+
} else if (station.isFloatingVehicle) {
|
|
68
|
+
// assumes that all floating vehicles are E-scooters
|
|
69
|
+
stationName = intl.formatMessage({
|
|
70
|
+
defaultMessage: _enUS.default["otpUi.VehicleRentalOverlay.floatingEScooter"],
|
|
71
|
+
description: "Popup title for a free-floating e-scooter",
|
|
72
|
+
id: "otpUi.VehicleRentalOverlay.floatingEScooter"
|
|
73
|
+
}, {
|
|
74
|
+
company: stationNetworks
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return stationName;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
38
81
|
/**
|
|
39
82
|
* This vehicle rental overlay can be used to render vehicle rentals of various
|
|
40
83
|
* types. This layer can be configured to show different styles of markers at
|
|
41
84
|
* different zoom levels.
|
|
42
85
|
*/
|
|
43
86
|
|
|
87
|
+
|
|
44
88
|
class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
45
89
|
constructor(props) {
|
|
46
90
|
super(props);
|
|
@@ -55,7 +99,7 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
55
99
|
}, this.renderPopupForStation(station, station.bikesAvailable !== undefined && !station.isFloatingBike));
|
|
56
100
|
|
|
57
101
|
SymbolWrapper.propTypes = {
|
|
58
|
-
entity:
|
|
102
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
59
103
|
zoom: _propTypes.default.number.isRequired
|
|
60
104
|
};
|
|
61
105
|
return SymbolWrapper;
|
|
@@ -113,9 +157,11 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
113
157
|
const {
|
|
114
158
|
configCompanies,
|
|
115
159
|
getStationName,
|
|
160
|
+
intl,
|
|
116
161
|
setLocation
|
|
117
162
|
} = this.props;
|
|
118
|
-
const
|
|
163
|
+
const getStationNameFunc = getStationName || makeDefaultGetStationName(intl);
|
|
164
|
+
const stationName = getStationNameFunc(configCompanies, station);
|
|
119
165
|
const location = {
|
|
120
166
|
lat: station.y,
|
|
121
167
|
lon: station.x,
|
|
@@ -143,7 +189,7 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
143
189
|
};
|
|
144
190
|
|
|
145
191
|
this.state = {
|
|
146
|
-
zoom:
|
|
192
|
+
zoom: null
|
|
147
193
|
};
|
|
148
194
|
}
|
|
149
195
|
/**
|
|
@@ -188,9 +234,13 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
188
234
|
*/
|
|
189
235
|
componentDidMount() {
|
|
190
236
|
const {
|
|
237
|
+
leaflet,
|
|
191
238
|
registerOverlay,
|
|
192
239
|
visible
|
|
193
240
|
} = this.props;
|
|
241
|
+
this.setState({
|
|
242
|
+
zoom: leaflet.map.getZoom()
|
|
243
|
+
});
|
|
194
244
|
if (visible) this.startRefreshing();
|
|
195
245
|
|
|
196
246
|
if (typeof registerOverlay === "function") {
|
|
@@ -211,11 +261,12 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
211
261
|
render() {
|
|
212
262
|
const {
|
|
213
263
|
companies,
|
|
264
|
+
leaflet,
|
|
214
265
|
mapSymbols,
|
|
215
266
|
stations
|
|
216
267
|
} = this.props;
|
|
217
268
|
const {
|
|
218
|
-
zoom
|
|
269
|
+
zoom = leaflet.map.getZoom()
|
|
219
270
|
} = this.state; // Render an empty FeatureGroup if the rental vehicles should not be visible
|
|
220
271
|
// on the map. Otherwise previous stations may still be shown due to some
|
|
221
272
|
// react-leaflet internals, maybe? Also, do not return null because that will
|
|
@@ -247,7 +298,8 @@ VehicleRentalOverlay.props = {
|
|
|
247
298
|
/**
|
|
248
299
|
* The entire companies config array.
|
|
249
300
|
*/
|
|
250
|
-
configCompanies:
|
|
301
|
+
// configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
|
|
302
|
+
// .isRequired,
|
|
251
303
|
|
|
252
304
|
/**
|
|
253
305
|
* A list of companies that are applicable to just this instance of the
|
|
@@ -266,7 +318,7 @@ VehicleRentalOverlay.props = {
|
|
|
266
318
|
* A configuration of what map markers or symbols to show at various
|
|
267
319
|
* zoom levels.
|
|
268
320
|
*/
|
|
269
|
-
mapSymbols:
|
|
321
|
+
// mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
270
322
|
|
|
271
323
|
/**
|
|
272
324
|
* If specified, a function that will be triggered every 30 seconds whenever this layer is
|
|
@@ -296,7 +348,7 @@ VehicleRentalOverlay.props = {
|
|
|
296
348
|
/**
|
|
297
349
|
* A list of the vehicle rental stations specific to this overlay instance.
|
|
298
350
|
*/
|
|
299
|
-
stations:
|
|
351
|
+
// stations: PropTypes.arrayOf(coreUtils.types.stationType),
|
|
300
352
|
|
|
301
353
|
/**
|
|
302
354
|
* Whether the overlay is currently visible.
|
|
@@ -304,22 +356,7 @@ VehicleRentalOverlay.props = {
|
|
|
304
356
|
visible: _propTypes.default.bool
|
|
305
357
|
};
|
|
306
358
|
VehicleRentalOverlay.defaultProps = {
|
|
307
|
-
getStationName:
|
|
308
|
-
const stationNetworks = _coreUtils.default.itinerary.getCompaniesLabelFromNetworks(station.networks, configCompanies);
|
|
309
|
-
|
|
310
|
-
let stationName = station.name || station.id;
|
|
311
|
-
|
|
312
|
-
if (station.isFloatingBike) {
|
|
313
|
-
stationName = `Free-floating bike: ${stationName}`;
|
|
314
|
-
} else if (station.isFloatingCar) {
|
|
315
|
-
stationName = `${stationNetworks} ${stationName}`;
|
|
316
|
-
} else if (station.isFloatingVehicle) {
|
|
317
|
-
// assumes that all floating vehicles are E-scooters
|
|
318
|
-
stationName = `${stationNetworks} E-scooter`;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return stationName;
|
|
322
|
-
},
|
|
359
|
+
getStationName: null,
|
|
323
360
|
mapSymbols: [{
|
|
324
361
|
zoom: 0,
|
|
325
362
|
symbol: _DefaultMarkers.GenericMarker
|
|
@@ -329,7 +366,7 @@ VehicleRentalOverlay.defaultProps = {
|
|
|
329
366
|
visible: false
|
|
330
367
|
};
|
|
331
368
|
|
|
332
|
-
var _default = (0, _reactLeaflet.withLeaflet)(VehicleRentalOverlay);
|
|
369
|
+
var _default = (0, _reactLeaflet.withLeaflet)((0, _reactIntl.injectIntl)(VehicleRentalOverlay));
|
|
333
370
|
|
|
334
371
|
exports.default = _default;
|
|
335
372
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["defaultMessages","defaultEnglishMessages","VehicleRentalOverlay","MapLayer","constructor","props","renderSymbolWithPopup","Symbol","SymbolWrapper","entity","station","zoom","renderPopupForStation","bikesAvailable","undefined","isFloatingBike","propTypes","coreUtils","types","stationType","isRequired","PropTypes","number","convertToZoomMarkerSymbols","mapSymbols","map","mapSymbol","symbol","type","HubAndFloatingBike","minZoom","onOverlayAdded","startRefreshing","onOverlayRemoved","stopRefreshing","onViewportChanged","viewport","newZoom","state","setState","stationIsHub","configCompanies","getStationName","setLocation","stationName","location","lat","y","lon","x","name","value","spacesAvailable","leaflet","getZoom","createLeafletElement","updateLeafletElement","refreshVehicles","refreshTimer","setInterval","clearInterval","componentDidMount","registerOverlay","visible","componentWillUnmount","render","companies","stations","filteredStations","filter","networks","includes","length","symbols","arrayOf","companyType","string","func","vehicleRentalMapOverlaySymbolsType","bool","defaultProps","stationNetworks","itinerary","getCompaniesLabelFromNetworks","id","isFloatingCar","isFloatingVehicle","GenericMarker"],"mappings":"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","sourcesContent":["import flatten from \"flat\";\nimport { Styled as BaseMapStyled } from \"@opentripplanner/base-map\";\nimport coreUtils from \"@opentripplanner/core-utils\";\nimport FromToLocationPicker from \"@opentripplanner/from-to-location-picker\";\nimport ZoomBasedMarkers from \"@opentripplanner/zoom-based-markers\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport { FormattedMessage } from \"react-intl\";\nimport { FeatureGroup, MapLayer, Popup, withLeaflet } from \"react-leaflet\";\n\nimport {\n GenericMarker,\n HubAndFloatingBike,\n SharedBikeCircle\n} from \"./DefaultMarkers\";\n\n// Load the default messages.\nimport defaultEnglishMessages from \"../i18n/en-US.yml\";\n\n// HACK: We should flatten the messages loaded above because\n// the YAML loaders behave differently between webpack and our version of jest:\n// - the yaml loader for webpack returns a nested object,\n// - the yaml loader for jest returns messages with flattened ids.\nconst defaultMessages = flatten(defaultEnglishMessages);\n\n/**\n * This vehicle rental overlay can be used to render vehicle rentals of various\n * types. This layer can be configured to show different styles of markers at\n * different zoom levels.\n */\nclass VehicleRentalOverlay extends MapLayer {\n constructor(props) {\n super(props);\n this.state = {\n zoom: props.leaflet.map.getZoom()\n };\n }\n\n /**\n * This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.\n * It creates a component that inserts a popup\n * as a child of the specified symbol from the mapSymbols prop.\n */\n renderSymbolWithPopup = Symbol => {\n const SymbolWrapper = ({ entity: station, zoom }) => (\n <Symbol entity={station} zoom={zoom}>\n {this.renderPopupForStation(\n station,\n station.bikesAvailable !== undefined && !station.isFloatingBike\n )}\n </Symbol>\n );\n SymbolWrapper.propTypes = {\n entity: coreUtils.types.stationType.isRequired,\n zoom: PropTypes.number.isRequired\n };\n\n return SymbolWrapper;\n };\n\n /**\n * Convert map symbols to zoomBasedSymbolType.\n */\n convertToZoomMarkerSymbols = mapSymbols =>\n mapSymbols.map(mapSymbol => {\n // If mapSymbol uses zoomBasedSymbolType, use it as is.\n if (mapSymbol.symbol) {\n return mapSymbol;\n }\n\n // Otherwise, convert into zoomBasedType (no support for symbols by type).\n let symbol;\n switch (mapSymbol.type) {\n case \"circle\":\n symbol = SharedBikeCircle(mapSymbol);\n break;\n case \"hubAndFloatingBike\":\n symbol = HubAndFloatingBike;\n break;\n default:\n symbol = GenericMarker(mapSymbol);\n }\n\n return {\n minZoom: mapSymbol.minZoom,\n symbol\n };\n });\n\n createLeafletElement() {}\n\n updateLeafletElement() {}\n\n startRefreshing() {\n const { refreshVehicles } = this.props;\n\n // Create the timer only if refreshVehicles is a valid function.\n if (typeof refreshVehicles === \"function\") {\n // initial station retrieval\n refreshVehicles();\n\n // set up timer to refresh stations periodically\n this.refreshTimer = setInterval(() => {\n refreshVehicles();\n }, 30000); // defaults to every 30 sec. TODO: make this configurable?\n }\n }\n\n stopRefreshing() {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n }\n\n /**\n * When the layer is added (or toggled on, or its visibility becomes true),\n * start refreshing vehicle positions.\n */\n onOverlayAdded = () => {\n this.startRefreshing();\n };\n\n /**\n * When the layer is removed (or toggled off, or its visibility becomes false),\n * stop refreshing vehicle positions.\n */\n onOverlayRemoved = () => {\n this.stopRefreshing();\n };\n\n /**\n * Listen to changes on the BaseMap's center or zoom.\n * @param viewport The viewport data. See https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js for details.\n */\n onViewportChanged = viewport => {\n const { zoom: newZoom } = viewport;\n if (this.state.zoom !== newZoom) {\n this.setState({ zoom: newZoom });\n }\n };\n\n /**\n * Upon mounting, see whether the vehicles should be fetched,\n * and also call the register overlay prop that the\n * @opentripplanner/base-map package has injected to listen to zoom/position changes.\n */\n componentDidMount() {\n const { registerOverlay, visible } = this.props;\n if (visible) this.startRefreshing();\n if (typeof registerOverlay === \"function\") {\n registerOverlay(this);\n }\n }\n\n componentWillUnmount() {\n this.stopRefreshing();\n }\n\n /**\n * Render some popup html for a station. This contains custom logic for\n * displaying rental vehicles in the TriMet MOD website that might not be\n * applicable to other regions.\n */\n renderPopupForStation = (station, stationIsHub = false) => {\n const { configCompanies, getStationName, setLocation } = this.props;\n const stationName = getStationName(configCompanies, station);\n const location = {\n lat: station.y,\n lon: station.x,\n name: stationName\n };\n return (\n <Popup>\n <BaseMapStyled.MapOverlayPopup>\n <BaseMapStyled.PopupTitle>{stationName}</BaseMapStyled.PopupTitle>\n\n {/* render dock info if it is available */}\n {stationIsHub && (\n <BaseMapStyled.PopupRow>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableBikes\"]\n }\n description=\"Label text for the number of bikes available\"\n id=\"otpUi.VehicleRentalOverlay.availableBikes\"\n values={{ value: station.bikesAvailable }}\n />\n </div>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableDocks\"]\n }\n description=\"Label text for the number of docks available\"\n id=\"otpUi.VehicleRentalOverlay.availableDocks\"\n values={{ value: station.spacesAvailable }}\n />\n </div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <FromToLocationPicker\n label\n location={location}\n setLocation={setLocation}\n />\n </BaseMapStyled.PopupRow>\n </BaseMapStyled.MapOverlayPopup>\n </Popup>\n );\n };\n\n render() {\n const { companies, mapSymbols, stations } = this.props;\n const { zoom } = this.state;\n // Render an empty FeatureGroup if the rental vehicles should not be visible\n // on the map. Otherwise previous stations may still be shown due to some\n // react-leaflet internals, maybe? Also, do not return null because that will\n // prevent the overlay from appearing in the layer controls.\n\n let filteredStations = stations;\n if (companies) {\n filteredStations = stations.filter(\n station =>\n station.networks.filter(value => companies.includes(value)).length > 0\n );\n }\n\n if (!filteredStations || filteredStations.length === 0) {\n return <FeatureGroup />;\n }\n\n // Convert map symbols for this overlay to zoomBasedSymbolType.\n const symbols = this.convertToZoomMarkerSymbols(mapSymbols);\n\n return (\n <FeatureGroup>\n <ZoomBasedMarkers\n entities={filteredStations}\n symbols={symbols}\n symbolTransform={this.renderSymbolWithPopup}\n zoom={zoom}\n />\n </FeatureGroup>\n );\n }\n}\n\nVehicleRentalOverlay.props = {\n /**\n * The entire companies config array.\n */\n configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)\n .isRequired,\n /**\n * A list of companies that are applicable to just this instance of the\n * overlay.\n */\n companies: PropTypes.arrayOf(PropTypes.string.isRequired),\n /**\n * An optional custom function to create a string name of a particular vehicle\n * rental station. This function takes two arguments of the configCompanies\n * prop and a vehicle rental station. The function must return a string.\n */\n getStationName: PropTypes.func,\n /**\n * A configuration of what map markers or symbols to show at various\n * zoom levels.\n */\n mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,\n /**\n * If specified, a function that will be triggered every 30 seconds whenever this layer is\n * visible.\n */\n refreshVehicles: PropTypes.func,\n /**\n * A callback for when a user clicks on setting this stop as either the from\n * or to location of a new search.\n *\n * This will be dispatched with the following argument:\n *\n * ```js\n * {\n * location: {\n * lat: number,\n * lon: number,\n * name: string\n * },\n * locationType: \"from\" or \"to\"\n * }\n * ```\n */\n setLocation: PropTypes.func.isRequired,\n /**\n * A list of the vehicle rental stations specific to this overlay instance.\n */\n stations: PropTypes.arrayOf(coreUtils.types.stationType),\n /**\n * Whether the overlay is currently visible.\n */\n visible: PropTypes.bool\n};\n\nVehicleRentalOverlay.defaultProps = {\n getStationName: (configCompanies, station) => {\n const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(\n station.networks,\n configCompanies\n );\n let stationName = station.name || station.id;\n if (station.isFloatingBike) {\n stationName = `Free-floating bike: ${stationName}`;\n } else if (station.isFloatingCar) {\n stationName = `${stationNetworks} ${stationName}`;\n } else if (station.isFloatingVehicle) {\n // assumes that all floating vehicles are E-scooters\n stationName = `${stationNetworks} E-scooter`;\n }\n return stationName;\n },\n mapSymbols: [\n {\n zoom: 0,\n symbol: GenericMarker\n }\n ],\n refreshVehicles: null,\n stations: [],\n visible: false\n};\n\nexport default withLeaflet(VehicleRentalOverlay);\n"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../src/index.js"],"names":["defaultMessages","defaultEnglishMessages","makeDefaultGetStationName","intl","defaultGetStationName","configCompanies","station","stationNetworks","coreUtils","itinerary","getCompaniesLabelFromNetworks","networks","stationName","name","id","match","length","isFloatingBike","formatMessage","defaultMessage","description","isFloatingCar","company","isFloatingVehicle","VehicleRentalOverlay","MapLayer","constructor","props","renderSymbolWithPopup","Symbol","SymbolWrapper","entity","zoom","renderPopupForStation","bikesAvailable","undefined","propTypes","PropTypes","number","isRequired","convertToZoomMarkerSymbols","mapSymbols","map","mapSymbol","symbol","type","HubAndFloatingBike","minZoom","onOverlayAdded","startRefreshing","onOverlayRemoved","stopRefreshing","onViewportChanged","viewport","newZoom","state","setState","stationIsHub","getStationName","setLocation","getStationNameFunc","location","lat","y","lon","x","value","spacesAvailable","createLeafletElement","updateLeafletElement","refreshVehicles","refreshTimer","setInterval","clearInterval","componentDidMount","leaflet","registerOverlay","visible","getZoom","componentWillUnmount","render","companies","stations","filteredStations","filter","includes","symbols","arrayOf","string","func","bool","defaultProps","GenericMarker"],"mappings":"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","sourcesContent":["import flatten from \"flat\";\nimport { Styled as BaseMapStyled } from \"@opentripplanner/base-map\";\nimport coreUtils from \"@opentripplanner/core-utils\";\nimport FromToLocationPicker from \"@opentripplanner/from-to-location-picker\";\nimport ZoomBasedMarkers from \"@opentripplanner/zoom-based-markers\";\nimport PropTypes from \"prop-types\";\nimport React from \"react\";\nimport { FormattedMessage, injectIntl } from \"react-intl\";\nimport { FeatureGroup, MapLayer, Popup, withLeaflet } from \"react-leaflet\";\n\nimport {\n GenericMarker,\n HubAndFloatingBike,\n SharedBikeCircle\n} from \"./DefaultMarkers\";\n\n// Load the default messages.\nimport defaultEnglishMessages from \"../i18n/en-US.yml\";\n\n// HACK: We should flatten the messages loaded above because\n// the YAML loaders behave differently between webpack and our version of jest:\n// - the yaml loader for webpack returns a nested object,\n// - the yaml loader for jest returns messages with flattened ids.\nconst defaultMessages = flatten(defaultEnglishMessages);\n\nfunction makeDefaultGetStationName(intl) {\n return function defaultGetStationName(configCompanies, station) {\n const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(\n station.networks,\n configCompanies\n );\n let stationName = station.name || station.id;\n // If the station name or id is a giant UUID (with more than 3 \"-\" characters)\n // best not to show that at all and instead use the network name.\n if ((stationName.match(/-/g) || []).length > 3) {\n stationName = stationNetworks;\n }\n\n if (station.isFloatingBike) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingBike\"],\n description: \"Popup title for a free-floating bike\",\n id: \"otpUi.VehicleRentalOverlay.floatingBike\"\n },\n { name: stationName }\n );\n } else if (station.isFloatingCar) {\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\"otpUi.VehicleRentalOverlay.floatingCar\"],\n description: \"Popup title for a free-floating car\",\n id: \"otpUi.VehicleRentalOverlay.floatingCar\"\n },\n {\n company: stationNetworks,\n name: stationName\n }\n );\n } else if (station.isFloatingVehicle) {\n // assumes that all floating vehicles are E-scooters\n stationName = intl.formatMessage(\n {\n defaultMessage:\n defaultEnglishMessages[\n \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n ],\n description: \"Popup title for a free-floating e-scooter\",\n id: \"otpUi.VehicleRentalOverlay.floatingEScooter\"\n },\n { company: stationNetworks }\n );\n }\n return stationName;\n };\n}\n\n/**\n * This vehicle rental overlay can be used to render vehicle rentals of various\n * types. This layer can be configured to show different styles of markers at\n * different zoom levels.\n */\nclass VehicleRentalOverlay extends MapLayer {\n constructor(props) {\n super(props);\n this.state = {\n zoom: null\n };\n }\n\n /**\n * This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.\n * It creates a component that inserts a popup\n * as a child of the specified symbol from the mapSymbols prop.\n */\n renderSymbolWithPopup = Symbol => {\n const SymbolWrapper = ({ entity: station, zoom }) => (\n <Symbol entity={station} zoom={zoom}>\n {this.renderPopupForStation(\n station,\n station.bikesAvailable !== undefined && !station.isFloatingBike\n )}\n </Symbol>\n );\n SymbolWrapper.propTypes = {\n // entity: coreUtils.types.stationType.isRequired,\n zoom: PropTypes.number.isRequired\n };\n\n return SymbolWrapper;\n };\n\n /**\n * Convert map symbols to zoomBasedSymbolType.\n */\n convertToZoomMarkerSymbols = mapSymbols =>\n mapSymbols.map(mapSymbol => {\n // If mapSymbol uses zoomBasedSymbolType, use it as is.\n if (mapSymbol.symbol) {\n return mapSymbol;\n }\n\n // Otherwise, convert into zoomBasedType (no support for symbols by type).\n let symbol;\n switch (mapSymbol.type) {\n case \"circle\":\n symbol = SharedBikeCircle(mapSymbol);\n break;\n case \"hubAndFloatingBike\":\n symbol = HubAndFloatingBike;\n break;\n default:\n symbol = GenericMarker(mapSymbol);\n }\n\n return {\n minZoom: mapSymbol.minZoom,\n symbol\n };\n });\n\n createLeafletElement() {}\n\n updateLeafletElement() {}\n\n startRefreshing() {\n const { refreshVehicles } = this.props;\n\n // Create the timer only if refreshVehicles is a valid function.\n if (typeof refreshVehicles === \"function\") {\n // initial station retrieval\n refreshVehicles();\n\n // set up timer to refresh stations periodically\n this.refreshTimer = setInterval(() => {\n refreshVehicles();\n }, 30000); // defaults to every 30 sec. TODO: make this configurable?\n }\n }\n\n stopRefreshing() {\n if (this.refreshTimer) clearInterval(this.refreshTimer);\n }\n\n /**\n * When the layer is added (or toggled on, or its visibility becomes true),\n * start refreshing vehicle positions.\n */\n onOverlayAdded = () => {\n this.startRefreshing();\n };\n\n /**\n * When the layer is removed (or toggled off, or its visibility becomes false),\n * stop refreshing vehicle positions.\n */\n onOverlayRemoved = () => {\n this.stopRefreshing();\n };\n\n /**\n * Listen to changes on the BaseMap's center or zoom.\n * @param viewport The viewport data. See https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js for details.\n */\n onViewportChanged = viewport => {\n const { zoom: newZoom } = viewport;\n if (this.state.zoom !== newZoom) {\n this.setState({ zoom: newZoom });\n }\n };\n\n /**\n * Upon mounting, see whether the vehicles should be fetched,\n * and also call the register overlay prop that the\n * @opentripplanner/base-map package has injected to listen to zoom/position changes.\n */\n componentDidMount() {\n const { leaflet, registerOverlay, visible } = this.props;\n this.setState({\n zoom: leaflet.map.getZoom()\n });\n if (visible) this.startRefreshing();\n if (typeof registerOverlay === \"function\") {\n registerOverlay(this);\n }\n }\n\n componentWillUnmount() {\n this.stopRefreshing();\n }\n\n /**\n * Render some popup html for a station. This contains custom logic for\n * displaying rental vehicles in the TriMet MOD website that might not be\n * applicable to other regions.\n */\n renderPopupForStation = (station, stationIsHub = false) => {\n const { configCompanies, getStationName, intl, setLocation } = this.props;\n const getStationNameFunc =\n getStationName || makeDefaultGetStationName(intl);\n const stationName = getStationNameFunc(configCompanies, station);\n const location = {\n lat: station.y,\n lon: station.x,\n name: stationName\n };\n return (\n <Popup>\n <BaseMapStyled.MapOverlayPopup>\n <BaseMapStyled.PopupTitle>{stationName}</BaseMapStyled.PopupTitle>\n\n {/* render dock info if it is available */}\n {stationIsHub && (\n <BaseMapStyled.PopupRow>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableBikes\"]\n }\n description=\"Label text for the number of bikes available\"\n id=\"otpUi.VehicleRentalOverlay.availableBikes\"\n values={{ value: station.bikesAvailable }}\n />\n </div>\n <div>\n <FormattedMessage\n defaultMessage={\n defaultMessages[\"otpUi.VehicleRentalOverlay.availableDocks\"]\n }\n description=\"Label text for the number of docks available\"\n id=\"otpUi.VehicleRentalOverlay.availableDocks\"\n values={{ value: station.spacesAvailable }}\n />\n </div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <FromToLocationPicker\n label\n location={location}\n setLocation={setLocation}\n />\n </BaseMapStyled.PopupRow>\n </BaseMapStyled.MapOverlayPopup>\n </Popup>\n );\n };\n\n render() {\n const { companies, leaflet, mapSymbols, stations } = this.props;\n const { zoom = leaflet.map.getZoom() } = this.state;\n // Render an empty FeatureGroup if the rental vehicles should not be visible\n // on the map. Otherwise previous stations may still be shown due to some\n // react-leaflet internals, maybe? Also, do not return null because that will\n // prevent the overlay from appearing in the layer controls.\n\n let filteredStations = stations;\n if (companies) {\n filteredStations = stations.filter(\n station =>\n station.networks.filter(value => companies.includes(value)).length > 0\n );\n }\n\n if (!filteredStations || filteredStations.length === 0) {\n return <FeatureGroup />;\n }\n\n // Convert map symbols for this overlay to zoomBasedSymbolType.\n const symbols = this.convertToZoomMarkerSymbols(mapSymbols);\n\n return (\n <FeatureGroup>\n <ZoomBasedMarkers\n entities={filteredStations}\n symbols={symbols}\n symbolTransform={this.renderSymbolWithPopup}\n zoom={zoom}\n />\n </FeatureGroup>\n );\n }\n}\n\nVehicleRentalOverlay.props = {\n /**\n * The entire companies config array.\n */\n // configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)\n // .isRequired,\n /**\n * A list of companies that are applicable to just this instance of the\n * overlay.\n */\n companies: PropTypes.arrayOf(PropTypes.string.isRequired),\n /**\n * An optional custom function to create a string name of a particular vehicle\n * rental station. This function takes two arguments of the configCompanies\n * prop and a vehicle rental station. The function must return a string.\n */\n getStationName: PropTypes.func,\n /**\n * A configuration of what map markers or symbols to show at various\n * zoom levels.\n */\n // mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,\n /**\n * If specified, a function that will be triggered every 30 seconds whenever this layer is\n * visible.\n */\n refreshVehicles: PropTypes.func,\n /**\n * A callback for when a user clicks on setting this stop as either the from\n * or to location of a new search.\n *\n * This will be dispatched with the following argument:\n *\n * ```js\n * {\n * location: {\n * lat: number,\n * lon: number,\n * name: string\n * },\n * locationType: \"from\" or \"to\"\n * }\n * ```\n */\n setLocation: PropTypes.func.isRequired,\n /**\n * A list of the vehicle rental stations specific to this overlay instance.\n */\n // stations: PropTypes.arrayOf(coreUtils.types.stationType),\n /**\n * Whether the overlay is currently visible.\n */\n visible: PropTypes.bool\n};\n\nVehicleRentalOverlay.defaultProps = {\n getStationName: null,\n mapSymbols: [\n {\n zoom: 0,\n symbol: GenericMarker\n }\n ],\n refreshVehicles: null,\n stations: [],\n visible: false\n};\n\nexport default withLeaflet(injectIntl(VehicleRentalOverlay));\n"],"file":"index.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentripplanner/vehicle-rental-overlay",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.3-alpha.1",
|
|
4
4
|
"description": "A map overlay to show vehicle rentals from a specific company",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@opentripplanner/core-utils": "^4.5.0",
|
|
22
|
-
"@opentripplanner/from-to-location-picker": "^2.1.
|
|
22
|
+
"@opentripplanner/from-to-location-picker": "^2.1.2",
|
|
23
23
|
"@opentripplanner/zoom-based-markers": "^1.2.1",
|
|
24
24
|
"@styled-icons/fa-solid": "^10.34.0",
|
|
25
25
|
"flat": "^5.0.2",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { divIcon } from "leaflet";
|
|
2
2
|
import memoize from "lodash.memoize";
|
|
3
|
-
import coreUtils from "@opentripplanner/core-utils";
|
|
4
3
|
import PropTypes from "prop-types";
|
|
5
4
|
import React from "react";
|
|
6
5
|
import ReactDOMServer from "react-dom/server";
|
|
@@ -22,7 +21,9 @@ const templatePropTypes = {
|
|
|
22
21
|
/** The children of the component. */
|
|
23
22
|
children: PropTypes.node,
|
|
24
23
|
/** The rental vehicle or station to render. */
|
|
25
|
-
entity: coreUtils.types.stationType.isRequired,
|
|
24
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
25
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
26
|
+
entity: PropTypes.object.isRequired,
|
|
26
27
|
/** leaflet attribute to control tabindex value for keyboaryd-only / SR users */
|
|
27
28
|
keyboard: PropTypes.bool
|
|
28
29
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
// Removed as core-utils is typescripted. TODO: Remove when typescripting!
|
|
2
|
+
/* eslint-disable react/forbid-prop-types */
|
|
1
3
|
import BaseMap from "@opentripplanner/base-map";
|
|
2
|
-
import coreUtils from "@opentripplanner/core-utils";
|
|
3
4
|
import PropTypes from "prop-types";
|
|
4
5
|
import React from "react";
|
|
5
6
|
import { CircleMarker } from "react-leaflet";
|
|
@@ -37,7 +38,8 @@ const MyCircle = ({ fillColor = "gray", pixels, strokeColor }) => {
|
|
|
37
38
|
);
|
|
38
39
|
GeneratedCircle.propTypes = {
|
|
39
40
|
children: PropTypes.node,
|
|
40
|
-
entity: coreUtils.types.stationType.isRequired
|
|
41
|
+
// entity: coreUtils.types.stationType.isRequired
|
|
42
|
+
entity: PropTypes.object.isRequired
|
|
41
43
|
};
|
|
42
44
|
GeneratedCircle.defaultProps = {
|
|
43
45
|
children: null
|
|
@@ -194,10 +196,12 @@ const ZoomControlledMapWithVehicleRentalOverlay = ({
|
|
|
194
196
|
ZoomControlledMapWithVehicleRentalOverlay.propTypes = {
|
|
195
197
|
companies: PropTypes.arrayOf(PropTypes.string.isRequired),
|
|
196
198
|
getStationName: PropTypes.func,
|
|
197
|
-
mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
199
|
+
// mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
200
|
+
mapSymbols: PropTypes.object,
|
|
198
201
|
refreshVehicles: PropTypes.func.isRequired,
|
|
199
|
-
stations: PropTypes.arrayOf(coreUtils.types.stationType.isRequired)
|
|
200
|
-
|
|
202
|
+
// stations: PropTypes.arrayOf(coreUtils.types.stationType.isRequired)
|
|
203
|
+
// .isRequired,
|
|
204
|
+
stations: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
|
|
201
205
|
visible: PropTypes.bool
|
|
202
206
|
};
|
|
203
207
|
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import FromToLocationPicker from "@opentripplanner/from-to-location-picker";
|
|
|
5
5
|
import ZoomBasedMarkers from "@opentripplanner/zoom-based-markers";
|
|
6
6
|
import PropTypes from "prop-types";
|
|
7
7
|
import React from "react";
|
|
8
|
-
import { FormattedMessage } from "react-intl";
|
|
8
|
+
import { FormattedMessage, injectIntl } from "react-intl";
|
|
9
9
|
import { FeatureGroup, MapLayer, Popup, withLeaflet } from "react-leaflet";
|
|
10
10
|
|
|
11
11
|
import {
|
|
@@ -23,6 +23,60 @@ import defaultEnglishMessages from "../i18n/en-US.yml";
|
|
|
23
23
|
// - the yaml loader for jest returns messages with flattened ids.
|
|
24
24
|
const defaultMessages = flatten(defaultEnglishMessages);
|
|
25
25
|
|
|
26
|
+
function makeDefaultGetStationName(intl) {
|
|
27
|
+
return function defaultGetStationName(configCompanies, station) {
|
|
28
|
+
const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(
|
|
29
|
+
station.networks,
|
|
30
|
+
configCompanies
|
|
31
|
+
);
|
|
32
|
+
let stationName = station.name || station.id;
|
|
33
|
+
// If the station name or id is a giant UUID (with more than 3 "-" characters)
|
|
34
|
+
// best not to show that at all and instead use the network name.
|
|
35
|
+
if ((stationName.match(/-/g) || []).length > 3) {
|
|
36
|
+
stationName = stationNetworks;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (station.isFloatingBike) {
|
|
40
|
+
stationName = intl.formatMessage(
|
|
41
|
+
{
|
|
42
|
+
defaultMessage:
|
|
43
|
+
defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingBike"],
|
|
44
|
+
description: "Popup title for a free-floating bike",
|
|
45
|
+
id: "otpUi.VehicleRentalOverlay.floatingBike"
|
|
46
|
+
},
|
|
47
|
+
{ name: stationName }
|
|
48
|
+
);
|
|
49
|
+
} else if (station.isFloatingCar) {
|
|
50
|
+
stationName = intl.formatMessage(
|
|
51
|
+
{
|
|
52
|
+
defaultMessage:
|
|
53
|
+
defaultEnglishMessages["otpUi.VehicleRentalOverlay.floatingCar"],
|
|
54
|
+
description: "Popup title for a free-floating car",
|
|
55
|
+
id: "otpUi.VehicleRentalOverlay.floatingCar"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
company: stationNetworks,
|
|
59
|
+
name: stationName
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
} else if (station.isFloatingVehicle) {
|
|
63
|
+
// assumes that all floating vehicles are E-scooters
|
|
64
|
+
stationName = intl.formatMessage(
|
|
65
|
+
{
|
|
66
|
+
defaultMessage:
|
|
67
|
+
defaultEnglishMessages[
|
|
68
|
+
"otpUi.VehicleRentalOverlay.floatingEScooter"
|
|
69
|
+
],
|
|
70
|
+
description: "Popup title for a free-floating e-scooter",
|
|
71
|
+
id: "otpUi.VehicleRentalOverlay.floatingEScooter"
|
|
72
|
+
},
|
|
73
|
+
{ company: stationNetworks }
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
return stationName;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
26
80
|
/**
|
|
27
81
|
* This vehicle rental overlay can be used to render vehicle rentals of various
|
|
28
82
|
* types. This layer can be configured to show different styles of markers at
|
|
@@ -32,7 +86,7 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
32
86
|
constructor(props) {
|
|
33
87
|
super(props);
|
|
34
88
|
this.state = {
|
|
35
|
-
zoom:
|
|
89
|
+
zoom: null
|
|
36
90
|
};
|
|
37
91
|
}
|
|
38
92
|
|
|
@@ -51,7 +105,7 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
51
105
|
</Symbol>
|
|
52
106
|
);
|
|
53
107
|
SymbolWrapper.propTypes = {
|
|
54
|
-
entity: coreUtils.types.stationType.isRequired,
|
|
108
|
+
// entity: coreUtils.types.stationType.isRequired,
|
|
55
109
|
zoom: PropTypes.number.isRequired
|
|
56
110
|
};
|
|
57
111
|
|
|
@@ -143,7 +197,10 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
143
197
|
* @opentripplanner/base-map package has injected to listen to zoom/position changes.
|
|
144
198
|
*/
|
|
145
199
|
componentDidMount() {
|
|
146
|
-
const { registerOverlay, visible } = this.props;
|
|
200
|
+
const { leaflet, registerOverlay, visible } = this.props;
|
|
201
|
+
this.setState({
|
|
202
|
+
zoom: leaflet.map.getZoom()
|
|
203
|
+
});
|
|
147
204
|
if (visible) this.startRefreshing();
|
|
148
205
|
if (typeof registerOverlay === "function") {
|
|
149
206
|
registerOverlay(this);
|
|
@@ -160,8 +217,10 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
160
217
|
* applicable to other regions.
|
|
161
218
|
*/
|
|
162
219
|
renderPopupForStation = (station, stationIsHub = false) => {
|
|
163
|
-
const { configCompanies, getStationName, setLocation } = this.props;
|
|
164
|
-
const
|
|
220
|
+
const { configCompanies, getStationName, intl, setLocation } = this.props;
|
|
221
|
+
const getStationNameFunc =
|
|
222
|
+
getStationName || makeDefaultGetStationName(intl);
|
|
223
|
+
const stationName = getStationNameFunc(configCompanies, station);
|
|
165
224
|
const location = {
|
|
166
225
|
lat: station.y,
|
|
167
226
|
lon: station.x,
|
|
@@ -212,8 +271,8 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
212
271
|
};
|
|
213
272
|
|
|
214
273
|
render() {
|
|
215
|
-
const { companies, mapSymbols, stations } = this.props;
|
|
216
|
-
const { zoom } = this.state;
|
|
274
|
+
const { companies, leaflet, mapSymbols, stations } = this.props;
|
|
275
|
+
const { zoom = leaflet.map.getZoom() } = this.state;
|
|
217
276
|
// Render an empty FeatureGroup if the rental vehicles should not be visible
|
|
218
277
|
// on the map. Otherwise previous stations may still be shown due to some
|
|
219
278
|
// react-leaflet internals, maybe? Also, do not return null because that will
|
|
@@ -251,8 +310,8 @@ VehicleRentalOverlay.props = {
|
|
|
251
310
|
/**
|
|
252
311
|
* The entire companies config array.
|
|
253
312
|
*/
|
|
254
|
-
configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
|
|
255
|
-
|
|
313
|
+
// configCompanies: PropTypes.arrayOf(coreUtils.types.companyType.isRequired)
|
|
314
|
+
// .isRequired,
|
|
256
315
|
/**
|
|
257
316
|
* A list of companies that are applicable to just this instance of the
|
|
258
317
|
* overlay.
|
|
@@ -268,7 +327,7 @@ VehicleRentalOverlay.props = {
|
|
|
268
327
|
* A configuration of what map markers or symbols to show at various
|
|
269
328
|
* zoom levels.
|
|
270
329
|
*/
|
|
271
|
-
mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
330
|
+
// mapSymbols: coreUtils.types.vehicleRentalMapOverlaySymbolsType,
|
|
272
331
|
/**
|
|
273
332
|
* If specified, a function that will be triggered every 30 seconds whenever this layer is
|
|
274
333
|
* visible.
|
|
@@ -295,7 +354,7 @@ VehicleRentalOverlay.props = {
|
|
|
295
354
|
/**
|
|
296
355
|
* A list of the vehicle rental stations specific to this overlay instance.
|
|
297
356
|
*/
|
|
298
|
-
stations: PropTypes.arrayOf(coreUtils.types.stationType),
|
|
357
|
+
// stations: PropTypes.arrayOf(coreUtils.types.stationType),
|
|
299
358
|
/**
|
|
300
359
|
* Whether the overlay is currently visible.
|
|
301
360
|
*/
|
|
@@ -303,22 +362,7 @@ VehicleRentalOverlay.props = {
|
|
|
303
362
|
};
|
|
304
363
|
|
|
305
364
|
VehicleRentalOverlay.defaultProps = {
|
|
306
|
-
getStationName:
|
|
307
|
-
const stationNetworks = coreUtils.itinerary.getCompaniesLabelFromNetworks(
|
|
308
|
-
station.networks,
|
|
309
|
-
configCompanies
|
|
310
|
-
);
|
|
311
|
-
let stationName = station.name || station.id;
|
|
312
|
-
if (station.isFloatingBike) {
|
|
313
|
-
stationName = `Free-floating bike: ${stationName}`;
|
|
314
|
-
} else if (station.isFloatingCar) {
|
|
315
|
-
stationName = `${stationNetworks} ${stationName}`;
|
|
316
|
-
} else if (station.isFloatingVehicle) {
|
|
317
|
-
// assumes that all floating vehicles are E-scooters
|
|
318
|
-
stationName = `${stationNetworks} E-scooter`;
|
|
319
|
-
}
|
|
320
|
-
return stationName;
|
|
321
|
-
},
|
|
365
|
+
getStationName: null,
|
|
322
366
|
mapSymbols: [
|
|
323
367
|
{
|
|
324
368
|
zoom: 0,
|
|
@@ -330,4 +374,4 @@ VehicleRentalOverlay.defaultProps = {
|
|
|
330
374
|
visible: false
|
|
331
375
|
};
|
|
332
376
|
|
|
333
|
-
export default withLeaflet(VehicleRentalOverlay);
|
|
377
|
+
export default withLeaflet(injectIntl(VehicleRentalOverlay));
|