Skip to content

Commit

Permalink
Merge remote-tracking branch 'otp/dev-2.x' into via
Browse files Browse the repository at this point in the history
  • Loading branch information
t2gran committed Oct 8, 2024
2 parents 162be1c + 58a1847 commit 339c89f
Show file tree
Hide file tree
Showing 469 changed files with 6,320 additions and 4,267 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/cibuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ jobs:

- name: Build GTFS GraphQL API documentation
run: |
npm install -g @magidoc/cli@6.0.0
npm install -g @magidoc/cli@6.1.0
magidoc generate --stacktrace
- name: Deploy compiled HTML to Github pages
Expand Down
4 changes: 2 additions & 2 deletions DEVELOPMENT_DECISION_RECORDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ tests. Expect to include some code cleanup as part of all PRs.
## Follow-Naming-Conventions

Use established terminology from GTFS, NeTEx or the existing OTP code. Make sure the code is easy
to read and understand. [Follow naming conventions](CODE_CONVENTIONS.md#naming-conventions) .
to read and understand. [Follow naming conventions](doc/dev/decisionrecords/NamingConventions.md#naming-conventions) .


## Write-Code-Documentation - Use JavaDoc
Expand All @@ -32,7 +32,7 @@ notes on `private` members and as inline comments.
**See also**
- [Developers-Guide > Code comments](doc/user/Developers-Guide.md#code-comments).
- [Codestyle > Javadoc Guidlines](doc/dev/decisionrecords/Codestyle.md#javadoc-guidlines) - JavaDoc checklist
- [Codestyle > Javadoc Guidelines](doc/dev/decisionrecords/Codestyle.md#javadoc-guidlines) - JavaDoc checklist


## Document-Config-and-APIs
Expand Down
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>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export function ItineraryPaginationControl({
return (
<div style={{ display: 'flex', justifyContent: 'space-evenly', margin: '1rem 0 ' }}>
<Button
variant="outline-primary"
size="sm"
disabled={!previousPageCursor || loading}
onClick={() => {
previousPageCursor && onPagination(previousPageCursor);
Expand All @@ -22,6 +24,8 @@ export function ItineraryPaginationControl({
Previous page
</Button>{' '}
<Button
variant="outline-primary"
size="sm"
disabled={!nextPageCursor || loading}
onClick={() => {
nextPageCursor && onPagination(nextPageCursor);
Expand Down
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>
);
}
17 changes: 12 additions & 5 deletions client/src/components/SearchBar/GraphiQLRouteButton.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { Button } from 'react-bootstrap';
import { TripQueryVariables } from '../../gql/graphql.ts';
import { queryAsString } from '../../static/query/tripQuery.tsx';
import graphqlIcon from '../../static/img/graphql-solid.svg';

const graphiQLUrl = import.meta.env.VITE_GRAPHIQL_URL;

function GraphiQLRouteButton({ tripQueryVariables }: { tripQueryVariables: TripQueryVariables }) {
const formattedVariables = encodeURIComponent(JSON.stringify(tripQueryVariables));
const formattedQuery = encodeURIComponent(queryAsString);

const hint = 'Open in GraphiQL';

return (
<div className="search-bar-route-button-wrapper">
<Button href={graphiQLUrl + '&query=' + formattedQuery + '&variables=' + formattedVariables} target={'_blank'}>
GraphiQL
</Button>
</div>
<Button
title={hint}
href={graphiQLUrl + '&query=' + formattedQuery + '&variables=' + formattedVariables}
target={'_blank'}
>
<img alt={hint} title={hint} src={graphqlIcon} width="20" height="20" className="d-inline-block align-middle" />
</Button>
);
}

export default GraphiQLRouteButton;
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export function ItineraryFilterDebugSelect({
return (
<Form.Group>
<Form.Label column="sm" htmlFor="itineraryDebugFilterSelect">
Itinerary filter debug
Filter debug
</Form.Label>
<Form.Select
id="itineraryDebugFilterSelect"
size="sm"
className="input-medium"
onChange={(e) => {
setTripQueryVariables({
...tripQueryVariables,
Expand Down
1 change: 1 addition & 0 deletions client/src/components/SearchBar/LocationInputField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export function LocationInputField({ location, id, label }: { location: Location
id={id}
size="sm"
placeholder="[Click in map]"
className="input-medium"
// Intentionally empty for now, but needed because of
// https://react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable
onChange={() => {}}
Expand Down
3 changes: 2 additions & 1 deletion client/src/components/SearchBar/NumTripPatternsInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ export function NumTripPatternsInput({
return (
<Form.Group>
<Form.Label column="sm" htmlFor="numTripPatternsInput">
Number of trip patterns
Num. results
</Form.Label>
<Form.Control
type="number"
id="numTripPatternsInput"
size="sm"
placeholder="12"
min={1}
className="input-small"
value={tripQueryVariables.numTripPatterns || ''}
onChange={(event) =>
setTripQueryVariables({
Expand Down
Loading

0 comments on commit 339c89f

Please sign in to comment.