Skip to content

Commit

Permalink
fetch on click; more i18n; minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
karussell committed Jun 3, 2024
1 parent 2163b44 commit b75c507
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 58 deletions.
14 changes: 5 additions & 9 deletions src/api/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { LineString } from 'geojson'
import { getTranslation, tr } from '@/translation/Translation'
import * as config from 'config'
import { Coordinate } from '@/stores/QueryStore'
import { KV } from '@/pois/AddressParseResult'

interface ApiProfile {
name: string
Expand All @@ -31,12 +32,7 @@ export default interface Api {

geocode(query: string, provider: string, additionalOptions?: Record<string, string>): Promise<GeocodingResult>

reverseGeocode(
query: string | undefined,
point: Coordinate,
radius: number,
tags?: string[]
): Promise<GeocodingResult>
reverseGeocode(query: string | undefined, point: Coordinate, radius: number, tags?: KV[]): Promise<GeocodingResult>

supportsGeocoding(): boolean
}
Expand Down Expand Up @@ -129,7 +125,7 @@ export class ApiImpl implements Api {
query: string | undefined,
point: Coordinate,
radius: number,
tags?: string[]
tags?: KV[]
): Promise<GeocodingResult> {
if (!this.supportsGeocoding())
return {
Expand All @@ -149,8 +145,8 @@ export class ApiImpl implements Api {
url.searchParams.append('locale', langAndCountry.length > 0 ? langAndCountry[0] : 'en')

if (tags) {
for (const value of tags) {
url.searchParams.append('osm_tag', value)
for (const tag of tags) {
url.searchParams.append('osm_tag', tag.k + ':' + tag.v)
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/layers/MapFeaturePopup.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
position: relative;
top: -40px;
left: 20px;
max-width: 250px;
max-width: 300px;

background-color: white;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
Expand Down Expand Up @@ -66,5 +66,5 @@

/* strange, why do we need the following? */
word-break: break-all;
min-width: 100px;
min-width: 120px;
}
25 changes: 12 additions & 13 deletions src/layers/POIPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'
import styles from '@/layers/MapFeaturePopup.module.css'
import MapPopup from '@/layers/MapPopup'
import { Map } from 'ol'
import { POIsStoreState } from '@/stores/POIsStore'
import { POI, POIsStoreState } from '@/stores/POIsStore'
import { tr } from '@/translation/Translation'
import Dispatcher from '@/stores/Dispatcher'
import { SelectPOI, SetPoint, SetPOIs } from '@/actions/Actions'
Expand Down Expand Up @@ -35,20 +35,26 @@ async function fetchInfo(type: string, ids: string[]): Promise<TagHash> {
}
}

function KVTable(props: { kv: TagHash }) {
function KVTable(props: { kv: TagHash; poi: POI | null }) {
return (
<table className={styles.poiPopupTable}>
<tbody>
{Object.entries(props.kv).map(([key, value]) => {
const url = value.startsWith('https://')
const url = value.startsWith('https://') || value.startsWith('http://')
const tel = key.toLowerCase().includes('phone')
const email = key.toLowerCase().includes('email')
const valueArr = value.split(':').map(v => v.trim())
const wiki = key.toLowerCase().includes('wikipedia') && valueArr.length == 2
const wikiUrl = wiki
? 'https://' + valueArr[0] + '.wikipedia.org/wiki/' + encodeURIComponent(valueArr[1])
: ''
// tags like amenity:restaurant should not be shown if it is a restaurant (determined by poi.tags)
const poiInfoRepeated = props.poi ? props.poi.tags.some(kv => kv.k == key && kv.v === value) : false
return (
!poiInfoRepeated &&
key !== 'source' &&
key !== 'image' &&
!key.includes('fax') &&
!key.startsWith('addr') &&
!key.startsWith('name') &&
!key.startsWith('building') && (
Expand Down Expand Up @@ -89,6 +95,7 @@ export default function POIStatePopup({ map, poiState }: POIStatePopupProps) {
const [kv, setKV] = useState<TagHash>({})

useEffect(() => {
if (selectedPOI) fetchInfo(type, [selectedPOI.osm_id]).then(tagHash => setKV(tagHash))
return () => {
setKV({})
}
Expand All @@ -99,16 +106,8 @@ export default function POIStatePopup({ map, poiState }: POIStatePopupProps) {
<div className={styles.poiPopup}>
<div>{selectedPOI?.name}</div>
<div>{selectedPOI?.address}</div>
{Object.keys(kv).length == 0 && (
<PlainButton
onClick={e => {
if (selectedPOI) fetchInfo(type, [selectedPOI.osm_id]).then(tagHash => setKV(tagHash))
}}
>
{tr('Fetch more info')}
</PlainButton>
)}
<KVTable kv={kv} />
{Object.keys(kv).length == 0 && <PlainButton>{tr('Fetching more info...')}</PlainButton>}
<KVTable kv={kv} poi={selectedPOI} />
<div className={styles.osmLink}>
<a href={'https://www.openstreetmap.org/' + type + '/' + selectedPOI?.osm_id} target="_blank">
OpenStreetMap.org
Expand Down
74 changes: 43 additions & 31 deletions src/pois/AddressParseResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import { tr, Translation } from '@/translation/Translation'

export class AddressParseResult {
location: string
tags: string[]
tags: KV[]
icon: string
poi: string
static VALUES: PoiTriggerPhrases[]
static TRIGGER_VALUES: PoiTriggerPhrases[]
static REMOVE_VALUES: string[]

constructor(location: string, tags: string[], icon: string, poi: string) {
constructor(location: string, tags: KV[], icon: string, poi: string) {
this.location = location
this.tags = tags
this.icon = icon
Expand All @@ -32,15 +33,15 @@ export class AddressParseResult {
static parse(query: string, incomplete: boolean): AddressParseResult {
query = query.toLowerCase()

const smallWords = ['in', 'around', 'nearby']
const smallWords = AddressParseResult.REMOVE_VALUES // e.g. 'restaurants in this area' or 'restaurants in berlin'
const queryTokens: string[] = query.split(' ').filter(token => !smallWords.includes(token))
const cleanQuery = queryTokens.join(' ')
const bigrams: string[] = []
for (let i = 0; i < queryTokens.length - 1; i++) {
bigrams.push(queryTokens[i] + ' ' + queryTokens[i + 1])
}

for (const val of AddressParseResult.VALUES) {
for (const val of AddressParseResult.TRIGGER_VALUES) {
// two word phrases like 'public transit' must be checked before single word phrases
for (const keyword of val.k) {
const i = bigrams.indexOf(keyword)
Expand Down Expand Up @@ -81,6 +82,7 @@ export class AddressParseResult {
const res = hitToItem(hit)
return {
name: res.mainText,
tags: parseResult.tags,
icon: parseResult.icon,
coordinate: hit.point,
address: res.secondText,
Expand All @@ -96,32 +98,42 @@ export class AddressParseResult {

// because of the static method we need to inject the Translation object as otherwise jest has a problem
static setPOITriggerPhrases(translation: Translation) {
const t = (s: string) =>
translation
.get(s)
.split(',')
.map(s => s.trim().toLowerCase())
AddressParseResult.VALUES = [
{ k: t('poi_airports'), t: ['aeroway:aerodrome'], i: 'flight_takeoff' },
{ k: t('poi_banks'), t: ['amenity:bank'], i: 'universal_currency_alt' },
{ k: t('poi_bus_stops'), t: ['highway:bus_stop'], i: 'train' },
{ k: t('poi_education'), t: ['amenity:school', 'building:school', 'building:university'], i: 'school' },
{ k: t('poi_hospitals'), t: ['amenity:hospital', 'building:hospital'], i: 'local_hospital' },
{ k: t('poi_hotels'), t: ['amenity:hotel', 'building:hotel', 'tourism:hotel'], i: 'hotel' },
{ k: t('poi_leisure'), t: ['leisure'], i: 'sports_handball' },
{ k: t('poi_museums'), t: ['tourism:museum', 'building:museum'], i: 'museum' },
{ k: t('poi_parking'), t: ['amenity:parking'], i: 'local_parking' },
{ k: t('poi_parks'), t: ['leisure:park'], i: 'sports_handball' },
{ k: t('poi_pharmacies'), t: ['amenity:pharmacy'], i: 'local_pharmacy' },
{ k: t('poi_playgrounds'), t: ['leisure:playground'], i: 'sports_handball' },
{ k: t('poi_public_transit'), t: ['railway:station', 'highway:bus_stop'], i: 'train' },
{ k: t('poi_railway_station'), t: ['railway:station'], i: 'train' },
{ k: t('poi_restaurants'), t: ['amenity:restaurant'], i: 'restaurant' },
{ k: t('poi_schools'), t: ['amenity:school', 'building:school'], i: 'school' },
{ k: t('poi_super_markets'), t: ['shop:supermarket', 'building:supermarket'], i: 'store' },
{ k: t('poi_tourism'), t: ['tourism'], i: 'luggage' },
]
const t = (s: string) => translation
.get(s)
.split(',')
.map(s => s.trim().toLowerCase())
AddressParseResult.REMOVE_VALUES = t('poi_removal_words')
AddressParseResult.TRIGGER_VALUES = [
{ k: 'poi_airports', t: ['aeroway:aerodrome'], i: 'flight_takeoff' },
{ k: 'poi_banks', t: ['amenity:bank'], i: 'universal_currency_alt' },
{ k: 'poi_bus_stops', t: ['highway:bus_stop'], i: 'train' },
{ k: 'poi_education', t: ['amenity:school', 'building:school', 'building:university'], i: 'school' },
{ k: 'poi_hospitals', t: ['amenity:hospital', 'building:hospital'], i: 'local_hospital' },
{ k: 'poi_hotels', t: ['amenity:hotel', 'building:hotel', 'tourism:hotel'], i: 'hotel' },
{ k: 'poi_leisure', t: ['leisure'], i: 'sports_handball' },
{ k: 'poi_museums', t: ['tourism:museum', 'building:museum'], i: 'museum' },
{ k: 'poi_parking', t: ['amenity:parking'], i: 'local_parking' },
{ k: 'poi_parks', t: ['leisure:park'], i: 'sports_handball' },
{ k: 'poi_pharmacies', t: ['amenity:pharmacy'], i: 'local_pharmacy' },
{ k: 'poi_playgrounds', t: ['leisure:playground'], i: 'sports_handball' },
{ k: 'poi_public_transit', t: ['railway:station', 'highway:bus_stop'], i: 'train' },
{ k: 'poi_railway_station', t: ['railway:station'], i: 'train' },
{ k: 'poi_restaurants', t: ['amenity:restaurant'], i: 'restaurant' },
{ k: 'poi_schools', t: ['amenity:school', 'building:school'], i: 'school' },
{ k: 'poi_super_markets', t: ['shop:supermarket', 'building:supermarket'], i: 'store' },
{ k: 'poi_tourism', t: ['tourism'], i: 'luggage' },
].map(v => {
const tags = v.t.map(val => {
return { k: val.split(':')[0], v: val.split(':')[1] }
})
return {
...v,
k: t(v.k),
t: tags,
}
})
}
}

export type PoiTriggerPhrases = { k: string[]; t: string[]; i: string }
export type KV = { k: string; v: string }
export type PoiTriggerPhrases = { k: string[]; t: KV[]; i: string }
2 changes: 2 additions & 0 deletions src/stores/POIsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { Coordinate, QueryPoint } from '@/stores/QueryStore'
import Store from '@/stores/Store'
import { Action } from '@/stores/Dispatcher'
import { SelectPOI, SetPOIs } from '@/actions/Actions'
import { KV } from '@/pois/AddressParseResult'

export interface POI {
name: string
tags: KV[]
osm_id: string
osm_type: string
icon: string
Expand Down
Loading

0 comments on commit b75c507

Please sign in to comment.