Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/dev-2.x' into arrive-by-filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
leonardehrenfried committed Sep 24, 2024
2 parents d37c51c + 9c10a0e commit 4c11b2a
Show file tree
Hide file tree
Showing 52 changed files with 1,454 additions and 538 deletions.
2 changes: 1 addition & 1 deletion client/.env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
VITE_API_URL=http://localhost:8080/otp/transmodel/v3
VITE_DEBUG_STYLE_URL=http://localhost:8080/otp/routers/default/inspector/vectortile/style.json
VITE_GRAPHIQL_URL=http://localhost:8080/graphiql?flavor=transmodel
VITE_GRAPHIQL_URL=http://localhost:8080/graphiql?flavor=transmodel
18 changes: 18 additions & 0 deletions client/package-lock.json

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

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
},
"dependencies": {
"@googlemaps/polyline-codec": "1.0.28",
"@js-temporal/polyfill": "0.4.4",
"bootstrap": "5.3.3",
"graphql": "16.9.0",
"graphql-request": "7.1.0",
Expand Down
13 changes: 8 additions & 5 deletions client/src/components/ItineraryList/ItineraryHeaderContent.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { TripPattern } from '../../gql/graphql.ts';
import { TIME_BOX_WIDTH, useHeaderContentStyleCalculations } from './useHeaderContentStyleCalculations.ts';
import { ItineraryHeaderLegContent } from './ItineraryHeaderLegContent.tsx';
import { useMemo } from 'react';
import { useContext, useMemo } from 'react';
import { formatTime } from '../../util/formatTime.ts';
import { TimeZoneContext } from '../../hooks/TimeZoneContext.ts';

export function ItineraryHeaderContent({
tripPattern,
Expand All @@ -24,14 +25,16 @@ export function ItineraryHeaderContent({
latestEndTime,
);

const timeZone = useContext(TimeZoneContext);

const formattedStartTime = useMemo(
() => formatTime(tripPattern.expectedStartTime, 'short'),
[tripPattern.expectedStartTime],
() => formatTime(tripPattern.expectedStartTime, timeZone, 'short'),
[tripPattern.expectedStartTime, timeZone],
);

const formattedEndTime = useMemo(
() => formatTime(tripPattern.expectedEndTime, 'short'),
[tripPattern.expectedEndTime],
() => formatTime(tripPattern.expectedEndTime, timeZone, 'short'),
[tripPattern.expectedEndTime, timeZone],
);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { ItineraryHeaderContent } from './ItineraryHeaderContent.tsx';
import { useEarliestAndLatestTimes } from './useEarliestAndLatestTimes.ts';
import { ItineraryDetails } from './ItineraryDetails.tsx';
import { ItineraryPaginationControl } from './ItineraryPaginationControl.tsx';
import { useContext } from 'react';
import { TimeZoneContext } from '../../hooks/TimeZoneContext.ts';

export function ItineraryListContainer({
tripQueryResult,
Expand All @@ -21,6 +23,7 @@ export function ItineraryListContainer({
}) {
const [earliestStartTime, latestEndTime] = useEarliestAndLatestTimes(tripQueryResult);
const { containerRef, containerWidth } = useContainerWidth();
const timeZone = useContext(TimeZoneContext);

return (
<section className="itinerary-list-container below-content" ref={containerRef}>
Expand Down Expand Up @@ -56,6 +59,9 @@ export function ItineraryListContainer({
</Accordion.Item>
))}
</Accordion>
<div className="time-zone-info">
All times in <code>{timeZone}</code>
</div>
</section>
);
}
9 changes: 6 additions & 3 deletions client/src/components/ItineraryList/LegTime.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { formatTime } from '../../util/formatTime.ts';
import { useContext } from 'react';
import { TimeZoneContext } from '../../hooks/TimeZoneContext.ts';

export function LegTime({
aimedTime,
Expand All @@ -9,18 +11,19 @@ export function LegTime({
expectedTime: string;
hasRealtime: boolean;
}) {
const timeZone = useContext(TimeZoneContext);
return aimedTime !== expectedTime ? (
<>
<span title={expectedTime} style={{ color: 'red' }}>
{formatTime(expectedTime, 'short')}
{formatTime(expectedTime, timeZone, 'short')}
</span>
<span title={aimedTime} style={{ textDecoration: 'line-through' }}>
{formatTime(aimedTime, 'short')}
{formatTime(aimedTime, timeZone, 'short')}
</span>
</>
) : (
<span title={expectedTime}>
{formatTime(expectedTime, 'short')}
{formatTime(expectedTime, timeZone, 'short')}
{hasRealtime && <span> (on time)</span>}
</span>
);
Expand Down
40 changes: 0 additions & 40 deletions client/src/components/SearchBar/DateInputField.tsx

This file was deleted.

42 changes: 42 additions & 0 deletions client/src/components/SearchBar/DateTimeInputField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Form } from 'react-bootstrap';
import { TripQueryVariables } from '../../gql/graphql.ts';
import { ChangeEvent, useCallback, useContext } from 'react';
import { Temporal } from '@js-temporal/polyfill';
import { TimeZoneContext } from '../../hooks/TimeZoneContext.ts';

export function DateTimeInputField({
tripQueryVariables,
setTripQueryVariables,
}: {
tripQueryVariables: TripQueryVariables;
setTripQueryVariables: (tripQueryVariables: TripQueryVariables) => void;
}) {
const timeZone = useContext(TimeZoneContext);
const current = Temporal.Instant.from(tripQueryVariables.dateTime)
.toZonedDateTimeISO(timeZone)
.toPlainDateTime()
.toString({ smallestUnit: 'minute', calendarName: 'never' });

const onChange = useCallback(
(event: ChangeEvent<HTMLInputElement>) => {
const dateTime = Temporal.PlainDateTime.from(event.target.value)
.toZonedDateTime(timeZone)
.toString({ calendarName: 'never', timeZoneName: 'never' });

setTripQueryVariables({
...tripQueryVariables,
dateTime: dateTime,
});
},
[tripQueryVariables, setTripQueryVariables, timeZone],
);

return (
<Form.Group>
<Form.Label column="sm" htmlFor="timePicker" title={'Time zone: ' + timeZone}>
Time
</Form.Label>
<Form.Control type="datetime-local" id="timePicker" size="sm" onChange={onChange} value={current} />
</Form.Group>
);
}
6 changes: 2 additions & 4 deletions client/src/components/SearchBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import { Button, Spinner } from 'react-bootstrap';
import { ServerInfo, TripQueryVariables } from '../../gql/graphql.ts';
import { LocationInputField } from './LocationInputField.tsx';
import { DepartureArrivalSelect } from './DepartureArrivalSelect.tsx';
import { TimeInputField } from './TimeInputField.tsx';
import { DateInputField } from './DateInputField.tsx';
import { DateTimeInputField } from './DateTimeInputField.tsx';
import { SearchWindowInput } from './SearchWindowInput.tsx';
import { AccessSelect } from './AccessSelect.tsx';
import { EgressSelect } from './EgressSelect.tsx';
Expand Down Expand Up @@ -40,8 +39,7 @@ export function SearchBar({ onRoute, tripQueryVariables, setTripQueryVariables,
<LocationInputField location={tripQueryVariables.from} label="From" id="fromInputField" />
<LocationInputField location={tripQueryVariables.to} label="To" id="toInputField" />
<DepartureArrivalSelect tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<TimeInputField tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<DateInputField tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<DateTimeInputField tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<NumTripPatternsInput tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<SearchWindowInput tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
<AccessSelect tripQueryVariables={tripQueryVariables} setTripQueryVariables={setTripQueryVariables} />
Expand Down
39 changes: 0 additions & 39 deletions client/src/components/SearchBar/TimeInputField.tsx

This file was deleted.

3 changes: 3 additions & 0 deletions client/src/hooks/TimeZoneContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createContext } from 'react';

export const TimeZoneContext = createContext('UTC');
1 change: 1 addition & 0 deletions client/src/hooks/useServerInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const query = graphql(`
routerConfigVersion
gitCommit
gitBranch
internalTransitModelTimeZone
}
}
`);
Expand Down
46 changes: 25 additions & 21 deletions client/src/screens/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,43 @@ import { useState } from 'react';
import { useTripQuery } from '../hooks/useTripQuery.ts';
import { useServerInfo } from '../hooks/useServerInfo.ts';
import { useTripQueryVariables } from '../hooks/useTripQueryVariables.ts';
import { TimeZoneContext } from '../hooks/TimeZoneContext.ts';

export function App() {
const serverInfo = useServerInfo();
const { tripQueryVariables, setTripQueryVariables } = useTripQueryVariables();
const [tripQueryResult, loading, callback] = useTripQuery(tripQueryVariables);
const serverInfo = useServerInfo();
const [selectedTripPatternIndex, setSelectedTripPatternIndex] = useState<number>(0);
const timeZone = serverInfo?.internalTransitModelTimeZone || Intl.DateTimeFormat().resolvedOptions().timeZone;

return (
<div className="app">
<SearchBar
onRoute={callback}
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
serverInfo={serverInfo}
loading={loading}
/>

<Stack direction="horizontal" gap={0}>
<ItineraryListContainer
tripQueryResult={tripQueryResult}
selectedTripPatternIndex={selectedTripPatternIndex}
setSelectedTripPatternIndex={setSelectedTripPatternIndex}
pageResults={callback}
loading={loading}
/>
<MapView
tripQueryResult={tripQueryResult}
<TimeZoneContext.Provider value={timeZone}>
<SearchBar
onRoute={callback}
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
selectedTripPatternIndex={selectedTripPatternIndex}
serverInfo={serverInfo}
loading={loading}
/>
</Stack>

<Stack direction="horizontal" gap={0}>
<ItineraryListContainer
tripQueryResult={tripQueryResult}
selectedTripPatternIndex={selectedTripPatternIndex}
setSelectedTripPatternIndex={setSelectedTripPatternIndex}
pageResults={callback}
loading={loading}
/>
<MapView
tripQueryResult={tripQueryResult}
tripQueryVariables={tripQueryVariables}
setTripQueryVariables={setTripQueryVariables}
selectedTripPatternIndex={selectedTripPatternIndex}
loading={loading}
/>
</Stack>
</TimeZoneContext.Provider>
</div>
);
}
6 changes: 6 additions & 0 deletions client/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
overflow-y: auto;
}

.itinerary-list-container .time-zone-info {
margin: 10px 20px;
font-size: 12px;
text-align: right;
}

.itinerary-header-wrapper {
position: relative;
background: #0a53be;
Expand Down
3 changes: 2 additions & 1 deletion client/src/util/formatTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* If style argument is provided formatted with ('medium') or without ('short') seconds,
* otherwise seconds are shown if not 0.
*/
export function formatTime(dateTime: string, style?: 'short' | 'medium') {
export function formatTime(dateTime: string, timeZone: string, style?: 'short' | 'medium') {
const parsed = new Date(dateTime);
return parsed.toLocaleTimeString('en-US', {
timeStyle: style ? style : parsed.getSeconds() === 0 ? 'short' : 'medium',
hourCycle: 'h24',
timeZone: timeZone,
});
}
1 change: 1 addition & 0 deletions doc/user/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ based on merged pull requests. Search GitHub issues and pull requests for smalle

- Extra leg when transferring at the same stop [#5984](https://github.com/opentripplanner/OpenTripPlanner/pull/5984)
- Filter vector tiles stops by current service week [#6003](https://github.com/opentripplanner/OpenTripPlanner/pull/6003)
- Add a matcher API for filters in the transit service used for datedServiceJourneyQuery [#5713](https://github.com/opentripplanner/OpenTripPlanner/pull/5713)
[](AUTOMATIC_CHANGELOG_PLACEHOLDER_DO_NOT_REMOVE)

## 2.6.0 (2024-09-18)
Expand Down
Loading

0 comments on commit 4c11b2a

Please sign in to comment.