forked from MapComplete/MapComplete
		
	Search results: add menu, update searchers
This commit is contained in:
		
							parent
							
								
									9e0ae3321f
								
							
						
					
					
						commit
						ee2b3ce329
					
				
					 10 changed files with 88 additions and 41 deletions
				
			
		|  | @ -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( | ||||
|  |  | |||
|  | @ -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]) | ||||
|     } | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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() | ||||
|         }) | ||||
|  |  | |||
							
								
								
									
										27
									
								
								src/UI/Base/DotMenu.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/UI/Base/DotMenu.svelte
									
										
									
									
									
										Normal 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> | ||||
|  | @ -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; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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} /> | ||||
|  |  | |||
|  | @ -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} | ||||
| 
 | ||||
|  |  | |||
|  | @ -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} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue