Skip to content

Commit

Permalink
Merge branch 'dev-2.x' into gmap-mobility-profile
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup committed Jan 19, 2024
2 parents a7ca124 + 3f69e5e commit 37ab3ec
Show file tree
Hide file tree
Showing 265 changed files with 5,484 additions and 3,194 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
OpenTripPlanner (OTP) is an open source multi-modal trip planner, focusing on travel by scheduled
public transportation in combination with bicycling, walking, and mobility services including bike
share and ride hailing. Its server component runs on any platform with a Java virtual machine (
including Linux, Mac, and Windows). It exposes REST and GraphQL APIs that can be accessed by various
including Linux, Mac, and Windows). It exposes GraphQL APIs that can be accessed by various
clients including open source Javascript components and native mobile applications. It builds its
representation of the transportation network from open data in open standard file formats (primarily
GTFS and OpenStreetMap). It applies real-time updates and alerts with immediate visibility to
Expand Down
56 changes: 28 additions & 28 deletions client-next/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion client-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"bootstrap": "5.3.1",
"graphql": "16.8.0",
"graphql-request": "6.1.0",
"maplibre-gl": "3.3.0",
"maplibre-gl": "3.6.2",
"react": "18.2.0",
"react-bootstrap": "2.8.0",
"react-dom": "18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion client-next/src/components/MapView/ContextMenuPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { TripQueryVariables } from '../../gql/graphql.ts';
import { LngLat, Popup } from 'react-map-gl';
import { LngLat, Popup } from 'react-map-gl/maplibre';
import { Button, ButtonGroup } from 'react-bootstrap';

