| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   import { UIEventSource } from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  |   import type { Feature } from "geojson"; | 
					
						
							|  |  |  |   import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; | 
					
						
							|  |  |  |   import ToSvelte from "../Base/ToSvelte.svelte"; | 
					
						
							|  |  |  |   import Svg from "../../Svg.js"; | 
					
						
							|  |  |  |   import Translations from "../i18n/Translations"; | 
					
						
							|  |  |  |   import Loading from "../Base/Loading.svelte"; | 
					
						
							|  |  |  |   import Hotkeys from "../Base/Hotkeys"; | 
					
						
							|  |  |  |   import { Geocoding } from "../../Logic/Osm/Geocoding"; | 
					
						
							|  |  |  |   import { BBox } from "../../Logic/BBox"; | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |   import { GeoIndexedStoreForLayer } from "../../Logic/FeatureSource/Actors/GeoIndexedStore"; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |   export let perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer> | undefined = undefined; | 
					
						
							|  |  |  |   export let bounds: UIEventSource<BBox>; | 
					
						
							|  |  |  |   export let selectedElement: UIEventSource<Feature> | undefined = undefined; | 
					
						
							|  |  |  |   export let selectedLayer: UIEventSource<LayerConfig> | undefined = undefined; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let searchContents: string = undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let isRunning: boolean = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let inputElement: HTMLInputElement; | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let feedback: string = undefined; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Hotkeys.RegisterHotkey( | 
					
						
							|  |  |  |     { ctrl: "F" }, | 
					
						
							|  |  |  |     Translations.t.hotkeyDocumentation.selectSearch, | 
					
						
							|  |  |  |     () => { | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |       inputElement?.focus(); | 
					
						
							|  |  |  |       inputElement?.select(); | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |   ); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |   async function performSearch() { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       isRunning = true; | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |       searchContents = searchContents?.trim() ?? ""; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       if (searchContents === "") { | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |       const result = await Geocoding.Search(searchContents, bounds.data); | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       if (result.length == 0) { | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |         feedback = Translations.t.search.nothing.txt; | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |       const poi = result[0]; | 
					
						
							|  |  |  |       const [lat0, lat1, lon0, lon1] = poi.boundingbox; | 
					
						
							|  |  |  |       bounds.set(new BBox([[lon0, lat0], [lon1, lat1]]).pad(0.01)); | 
					
						
							|  |  |  |       if (perLayer !== undefined) { | 
					
						
							|  |  |  |         const id = poi.osm_type + "/" + poi.osm_id; | 
					
						
							|  |  |  |         const layers = Array.from(perLayer?.values() ?? []); | 
					
						
							|  |  |  |         for (const layer of layers) { | 
					
						
							|  |  |  |           const found = layer.features.data.find(f => f.properties.id === id); | 
					
						
							|  |  |  |           selectedElement?.setData(found); | 
					
						
							|  |  |  |           selectedLayer?.setData(layer.layer.layerDef); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |     } catch (e) { | 
					
						
							|  |  |  |       console.error(e); | 
					
						
							|  |  |  |       feedback = Translations.t.search.error.txt; | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     } finally { | 
					
						
							|  |  |  |       isRunning = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-24 02:27:55 +02:00
										 |  |  | <div class="flex normal-background rounded-full pl-2 justify-between"> | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |   <form> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     {#if isRunning} | 
					
						
							|  |  |  |       <Loading>{Translations.t.general.search.searching}</Loading> | 
					
						
							| 
									
										
										
										
											2023-04-14 02:42:57 +02:00
										 |  |  |     {:else if feedback !== undefined} | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |       <div class="alert" on:click={() => feedback = undefined}> | 
					
						
							|  |  |  |         {feedback} | 
					
						
							|  |  |  |       </div> | 
					
						
							|  |  |  |     {:else } | 
					
						
							|  |  |  |       <input | 
					
						
							| 
									
										
										
										
											2023-03-30 04:51:56 +02:00
										 |  |  |         type="search" | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |         bind:this={inputElement} | 
					
						
							|  |  |  |         on:keypress={keypr => keypr.key === "Enter" ? performSearch() : undefined} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bind:value={searchContents} | 
					
						
							|  |  |  |         placeholder={Translations.t.general.search.search}> | 
					
						
							|  |  |  |     {/if} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   </form> | 
					
						
							| 
									
										
										
										
											2023-04-24 02:27:55 +02:00
										 |  |  |   <div class="w-6 h-6 self-end" on:click={performSearch}> | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |     <ToSvelte construct={Svg.search_ui}></ToSvelte> | 
					
						
							|  |  |  |   </div> | 
					
						
							|  |  |  | </div> |