Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

poi search #394

Merged
merged 41 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
b3fc35e
poi search on every key stroke
karussell Jun 1, 2024
14911f5
new autocomplete item, better usability
karussell Jun 1, 2024
a58721f
fix poi search without location keywords
karussell Jun 1, 2024
895c9c6
proper marker Select
karussell Jun 1, 2024
d3124da
change scale, not color
karussell Jun 1, 2024
bd2f7ae
keyboard support
karussell Jun 2, 2024
59ea6ab
show popup and POI being used in route
karussell Jun 2, 2024
bbb0f55
do not zoom if no location; fix bbox if single point; minor layout fix
karussell Jun 2, 2024
006d1bc
translation; move AddressParseResult into separate class and inject d…
karussell Jun 2, 2024
20bba56
fetch more information from OSM
karussell Jun 2, 2024
2426a23
minor fixes
karussell Jun 3, 2024
2163b44
use overpass instead osm
karussell Jun 3, 2024
b75c507
fetch on click; more i18n; minor fixes
karussell Jun 3, 2024
46bae86
Merge branch 'master' into integrated_poi_search
karussell Jun 4, 2024
b539ae4
reorder
karussell Jun 4, 2024
7263c65
one more exclusion
karussell Jun 4, 2024
a92f9ed
added a few more POIs
karussell Jun 4, 2024
6c9bec6
photon does not know public_transport:station (?)
karussell Jun 4, 2024
50a73fc
rename
karussell Jun 15, 2024
c9e10aa
merged master
karussell Jul 6, 2024
7da4578
use overpass API
karussell Jul 7, 2024
3bd1553
use out center and let overpass do the work; fix a few bugs
karussell Jul 7, 2024
2a594d1
translate 'nearby'
karussell Jul 7, 2024
1bbd00b
make 'AND NOT' possible to exclude military airports
karussell Jul 7, 2024
314b289
fix a few POI queries and i18n
karussell Jul 7, 2024
929bd57
allow generic query in simplified 'photon' format
karussell Jul 7, 2024
9e83c67
merged master
karussell Jul 11, 2024
85c0de6
merged master
karussell Jul 17, 2024
8177b73
workaround for initial search
karussell Jul 17, 2024
a897bd6
bug fix in merge
karussell Jul 17, 2024
6b5624e
support simple 'or' and 'and' queries with 'not'. use more overpass w…
karussell Jul 21, 2024
13b0f6f
merged master
karussell Jul 21, 2024
ce8a62b
special case for all value query
karussell Jul 21, 2024
f1be945
Merge branch 'master' into integrated_poi_search
karussell Aug 9, 2024
5edc798
avoid POI layer setup in most cases
karussell Aug 10, 2024
cda23c1
merged master
karussell Aug 10, 2024
6bb713d
minor cosmetics
karussell Aug 12, 2024
fe1b29d
simplify and avoid hack. UX is more clear too.
karussell Aug 12, 2024
56df128
formatting
karussell Aug 12, 2024
5b794b9
merged master
karussell Aug 12, 2024
b764401
minor fix
karussell Aug 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ This project uses
* the [codemirror](https://codemirror.net/) code editor for the custom model editor.
* many icons from Google's [open source font library](https://fonts.google.com/icons).
* many more open source projects - see the package.json

24 changes: 14 additions & 10 deletions 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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"prettier": "2.8.8",
"source-map-loader": "^4.0.0",
"style-loader": "^3.3.1",
"ts-jest": "^29.0.5",
"ts-jest": "^29.1.4",
"ts-loader": "^9.4.2",
"typescript": "^5.1.3",
"webpack": "^5.75.0",
Expand Down
22 changes: 19 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getMapFeatureStore,
getMapOptionsStore,
getPathDetailsStore,
getPOIsStore,
getQueryStore,
getRouteStore,
getSettingsStore,
Expand Down Expand Up @@ -42,7 +43,8 @@ import PlainButton from '@/PlainButton'
import useAreasLayer from '@/layers/UseAreasLayer'
import useExternalMVTLayer from '@/layers/UseExternalMVTLayer'
import LocationButton from '@/map/LocationButton'
import { SettingsContext } from './contexts/SettingsContext'
import { SettingsContext } from '@/contexts/SettingsContext'
import usePOIsLayer from '@/layers/UsePOIsLayer'

export const POPUP_CONTAINER_ID = 'popup-container'
export const SIDEBAR_CONTENT_ID = 'sidebar-content'
Expand All @@ -56,6 +58,7 @@ export default function App() {
const [mapOptions, setMapOptions] = useState(getMapOptionsStore().state)
const [pathDetails, setPathDetails] = useState(getPathDetailsStore().state)
const [mapFeatures, setMapFeatures] = useState(getMapFeatureStore().state)
const [pois, setPOIs] = useState(getPOIsStore().state)

const map = getMap()

Expand All @@ -68,6 +71,7 @@ export default function App() {
const onMapOptionsChanged = () => setMapOptions(getMapOptionsStore().state)
const onPathDetailsChanged = () => setPathDetails(getPathDetailsStore().state)
const onMapFeaturesChanged = () => setMapFeatures(getMapFeatureStore().state)
const onPOIsChanged = () => setPOIs(getPOIsStore().state)

getSettingsStore().register(onSettingsChanged)
getQueryStore().register(onQueryChanged)
Expand All @@ -77,6 +81,7 @@ export default function App() {
getMapOptionsStore().register(onMapOptionsChanged)
getPathDetailsStore().register(onPathDetailsChanged)
getMapFeatureStore().register(onMapFeaturesChanged)
getPOIsStore().register(onPOIsChanged)

onQueryChanged()
onInfoChanged()
Expand All @@ -85,6 +90,7 @@ export default function App() {
onMapOptionsChanged()
onPathDetailsChanged()
onMapFeaturesChanged()
onPOIsChanged()

return () => {
getSettingsStore().register(onSettingsChanged)
Expand All @@ -95,6 +101,7 @@ export default function App() {
getMapOptionsStore().deregister(onMapOptionsChanged)
getPathDetailsStore().deregister(onPathDetailsChanged)
getMapFeatureStore().deregister(onMapFeaturesChanged)
getPOIsStore().deregister(onPOIsChanged)
}
}, [])

Expand All @@ -108,11 +115,19 @@ export default function App() {
usePathsLayer(map, route.routingResult.paths, route.selectedPath, query.queryPoints)
useQueryPointsLayer(map, query.queryPoints)
usePathDetailsLayer(map, pathDetails)
usePOIsLayer(map, pois)

const isSmallScreen = useMediaQuery({ query: '(max-width: 44rem)' })
return (
<SettingsContext.Provider value={settings}>
<div className={styles.appWrapper}>
<MapPopups map={map} pathDetails={pathDetails} mapFeatures={mapFeatures} />
<MapPopups
map={map}
pathDetails={pathDetails}
mapFeatures={mapFeatures}
poiState={pois}
query={query}
/>
<ContextMenu map={map} route={route} queryPoints={query.queryPoints} />
{isSmallScreen ? (
<SmallScreenLayout
Expand Down Expand Up @@ -177,7 +192,7 @@ function LargeScreenLayout({ query, route, map, error, mapOptions, encodedValues
drawAreas={drawAreas}
/>
)}
<Search points={query.queryPoints} />
<Search points={query.queryPoints} map={map} />
<div>{!error.isDismissed && <ErrorMessage error={error} />}</div>
<RoutingResults
info={route.routingResult.info}
Expand Down Expand Up @@ -224,6 +239,7 @@ function SmallScreenLayout({ query, route, map, error, mapOptions, encodedValues
error={error}
encodedValues={encodedValues}
drawAreas={drawAreas}
map={map}
/>
</div>
<div className={styles.smallScreenMap}>
Expand Down
5 changes: 4 additions & 1 deletion src/Converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export function milliSecondsToText(ms: number) {
return (hourText ? hourText + ' ' : '') + minutes + ' min'
}

const distanceFormat = new Intl.NumberFormat(navigator.language, { maximumFractionDigits: 1 })
let distanceFormat: Intl.NumberFormat = new Intl.NumberFormat('en', { maximumFractionDigits: 1 })
export function setDistanceFormat(_distanceFormat: Intl.NumberFormat) {
distanceFormat = _distanceFormat
}

export function metersToText(meters: number, showDistanceInMiles: boolean, forceSmallUnits: boolean = false) {
if (showDistanceInMiles) {
Expand Down
44 changes: 19 additions & 25 deletions src/NavBar.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
import { coordinateToText } from '@/Converters'
import { Bbox } from '@/api/graphhopper'
import Dispatcher from '@/stores/Dispatcher'
import { ClearPoints, SelectMapLayer, SetBBox, SetQueryPoints, SetVehicleProfile } from '@/actions/Actions'
// import the window like this so that it can be mocked during testing
import { window } from '@/Window'
import QueryStore, {
Coordinate,
getBBoxFromCoord,
QueryPoint,
QueryPointType,
QueryStoreState,
} from '@/stores/QueryStore'
import QueryStore, { getBBoxFromCoord, QueryPoint, QueryPointType, QueryStoreState } from '@/stores/QueryStore'
import MapOptionsStore, { MapOptionsStoreState } from './stores/MapOptionsStore'
import { getApi } from '@/api/Api'
import { ApiImpl, getApi } from '@/api/Api'
import { AddressParseResult } from '@/pois/AddressParseResult'
import { getQueryStore } from '@/stores/Stores'

export default class NavBar {
private readonly queryStore: QueryStore
Expand Down Expand Up @@ -116,6 +111,19 @@ export default class NavBar {
if (parsedPoints.some(p => !p.isInitialized && p.queryText.length > 0)) {
const promises = parsedPoints.map(p => {
if (p.isInitialized) return Promise.resolve(p)
const result = AddressParseResult.parse(p.queryText, false)
if (result.hasPOIs() && result.location) {
// two stage POI search: 1. use extracted location to get coordinates 2. do reverse geocoding with this coordinates
return getApi()
.geocode(result.location, 'nominatim')
.then(res => {
if (res.hits.length == 0) return p
getApi()
.reverseGeocode(result.query, res.hits[0].extent)
.then(res => AddressParseResult.handleGeocodingResponse(res, result))
return p
})
}
return (
getApi()
.geocode(p.queryText, 'nominatim')
Expand All @@ -129,7 +137,7 @@ export default class NavBar {
}
})
// if the geocoding request fails we just keep the point as it is, just as if no results were found
.catch(() => Promise.resolve(p))
.catch(() => p)
)
})
const points = await Promise.all(promises)
Expand All @@ -151,7 +159,7 @@ export default class NavBar {
const bbox =
initializedPoints.length == 1
? getBBoxFromCoord(initializedPoints[0].coordinate)
: NavBar.getBBoxFromUrlPoints(initializedPoints.map(p => p.coordinate))
: ApiImpl.getBBoxPoints(initializedPoints.map(p => p.coordinate))
if (bbox) Dispatcher.dispatch(new SetBBox(bbox))
return Dispatcher.dispatch(new SetQueryPoints(points))
}
Expand All @@ -169,18 +177,4 @@ export default class NavBar {
this.mapStore.state
).toString()
}

private static getBBoxFromUrlPoints(urlPoints: Coordinate[]): Bbox | null {
const bbox: Bbox = urlPoints.reduce(
(res: Bbox, c) => [
Math.min(res[0], c.lng),
Math.min(res[1], c.lat),
Math.max(res[2], c.lng),
Math.max(res[3], c.lat),
],
[180, 90, -180, -90] as Bbox
)
// return null if the bbox is not valid, e.g. if no url points were given at all
return bbox[0] < bbox[2] && bbox[1] < bbox[3] ? bbox : null
}
}
17 changes: 17 additions & 0 deletions src/actions/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Action } from '@/stores/Dispatcher'
import { Coordinate, QueryPoint } from '@/stores/QueryStore'
import { ApiInfo, Bbox, Path, RoutingArgs, RoutingProfile, RoutingResult } from '@/api/graphhopper'
import { PathDetailsPoint } from '@/stores/PathDetailsStore'
import { POI } from '@/stores/POIsStore'
import { Settings } from '@/stores/SettingsStore'

export class InfoReceived implements Action {
Expand Down Expand Up @@ -246,3 +247,19 @@ export class UpdateSettings implements Action {
this.updatedSettings = updatedSettings
}
}

export class SelectPOI implements Action {
readonly selected: POI | null

constructor(selected: POI | null) {
this.selected = selected
}
}

export class SetPOIs implements Action {
readonly pois: POI[]

constructor(pois: POI[]) {
this.pois = pois
}
}
Loading
Loading