forked from MapComplete/MapComplete
		
	Various small fixes to translations, login flow, docs, ...
This commit is contained in:
		
							parent
							
								
									1805f644ea
								
							
						
					
					
						commit
						e320f1af0c
					
				
					 9 changed files with 69 additions and 46 deletions
				
			
		| 
						 | 
					@ -1,6 +1,9 @@
 | 
				
			||||||
import {LayerDefinition} from "./LayerDefinition";
 | 
					import {LayerDefinition} from "./LayerDefinition";
 | 
				
			||||||
import {UIElement} from "../UI/UIElement";
 | 
					import {UIElement} from "../UI/UIElement";
 | 
				
			||||||
import Translations from "../UI/i18n/Translations";
 | 
					import Translations from "../UI/i18n/Translations";
 | 
				
			||||||
 | 
					import Combine from "../UI/Base/Combine";
 | 
				
			||||||
 | 
					import {FixedUiElement} from "../UI/Base/FixedUiElement";
 | 
				
			||||||
 | 
					import {State} from "../State";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
 | 
					 * A layout is a collection of settings of the global view (thus: welcome text, title, selection of layers).
 | 
				
			||||||
| 
						 | 
					@ -66,7 +69,12 @@ export class Layout {
 | 
				
			||||||
        startLat: number,
 | 
					        startLat: number,
 | 
				
			||||||
        startLon: number,
 | 
					        startLon: number,
 | 
				
			||||||
        welcomeMessage: UIElement | string,
 | 
					        welcomeMessage: UIElement | string,
 | 
				
			||||||
        gettingStartedPlzLogin: UIElement | string = Translations.t.general.getStarted,
 | 
					        gettingStartedPlzLogin: UIElement | string = new Combine([
 | 
				
			||||||
 | 
					            Translations.t.general.getStartedLogin
 | 
				
			||||||
 | 
					                .SetClass("soft")
 | 
				
			||||||
 | 
					                .onClick(() => {State.state.osmConnection.AttemptLogin()}),
 | 
				
			||||||
 | 
					            Translations.t.general.getStartedNewAccount
 | 
				
			||||||
 | 
					        ]),
 | 
				
			||||||
        welcomeBackMessage: UIElement | string = Translations.t.general.welcomeBack,
 | 
					        welcomeBackMessage: UIElement | string = Translations.t.general.welcomeBack,
 | 
				
			||||||
        welcomeTail: UIElement | string = ""
 | 
					        welcomeTail: UIElement | string = ""
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ import {State} from "../State";
 | 
				
			||||||
import {TagRenderingOptions} from "./TagRenderingOptions";
 | 
					import {TagRenderingOptions} from "./TagRenderingOptions";
 | 
				
			||||||
import Translation from "../UI/i18n/Translation";
 | 
					import Translation from "../UI/i18n/Translation";
 | 
				
			||||||
import {SubtleButton} from "../UI/Base/SubtleButton";
 | 
					import {SubtleButton} from "../UI/Base/SubtleButton";
 | 
				
			||||||
 | 
					import Combine from "../UI/Base/Combine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class TagRendering extends UIElement implements TagDependantUIElement {
 | 
					export class TagRendering extends UIElement implements TagDependantUIElement {
 | 
				
			||||||
| 
						 | 
					@ -393,12 +394,14 @@ export class TagRendering extends UIElement implements TagDependantUIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.IsQuestioning() && !State.state?.osmConnection?.userDetails?.data?.loggedIn) {
 | 
					        if (this.IsQuestioning() && !State.state?.osmConnection?.userDetails?.data?.loggedIn) {
 | 
				
			||||||
            const question =
 | 
					            const question =
 | 
				
			||||||
                this.ApplyTemplate(this._question).Render();
 | 
					                this.ApplyTemplate(this._question).SetClass('question-text');
 | 
				
			||||||
            return "<div class='question'>" +
 | 
					            return "<div class='question'>" +
 | 
				
			||||||
                "<span class='question-text'>" + question + "</span>" +
 | 
					                new Combine([
 | 
				
			||||||
                "<br/>" +
 | 
					                    question,
 | 
				
			||||||
                "<span class='login-button-friendly'>" + this._friendlyLogin.Render() + "</span>" +
 | 
					                    "<br/>",
 | 
				
			||||||
                "</div>"
 | 
					                    this._questionElement.Render(),
 | 
				
			||||||
 | 
					                    "<span class='login-button-friendly'>" + this._friendlyLogin.Render() + "</span>",
 | 
				
			||||||
 | 
					                ]).Render() + "</div>";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.IsQuestioning() || this._editMode.data) {
 | 
					        if (this.IsQuestioning() || this._editMode.data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ export class OsmConnection {
 | 
				
			||||||
        const iframeMode = window !== window.top;
 | 
					        const iframeMode = window !== window.top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ( iframeMode || !singlePage) {
 | 
					        if ( iframeMode || pwaStandAloneMode || !singlePage) {
 | 
				
			||||||
            // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway...
 | 
					            // In standalone mode, we DON'T use single page login, as 'redirecting' opens a new window anyway...
 | 
				
			||||||
            // Same for an iframe...
 | 
					            // Same for an iframe...
 | 
				
			||||||
            this.auth = new osmAuth({
 | 
					            this.auth = new osmAuth({
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										28
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
					@ -40,23 +40,19 @@ MapComplete is set up to lure people into OpenStreetMap and to teach them while
 | 
				
			||||||
 | 
					
 | 
				
			||||||
A typical user journey would be:
 | 
					A typical user journey would be:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
0) Oh, this is a cool map of _my specific interest_! There is a lot of data already...
 | 
					0. Oh, this is a cool map of _my specific interest_! There is a lot of data already...
 | 
				
			||||||
0a) The user might discover the explanation about OSM in the dedicated tab page
 | 
					    a. The user might discover the explanation about OSM in the dedicated tab page
 | 
				
			||||||
0b) The user might discover the other themes in the other tab
 | 
					    b. The user might discover the other themes in the other tab
 | 
				
			||||||
0c) The user might share the map and/or embed it
 | 
					    c. The user might share the map and/or embed it
 | 
				
			||||||
 | 
					 | 
				
			||||||
1) The user clicks that big tempting button 'login' in order to answer questions. The user makes an account - a big step.
 | 
					1) The user clicks that big tempting button 'login' in order to answer questions. The user makes an account - a big step.
 | 
				
			||||||
 | 
					2. The user answers a question! Hooray!
 | 
				
			||||||
2) The user answers a question! Hooray!
 | 
					 | 
				
			||||||
    When at least one question is answered (aka: having one changeset on OSM), adding a new point is unlocked
 | 
					    When at least one question is answered (aka: having one changeset on OSM), adding a new point is unlocked
 | 
				
			||||||
    
 | 
					3. The user adds a new POI somewhere 
 | 
				
			||||||
3) The user adds a new POI somewhere 
 | 
					    a. Note that _all messages_ must be read before being able to add a point. In other words, sending a message to a misbehaving MapComplete user acts as having a zero-minutes-block. This is added deliberately to avoid new users fucking up too much
 | 
				
			||||||
3a) Note that _all messages_ must be read before being able to add a point. In other words, sending a message to a misbehaving MapComplete user acts as having a zero-minutes-block. This is added deliberately to avoid new users fucking up too much
 | 
					4. At 50 changesets, the custom layout becomes available
 | 
				
			||||||
 | 
					5. At 200 changesets, the tags become visible when answering questions and when adding a new point from a preset. This is to give more control to power users and to teach new users the tagging scheme
 | 
				
			||||||
4) At 50 changesets, the custom layout becomes available
 | 
					6. At 250 changesets, the tags get linked to the wiki
 | 
				
			||||||
5) At 200 changesets, the tags become visible when answering questions and when adding a new point from a preset. This is to give more control to power users and to teach new users the tagging scheme
 | 
					7. At 500 changesets, I expect contributors to be power users and to be comfortable with tagging scheme and such. The custom theme generator is unlocked.
 | 
				
			||||||
