Skip to content

Commit

Permalink
Merge branch 'metro-mode-selector' into metro-mode-selector-qbd
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup committed Feb 27, 2023
2 parents c80bbdd + 5e97475 commit c296983
Show file tree
Hide file tree
Showing 50 changed files with 5,887 additions and 16,014 deletions.
19,662 changes: 3,894 additions & 15,768 deletions __snapshots__/storybook.test.ts.snap

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
"babel-plugin-styled-components",
"@babel/plugin-transform-runtime",
"import-graphql"
"import-graphql",
"@babel/plugin-proposal-nullish-coalescing-operator"
],
"presets": [
["@babel/preset-env", { "targets": { "node": "current" } }],
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@babel/cli": "^7.10",
"@babel/core": "^7.10",
"@babel/plugin-proposal-class-properties": "^7.10",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.14.0",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.10",
Expand Down
2 changes: 1 addition & 1 deletion packages/core-utils/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opentripplanner/core-utils",
"version": "8.0.1",
"version": "8.1.1",
"description": "Core functionality that is shared among numerous UI components",
"engines": {
"node": ">=13"
Expand Down
68 changes: 68 additions & 0 deletions packages/core-utils/src/itinerary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Config,
ElevationProfile,
FlexBookingInfo,
Itinerary,
ItineraryOnlyLegsRequired,
LatLngArray,
Leg,
Expand Down Expand Up @@ -561,3 +562,70 @@ export function getDisplayedStopId(placeOrStop: Place | Stop): string {
}
return stopCode || stopId?.split(":")[1] || stopId;
}

/**
* Adds the fare product info to each leg in an itinerary, from the itinerary's fare property
* @param itinerary Itinerary with legProducts in fare object
* @returns Itinerary with legs that have fare products attached to them
*/
export function getLegsWithFares(itinerary: Itinerary): Leg[] {
return itinerary.legs.map((leg, i) => ({
...leg,
fareProducts: itinerary.fare?.legProducts
?.filter(lp => lp?.legIndices?.includes(i))
.flatMap(lp => lp.products)
}));
}

/**
* Extracts useful data from the fare products on a leg, such as the leg cost and transfer info.
* @param leg Leg with fare products (must have used getLegsWithFares)
* @param category Rider category
* @param container Fare container (cash, electronic)
* @returns Object containing price as well as the transfer discount amount, if a transfer was used.
*/
export function getLegCost(
leg: Leg,
category: string,
container: string
): { price?: Money; transferAmount?: number } {
if (!leg.fareProducts) return { price: undefined };

const relevantFareProducts = leg.fareProducts.filter(
fp => fp.category.name === category && fp.container.name === container
);
const totalCost = relevantFareProducts.find(fp => fp.name === "rideCost")
?.amount;
const transferFareProduct = relevantFareProducts.find(
fp => fp.name === "transfer"
);

return {
price: totalCost,
transferAmount: transferFareProduct?.amount?.cents
};
}

/**
* Returns the total itinerary cost for a given set of legs.
* @param legs Itinerary legs with fare products (must have used getLegsWithFares)
* @param category Rider category (youth, regular, senior)
* @param container Fare container (cash, electronic)
* @returns Money object for the total itinerary cost.
*/
export function getItineraryCost(
legs: Leg[],
category: string,
container: string
): Money {
return legs
.filter(leg => !!leg.fareProducts)
.map(leg => getLegCost(leg, category, container).price)
.reduce<Money>(
(prev, cur) => ({
cents: prev.cents + cur?.cents || 0,
currency: prev.currency ?? cur?.currency
}),
{ cents: 0, currency: null }
);
}
1 change: 1 addition & 0 deletions packages/core-utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"target": "es2019",
"outDir": "./lib",
"rootDir": "./src",
"lib": ["es2019", "dom"],
"skipLibCheck": true
},
"include": ["src/**/*"]
Expand Down
2 changes: 1 addition & 1 deletion packages/geocoder/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opentripplanner/geocoder",
"version": "1.3.4",
"version": "1.4.0",
"description": "Geocoding tools for multiple geocoding providers",
"main": "lib/index.js",
"module": "esm/index.js",
Expand Down
51 changes: 51 additions & 0 deletions packages/geocoder/src/apis/otp/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@

