| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  | <script lang="ts"> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     import EditLayerState from "./EditLayerState"; | 
					
						
							|  |  |  |     import type {ConfigMeta} from "./configMeta"; | 
					
						
							|  |  |  |     import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							|  |  |  |     import type { | 
					
						
							|  |  |  |         QuestionableTagRenderingConfigJson | 
					
						
							|  |  |  |     } from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"; | 
					
						
							|  |  |  |     import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte"; | 
					
						
							|  |  |  |     import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"; | 
					
						
							|  |  |  |     import {onDestroy} from "svelte"; | 
					
						
							|  |  |  |     import SchemaBasedInput from "./SchemaBasedInput.svelte"; | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     import type {JsonSchemaType} from "./jsonSchema"; | 
					
						
							|  |  |  |     import nmd from "nano-markdown" | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * If 'types' is defined: allow the user to pick one of the types to input. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     export let state: EditLayerState | 
					
						
							|  |  |  |     export let path: (string | number)[] = [] | 
					
						
							|  |  |  |     export let schema: ConfigMeta | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     const defaultOption = schema.hints.typesdefault ? Number(schema.hints.typesdefault) : undefined | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     const hasBooleanOption = (<JsonSchemaType[]>schema.type)?.findIndex(t => t["type"] === "boolean") | 
					
						
							|  |  |  |     const types = schema.hints.types.split(";") | 
					
						
							|  |  |  |     if (hasBooleanOption >= 0) { | 
					
						
							|  |  |  |         console.log(path.join("."), ": types are", types, ", boolean index is", hasBooleanOption) | 
					
						
							|  |  |  |         types.splice(hasBooleanOption) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const configJson: QuestionableTagRenderingConfigJson = { | 
					
						
							|  |  |  |         id: "TYPE_OF:" + path.join("_"), | 
					
						
							|  |  |  |         question: "Which subcategory is needed?", | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |         questionHint: nmd(schema.description), | 
					
						
							|  |  |  |         mappings: types.map(opt => opt.trim()).filter(opt => opt.length > 0).map((opt, i) => ({ | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |             if: "value=" + i, | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |             addExtraTags: ["direct="], | 
					
						
							|  |  |  |             then: opt + (i === defaultOption ? " (Default)" : "") | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |         })) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     let tags = new UIEventSource<Record<string, string>>({}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     if (hasBooleanOption >= 0) { | 
					
						
							|  |  |  |         configJson.mappings.unshift( | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |               if: "direct=true", | 
					
						
							|  |  |  |               then: "Yes " + (schema.hints.iftrue ?? ""), | 
					
						
							|  |  |  |               addExtraTags: ["value="] | 
					
						
							|  |  |  |           }, | 
					
						
							|  |  |  |           { | 
					
						
							|  |  |  |               if: "direct=false", | 
					
						
							|  |  |  |               then: "No " + (schema.hints.iffalse ?? ""), | 
					
						
							|  |  |  |               addExtraTags: ["value="] | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const config = new TagRenderingConfig(configJson, "config based on " + schema.path.join(".")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const existingValue = state.getCurrentValueFor(path) | 
					
						
							|  |  |  |     console.log("Setting direct: ", hasBooleanOption, path.join("."), existingValue) | 
					
						
							|  |  |  |     if (hasBooleanOption >= 0 && (existingValue === true || existingValue === false)) { | 
					
						
							|  |  |  |         tags.setData({direct: "" + existingValue}) | 
					
						
							|  |  |  |     } else if (existingValue) { | 
					
						
							|  |  |  |         // We found an existing value. Let's figure out what type it matches and select that one | 
					
						
							|  |  |  |         // We run over all possibilities and check what is required | 
					
						
							|  |  |  |         const possibleTypes = [] | 
					
						
							|  |  |  |         outer: for (let i = 0; i < (<[]>schema.type).length; i++) { | 
					
						
							|  |  |  |             const type = schema.type[i]; | 
					
						
							|  |  |  |             if (type.required) { | 
					
						
							|  |  |  |                 for (const requiredAttribute of type.required) { | 
					
						
							|  |  |  |                     if (existingValue[requiredAttribute] === undefined) { | 
					
						
							|  |  |  |                         console.log(path.join("."), " does not have required field", requiredAttribute, " so it cannot be type ", type) | 
					
						
							|  |  |  |                         // The 'existingValue' does _not_ have this required attribute, so it cannot be of this type | 
					
						
							|  |  |  |                         continue outer | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 possibleTypes.push(i) | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 possibleTypes.push(i) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (possibleTypes.length > 0) { | 
					
						
							|  |  |  |             tags.setData({value: "" + possibleTypes[0]}) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (defaultOption !== undefined) { | 
					
						
							|  |  |  |         tags.setData({value: "" + defaultOption}) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hasBooleanOption >= 0) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const directValue = tags.mapD(tags => { | 
					
						
							|  |  |  |             if(tags["value"]){ | 
					
						
							|  |  |  |                 return undefined | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return tags["direct"] === "true"; | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         onDestroy(state.register(path, directValue, true)) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     let chosenOption: number = defaultOption | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |     let subSchemas: ConfigMeta[] = [] | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     onDestroy(tags.addCallbackAndRun(tags => { | 
					
						
							|  |  |  |         chosenOption = tags["value"] ? Number(tags["value"]) : defaultOption | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |         const type = schema.type[chosenOption] | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |         if (!type) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!type.properties) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const cleanPath = <string[]>path.filter(p => typeof p === "string") | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |         for (const crumble of Object.keys(type.properties)) { | 
					
						
							|  |  |  |             subSchemas.push(...(state.getSchema([...cleanPath, crumble]))) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     })) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  | <div class="p-2 border-2 border-dashed border-gray-300 flex flex-col gap-y-2"> | 
					
						
							|  |  |  |     <div> | 
					
						
							|  |  |  |         <TagRenderingEditable selectedElement={undefined} {config} showQuestionIfUnknown={true} {state} {tags}/> | 
					
						
							|  |  |  |     </div> | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     {#if chosenOption !== undefined} | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |         {#each subSchemas as subschema} | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |             <SchemaBasedInput {state} schema={subschema} | 
					
						
							|  |  |  |                               path={[...path, (subschema?.path?.at(-1) ?? "???")]}></SchemaBasedInput> | 
					
						
							| 
									
										
										
										
											2023-06-21 17:13:09 +02:00
										 |  |  |         {/each} | 
					
						
							| 
									
										
										
										
											2023-06-23 16:14:43 +02:00
										 |  |  |     {/if} | 
					
						
							|  |  |  | </div> |