forked from MapComplete/MapComplete
		
	Fix back button; add title
This commit is contained in:
		
							parent
							
								
									6e77504854
								
							
						
					
					
						commit
						2f57010202
					
				
					 14 changed files with 115 additions and 43 deletions
				
			
		|  | @ -39,7 +39,7 @@ export default class AllTranslationAssets { | |||
|     number: new Translation( {"en":"number","ca":"nombre","es":"número","nl":"getal","fr":"nombre","gl":"número","de":"Zahl"} ), | ||||
|     osmLinkTooltip: new Translation( {"en":"See this object on OpenStreetMap for history and more editing options","ca":"Mira aquest objecte a OpenStreetMap per veure historial i altres opcions d'edició","es":"Mira este objeto en OpenStreetMap para ver historial y otras opciones de edición","nl":"Bekijk dit object op OpenStreetMap waar geschiedenis en meer aanpasopties zijn","fr":"Voir l'historique de cet objet sur OpenStreetMap et plus d'options d'édition","gl":"Ollar este obxecto no OpenStreetMap para ollar o historial e outras opcións de edición","de":"Dieses Objekt auf OpenStreetMap anschauen für die Geschichte und weitere Bearbeitungsmöglichkeiten"} ), | ||||
|     add: {      addNew: new Translation( {"en":"Add a new {category} here","ca":"Afegir {category} aquí","es":"Añadir {category} aquí","nl":"Voeg hier een {category} toe","fr":"Ajouter un/une {category} ici","gl":"Engadir {category} aquí","de":"Hier eine neue {category} hinzufügen"} ), | ||||
|       title: new Translation( {"en":"Add a point?","ca":"Vols afegir un punt?","es":"Quieres añadir un punto?","nl":"Punt toevoegen?","fr":"Pas de données","gl":"Queres engadir un punto?","de":"Punkt hinzufügen?"} ), | ||||
|       title: new Translation( {"en":"Add a new point?","ca":"Vols afegir un punt?","es":"Quieres añadir un punto?","nl":"Nieuw punt toevoegen?","fr":"Pas de données","gl":"Queres engadir un punto?","de":"Punkt hinzufügen?"} ), | ||||
|       intro: new Translation( {"en":"You clicked somewhere where no data is known yet.<br/>","ca":"Has marcat un lloc on no coneixem les dades.<br/>","es":"Has marcado un lugar del que no conocemos los datos.<br/>","nl":"Je klikte ergens waar er nog geen data is. Kies hieronder welk punt je wilt toevoegen<br/>","fr":"Vous avez cliqué sur un endroit où il n'y a pas encore de données. <br/>","gl":"Marcaches un lugar onde non coñecemos os datos.<br/>","de":"Sie haben irgendwo geklickt, wo noch keine Daten bekannt sind.<br/>"} ), | ||||
|       pleaseLogin: new Translation( {"en":"<a class='activate-osm-authentication'>Please log in to add a new point</a>","ca":"<a class='activate-osm-authentication'>Entra per afegir un nou punt</a>","es":"<a class='activate-osm-authentication'>Entra para añadir un nuevo punto</a>","nl":"<a class='activate-osm-authentication'>Gelieve je aan te melden om een punt to te voegen</a>","fr":"<a class='activate-osm-authentication'>Vous devez vous connecter pour ajouter un point</a>","gl":"<a class='activate-osm-authentication'>Inicia a sesión para engadir un novo punto</a>","de":"<a class='activate-osm-authentication'>Bitte loggen Sie sich ein, um einen neuen Punkt hinzuzufügen</a>"} ), | ||||
|       zoomInFurther: new Translation( {"en":"Zoom in further to add a point.","ca":"Apropa per afegir un punt.","es":"Acerca para añadir un punto.","nl":"Gelieve verder in te zoomen om een punt toe te voegen.","fr":"Rapprochez vous pour ajouter un point.","gl":"Achégate para engadir un punto.","de":"Weiter einzoomen, um einen Punkt hinzuzufügen."} ), | ||||
|  |  | |||
|  | @ -177,7 +177,6 @@ export default class LayerConfig { | |||
|         this.tagRenderings.push(...addAll.tagRenderings); | ||||
|         this.iconOverlays.push(...addAll.iconOverlays); | ||||
|         for (const icon of addAll.titleIcons) { | ||||
|             console.log("Adding ",icon, "to", this.id) | ||||
|             this.titleIcons.splice(0,0, icon); | ||||
|         } | ||||
|         return this; | ||||
|  |  | |||
|  | @ -96,7 +96,6 @@ export default class LayoutConfig { | |||
|                 if (shared === undefined) { | ||||
|                     throw "Unkown fixed layer " + name; | ||||
|                 } | ||||
|                 console.log("PREMERGE", layer, shared) | ||||
|                 // @ts-ignore
 | ||||
|                 layer = Utils.Merge(layer.override, shared); | ||||
|             } | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ import FeatureDuplicatorPerLayer from "./Logic/FeatureSource/FeatureDuplicatorPe | |||
| import LayerConfig from "./Customizations/JSON/LayerConfig"; | ||||
| import ShowDataLayer from "./UI/ShowDataLayer"; | ||||
| import Hash from "./Logic/Web/Hash"; | ||||
| import HistoryHandling from "./Logic/Actors/HistoryHandling"; | ||||
| 
 | ||||
| export class InitUiElements { | ||||
| 
 | ||||
|  | @ -133,7 +134,6 @@ export class InitUiElements { | |||
| 
 | ||||
|                 if (feature === undefined) { | ||||
|                     State.state.fullScreenMessage.setData(undefined); | ||||
|                     Hash.hash.setData(undefined); | ||||
|                 } | ||||
|                 if (feature?.properties === undefined) { | ||||
|                     return; | ||||
|  | @ -159,12 +159,18 @@ export class InitUiElements { | |||
|                         layer | ||||
|                     ); | ||||
| 
 | ||||
|                     State.state.fullScreenMessage.setData(featureBox); | ||||
|                     State.state.fullScreenMessage.setData({ | ||||
|                         content: featureBox, | ||||
|                         hashText: feature.properties.id.replace("/", "_"), | ||||
|                         titleText: featureBox.title | ||||
|                     }); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
| 
 | ||||
|         new HistoryHandling(Hash.hash, State.state.fullScreenMessage); | ||||
| 
 | ||||
|         InitUiElements.OnlyIf(State.state.featureSwitchUserbadge, () => { | ||||
|             new UserBadge().AttachTo('userbadge'); | ||||
|         }); | ||||
|  | @ -279,20 +285,20 @@ export class InitUiElements { | |||
|         }) | ||||
| 
 | ||||
|         State.state.selectedElement.addCallback(selected => { | ||||
|             if(selected !== undefined){ | ||||
|             if (selected !== undefined) { | ||||
|                 checkbox.isEnabled.setData(false); | ||||
|             } | ||||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|         const fullOptions2 = new FullWelcomePaneWithTabs(); | ||||
|         State.state.fullScreenMessage.setData(fullOptions2) | ||||
|         State.state.fullScreenMessage.setData({content: fullOptions2, hashText: "welcome"}) | ||||
| 
 | ||||
|         Svg.help_svg() | ||||
|             .SetClass("open-welcome-button") | ||||
|             .SetClass("shadow") | ||||
|             .onClick(() => { | ||||
|                 State.state.fullScreenMessage.setData(fullOptions2) | ||||
|                 State.state.fullScreenMessage.setData({content: fullOptions2, hashText: "welcome"}) | ||||
|             }).AttachTo("help-button-mobile"); | ||||
| 
 | ||||
| 
 | ||||
|  | @ -326,7 +332,7 @@ export class InitUiElements { | |||
|             const fullScreen = new LayerControlPanel(); | ||||
|             checkbox.isEnabled.addCallback(isEnabled => { | ||||
|                 if (isEnabled) { | ||||
|                     State.state.fullScreenMessage.setData(fullScreen); | ||||
|                     State.state.fullScreenMessage.setData({content: fullScreen, hashText: "layer-select"}); | ||||
|                 } | ||||
|             }) | ||||
|             State.state.fullScreenMessage.addCallback(latest => { | ||||
|  |  | |||
							
								
								
									
										19
									
								
								Logic/Actors/HistoryHandling.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Logic/Actors/HistoryHandling.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| 
 | ||||
| export default class HistoryHandling { | ||||
| 
 | ||||
|     constructor(hash: UIEventSource<string>, fullscreenMessage: UIEventSource<{ content: UIElement, hashText: string }>) { | ||||
|         hash.addCallback(h => { | ||||
|             if (h === undefined || h === "") { | ||||
|                 fullscreenMessage.setData(undefined); | ||||
|             } | ||||
|         }) | ||||
|          | ||||
|         fullscreenMessage.addCallback(fs => { | ||||
|             hash.setData(fs?.hashText); | ||||
|         }) | ||||
|          | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -17,7 +17,7 @@ export default class StrayClickHandler { | |||
|         selectedElement: UIEventSource<string>, | ||||
|         filteredLayers: UIEventSource<{ readonly isDisplayed: UIEventSource<boolean> }[]>, | ||||
|         leafletMap: UIEventSource<L.Map>, | ||||
|         fullscreenMessage: UIEventSource<UIElement>, | ||||
|         fullscreenMessage: UIEventSource<{content: UIElement, hashText: string}>, | ||||
|         uiToShow: (() => UIElement)) { | ||||
|         this._uiToShow = uiToShow; | ||||
|         const self = this; | ||||
|  | @ -51,7 +51,7 @@ export default class StrayClickHandler { | |||
|             self._lastMarker.bindPopup(popup); | ||||
| 
 | ||||
|             self._lastMarker.on("click", () => { | ||||
|                 fullscreenMessage.setData(self._uiToShow()); | ||||
|                 fullscreenMessage.setData({content: self._uiToShow(), hashText: "new"}); | ||||
|                 uiElement.Update(); | ||||
|             }); | ||||
|         }); | ||||
|  |  | |||
							
								
								
									
										33
									
								
								Logic/Actors/TitleHandler.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Logic/Actors/TitleHandler.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import LayoutConfig from "../../Customizations/JSON/LayoutConfig"; | ||||
| import Translations from "../../UI/i18n/Translations"; | ||||
| import Locale from "../../UI/i18n/Locale"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| 
 | ||||
| export default class TitleHandler{ | ||||
|     constructor(layoutToUse: UIEventSource<LayoutConfig>, fullScreenMessage: UIEventSource<{ content: UIElement, hashText: string, titleText?: UIElement }>) { | ||||
| 
 | ||||
| 
 | ||||
|         layoutToUse.map((layoutToUse) => { | ||||
|                 return Translations.WT(layoutToUse?.title)?.txt ?? "MapComplete" | ||||
|             }, [Locale.language] | ||||
|         ).addCallbackAndRun((title) => { | ||||
|             document.title = title | ||||
|         }); | ||||
| 
 | ||||
|         fullScreenMessage.addCallbackAndRun(selected => { | ||||
|             const title = Translations.WT(layoutToUse.data?.title)?.txt ?? "MapComplete" | ||||
|             if(selected?.titleText?.data === undefined){ | ||||
|                 document.title = title | ||||
|             }else{ | ||||
|                 selected.titleText.Update(); | ||||
|                 var d = document.createElement('div'); | ||||
|                 d.innerHTML = selected.titleText.InnerRender(); | ||||
|                 const poi = (d.textContent || d.innerText) | ||||
|                 document.title = title + " | " + poi; | ||||
|             } | ||||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | @ -1,29 +1,52 @@ | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import Constants from "../../Models/Constants"; | ||||
| import {Utils} from "../../Utils"; | ||||
| 
 | ||||
| export default class Hash { | ||||
|      | ||||
|     public static hash : UIEventSource<string> = Hash.Get(); | ||||
|      | ||||
|     private static Get() : UIEventSource<string>{ | ||||
|         if(Utils.runningFromConsole){ | ||||
| 
 | ||||
|     public static hash: UIEventSource<string> = Hash.Get(); | ||||
| 
 | ||||
|     /** | ||||
|      * Gets the current string, including the pound sign | ||||
|      * @constructor | ||||
|      */ | ||||
|     public static Current(): string { | ||||
|         if (Hash.hash.data === undefined || Hash.hash.data === "") { | ||||
|             return "" | ||||
|         } else { | ||||
|             return "#" + Hash.hash.data; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private static Get(): UIEventSource<string> { | ||||
|         if (Utils.runningFromConsole) { | ||||
|             return new UIEventSource<string>(undefined); | ||||
|         } | ||||
|         const hash = new UIEventSource<string>(window.location.hash.substr(1)); | ||||
|         hash.addCallback(h => { | ||||
|             if(h === undefined || h === ""){ | ||||
|             if (h === "undefined") { | ||||
|                 console.warn("Got a literal 'undefined' as hash, ignoring") | ||||
|                 h = undefined; | ||||
|             } | ||||
| 
 | ||||
|             if (h === undefined || h === "") { | ||||
|                 window.location.hash = ""; | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             h = h.replace(/\//g, "_"); | ||||
|             window.location.hash = "#" + h; | ||||
|         }); | ||||
| 
 | ||||
| 
 | ||||
|         window.onhashchange = () => { | ||||
|             hash.setData(window.location.hash.substr(1)) | ||||
|             let newValue = window.location.hash.substr(1); | ||||
|             if (newValue === "") { | ||||
|                 newValue = undefined; | ||||
|             } | ||||
|             hash.setData(newValue) | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|         return hash; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
| } | ||||
|  | @ -43,27 +43,23 @@ export class QueryParameters { | |||
|     private static Serialize() { | ||||
|         const parts = [] | ||||
|         for (const key of QueryParameters.order) { | ||||
|             if (QueryParameters.knownSources[key] === undefined || QueryParameters.knownSources[key].data === undefined) { | ||||
|             if (QueryParameters.knownSources[key]?.data === undefined) { | ||||
|                 continue; | ||||
|             } | ||||
|              | ||||
|             if (QueryParameters.knownSources[key].data === undefined) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             if (QueryParameters.knownSources[key].data === "undefined") { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             if (QueryParameters.knownSources[key].data == QueryParameters.defaults[key]) { | ||||
|             if (QueryParameters.knownSources[key].data === QueryParameters.defaults[key]) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(QueryParameters.knownSources[key].data)) | ||||
|         } | ||||
|         // Don't pollute the history every time a parameter changes
 | ||||
|         history.replaceState(null, "", "?" + parts.join("&") + "#" + Hash.hash.data); | ||||
|          | ||||
|         history.replaceState(null, "", "?" + parts.join("&") + Hash.Current()); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										17
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -4,7 +4,6 @@ import {ElementStorage} from "./Logic/ElementStorage"; | |||
| import {Changes} from "./Logic/Osm/Changes"; | ||||
| import {OsmConnection} from "./Logic/Osm/OsmConnection"; | ||||
| import Locale from "./UI/i18n/Locale"; | ||||
| import Translations from "./UI/i18n/Translations"; | ||||
| import {UIEventSource} from "./Logic/UIEventSource"; | ||||
| import {LocalStorageSource} from "./Logic/Web/LocalStorageSource"; | ||||
| import {QueryParameters} from "./Logic/Web/QueryParameters"; | ||||
|  | @ -18,6 +17,7 @@ import Constants from "./Models/Constants"; | |||
| 
 | ||||
| import UpdateFromOverpass from "./Logic/Actors/UpdateFromOverpass"; | ||||
| import LayerConfig from "./Customizations/JSON/LayerConfig"; | ||||
| import TitleHandler from "./Logic/Actors/TitleHandler"; | ||||
| 
 | ||||
| /** | ||||
|  * Contains the global state: a bunch of UI-event sources | ||||
|  | @ -75,7 +75,7 @@ export default class State { | |||
|     /** | ||||
|      This message is shown full screen on mobile devices | ||||
|      */ | ||||
|     public readonly fullScreenMessage = new UIEventSource<UIElement>(undefined) | ||||
|     public readonly fullScreenMessage = new UIEventSource<{ content: UIElement, hashText: string, titleText?: UIElement }>(undefined) | ||||
| 
 | ||||
|     /** | ||||
|      The latest element that was selected - used to generate the right UI at the right place | ||||
|  | @ -112,9 +112,9 @@ export default class State { | |||
|     public layoutDefinition: string; | ||||
|     public installedThemes: UIEventSource<{ layout: LayoutConfig; definition: string }[]>; | ||||
| 
 | ||||
|     public layerControlIsOpened: UIEventSource<boolean> =  | ||||
|     public layerControlIsOpened: UIEventSource<boolean> = | ||||
|         QueryParameters.GetQueryParameter("layer-control-toggle", "false", "Whether or not the layer control is shown") | ||||
|         .map<boolean>((str) => str !== "false", [], b => "" + b) | ||||
|             .map<boolean>((str) => str !== "false", [], b => "" + b) | ||||
| 
 | ||||
|     public welcomeMessageOpenedTab = QueryParameters.GetQueryParameter("tab", "0", `The tab that is shown in the welcome-message. 0 = the explanation of the theme,1 = OSM-credits, 2 = sharescreen, 3 = more themes, 4 = about mapcomplete (user must be logged in and have >${Constants.userJourney.mapCompleteHelpUnlock} changesets)`).map<number>( | ||||
|         str => isNaN(Number(str)) ? 0 : Number(str), [], n => "" + n | ||||
|  | @ -240,13 +240,8 @@ export default class State { | |||
|             } | ||||
|         }).ping() | ||||
| 
 | ||||
|         this.layoutToUse.map((layoutToUse) => { | ||||
|                 return Translations.WT(layoutToUse?.title)?.txt ?? "MapComplete" | ||||
|             }, [Locale.language] | ||||
|         ).addCallbackAndRun((title) => { | ||||
|             document.title = title | ||||
|         }); | ||||
| 
 | ||||
|         new TitleHandler(this.layoutToUse, this.fullScreenMessage); | ||||
|          | ||||
| 
 | ||||
|         this.allElements = new ElementStorage(); | ||||
|         this.changes = new Changes(); | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ export default class FullScreenMessageBox extends UIElement { | |||
|         if (State.state.fullScreenMessage.data === undefined) { | ||||
|             return ""; | ||||
|         } | ||||
|         this._content = State.state.fullScreenMessage.data; | ||||
|         this._content = State.state.fullScreenMessage.data.content; | ||||
|         return new Combine([this._content]).SetClass("fullscreenmessage-content").Render(); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,8 @@ import ScrollableFullScreen from "../Base/ScrollableFullScreen"; | |||
| export default class FeatureInfoBox extends UIElement { | ||||
|     private _component: UIElement; | ||||
| 
 | ||||
|     public title: UIEventSource<string> ; | ||||
|      | ||||
|     constructor( | ||||
|         tags: UIEventSource<any>, | ||||
|         layerConfig: LayerConfig | ||||
|  | @ -24,6 +26,7 @@ export default class FeatureInfoBox extends UIElement { | |||
| 
 | ||||
|         const title = new TagRenderingAnswer(tags, layerConfig.title ?? new TagRenderingConfig("POI", undefined)) | ||||
|             .SetClass("featureinfobox-title"); | ||||
|         this.title = title; | ||||
|         const titleIcons = new Combine( | ||||
|             layerConfig.titleIcons.map(icon => new TagRenderingAnswer(tags, icon))) | ||||
|             .SetClass("featureinfobox-icons"); | ||||
|  |  | |||
|  | @ -154,7 +154,7 @@ export default class ShowDataLayer { | |||
|         this._onSelectedTrigger[feature.properties.id.replace("/","_")] = this._onSelectedTrigger[id]; | ||||
|         if (feature.properties.id.replace(/\//g, "_") === Hash.hash.data) { | ||||
|             // This element is in the URL, so this is a share link
 | ||||
|             // We already open it
 | ||||
|             // We open the relevant popup straight away
 | ||||
|             uiElement.Activate(); | ||||
|             popup.setContent(uiElement.Render()); | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								index.ts
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								index.ts
									
										
									
									
									
								
							|  | @ -6,7 +6,6 @@ import {UIEventSource} from "./Logic/UIEventSource"; | |||
| import * as $ from "jquery"; | ||||
| import LayoutConfig from "./Customizations/JSON/LayoutConfig"; | ||||
| import {Utils} from "./Utils"; | ||||
| import {Overpass} from "./Logic/Osm/Overpass"; | ||||
| 
 | ||||
| let defaultLayout = "bookcases" | ||||
| // --------------------- Special actions based on the parameters -----------------
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue