Search results: add menu, update searchers

This commit is contained in:
Pieter Vander Vennet 2024-09-06 23:01:00 +02:00
parent 9e0ae3321f
commit ee2b3ce329
10 changed files with 88 additions and 41 deletions

View file

@ -78,9 +78,6 @@ export class SummaryTileSource extends DynamicTileSource {
isActive?: Store<boolean>
}
) {
if(layers.length === 0){
return
}
const layersSummed = layers.join("+")
const zDiff = 2
super(

View file

@ -61,6 +61,7 @@ export class RecentSearch {
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
const entry = <GeocodeResult>{
feature: selected,
display_name: selected.properties.name ?? selected.properties.alt_name ?? selected.properties.local_name,
osm_id, osm_type,
lon, lat,
}
@ -70,9 +71,9 @@ export class RecentSearch {
}
addSelected(entry: GeocodeResult) {
const id = entry.osm_type+entry.osm_id
const id = entry.osm_type + entry.osm_id
const arr = [...(this.seenThisSession.data.reverse() ?? []).slice(0, 5)]
.filter(e => e.osm_type+e.osm_id !== id)
.filter(e => e.osm_type + e.osm_id !== id)
this.seenThisSession.set([entry, ...arr])
}

View file

@ -138,20 +138,24 @@ export default class SearchState {
if (query === "") {
return
}
const geolocationState = this.state.geolocation.geolocationState
const searcher = this.state.searchState.geosearch
const bounds = this.state.mapProperties.bounds
const bbox = this.state.mapProperties.bounds.data
try {
this.isSearching.set(true)
geolocationState?.allowMoving.setData(true)
geolocationState?.requestMoment.setData(undefined) // If the GPS is still searching for a fix, we say that we don't want tozoom to it anymore
const result = await searcher.search(query, { bbox })
if (result.length == 0) {
this.feedback.set(Translations.t.general.search.nothing)
return false
let poi: SearchResult
if(this.suggestions.data){
poi = this.suggestions.data[0]
}else{
const results = GeocodingUtils.mergeSimilarResults([].concat(...await Promise.all(this.locationSearchers.map(ls => ls.search(query, { bbox: bounds.data })))))
poi = results[0]
}
const poi = result[0]
if (poi.category === "theme") {
const theme = <MinimalLayoutInformation>poi.payload
const url = MoreScreen.createUrlFor(theme)

View file

@ -26,7 +26,6 @@ export default class Constants {
"last_click",
"favourite",
"summary",
"search"
] as const
/**
* Special layers which are not included in a theme by default
@ -39,7 +38,8 @@ export default class Constants {
"import_candidate",
"usersettings",
"icons",
"filters"
"filters",
"search"
] as const
/**
* Layer IDs of layers which have special properties through built-in hooks

View file

@ -554,6 +554,10 @@ export default class ThemeViewState implements SpecialVisualizationState {
this.previewedImage.setData(undefined)
return
}
if(this.selectedElement.data){
this.selectedElement.setData(undefined)
return
}
if (this.searchState.showSearchDrawer.data){
this.searchState.showSearchDrawer.set(false)
return
@ -561,7 +565,6 @@ export default class ThemeViewState implements SpecialVisualizationState {
if (this.guistate.closeAll()){
return
}
this.selectedElement.setData(undefined)
Zoomcontrol.resetzoom()
this.focusOnMap()
})

View file

@ -0,0 +1,27 @@
<script lang="ts">
import DotsCircleHorizontal from "@rgossiaux/svelte-heroicons/solid/DotsCircleHorizontal"
import { Dropdown } from "flowbite-svelte"
import { TrashIcon } from "@babeard/svelte-heroicons/mini"
import SidebarUnit from "./SidebarUnit.svelte"
import { UIEventSource } from "../../Logic/UIEventSource"
/**
* A menu, opened by a dot
*/
export let dotColor = "var(--background-interactive)"
export let placement: "left" | "right" | "top" | "bottom" = "left"
export let isOpen : UIEventSource<boolean> = new UIEventSource<boolean>(false)
let _isOpen = isOpen.data
$: {
console.log("is open?", _isOpen)
isOpen.set(_isOpen)
}
</script>
<DotsCircleHorizontal class="w-6 h-6 dots-menu-themes transition-colors" color={$isOpen ? "black": "var(--interactive-background)"} />
<Dropdown placement="left" bind:open={_isOpen} triggeredBy=".dots-menu-themes" containerClass="p-1 border border-2 border-gray button-unstyled">
<SidebarUnit>
<slot />
</SidebarUnit>
</Dropdown>

View file

@ -18,7 +18,7 @@
padding: 0.25rem;
}
:global(.sidebar-button svg, .sidebar-button img) {
:global(.sidebar-button svg, .sidebar-button img, .sidebar-unit > button img, .sidebar-unit > button svg) {
width: 1.5rem;
height: 1.5rem;
margin-right: 0.5rem;
@ -32,7 +32,7 @@
}
:global(.sidebar-button, .sidebar-unit > a) {
:global(.sidebar-button, .sidebar-unit > a, .sidebar-unit > button) {
display: flex;
align-items: center;
border-radius: 0.25rem !important;
@ -42,12 +42,12 @@
text-align: start;
}
:global(.sidebar-button > svg , .sidebar-button > img, .sidebar-unit > a img, .sidebar-unit > a svg) {
:global(.sidebar-button > svg , .sidebar-button > img, .sidebar-unit > a img, .sidebar-unit > a svg, .sidebar-unit > button svg, .sidebar-unit > button img) {
margin-right: 0.5rem;
flex-shrink: 0;
}
:global(.sidebar-button:hover, .sidebar-unit > a:hover) {
:global(.sidebar-button:hover, .sidebar-unit > a:hover, .sidebar-unit > button:hover) {
background: var(--low-interaction-background) !important;
}

View file

@ -158,11 +158,11 @@
<Page {onlyLink} shown={pg.about_theme}>
<svelte:fragment slot="link">
<Marker icons={layout.icon} />
<Marker size="h-6 w-6 mr-2" icons={layout.icon} />
<Tr t={t.showIntroduction} />
</svelte:fragment>
<svelte:fragment slot="header">
<Marker size="h-6 w-6 mr-2" icons={layout.icon} />
<Marker size="h-8 w-8 mr-3" icons={layout.icon} />
<Tr t={layout.title} />
</svelte:fragment>
<ThemeIntroPanel {state} />

View file

@ -15,6 +15,10 @@
import ThemeResult from "./ThemeResult.svelte"
import SidebarUnit from "../Base/SidebarUnit.svelte"
import { TrashIcon } from "@babeard/svelte-heroicons/mini"
import { Dropdown, DropdownItem } from "flowbite-svelte"
import DotsCircleHorizontal from "@rgossiaux/svelte-heroicons/solid/DotsCircleHorizontal"
import DotMenu from "../Base/DotMenu.svelte"
import { CogIcon } from "@rgossiaux/svelte-heroicons/solid"
export let state: ThemeViewState
let activeFilters: Store<ActiveFilter[]> = state.layerState.activeFilters.map(fs => fs.filter(f => Constants.priviliged_layers.indexOf(<any>f.layer.id) < 0))
@ -90,11 +94,11 @@
<h3 class="m-2">
<Tr t={Translations.t.general.search.recents} />
</h3>
{#each $recentlySeen as entry}
{#each $recentlySeen as entry (entry)}
<SearchResultSvelte {entry} {state} on:select />
{/each}
<button class="as-link flex self-end" on:click={() => {recentlySeen.set([])}}>
<TrashIcon class="w-4 h-4"/>
<TrashIcon class="w-4 h-4" />
Delete history
</button>
</SidebarUnit>
@ -102,19 +106,29 @@
{#if $searchTerm.length === 0 && $recentThemes?.length > 0 && $allowOtherThemes}
<SidebarUnit>
<h3 class="m-2">
<Tr t={Translations.t.general.search.recentThemes} />
</h3>
<div class="flex w-full justify-between">
<h3 class="m-2">
<Tr t={Translations.t.general.search.recentThemes} />
</h3>
<DotMenu>
<button on:click={() => {state.userRelatedState.recentlyVisitedThemes.set([])}}>
<TrashIcon />
Delete earlier visited themes
</button>
<button>
<CogIcon/>
Edit sync settings
</button>
</DotMenu>
</div>
{#each $recentThemes as themeId (themeId)}
<SearchResultSvelte
entry={{payload: MoreScreen.officialThemesById.get(themeId), osm_id: themeId, category: "theme"}}
{state}
on:select />
{/each}
<button class="as-link flex self-end" on:click={() => {state.userRelatedState.recentlyVisitedThemes.set([])}}>
<TrashIcon class="w-4 h-4"/>
Delete history
</button>
</SidebarUnit>
{/if}

View file

@ -5,18 +5,19 @@
import Icon from "../Map/Icon.svelte"
import Tr from "../Base/Tr.svelte"
export let entry: MinimalLayoutInformation
export let entry: MinimalLayoutInformation
let otherTheme = entry
</script>
{#if entry}
<a href={MoreScreen.createUrlFor(otherTheme)}
class="flex items-center p-2 w-full gap-y-2 rounded-xl searchresult">
<a href={MoreScreen.createUrlFor(otherTheme, false)}
class="flex items-center p-2 w-full gap-y-2 rounded-xl searchresult">
<Icon icon={otherTheme.icon} clss="w-6 h-6 m-1" />
<div class="flex flex-col">
<b>
<Tr t={new Translation(otherTheme.title)} />
</b>
<!--<Tr t={new Translation(otherTheme.shortDescription)} /> -->
</div>
</a>
<Icon icon={otherTheme.icon} clss="w-6 h-6 m-1" />
<div class="flex flex-col">
<b>
<Tr t={new Translation(otherTheme.title)} />
</b>
<!--<Tr t={new Translation(otherTheme.shortDescription)} /> -->
</div>
</a>
{/if}