fix(maps): sag bei jedem Vorschlag, welcher Index geantwortet hat

Seit die Tipp-Suche beide Schichten fragt, ist ihre Liste gemischt — die
Antwort nennt aber weiterhin EINE Quelle fuer die ganze Liste, und die heisst
'trek-places'. Der Client beschriftet damit jede Zeile, auch die aus
OpenStreetMap. Wer tippt, liest also acht Mal "TREK" und schliesst daraus, die
OSM-Schicht antworte gar nicht. Sie antwortet, sie steht nur unter falschem
Namen da. Auf der Suchstrecke daneben stimmt es laengst: dort traegt jeder Ort
sein eigenes `source`, und genau deshalb liest sich diese Liste richtig.

Also traegt es jetzt auch die Zeile. Das Feld ist optional, weil Google und der
Nominatim-Rueckfall je aus einer Quelle antworten; eine Zeile ohne eigene
Angabe faellt weiter auf den Namen der Liste zurueck.

Dazu die Koordinaten, die der Vorschlag ohnehin schon kennt. Bisher wurden sie
weggeworfen, und wenn der Details-Aufruf nicht antwortete — Kill-Switch, ein
ueberlasteter Overpass-Spiegel, irgendein Fehler oben — baute der Client eine
Textsuche aus Name und zweiter Zeile. Bei einer OSM-Zeile ist die zweite Zeile
aber keine Adresse, sondern der ortsuebliche Name: gesucht wurde dann nach
"Tokio Hauptbahnhof, 東京駅丸の内駅舎", und dessen erstes Ergebnis wurde
kommentarlos als der Ort genommen, den der Nutzer angeklickt hatte. Jetzt
nimmt der Rueckfall den Punkt, den die Zeile mitbringt.

Und das Abzeichen gibt es endlich auch mobil. Die Marke und ihre Tabelle
liegen dafuer in client/src/utils/placeSource.ts, weil beide Oberflaechen
dieselben Listen zeigen und ein Zeichen, das nur auf einer davon steht,
schlimmer ist als keines.

Was hier NICHT drin ist, obwohl es dazugehoert: dass der richtige Bahnhof in
der Liste steht. Das liegt am Dienst, nicht an TREK, und ist dort gemessen und
behoben — Rangfolge nach Art des Ortes plus die Verkehrsknoten, die der
OSM-Schicht ganz fehlten.
This commit is contained in:
Maurice
2026-09-09 17:24:05 +02:00
committed by Maurice
parent 2f71549413
commit 7ba7338f5f
7 changed files with 223 additions and 39 deletions
+16 -2
View File
@@ -2021,7 +2021,7 @@ export class MapsService {
lang?: string,
locationBias?: { low: { lat: number; lng: number }; high: { lat: number; lng: number } },
sessionToken?: string,
): Promise<{ suggestions: { placeId: string; mainText: string; secondaryText: string }[]; source: string }> {
): Promise<MapsAutocompleteResult> {
const { key: apiKey, source: keySource } = this.resolveMapsKey(userId);
// This is the path that mattered most. Nominatim's usage policy names
@@ -2071,11 +2071,25 @@ export class MapsService {
// place is called on the spot, which is more use under a
// translated label than an empty line.
secondaryText: p.local_name && p.local_name !== p.name ? p.local_name : '',
// Per row, because this list is two indexes interleaved.
// The name above the list says `trek-places`, which is true
// of the call and false of half the rows in it — the layer
// is OpenStreetMap, and a reader deciding whether to trust
// a suggestion is asking exactly that.
source: 'openstreetmap',
// Both indexes hand these over with the row. Carried rather
// than dropped so picking a suggestion has something to fall
// back on when the details lookup cannot answer.
lat: p.lat,
lng: p.lng,
}
: {
placeId: `gers:${p.gers}`,
mainText: p.name,
secondaryText: [p.address?.locality, p.address?.country].filter(Boolean).join(', '),
source: 'trek-places',
lat: p.lat,
lng: p.lng,
},
),
source: 'trek-places',
@@ -2143,7 +2157,7 @@ export class MapsService {
private async autocompleteNominatim(
input: string,
lang?: string,
): Promise<{ suggestions: { placeId: string; mainText: string; secondaryText: string }[]; source: string }> {
): Promise<MapsAutocompleteResult> {
try {
const places = await this.searchNominatim(input, lang);
const suggestions = places
@@ -196,6 +196,19 @@ describe('MapsService.autocompletePlaces', () => {
expect(second.suggestions[0].secondaryText).toBe('');
});
it('MAPS-AUTO-010: each row says which index it came from, because the list is two', async () => {
mockSearch.mockResolvedValue([hit(), osmHit()]);
const { suggestions, source } = await make().autocompletePlaces(1, INPUT);
// The name above the list describes the call, and the call asked both. Only
// the row can say which of the two answered it — without that the reader is
// told a place from OpenStreetMap came out of the TREK index, which is the
// one thing the mark beside a suggestion exists to answer.
expect(source).toBe('trek-places');
expect(suggestions.map(s => s.source)).toEqual(['trek-places', 'openstreetmap']);
});
it('MAPS-AUTO-007: the keystroke never leaves for the index while the admin has it off', async () => {
mockSearch.mockResolvedValue([hit()]);