forked from MapComplete/MapComplete
		
	Huge refactorings of JSON-parsing and Tagsfilter, other cleanups, warning cleanups and lots of small subtle bugfixes
This commit is contained in:
		
							parent
							
								
									9a5b35b9f3
								
							
						
					
					
						commit
						a57b7d93fa
					
				
					 113 changed files with 1565 additions and 2594 deletions
				
			
		
							
								
								
									
										259
									
								
								Customizations/JSON/FromJSON.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								Customizations/JSON/FromJSON.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,259 @@ | |||
| import {Layout} from "../Layout"; | ||||
| import {LayoutConfigJson} from "./LayoutConfigJson"; | ||||
| import {AndOrTagConfigJson} from "./TagConfigJson"; | ||||
| import {And, RegexTag, Tag, TagsFilter} from "../../Logic/Tags"; | ||||
| import {TagRenderingConfigJson} from "./TagRenderingConfigJson"; | ||||
| import {TagRenderingOptions} from "../TagRenderingOptions"; | ||||
| import Translation from "../../UI/i18n/Translation"; | ||||
| import {LayerConfigJson} from "./LayerConfigJson"; | ||||
| import {LayerDefinition, Preset} from "../LayerDefinition"; | ||||
| import {TagDependantUIElementConstructor} from "../UIElementConstructor"; | ||||
| import FixedText from "../Questions/FixedText"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import Combine from "../../UI/Base/Combine"; | ||||
| import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWithUpload"; | ||||
| import {ImageCarouselConstructor} from "../../UI/Image/ImageCarousel"; | ||||
| 
 | ||||
| 
 | ||||