5) At 250 changesets, the tags get linked to the wiki
 | 
					 | 
				
			||||||
6) At 500 changesets, I expect users to be power users and to be comfortable with tagging scheme and such. The custom theme generator is unlocked.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## License
 | 
					## License
 | 
				
			||||||
| 
						 | 
					@ -133,7 +129,7 @@ Geolocation is available on mobile only throught hte device's GPS location (so n
 | 
				
			||||||
TODO: erase cookies of third party websites and API's
 | 
					TODO: erase cookies of third party websites and API's
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Attributions:
 | 
					# Attributions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Data from OpenStreetMap
 | 
					Data from OpenStreetMap
 | 
				
			||||||
Images from Wikipedia/Wikimedia
 | 
					Images from Wikipedia/Wikimedia
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								State.ts
									
										
									
									
									
								
							| 
						 | 
					@ -24,7 +24,7 @@ export class State {
 | 
				
			||||||
    // The singleton of the global state
 | 
					    // The singleton of the global state
 | 
				
			||||||
    public static state: State;
 | 
					    public static state: State;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    public static vNumber = "0.0.6";
 | 
					    public static vNumber = "0.0.6a";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // The user journey states thresholds when a new feature gets unlocked
 | 
					    // The user journey states thresholds when a new feature gets unlocked
 | 
				
			||||||
    public static userJourney = {
 | 
					    public static userJourney = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@ import {VerticalCombine} from "./Base/VerticalCombine";
 | 
				
			||||||
import {State} from "../State";
 | 
					import {State} from "../State";
 | 
				
			||||||
import {UIEventSource} from "../Logic/UIEventSource";
 | 
					import {UIEventSource} from "../Logic/UIEventSource";
 | 
				
			||||||
import {Imgur} from "../Logic/Web/Imgur";
 | 
					import {Imgur} from "../Logic/Web/Imgur";
 | 
				
			||||||
 | 
					import {SubtleButton} from "./Base/SubtleButton";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class ImageUploadFlow extends UIElement {
 | 
					export class ImageUploadFlow extends UIElement {
 | 
				
			||||||
    private _licensePicker: UIElement;
 | 
					    private _licensePicker: UIElement;
 | 
				
			||||||
| 
						 | 
					@ -18,6 +19,7 @@ export class ImageUploadFlow extends UIElement {
 | 
				
			||||||
    private _didFail: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
					    private _didFail: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
				
			||||||
    private _allDone: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
					    private _allDone: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
				
			||||||
    private _uploadOptions: (license: string) => { title: string; description: string; handleURL: (url: string) => void; allDone: (() => void) };
 | 
					    private _uploadOptions: (license: string) => { title: string; description: string; handleURL: (url: string) => void; allDone: (() => void) };
 | 
				
			||||||
 | 
					    private _connectButton : UIElement;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        preferedLicense: UIEventSource<string>,
 | 
					        preferedLicense: UIEventSource<string>,
 | 
				
			||||||
| 
						 | 
					@ -42,10 +44,13 @@ export class ImageUploadFlow extends UIElement {
 | 
				
			||||||
                {value: "CC-BY 4.0", shown: Translations.t.image.ccb}
 | 
					                {value: "CC-BY 4.0", shown: Translations.t.image.ccb}
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
            preferedLicense
 | 
					            preferedLicense
 | 
				
			||||||
        );
 | 
					        ); const t = Translations.t.image;
 | 
				
			||||||
 | 
					       
 | 
				
			||||||
        this._licensePicker = licensePicker;
 | 
					        this._licensePicker = licensePicker;
 | 
				
			||||||
        this._selectedLicence = licensePicker.GetValue();
 | 
					        this._selectedLicence = licensePicker.GetValue();
 | 
				
			||||||
 | 
					        this._connectButton = new Combine([ t.pleaseLogin])
 | 
				
			||||||
 | 
					            .onClick(() => State.state.osmConnection.AttemptLogin())
 | 
				
			||||||
 | 
					            .SetClass("login-button-friendly");    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +63,7 @@ export class ImageUploadFlow extends UIElement {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!State.state.osmConnection.userDetails.data.loggedIn) {
 | 
					        if (!State.state.osmConnection.userDetails.data.loggedIn) {
 | 
				
			||||||
            return t.pleaseLogin.Render();
 | 
					            return this._connectButton.Render();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let currentState: UIElement[] = [];
 | 
					        let currentState: UIElement[] = [];
 | 
				
			||||||
| 
						 | 
					@ -115,12 +120,6 @@ export class ImageUploadFlow extends UIElement {
 | 
				
			||||||
        super.InnerUpdate(htmlElement);
 | 
					        super.InnerUpdate(htmlElement);
 | 
				
			||||||
        const user = State.state.osmConnection.userDetails.data;
 | 
					        const user = State.state.osmConnection.userDetails.data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        htmlElement.onclick = function () {
 | 
					 | 
				
			||||||
            if (!user.loggedIn) {
 | 
					 | 
				
			||||||
                State.state.osmConnection.AttemptLogin();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this._licensePicker.Update()
 | 
					        this._licensePicker.Update()
 | 
				
			||||||
        const form = document.getElementById('fileselector-form-' + this.id) as HTMLFormElement
 | 
					        const form = document.getElementById('fileselector-form-' + this.id) as HTMLFormElement
 | 
				
			||||||
        const selector = document.getElementById('fileselector-' + this.id)
 | 
					        const selector = document.getElementById('fileselector-' + this.id)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ export class WelcomeMessage extends UIElement {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return "<span>" +
 | 
					        return "<span>" +
 | 
				
			||||||
            this.description.Render() +
 | 
					            this.description.Render() +
 | 
				
			||||||
            "<br/>" +
 | 
					            "<br/></br>" +
 | 
				
			||||||
            loginStatus +
 | 
					            loginStatus +
 | 
				
			||||||
            this.tail.Render() +
 | 
					            this.tail.Render() +
 | 
				
			||||||
            "<br/>" +
 | 
					            "<br/>" +
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -619,9 +619,9 @@ export default class Translations {
 | 
				
			||||||
                fr: 'Mettre votre {count} photos en ligne'
 | 
					                fr: 'Mettre votre {count} photos en ligne'
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            pleaseLogin: new T({
 | 
					            pleaseLogin: new T({
 | 
				
			||||||
                en: 'Please login to add a picure or to answer questions',
 | 
					                en: 'Please login to add a picure',
 | 
				
			||||||
                nl: 'Gelieve je aan te melden om een foto toe te voegen of vragen te beantwoorden',
 | 
					                nl: 'Gelieve je aan te melden om een foto toe te voegen',
 | 
				
			||||||
                fr: 'Merci de vous connecter pour mettre une photo en ligne ou répondre aux questions'
 | 
					                fr: 'Connectez vous pour mettre une photo en ligne'
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            willBePublished: new T({
 | 
					            willBePublished: new T({
 | 
				
			||||||
                en: 'Your picture will be published: ',
 | 
					                en: 'Your picture will be published: ',
 | 
				
			||||||
| 
						 | 
					@ -664,12 +664,6 @@ export default class Translations {
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        general: {
 | 
					        general: {
 | 
				
			||||||
            loginWithOpenStreetMap: new T({en: "Login with OpenStreetMap", nl: "Aanmelden met OpenStreetMap", fr:'Se connecter avec OpenStreeMap'}),
 | 
					            loginWithOpenStreetMap: new T({en: "Login with OpenStreetMap", nl: "Aanmelden met OpenStreetMap", fr:'Se connecter avec OpenStreeMap'}),
 | 
				
			||||||
            getStarted: new T({
 | 
					 | 
				
			||||||
                en: "<span class='activate-osm-authentication'>Login with OpenStreetMap</span> or <a href='https://www.openstreetmap.org/user/new' target='_blank'>make a free account to get started</a>",
 | 
					 | 
				
			||||||
                nl: "<span class='activate-osm-authentication'>Meld je aan met je OpenStreetMap-account</span> of <a href='https://www.openstreetmap.org/user/new' target='_blank'>maak snel en gratis een account om te beginnen</a>",
 | 
					 | 
				
			||||||
                fr: "<span class='activate-osm-authentication'>Se connecter avec OpenStreetMap</span> ou <a href='https://www.openstreetmap.org/user/new' target='_blank'>créer un compte gratuitement pour commencer</a>",
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            }),
 | 
					 | 
				
			||||||
            welcomeBack: new T({
 | 
					            welcomeBack: new T({
 | 
				
			||||||
                en: "You are logged in, welcome back!",
 | 
					                en: "You are logged in, welcome back!",
 | 
				
			||||||
                nl: "Je bent aangemeld. Welkom terug!",
 | 
					                nl: "Je bent aangemeld. Welkom terug!",
 | 
				
			||||||
| 
						 | 
					@ -677,7 +671,8 @@ export default class Translations {
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            loginToStart: new T({
 | 
					            loginToStart: new T({
 | 
				
			||||||
                en: "Login to answer this question",
 | 
					                en: "Login to answer this question",
 | 
				
			||||||
                nl: "Meld je aan om deze vraag te beantwoorden"
 | 
					                nl: "Meld je aan om deze vraag te beantwoorden",
 | 
				
			||||||
 | 
					                fr: "Connectez vous pour répondre à cette question"
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
            search: {
 | 
					            search: {
 | 
				
			||||||
                search: new Translation({
 | 
					                search: new Translation({
 | 
				
			||||||
| 
						 | 
					@ -926,7 +921,17 @@ export default class Translations {
 | 
				
			||||||
                en: "Open inbox",
 | 
					                en: "Open inbox",
 | 
				
			||||||
                nl: "Ga naar de berichten",
 | 
					                nl: "Ga naar de berichten",
 | 
				
			||||||
                fr: "Ouvrir les messages"
 | 
					                fr: "Ouvrir les messages"
 | 
				
			||||||
            })
 | 
					            }),
 | 
				
			||||||
 | 
					            getStartedLogin: new T({
 | 
				
			||||||
 | 
					                en: "Login with OpenStreetMap to get started",
 | 
				
			||||||
 | 
					                nl: "Login met OpenStreetMap om te beginnen",
 | 
				
			||||||
 | 
					                fr: "Connectez vous avec OpenStreetMap pour commencer"
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            getStartedNewAccount: new T({
 | 
				
			||||||
 | 
					                en: " or <a href='https://www.openstreetmap.org/user/new' target='_blank'>create a new account</a>",
 | 
				
			||||||
 | 
					                nl: " of <a href='https://www.openstreetmap.org/user/new' target='_blank'>maak een nieuwe account aan</a> ",
 | 
				
			||||||
 | 
					                fr: " ou <a href='https://www.openstreetmap.org/user/new' target='_blank'>registrez vous</a>"
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        favourite: {
 | 
					        favourite: {
 | 
				
			||||||
            title: new T({en: "Personal theme"}),
 | 
					            title: new T({en: "Personal theme"}),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								index.css
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								index.css
									
										
									
									
									
								
							| 
						 | 
					@ -78,6 +78,18 @@ form {
 | 
				
			||||||
    padding-bottom: 0.15em;
 | 
					    padding-bottom: 0.15em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.soft {
 | 
				
			||||||
 | 
					    background-color: #e5f5ff;
 | 
				
			||||||
 | 
					    font-weight: bold;
 | 
				
			||||||
 | 
					    border-radius: 1em;
 | 
				
			||||||
 | 
					    padding: 0.3em;
 | 
				
			||||||
 | 
					    margin: 0.25em;
 | 
				
			||||||
 | 
					    text-align: center;
 | 
				
			||||||
 | 
					    padding-top: 0.15em;
 | 
				
			||||||
 | 
					    padding-bottom: 0.15em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.subtle {
 | 
					.subtle {
 | 
				
			||||||
    color: #999;
 | 
					    color: #999;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue