Skip to content

Commit

Permalink
fix(Add lat/lng validation): lat/lng validation done in core-utils/ma…
Browse files Browse the repository at this point in the history
…p; added support for isRequired
  • Loading branch information
binh-dam-ibigroup committed Dec 18, 2019
1 parent 0cad5d1 commit 8659b67
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 21 deletions.
3 changes: 2 additions & 1 deletion packages/base-map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"dependencies": {
"leaflet": "^1.6.0",
"react-leaflet": "^2.6.0",
"prop-types": "^15.7.2"
"prop-types": "^15.7.2",
"core-utils": "0.0.1"
},
"peerDependencies": {
"react": "^16.8.6",
Expand Down
23 changes: 3 additions & 20 deletions packages/base-map/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { LayersControl, Map, Popup, TileLayer } from "react-leaflet";
import { LatlngPropType } from "@opentripplanner/core-utils/lib/react-props";
import L from "leaflet";

// eslint-disable-next-line func-names
Expand Down Expand Up @@ -169,24 +170,6 @@ class BaseMap extends Component {
}
}

const twoNumberArrayChecker = (
propValue,
key,
componentName,
location,
propFullName
) => {
// Source: https://reactjs.org/docs/typechecking-with-proptypes.html#react.proptypes
if (
!Array.isArray(propValue) ||
propValue.length !== 2 ||
!Number.isFinite(propValue[key])
) {
return new Error(`${propFullName} needs to be an array of two numbers`);
}
return null;
};

BaseMap.propTypes = {
/**
* Zero, one, or multiple components that extend { MapLayer } from 'react-leaflet'.
Expand Down Expand Up @@ -214,7 +197,7 @@ BaseMap.propTypes = {
/**
* The center of the map, as a [lat, lng] array.
*/
center: PropTypes.arrayOf(twoNumberArrayChecker).isRequired,
center: LatlngPropType.isRequired,
/**
* The maximum zoom level allowed on the map.
*/
Expand Down Expand Up @@ -250,7 +233,7 @@ BaseMap.propTypes = {
/**
* The coordinates of the popup object to display, as a [lat, lng] array.
*/
popupLocation: PropTypes.arrayOf(twoNumberArrayChecker),
popupLocation: LatlngPropType,
/**
* The zoom level of the map.
*/
Expand Down
17 changes: 17 additions & 0 deletions packages/core-utils/src/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,20 @@ export function itineraryToTransitive(itin) {
export function isBikeshareStation(place) {
return place.place_id.lastIndexOf("bicycle_rent_station") !== -1;
}

export function isValidLat(lat) {
return Number.isFinite(lat) && lat >= -90 && lat <= 90;
}

export function isValidLng(lng) {
return Number.isFinite(lng) && lng >= -180 && lng <= 180;
}

export function isValidLatLng(arr) {
return (
Array.isArray(arr) &&
arr.length === 2 &&
isValidLat(arr[0]) &&
isValidLng(arr[1])
);
}
36 changes: 36 additions & 0 deletions packages/core-utils/src/react-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { ReactPropTypeLocationNames } from "react";
import { isValidLatLng } from "./map";

/**
* Utility function to help create chained validators
* per https://www.ian-thomas.net/custom-proptype-validation-with-react/
* @param {*} validator The validator to use.
*/
export function createChainableTypeChecker(validator) {
function checkType(isRequired, props, propName, componentName, location) {
componentName = componentName || "ANONYMOUS";
if (props[propName] == null) {
if (isRequired) {
const locationName = ReactPropTypeLocationNames[location];
return new Error(
`Required '${locationName}/${propName}' was not specified in '${componentName}'.`
);
}
return null;
}
return validator(props, propName, componentName, location);
}

const chainedCheckType = checkType.bind(null, false);
chainedCheckType.isRequired = checkType.bind(null, true);

return chainedCheckType;
}

export const LatlngPropType = createChainableTypeChecker((props, propName) => {
// Source: https://reactjs.org/docs/typechecking-with-proptypes.html#react.proptypes
if (!isValidLatLng(props[propName])) {
return new Error(`${propName} needs to be a [lat, lng] array`);
}
return null;
});

0 comments on commit 8659b67

Please sign in to comment.