| export class FromJSON { | ||||
| 
 | ||||
| 
 | ||||
|     public static FromBase64(layoutFromBase64: string): Layout { | ||||
|         return FromJSON.LayoutFromJSON(JSON.parse(atob(layoutFromBase64))); | ||||
|     } | ||||
| 
 | ||||
|     public static LayoutFromJSON(json: LayoutConfigJson): Layout { | ||||
|         console.log("Parsing ", json.id) | ||||
|         const tr = FromJSON.Translation; | ||||
| 
 | ||||
|         const layers = json.layers.map(FromJSON.Layer); | ||||
|         const roaming: TagDependantUIElementConstructor[] = json.roamingRenderings?.map(FromJSON.TagRendering) ?? []; | ||||
|         for (const layer of layers) { | ||||
|             layer.elementsToShow.push(...roaming); | ||||
|         } | ||||
| 
 | ||||
|         const layout = new Layout( | ||||
|             json.id, | ||||
|             typeof (json.language) === "string" ? [json.language] : json.language, | ||||
|             tr(json.title), | ||||
|             layers, | ||||
|             json.startZoom, | ||||
|             json.startLat, | ||||
|             json.startLon, | ||||
|             new Combine(["<h3>", tr(json.title), "</h3>", tr(json.description)]), | ||||
|         ); | ||||
| 
 | ||||
|         layout.widenFactor = json.widenFactor ?? 0.07; | ||||
|         layout.icon = json.icon; | ||||
|         layout.maintainer = json.maintainer; | ||||
|         layout.version = json.version; | ||||
|         layout.socialImage = json.socialImage; | ||||
|         layout.changesetMessage = json.changesetmessage; | ||||
|         return layout; | ||||
|     } | ||||
| 
 | ||||
|     public static Translation(json: string | any): string | Translation { | ||||
|         if (json === undefined) { | ||||
|             return undefined; | ||||
|         } | ||||
|         if (typeof (json) === "string") { | ||||
|             return json; | ||||
|         } | ||||
|         const tr = {}; | ||||
|         for (let key in json) { | ||||
|             tr[key] = json[key]; // I'm doing this wrong, I know
 | ||||
|         } | ||||
|         return new Translation(tr); | ||||
|     } | ||||
| 
 | ||||
|     public static TagRendering(json: TagRenderingConfigJson | string): TagDependantUIElementConstructor { | ||||
|         return FromJSON.TagRenderingWithDefault(json, "", undefined); | ||||
|     } | ||||
| 
 | ||||
|     public static TagRenderingWithDefault(json: TagRenderingConfigJson | string, propertyName, defaultValue: string): TagDependantUIElementConstructor { | ||||
|             if (json === undefined) { | ||||
|             if(defaultValue !== undefined){ | ||||
|                 console.warn(`Using default value ${defaultValue} for  ${propertyName}`) | ||||
|                 return FromJSON.TagRendering(defaultValue); | ||||
|             } | ||||
|             throw `Tagrendering ${propertyName} is undefined...` | ||||
|         } | ||||
| 
 | ||||
|         if (typeof json === "string") { | ||||
| 
 | ||||
|             switch (json) { | ||||
|                 case "picture": { | ||||
|                     return new ImageCarouselWithUploadConstructor() | ||||
|                 } | ||||
|                 case "pictures": { | ||||
|                     return new ImageCarouselWithUploadConstructor() | ||||
|                 } | ||||
|                 case "image": { | ||||
|                     return new ImageCarouselWithUploadConstructor() | ||||
|                 } | ||||
|                 case "images": { | ||||
|                     return new ImageCarouselWithUploadConstructor() | ||||
|                 } | ||||
|                 case "picturesNoUpload": { | ||||
|                     return new ImageCarouselConstructor() | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             return new TagRenderingOptions({ | ||||
|                 freeform: { | ||||
|                     key: "id", | ||||
|                     renderTemplate: json, | ||||
|                     template: "$$$" | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         let template = FromJSON.Translation(json.render); | ||||
| 
 | ||||
|         let freeform = undefined; | ||||
|         if (json.freeform) { | ||||
| 
 | ||||
|             if(json.render === undefined){ | ||||
|                 console.error("Freeform is defined, but render is not. This is not allowed.", json) | ||||
|                 throw "Freeform is defined, but render is not. This is not allowed." | ||||
|             } | ||||
|              | ||||
|             freeform = { | ||||
|                 template: `$${json.freeform.type ?? "string"}$`, | ||||
|                 renderTemplate: template, | ||||
|                 key: json.freeform.key | ||||
|             }; | ||||
|             if (json.freeform.addExtraTags) { | ||||
|                 freeform["extraTags"] = FromJSON.Tag(json.freeform.addExtraTags); | ||||
|             } | ||||
|         } else if (json.render) { | ||||
|             freeform = { | ||||
|                 template: `$string$`, | ||||
|                 renderTemplate: template, | ||||
|                 key: "id" | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const mappings = json.mappings?.map(mapping => ( | ||||
|             { | ||||
|                 k: FromJSON.Tag(mapping.if), | ||||
|                 txt: FromJSON.Translation(mapping.then), | ||||
|                 hideInAnswer: mapping.hideInAnswer   | ||||
|             }) | ||||
|         ); | ||||
| 
 | ||||
|         return new TagRenderingOptions({ | ||||
|             question: FromJSON.Translation(json.question), | ||||
|             freeform: freeform, | ||||
|             mappings: mappings | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     public static SimpleTag(json: string): Tag { | ||||
|         const tag = json.split("="); | ||||
|         return new Tag(tag[0], tag[1]); | ||||
|     } | ||||
| 
 | ||||
|     public static Tag(json: AndOrTagConfigJson | string): TagsFilter { | ||||
|         if (typeof (json) == "string") { | ||||
|             const tag = json as string; | ||||
|             if (tag.indexOf("!~") >= 0) { | ||||
|                 const split = tag.split("!~"); | ||||
|                 if(split[1] == "*"){ | ||||
|                     split[1] = ".*" | ||||
|                 } | ||||
|                 return new RegexTag( | ||||
|                     new RegExp(split[0]), | ||||
|                     new RegExp(split[1]), | ||||
|                     true | ||||
|                 ); | ||||
|             } | ||||
|             if (tag.indexOf("!=") >= 0) { | ||||
|                 const split = tag.split("!="); | ||||
|                 return new RegexTag( | ||||
|                     new RegExp(split[0]), | ||||
|                     new RegExp(split[1]), | ||||
|                     true | ||||
|                 ); | ||||
|             } | ||||
|             if (tag.indexOf("~") >= 0) { | ||||
|                 const split = tag.split("~"); | ||||
|                 if(split[1] == "*"){ | ||||
|                     split[1] = ".*" | ||||
|                 } | ||||
|                 return new RegexTag( | ||||
|                     new RegExp("^"+split[0]+"$"), | ||||
|                     new RegExp("^"+split[1]+"$") | ||||
|                 ); | ||||
|             } | ||||
|             const split = tag.split("="); | ||||
|             return new Tag(split[0], split[1]) | ||||
|         } | ||||
|         if (json.and !== undefined) { | ||||
|             return new And(json.and.map(FromJSON.Tag)); | ||||
|         } | ||||
|         if (json.or !== undefined) { | ||||
|             return new And(json.or.map(FromJSON.Tag)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static Title(json: string | Map<string, string> | TagRenderingConfigJson): TagDependantUIElementConstructor { | ||||
|         if ((json as TagRenderingConfigJson).render !== undefined) { | ||||
|             return FromJSON.TagRendering((json as TagRenderingConfigJson)); | ||||
|         } else if (typeof (json) === "string") { | ||||
|             return new FixedText(Translations.WT(json)); | ||||
|         } else { | ||||
|             return new FixedText(FromJSON.Translation(json as Map<string, string>)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static Layer(json: LayerConfigJson): LayerDefinition { | ||||
|         console.log("Parsing ",json.name); | ||||
|         const tr = FromJSON.Translation; | ||||
|         const overpassTags = FromJSON.Tag(json.overpassTags); | ||||
|         const icon = FromJSON.TagRenderingWithDefault(json.icon, "layericon", "./assets/bug.svg"); | ||||
|         const color = FromJSON.TagRenderingWithDefault(json.color, "layercolor", "#0000ff"); | ||||
|         const width = FromJSON.TagRenderingWithDefault(json.width, "layerwidth", "10"); | ||||
|         const renderTags = {"id": "node/-1"} | ||||
|         const presets: Preset[] = json?.presets?.map(preset => { | ||||
|             return ({ | ||||
|                 title: tr(preset.title), | ||||
|                 description: tr(preset.description), | ||||
|                 tags: preset.tags.map(FromJSON.SimpleTag) | ||||
|             }); | ||||
|         }) ?? []; | ||||
| 
 | ||||
|         function style(tags) { | ||||
|             return { | ||||
|                 color: color.GetContent(tags).txt, | ||||
|                 weight: width.GetContent(tags).txt, | ||||
|                 icon: { | ||||
|                     iconUrl: icon.GetContent(tags).txt | ||||
|                 }, | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const layer = new LayerDefinition( | ||||
|             json.id, | ||||
|             { | ||||
|                 name: tr(json.name), | ||||
|                 description: tr(json.description), | ||||
|                 icon: icon.GetContent(renderTags).txt, | ||||
|                 overpassFilter: overpassTags, | ||||
| 
 | ||||
|                 title: FromJSON.Title(json.title), | ||||
|                 minzoom: json.minzoom, | ||||
|                 presets: presets, | ||||
|                 elementsToShow: json.tagRenderings?.map(FromJSON.TagRendering) ?? [], | ||||
|                 style: style, | ||||
|                 wayHandling: json.wayHandling | ||||
| 
 | ||||
|             } | ||||
|         ); | ||||
|         return layer; | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue