Merge develop
This commit is contained in:
commit
32e30e4b01
14 changed files with 90 additions and 131 deletions
|
@ -151,7 +151,7 @@ export class Denomination {
|
|||
if (stripped === null) {
|
||||
return null;
|
||||
}
|
||||
return stripped + this.canonical
|
||||
return stripped + " " + this.canonical.trim()
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,33 +2,33 @@ import {Changes} from "../Osm/Changes";
|
|||
import Constants from "../../Models/Constants";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
|
||||
export default class PendingChangesUploader{
|
||||
|
||||
private lastChange : Date;
|
||||
|
||||
export default class PendingChangesUploader {
|
||||
|
||||
private lastChange: Date;
|
||||
|
||||
constructor(changes: Changes, selectedFeature: UIEventSource<any>) {
|
||||
const self = this;
|
||||
this.lastChange = new Date();
|
||||
changes.pending.addCallback(() => {
|
||||
self.lastChange = new Date();
|
||||
|
||||
|
||||
window.setTimeout(() => {
|
||||
const diff = (new Date().getTime() - self.lastChange.getTime()) / 1000;
|
||||
if(Constants.updateTimeoutSec >= diff - 1){
|
||||
if (Constants.updateTimeoutSec >= diff - 1) {
|
||||
changes.flushChanges("Flushing changes due to timeout");
|
||||
}
|
||||
}, Constants.updateTimeoutSec * 1000);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
selectedFeature
|
||||
.stabilized(10000)
|
||||
.addCallback(feature => {
|
||||
if(feature === undefined){
|
||||
// The popup got closed - we flush
|
||||
changes.flushChanges("Flushing changes due to popup closed");
|
||||
}
|
||||
});
|
||||
if (feature === undefined) {
|
||||
// The popup got closed - we flush
|
||||
changes.flushChanges("Flushing changes due to popup closed");
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('mouseout', e => {
|
||||
// @ts-ignore
|
||||
|
@ -36,7 +36,7 @@ export default class PendingChangesUploader{
|
|||
changes.flushChanges("Flushing changes due to focus lost");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
document.onfocus = () => {
|
||||
changes.flushChanges("OnFocus")
|
||||
}
|
||||
|
@ -44,18 +44,17 @@ export default class PendingChangesUploader{
|
|||
document.onblur = () => {
|
||||
changes.flushChanges("OnFocus")
|
||||
}
|
||||
try{
|
||||
try {
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
changes.flushChanges("Visibility change")
|
||||
}, false);
|
||||
}catch(e){
|
||||
} catch (e) {
|
||||
console.warn("Could not register visibility change listener", e)
|
||||
}
|
||||
|
||||
|
||||
window.onbeforeunload = function(e){
|
||||
|
||||
if(changes.pending.data.length == 0){
|
||||
function onunload(e) {
|
||||
if (changes.pending.data.length == 0) {
|
||||
return;
|
||||
}
|
||||
changes.flushChanges("onbeforeunload - probably closing or something similar");
|
||||
|
@ -63,8 +62,11 @@ export default class PendingChangesUploader{
|
|||
return "Saving your last changes..."
|
||||
}
|
||||
|
||||
window.onbeforeunload = onunload
|
||||
// https://stackoverflow.com/questions/3239834/window-onbeforeunload-not-working-on-the-ipad#4824156
|
||||
window.addEventListener("pagehide", onunload)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@ import { Utils } from "../Utils";
|
|||
|
||||
export default class Constants {
|
||||
|
||||
public static vNumber = "0.8.2";
|
||||
public static vNumber = "0.8.2a";
|
||||
|
||||
// The user journey states thresholds when a new feature gets unlocked
|
||||
public static userJourney = {
|
||||
|
|
|
@ -65,8 +65,8 @@ export default class AttributionPanel extends Combine {
|
|||
...Utils.NoNull(Array.from(layoutToUse.data.ExtractImages()))
|
||||
.map(AttributionPanel.IconAttribution)
|
||||
]);
|
||||
this.SetClass("flex flex-col link-underline")
|
||||
this.SetStyle("max-width: calc(100vw - 5em); width: 40em;")
|
||||
this.SetClass("flex flex-col link-underline overflow-hidden")
|
||||
this.SetStyle("max-width: calc(100vw - 5em); width: 40rem;")
|
||||
}
|
||||
|
||||
private static CodeContributors(): BaseUIElement {
|
||||
|
@ -105,7 +105,7 @@ export default class AttributionPanel extends Combine {
|
|||
const sources = Utils.NoNull(Utils.NoEmpty(license.sources))
|
||||
|
||||
return new Combine([
|
||||
`<img src='${iconPath}' style="width: 50px; height: 50px; margin-right: 0.5em;">`,
|
||||
`<img src='${iconPath}' style="width: 50px; height: 50px; min-width: 50px; min-height: 50px; margin-right: 0.5em;">`,
|
||||
new Combine([
|
||||
new FixedUiElement(license.authors.join("; ")).SetClass("font-bold"),
|
||||
new Combine([license.license,
|
||||
|
@ -120,9 +120,10 @@ export default class AttributionPanel extends Combine {
|
|||
return new Link(sourceLinkContent, lnk, true);
|
||||
})
|
||||
]
|
||||
).SetClass("block")
|
||||
]).SetClass("flex flex-col")
|
||||
]).SetClass("flex")
|
||||
).SetClass("block m-2")
|
||||
|
||||
]).SetClass("flex flex-col").SetStyle("width: calc(100% - 50px - 0.5em); min-width: 12rem;")
|
||||
]).SetClass("flex flex-wrap border-b border-gray-300 m-2 border-box")
|
||||
}
|
||||
|
||||
private static GenerateLicenses() {
|
||||
|
|
|
@ -26,12 +26,6 @@ export class Basemap {
|
|||
attributionControl: extraAttribution !== undefined
|
||||
});
|
||||
|
||||
L.control.scale(
|
||||
{
|
||||
position: 'topright',
|
||||
}
|
||||
).addTo(this.map)
|
||||
|
||||
|
||||
// Users are not allowed to zoom to the 'copies' on the left and the right, stuff goes wrong then
|
||||
// We give a bit of leeway for people on the edges
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
/**
|
||||
* Handles and updates the user badge
|
||||
*/
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import Svg from "../../Svg";
|
||||
import State from "../../State";
|
||||
|
@ -21,7 +18,7 @@ export default class UserBadge extends Toggle {
|
|||
|
||||
const loginButton = Translations.t.general.loginWithOpenStreetMap
|
||||
.Clone()
|
||||
.SetClass("userbadge-login pt-3 w-full")
|
||||
.SetClass("userbadge-login pt-3 w-full h-full")
|
||||
.onClick(() => State.state.osmConnection.AttemptLogin());
|
||||
|
||||
|
||||
|
@ -32,7 +29,7 @@ export default class UserBadge extends Toggle {
|
|||
});
|
||||
|
||||
|
||||
const userBadge = userDetails.map(user => {
|
||||
const userBadge = new VariableUiElement(userDetails.map(user => {
|
||||
{
|
||||
const homeButton = new VariableUiElement(
|
||||
userDetails.map((userinfo) => {
|
||||
|
@ -78,7 +75,7 @@ export default class UserBadge extends Toggle {
|
|||
|
||||
let dryrun = new FixedUiElement("");
|
||||
if (user.dryRun) {
|
||||
dryrun = new FixedUiElement("TESTING").SetClass("alert");
|
||||
dryrun = new FixedUiElement("TESTING").SetClass("alert font-xs p-0 max-h-4");
|
||||
}
|
||||
|
||||
const settings =
|
||||
|
@ -87,15 +84,6 @@ export default class UserBadge extends Toggle {
|
|||
true)
|
||||
|
||||
|
||||
const userIcon = new Link(
|
||||
user.img === undefined ? Svg.osm_logo_ui() : new Img(user.img)
|
||||
.SetClass("rounded-full opacity-0 m-0 p-0 duration-500 w-16 h16 float-left")
|
||||
,
|
||||
`${user.backend}/user/${encodeURIComponent(user.name)}`,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
const userName = new Link(
|
||||
new FixedUiElement(user.name),
|
||||
`${user.backend}/user/${user.name}`,
|
||||
|
@ -113,24 +101,40 @@ export default class UserBadge extends Toggle {
|
|||
.SetClass("userstats")
|
||||
|
||||
const usertext = new Combine([
|
||||
userName,
|
||||
dryrun,
|
||||
new Combine([userName, dryrun]).SetClass("flex justify-end w-full"),
|
||||
userStats
|
||||
]).SetClass("usertext")
|
||||
]).SetClass("flex flex-col sm:w-auto sm:pl-2 overflow-hidden w-0")
|
||||
const userIcon =
|
||||
(user.img === undefined ? Svg.osm_logo_ui() : new Img(user.img)).SetClass("rounded-full opacity-0 m-0 p-0 duration-500 w-16 min-width-16 h16 float-left")
|
||||
.onClick(() => {
|
||||
if(usertext.HasClass("w-0")){
|
||||
usertext.RemoveClass("w-0")
|
||||
usertext.SetClass("w-min pl-2")
|
||||
}else{
|
||||
usertext.RemoveClass("w-min")
|
||||
usertext.RemoveClass("pl-2")
|
||||
usertext.SetClass("w-0")
|
||||
}
|
||||
})
|
||||
|
||||
return new Combine([
|
||||
userIcon,
|
||||
usertext,
|
||||
]).SetClass("h-16")
|
||||
userIcon,
|
||||
]).SetClass("h-16 flex bg-white")
|
||||
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
userBadge.SetClass("inline-block m-0 w-full").SetStyle("pointer-events: all")
|
||||
super(
|
||||
new VariableUiElement(userBadge),
|
||||
userBadge,
|
||||
loginButton,
|
||||
State.state.osmConnection.isLoggedIn
|
||||
)
|
||||
|
||||
|
||||
this.SetClass("shadow rounded-full h-min overflow-hidden block w-max")
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,15 +15,6 @@ Contains tweaks for small screens
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
#help-button-mobile div {
|
||||
box-shadow: 0 0 10px #0006;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#geolocate-button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#centermessage {
|
||||
top: 30%;
|
||||
left: 15%;
|
||||
|
@ -57,21 +48,5 @@ Contains tweaks for small screens
|
|||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
/* Portrait */
|
||||
#userbadge-and-search {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
||||
.userbadge-login {
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
#userbadge {
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,16 +1,4 @@
|
|||
#userbadge {
|
||||
display: inline-block;
|
||||
background-color: var(--background-color);
|
||||
color: var(--foreground-color);
|
||||
margin: 0;
|
||||
margin-bottom: 0.5em;
|
||||
width: 100%;
|
||||
min-width: 20em;
|
||||
pointer-events: all;
|
||||
border-radius: 999em;
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
|
||||
.userstats {
|
||||
display: flex;
|
||||
|
@ -45,28 +33,6 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.usertext {
|
||||
display: block;
|
||||
width: max-content;
|
||||
margin: 0;
|
||||
|
||||
padding: 0.9em;
|
||||
padding-left: 4.7em; /* Should be half of profile-pic's width + actual padding (same as padding-right)*/
|
||||
padding-right: 1.5em;
|
||||
border-radius: 2em; /*Half border radius width/height*/
|
||||
height: 2.2em; /*SHould equal profile-pic height - padding*/
|
||||
z-index: 5000;
|
||||
text-align: left;
|
||||
background-color: var(--background-color);
|
||||
color: var(--foreground-color);
|
||||
background-size: 100%;
|
||||
|
||||
line-height: 0.75em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.userbadge-login {
|
||||
font-weight: bold;
|
||||
font-size: large;
|
||||
|
@ -81,10 +47,3 @@
|
|||
min-width: 20em;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
#userbadge-and-search {
|
||||
display: inline-block;
|
||||
width: min-content;
|
||||
overflow-x: hidden;
|
||||
max-width: 100vw;
|
||||
}
|
||||
|
|
12
index.css
12
index.css
|
@ -93,6 +93,18 @@ a {
|
|||
color: var(--foreground-color);
|
||||
}
|
||||
|
||||
.h-min {
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.w-min {
|
||||
width: min-content;
|
||||
}
|
||||
|
||||
.space-between{
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.link-underline a {
|
||||
text-decoration: underline 1px #0078a855;;
|
||||
color: #0078A8;
|
||||
|
|
|
@ -59,9 +59,9 @@
|
|||
|
||||
<div id="fullscreen" class="hidden md:hidden fixed inset-0 block z-above-controls"></div>
|
||||
<div id="topleft-tools" class="z-index-above-map">
|
||||
<div id="userbadge-and-search" class="p-3">
|
||||
<div id="userbadge" class="shadow rounded-3xl overflow-hidden"></div>
|
||||
<div id="searchbox" class="shadow rounded-3xl overflow-hidden"></div>
|
||||
<div class="p-3 flex flex-col items-end sm:items-start sm:flex-row sm:flex-wrap w-full sm:justify-between">
|
||||
<div id="searchbox" class="shadow rounded-full h-min w-full overflow-hidden sm:max-w-sm"></div>
|
||||
<div id="userbadge" class="m-1"></div>
|
||||
</div>
|
||||
<div id="messagesbox" class="rounded-3xl overflow-hidden ml-3"></div>
|
||||
</div>
|
||||
|
|
1
langs/*.json
Normal file
1
langs/*.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -8,6 +8,16 @@
|
|||
"pleaseLogin": "Faça login para adicionar uma imagem",
|
||||
"uploadingMultiple": "Fazendo upload de {count} imagens…",
|
||||
"uploadingPicture": "Enviando sua imagem…",
|
||||
"addPicture": "Adicionar imagem"
|
||||
"addPicture": "Adicionar imagem",
|
||||
"isDeleted": "Excluída",
|
||||
"doDelete": "Remover imagem",
|
||||
"dontDelete": "Cancelar",
|
||||
"uploadDone": "<span class=\"thanks\">Sua foto foi adicionada. Obrigado por ajudar!</span>",
|
||||
"uploadFailed": "Não foi possível enviar sua foto. Você está conectado à Internet e permite APIs de terceiros? O navegador Brave ou o plugin uMatrix podem bloqueá-los."
|
||||
},
|
||||
"centerMessage": {
|
||||
"ready": "Concluído!",
|
||||
"zoomIn": "Amplie para ver ou editar os dados",
|
||||
"loadingData": "Carregando dados…"
|
||||
}
|
||||
}
|
||||
|
|
1
langs/shared-questions/*.json
Normal file
1
langs/shared-questions/*.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"aed": {
|
||||
"title": "Открытая карта AED (Автоматизированных внешних дефибрилляторов)",
|
||||
"title": "Открытая карта АВД (Автоматизированных внешних дефибрилляторов)",
|
||||
"description": "На этой карте вы можете найти и отметить ближайшие дефибрилляторы"
|
||||
},
|
||||
"artworks": {
|
||||
|
@ -522,4 +522,4 @@
|
|||
"trees": {
|
||||
"title": "Деревья"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue