From aa48a324a224bc0ce0faedebf01b593db30b06df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Wed, 9 Oct 2024 13:02:29 +0200 Subject: [PATCH 1/6] debug client: support stop ids in from / to inputs --- .../SearchBar/LocationInputField.tsx | 50 +++++++++++++++---- client/src/components/SearchBar/SearchBar.tsx | 16 +++++- client/src/hooks/useTripQuery.ts | 8 ++- client/src/util/locationConverter.ts | 47 +++++++++++++++++ 4 files changed, 106 insertions(+), 15 deletions(-) create mode 100644 client/src/util/locationConverter.ts diff --git a/client/src/components/SearchBar/LocationInputField.tsx b/client/src/components/SearchBar/LocationInputField.tsx index bfa707776f1..5f2ae950e52 100644 --- a/client/src/components/SearchBar/LocationInputField.tsx +++ b/client/src/components/SearchBar/LocationInputField.tsx @@ -1,8 +1,37 @@ import { Form } from 'react-bootstrap'; -import { COORDINATE_PRECISION } from './constants.ts'; -import { Location } from '../../gql/graphql.ts'; +import { toString, parseLocation } from '../../util/locationConverter.ts'; +import { Location, TripQueryVariables } from '../../gql/graphql.ts'; +import { useCallback, useEffect, useState } from 'react'; + +interface Props { + id: string; + label: string; + tripQueryVariables: TripQueryVariables; + setTripQueryVariables: (tripQueryVariables: TripQueryVariables) => void; + locationFieldKey: 'from' | 'to'; +} + +export function LocationInputField({ id, label, tripQueryVariables, setTripQueryVariables, locationFieldKey }: Props) { + const [value, setValue] = useState(''); + + useEffect(() => { + const initialLocation: Location = tripQueryVariables[locationFieldKey]; + + setValue(toString(initialLocation) || ''); + }, [tripQueryVariables, locationFieldKey]); + + const onLocationChange = useCallback( + (value: string) => { + const newLocation = parseLocation(value) || {}; + + setTripQueryVariables({ + ...tripQueryVariables, + [locationFieldKey]: newLocation, + }); + }, + [tripQueryVariables, setTripQueryVariables, locationFieldKey], + ); -export function LocationInputField({ location, id, label }: { location: Location; id: string; label: string }) { return ( @@ -16,14 +45,13 @@ export function LocationInputField({ location, id, label }: { location: Location 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={() => {}} - value={ - location.coordinates - ? `${location.coordinates?.latitude.toPrecision( - COORDINATE_PRECISION, - )} ${location.coordinates?.longitude.toPrecision(COORDINATE_PRECISION)}` - : '' - } + onChange={(e) => { + setValue(e.target.value); + }} + onBlur={(event) => { + onLocationChange(event.target.value); + }} + value={value} /> ); diff --git a/client/src/components/SearchBar/SearchBar.tsx b/client/src/components/SearchBar/SearchBar.tsx index 73df12fe103..47781532179 100644 --- a/client/src/components/SearchBar/SearchBar.tsx +++ b/client/src/components/SearchBar/SearchBar.tsx @@ -38,9 +38,21 @@ export function SearchBar({ onRoute, tripQueryVariables, setTripQueryVariables, {showServerInfo && } - + - + diff --git a/client/src/hooks/useTripQuery.ts b/client/src/hooks/useTripQuery.ts index 5ff6fc80a1f..3abb4617d2a 100644 --- a/client/src/hooks/useTripQuery.ts +++ b/client/src/hooks/useTripQuery.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; import { request } from 'graphql-request'; // eslint-disable-line import/no-unresolved -import { QueryType, TripQueryVariables } from '../gql/graphql.ts'; +import { Location, QueryType, TripQueryVariables } from '../gql/graphql.ts'; import { getApiUrl } from '../util/getApiUrl.ts'; import { query } from '../static/query/tripQuery.tsx'; @@ -37,10 +37,14 @@ export const useTripQuery: TripQueryHook = (variables) => { ); useEffect(() => { - if (variables?.from.coordinates && variables?.to.coordinates) { + if (validLocation(variables?.from) && validLocation(variables?.to)) { callback(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [variables?.from, variables?.to]); return [data, loading, callback]; }; + +function validLocation(location: Location | undefined) { + return location && (location.coordinates || location.place); +} diff --git a/client/src/util/locationConverter.ts b/client/src/util/locationConverter.ts new file mode 100644 index 00000000000..647c78582e9 --- /dev/null +++ b/client/src/util/locationConverter.ts @@ -0,0 +1,47 @@ +import { COORDINATE_PRECISION } from '../components/SearchBar/constants.ts'; +import { Location } from '../gql/graphql.ts'; + +const DOUBLE_PATTERN = '-{0,1}\\d+(\\.\\d+){0,1}'; + +const LAT_LON_PATTERN = '(' + DOUBLE_PATTERN + ')(\\s*,\\s*|\\s+)(' + DOUBLE_PATTERN + ')'; + +const ID_SEPARATOR = ':'; + +export function parseLocation(value: string): Location | null { + const latLonMatch = value.match(LAT_LON_PATTERN); + + if (latLonMatch) { + return { + coordinates: { + latitude: +latLonMatch[1], + longitude: +latLonMatch[4], + }, + }; + } + + if (validFeedScopeIdString(value)) { + return { + place: value, + }; + } + + return null; +} + +function validFeedScopeIdString(value: string): boolean { + return value.indexOf(ID_SEPARATOR) > -1; +} + +export function toString(location: Location): string | null { + if (location.coordinates) { + return `${location.coordinates?.latitude.toPrecision( + COORDINATE_PRECISION, + )} ${location.coordinates?.longitude.toPrecision(COORDINATE_PRECISION)}`; + } + + if (location.place) { + return location.place; + } + + return null; +} From 17228b2c07f17493c7a463b7c956b1ef18b1f6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Thu, 17 Oct 2024 15:01:46 +0200 Subject: [PATCH 2/6] debug client: resolve coordinates for stop ids --- .../components/MapView/NavigationMarkers.tsx | 16 ++++++---- .../MapView/useCoordinateResolver.ts | 30 +++++++++++++++++ client/src/hooks/useQuayCoordinateQuery.ts | 32 +++++++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 client/src/components/MapView/useCoordinateResolver.ts create mode 100644 client/src/hooks/useQuayCoordinateQuery.ts diff --git a/client/src/components/MapView/NavigationMarkers.tsx b/client/src/components/MapView/NavigationMarkers.tsx index 6d043038ae9..2ae62cab8f2 100644 --- a/client/src/components/MapView/NavigationMarkers.tsx +++ b/client/src/components/MapView/NavigationMarkers.tsx @@ -2,6 +2,7 @@ import { TripQueryVariables } from '../../gql/graphql.ts'; import { Marker } from 'react-map-gl'; import markerFlagStart from '../../static/img/marker-flag-start-shadowed.png'; import markerFlagEnd from '../../static/img/marker-flag-end-shadowed.png'; +import { useCoordinateResolver } from './useCoordinateResolver.ts'; export function NavigationMarkers({ setCursor, @@ -14,13 +15,16 @@ export function NavigationMarkers({ setTripQueryVariables: (variables: TripQueryVariables) => void; loading: boolean; }) { + const fromCoordinates = useCoordinateResolver(tripQueryVariables.from); + const toCoordinates = useCoordinateResolver(tripQueryVariables.to); + return ( <> - {tripQueryVariables.from.coordinates && ( + {fromCoordinates && ( setCursor('grabbing')} onDragEnd={(e) => { setCursor('auto'); @@ -36,11 +40,11 @@ export function NavigationMarkers({ )} - {tripQueryVariables.to.coordinates && ( + {toCoordinates && ( setCursor('grabbing')} onDragEnd={(e) => { setCursor('auto'); diff --git a/client/src/components/MapView/useCoordinateResolver.ts b/client/src/components/MapView/useCoordinateResolver.ts new file mode 100644 index 00000000000..e44472df549 --- /dev/null +++ b/client/src/components/MapView/useCoordinateResolver.ts @@ -0,0 +1,30 @@ +import { Location } from '../../gql/graphql.ts'; +import { useQuayCoordinateQuery } from '../../hooks/useQuayCoordinateQuery.ts'; + +interface Coordinates { + latitude: number; + longitude: number; +} + +export function useCoordinateResolver(location: Location): Coordinates | undefined { + const quay = useQuayCoordinateQuery(location); + + if (quay) { + const { latitude, longitude } = quay; + + if (latitude && longitude) { + return { + latitude, + longitude, + }; + } + } + + if (location.coordinates) { + return { + ...location.coordinates, + }; + } + + return undefined; +} diff --git a/client/src/hooks/useQuayCoordinateQuery.ts b/client/src/hooks/useQuayCoordinateQuery.ts new file mode 100644 index 00000000000..e2e401a950b --- /dev/null +++ b/client/src/hooks/useQuayCoordinateQuery.ts @@ -0,0 +1,32 @@ +import { useEffect, useState } from 'react'; +import { request } from 'graphql-request'; // eslint-disable-line import/no-unresolved +import { Location, QueryType } from '../gql/graphql.ts'; +import { getApiUrl } from '../util/getApiUrl.ts'; +import { graphql } from '../gql'; + +const query = graphql(` + query quayCoordinate($id: String!) { + quay(id: $id) { + latitude + longitude + } + } +`); + +export const useQuayCoordinateQuery = (location: Location) => { + const [data, setData] = useState(null); + + useEffect(() => { + const fetchData = async () => { + if (location.place) { + const variables = { id: location.place }; + setData((await request(getApiUrl(), query, variables)) as QueryType); + } else { + setData(null); + } + }; + fetchData(); + }, [location]); + + return data?.quay; +}; From ab96fec8f3ed31f32ffe7b676568ea8c706e9fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Mon, 18 Nov 2024 11:35:59 +0100 Subject: [PATCH 3/6] Remove unneeded eslint-disable-line --- client/src/hooks/useQuayCoordinateQuery.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/hooks/useQuayCoordinateQuery.ts b/client/src/hooks/useQuayCoordinateQuery.ts index e2e401a950b..4b30f0f5ca2 100644 --- a/client/src/hooks/useQuayCoordinateQuery.ts +++ b/client/src/hooks/useQuayCoordinateQuery.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { request } from 'graphql-request'; // eslint-disable-line import/no-unresolved +import { request } from 'graphql-request'; import { Location, QueryType } from '../gql/graphql.ts'; import { getApiUrl } from '../util/getApiUrl.ts'; import { graphql } from '../gql'; From a2ff9e196fcf8402cdc7471cbbe00ad7d0a16f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Mon, 18 Nov 2024 16:24:26 +0100 Subject: [PATCH 4/6] debug client: turn off location validation in inputs and handle query errors --- client/src/hooks/useQuayCoordinateQuery.ts | 6 +++++- client/src/hooks/useTripQuery.ts | 12 ++++++++---- client/src/util/locationConverter.ts | 16 +++------------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/client/src/hooks/useQuayCoordinateQuery.ts b/client/src/hooks/useQuayCoordinateQuery.ts index 4b30f0f5ca2..6d4655a6838 100644 --- a/client/src/hooks/useQuayCoordinateQuery.ts +++ b/client/src/hooks/useQuayCoordinateQuery.ts @@ -20,7 +20,11 @@ export const useQuayCoordinateQuery = (location: Location) => { const fetchData = async () => { if (location.place) { const variables = { id: location.place }; - setData((await request(getApiUrl(), query, variables)) as QueryType); + try { + setData((await request(getApiUrl(), query, variables)) as QueryType); + } catch (e) { + console.error('Error at useQuayCoordinateQuery', e); + } } else { setData(null); } diff --git a/client/src/hooks/useTripQuery.ts b/client/src/hooks/useTripQuery.ts index 651a99a8d8f..f1f8c859bd0 100644 --- a/client/src/hooks/useTripQuery.ts +++ b/client/src/hooks/useTripQuery.ts @@ -22,10 +22,14 @@ export const useTripQuery: TripQueryHook = (variables) => { } else { if (variables) { setLoading(true); - if (pageCursor) { - setData((await request(getApiUrl(), query, { ...variables, pageCursor })) as QueryType); - } else { - setData((await request(getApiUrl(), query, variables)) as QueryType); + try { + if (pageCursor) { + setData((await request(getApiUrl(), query, { ...variables, pageCursor })) as QueryType); + } else { + setData((await request(getApiUrl(), query, variables)) as QueryType); + } + } catch (e) { + console.error('Error at useTripQuery', e); } setLoading(false); } else { diff --git a/client/src/util/locationConverter.ts b/client/src/util/locationConverter.ts index 647c78582e9..bb9c8a5b01d 100644 --- a/client/src/util/locationConverter.ts +++ b/client/src/util/locationConverter.ts @@ -5,8 +5,6 @@ const DOUBLE_PATTERN = '-{0,1}\\d+(\\.\\d+){0,1}'; const LAT_LON_PATTERN = '(' + DOUBLE_PATTERN + ')(\\s*,\\s*|\\s+)(' + DOUBLE_PATTERN + ')'; -const ID_SEPARATOR = ':'; - export function parseLocation(value: string): Location | null { const latLonMatch = value.match(LAT_LON_PATTERN); @@ -19,17 +17,9 @@ export function parseLocation(value: string): Location | null { }; } - if (validFeedScopeIdString(value)) { - return { - place: value, - }; - } - - return null; -} - -function validFeedScopeIdString(value: string): boolean { - return value.indexOf(ID_SEPARATOR) > -1; + return { + place: value, + }; } export function toString(location: Location): string | null { From 7f267f7cbab2626d516aea2fcc49dd0ba6c81fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Thu, 21 Nov 2024 10:34:58 +0100 Subject: [PATCH 5/6] Remove unnecessary comment --- client/src/components/SearchBar/LocationInputField.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/src/components/SearchBar/LocationInputField.tsx b/client/src/components/SearchBar/LocationInputField.tsx index 5f2ae950e52..70584e0e6d8 100644 --- a/client/src/components/SearchBar/LocationInputField.tsx +++ b/client/src/components/SearchBar/LocationInputField.tsx @@ -43,8 +43,6 @@ export function LocationInputField({ id, label, tripQueryVariables, setTripQuery 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={(e) => { setValue(e.target.value); }} From bc1bca070ae9574f7d557f6681914f1d6cc67a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rich=C3=A1rd=20K=C5=91szegi?= Date: Thu, 21 Nov 2024 11:12:29 +0100 Subject: [PATCH 6/6] debug client: simplify location parser coordinate format --- client/src/util/locationConverter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/util/locationConverter.ts b/client/src/util/locationConverter.ts index bb9c8a5b01d..952a36a1dc4 100644 --- a/client/src/util/locationConverter.ts +++ b/client/src/util/locationConverter.ts @@ -3,7 +3,7 @@ import { Location } from '../gql/graphql.ts'; const DOUBLE_PATTERN = '-{0,1}\\d+(\\.\\d+){0,1}'; -const LAT_LON_PATTERN = '(' + DOUBLE_PATTERN + ')(\\s*,\\s*|\\s+)(' + DOUBLE_PATTERN + ')'; +const LAT_LON_PATTERN = '(' + DOUBLE_PATTERN + ')(\\s+)(' + DOUBLE_PATTERN + ')'; export function parseLocation(value: string): Location | null { const latLonMatch = value.match(LAT_LON_PATTERN);