forked from MapComplete/MapComplete
		
	Fix: correctly replace fields in filterview
This commit is contained in:
		
							parent
							
								
									af7bc0f7ce
								
							
						
					
					
						commit
						ae491f4916
					
				
					 2 changed files with 77 additions and 49 deletions
				
			
		|  | @ -1,57 +1,60 @@ | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
|   import FilteredLayer from "../../Models/FilteredLayer"; |     import FilteredLayer from "../../Models/FilteredLayer"; | ||||||
|   import type { FilterConfigOption } from "../../Models/ThemeConfig/FilterConfig"; |     import type {FilterConfigOption} from "../../Models/ThemeConfig/FilterConfig"; | ||||||
|   import Locale from "../i18n/Locale"; |     import Locale from "../i18n/Locale"; | ||||||
|   import ValidatedInput from "../InputElement/ValidatedInput.svelte"; |     import ValidatedInput from "../InputElement/ValidatedInput.svelte"; | ||||||
|   import { UIEventSource } from "../../Logic/UIEventSource"; |     import {UIEventSource} from "../../Logic/UIEventSource"; | ||||||
|   import { onDestroy } from "svelte"; |     import {onDestroy} from "svelte"; | ||||||
|  |     import {Utils} from "../../Utils"; | ||||||
| 
 | 
 | ||||||
|   export let filteredLayer: FilteredLayer; |     export let filteredLayer: FilteredLayer; | ||||||
|   export let option: FilterConfigOption; |     export let option: FilterConfigOption; | ||||||
|   export let id: string; |     export let id: string; | ||||||
|   let parts: string[]; |     let parts: ({ message: string } | { subs: string })[]; | ||||||
|   let language = Locale.language; |     let language = Locale.language; | ||||||
|   $: { |     $: { | ||||||
|     parts = option.question.textFor($language).split("{"); |         const template = option.question.textFor($language) | ||||||
|   } |         parts = Utils.splitIntoSubstitutionParts(template) | ||||||
|   let fieldValues: Record<string, UIEventSource<string>> = {}; |  | ||||||
|   let fieldTypes: Record<string, string> = {}; |  | ||||||
|   let appliedFilter = <UIEventSource<string>>filteredLayer.appliedFilters.get(id); |  | ||||||
|   let initialState: Record<string, string> = JSON.parse(appliedFilter?.data ?? "{}"); |  | ||||||
| 
 |  | ||||||
|   function setFields() { |  | ||||||
|     const properties: Record<string, string> = {}; |  | ||||||
|     for (const key in fieldValues) { |  | ||||||
|       const v = fieldValues[key].data; |  | ||||||
|       const k = key.substring(0, key.length - 1); |  | ||||||
|       if (v === undefined) { |  | ||||||
|         properties[k] = undefined; |  | ||||||
|       } else { |  | ||||||
|         properties[k] = v; |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|     appliedFilter?.setData(FilteredLayer.fieldsToString(properties)); |     let fieldValues: Record<string, UIEventSource<string>> = {}; | ||||||
|   } |     let fieldTypes: Record<string, string> = {}; | ||||||
|  |     let appliedFilter = <UIEventSource<string>>filteredLayer.appliedFilters.get(id); | ||||||
|  |     let initialState: Record<string, string> = JSON.parse(appliedFilter?.data ?? "{}"); | ||||||
| 
 | 
 | ||||||
|   for (const field of option.fields) { |     function setFields() { | ||||||
|     // A bit of cheating: the 'parts' will have '}' suffixed for fields |         const properties: Record<string, string> = {}; | ||||||
|     fieldTypes[field.name + "}"] = field.type; |         for (const key in fieldValues) { | ||||||
|     const src = new UIEventSource<string>(initialState[field.name] ?? ""); |             const v = fieldValues[key].data; | ||||||
|     fieldValues[field.name + "}"] = src; |             if (v === undefined) { | ||||||
|     onDestroy(src.stabilized(200).addCallback(() => { |                 properties[key] = undefined; | ||||||
|       setFields(); |             } else { | ||||||
|     })); |                 properties[key] = v; | ||||||
|   } |             } | ||||||
|  |         } | ||||||
|  |         appliedFilter?.setData(FilteredLayer.fieldsToString(properties)); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     for (const field of option.fields) { | ||||||
|  |         // A bit of cheating: the 'parts' will have '}' suffixed for fields | ||||||
|  |         const src = new UIEventSource<string>(initialState[field.name] ?? ""); | ||||||
|  |         fieldTypes[field.name] = field.type; | ||||||
|  |         fieldValues[field.name] = src; | ||||||
|  |         onDestroy(src.stabilized(200).addCallback(() => { | ||||||
|  |             setFields(); | ||||||
|  |         })); | ||||||
|  |     } | ||||||
|  |      | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <div> | <div> | ||||||
|   {#each parts as part, i} |     {#each parts as part, i} | ||||||
|     {#if part.endsWith("}")} |         {#if part.subs} | ||||||
|       <!-- This is a field! --> |             <!-- This is a field! --> | ||||||
|       <ValidatedInput value={fieldValues[part]} type={fieldTypes[part]} /> |             <span class="mx-1"> | ||||||
|     {:else} |             <ValidatedInput value={fieldValues[part.subs]} type={fieldTypes[part.subs]}/> | ||||||
|       {part} |             </span> | ||||||
|     {/if} |         {:else} | ||||||
|   {/each} |             {part.message} | ||||||
|  |         {/if} | ||||||
|  |     {/each} | ||||||
| </div> | </div> | ||||||
|  |  | ||||||
							
								
								
									
										27
									
								
								Utils.ts
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								Utils.ts
									
										
									
									
									
								
							|  | @ -1430,7 +1430,7 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | ||||||
|         return true |         return true | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     static SameObject(a: any, b: any) { |    public static SameObject(a: any, b: any) { | ||||||
|         if (a === b) { |         if (a === b) { | ||||||
|             return true |             return true | ||||||
|         } |         } | ||||||
|  | @ -1465,4 +1465,29 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be | ||||||
|     ) { |     ) { | ||||||
|         return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b) |         return Math.abs(c0.r - c1.r) + Math.abs(c0.g - c1.g) + Math.abs(c0.b - c1.b) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * | ||||||
|  |      * Utils.splitIntoSubstitutionParts("abc") // => [{message: "abc"}]
 | ||||||
|  |      * Utils.splitIntoSubstitutionParts("abc {search} def") // => [{message: "abc "}, {subs: "search"}, {message: " def"}]
 | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     public static splitIntoSubstitutionParts(template: string): ({ message: string } | {subs: string})[]{ | ||||||
|  |         const preparts = template.split("{") | ||||||
|  |         const spec : ({ message: string } | {subs: string})[] = [] | ||||||
|  |         for (const prepart of preparts) { | ||||||
|  |             const postParts = prepart.split("}") | ||||||
|  |             if(postParts.length === 1){ | ||||||
|  |                 // This was a normal part
 | ||||||
|  |                 spec.push({message: postParts[0]}) | ||||||
|  |             }else{ | ||||||
|  |                 const [subs, message] = postParts | ||||||
|  |                 spec.push({subs}) | ||||||
|  |                 if(message !== ""){ | ||||||
|  |                     spec.push({message}) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return spec | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue