forked from MapComplete/MapComplete
		
	Fix #1956 with workaround
This commit is contained in:
		
							parent
							
								
									4fd592cc4f
								
							
						
					
					
						commit
						8b6ee7075c
					
				
					 6 changed files with 106 additions and 66 deletions
				
			
		|  | @ -198,6 +198,9 @@ export default class MetaTagging { | ||||||
|         for (let i = 0; i < features.length; i++) { |         for (let i = 0; i < features.length; i++) { | ||||||
|             const feature = features[i] |             const feature = features[i] | ||||||
|             const tags = featurePropertiesStores?.getStore(feature.properties.id) |             const tags = featurePropertiesStores?.getStore(feature.properties.id) | ||||||
|  |             if(!tags){ | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|             let somethingChanged = false |             let somethingChanged = false | ||||||
|             const definedTags = new Set(Object.getOwnPropertyNames(feature.properties)) |             const definedTags = new Set(Object.getOwnPropertyNames(feature.properties)) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										62
									
								
								src/UI/Base/SelectedElementPanel.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/UI/Base/SelectedElementPanel.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | ||||||
|  | <script lang="ts"> | ||||||
|  |   import type { SpecialVisualizationState } from "../SpecialVisualization" | ||||||
|  |   import type { Feature } from "geojson" | ||||||
|  |   import SelectedElementView from "../BigComponents/SelectedElementView.svelte" | ||||||
|  |   import SelectedElementTitle from "../BigComponents/SelectedElementTitle.svelte" | ||||||
|  |   import UserRelatedState from "../../Logic/State/UserRelatedState" | ||||||
|  |   import { LastClickFeatureSource } from "../../Logic/FeatureSource/Sources/LastClickFeatureSource" | ||||||
|  |   import Loading from "./Loading.svelte" | ||||||
|  |   import { onDestroy } from "svelte" | ||||||
|  | 
 | ||||||
|  |   export let state: SpecialVisualizationState | ||||||
|  |   export let selected: Feature | ||||||
|  |   let tags = state.featureProperties.getStore(selected.properties.id) | ||||||
|  | 
 | ||||||
|  |   export let absolute = true | ||||||
|  |   function getLayer(properties: Record<string, string>) { | ||||||
|  |     if (properties.id === "settings") { | ||||||
|  |       return UserRelatedState.usersettingsConfig | ||||||
|  |     } | ||||||
|  |     if (properties.id.startsWith(LastClickFeatureSource.newPointElementId)) { | ||||||
|  |       return state.layout.layers.find((l) => l.id === "last_click") | ||||||
|  |     } | ||||||
|  |     if (properties.id === "location_track") { | ||||||
|  |       return state.layout.layers.find((l) => l.id === "gps_track") | ||||||
|  |     } | ||||||
|  |     return state.layout.getMatchingLayer(properties) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   let layer = getLayer(selected.properties) | ||||||
|  | 
 | ||||||
|  |   let stillMatches = tags.map( | ||||||
|  |     (tags) => !layer?.source?.osmTags || layer?.source?.osmTags?.matchesProperties(tags) | ||||||
|  |   ) | ||||||
|  |   onDestroy( | ||||||
|  |     stillMatches.addCallbackAndRunD(matches => { | ||||||
|  |       if (matches) { | ||||||
|  |         return | ||||||
|  |       } | ||||||
|  |       /* | ||||||
|  |        * This is a workaround. Normally, we would dynamically rewrite 'layer' and this should update the view. | ||||||
|  |        * However, because there are quite some legacy elements and some elements have a different layer calculation, | ||||||
|  |        * we simply close the popup and open it again. | ||||||
|  |        * See #1956 | ||||||
|  |       */ | ||||||
|  |       state.selectedElement.setData(undefined) | ||||||
|  |       requestAnimationFrame(() => { | ||||||
|  |         state.selectedElement.setData(selected) | ||||||
|  |       }) | ||||||
|  |     }) | ||||||
|  |   ) | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | {#if !$stillMatches} | ||||||
|  |   <Loading /> | ||||||
|  | {:else} | ||||||
|  |   <div class="normal-background flex h-full w-full flex-col" class:absolute={absolute}> | ||||||
|  |     <SelectedElementTitle {state} {layer} selectedElement={selected} /> | ||||||
|  |     <SelectedElementView {state} {layer} selectedElement={selected} /> | ||||||
|  |   </div> | ||||||
|  | {/if} | ||||||
|  | @ -1,8 +1,3 @@ | ||||||
| <script lang="ts"> |  | ||||||
| 
 |  | ||||||
|   import Translations from "../i18n/Translations" |  | ||||||
| </script> |  | ||||||
| 
 |  | ||||||
| <div class="flex h-full flex-col"> | <div class="flex h-full flex-col"> | ||||||
|   <h2 class="low-interaction m-0 flex items-center p-4 drop-shadow-md"> |   <h2 class="low-interaction m-0 flex items-center p-4 drop-shadow-md"> | ||||||
|     <slot name="title" /> |     <slot name="title" /> | ||||||
|  |  | ||||||
|  | @ -72,14 +72,14 @@ | ||||||
|     {/if} |     {/if} | ||||||
|   </div> |   </div> | ||||||
|   <slot name="close-button"> |   <slot name="close-button"> | ||||||
|     <div |     <button | ||||||
|       class="mt-2 h-fit shrink-0 rounded-full border-none p-0 cursor-pointer" |       class="mt-2 h-fit shrink-0 rounded-full border-none p-0 cursor-pointer self-center" | ||||||
|       on:click={() => state.selectedElement.setData(undefined)} |       on:click={() => state.selectedElement.setData(undefined)} | ||||||
|       style="border: 0 !important; padding: 0 !important;" |       style="border: 0 !important; padding: 0 !important;" | ||||||
|       use:ariaLabel={Translations.t.general.backToMap} |       use:ariaLabel={Translations.t.general.backToMap} | ||||||
|     > |     > | ||||||
|       <XCircleIcon aria-hidden={true} class="h-8 w-8" /> |       <XCircleIcon aria-hidden={true} class="h-8 w-8" /> | ||||||
|     </div> |     </button> | ||||||
|   </slot> |   </slot> | ||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,12 +3,10 @@ | ||||||
|   import { Store, UIEventSource } from "../../Logic/UIEventSource" |   import { Store, UIEventSource } from "../../Logic/UIEventSource" | ||||||
|   import LayerConfig from "../../Models/ThemeConfig/LayerConfig" |   import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | ||||||
|   import type { SpecialVisualizationState } from "../SpecialVisualization" |   import type { SpecialVisualizationState } from "../SpecialVisualization" | ||||||
|   import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte" |  | ||||||
|   import { onDestroy } from "svelte" |   import { onDestroy } from "svelte" | ||||||
|   import Translations from "../i18n/Translations" |   import Translations from "../i18n/Translations" | ||||||
|   import Tr from "../Base/Tr.svelte" |   import Tr from "../Base/Tr.svelte" | ||||||
|   import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" |   import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig" | ||||||
|   import UserRelatedState from "../../Logic/State/UserRelatedState" |  | ||||||
|   import Delete_icon from "../../assets/svg/Delete_icon.svelte" |   import Delete_icon from "../../assets/svg/Delete_icon.svelte" | ||||||
|   import BackButton from "../Base/BackButton.svelte" |   import BackButton from "../Base/BackButton.svelte" | ||||||
|   import TagRenderingEditableDynamic from "../Popup/TagRendering/TagRenderingEditableDynamic.svelte" |   import TagRenderingEditableDynamic from "../Popup/TagRendering/TagRenderingEditableDynamic.svelte" | ||||||
|  | @ -24,24 +22,8 @@ | ||||||
| 
 | 
 | ||||||
|   let isAddNew = tags.mapD(t => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false) |   let isAddNew = tags.mapD(t => t?.id?.startsWith(LastClickFeatureSource.newPointElementId) ?? false) | ||||||
| 
 | 
 | ||||||
|   function getLayer(properties: Record<string, string>) { |  | ||||||
|     if (properties.id === "settings") { |  | ||||||
|       return UserRelatedState.usersettingsConfig |  | ||||||
|     } |  | ||||||
|     if (properties.id.startsWith(LastClickFeatureSource.newPointElementId)) { |  | ||||||
|       return state.layout.layers.find((l) => l.id === "last_click") |  | ||||||
|     } |  | ||||||
|     if (properties.id === "location_track") { |  | ||||||
|       return state.layout.layers.find((l) => l.id === "gps_track") |  | ||||||
|     } |  | ||||||
|     return state.layout.getMatchingLayer(properties) |  | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   let layer: LayerConfig = getLayer(selectedElement.properties) |   export let layer: LayerConfig | ||||||
| 
 |  | ||||||
|   let stillMatches = tags.map( |  | ||||||
|     (tags) => !layer?.source?.osmTags || layer.source.osmTags?.matchesProperties(tags) |  | ||||||
|   ) |  | ||||||
| 
 | 
 | ||||||
|   let _metatags: Record<string, string> |   let _metatags: Record<string, string> | ||||||
|   if (state?.userRelatedState?.preferencesAsTags) { |   if (state?.userRelatedState?.preferencesAsTags) { | ||||||
|  | @ -53,7 +35,7 @@ | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   let knownTagRenderings: Store<TagRenderingConfig[]> = tags.mapD((tgs) => |   let knownTagRenderings: Store<TagRenderingConfig[]> = tags.mapD((tgs) => | ||||||
|     layer.tagRenderings.filter( |     layer?.tagRenderings?.filter( | ||||||
|       (config) => |       (config) => | ||||||
|         (config.condition?.matchesProperties(tgs) ?? true) && |         (config.condition?.matchesProperties(tgs) ?? true) && | ||||||
|         (config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true) && |         (config.metacondition?.matchesProperties({ ...tgs, ..._metatags }) ?? true) && | ||||||
|  | @ -62,11 +44,7 @@ | ||||||
|   ) |   ) | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| {#if !$stillMatches} | {#if $tags._deleted === "yes"} | ||||||
|   <div class="alert" aria-live="assertive"> |  | ||||||
|     <Tr t={Translations.t.delete.isChanged} /> |  | ||||||
|   </div> |  | ||||||
| {:else if $tags._deleted === "yes"} |  | ||||||
|   <div class="flex w-full flex-col p-2"> |   <div class="flex w-full flex-col p-2"> | ||||||
|     <div aria-live="assertive" class="alert flex items-center justify-center self-stretch"> |     <div aria-live="assertive" class="alert flex items-center justify-center self-stretch"> | ||||||
|       <Delete_icon class="m-2 h-8 w-8" /> |       <Delete_icon class="m-2 h-8 w-8" /> | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ | ||||||
|     EyeIcon, |     EyeIcon, | ||||||
|     HeartIcon, |     HeartIcon, | ||||||
|     MenuIcon, |     MenuIcon, | ||||||
|     XCircleIcon, |     XCircleIcon | ||||||
|   } from "@rgossiaux/svelte-heroicons/solid" |   } from "@rgossiaux/svelte-heroicons/solid" | ||||||
|   import Tr from "./Base/Tr.svelte" |   import Tr from "./Base/Tr.svelte" | ||||||
|   import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte" |   import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte" | ||||||
|  | @ -72,9 +72,8 @@ | ||||||
|   import DocumentChartBar from "@babeard/svelte-heroicons/outline/DocumentChartBar" |   import DocumentChartBar from "@babeard/svelte-heroicons/outline/DocumentChartBar" | ||||||
|   import Marker from "./Map/Marker.svelte" |   import Marker from "./Map/Marker.svelte" | ||||||
|   import AboutMapComplete from "./BigComponents/AboutMapComplete.svelte" |   import AboutMapComplete from "./BigComponents/AboutMapComplete.svelte" | ||||||
|   import IfNot from "./Base/IfNot.svelte" |  | ||||||
|   import Hotkeys from "./Base/Hotkeys" |  | ||||||
|   import HotkeyTable from "./BigComponents/HotkeyTable.svelte" |   import HotkeyTable from "./BigComponents/HotkeyTable.svelte" | ||||||
|  |   import SelectedElementPanel from "./Base/SelectedElementPanel.svelte" | ||||||
| 
 | 
 | ||||||
|   export let state: ThemeViewState |   export let state: ThemeViewState | ||||||
|   let layout = state.layout |   let layout = state.layout | ||||||
|  | @ -146,7 +145,7 @@ | ||||||
|     const bottomRight = mlmap.unproject([rect.right, rect.bottom]) |     const bottomRight = mlmap.unproject([rect.right, rect.bottom]) | ||||||
|     const bbox = new BBox([ |     const bbox = new BBox([ | ||||||
|       [topLeft.lng, topLeft.lat], |       [topLeft.lng, topLeft.lat], | ||||||
|       [bottomRight.lng, bottomRight.lat], |       [bottomRight.lng, bottomRight.lat] | ||||||
|     ]) |     ]) | ||||||
|     state.visualFeedbackViewportBounds.setData(bbox) |     state.visualFeedbackViewportBounds.setData(bbox) | ||||||
|   } |   } | ||||||
|  | @ -213,7 +212,7 @@ | ||||||
| 
 | 
 | ||||||
| <main> | <main> | ||||||
|   <div class="absolute top-0 left-0 h-screen w-screen overflow-hidden"> |   <div class="absolute top-0 left-0 h-screen w-screen overflow-hidden"> | ||||||
|     <MaplibreMap map={maplibremap} mapProperties={mapproperties} autorecovery={true}/> |     <MaplibreMap map={maplibremap} mapProperties={mapproperties} autorecovery={true} /> | ||||||
|   </div> |   </div> | ||||||
| 
 | 
 | ||||||
|   {#if $visualFeedback} |   {#if $visualFeedback} | ||||||
|  | @ -287,9 +286,9 @@ | ||||||
|           htmlElem={openCurrentViewLayerButton} |           htmlElem={openCurrentViewLayerButton} | ||||||
|         > |         > | ||||||
|           <div class="w-8 h-8 cursor-pointer"> |           <div class="w-8 h-8 cursor-pointer"> | ||||||
|           <ToSvelte |             <ToSvelte | ||||||
|             construct={() => currentViewLayer.defaultIcon()} |               construct={() => currentViewLayer.defaultIcon()} | ||||||
|           /> |             /> | ||||||
|           </div> |           </div> | ||||||
|         </MapControlButton> |         </MapControlButton> | ||||||
|       {/if} |       {/if} | ||||||
|  | @ -303,7 +302,7 @@ | ||||||
|         <div class="thanks"> |         <div class="thanks"> | ||||||
|           Testserver |           Testserver | ||||||
|         </div> |         </div> | ||||||
|         {/if} |       {/if} | ||||||
|       <If condition={state.featureSwitches.featureSwitchFakeUser}> |       <If condition={state.featureSwitches.featureSwitchFakeUser}> | ||||||
|         <div class="alert w-fit">Faking a user (Testmode)</div> |         <div class="alert w-fit">Faking a user (Testmode)</div> | ||||||
|       </If> |       </If> | ||||||
|  | @ -453,29 +452,32 @@ | ||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|       <div slot="close-button" /> |       <div slot="close-button" /> | ||||||
|       <div class="normal-background absolute flex h-full w-full flex-col"> |       <SelectedElementPanel {state} selected={$selectedElement} /> | ||||||
|         <SelectedElementTitle {state} layer={$selectedLayer} selectedElement={$selectedElement} /> |  | ||||||
|         <SelectedElementView {state} selectedElement={$selectedElement} /> |  | ||||||
|       </div> |  | ||||||
|     </ModalRight> |     </ModalRight> | ||||||
|   {/if} |   {/if} | ||||||
| 
 | 
 | ||||||
|   {#if $selectedElement !== undefined && $selectedLayer !== undefined && $selectedLayer.popupInFloatover} |   {#if $selectedElement !== undefined && $selectedLayer !== undefined && $selectedLayer.popupInFloatover} | ||||||
|     <!-- Floatover with the selected element, if applicable --> |     <!-- Floatover with the selected element, if applicable --> | ||||||
|     <FloatOver | 
 | ||||||
|       on:close={() => { |     {#if $selectedLayer.popupInFloatover === "title"} | ||||||
|  |       <FloatOver | ||||||
|  |         on:close={() => { | ||||||
|         state.selectedElement.setData(undefined) |         state.selectedElement.setData(undefined) | ||||||
|       }} |       }} | ||||||
|     > |       > | ||||||
|       <div class="flex h-full w-full flex-col"> |         <span slot="close-button" /> | ||||||
|         {#if $selectedLayer.popupInFloatover === "title"} |          <SelectedElementPanel absolute={false} {state} selected={$selectedElement} /> | ||||||
|           <SelectedElementTitle {state} layer={$selectedLayer} selectedElement={$selectedElement}> |       </FloatOver> | ||||||
|             <span slot="close-button" /> |     {:else} | ||||||
|           </SelectedElementTitle> |       <FloatOver | ||||||
|         {/if} |         on:close={() => { | ||||||
|         <SelectedElementView {state} selectedElement={$selectedElement} /> |         state.selectedElement.setData(undefined) | ||||||
|       </div> |       }} | ||||||
|     </FloatOver> |       > | ||||||
|  |         <SelectedElementView {state} layer={$selectedLayer} selectedElement={$selectedElement} /> | ||||||
|  |       </FloatOver> | ||||||
|  |     {/if} | ||||||
|  | 
 | ||||||
|   {/if} |   {/if} | ||||||
| 
 | 
 | ||||||
|   <If condition={state.previewedImage.map((i) => i !== undefined)}> |   <If condition={state.previewedImage.map((i) => i !== undefined)}> | ||||||
|  | @ -551,13 +553,13 @@ | ||||||
|         state.guistate.backgroundLayerSelectionIsOpened.setData(false) |         state.guistate.backgroundLayerSelectionIsOpened.setData(false) | ||||||
|       }} |       }} | ||||||
|     > |     > | ||||||
|         <RasterLayerOverview |       <RasterLayerOverview | ||||||
|           {availableLayers} |         {availableLayers} | ||||||
|           map={state.map} |         map={state.map} | ||||||
|           mapproperties={state.mapProperties} |         mapproperties={state.mapProperties} | ||||||
|           userstate={state.userRelatedState} |         userstate={state.userRelatedState} | ||||||
|           visible={state.guistate.backgroundLayerSelectionIsOpened} |         visible={state.guistate.backgroundLayerSelectionIsOpened} | ||||||
|         /> |       /> | ||||||
|     </FloatOver> |     </FloatOver> | ||||||
|   </IfHidden> |   </IfHidden> | ||||||
| 
 | 
 | ||||||
|  | @ -583,7 +585,7 @@ | ||||||
|         <div slot="content0" class="flex flex-col"> |         <div slot="content0" class="flex flex-col"> | ||||||
|           <AboutMapComplete {state} /> |           <AboutMapComplete {state} /> | ||||||
|           <div class="m-2 flex flex-col"> |           <div class="m-2 flex flex-col"> | ||||||
|             <HotkeyTable/> |             <HotkeyTable /> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue