Skip choice for unique postcode matches
This commit is contained in:
parent
71e1b57164
commit
7da704d837
4 changed files with 36 additions and 1 deletions
|
|
@ -118,6 +118,7 @@ the search box. Selecting a stop shows its tags and stop-area-aware bus route
|
||||||
relations. Stop results identify their transport mode (such as bus, rail or
|
relations. Stop results identify their transport mode (such as bus, rail or
|
||||||
tram), and moving the map at zoom level 15 or closer loads stops in the visible
|
tram), and moving the map at zoom level 15 or closer loads stops in the visible
|
||||||
area. Wider map views deliberately do not query Overpass.
|
area. Wider map views deliberately do not query Overpass.
|
||||||
|
Postcode searches with exactly one Nominatim match skip the choice screen.
|
||||||
The current map bounds bias Nominatim's ranking without excluding UK matches
|
The current map bounds bias Nominatim's ranking without excluding UK matches
|
||||||
outside the visible area.
|
outside the visible area.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,11 @@ function parseCoordinates(value) {
|
||||||
return {lat, lon};
|
return {lat, lon};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Return whether text has the shape of a complete UK postcode. */
|
||||||
|
function isUkPostcode(value) {
|
||||||
|
return /^(?:GIR\s*0AA|[A-Z]{1,2}\d[A-Z\d]?\s*\d[A-Z]{2})$/i.test(value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
/** Put the current search in the address bar without reloading the page. */
|
/** Put the current search in the address bar without reloading the page. */
|
||||||
function setSearchUrl(params, replace = false) {
|
function setSearchUrl(params, replace = false) {
|
||||||
const query = params.toString();
|
const query = params.toString();
|
||||||
|
|
@ -305,6 +310,10 @@ function renderStops(data, fitMap = true, sortOrigin = null, preserveSelection =
|
||||||
|
|
||||||
/** Show UK-only Nominatim matches and wait for the user to choose one. */
|
/** Show UK-only Nominatim matches and wait for the user to choose one. */
|
||||||
function renderGeocodeChoices(data) {
|
function renderGeocodeChoices(data) {
|
||||||
|
if (data.locations.length === 1 && isUkPostcode(data.query)) {
|
||||||
|
chooseLocation(data.locations[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
selectedStop = null;
|
selectedStop = null;
|
||||||
markers.clearLayers();
|
markers.clearLayers();
|
||||||
if (searchMarker) { searchMarker.remove(); searchMarker = null; }
|
if (searchMarker) { searchMarker.remove(); searchMarker = null; }
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><code>q</code></td>
|
<td><code>q</code></td>
|
||||||
<td>A postcode, street, place name, or exact ATCO code. Place searches show up to 20 UK-only matches to choose from.</td>
|
<td>A postcode, street, place name, or exact ATCO code. Place searches show up to 20 UK-only matches to choose from; a postcode with one match opens directly.</td>
|
||||||
<td><a href="{{ url_for('index', q='Bristol Temple Meads') }}"><code>{{ url_for('index') }}?q=Bristol+Temple+Meads</code></a></td>
|
<td><a href="{{ url_for('index', q='Bristol Temple Meads') }}"><code>{{ url_for('index') }}?q=Bristol+Temple+Meads</code></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,31 @@ def test_coordinate_url_and_search_input(chromium_browser: Any, flask_url: str)
|
||||||
page.close()
|
page.close()
|
||||||
|
|
||||||
|
|
||||||
|
def test_single_postcode_match_opens_directly(chromium_browser: Any, flask_url: str) -> None:
|
||||||
|
"""A unique UK postcode result skips the location-choice panel."""
|
||||||
|
page = chromium_browser.new_page(viewport={"width": 1280, "height": 800})
|
||||||
|
page.route("**/api/search?*", lambda route: route.fulfill(json={
|
||||||
|
"kind": "geocode",
|
||||||
|
"query": "SW1A 1AA",
|
||||||
|
"locations": [{
|
||||||
|
"lat": 51.501, "lon": -0.142, "label": "Westminster, London",
|
||||||
|
"type": "postcode",
|
||||||
|
}],
|
||||||
|
}))
|
||||||
|
page.route("**/api/stops?*", lambda route: route.fulfill(json={
|
||||||
|
"kind": "location",
|
||||||
|
"location": {"lat": 51.501, "lon": -0.142, "label": "Westminster, London"},
|
||||||
|
"stops": [],
|
||||||
|
}))
|
||||||
|
page.goto(flask_url, wait_until="networkidle")
|
||||||
|
page.get_by_label("Location or ATCO code").fill("SW1A 1AA")
|
||||||
|
page.get_by_role("button", name="Search").click()
|
||||||
|
playwright_api.expect(page).to_have_url(re.compile(r"\?lat=51.501&lon=-0.142$"))
|
||||||
|
playwright_api.expect(page.locator("#stop-count")).to_have_text("0 found")
|
||||||
|
playwright_api.expect(page.locator("#geocode-panel")).to_be_hidden()
|
||||||
|
page.close()
|
||||||
|
|
||||||
|
|
||||||
def test_mobile_layout_opens_results_sheet(chromium_browser: Any, flask_url: str) -> None:
|
def test_mobile_layout_opens_results_sheet(chromium_browser: Any, flask_url: str) -> None:
|
||||||
"""The finder exposes its search panel as an open mobile bottom sheet."""
|
"""The finder exposes its search panel as an open mobile bottom sheet."""
|
||||||
page = chromium_browser.new_page(viewport={"width": 390, "height": 844})
|
page = chromium_browser.new_page(viewport={"width": 390, "height": 844})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue