| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | import {UIElement} from "../UI/UIElement"; | 
					
						
							|  |  |  | import {UIEventSource} from "../UI/UIEventSource"; | 
					
						
							|  |  |  | import {And, Tag, TagsFilter, TagUtils} from "../Logic/TagsFilter"; | 
					
						
							|  |  |  | import {FixedUiElement} from "../UI/Base/FixedUiElement"; | 
					
						
							|  |  |  | import {SaveButton} from "../UI/SaveButton"; | 
					
						
							|  |  |  | import {VariableUiElement} from "../UI/Base/VariableUIElement"; | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  | import {TagDependantUIElement} from "./UIElementConstructor"; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | import {TextField} from "../UI/Input/TextField"; | 
					
						
							|  |  |  | import {InputElement} from "../UI/Input/InputElement"; | 
					
						
							|  |  |  | import {InputElementWrapper} from "../UI/Input/InputElementWrapper"; | 
					
						
							|  |  |  | import {FixedInputElement} from "../UI/Input/FixedInputElement"; | 
					
						
							|  |  |  | import {RadioButton} from "../UI/Input/RadioButton"; | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  | import Translations from "../UI/i18n/Translations"; | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  | import Locale from "../UI/i18n/Locale"; | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  | import {State} from "../State"; | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  | import {TagRenderingOptions} from "./TagRenderingOptions"; | 
					
						
							| 
									
										
										
										
											2020-07-26 19:13:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  | export class TagRendering extends UIElement implements TagDependantUIElement { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     private _priority: number; | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |     private _question: UIElement; | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |     private _mapping: { k: TagsFilter, txt: string | UIElement, priority?: number }[]; | 
					
						
							| 
									
										
										
										
											2020-07-08 16:24:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     private _tagsPreprocessor?: ((tags: any) => any); | 
					
						
							|  |  |  |     private _freeform: { | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |         key: string,  | 
					
						
							|  |  |  |         template: string | UIElement, | 
					
						
							|  |  |  |         renderTemplate: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |         placeholder?: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         extraTags?: TagsFilter | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private readonly _questionElement: InputElement<TagsFilter>; | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     private readonly _saveButton: UIElement; | 
					
						
							|  |  |  |     private readonly _skipButton: UIElement; | 
					
						
							|  |  |  |     private readonly _editButton: UIElement; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private readonly _questionSkipped: UIEventSource<boolean> = new UIEventSource<boolean>(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private readonly _editMode: UIEventSource<boolean> = new UIEventSource<boolean>(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |     private static injected = TagRendering.injectFunction();  | 
					
						
							|  |  |  |     static injectFunction() { | 
					
						
							|  |  |  |         // This is a workaround as not to import tagrendering into TagREnderingOptions
 | 
					
						
							|  |  |  |         TagRenderingOptions.tagRendering = (tags, options) => new TagRendering(tags, options); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |     constructor(tags: UIEventSource<any>, options: { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         priority?: number | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         question?: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         freeform?: { | 
					
						
							| 
									
										
										
										
											2020-07-31 17:38:03 +02:00
										 |  |  |             key: string, | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |             template: string | UIElement, | 
					
						
							|  |  |  |             renderTemplate: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |             placeholder?: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             extraTags?: TagsFilter, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         tagsPreprocessor?: ((tags: any) => any), | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[] | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     }) { | 
					
						
							|  |  |  |         super(tags); | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |         this.ListenTo(Locale.language); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         this.ListenTo(this._questionSkipped); | 
					
						
							|  |  |  |         this.ListenTo(this._editMode); | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         this.ListenTo(State.state.osmConnection.userDetails); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 17:21:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |         | 
					
						
							| 
									
										
										
										
											2020-07-12 23:19:05 +02:00
										 |  |  |         this._priority = options.priority ?? 0; | 
					
						
							| 
									
										
										
										
											2020-07-17 17:21:07 +02:00
										 |  |  |         this._tagsPreprocessor = function (properties) { | 
					
						
							|  |  |  |             if (options.tagsPreprocessor === undefined) { | 
					
						
							|  |  |  |                 return properties; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const newTags = {}; | 
					
						
							|  |  |  |             for (const k in properties) { | 
					
						
							|  |  |  |                 newTags[k] = properties[k]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             options.tagsPreprocessor(newTags); | 
					
						
							|  |  |  |             return newTags; | 
					
						
							|  |  |  |         }; | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (options.question !== undefined) { | 
					
						
							|  |  |  |             this._question = this.ApplyTemplate(options.question); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-17 17:21:07 +02:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         this._mapping = []; | 
					
						
							|  |  |  |         this._freeform = options.freeform; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 16:07:16 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         for (const choice of options.mappings ?? []) { | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |             let choiceSubbed = { | 
					
						
							|  |  |  |                 k: choice.k, | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |                 txt: choice.txt, | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |                 priority: choice.priority | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             if (choice.substitute) { | 
					
						
							|  |  |  |                 choiceSubbed = { | 
					
						
							| 
									
										
										
										
											2020-07-08 11:23:36 +02:00
										 |  |  |                     k: choice.k.substituteValues( | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                         options.tagsPreprocessor(this._source.data)), | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |                     txt: choice.txt, | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                     priority: choice.priority | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-08 11:23:36 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |             this._mapping.push({ | 
					
						
							|  |  |  |                 k: choiceSubbed.k, | 
					
						
							|  |  |  |                 txt: choiceSubbed.txt | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Prepare the actual input element -> pick an appropriate implementation
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         this._questionElement = this.InputElementFor(options); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         const save = () => { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             const selection = self._questionElement.GetValue().data; | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             if (selection) { | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |                 State.state.changes.addTag(tags.data.id, selection); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             self._editMode.setData(false); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const cancel = () => { | 
					
						
							|  |  |  |             self._questionSkipped.setData(true); | 
					
						
							|  |  |  |             self._editMode.setData(false); | 
					
						
							| 
									
										
										
										
											2020-07-08 16:07:16 +02:00
										 |  |  |             self._source.ping(); // Send a ping upstream to render the next question
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Setup the save button and it's action
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         this._saveButton = new SaveButton(this._questionElement.GetValue()) | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             .onClick(save); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         this._editButton = new FixedUiElement(""); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         if (this._question !== undefined) { | 
					
						
							|  |  |  |             this._editButton = new FixedUiElement("<img class='editbutton' src='./assets/pencil.svg' alt='edit'>") | 
					
						
							|  |  |  |                 .onClick(() => { | 
					
						
							|  |  |  |                     self._editMode.setData(true); | 
					
						
							| 
									
										
										
										
											2020-07-20 21:39:07 +02:00
										 |  |  |                     self._questionElement.GetValue().setData(self.CurrentValue()); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 }); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const cancelContents = this._editMode.map((isEditing) => { | 
					
						
							|  |  |  |             if (isEditing) { | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |                 return "<span class='skip-button'>"+Translations.t.general.cancel.R()+"</span>"; | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |                 return "<span class='skip-button'>"+Translations.t.general.skip.R()+"</span>"; | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-22 00:18:07 +02:00
										 |  |  |         }, [Locale.language]); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         // And at last, set up the skip button
 | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |         this._skipButton = new VariableUiElement(cancelContents).onClick(cancel)    ; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     private InputElementFor(options: { | 
					
						
							|  |  |  |         freeform?: { | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |             key: string,  | 
					
						
							|  |  |  |             template: string | UIElement, | 
					
						
							|  |  |  |             renderTemplate: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-21 02:55:28 +02:00
										 |  |  |             placeholder?: string | UIElement, | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             extraTags?: TagsFilter, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         mappings?: { k: TagsFilter, txt: string | UIElement, priority?: number, substitute?: boolean }[] | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     }): | 
					
						
							|  |  |  |         InputElement<TagsFilter> { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const elements = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (options.mappings !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |              | 
					
						
							|  |  |  |             const previousTexts= []; | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |             for (const mapping of options.mappings) { | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |                 if(mapping.k === null){ | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 if(previousTexts.indexOf(mapping.txt) >= 0){ | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 previousTexts.push(mapping.txt); | 
					
						
							|  |  |  |                  | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 elements.push(this.InputElementForMapping(mapping)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (options.freeform !== undefined) { | 
					
						
							|  |  |  |             elements.push(this.InputForFreeForm(options.freeform)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (elements.length == 0) { | 
					
						
							| 
									
										
										
										
											2020-07-26 23:28:31 +02:00
										 |  |  |             //console.warn("WARNING: no tagrendering with following options:", options);
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |             return new FixedInputElement("This should not happen: no tag renderings defined", undefined); | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |         if (elements.length == 1) { | 
					
						
							|  |  |  |             return elements[0]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new RadioButton(elements, false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |     private InputElementForMapping(mapping: { k: TagsFilter, txt: string | UIElement }) { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |         return new FixedInputElement(mapping.txt, mapping.k); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private InputForFreeForm(freeform): InputElement<TagsFilter> { | 
					
						
							|  |  |  |         if (freeform === undefined) { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-29 20:19:29 +02:00
										 |  |  |         const prepost = Translations.W(freeform.template).InnerRender() | 
					
						
							|  |  |  |             .replace("$$$","$string$") | 
					
						
							|  |  |  |             .split("$"); | 
					
						
							| 
									
										
										
										
											2020-07-23 17:32:18 +02:00
										 |  |  |         const type = prepost[1]; | 
					
						
							| 
									
										
										
										
											2020-07-29 20:19:29 +02:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2020-07-26 02:01:34 +02:00
										 |  |  |         let isValid = TagRenderingOptions.inputValidation[type]; | 
					
						
							| 
									
										
										
										
											2020-07-26 19:13:52 +02:00
										 |  |  |         if (isValid === undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-26 02:01:34 +02:00
										 |  |  |             isValid = (str) => true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         let formatter = TagRenderingOptions.formatting[type] ?? ((str) => str); | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const pickString = | 
					
						
							| 
									
										
										
										
											2020-07-23 17:32:18 +02:00
										 |  |  |             (string: any) => { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 if (string === "" || string === undefined) { | 
					
						
							|  |  |  |                     return undefined; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-26 19:13:52 +02:00
										 |  |  |                 if (!isValid(string, this._source.data._country)) { | 
					
						
							| 
									
										
										
										
											2020-07-23 17:32:18 +02:00
										 |  |  |                     return undefined; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-26 19:13:52 +02:00
										 |  |  |                 const tag = new Tag(freeform.key, formatter(string, this._source.data._country)); | 
					
						
							| 
									
										
										
										
											2020-07-23 17:32:18 +02:00
										 |  |  |                  | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 if (freeform.extraTags === undefined) { | 
					
						
							|  |  |  |                     return tag; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return new And([ | 
					
						
							| 
									
										
										
										
											2020-07-20 21:03:55 +02:00
										 |  |  |                         tag, | 
					
						
							|  |  |  |                         freeform.extraTags | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                     ] | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const toString = | 
					
						
							|  |  |  |             (tag) => { | 
					
						
							|  |  |  |                 if (tag instanceof And) { | 
					
						
							|  |  |  |                     return toString(tag.and[0]) | 
					
						
							|  |  |  |                 } else if (tag instanceof Tag) { | 
					
						
							|  |  |  |                     return tag.value | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return undefined; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let inputElement: InputElement<TagsFilter>; | 
					
						
							|  |  |  |         const textField = new TextField({ | 
					
						
							|  |  |  |             placeholder: this._freeform.placeholder, | 
					
						
							|  |  |  |             fromString: pickString, | 
					
						
							|  |  |  |             toString: toString | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-23 17:32:18 +02:00
										 |  |  |         return new InputElementWrapper(prepost[0], textField, prepost[2]); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     IsKnown(): boolean { | 
					
						
							|  |  |  |         const tags = TagUtils.proprtiesToKV(this._source.data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |         for (const oneOnOneElement of this._mapping) { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             if (oneOnOneElement.k === null || oneOnOneElement.k.matches(tags)) { | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         return this._freeform !== undefined && this._source.data[this._freeform.key] !== undefined; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-25 01:07:02 +02:00
										 |  |  |     IsSkipped(): boolean { | 
					
						
							|  |  |  |         return this._questionSkipped.data; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |     private CurrentValue(): TagsFilter { | 
					
						
							|  |  |  |         const tags = TagUtils.proprtiesToKV(this._source.data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |         for (const oneOnOneElement of this._mapping) { | 
					
						
							| 
									
										
										
										
											2020-07-20 21:03:55 +02:00
										 |  |  |             if (oneOnOneElement.k !== null && oneOnOneElement.k.matches(tags)) { | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  |                 return oneOnOneElement.k; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (this._freeform === undefined) { | 
					
						
							|  |  |  |             return undefined; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new Tag(this._freeform.key, this._source.data[this._freeform.key]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     IsQuestioning(): boolean { | 
					
						
							|  |  |  |         if (this.IsKnown()) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (this._question === undefined) { | 
					
						
							|  |  |  |             // We don't ask this question in the first place
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (this._questionSkipped.data) { | 
					
						
							|  |  |  |             // We don't ask for this question anymore, skipped by user
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |     private RenderAnwser(): UIElement { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         const tags = TagUtils.proprtiesToKV(this._source.data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         let freeform: UIElement = new FixedUiElement(""); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         let freeformScore = -10; | 
					
						
							|  |  |  |         if (this._freeform !== undefined && this._source.data[this._freeform.key] !== undefined) { | 
					
						
							|  |  |  |             freeform = this.ApplyTemplate(this._freeform.renderTemplate); | 
					
						
							|  |  |  |             freeformScore = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         let highestScore = -100; | 
					
						
							|  |  |  |         let highestTemplate = undefined; | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |         for (const oneOnOneElement of this._mapping) { | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |             if (oneOnOneElement.k == null || | 
					
						
							|  |  |  |                 oneOnOneElement.k.matches(tags)) { | 
					
						
							|  |  |  |                 // We have found a matching key -> we use the template, but only if it scores better
 | 
					
						
							|  |  |  |                 let score = oneOnOneElement.priority ?? | 
					
						
							|  |  |  |                     (oneOnOneElement.k === null ? -1 : 0); | 
					
						
							|  |  |  |                 if (score > highestScore) { | 
					
						
							|  |  |  |                     highestScore = score; | 
					
						
							|  |  |  |                     highestTemplate = oneOnOneElement.txt | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         if (freeformScore > highestScore) { | 
					
						
							|  |  |  |             return freeform; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (highestTemplate !== undefined) { | 
					
						
							|  |  |  |             // we render the found template
 | 
					
						
							|  |  |  |             return this.ApplyTemplate(highestTemplate); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 18:24:00 +02:00
										 |  |  |     InnerRender(): string { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |         if (this.IsQuestioning() || this._editMode.data) { | 
					
						
							|  |  |  |             // Not yet known or questioning, we have to ask a question
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |             const question = | 
					
						
							|  |  |  |                 this.ApplyTemplate(this._question).Render(); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return "<div class='question'>" + | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |                 "<span class='question-text'>" + question + "</span>" + | 
					
						
							| 
									
										
										
										
											2020-07-21 00:38:03 +02:00
										 |  |  |                 (this._question.IsEmpty() ? "" : "<br/>") + | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |                 "<div>" + this._questionElement.Render() + "</div>" + | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 this._skipButton.Render() + | 
					
						
							|  |  |  |                 this._saveButton.Render() + | 
					
						
							|  |  |  |                 "</div>" | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (this.IsKnown()) { | 
					
						
							| 
									
										
										
										
											2020-07-21 00:38:03 +02:00
										 |  |  |             const answer = this.RenderAnwser() | 
					
						
							|  |  |  |             if (answer.IsEmpty()) { | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 return ""; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-21 00:38:03 +02:00
										 |  |  |             const html = answer.Render(); | 
					
						
							| 
									
										
										
										
											2020-07-13 16:18:04 +02:00
										 |  |  |             let editButton = ""; | 
					
						
							| 
									
										
										
										
											2020-07-31 01:45:54 +02:00
										 |  |  |             if (State.state.osmConnection.userDetails.data.loggedIn && this._question !== undefined) { | 
					
						
							| 
									
										
										
										
											2020-07-13 16:18:04 +02:00
										 |  |  |                 editButton = this._editButton.Render(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |             return "<span class='answer'>" + | 
					
						
							| 
									
										
										
										
											2020-07-13 16:18:04 +02:00
										 |  |  |                 "<span class='answer-text'>" + html + "</span>" + | 
					
						
							|  |  |  |                 editButton + | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |                 "</span>"; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-20 15:54:50 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Priority(): number { | 
					
						
							|  |  |  |         return this._priority; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |     private ApplyTemplate(template: string | UIElement): UIElement { | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |         if (template === undefined || template === null) { | 
					
						
							| 
									
										
										
										
											2020-07-21 23:31:41 +02:00
										 |  |  |             throw "Trying to apply a template, but the template is null/undefined" | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |          | 
					
						
							|  |  |  |         const contents = Translations.W(template).map(contents =>  | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 let templateStr = ""; | 
					
						
							|  |  |  |                 if (template instanceof UIElement) { | 
					
						
							|  |  |  |                     templateStr = template.Render(); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     templateStr = template; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 const tags = this._tagsPreprocessor(this._source.data); | 
					
						
							|  |  |  |                 return TagUtils.ApplyTemplate(templateStr, tags); | 
					
						
							|  |  |  |             }, [this._source] | 
					
						
							|  |  |  |         ); | 
					
						
							|  |  |  |         return new VariableUiElement(contents); | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-21 00:07:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-27 01:19:38 +02:00
										 |  |  |   | 
					
						
							| 
									
										
										
										
											2020-07-05 18:59:47 +02:00
										 |  |  | } |