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…
Reference in a new issue