@opentripplanner/vehicle-rental-overlay 1.3.0 → 1.4.0
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 +12 -2
- package/esm/DefaultMarkers/index.js.map +1 -1
- package/esm/index.js +80 -31
- package/esm/index.js.map +1 -1
- package/i18n/en-US.yml +14 -0
- package/i18n/fr.yml +14 -0
- package/lib/DefaultMarkers/index.js +12 -2
- package/lib/DefaultMarkers/index.js.map +1 -1
- package/lib/index.js +82 -21
- package/lib/index.js.map +1 -1
- package/package.json +9 -7
- package/src/DefaultMarkers/index.js +15 -7
- package/src/VehicleRentalOverlay.story.js +28 -48
- package/src/index.js +77 -19
- package/esm/leaflet-layer-control-interface.js +0 -90
- package/esm/leaflet-layer-control-interface.js.map +0 -1
- package/lib/leaflet-layer-control-interface.js +0 -85
- package/lib/leaflet-layer-control-interface.js.map +0 -1
- package/src/leaflet-layer-control-interface.tsx +0 -81
package/lib/index.js
CHANGED
|
@@ -7,6 +7,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
});
|
|
8
8
|
exports.default = void 0;
|
|
9
9
|
|
|
10
|
+
var _flat = _interopRequireDefault(require("flat"));
|
|
11
|
+
|
|
10
12
|
var _baseMap = require("@opentripplanner/base-map");
|
|
11
13
|
|
|
12
14
|
var _coreUtils = _interopRequireDefault(require("@opentripplanner/core-utils"));
|
|
@@ -19,18 +21,29 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
19
21
|
|
|
20
22
|
var _react = _interopRequireDefault(require("react"));
|
|
21
23
|
|
|
24
|
+
var _reactIntl = require("react-intl");
|
|
25
|
+
|
|
22
26
|
var _reactLeaflet = require("react-leaflet");
|
|
23
27
|
|
|
24
28
|
var _DefaultMarkers = require("./DefaultMarkers");
|
|
25
29
|
|
|
30
|
+
var _enUS = _interopRequireDefault(require("../i18n/en-US.yml"));
|
|
31
|
+
|
|
32
|
+
// Load the default messages.
|
|
33
|
+
// HACK: We should flatten the messages loaded above because
|
|
34
|
+
// the YAML loaders behave differently between webpack and our version of jest:
|
|
35
|
+
// - the yaml loader for webpack returns a nested object,
|
|
36
|
+
// - the yaml loader for jest returns messages with flattened ids.
|
|
37
|
+
const defaultMessages = (0, _flat.default)(_enUS.default);
|
|
26
38
|
/**
|
|
27
39
|
* This vehicle rental overlay can be used to render vehicle rentals of various
|
|
28
40
|
* types. This layer can be configured to show different styles of markers at
|
|
29
41
|
* different zoom levels.
|
|
30
42
|
*/
|
|
43
|
+
|
|
31
44
|
class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
32
|
-
constructor(
|
|
33
|
-
super(
|
|
45
|
+
constructor(props) {
|
|
46
|
+
super(props);
|
|
34
47
|
|
|
35
48
|
this.renderSymbolWithPopup = Symbol => {
|
|
36
49
|
const SymbolWrapper = ({
|
|
@@ -76,6 +89,26 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
76
89
|
};
|
|
77
90
|
});
|
|
78
91
|
|
|
92
|
+
this.onOverlayAdded = () => {
|
|
93
|
+
this.startRefreshing();
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
this.onOverlayRemoved = () => {
|
|
97
|
+
this.stopRefreshing();
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
this.onViewportChanged = viewport => {
|
|
101
|
+
const {
|
|
102
|
+
zoom: newZoom
|
|
103
|
+
} = viewport;
|
|
104
|
+
|
|
105
|
+
if (this.state.zoom !== newZoom) {
|
|
106
|
+
this.setState({
|
|
107
|
+
zoom: newZoom
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
79
112
|
this.renderPopupForStation = (station, stationIsHub = false) => {
|
|
80
113
|
const {
|
|
81
114
|
configCompanies,
|
|
@@ -88,12 +121,37 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
88
121
|
lon: station.x,
|
|
89
122
|
name: stationName
|
|
90
123
|
};
|
|
91
|
-
return /*#__PURE__*/_react.default.createElement(_reactLeaflet.Popup, null, /*#__PURE__*/_react.default.createElement(_baseMap.Styled.MapOverlayPopup, null, /*#__PURE__*/_react.default.createElement(_baseMap.Styled.PopupTitle, null, stationName), stationIsHub && /*#__PURE__*/_react.default.createElement(_baseMap.Styled.PopupRow, null, /*#__PURE__*/_react.default.createElement("div", null,
|
|
124
|
+
return /*#__PURE__*/_react.default.createElement(_reactLeaflet.Popup, null, /*#__PURE__*/_react.default.createElement(_baseMap.Styled.MapOverlayPopup, null, /*#__PURE__*/_react.default.createElement(_baseMap.Styled.PopupTitle, null, stationName), stationIsHub && /*#__PURE__*/_react.default.createElement(_baseMap.Styled.PopupRow, null, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
|
|
125
|
+
defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableBikes"],
|
|
126
|
+
description: "Label text for the number of bikes available",
|
|
127
|
+
id: "otpUi.VehicleRentalOverlay.availableBikes",
|
|
128
|
+
values: {
|
|
129
|
+
value: station.bikesAvailable
|
|
130
|
+
}
|
|
131
|
+
})), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_reactIntl.FormattedMessage, {
|
|
132
|
+
defaultMessage: defaultMessages["otpUi.VehicleRentalOverlay.availableDocks"],
|
|
133
|
+
description: "Label text for the number of docks available",
|
|
134
|
+
id: "otpUi.VehicleRentalOverlay.availableDocks",
|
|
135
|
+
values: {
|
|
136
|
+
value: station.spacesAvailable
|
|
137
|
+
}
|
|
138
|
+
}))), /*#__PURE__*/_react.default.createElement(_baseMap.Styled.PopupRow, null, /*#__PURE__*/_react.default.createElement(_fromToLocationPicker.default, {
|
|
139
|
+
label: true,
|
|
92
140
|
location: location,
|
|
93
141
|
setLocation: setLocation
|
|
94
142
|
}))));
|
|
95
143
|
};
|
|
144
|
+
|
|
145
|
+
this.state = {
|
|
146
|
+
zoom: props.leaflet.map.getZoom()
|
|
147
|
+
};
|
|
96
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.
|
|
151
|
+
* It creates a component that inserts a popup
|
|
152
|
+
* as a child of the specified symbol from the mapSymbols prop.
|
|
153
|
+
*/
|
|
154
|
+
|
|
97
155
|
|
|
98
156
|
createLeafletElement() {}
|
|
99
157
|
|
|
@@ -117,25 +175,32 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
117
175
|
stopRefreshing() {
|
|
118
176
|
if (this.refreshTimer) clearInterval(this.refreshTimer);
|
|
119
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* When the layer is added (or toggled on, or its visibility becomes true),
|
|
180
|
+
* start refreshing vehicle positions.
|
|
181
|
+
*/
|
|
182
|
+
|
|
120
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Upon mounting, see whether the vehicles should be fetched,
|
|
186
|
+
* and also call the register overlay prop that the
|
|
187
|
+
* @opentripplanner/base-map package has injected to listen to zoom/position changes.
|
|
188
|
+
*/
|
|
121
189
|
componentDidMount() {
|
|
122
190
|
const {
|
|
191
|
+
registerOverlay,
|
|
123
192
|
visible
|
|
124
193
|
} = this.props;
|
|
125
194
|
if (visible) this.startRefreshing();
|
|
195
|
+
|
|
196
|
+
if (typeof registerOverlay === "function") {
|
|
197
|
+
registerOverlay(this);
|
|
198
|
+
}
|
|
126
199
|
}
|
|
127
200
|
|
|
128
201
|
componentWillUnmount() {
|
|
129
202
|
this.stopRefreshing();
|
|
130
203
|
}
|
|
131
|
-
|
|
132
|
-
componentDidUpdate(prevProps) {
|
|
133
|
-
if (!prevProps.visible && this.props.visible) {
|
|
134
|
-
this.startRefreshing();
|
|
135
|
-
} else if (prevProps.visible && !this.props.visible) {
|
|
136
|
-
this.stopRefreshing();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
204
|
/**
|
|
140
205
|
* Render some popup html for a station. This contains custom logic for
|
|
141
206
|
* displaying rental vehicles in the TriMet MOD website that might not be
|
|
@@ -147,17 +212,15 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
147
212
|
const {
|
|
148
213
|
companies,
|
|
149
214
|
mapSymbols,
|
|
150
|
-
stations
|
|
151
|
-
|
|
152
|
-
|
|
215
|
+
stations
|
|
216
|
+
} = this.props;
|
|
217
|
+
const {
|
|
218
|
+
zoom
|
|
219
|
+
} = this.state; // Render an empty FeatureGroup if the rental vehicles should not be visible
|
|
153
220
|
// on the map. Otherwise previous stations may still be shown due to some
|
|
154
221
|
// react-leaflet internals, maybe? Also, do not return null because that will
|
|
155
222
|
// prevent the overlay from appearing in the layer controls.
|
|
156
223
|
|
|
157
|
-
if (!visible) {
|
|
158
|
-
return /*#__PURE__*/_react.default.createElement(_reactLeaflet.FeatureGroup, null);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
224
|
let filteredStations = stations;
|
|
162
225
|
|
|
163
226
|
if (companies) {
|
|
@@ -166,10 +229,8 @@ class VehicleRentalOverlay extends _reactLeaflet.MapLayer {
|
|
|
166
229
|
|
|
167
230
|
if (!filteredStations || filteredStations.length === 0) {
|
|
168
231
|
return /*#__PURE__*/_react.default.createElement(_reactLeaflet.FeatureGroup, null);
|
|
169
|
-
} //
|
|
170
|
-
|
|
232
|
+
} // Convert map symbols for this overlay to zoomBasedSymbolType.
|
|
171
233
|
|
|
172
|
-
const zoom = this.props.leaflet.map.getZoom(); // Convert map symbols for this overlay to zoomBasedSymbolType.
|
|
173
234
|
|
|
174
235
|
const symbols = this.convertToZoomMarkerSymbols(mapSymbols);
|
|
175
236
|
return /*#__PURE__*/_react.default.createElement(_reactLeaflet.FeatureGroup, null, /*#__PURE__*/_react.default.createElement(_zoomBasedMarkers.default, {
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.js"],"names":["VehicleRentalOverlay","MapLayer","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","stationIsHub","configCompanies","getStationName","setLocation","props","stationName","location","lat","y","lon","x","name","spacesAvailable","createLeafletElement","updateLeafletElement","startRefreshing","refreshVehicles","refreshTimer","setInterval","stopRefreshing","clearInterval","componentDidMount","visible","componentWillUnmount","componentDidUpdate","prevProps","render","companies","stations","filteredStations","filter","networks","value","includes","length","leaflet","getZoom","symbols","arrayOf","companyType","string","func","vehicleRentalMapOverlaySymbolsType","bool","defaultProps","stationNetworks","itinerary","getCompaniesLabelFromNetworks","id","isFloatingCar","isFloatingVehicle","GenericMarker"],"mappings":"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","sourcesContent":["import { 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 { FeatureGroup, MapLayer, Popup, withLeaflet } from \"react-leaflet\";\n\nimport {\n GenericMarker,\n HubAndFloatingBike,\n SharedBikeCircle\n} from \"./DefaultMarkers\";\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 /**\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 componentDidMount() {\n const { visible } = this.props;\n if (visible) this.startRefreshing();\n }\n\n componentWillUnmount() {\n this.stopRefreshing();\n }\n\n componentDidUpdate(prevProps) {\n if (!prevProps.visible && this.props.visible) {\n this.startRefreshing();\n } else if (prevProps.visible && !this.props.visible) {\n this.stopRefreshing();\n }\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>Available bikes: {station.bikesAvailable}</div>\n <div>Available docks: {station.spacesAvailable}</div>\n </BaseMapStyled.PopupRow>\n )}\n\n {/* Set as from/to toolbar */}\n <BaseMapStyled.PopupRow>\n <b>Plan a trip:</b>\n <FromToLocationPicker\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, visible } = this.props;\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 if (!visible) {\n return <FeatureGroup />;\n }\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 // get zoom to check which symbol to render\n const zoom = this.props.leaflet.map.getZoom();\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","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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opentripplanner/vehicle-rental-overlay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
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",
|
|
@@ -18,17 +18,19 @@
|
|
|
18
18
|
"url": "git+https://github.com/opentripplanner/otp-ui.git"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@opentripplanner/
|
|
22
|
-
"@opentripplanner/
|
|
23
|
-
"@opentripplanner/
|
|
21
|
+
"@opentripplanner/core-utils": "^4.5.0",
|
|
22
|
+
"@opentripplanner/from-to-location-picker": "^2.1.0",
|
|
23
|
+
"@opentripplanner/zoom-based-markers": "^1.2.1",
|
|
24
|
+
"@styled-icons/fa-solid": "^10.34.0",
|
|
25
|
+
"flat": "^5.0.2",
|
|
24
26
|
"lodash.memoize": "^4.1.2",
|
|
25
|
-
"prop-types": "^15.7.2"
|
|
26
|
-
"@styled-icons/fa-solid": "^10.34.0"
|
|
27
|
+
"prop-types": "^15.7.2"
|
|
27
28
|
},
|
|
28
29
|
"peerDependencies": {
|
|
29
|
-
"@opentripplanner/base-map": "^
|
|
30
|
+
"@opentripplanner/base-map": "^2.0.0",
|
|
30
31
|
"react": "^16.14.0",
|
|
31
32
|
"react-dom": "^16.8.6",
|
|
33
|
+
"react-intl": "^5.24.6",
|
|
32
34
|
"react-leaflet": "^2.6.1",
|
|
33
35
|
"styled-components": "^5.3.0"
|
|
34
36
|
}
|
|
@@ -22,10 +22,13 @@ const templatePropTypes = {
|
|
|
22
22
|
/** The children of the component. */
|
|
23
23
|
children: PropTypes.node,
|
|
24
24
|
/** The rental vehicle or station to render. */
|
|
25
|
-
entity: coreUtils.types.stationType.isRequired
|
|
25
|
+
entity: coreUtils.types.stationType.isRequired,
|
|
26
|
+
/** leaflet attribute to control tabindex value for keyboaryd-only / SR users */
|
|
27
|
+
keyboard: PropTypes.bool
|
|
26
28
|
};
|
|
27
29
|
const templateDefaultProps = {
|
|
28
|
-
children: null
|
|
30
|
+
children: null,
|
|
31
|
+
keyboard: false
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
/**
|
|
@@ -38,7 +41,7 @@ export const SharedBikeCircle = ({
|
|
|
38
41
|
pixels,
|
|
39
42
|
strokeColor
|
|
40
43
|
}) => {
|
|
41
|
-
const GeneratedMarker = ({ children, entity: station }) => {
|
|
44
|
+
const GeneratedMarker = ({ children, keyboard, entity: station }) => {
|
|
42
45
|
let newStrokeColor = strokeColor || fillColor;
|
|
43
46
|
|
|
44
47
|
if (!station.isFloatingBike) {
|
|
@@ -51,6 +54,7 @@ export const SharedBikeCircle = ({
|
|
|
51
54
|
color={newStrokeColor}
|
|
52
55
|
fillColor={fillColor}
|
|
53
56
|
fillOpacity={1}
|
|
57
|
+
keyboard={keyboard}
|
|
54
58
|
radius={pixels - (station.isFloatingBike ? 1 : 0)}
|
|
55
59
|
weight={1}
|
|
56
60
|
>
|
|
@@ -68,7 +72,7 @@ export const SharedBikeCircle = ({
|
|
|
68
72
|
* A component that renders rental bike entities
|
|
69
73
|
* either as a bike or a bike dock (or hub, showing spaces available).
|
|
70
74
|
*/
|
|
71
|
-
export const HubAndFloatingBike = ({ children, entity: station }) => {
|
|
75
|
+
export const HubAndFloatingBike = ({ children, keyboard, entity: station }) => {
|
|
72
76
|
let icon;
|
|
73
77
|
if (station.isFloatingBike) {
|
|
74
78
|
icon = floatingBikeIcon;
|
|
@@ -80,7 +84,7 @@ export const HubAndFloatingBike = ({ children, entity: station }) => {
|
|
|
80
84
|
icon = hubIcons[i];
|
|
81
85
|
}
|
|
82
86
|
return (
|
|
83
|
-
<Marker icon={icon} position={[station.y, station.x]}>
|
|
87
|
+
<Marker icon={icon} keyboard={keyboard} position={[station.y, station.x]}>
|
|
84
88
|
{children}
|
|
85
89
|
</Marker>
|
|
86
90
|
);
|
|
@@ -110,8 +114,12 @@ const getStationMarkerByColor = memoize(color =>
|
|
|
110
114
|
export const GenericMarker = ({ fillColor = "gray" }) => {
|
|
111
115
|
const markerIcon = getStationMarkerByColor(fillColor);
|
|
112
116
|
|
|
113
|
-
const GeneratedMarker = ({ children, entity: station }) => (
|
|
114
|
-
<Marker
|
|
117
|
+
const GeneratedMarker = ({ children, keyboard, entity: station }) => (
|
|
118
|
+
<Marker
|
|
119
|
+
icon={markerIcon}
|
|
120
|
+
keyboard={keyboard}
|
|
121
|
+
position={[station.y, station.x]}
|
|
122
|
+
>
|
|
115
123
|
{children}
|
|
116
124
|
</Marker>
|
|
117
125
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import BaseMap from "@opentripplanner/base-map";
|
|
2
2
|
import coreUtils from "@opentripplanner/core-utils";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import React
|
|
4
|
+
import React from "react";
|
|
5
5
|
import { CircleMarker } from "react-leaflet";
|
|
6
6
|
import { action } from "@storybook/addon-actions";
|
|
7
7
|
import { boolean } from "@storybook/addon-knobs";
|
|
@@ -11,7 +11,6 @@ import bikeRentalStations from "../__mocks__/bike-rental-stations.json";
|
|
|
11
11
|
import carRentalStations from "../__mocks__/car-rental-stations.json";
|
|
12
12
|
import eScooterStations from "../__mocks__/e-scooter-rental-stations.json";
|
|
13
13
|
import { HubAndFloatingBike } from "./DefaultMarkers";
|
|
14
|
-
import LeafletLayerControlInterface from "./leaflet-layer-control-interface";
|
|
15
14
|
|
|
16
15
|
import "../../../node_modules/leaflet/dist/leaflet.css";
|
|
17
16
|
|
|
@@ -165,51 +164,32 @@ const EScooterMapSymbols = [
|
|
|
165
164
|
];
|
|
166
165
|
const setLocation = action("setLocation");
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
constructor() {
|
|
170
|
-
super();
|
|
171
|
-
this.state = { zoom: 13 };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
onViewportChanged = ({ zoom }) => {
|
|
175
|
-
const { zoom: stateZoom } = this.state;
|
|
176
|
-
if (zoom !== stateZoom) {
|
|
177
|
-
this.setState({ zoom });
|
|
178
|
-
}
|
|
179
|
-
};
|
|
167
|
+
const INITIAL_ZOOM = 13;
|
|
180
168
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
stations={stations}
|
|
206
|
-
visible={visible}
|
|
207
|
-
zoom={zoom}
|
|
208
|
-
/>
|
|
209
|
-
</BaseMap>
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
169
|
+
const ZoomControlledMapWithVehicleRentalOverlay = ({
|
|
170
|
+
companies,
|
|
171
|
+
getStationName,
|
|
172
|
+
mapSymbols,
|
|
173
|
+
refreshVehicles,
|
|
174
|
+
stations,
|
|
175
|
+
visible
|
|
176
|
+
}) => (
|
|
177
|
+
// Caution, <BaseMap> must be a direct parent of <VehicleRentalOverlay>.
|
|
178
|
+
// Therefore, do not place <BaseMap> in a decorator at this time.
|
|
179
|
+
<BaseMap center={center} zoom={INITIAL_ZOOM}>
|
|
180
|
+
<VehicleRentalOverlay
|
|
181
|
+
configCompanies={configCompanies}
|
|
182
|
+
companies={companies}
|
|
183
|
+
getStationName={getStationName}
|
|
184
|
+
setLocation={setLocation}
|
|
185
|
+
mapSymbols={mapSymbols}
|
|
186
|
+
name="Rentals"
|
|
187
|
+
refreshVehicles={refreshVehicles}
|
|
188
|
+
stations={stations}
|
|
189
|
+
visible={visible}
|
|
190
|
+
/>
|
|
191
|
+
</BaseMap>
|
|
192
|
+
);
|
|
213
193
|
|
|
214
194
|
ZoomControlledMapWithVehicleRentalOverlay.propTypes = {
|
|
215
195
|
companies: PropTypes.arrayOf(PropTypes.string.isRequired),
|
|
@@ -225,7 +205,7 @@ ZoomControlledMapWithVehicleRentalOverlay.defaultProps = {
|
|
|
225
205
|
companies: null,
|
|
226
206
|
getStationName: undefined,
|
|
227
207
|
mapSymbols: null,
|
|
228
|
-
visible:
|
|
208
|
+
visible: true
|
|
229
209
|
};
|
|
230
210
|
|
|
231
211
|
function customStationName(_, station) {
|
|
@@ -249,7 +229,7 @@ export const RentalBicycles = () => (
|
|
|
249
229
|
export const RentalBicyclesVisibilityControlledByKnob = () => {
|
|
250
230
|
const isOverlayVisible = boolean(
|
|
251
231
|
"Toggle visibility of vehicle rental overlay",
|
|
252
|
-
|
|
232
|
+
false
|
|
253
233
|
);
|
|
254
234
|
return (
|
|
255
235
|
<ZoomControlledMapWithVehicleRentalOverlay
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import flatten from "flat";
|
|
1
2
|
import { Styled as BaseMapStyled } from "@opentripplanner/base-map";
|
|
2
3
|
import coreUtils from "@opentripplanner/core-utils";
|
|
3
4
|
import FromToLocationPicker from "@opentripplanner/from-to-location-picker";
|
|
4
5
|
import ZoomBasedMarkers from "@opentripplanner/zoom-based-markers";
|
|
5
6
|
import PropTypes from "prop-types";
|
|
6
7
|
import React from "react";
|
|
8
|
+
import { FormattedMessage } from "react-intl";
|
|
7
9
|
import { FeatureGroup, MapLayer, Popup, withLeaflet } from "react-leaflet";
|
|
8
10
|
|
|
9
11
|
import {
|
|
@@ -12,12 +14,28 @@ import {
|
|
|
12
14
|
SharedBikeCircle
|
|
13
15
|
} from "./DefaultMarkers";
|
|
14
16
|
|
|
17
|
+
// Load the default messages.
|
|
18
|
+
import defaultEnglishMessages from "../i18n/en-US.yml";
|
|
19
|
+
|
|
20
|
+
// HACK: We should flatten the messages loaded above because
|
|
21
|
+
// the YAML loaders behave differently between webpack and our version of jest:
|
|
22
|
+
// - the yaml loader for webpack returns a nested object,
|
|
23
|
+
// - the yaml loader for jest returns messages with flattened ids.
|
|
24
|
+
const defaultMessages = flatten(defaultEnglishMessages);
|
|
25
|
+
|
|
15
26
|
/**
|
|
16
27
|
* This vehicle rental overlay can be used to render vehicle rentals of various
|
|
17
28
|
* types. This layer can be configured to show different styles of markers at
|
|
18
29
|
* different zoom levels.
|
|
19
30
|
*/
|
|
20
31
|
class VehicleRentalOverlay extends MapLayer {
|
|
32
|
+
constructor(props) {
|
|
33
|
+
super(props);
|
|
34
|
+
this.state = {
|
|
35
|
+
zoom: props.leaflet.map.getZoom()
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
21
39
|
/**
|
|
22
40
|
* This helper method will be passed to the ZoomBasedMarkers symbolTransform prop.
|
|
23
41
|
* It creates a component that inserts a popup
|
|
@@ -92,23 +110,50 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
92
110
|
if (this.refreshTimer) clearInterval(this.refreshTimer);
|
|
93
111
|
}
|
|
94
112
|
|
|
113
|
+
/**
|
|
114
|
+
* When the layer is added (or toggled on, or its visibility becomes true),
|
|
115
|
+
* start refreshing vehicle positions.
|
|
116
|
+
*/
|
|
117
|
+
onOverlayAdded = () => {
|
|
118
|
+
this.startRefreshing();
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* When the layer is removed (or toggled off, or its visibility becomes false),
|
|
123
|
+
* stop refreshing vehicle positions.
|
|
124
|
+
*/
|
|
125
|
+
onOverlayRemoved = () => {
|
|
126
|
+
this.stopRefreshing();
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Listen to changes on the BaseMap's center or zoom.
|
|
131
|
+
* @param viewport The viewport data. See https://github.com/PaulLeCam/react-leaflet/blob/master/example/components/viewport.js for details.
|
|
132
|
+
*/
|
|
133
|
+
onViewportChanged = viewport => {
|
|
134
|
+
const { zoom: newZoom } = viewport;
|
|
135
|
+
if (this.state.zoom !== newZoom) {
|
|
136
|
+
this.setState({ zoom: newZoom });
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Upon mounting, see whether the vehicles should be fetched,
|
|
142
|
+
* and also call the register overlay prop that the
|
|
143
|
+
* @opentripplanner/base-map package has injected to listen to zoom/position changes.
|
|
144
|
+
*/
|
|
95
145
|
componentDidMount() {
|
|
96
|
-
const { visible } = this.props;
|
|
146
|
+
const { registerOverlay, visible } = this.props;
|
|
97
147
|
if (visible) this.startRefreshing();
|
|
148
|
+
if (typeof registerOverlay === "function") {
|
|
149
|
+
registerOverlay(this);
|
|
150
|
+
}
|
|
98
151
|
}
|
|
99
152
|
|
|
100
153
|
componentWillUnmount() {
|
|
101
154
|
this.stopRefreshing();
|
|
102
155
|
}
|
|
103
156
|
|
|
104
|
-
componentDidUpdate(prevProps) {
|
|
105
|
-
if (!prevProps.visible && this.props.visible) {
|
|
106
|
-
this.startRefreshing();
|
|
107
|
-
} else if (prevProps.visible && !this.props.visible) {
|
|
108
|
-
this.stopRefreshing();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
157
|
/**
|
|
113
158
|
* Render some popup html for a station. This contains custom logic for
|
|
114
159
|
* displaying rental vehicles in the TriMet MOD website that might not be
|
|
@@ -130,15 +175,33 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
130
175
|
{/* render dock info if it is available */}
|
|
131
176
|
{stationIsHub && (
|
|
132
177
|
<BaseMapStyled.PopupRow>
|
|
133
|
-
<div>
|
|
134
|
-
|
|
178
|
+
<div>
|
|
179
|
+
<FormattedMessage
|
|
180
|
+
defaultMessage={
|
|
181
|
+
defaultMessages["otpUi.VehicleRentalOverlay.availableBikes"]
|
|
182
|
+
}
|
|
183
|
+
description="Label text for the number of bikes available"
|
|
184
|
+
id="otpUi.VehicleRentalOverlay.availableBikes"
|
|
185
|
+
values={{ value: station.bikesAvailable }}
|
|
186
|
+
/>
|
|
187
|
+
</div>
|
|
188
|
+
<div>
|
|
189
|
+
<FormattedMessage
|
|
190
|
+
defaultMessage={
|
|
191
|
+
defaultMessages["otpUi.VehicleRentalOverlay.availableDocks"]
|
|
192
|
+
}
|
|
193
|
+
description="Label text for the number of docks available"
|
|
194
|
+
id="otpUi.VehicleRentalOverlay.availableDocks"
|
|
195
|
+
values={{ value: station.spacesAvailable }}
|
|
196
|
+
/>
|
|
197
|
+
</div>
|
|
135
198
|
</BaseMapStyled.PopupRow>
|
|
136
199
|
)}
|
|
137
200
|
|
|
138
201
|
{/* Set as from/to toolbar */}
|
|
139
202
|
<BaseMapStyled.PopupRow>
|
|
140
|
-
<b>Plan a trip:</b>
|
|
141
203
|
<FromToLocationPicker
|
|
204
|
+
label
|
|
142
205
|
location={location}
|
|
143
206
|
setLocation={setLocation}
|
|
144
207
|
/>
|
|
@@ -149,14 +212,12 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
149
212
|
};
|
|
150
213
|
|
|
151
214
|
render() {
|
|
152
|
-
const { companies, mapSymbols, stations
|
|
215
|
+
const { companies, mapSymbols, stations } = this.props;
|
|
216
|
+
const { zoom } = this.state;
|
|
153
217
|
// Render an empty FeatureGroup if the rental vehicles should not be visible
|
|
154
218
|
// on the map. Otherwise previous stations may still be shown due to some
|
|
155
219
|
// react-leaflet internals, maybe? Also, do not return null because that will
|
|
156
220
|
// prevent the overlay from appearing in the layer controls.
|
|
157
|
-
if (!visible) {
|
|
158
|
-
return <FeatureGroup />;
|
|
159
|
-
}
|
|
160
221
|
|
|
161
222
|
let filteredStations = stations;
|
|
162
223
|
if (companies) {
|
|
@@ -170,9 +231,6 @@ class VehicleRentalOverlay extends MapLayer {
|
|
|
170
231
|
return <FeatureGroup />;
|
|
171
232
|
}
|
|
172
233
|
|
|
173
|
-
// get zoom to check which symbol to render
|
|
174
|
-
const zoom = this.props.leaflet.map.getZoom();
|
|
175
|
-
|
|
176
234
|
// Convert map symbols for this overlay to zoomBasedSymbolType.
|
|
177
235
|
const symbols = this.convertToZoomMarkerSymbols(mapSymbols);
|
|
178
236
|
|