export function ContextMenuPopup({
Expand Down
10 changes: 8 additions & 2 deletions client-next/src/components/MapView/GeometryPropertyPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LngLat, Popup } from 'react-map-gl';
import { LngLat, Popup } from 'react-map-gl/maplibre';
import { Table } from 'react-bootstrap';

export function GeometryPropertyPopup({
Expand All @@ -11,7 +11,13 @@ export function GeometryPropertyPopup({
onClose: () => void;
}) {
return (
<Popup latitude={coordinates.lat} longitude={coordinates.lng} closeButton={true} onClose={() => onClose()}>
<Popup
latitude={coordinates.lat}
longitude={coordinates.lng}
closeButton={true}
onClose={() => onClose()}
maxWidth="350px"
>
<Table bordered>
<tbody>
{Object.entries(properties).map(([key, value]) => (
Expand Down
82 changes: 82 additions & 0 deletions client-next/src/components/MapView/LayerControl.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type { ControlPosition } from 'react-map-gl';
import { useControl } from 'react-map-gl';
import { IControl, Map } from 'maplibre-gl';

type LayerControlProps = {
position: ControlPosition;
};

/**
* A maplibre control that allows you to switch vector tile layers on and off.
*
* It appears that you cannot use React elements but have to drop down to raw DOM. Please correct
* me if I'm wrong.
*/
class LayerControl implements IControl {
private readonly container: HTMLDivElement = document.createElement('div');

onAdd(map: Map) {
this.container.className = 'maplibregl-ctrl maplibregl-ctrl-group layer-select';

map.on('load', () => {
// clean on
while (this.container.firstChild) {
this.container.removeChild(this.container.firstChild);
}

const title = document.createElement('h6');
title.textContent = 'Debug layers';
this.container.appendChild(title);

map
.getLayersOrder()
.map((l) => map.getLayer(l))
.filter((s) => s?.type !== 'raster')
.reverse()
.forEach((layer) => {
if (layer) {
const div = document.createElement('div');
const input = document.createElement('input');
input.type = 'checkbox';
input.value = layer.id;
input.id = layer.id;
input.onchange = (e) => {
e.preventDefault();
e.stopPropagation();

if (this.layerVisible(map, layer)) {
map.setLayoutProperty(layer.id, 'visibility', 'none');
} else {
map.setLayoutProperty(layer.id, 'visibility', 'visible');
}
};
input.checked = this.layerVisible(map, layer);
const label = document.createElement('label');
label.textContent = layer.id;
label.htmlFor = layer.id;
div.appendChild(input);
div.appendChild(label);
this.container.appendChild(div);
}
});
});

return this.container;
}

private layerVisible(map: Map, layer: { id: string }) {
return map.getLayoutProperty(layer.id, 'visibility') !== 'none';
}

onRemove() {
this.container.parentNode?.removeChild(this.container);
}
}

export default function DebugLayerControl(props: LayerControlProps) {
useControl(() => new LayerControl(), {
position: props.position,
});

return null;
}
42 changes: 29 additions & 13 deletions client-next/src/components/MapView/MapView.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { LngLat, Map, MapboxGeoJSONFeature, NavigationControl } from 'react-map-gl';
import {
LngLat,
Map,
MapEvent,
MapGeoJSONFeature,
MapMouseEvent,
NavigationControl,
VectorTileSource,
} from 'react-map-gl/maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
import { TripPattern, TripQuery, TripQueryVariables } from '../../gql/graphql.ts';
import { NavigationMarkers } from './NavigationMarkers.tsx';
Expand All @@ -7,17 +15,11 @@ import { useMapDoubleClick } from './useMapDoubleClick.ts';
import { useState } from 'react';
import { ContextMenuPopup } from './ContextMenuPopup.tsx';
import { GeometryPropertyPopup } from './GeometryPropertyPopup.tsx';

// TODO: this should be configurable
const initialViewState = {
latitude: 60.7554885,
longitude: 10.2332855,
zoom: 4,
};
import DebugLayerControl from './LayerControl.tsx';

const styleUrl = import.meta.env.VITE_DEBUG_STYLE_URL;

type PopupData = { coordinates: LngLat; feature: MapboxGeoJSONFeature };
type PopupData = { coordinates: LngLat; feature: MapGeoJSONFeature };

export function MapView({
tripQueryVariables,
Expand All @@ -36,8 +38,8 @@ export function MapView({
const [showContextPopup, setShowContextPopup] = useState<LngLat | null>(null);
const [showPropsPopup, setShowPropsPopup] = useState<PopupData | null>(null);
const showFeaturePropPopup = (
e: mapboxgl.MapMouseEvent & {
features?: mapboxgl.MapboxGeoJSONFeature[] | undefined;
e: MapMouseEvent & {
features?: MapGeoJSONFeature[] | undefined;
},
) => {
if (e.features) {
Expand All @@ -48,6 +50,17 @@ export function MapView({
setShowPropsPopup({ coordinates: e.lngLat, feature: feature });
}
};
const panToWorldEnvelopeIfRequired = (e: MapEvent) => {
const map = e.target;
// if we are really far zoomed out and show the entire world it means that we are not starting
// in a location selected from the URL hash.
// in such a case we pan to the area that is specified in the tile bounds, which is
// provided by the WorldEnvelopeService
if (map.getZoom() < 2) {
const source = map.getSource('stops') as VectorTileSource;
map.fitBounds(source.bounds, { maxDuration: 50, linear: true });
}
};

return (
<div className="map-container below-content">
Expand All @@ -56,25 +69,28 @@ export function MapView({
mapLib={import('maplibre-gl')}
// @ts-ignore
mapStyle={styleUrl}
initialViewState={initialViewState}
onDblClick={onMapDoubleClick}
onContextMenu={(e) => {
setShowContextPopup(e.lngLat);
}}
interactiveLayerIds={['regular-stop']}
// it's unfortunate that you have to list these layers here.
// maybe there is a way around it: https://github.com/visgl/react-map-gl/discussions/2343
interactiveLayerIds={['regular-stop', 'vertex', 'edge', 'link']}
onClick={showFeaturePropPopup}
// put lat/long in URL and pan to it on page reload
hash={true}
// disable pitching and rotating the map
touchPitch={false}
dragRotate={false}
onLoad={panToWorldEnvelopeIfRequired}
>
<NavigationControl position="top-left" />
<NavigationMarkers
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
loading={loading}
/>
<DebugLayerControl position="top-right" />
{tripQueryResult?.trip.tripPatterns.length && (
<LegLines tripPattern={tripQueryResult.trip.tripPatterns[selectedTripPatternIndex] as TripPattern} />
)}
Expand Down
2 changes: 1 addition & 1 deletion client-next/src/components/MapView/useMapDoubleClick.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from 'react';
import { TripQueryVariables } from '../../gql/graphql.ts';
import { LngLat, MapLayerMouseEvent } from 'react-map-gl';
import { LngLat, MapLayerMouseEvent } from 'react-map-gl/maplibre';

const setCoordinates = (tripQueryVariables: TripQueryVariables, lngLat: LngLat, key: 'from' | 'to') => ({
...tripQueryVariables,
Expand Down
9 changes: 9 additions & 0 deletions client-next/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,12 @@
font-size: 14px;
padding-left: 2px;
}

/* debug layer selector */

.maplibregl-ctrl-group.layer-select {
padding: 10px;
}
.maplibregl-ctrl-group.layer-select label {
margin-left: 6px;
}
13 changes: 11 additions & 2 deletions doc-templates/UpdaterConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

# Updater configuration

This section covers all options that can be set in the *router-config.json* in the
[updaters](RouterConfiguration.md) section.
This section covers options that can be set in the updaters section of `router-config.json`.
See the parameter summary and examples in the router configuration documentation

Real-time data are those that are not added to OTP during the graph build phase but during runtime.

Expand Down Expand Up @@ -44,6 +44,15 @@ The information is downloaded in a single HTTP request and polled regularly.

<!-- INSERT: stop-time-updater -->

### Streaming TripUpdates via MQTT

This updater connects to an MQTT broker and processes TripUpdates in a streaming fashion. This means
that they will be applied individually in near-realtime rather than in batches at a certain interval.

This system powers the realtime updates in Helsinki and more information can be found
[on Github](https://github.com/HSLdevcom/transitdata).

<!-- INSERT: mqtt-gtfs-rt-updater -->

### Vehicle Positions

Expand Down
4 changes: 4 additions & 0 deletions docs/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle
- Fix high walk reluctance leading to zero egress results for rental searches [#5605](https://github.com/opentripplanner/OpenTripPlanner/pull/5605)
- Remove GTFS-RT websocket updater [#5604](https://github.com/opentripplanner/OpenTripPlanner/pull/5604)
- Add stop layer to new Debug UI [#5602](https://github.com/opentripplanner/OpenTripPlanner/pull/5602)
- Use fallback timezone if no transit data is loaded [#4652](https://github.com/opentripplanner/OpenTripPlanner/pull/4652)
- Add new path for GTFS GraphQL API, remove batch feature [#5581](https://github.com/opentripplanner/OpenTripPlanner/pull/5581)
- Restructure walk/bicycle/car preferences in router-config.json [#5582](https://github.com/opentripplanner/OpenTripPlanner/pull/5582)
- Revert REST API spelling change of real-time [#5629](https://github.com/opentripplanner/OpenTripPlanner/pull/5629)
[](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE)

## 2.4.0 (2023-09-13)
Expand Down
Loading

0 comments on commit 37ab3ec

Please sign in to comment.