forked from MapComplete/MapComplete
		
	More work
This commit is contained in:
		
							parent
							
								
									2052976909
								
							
						
					
					
						commit
						e68d9d99a5
					
				
					 5 changed files with 170 additions and 68 deletions
				
			
		|  | @ -60,7 +60,7 @@ export class UIEventSource<T>{ | |||
| 
 | ||||
|         this.addCallback(update); | ||||
|         for (const extraSource of extraSources) { | ||||
|             extraSource.addCallback(update); | ||||
|             extraSource?.addCallback(update); | ||||
|         } | ||||
|        | ||||
|         if(g !== undefined) { | ||||
|  |  | |||
|  | @ -13,21 +13,12 @@ export default class SharePanel extends UIElement { | |||
|         super(undefined); | ||||
|         this._config = config; | ||||
| 
 | ||||
|         const json = new VariableUiElement(config.map(config => { | ||||
|             return JSON.stringify(config, null, 2) | ||||
|                 .replace(/\n/g, "<br/>") | ||||
|                 .replace(/ /g, " "); | ||||
|         })); | ||||
| 
 | ||||
| 
 | ||||
|         this._panel = new Combine([ | ||||
|             "<h2>share</h2>", | ||||
|             "Share the following link with friends:<br/>", | ||||
|             new VariableUiElement(liveUrl.map(url => `<a href='${url}' target="_blank">${url}</a>`)), | ||||
|             "<h3>Json</h3>", | ||||
|             "The json configuration is included for debugging purposes", | ||||
|             "<div class='literal-code json'>", | ||||
|             json, | ||||
|             "</div>" | ||||
|         ]); | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										90
									
								
								UI/Input/AndOrTagInput.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								UI/Input/AndOrTagInput.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | |||
| import {InputElement} from "./InputElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| import {UIElement} from "../UIElement"; | ||||
| import Combine from "../Base/Combine"; | ||||
| import {SubtleButton} from "../Base/SubtleButton"; | ||||
| import TagInput from "./TagInput"; | ||||
| import {FixedUiElement} from "../Base/FixedUiElement"; | ||||
| 
 | ||||
| export class AndOrTagInput extends InputElement<(string | AndOrTagInput)[]> { | ||||
| 
 | ||||
| 
 | ||||
|     private readonly _value: UIEventSource<string[]>; | ||||
|     IsSelected: UIEventSource<boolean>; | ||||
|     private elements: UIElement[] = []; | ||||
|     private inputELements: (InputElement<string> | InputElement<AndOrTagInput>)[] = []; | ||||
|     private addTag: UIElement; | ||||
| 
 | ||||
|     constructor(value: UIEventSource<string[]> = new UIEventSource<string[]>([])) { | ||||
|         super(undefined); | ||||
|         this._value = value; | ||||
| 
 | ||||
|         this.addTag = new SubtleButton("./assets/addSmall.svg", "Add a tag") | ||||
|             .SetClass("small-button") | ||||
|             .onClick(() => { | ||||
|                 this.IsSelected.setData(true); | ||||
|                 value.data.push(""); | ||||
|                 value.ping(); | ||||
|             }); | ||||
|         const self = this; | ||||
|         value.map<number>((tags: string[]) => tags.length).addCallback(() => self.createElements()); | ||||
|         this.createElements(); | ||||
| 
 | ||||
| 
 | ||||
|         this._value.addCallback(tags => self.load(tags)); | ||||
|         this.IsSelected = new UIEventSource<boolean>(false); | ||||
|     } | ||||
| 
 | ||||
|     private load(tags: string[]) { | ||||
|         if (tags === undefined) { | ||||
|             return; | ||||
|         } | ||||
|         for (let i = 0; i < tags.length; i++) { | ||||
|             console.log("Setting tag ", i) | ||||
|             this.inputELements[i].GetValue().setData(tags[i]); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     private UpdateIsSelected(){ | ||||
|         this.IsSelected.setData(this.inputELements.map(input => input.IsSelected.data).reduce((a,b) => a && b)) | ||||
|     } | ||||
| 
 | ||||
|     private createElements() { | ||||
|         this.inputELements = []; | ||||
|         this.elements = []; | ||||
|         for (let i = 0; i < this._value.data.length; i++) { | ||||
|             let tag = this._value.data[i]; | ||||
|             const input = new TagInput(new UIEventSource<string>(tag)); | ||||
|             input.GetValue().addCallback(tag => { | ||||
|                     console.log("Writing ", tag) | ||||
|                     this._value.data[i] = tag; | ||||
|                     this._value.ping(); | ||||
|                 } | ||||
|             ); | ||||
|             this.inputELements.push(input); | ||||
|             input.IsSelected.addCallback(() => this.UpdateIsSelected()); | ||||
|             const deleteBtn = new FixedUiElement("<img src='./assets/delete.svg' style='max-width: 1.5em; margin-left: 5px;'>") | ||||
|                 .onClick(() => { | ||||
|                     this._value.data.splice(i, 1); | ||||
|                     this._value.ping(); | ||||
|                 }); | ||||
|             this.elements.push(new Combine([input, deleteBtn, "<br/>"]).SetClass("tag-input-row")) | ||||
|         } | ||||
|          | ||||
|         this.Update(); | ||||
|     } | ||||
| 
 | ||||
|     InnerRender(): string { | ||||
|         return new Combine([...this.elements, this.addTag]).SetClass("bordered").Render(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     IsValid(t: string[]): boolean { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     GetValue(): UIEventSource<string[]> { | ||||
|         return this._value; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -13,16 +13,20 @@ import {Utils} from "../Utils"; | |||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| import Translation from "./i18n/Translation"; | ||||
| import {SubtleButton} from "./Base/SubtleButton"; | ||||
| import {Layout} from "../Customizations/Layout"; | ||||
| 
 | ||||
| export class ShareScreen extends UIElement { | ||||
|     private  readonly _options: UIElement; | ||||
|     private  readonly _iframeCode: UIElement; | ||||
|     private  readonly _link: UIElement; | ||||
|     private  readonly _linkStatus: UIEventSource<string | UIElement>; | ||||
|     private  readonly _editLayout: UIElement; | ||||
|     private readonly _options: UIElement; | ||||
|     private readonly _iframeCode: UIElement; | ||||
|     public iframe: UIEventSource<string>; | ||||
|     private readonly _link: UIElement; | ||||
|     private readonly _linkStatus: UIEventSource<string | UIElement>; | ||||
|     private readonly _editLayout: UIElement; | ||||
| 
 | ||||
|     constructor() { | ||||
|     constructor(layout: Layout = undefined, layoutDefinition: string = undefined) { | ||||
|         super(undefined) | ||||
|         layout = layout ?? State.state?.layoutToUse?.data; | ||||
|         layoutDefinition = layoutDefinition ?? State.state?.layoutDefinition; | ||||
|         const tr = Translations.t.general.sharescreen; | ||||
| 
 | ||||
|         const optionCheckboxes: UIElement[] = [] | ||||
|  | @ -35,10 +39,12 @@ export class ShareScreen extends UIElement { | |||
|         ) | ||||
|         optionCheckboxes.push(includeLocation); | ||||
| 
 | ||||
|         const currentLocation = State.state.locationControl; | ||||
|         const layout = State.state.layoutToUse.data; | ||||
|         const currentLocation = State.state?.locationControl; | ||||
| 
 | ||||
|         optionParts.push(includeLocation.isEnabled.map((includeL) => { | ||||
|             if (currentLocation === undefined) { | ||||
|                 return null; | ||||
|             } | ||||
|             if (includeL) { | ||||
|                 return `z=${currentLocation.data.zoom}&lat=${currentLocation.data.lat}&lon=${currentLocation.data.lon}` | ||||
|             } else { | ||||
|  | @ -47,54 +53,58 @@ export class ShareScreen extends UIElement { | |||
|         }, [currentLocation])); | ||||
| 
 | ||||
| 
 | ||||
|         const currentLayer: UIEventSource<{ id: string, name: string, layer: any }> = (State.state.bm as Basemap).CurrentLayer; | ||||
|         const currentBackground = tr.fsIncludeCurrentBackgroundMap.Subs({name: layout.id}); | ||||
|         const includeCurrentBackground = new CheckBox( | ||||
|             new Combine([Img.checkmark, currentBackground]), | ||||
|             new Combine([Img.no_checkmark, currentBackground]), | ||||
|             true | ||||
|         ) | ||||
|         optionCheckboxes.push(includeCurrentBackground); | ||||
|         optionParts.push(includeCurrentBackground.isEnabled.map((includeBG) => { | ||||
|             if (includeBG) { | ||||
|                 return "background=" + currentLayer.data.id | ||||
|             } else { | ||||
|                 return null | ||||
|             } | ||||
|         }, [currentLayer])); | ||||
| 
 | ||||
| 
 | ||||
|         const includeLayerChoices = new CheckBox( | ||||
|             new Combine([Img.checkmark, tr.fsIncludeCurrentLayers]), | ||||
|             new Combine([Img.no_checkmark, tr.fsIncludeCurrentLayers]), | ||||
|             true | ||||
|         ) | ||||
|         optionCheckboxes.push(includeLayerChoices); | ||||
| 
 | ||||
|         function fLayerToParam(flayer: FilteredLayer){ | ||||
|             if(flayer.isDisplayed.data){ | ||||
|         function fLayerToParam(flayer: FilteredLayer) { | ||||
|             if (flayer.isDisplayed.data) { | ||||
|                 return null; // Being displayed is the default
 | ||||
|             } | ||||
|             return "layer-"+flayer.layerDef.id+"="+flayer.isDisplayed.data | ||||
|             return "layer-" + flayer.layerDef.id + "=" + flayer.isDisplayed.data | ||||
|         } | ||||
| 
 | ||||
|         optionParts.push(includeLayerChoices.isEnabled.map((includeLayerSelection) => { | ||||
|             if (includeLayerSelection) { | ||||
|                 return Utils.NoNull(State.state.filteredLayers.data.map(fLayerToParam)).join("&") | ||||
|             } else { | ||||
|                 return null | ||||
|             } | ||||
|         }, State.state.filteredLayers.data.map((flayer) => flayer.isDisplayed))); | ||||
| 
 | ||||
|         if (State.state !== undefined) { | ||||
| 
 | ||||
|             const currentLayer: UIEventSource<{ id: string, name: string, layer: any }> = (State.state.bm as Basemap).CurrentLayer; | ||||
|             const currentBackground = tr.fsIncludeCurrentBackgroundMap.Subs({name: layout.id}); | ||||
|             const includeCurrentBackground = new CheckBox( | ||||
|                 new Combine([Img.checkmark, currentBackground]), | ||||
|                 new Combine([Img.no_checkmark, currentBackground]), | ||||
|                 true | ||||
|             ) | ||||
|             optionCheckboxes.push(includeCurrentBackground); | ||||
|             optionParts.push(includeCurrentBackground.isEnabled.map((includeBG) => { | ||||
|                 if (includeBG) { | ||||
|                     return "background=" + currentLayer.data.id | ||||
|                 } else { | ||||
|                     return null | ||||
|                 } | ||||
|             }, [currentLayer])); | ||||
| 
 | ||||
| 
 | ||||
|             const includeLayerChoices = new CheckBox( | ||||
|                 new Combine([Img.checkmark, tr.fsIncludeCurrentLayers]), | ||||
|                 new Combine([Img.no_checkmark, tr.fsIncludeCurrentLayers]), | ||||
|                 true | ||||
|             ) | ||||
|             optionCheckboxes.push(includeLayerChoices); | ||||
| 
 | ||||
|             optionParts.push(includeLayerChoices.isEnabled.map((includeLayerSelection) => { | ||||
|                 if (includeLayerSelection) { | ||||
|                     return Utils.NoNull(State.state.filteredLayers.data.map(fLayerToParam)).join("&") | ||||
|                 } else { | ||||
|                     return null | ||||
|                 } | ||||
|             }, State.state.filteredLayers.data.map((flayer) => flayer.isDisplayed))); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         const switches = [ | ||||
|             {urlName: "fs-userbadge", human:  tr.fsUserbadge}, | ||||
|             {urlName: "fs-search", human:  tr.fsSearch}, | ||||
|             {urlName: "fs-welcome-message", human:  tr.fsWelcomeMessage},  | ||||
|             {urlName: "fs-layers", human:  tr.fsLayers}, | ||||
|             {urlName: "layer-control-toggle", human:  tr.fsLayerControlToggle, reverse: true},  | ||||
|             {urlName: "fs-addXXXnew", human:  tr.fsAddNew}, | ||||
|             {urlName: "fs-geolocation", human:  tr.fsGeolocation},  | ||||
|             {urlName: "fs-userbadge", human: tr.fsUserbadge}, | ||||
|             {urlName: "fs-search", human: tr.fsSearch}, | ||||
|             {urlName: "fs-welcome-message", human: tr.fsWelcomeMessage}, | ||||
|             {urlName: "fs-layers", human: tr.fsLayers}, | ||||
|             {urlName: "layer-control-toggle", human: tr.fsLayerControlToggle, reverse: true}, | ||||
|             {urlName: "fs-add-new", human: tr.fsAddNew}, | ||||
|             {urlName: "fs-geolocation", human: tr.fsGeolocation}, | ||||
|         ] | ||||
| 
 | ||||
| 
 | ||||
|  | @ -124,7 +134,7 @@ export class ShareScreen extends UIElement { | |||
| 
 | ||||
| 
 | ||||
|         this._options = new VerticalCombine(optionCheckboxes) | ||||
|         const url = currentLocation.map(() => { | ||||
|         const url = (currentLocation ?? new UIEventSource(undefined)).map(() => { | ||||
| 
 | ||||
| 
 | ||||
|             let literalText = "https://pietervdvn.github.io/MapComplete/" + layout.id.toLowerCase() + ".html" | ||||
|  | @ -132,8 +142,8 @@ export class ShareScreen extends UIElement { | |||
|             const parts = Utils.NoEmpty(Utils.NoNull(optionParts.map((eventSource) => eventSource.data))); | ||||
| 
 | ||||
|             let hash = ""; | ||||
|             if (State.state.layoutDefinition !== undefined) { | ||||
|                 hash = ("#" + State.state.layoutDefinition) | ||||
|             if (layoutDefinition !== undefined) { | ||||
|                 hash = ("#" + layoutDefinition) | ||||
|                 literalText = "https://pietervdvn.github.io/MapComplete/index.html" | ||||
|                 parts.push("userlayout=true"); | ||||
|             } | ||||
|  | @ -145,10 +155,13 @@ export class ShareScreen extends UIElement { | |||
| 
 | ||||
|             return literalText + "?" + parts.join("&") + hash; | ||||
|         }, optionParts); | ||||
| 
 | ||||
| 
 | ||||
|         this.iframe = url.map(url => `<iframe src="${url}" width="100%" height="100%" title="${layout.title.InnerRender()} with MapComplete"></iframe>`); | ||||
|          | ||||
|         this._iframeCode = new VariableUiElement( | ||||
|             url.map((url) => { | ||||
|                 return `<span class='literal-code iframe-code-block'>
 | ||||
|                         <iframe src="${url}" width="100%" height="100%" title="${layout.title.InnerRender()} with MapComplete"></iframe>  | ||||
|                     </span>` | ||||
|             }) | ||||
|         ); | ||||
|  | @ -157,7 +170,7 @@ export class ShareScreen extends UIElement { | |||
|       | ||||
| 
 | ||||
|         this._editLayout = new FixedUiElement(""); | ||||
|         if ((State.state.layoutDefinition !== undefined)) { | ||||
|         if ((layoutDefinition !== undefined && State.state?.osmConnection !== undefined)) { | ||||
|             this._editLayout = | ||||
|                 new VariableUiElement( | ||||
|                     State.state.osmConnection.userDetails.map( | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ import GeneralSettings from "./UI/CustomGenerator/GeneralSettings"; | |||
| import {SubtleButton} from "./UI/Base/SubtleButton"; | ||||
| import {TabbedComponent} from "./UI/Base/TabbedComponent"; | ||||
| import AllLayersPanel from "./UI/CustomGenerator/AllLayersPanel"; | ||||
| import {ShareScreen} from "./UI/ShareScreen"; | ||||
| import {FromJSON} from "./Customizations/JSON/FromJSON"; | ||||
| import SharePanel from "./UI/CustomGenerator/SharePanel"; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -46,6 +48,7 @@ const es = new UIEventSource(test); | |||
| const encoded = es.map(config => btoa(JSON.stringify(config))); | ||||
| const testUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}&test=true#${encoded}`) | ||||
| const liveUrl = encoded.map(encoded => `./index.html?userlayout=${es.data.id}#${encoded}`) | ||||
| const iframe = liveUrl.map(url => `<iframe src='${url}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`); | ||||
| 
 | ||||
| 
 | ||||
| const currentSetting = new UIEventSource<SingleSetting<any>>(undefined) | ||||
|  | @ -63,7 +66,12 @@ new TabbedComponent([ | |||
|     }, | ||||
|     { | ||||
|         header: "<img src='./assets/floppy.svg'>", | ||||
|         content: "Save" | ||||
|         content: new VariableUiElement(es.map(config => { | ||||
|             return JSON.stringify(config, null, 2) | ||||
|                 .replace(/\n/g, "<br/>") | ||||
|                 .replace(/ /g, " "); | ||||
|         })) | ||||
| 
 | ||||
|     }, | ||||
|     { | ||||
|         header: "<img src='./assets/share.svg'>", | ||||
|  | @ -103,7 +111,7 @@ new Combine([helpText, | |||
| 
 | ||||
| // The preview
 | ||||
| new Combine([ | ||||
|     new VariableUiElement(testUrl.map(testUrl => `<iframe src='${testUrl}' width='100%' height='99%' style="box-sizing: border-box" title='Theme Preview'></iframe>`)) | ||||
|     new VariableUiElement(iframe) | ||||
| ]).AttachTo("bottomright"); | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue