Various small fixes to translations, login flow, docs, ...

This commit is contained in:
Pieter Vander Vennet 2020-08-25 00:10:48 +02:00
parent 1805f644ea
commit e320f1af0c
9 changed files with 69 additions and 46 deletions

View file

@ -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 = ""
) { ) {

View file

@ -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) {

View file

@ -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({

View file

@ -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

View file

@ -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 = {

View file

@ -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,7 +19,8 @@ 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>,
uploadOptions: ((license: string) => uploadOptions: ((license: 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)

View file

@ -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/>" +

View file

@ -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"}),

View file

@ -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;
} }