// eslint-disable-next-line prettier/prettier
import type { AutocompleteQuery } from "../../geocoders/types"

type FetchArgs = {
url: string
query: string
}

type OTPGeocoderResponse = {
results: {
lat: number,
lng: number,
description: string,
id: string
}[]
} | undefined


function run({ query, url }: FetchArgs): Promise<OTPGeocoderResponse> {
// TODO: Support corners/osm nodes?
return fetch(`${url}/geocode?corners=false&query=${query}`)
.then(res => res.text())
.then(res => JSON.parse(`{"results": ${res}}`));
}

/**
* Search for an address using
* OTP Geocoder
*
* @param {Object} $0
* @param {string} $0.url The OTP instance, ending with /default/
* @param {string} $0.text query
* @return {Promise} A Promise that'll get resolved with the autocomplete result
*/
async function autocomplete({
url,
text
}: AutocompleteQuery): Promise<OTPGeocoderResponse> {
return run({
query: text,
url
})
}

function search(): Promise<unknown> { console.warn("Not implemented"); return null }
function reverse(): Promise<unknown> { console.warn("Not implemented"); return null }


export { autocomplete, reverse, search };
export type { OTPGeocoderResponse }
37 changes: 37 additions & 0 deletions packages/geocoder/src/geocoders/otp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Prettier does not support typescript annotation
// eslint-disable-next-line prettier/prettier
import type { AutocompleteQuery, MultiGeocoderResponse } from "./types";

import Geocoder from "./abstract-geocoder";
import { OTPGeocoderResponse } from "../apis/otp";

/**
* Allows fetching results from OTP instance with the geocoder endpoint enabled
*/
export default class OTPGeocoder extends Geocoder {
getAutocompleteQuery(query: AutocompleteQuery): AutocompleteQuery {
const {
baseUrl,
} = this.geocoderConfig;
return {
url: baseUrl,
...query
};
}


rewriteAutocompleteResponse(response: OTPGeocoderResponse): MultiGeocoderResponse {
return {
features: response?.results?.map(stop => ({
geometry: { type: "Point", coordinates: [stop.lng, stop.lat] },
id: stop.id,
// TODO: if non-stops are supported, these need to be detected here and
// this layer property updated accordingly
properties: { layer: "stops", source: "otp", name: stop.description, label: stop.description },
type: "Feature"
})),
type: "FeatureCollection"
};
}

}
33 changes: 32 additions & 1 deletion packages/geocoder/src/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const GeocoderTester = ({
const [enableGeocodeEarth, setEnableGeocodeEarth] = useState(true);
const [enableHere, setEnableHere] = useState(true);
const [enablePhoton, setEnablePhoton] = useState(true);
const [enableOtp, setEnableOtp] = useState(false);
const [otpHost, setOtpHost] = useState("");
const [
reverseUseFeatureCollection,
setReverseUseFeatureCollection
Expand Down Expand Up @@ -57,6 +59,12 @@ const GeocoderTester = ({
type: "PHOTON"
});

const otpGeocoder = getGeocoder({
baseUrl: otpHost,
size: 1,
type: "OTP"
});

const searchObj: AnyGeocoderQuery = {
text: searchTerm
};
Expand All @@ -77,15 +85,29 @@ const GeocoderTester = ({
const photonRes = enablePhoton
? await photonGeocoder[endpoint](searchObj)
: null;
const otpRes = enableOtp ? await otpGeocoder[endpoint](searchObj) : null;
onResults({
hereRes,
peliasRes,
photonRes
photonRes,
otpRes
});
};

return (
<div>
{endpoint === "autocomplete" && (
<div>
<label htmlFor="otpHost">
OTP Host (ending with{" "}
<pre style={{ display: "inline" }}>/router/default</pre>)
</label>
<input
id="otpHost"
onChange={e => setOtpHost(e.target.value)}
></input>
</div>
)}
{/* Boundary Input */}
{endpoint !== "reverse" && (
<div>
Expand Down Expand Up @@ -219,6 +241,15 @@ const GeocoderTester = ({
type="checkbox"
/>
</label>
<label htmlFor="otp">
OTP:
<input
checked={enableOtp}
id="otp"
onChange={e => setEnableOtp(e.target.checked)}
type="checkbox"
/>
</label>
</div>
<div>
{endpoint !== "reverse" && (
Expand Down
4 changes: 4 additions & 0 deletions packages/geocoder/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import * as pelias from "isomorphic-mapzen-search";
import memoize from "lodash.memoize";
import * as here from "./apis/here";
import * as photon from "./apis/photon";
import * as otp from "./apis/otp";

import ArcGISGeocoder from "./geocoders/arcgis";
import NoApiGeocoder from "./geocoders/noapi";
import PeliasGeocoder from "./geocoders/pelias";
import HereGeocoder from "./geocoders/here";
import PhotonGeocoder from "./geocoders/photon";
import OTPGeocoder from "./geocoders/otp";

// Prettier does not support typescript annotation
// eslint-disable-next-line prettier/prettier
Expand All @@ -29,6 +31,8 @@ const getGeocoder = memoize((geocoderConfig: GeocoderConfig & { type: string })
return new HereGeocoder(here, geocoderConfig);
case "PHOTON":
return new PhotonGeocoder(photon, geocoderConfig);
case "OTP":
return new OTPGeocoder(otp, geocoderConfig);
default:
console.error(`Unknown geocoder type: "${type}". Using NoApiGeocoder.`);
return new NoApiGeocoder();
Expand Down
2 changes: 1 addition & 1 deletion packages/itinerary-body/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opentripplanner/itinerary-body",
"version": "4.1.8",
"version": "4.1.9",
"description": "A component for displaying an itinerary body of a trip planning result",
"main": "lib/index.js",
"module": "esm/index.js",
Expand Down
8 changes: 6 additions & 2 deletions packages/itinerary-body/src/TransitLegBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ class TransitLegBody extends Component<Props, State> {
leg
);

// If the config contains an operator name, prefer that one over the
// one provided by OTP

const transitOperatorName = transitOperator?.name || agencyName;
// If the config contains an operator with a logo URL, prefer that over the
// one provided by OTP (which is derived from agency.txt#agency_branding_url)
const logoUrl =
Expand All @@ -172,6 +176,7 @@ class TransitLegBody extends Component<Props, State> {
!(shouldCollapseDueToAlertCount || alwaysCollapseAlerts) || !leg.alerts;
const expandAlerts = alertsExpanded || shouldOnlyShowAlertsExpanded;
const fareForLeg = this.getFareForLeg(leg, fare);

return (
<>
{TransitLegSubheader && <TransitLegSubheader leg={leg} />}
Expand Down Expand Up @@ -216,7 +221,7 @@ class TransitLegBody extends Component<Props, State> {
rel="noopener noreferrer"
target="_blank"
>
{agencyName}
{transitOperatorName}
{logoUrl && <img alt="" src={logoUrl} height={25} />}
</a>
)
Expand All @@ -236,7 +241,6 @@ class TransitLegBody extends Component<Props, State> {
/>
</S.CallAheadWarning>
)}

{/* Alerts toggle */}
{!shouldOnlyShowAlertsExpanded && (
<S.TransitAlertToggle onClick={this.onToggleAlertsClick}>
Expand Down
Loading

0 comments on commit c296983

Please sign in to comment.