forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
d0ebd0e233
187 changed files with 1201 additions and 22352 deletions
74
src/UI/AllThemesGui.svelte
Normal file
74
src/UI/AllThemesGui.svelte
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<script lang="ts">
|
||||
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState";
|
||||
import { OsmConnection } from "../Logic/Osm/OsmConnection";
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters";
|
||||
import UserRelatedState from "../Logic/State/UserRelatedState";
|
||||
import LanguagePicker from "./InputElement/LanguagePicker.svelte";
|
||||
import Translations from "./i18n/Translations";
|
||||
import Logo from "../assets/svg/Logo.svelte";
|
||||
import Tr from "./Base/Tr.svelte";
|
||||
import ToSvelte from "./Base/ToSvelte.svelte";
|
||||
import MoreScreen from "./BigComponents/MoreScreen";
|
||||
import LoginToggle from "./Base/LoginToggle.svelte";
|
||||
import Pencil from "../assets/svg/Pencil.svelte";
|
||||
import Login from "../assets/svg/Login.svelte";
|
||||
import Constants from "../Models/Constants";
|
||||
|
||||
const featureSwitches = new OsmConnectionFeatureSwitches();
|
||||
const osmConnection = new OsmConnection({
|
||||
fakeUser: featureSwitches.featureSwitchFakeUser.data,
|
||||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
)
|
||||
});
|
||||
const state = new UserRelatedState(osmConnection);
|
||||
const t = Translations.t.index;
|
||||
let userLanguages = osmConnection.userDetails.map(ud => ud.languages);
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col m-4">
|
||||
<div class="self-end">
|
||||
<LanguagePicker assignTo={state.language} availableLanguages={t.title.SupportedLanguages()}
|
||||
preferredLanguages={userLanguages} />
|
||||
</div>
|
||||
|
||||
<div class="flex mt-4">
|
||||
|
||||
<div class="flex-none m-3">
|
||||
<Logo alt="MapComplete Logo" class="w-12 h-12 sm:h-24 sm:w-24" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<h1 class="tracking-tight font-extrabold md:text-6xl m-0">
|
||||
<Tr t={t.title} />
|
||||
</h1>
|
||||
<Tr cls="my-4 mr-4 text-base font-semibold sm:text-lg md:mt-5 md:text-xl lg:mx-0"
|
||||
t={Translations.t.index.intro} />
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ToSvelte construct={new MoreScreen(state, true)} />
|
||||
|
||||
<LoginToggle state={state}>
|
||||
<div slot="not-logged-in">
|
||||
<button class="w-full" on:click={() => osmConnection.AttemptLogin()}>
|
||||
<Login class="w-6 h-6 mr-2 "/>
|
||||
<Tr t={Translations.t.index.logIn} />
|
||||
</button>
|
||||
</div>
|
||||
<a class="w-full h-fit button" href={window.location.protocol + "//" + window.location.host + "/studio.html"}>
|
||||
<Pencil class="w-6 h-6 mr-2" />
|
||||
<Tr t={ Translations.t.general.morescreen.createYourOwnTheme} />
|
||||
</a>
|
||||
</LoginToggle>
|
||||
|
||||
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro}/>
|
||||
<div class="subtle self-end mb-16">
|
||||
v{Constants.vNumber}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
import UserRelatedState from "../Logic/State/UserRelatedState"
|
||||
import { FixedUiElement } from "./Base/FixedUiElement"
|
||||
import Combine from "./Base/Combine"
|
||||
import MoreScreen from "./BigComponents/MoreScreen"
|
||||
import Translations from "./i18n/Translations"
|
||||
import Constants from "../Models/Constants"
|
||||
import LanguagePicker from "./LanguagePicker"
|
||||
import IndexText from "./BigComponents/IndexText"
|
||||
import { LoginToggle } from "./Popup/LoginButton"
|
||||
import { ImmutableStore } from "../Logic/UIEventSource"
|
||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters"
|
||||
import { OsmConnectionFeatureSwitches } from "../Logic/State/FeatureSwitchState"
|
||||
import { SubtleButton } from "./Base/SubtleButton"
|
||||
import Svg from "../Svg"
|
||||
import Link from "./Base/Link"
|
||||
|
||||
export default class AllThemesGui {
|
||||
setup() {
|
||||
try {
|
||||
const featureSwitches = new OsmConnectionFeatureSwitches()
|
||||
const osmConnection = new OsmConnection({
|
||||
fakeUser: featureSwitches.featureSwitchFakeUser.data,
|
||||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
),
|
||||
})
|
||||
const state = new UserRelatedState(osmConnection)
|
||||
const intro = new Combine([
|
||||
new LanguagePicker(
|
||||
Translations.t.index.title.SupportedLanguages(),
|
||||
state.language
|
||||
).SetClass("flex absolute top-2 right-3"),
|
||||
new IndexText(),
|
||||
])
|
||||
new Combine([
|
||||
intro,
|
||||
new MoreScreen(state, true),
|
||||
new LoginToggle(
|
||||
new Link(
|
||||
new Combine([
|
||||
Svg.pencil_svg().SetClass("w-6 h-6 mr-2"),
|
||||
Translations.t.general.morescreen.createYourOwnTheme,
|
||||
]).SetClass("flex p-2"),
|
||||
window.location.protocol + "//" + window.location.host + "/studio.html"
|
||||
).SetClass("w-full h-fit button"),
|
||||
Translations.t.index.logIn,
|
||||
{
|
||||
osmConnection,
|
||||
featureSwitchUserbadge: new ImmutableStore(true),
|
||||
}
|
||||
).SetClass("flex justify-center w-full"),
|
||||
Translations.t.general.aboutMapComplete.intro.SetClass("link-underline"),
|
||||
new FixedUiElement("v" + Constants.vNumber).SetClass("block"),
|
||||
])
|
||||
.SetClass("block m-5 lg:w-3/4 lg:ml-40")
|
||||
.AttachTo("main")
|
||||
} catch (e) {
|
||||
console.error(">>>> CRITICAL", e)
|
||||
new FixedUiElement(
|
||||
"Seems like no layers are compiled - check the output of `npm run generate:layeroverview`. Is this visible online? Contact pietervdvn immediately!"
|
||||
)
|
||||
.SetClass("alert")
|
||||
.AttachTo("main")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
import { Store } from "../../Logic/UIEventSource"
|
||||
import { onDestroy } from "svelte"
|
||||
import Hand from "../../assets/svg/Hand.svelte";
|
||||
|
||||
let mainElem: HTMLElement
|
||||
export let hideSignal: Store<any>
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
|
||||
<div bind:this={mainElem} class="pointer-events-none absolute bottom-0 right-0 h-full w-full">
|
||||
<div id="hand-container">
|
||||
<img src="./assets/svg/hand.svg" />
|
||||
<Hand />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,31 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../Logic/UIEventSource.js"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource.js";
|
||||
|
||||
/**
|
||||
* For some stupid reason, it is very hard to bind inputs
|
||||
*/
|
||||
export let value: UIEventSource<number>
|
||||
let i: number = value.data
|
||||
$: value.setData(i)
|
||||
export let value: UIEventSource<any>
|
||||
let i: any = value.data
|
||||
let htmlElement : HTMLSelectElement
|
||||
function selectAppropriateValue(){
|
||||
if(!htmlElement){
|
||||
return;
|
||||
}
|
||||
const v = value.data
|
||||
for (let option of htmlElement.getElementsByTagName("option")) {
|
||||
if(option.value === v){
|
||||
option.selected = true
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
value.addCallbackD(() => selectAppropriateValue())
|
||||
$: {
|
||||
if(htmlElement){
|
||||
selectAppropriateValue()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<select bind:value={i}>
|
||||
<select bind:this={htmlElement} on:change={(e) => {value.setData(e.srcElement.value)}}>
|
||||
<slot />
|
||||
</select>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import Tr from "./Tr.svelte"
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import { ImmutableStore, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import Invalid from "../../assets/svg/Invalid.svelte";
|
||||
|
||||
export let state: {
|
||||
osmConnection: OsmConnection
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
</slot>
|
||||
{:else if $loadingStatus === "error"}
|
||||
<div class="alert max-w-64 flex items-center">
|
||||
<img src="./assets/svg/invalid.svg" class="m-2 h-8 w-8 shrink-0" />
|
||||
<Invalid class="m-2 h-8 w-8 shrink-0" />
|
||||
<Tr t={offlineModes[$apiState]} />
|
||||
</div>
|
||||
{:else if $loadingStatus === "logged-in"}
|
||||
|
|
|
|||
15
src/UI/Base/LogoutButton.svelte
Normal file
15
src/UI/Base/LogoutButton.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection";
|
||||
import Logout from "../../assets/svg/Logout.svelte";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "./Tr.svelte";
|
||||
|
||||
export let osmConnection: OsmConnection
|
||||
</script>
|
||||
|
||||
<button on:click={() => {
|
||||
state.osmConnection.LogOut()
|
||||
}}>
|
||||
<Logout class="w-6 h-6"/>
|
||||
<Tr t={Translations.t.general.logout}/>
|
||||
</button>
|
||||
48
src/UI/Base/OpenJosm.svelte
Normal file
48
src/UI/Base/OpenJosm.svelte
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "./Tr.svelte";
|
||||
import Josm_logo from "../../assets/svg/Josm_logo.svelte";
|
||||
import Constants from "../../Models/Constants";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
|
||||
export let state : SpecialVisualizationState
|
||||
const t = Translations.t.general.attribution;
|
||||
const josmState = new UIEventSource<"OK" | string>(undefined);
|
||||
// Reset after 15s
|
||||
josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined));
|
||||
|
||||
const showButton = state.osmConnection.userDetails.map(
|
||||
(ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible
|
||||
);
|
||||
|
||||
function openJosm() {
|
||||
const bbox = state.mapProperties. bounds.data;
|
||||
if (bbox === undefined) {
|
||||
return;
|
||||
}
|
||||
const top = bbox.getNorth();
|
||||
const bottom = bbox.getSouth();
|
||||
const right = bbox.getEast();
|
||||
const left = bbox.getWest();
|
||||
const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`;
|
||||
Utils.download(josmLink)
|
||||
.then((answer) => josmState.setData(answer.replace(/\n/g, "").trim()))
|
||||
.catch(() => josmState.setData("ERROR"));
|
||||
}
|
||||
|
||||
</script>
|
||||
{#if $showButton}
|
||||
{#if $josmState === undefined}
|
||||
<!-- empty -->
|
||||
{:else if state === "OK"}
|
||||
<Tr cls="thanks" t={t.josmOpened} />
|
||||
{:else}
|
||||
<Tr cls="alert" t={t.josmNotOpened} />
|
||||
{/if}
|
||||
|
||||
<button class="flex items-center" on:click={openJosm}>
|
||||
<Josm_logo class="h-12 w-12 p-2 pr-4" />
|
||||
<Tr t={t.editJosm} />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import ToSvelte from "./ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import Share from "../../assets/svg/Share.svelte";
|
||||
|
||||
export let generateShareData: () => {
|
||||
text: string
|
||||
|
|
@ -25,6 +26,6 @@
|
|||
|
||||
<button on:click={share} class="secondary m-0 h-8 w-8 p-0">
|
||||
<slot name="content">
|
||||
<ToSvelte construct={Svg.share_svg().SetClass("w-7 h-7 p-1")} />
|
||||
<Share class="w-7 h-7 p-1"/>
|
||||
</slot>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ export default class SvelteUIElement<
|
|||
private readonly _events: Events
|
||||
private readonly _slots: Slots
|
||||
|
||||
constructor(svelteElement, props: Props, events?: Events, slots?: Slots) {
|
||||
constructor(svelteElement, props?: Props, events?: Events, slots?: Slots) {
|
||||
super()
|
||||
this._svelteComponent = svelteElement
|
||||
this._props = props
|
||||
this._props = props ?? <Props>{}
|
||||
this._events = events
|
||||
this._slots = slots
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import Locale from "../i18n/Locale"
|
||||
import LinkToWeblate from "./LinkToWeblate"
|
||||
import Translate from "../../assets/svg/Translate.svelte";
|
||||
|
||||
/**
|
||||
* Shows a small icon which will open up weblate; a contributor can translate the item for 'context' there
|
||||
|
|
@ -19,7 +20,7 @@
|
|||
target="_blank"
|
||||
class="weblate-link mx-1"
|
||||
>
|
||||
<img src="./assets/svg/translate.svg" class="font-gray" />
|
||||
<Translate class="font-gray" />
|
||||
</a>
|
||||
{:else if $linkToWeblate}
|
||||
<a
|
||||
|
|
@ -27,7 +28,7 @@
|
|||
class="weblate-link hidden-on-mobile mx-1"
|
||||
target="_blank"
|
||||
>
|
||||
<img src="./assets/svg/translate.svg" class="font-gray inline-block" />
|
||||
<Translate class="font-gray inline-block" />
|
||||
</a>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -4,25 +4,7 @@ import { FixedUiElement } from "../Base/FixedUiElement"
|
|||
|
||||
export default class IndexText extends Combine {
|
||||
constructor() {
|
||||
super([
|
||||
new FixedUiElement(
|
||||
`<img class="w-12 h-12 sm:h-24 sm:w-24" src="./assets/svg/logo.svg" alt="MapComplete Logo">`
|
||||
).SetClass("flex-none m-3"),
|
||||
|
||||
new Combine([
|
||||
Translations.t.index.title.SetClass(
|
||||
"text-2xl tracking-tight font-extrabold text-gray-900 sm:text-5xl md:text-6xl block text-gray-800 xl:inline"
|
||||
),
|
||||
|
||||
Translations.t.index.intro.SetClass(
|
||||
"mt-3 text-base font-semibold text-gray-500 sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"
|
||||
),
|
||||
|
||||
Translations.t.index.pickTheme.SetClass(
|
||||
"mt-3 text-base sm:mt-5 sm:text-lg sm:max-w-xl sm:mx-auto md:mt-5 md:text-xl lg:mx-0"
|
||||
),
|
||||
]).SetClass("flex flex-col sm:text-center lg:text-left m-1 mt-2 md:m-2 md:mt-4"),
|
||||
])
|
||||
super([])
|
||||
|
||||
this.SetClass("flex flex-row")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { Store } from "../../Logic/UIEventSource"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Mapillary_black from "../../assets/svg/Mapillary_black.svelte";
|
||||
|
||||
/*
|
||||
A subtleButton which opens mapillary in a new tab at the current location
|
||||
|
|
@ -21,7 +22,7 @@
|
|||
</script>
|
||||
|
||||
<a class="button flex items-center" href={mapillaryLink} target="_blank">
|
||||
<ToSvelte construct={() => Svg.mapillary_black_svg().SetClass("w-12 h-12 m-2 mr-4 shrink-0")} />
|
||||
<Mapillary_black class="w-12 h-12 m-2 mr-4 shrink-0"/>
|
||||
<div class="flex flex-col">
|
||||
<Tr t={Translations.t.general.attribution.openMapillary} />
|
||||
<Tr cls="subtle" t={Translations.t.general.attribution.mapillaryHelp} />
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { Utils } from "../../Utils"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import Move_arrows from "../../assets/svg/Move_arrows.svelte";
|
||||
|
||||
/**
|
||||
* An advanced location input, which has support to:
|
||||
|
|
@ -125,6 +126,6 @@
|
|||
maxDistanceInMeters="50"
|
||||
>
|
||||
<slot name="image" slot="image">
|
||||
<img class="h-full max-h-24" src="./assets/svg/move-arrows.svg" />
|
||||
<Move_arrows class="h-full max-h-24" />
|
||||
</slot>
|
||||
</LocationInput>
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
import Combine from "../Base/Combine"
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import Translations from "../i18n/Translations"
|
||||
import { VariableUiElement } from "../Base/VariableUIElement"
|
||||
import Toggle from "../Input/Toggle"
|
||||
import { SubtleButton } from "../Base/SubtleButton"
|
||||
import Svg from "../../Svg"
|
||||
import { Utils } from "../../Utils"
|
||||
import Constants from "../../Models/Constants"
|
||||
|
||||
export class OpenJosm extends Combine {
|
||||
public static readonly needsUrls = ["http://127.0.0.1:8111/load_and_zoom"]
|
||||
constructor(osmConnection: OsmConnection, bounds: Store<BBox>, iconStyle?: string) {
|
||||
const t = Translations.t.general.attribution
|
||||
|
||||
const josmState = new UIEventSource<string>(undefined)
|
||||
// Reset after 15s
|
||||
josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined))
|
||||
|
||||
const stateIndication = new VariableUiElement(
|
||||
josmState.map((state) => {
|
||||
if (state === undefined) {
|
||||
return undefined
|
||||
}
|
||||
state = state.toUpperCase()
|
||||
if (state === "OK") {
|
||||
return t.josmOpened.SetClass("thanks")
|
||||
}
|
||||
return t.josmNotOpened.SetClass("alert")
|
||||
})
|
||||
)
|
||||
|
||||
const toggle = new Toggle(
|
||||
new SubtleButton(Svg.josm_logo_svg().SetStyle(iconStyle), t.editJosm)
|
||||
.onClick(() => {
|
||||
const bbox = bounds.data
|
||||
if (bbox === undefined) {
|
||||
return
|
||||
}
|
||||
const top = bbox.getNorth()
|
||||
const bottom = bbox.getSouth()
|
||||
const right = bbox.getEast()
|
||||
const left = bbox.getWest()
|
||||
const josmLink = `http://127.0.0.1:8111/load_and_zoom?left=${left}&right=${right}&top=${top}&bottom=${bottom}`
|
||||
Utils.download(josmLink)
|
||||
.then((answer) => josmState.setData(answer.replace(/\n/g, "").trim()))
|
||||
.catch(() => josmState.setData("ERROR"))
|
||||
})
|
||||
.SetClass("w-full"),
|
||||
undefined,
|
||||
osmConnection.userDetails.map(
|
||||
(ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible
|
||||
)
|
||||
)
|
||||
|
||||
super([stateIndication, toggle])
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,21 @@
|
|||
<script lang="ts">
|
||||
import Translations from "../i18n/Translations"
|
||||
import Svg from "../../Svg"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import NextButton from "../Base/NextButton.svelte"
|
||||
import Geosearch from "./Geosearch.svelte"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { Utils } from "../../Utils"
|
||||
import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState"
|
||||
import { GeoLocationState } from "../../Logic/State/GeoLocationState"
|
||||
import If from "../Base/If.svelte"
|
||||
import { ExclamationTriangleIcon } from "@babeard/svelte-heroicons/mini"
|
||||
import type { Readable } from "svelte/store"
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import NextButton from "../Base/NextButton.svelte";
|
||||
import Geosearch from "./Geosearch.svelte";
|
||||
import ThemeViewState from "../../Models/ThemeViewState";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
import { twJoin } from "tailwind-merge";
|
||||
import { Utils } from "../../Utils";
|
||||
import type { GeolocationPermissionState } from "../../Logic/State/GeoLocationState";
|
||||
import { GeoLocationState } from "../../Logic/State/GeoLocationState";
|
||||
import If from "../Base/If.svelte";
|
||||
import { ExclamationTriangleIcon } from "@babeard/svelte-heroicons/mini";
|
||||
import type { Readable } from "svelte/store";
|
||||
import Add from "../../assets/svg/Add.svelte";
|
||||
import Location_refused from "../../assets/svg/Location_refused.svelte";
|
||||
import Crosshair from "../../assets/svg/Crosshair.svelte";
|
||||
|
||||
/**
|
||||
* The theme introduction panel
|
||||
|
|
@ -70,7 +71,7 @@
|
|||
<If condition={state.featureSwitches.featureSwitchGeolocation}>
|
||||
{#if $currentGPSLocation !== undefined || $geopermission === "prompt"}
|
||||
<button class="flex w-full items-center gap-x-2" on:click={jumpToCurrentLocation}>
|
||||
<ToSvelte construct={Svg.crosshair_svg().SetClass("w-8 h-8")} />
|
||||
<Crosshair class="w-8 h-8"/>
|
||||
<Tr t={Translations.t.general.openTheMapAtGeolocation} />
|
||||
</button>
|
||||
<!-- No geolocation granted - we don't show the button -->
|
||||
|
|
@ -80,25 +81,17 @@
|
|||
on:click={jumpToCurrentLocation}
|
||||
>
|
||||
<!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
|
||||
<ToSvelte
|
||||
construct={Svg.crosshair_svg()
|
||||
.SetClass("w-8 h-8")
|
||||
.SetStyle("animation: 3s linear 0s infinite normal none running spin;")}
|
||||
/>
|
||||
<Crosshair class="w-8 h-8" style="animation: 3s linear 0s infinite normal none running spin;" />
|
||||
<Tr t={Translations.t.general.waitingForGeopermission} />
|
||||
</button>
|
||||
{:else if $geopermission === "denied"}
|
||||
<button class="disabled flex w-full items-center gap-x-2">
|
||||
<ToSvelte construct={Svg.location_refused_svg().SetClass("w-8 h-8")} />
|
||||
<Location_refused class="w-8 h-8"/>
|
||||
<Tr t={Translations.t.general.geopermissionDenied} />
|
||||
</button>
|
||||
{:else}
|
||||
<button class="disabled flex w-full items-center gap-x-2">
|
||||
<ToSvelte
|
||||
construct={Svg.crosshair_svg()
|
||||
.SetClass("w-8 h-8")
|
||||
.SetStyle("animation: 3s linear 0s infinite normal none running spin;")}
|
||||
/>
|
||||
<Crosshair class="w-8 h-8" style="animation: 3s linear 0s infinite normal none running spin;" />
|
||||
<Tr t={Translations.t.general.waitingForLocation} />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
@ -156,7 +149,7 @@
|
|||
<div class="links-as-button links-w-full m-2 flex flex-col gap-y-1">
|
||||
<!-- bottom buttons, a bit hidden away: switch layout -->
|
||||
<a class="flex" href={Utils.HomepageLink()}>
|
||||
<img class="h-6 w-6" src="./assets/svg/add.svg" />
|
||||
<Add class="h-6 w-6"/>
|
||||
<Tr t={Translations.t.general.backToIndex} />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
|||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import { LoginToggle } from "../Popup/LoginButton"
|
||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||
import Upload from "../../assets/svg/Upload.svelte"
|
||||
|
||||
export default class UploadTraceToOsmUI extends LoginToggle {
|
||||
constructor(
|
||||
|
|
@ -83,7 +85,7 @@ export default class UploadTraceToOsmUI extends LoginToggle {
|
|||
clicked.setData(false)
|
||||
})
|
||||
.SetClass(""),
|
||||
new SubtleButton(Svg.upload_svg(), t.confirm).OnClickWithLoading(
|
||||
new SubtleButton(new SvelteUIElement(Upload, {}), t.confirm).OnClickWithLoading(
|
||||
t.uploading,
|
||||
async () => {
|
||||
const titleStr = UploadTraceToOsmUI.createDefault(
|
||||
|
|
@ -119,7 +121,7 @@ export default class UploadTraceToOsmUI extends LoginToggle {
|
|||
]).SetClass("flex p-2 rounded-xl border-2 subtle-border items-center"),
|
||||
new Toggle(
|
||||
confirmPanel,
|
||||
new SubtleButton(Svg.upload_svg(), t.title).onClick(() =>
|
||||
new SubtleButton(new SvelteUIElement(Upload), t.title).onClick(() =>
|
||||
clicked.setData(true)
|
||||
),
|
||||
clicked
|
||||
|
|
|
|||
|
|
@ -3,16 +3,15 @@
|
|||
* Shows an 'upload'-button which will start the upload for this feature
|
||||
*/
|
||||
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
|
||||
import type { OsmTags } from "../../Models/OsmFeature"
|
||||
import LoginToggle from "../Base/LoginToggle.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import UploadingImageCounter from "./UploadingImageCounter.svelte"
|
||||
import FileSelector from "../Base/FileSelector.svelte"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource";
|
||||
import type { OsmTags } from "../../Models/OsmFeature";
|
||||
import LoginToggle from "../Base/LoginToggle.svelte";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import UploadingImageCounter from "./UploadingImageCounter.svelte";
|
||||
import FileSelector from "../Base/FileSelector.svelte";
|
||||
import Camera_plus from "../../assets/svg/Camera_plus.svelte";
|
||||
|
||||
export let state: SpecialVisualizationState
|
||||
|
||||
|
|
@ -58,7 +57,7 @@
|
|||
{#if image !== undefined}
|
||||
<img src={image} />
|
||||
{:else}
|
||||
<ToSvelte construct={Svg.camera_plus_svg().SetClass("block w-12 h-12 p-1 text-4xl ")} />
|
||||
<Camera_plus class="block w-12 h-12 p-1 text-4xl"/>
|
||||
{/if}
|
||||
{#if labelText}
|
||||
{labelText}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
import MaplibreMap from "../../Map/MaplibreMap.svelte"
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte"
|
||||
import Svg from "../../../Svg.js"
|
||||
import Direction_stroke from "../../../assets/svg/Direction_stroke.svelte";
|
||||
|
||||
/**
|
||||
* A visualisation to pick a direction on a map background.
|
||||
|
|
@ -67,6 +68,6 @@
|
|||
</div>
|
||||
|
||||
<div bind:this={directionElem} class="absolute top-0 left-0 h-full w-full">
|
||||
<ToSvelte construct={Svg.direction_stroke_svg} />
|
||||
<Direction_stroke/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
import * as turf from "@turf/turf"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import Move_arrows from "../../../assets/svg/Move_arrows.svelte";
|
||||
|
||||
/**
|
||||
* A visualisation to pick a location on a map background
|
||||
|
|
@ -90,7 +91,7 @@
|
|||
class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center p-8 opacity-50"
|
||||
>
|
||||
<slot name="image">
|
||||
<img class="h-full max-h-24" src="./assets/svg/move-arrows.svg" />
|
||||
<Move_arrows class="h-full max-h-24"/>
|
||||
</slot>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
66
src/UI/InputElement/LanguagePicker.svelte
Normal file
66
src/UI/InputElement/LanguagePicker.svelte
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<script lang="ts">
|
||||
// Languages in the language itself
|
||||
import native from "../../assets/language_native.json";
|
||||
// Translated languages
|
||||
import language_translations from "../../assets/language_translations.json";
|
||||
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import Locale from "../i18n/Locale";
|
||||
import { LanguageIcon } from "@babeard/svelte-heroicons/solid";
|
||||
import Dropdown from "../Base/Dropdown.svelte";
|
||||
|
||||
/**
|
||||
* Languages one can choose from
|
||||
* Defaults to _all_ languages known by MapComplete
|
||||
*/
|
||||
export let availableLanguages: string[] = Object.keys(native);
|
||||
/**
|
||||
* EventStore to assign to, defaults to 'Locale.langauge'
|
||||
*/
|
||||
export let assignTo: UIEventSource<string> = Locale.language;
|
||||
export let preferredLanguages: UIEventSource<string[]> = undefined;
|
||||
let preferredFiltered: string[] = undefined;
|
||||
preferredLanguages?.addCallbackAndRunD(preferredLanguages => {
|
||||
let lng = navigator.language;
|
||||
if (lng === "en-US") {
|
||||
lng = "en";
|
||||
}
|
||||
if (preferredLanguages?.indexOf(lng) < 0) {
|
||||
preferredLanguages?.push(lng);
|
||||
}
|
||||
preferredFiltered = preferredLanguages?.filter(l => availableLanguages.indexOf(l) >= 0);
|
||||
});
|
||||
|
||||
let current = Locale.language;
|
||||
|
||||
</script>
|
||||
|
||||
{#if availableLanguages?.length > 1}
|
||||
<form class="flex items-center">
|
||||
|
||||
<LanguageIcon class="h-4 w-4 mr-1" />
|
||||
<Dropdown value={assignTo}>
|
||||
{#if preferredFiltered}
|
||||
{#each preferredFiltered as language}
|
||||
<option value={language} class="font-bold">
|
||||
{native[language] ?? ""}
|
||||
{#if language !== $current}
|
||||
({language_translations[language]?.[$current] ?? language})
|
||||
{/if}
|
||||
</option>
|
||||
{/each}
|
||||
<option disabled></option>
|
||||
{/if}
|
||||
|
||||
{#each availableLanguages as language}
|
||||
<option value={language} class="font-bold">
|
||||
{native[language] ?? ""}
|
||||
{#if language !== $current}
|
||||
({(language_translations[language]?.[$current] + " - " + language) ?? language})
|
||||
{/if}
|
||||
</option>
|
||||
{/each}
|
||||
</Dropdown>
|
||||
</form>
|
||||
|
||||
{/if}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import { DropDown } from "./Input/DropDown"
|
||||
import Locale from "./i18n/Locale"
|
||||
import BaseUIElement from "./BaseUIElement"
|
||||
import native from "../assets/language_native.json"
|
||||
import language_translations from "../assets/language_translations.json"
|
||||
import { Translation } from "./i18n/Translation"
|
||||
import Lazy from "./Base/Lazy"
|
||||
import Toggle from "./Input/Toggle"
|
||||
import LanguageUtils from "../Utils/LanguageUtils"
|
||||
import { UIEventSource } from "../Logic/UIEventSource"
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters"
|
||||
|
||||
export default class LanguagePicker extends Toggle {
|
||||
constructor(languages: string[], assignTo: UIEventSource<string>) {
|
||||
console.log("Constructing a language picker for languages", languages)
|
||||
if (
|
||||
languages === undefined ||
|
||||
languages.length <= 1 ||
|
||||
QueryParameters.wasInitialized("language")
|
||||
) {
|
||||
super(undefined, undefined, undefined)
|
||||
} else {
|
||||
const normalPicker = LanguagePicker.dropdownFor(languages, assignTo ?? Locale.language)
|
||||
const fullPicker = new Lazy(() =>
|
||||
LanguagePicker.dropdownFor(allLanguages, assignTo ?? Locale.language)
|
||||
)
|
||||
super(fullPicker, normalPicker, Locale.showLinkToWeblate)
|
||||
const allLanguages: string[] = LanguageUtils.usedLanguagesSorted
|
||||
}
|
||||
}
|
||||
|
||||
private static dropdownFor(
|
||||
languages: string[],
|
||||
assignTo: UIEventSource<string>
|
||||
): BaseUIElement {
|
||||
return new DropDown(
|
||||
undefined,
|
||||
languages
|
||||
.filter((lang) => lang !== "_context")
|
||||
.map((lang) => {
|
||||
return { value: lang, shown: LanguagePicker.hybrid(lang) }
|
||||
}),
|
||||
assignTo
|
||||
)
|
||||
}
|
||||
|
||||
private static hybrid(lang: string): Translation {
|
||||
const nativeText = native[lang] ?? lang
|
||||
const translation = {}
|
||||
const trans = language_translations[lang]
|
||||
if (trans === undefined) {
|
||||
return new Translation({ "*": nativeText })
|
||||
}
|
||||
for (const key in trans) {
|
||||
if (key.startsWith("_")) {
|
||||
continue
|
||||
}
|
||||
const translationInKey = language_translations[lang][key]
|
||||
if (nativeText.toLowerCase() === translationInKey.toLowerCase()) {
|
||||
translation[key] = nativeText
|
||||
} else {
|
||||
translation[key] = nativeText + " (" + translationInKey + ")"
|
||||
}
|
||||
}
|
||||
return new Translation(translation)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
<script lang="ts">
|
||||
import PointRenderingConfig, { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig"
|
||||
import { Store } from "../../Logic/UIEventSource"
|
||||
import DynamicIcon from "./DynamicIcon.svelte"
|
||||
import { IconConfig } from "../../Models/ThemeConfig/PointRenderingConfig";
|
||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource";
|
||||
import DynamicIcon from "./DynamicIcon.svelte";
|
||||
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig";
|
||||
|
||||
/**
|
||||
* Renders a 'marker', which consists of multiple 'icons'
|
||||
*/
|
||||
export let config: PointRenderingConfig
|
||||
let icons: IconConfig[] = config.marker
|
||||
export let tags: Store<Record<string, string>>
|
||||
let rotation = tags.map((tags) => config.rotation.GetRenderValue(tags).Subs(tags).txt)
|
||||
export let marker: IconConfig[] = config?.marker;
|
||||
export let tags: Store<Record<string, string>>;
|
||||
export let rotation: TagRenderingConfig
|
||||
let _rotation = rotation ? tags.map(tags => rotation.GetRenderValue(tags).Subs(tags).txt) : new ImmutableStore(0);
|
||||
|
||||
</script>
|
||||
|
||||
{#if config !== undefined}
|
||||
<div class="relative h-full w-full" style={`transform: rotate(${$rotation})`}>
|
||||
{#each icons as icon}
|
||||
{#if marker && marker}
|
||||
<div class="relative h-full w-full" style={`transform: rotate(${$_rotation})`}>
|
||||
{#each marker as icon}
|
||||
<DynamicIcon {icon} {tags} />
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
import Teardrop from "../../assets/svg/Teardrop.svelte"
|
||||
import Teardrop_with_hole_green from "../../assets/svg/Teardrop_with_hole_green.svelte"
|
||||
import Triangle from "../../assets/svg/Triangle.svelte"
|
||||
import Brick_wall_square from "../../assets/svg/Brick_wall_square.svelte";
|
||||
import Brick_wall_round from "../../assets/svg/Brick_wall_round.svelte";
|
||||
import Gps_arrow from "../../assets/svg/Gps_arrow.svelte";
|
||||
|
||||
/**
|
||||
* Renders a single icon.
|
||||
|
|
@ -72,6 +75,20 @@
|
|||
<Teardrop_with_hole_green {color} />
|
||||
{:else if icon === "triangle"}
|
||||
<Triangle {color} />
|
||||
{:else if icon === "brick_wall_square"}
|
||||
<Brick_wall_square {color} />
|
||||
{:else if icon === "brick_wall_round"}
|
||||
<Brick_wall_round {color} />
|
||||
{:else if icon === "gps_arrow"}
|
||||
<Gps_arrow {color} />
|
||||
{:else if icon === "checkmark"}
|
||||
<Checkmark {color} />
|
||||
{:else if icon === "help"}
|
||||
<Help {color} />
|
||||
{:else if icon === "close"}
|
||||
<Close {color} />
|
||||
{:else if icon === "invalid"}
|
||||
<Invalid {color} />
|
||||
{:else}
|
||||
<img class="h-full w-full" src={icon} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
import { createEventDispatcher } from "svelte"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte";
|
||||
|
||||
/**
|
||||
* The main entry point for the plantnet wizard
|
||||
|
|
@ -142,9 +143,7 @@
|
|||
</BackButton>
|
||||
{/if}
|
||||
<div class="low-interaction flex self-end rounded-xl p-2">
|
||||
<ToSvelte
|
||||
construct={Svg.plantnet_logo_svg().SetClass("w-8 h-8 p-1 mr-1 bg-white rounded-full")}
|
||||
/>
|
||||
<Plantnet_logo class="w-8 h-8 p-1 mr-1 bg-white rounded-full"/>
|
||||
<Tr t={t.poweredByPlantnet} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,109 +3,110 @@
|
|||
* This component ties together all the steps that are needed to create a new point.
|
||||
* There are many subcomponents which help with that
|
||||
*/
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization"
|
||||
import PresetList from "./PresetList.svelte"
|
||||
import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||
import Tr from "../../Base/Tr.svelte"
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte"
|
||||
import FromHtml from "../../Base/FromHtml.svelte"
|
||||
import Translations from "../../i18n/Translations.js"
|
||||
import TagHint from "../TagHint.svelte"
|
||||
import { And } from "../../../Logic/Tags/And.js"
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte"
|
||||
import Constants from "../../../Models/Constants.js"
|
||||
import FilteredLayer from "../../../Models/FilteredLayer"
|
||||
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
|
||||
import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import LoginButton from "../../Base/LoginButton.svelte"
|
||||
import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte"
|
||||
import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction"
|
||||
import { OsmWay } from "../../../Logic/Osm/OsmObject"
|
||||
import { Tag } from "../../../Logic/Tags/Tag"
|
||||
import type { WayId } from "../../../Models/OsmFeature"
|
||||
import Loading from "../../Base/Loading.svelte"
|
||||
import type { GlobalFilter } from "../../../Models/GlobalFilter"
|
||||
import { onDestroy } from "svelte"
|
||||
import NextButton from "../../Base/NextButton.svelte"
|
||||
import BackButton from "../../Base/BackButton.svelte"
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte"
|
||||
import Svg from "../../../Svg"
|
||||
import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import type { SpecialVisualizationState } from "../../SpecialVisualization";
|
||||
import PresetList from "./PresetList.svelte";
|
||||
import type PresetConfig from "../../../Models/ThemeConfig/PresetConfig";
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
import Tr from "../../Base/Tr.svelte";
|
||||
import SubtleButton from "../../Base/SubtleButton.svelte";
|
||||
import Translations from "../../i18n/Translations.js";
|
||||
import TagHint from "../TagHint.svelte";
|
||||
import { And } from "../../../Logic/Tags/And.js";
|
||||
import LoginToggle from "../../Base/LoginToggle.svelte";
|
||||
import Constants from "../../../Models/Constants.js";
|
||||
import FilteredLayer from "../../../Models/FilteredLayer";
|
||||
import { Store, UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import { EyeIcon, EyeOffIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
import LoginButton from "../../Base/LoginButton.svelte";
|
||||
import NewPointLocationInput from "../../BigComponents/NewPointLocationInput.svelte";
|
||||
import CreateNewNodeAction from "../../../Logic/Osm/Actions/CreateNewNodeAction";
|
||||
import { OsmWay } from "../../../Logic/Osm/OsmObject";
|
||||
import { Tag } from "../../../Logic/Tags/Tag";
|
||||
import type { WayId } from "../../../Models/OsmFeature";
|
||||
import Loading from "../../Base/Loading.svelte";
|
||||
import type { GlobalFilter } from "../../../Models/GlobalFilter";
|
||||
import { onDestroy } from "svelte";
|
||||
import NextButton from "../../Base/NextButton.svelte";
|
||||
import BackButton from "../../Base/BackButton.svelte";
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte";
|
||||
import Svg from "../../../Svg";
|
||||
import OpenBackgroundSelectorButton from "../../BigComponents/OpenBackgroundSelectorButton.svelte";
|
||||
import { twJoin } from "tailwind-merge";
|
||||
import Confirm from "../../../assets/svg/Confirm.svelte";
|
||||
import Close from "../../../assets/svg/Close.svelte";
|
||||
|
||||
export let coordinate: { lon: number; lat: number }
|
||||
export let state: SpecialVisualizationState
|
||||
export let coordinate: { lon: number; lat: number };
|
||||
export let state: SpecialVisualizationState;
|
||||
|
||||
let selectedPreset: {
|
||||
preset: PresetConfig
|
||||
layer: LayerConfig
|
||||
icon: string
|
||||
tags: Record<string, string>
|
||||
} = undefined
|
||||
let checkedOfGlobalFilters: number = 0
|
||||
let confirmedCategory = false
|
||||
} = undefined;
|
||||
let checkedOfGlobalFilters: number = 0;
|
||||
let confirmedCategory = false;
|
||||
$: if (selectedPreset === undefined) {
|
||||
confirmedCategory = false
|
||||
creating = false
|
||||
checkedOfGlobalFilters = 0
|
||||
confirmedCategory = false;
|
||||
creating = false;
|
||||
checkedOfGlobalFilters = 0;
|
||||
}
|
||||
|
||||
let flayer: FilteredLayer = undefined
|
||||
let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined
|
||||
let layerHasFilters: Store<boolean> | undefined = undefined
|
||||
let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters
|
||||
let _globalFilter: GlobalFilter[] = []
|
||||
let flayer: FilteredLayer = undefined;
|
||||
let layerIsDisplayed: UIEventSource<boolean> | undefined = undefined;
|
||||
let layerHasFilters: Store<boolean> | undefined = undefined;
|
||||
let globalFilter: UIEventSource<GlobalFilter[]> = state.layerState.globalFilters;
|
||||
let _globalFilter: GlobalFilter[] = [];
|
||||
onDestroy(
|
||||
globalFilter.addCallbackAndRun((globalFilter) => {
|
||||
console.log("Global filters are", globalFilter)
|
||||
_globalFilter = globalFilter ?? []
|
||||
console.log("Global filters are", globalFilter);
|
||||
_globalFilter = globalFilter ?? [];
|
||||
})
|
||||
)
|
||||
);
|
||||
$: {
|
||||
flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id)
|
||||
layerIsDisplayed = flayer?.isDisplayed
|
||||
layerHasFilters = flayer?.hasFilter
|
||||
flayer = state.layerState.filteredLayers.get(selectedPreset?.layer?.id);
|
||||
layerIsDisplayed = flayer?.isDisplayed;
|
||||
layerHasFilters = flayer?.hasFilter;
|
||||
}
|
||||
const t = Translations.t.general.add
|
||||
const t = Translations.t.general.add;
|
||||
|
||||
const zoom = state.mapProperties.zoom
|
||||
const zoom = state.mapProperties.zoom;
|
||||
|
||||
const isLoading = state.dataIsLoading
|
||||
let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined)
|
||||
let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
const isLoading = state.dataIsLoading;
|
||||
let preciseCoordinate: UIEventSource<{ lon: number; lat: number }> = new UIEventSource(undefined);
|
||||
let snappedToObject: UIEventSource<string> = new UIEventSource<string>(undefined);
|
||||
|
||||
// Small helper variable: if the map is tapped, we should let the 'Next'-button grab some attention as users have to click _that_ to continue, not the map
|
||||
let preciseInputIsTapped = false
|
||||
let preciseInputIsTapped = false;
|
||||
|
||||
let creating = false
|
||||
let creating = false;
|
||||
|
||||
/**
|
||||
* Call when the user should restart the flow by clicking on the map, e.g. because they disabled filters.
|
||||
* Will delete the lastclick-location
|
||||
*/
|
||||
function abort() {
|
||||
state.selectedElement.setData(undefined)
|
||||
state.selectedElement.setData(undefined);
|
||||
// When aborted, we force the contributors to place the pin _again_
|
||||
// This is because there might be a nearby object that was disabled; this forces them to re-evaluate the map
|
||||
state.lastClickObject.features.setData([])
|
||||
preciseInputIsTapped = false
|
||||
state.lastClickObject.features.setData([]);
|
||||
preciseInputIsTapped = false;
|
||||
}
|
||||
|
||||
async function confirm() {
|
||||
creating = true
|
||||
const location: { lon: number; lat: number } = preciseCoordinate.data
|
||||
const snapTo: WayId | undefined = <WayId>snappedToObject.data
|
||||
creating = true;
|
||||
const location: { lon: number; lat: number } = preciseCoordinate.data;
|
||||
const snapTo: WayId | undefined = <WayId>snappedToObject.data;
|
||||
const tags: Tag[] = selectedPreset.preset.tags.concat(
|
||||
..._globalFilter.map((f) => f?.onNewPoint?.tags ?? [])
|
||||
)
|
||||
console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags)
|
||||
);
|
||||
console.log("Creating new point at", location, "snapped to", snapTo, "with tags", tags);
|
||||
|
||||
let snapToWay: undefined | OsmWay = undefined
|
||||
let snapToWay: undefined | OsmWay = undefined;
|
||||
if (snapTo !== undefined && snapTo !== null) {
|
||||
const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0)
|
||||
const downloaded = await state.osmObjectDownloader.DownloadObjectAsync(snapTo, 0);
|
||||
if (downloaded !== "deleted") {
|
||||
snapToWay = downloaded
|
||||
snapToWay = downloaded;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -113,44 +114,44 @@
|
|||
theme: state.layout?.id ?? "unkown",
|
||||
changeType: "create",
|
||||
snapOnto: snapToWay,
|
||||
reusePointWithinMeters: 1,
|
||||
})
|
||||
await state.changes.applyAction(newElementAction)
|
||||
state.newFeatures.features.ping()
|
||||
reusePointWithinMeters: 1
|
||||
});
|
||||
await state.changes.applyAction(newElementAction);
|
||||
state.newFeatures.features.ping();
|
||||
// The 'changes' should have created a new point, which added this into the 'featureProperties'
|
||||
const newId = newElementAction.newElementId
|
||||
console.log("Applied pending changes, fetching store for", newId)
|
||||
const tagsStore = state.featureProperties.getStore(newId)
|
||||
const newId = newElementAction.newElementId;
|
||||
console.log("Applied pending changes, fetching store for", newId);
|
||||
const tagsStore = state.featureProperties.getStore(newId);
|
||||
if (!tagsStore) {
|
||||
console.error("Bug: no tagsStore found for", newId)
|
||||
console.error("Bug: no tagsStore found for", newId);
|
||||
}
|
||||
{
|
||||
// Set some metainfo
|
||||
const properties = tagsStore.data
|
||||
const properties = tagsStore.data;
|
||||
if (snapTo) {
|
||||
// metatags (starting with underscore) are not uploaded, so we can safely mark this
|
||||
delete properties["_referencing_ways"]
|
||||
properties["_referencing_ways"] = `["${snapTo}"]`
|
||||
delete properties["_referencing_ways"];
|
||||
properties["_referencing_ways"] = `["${snapTo}"]`;
|
||||
}
|
||||
properties["_backend"] = state.osmConnection.Backend()
|
||||
properties["_last_edit:timestamp"] = new Date().toISOString()
|
||||
const userdetails = state.osmConnection.userDetails.data
|
||||
properties["_last_edit:contributor"] = userdetails.name
|
||||
properties["_last_edit:uid"] = "" + userdetails.uid
|
||||
tagsStore.ping()
|
||||
properties["_backend"] = state.osmConnection.Backend();
|
||||
properties["_last_edit:timestamp"] = new Date().toISOString();
|
||||
const userdetails = state.osmConnection.userDetails.data;
|
||||
properties["_last_edit:contributor"] = userdetails.name;
|
||||
properties["_last_edit:uid"] = "" + userdetails.uid;
|
||||
tagsStore.ping();
|
||||
}
|
||||
const feature = state.indexedFeatures.featuresById.data.get(newId)
|
||||
console.log("Selecting feature", feature, "and opening their popup")
|
||||
abort()
|
||||
state.selectedLayer.setData(selectedPreset.layer)
|
||||
state.selectedElement.setData(feature)
|
||||
tagsStore.ping()
|
||||
const feature = state.indexedFeatures.featuresById.data.get(newId);
|
||||
console.log("Selecting feature", feature, "and opening their popup");
|
||||
abort();
|
||||
state.selectedLayer.setData(selectedPreset.layer);
|
||||
state.selectedElement.setData(feature);
|
||||
tagsStore.ping();
|
||||
}
|
||||
|
||||
function confirmSync() {
|
||||
confirm()
|
||||
.then((_) => console.debug("New point successfully handled"))
|
||||
.catch((e) => console.error("Handling the new point went wrong due to", e))
|
||||
.catch((e) => console.error("Handling the new point went wrong due to", e));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -285,7 +286,7 @@
|
|||
<NextButton on:click={() => (confirmedCategory = true)} clss="primary w-full">
|
||||
<div slot="image" class="relative">
|
||||
<ToSvelte construct={selectedPreset.icon} />
|
||||
<img class="absolute bottom-0 right-0 h-4 w-4" src="./assets/svg/confirm.svg" />
|
||||
<Confirm class="absolute bottom-0 right-0 h-4 w-4" />
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<Tr t={selectedPreset.text} />
|
||||
|
|
@ -299,11 +300,7 @@
|
|||
checkedOfGlobalFilters = checkedOfGlobalFilters + 1
|
||||
}}
|
||||
>
|
||||
<img
|
||||
slot="image"
|
||||
src={_globalFilter[checkedOfGlobalFilters].onNewPoint?.icon ?? "./assets/svg/confirm.svg"}
|
||||
class="h-12 w-12"
|
||||
/>
|
||||
<Confirm slot="image" class="h-12 w-12" />
|
||||
<Tr
|
||||
slot="message"
|
||||
t={_globalFilter[checkedOfGlobalFilters].onNewPoint?.confirmAddNew.Subs({
|
||||
|
|
@ -317,7 +314,7 @@
|
|||
abort()
|
||||
}}
|
||||
>
|
||||
<img slot="image" src="./assets/svg/close.svg" class="h-8 w-8" />
|
||||
<Close slot="image" class="h-8 w-8" />
|
||||
<Tr slot="message" t={Translations.t.general.cancel} />
|
||||
</SubtleButton>
|
||||
{:else if !creating}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
import Lazy from "../Base/Lazy"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { VariableUiElement } from "../Base/VariableUIElement";
|
||||
|
||||
//Svelte props
|
||||
export let tags: UIEventSource<any>
|
||||
|
|
@ -54,13 +55,7 @@
|
|||
return parts
|
||||
})
|
||||
|
||||
let _allTags = []
|
||||
onDestroy(
|
||||
allTags.addCallbackAndRunD((allTags) => {
|
||||
_allTags = allTags
|
||||
})
|
||||
)
|
||||
const tagsTable = new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all")
|
||||
const tagsTable = new VariableUiElement(allTags.mapD(_allTags => new Table(["Key", "Value"], _allTags).SetClass("zebra-table break-all")))
|
||||
</script>
|
||||
|
||||
<section>
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
import NewPointLocationInput from "../BigComponents/NewPointLocationInput.svelte"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import Layers from "../../assets/svg/Layers.svelte";
|
||||
import AddSmall from "../../assets/svg/AddSmall.svelte";
|
||||
|
||||
export let coordinate: UIEventSource<{ lon: number; lat: number }>
|
||||
export let state: SpecialVisualizationState
|
||||
|
|
@ -97,7 +99,7 @@
|
|||
<Tr t={Translations.t.notes.noteLayerHasFilters} />
|
||||
</div>
|
||||
<SubtleButton on:click={() => notelayer.disableAllFilters()}>
|
||||
<img slot="image" src="./assets/svg/filter.svg" class="mr-4 h-8 w-8" />
|
||||
<Layers class="mr-4 h-8 w-8"/>
|
||||
<Tr slot="message" t={Translations.t.notes.disableAllNoteFilters} />
|
||||
</SubtleButton>
|
||||
</div>
|
||||
|
|
@ -126,7 +128,7 @@
|
|||
|
||||
{#if $comment?.length >= 3}
|
||||
<SubtleButton on:click={uploadNote}>
|
||||
<img slot="image" src="./assets/svg/addSmall.svg" class="mr-4 h-8 w-8" />
|
||||
<AddSmall slot="image" class="mr-4 h-8 w-8" />
|
||||
<Tr slot="message" t={Translations.t.notes.createNote} />
|
||||
</SubtleButton>
|
||||
{:else}
|
||||
|
|
@ -143,7 +145,7 @@
|
|||
<Tr t={Translations.t.notes.noteLayerNotEnabled} />
|
||||
</div>
|
||||
<SubtleButton on:click={enableNoteLayer}>
|
||||
<img slot="image" src="./assets/svg/layers.svg" class="mr-4 h-8 w-8" />
|
||||
<Layers slot="image" class="mr-4 h-8 w-8" />
|
||||
<Tr slot="message" t={Translations.t.notes.noteLayerDoEnable} />
|
||||
</SubtleButton>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
|
||||
import exp from "constants"
|
||||
import Camera_plus from "../../assets/svg/Camera_plus.svelte";
|
||||
|
||||
export let tags: Store<OsmTags>
|
||||
export let state: SpecialVisualizationState
|
||||
|
|
@ -42,7 +43,7 @@
|
|||
expanded = true
|
||||
}}
|
||||
>
|
||||
<ToSvelte construct={Svg.camera_plus_svg().SetClass("block w-8 h-8 p-1 mr-2 ")} />
|
||||
<Camera_plus class="block w-8 h-8 p-1 mr-2"/>
|
||||
<Tr t={t.seeNearby} />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
import UserRelatedState from "../../../Logic/State/UserRelatedState"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { TagUtils } from "../../../Logic/Tags/TagUtils"
|
||||
import Search from "../../../assets/svg/Search.svelte";
|
||||
import Login from "../../../assets/svg/Login.svelte";
|
||||
|
||||
export let config: TagRenderingConfig
|
||||
export let tags: UIEventSource<Record<string, string>>
|
||||
|
|
@ -211,7 +213,7 @@
|
|||
|
||||
{#if config.mappings?.length >= 8}
|
||||
<div class="sticky flex w-full">
|
||||
<img src="./assets/svg/search.svg" class="h-6 w-6" />
|
||||
<Search class="h-6 w-6"/>
|
||||
<input type="text" bind:value={$searchTerm} class="w-full" />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -318,7 +320,7 @@
|
|||
<LoginToggle {state}>
|
||||
<Loading slot="loading" />
|
||||
<SubtleButton slot="not-logged-in" on:click={() => state?.osmConnection?.AttemptLogin()}>
|
||||
<img slot="image" src="./assets/svg/login.svg" class="h-8 w-8" />
|
||||
<Login slot="image" class="h-8 w-8" />
|
||||
<Tr t={Translations.t.general.loginToStart} slot="message" />
|
||||
</SubtleButton>
|
||||
{#if $feedback !== undefined}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import Mangrove_logo from "../../assets/svg/Mangrove_logo.svelte";
|
||||
|
||||
/**
|
||||
* An element showing all reviews
|
||||
|
|
@ -40,7 +41,7 @@
|
|||
<Tr t={Translations.t.reviews.no_reviews_yet} />
|
||||
{/if}
|
||||
<div class="flex justify-end">
|
||||
<ToSvelte construct={Svg.mangrove_logo_svg().SetClass("w-12 h-12 shrink-0 p-1 ")} />
|
||||
<Mangrove_logo class="w-12 h-12 shrink-0 p-1"/>
|
||||
<Tr cls="text-sm subtle" t={Translations.t.reviews.attribution} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import Svg from "../../Svg"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import Star from "../../assets/svg/Star.svelte";
|
||||
import Star_half from "../../assets/svg/Star_half.svelte";
|
||||
import Star_outline from "../../assets/svg/Star_outline.svelte";
|
||||
|
||||
export let score: number
|
||||
export let cutoff: number
|
||||
|
|
@ -23,10 +26,10 @@
|
|||
on:mousemove={(e) => dispatch("hover", { score: getScore(e) })}
|
||||
>
|
||||
{#if score >= cutoff}
|
||||
<ToSvelte construct={Svg.star_svg().SetClass(starSize)} />
|
||||
<Star class={starSize}/>
|
||||
{:else if score + 10 >= cutoff}
|
||||
<ToSvelte construct={Svg.star_half_svg().SetClass(starSize)} />
|
||||
<Star_half class={starSize}/>
|
||||
{:else}
|
||||
<ToSvelte construct={Svg.star_outline_svg().SetClass(starSize)} />
|
||||
<Star_outline class={starSize}/>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ export interface SpecialVisualization {
|
|||
readonly funcName: string
|
||||
readonly docs: string | BaseUIElement
|
||||
readonly example?: string
|
||||
readonly needsUrls: string[]
|
||||
readonly needsUrls: string[] | ((args: string[]) => string)
|
||||
|
||||
/**
|
||||
* Indicates that this special visualisation will make requests to the 'alLNodesDatabase' and that it thus should be included
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ import { GeoOperations } from "../Logic/GeoOperations"
|
|||
import CreateNewNote from "./Popup/CreateNewNote.svelte"
|
||||
import AddNewPoint from "./Popup/AddNewPoint/AddNewPoint.svelte"
|
||||
import UserProfile from "./BigComponents/UserProfile.svelte"
|
||||
import LanguagePicker from "./LanguagePicker"
|
||||
import Link from "./Base/Link"
|
||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
|
||||
import TagRenderingConfig from "../Models/ThemeConfig/TagRenderingConfig"
|
||||
|
|
@ -59,7 +58,6 @@ import { PointImportButtonViz } from "./Popup/ImportButtons/PointImportButtonViz
|
|||
import WayImportButtonViz from "./Popup/ImportButtons/WayImportButtonViz"
|
||||
import ConflateImportButtonViz from "./Popup/ImportButtons/ConflateImportButtonViz"
|
||||
import DeleteWizard from "./Popup/DeleteFlow/DeleteWizard.svelte"
|
||||
import { OpenJosm } from "./BigComponents/OpenJosm"
|
||||
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"
|
||||
import FediverseValidator from "./InputElement/Validators/FediverseValidator"
|
||||
import SendEmail from "./Popup/SendEmail.svelte"
|
||||
|
|
@ -78,6 +76,9 @@ import Questionbox from "./Popup/TagRendering/Questionbox.svelte"
|
|||
import { TagUtils } from "../Logic/Tags/TagUtils"
|
||||
import Giggity from "./BigComponents/Giggity.svelte"
|
||||
import ThemeViewState from "../Models/ThemeViewState"
|
||||
import LanguagePicker from "./InputElement/LanguagePicker.svelte"
|
||||
import LogoutButton from "./Base/LogoutButton.svelte"
|
||||
import OpenJosm from "./Base/OpenJosm.svelte"
|
||||
|
||||
class NearbyImageVis implements SpecialVisualization {
|
||||
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
|
||||
|
|
@ -453,10 +454,13 @@ export default class SpecialVisualizations {
|
|||
needsUrls: [],
|
||||
docs: "A component to set the language of the user interface",
|
||||
constr(state: SpecialVisualizationState): BaseUIElement {
|
||||
return new LanguagePicker(
|
||||
state.layout.language,
|
||||
state.userRelatedState.language
|
||||
)
|
||||
return new SvelteUIElement(LanguagePicker, {
|
||||
assignTo: state.userRelatedState.language,
|
||||
availableLanguages: state.layout.language,
|
||||
preferredLanguages: state.osmConnection.userDetails.map(
|
||||
(ud) => ud.languages
|
||||
),
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -465,11 +469,7 @@ export default class SpecialVisualizations {
|
|||
needsUrls: [Constants.osmAuthConfig.url],
|
||||
docs: "Shows a button where the user can log out",
|
||||
constr(state: SpecialVisualizationState): BaseUIElement {
|
||||
return new SubtleButton(Svg.logout_svg(), Translations.t.general.logout, {
|
||||
imgSize: "w-6 h-6",
|
||||
}).onClick(() => {
|
||||
state.osmConnection.LogOut()
|
||||
})
|
||||
return new SvelteUIElement(LogoutButton, { osmConnection: state.osmConnection })
|
||||
},
|
||||
},
|
||||
new HistogramViz(),
|
||||
|
|
@ -903,10 +903,10 @@ export default class SpecialVisualizations {
|
|||
funcName: "open_in_josm",
|
||||
docs: "Opens the current view in the JOSM-editor",
|
||||
args: [],
|
||||
needsUrls: OpenJosm.needsUrls,
|
||||
needsUrls: ["http://127.0.0.1:8111/load_and_zoom"],
|
||||
|
||||
constr: (state) => {
|
||||
return new OpenJosm(state.osmConnection, state.mapProperties.bounds)
|
||||
return new SvelteUIElement(OpenJosm, { state })
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -1099,12 +1099,6 @@ export default class SpecialVisualizations {
|
|||
if (maproulette_id_key === "" || maproulette_id_key === undefined) {
|
||||
maproulette_id_key = "mr_taskId"
|
||||
}
|
||||
if (Svg.All[image] !== undefined || Svg.All[image + ".svg"] !== undefined) {
|
||||
if (image.endsWith(".svg")) {
|
||||
image = image.substring(0, image.length - 4)
|
||||
}
|
||||
image = Svg[image + "_svg"]()
|
||||
}
|
||||
const failed = new UIEventSource(false)
|
||||
|
||||
const closeButton = new SubtleButton(image, message).OnClickWithLoading(
|
||||
|
|
@ -1460,7 +1454,7 @@ export default class SpecialVisualizations {
|
|||
},
|
||||
],
|
||||
docs: "Shows events that are happening based on a Giggity URL",
|
||||
needsUrls: ["*"],
|
||||
needsUrls: (args) => args[0],
|
||||
constr(
|
||||
state: SpecialVisualizationState,
|
||||
tagSource: UIEventSource<Record<string, string>>,
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
<script lang="ts">
|
||||
import NextButton from "./Base/NextButton.svelte"
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import EditLayerState, { EditThemeState } from "./Studio/EditLayerState"
|
||||
import EditLayer from "./Studio/EditLayer.svelte"
|
||||
import Loading from "../assets/svg/Loading.svelte"
|
||||
import StudioServer from "./Studio/StudioServer"
|
||||
import LoginToggle from "./Base/LoginToggle.svelte"
|
||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters"
|
||||
import NextButton from "./Base/NextButton.svelte"
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import EditLayerState, { EditThemeState } from "./Studio/EditLayerState"
|
||||
import EditLayer from "./Studio/EditLayer.svelte"
|
||||
import Loading from "../assets/svg/Loading.svelte"
|
||||
import StudioServer from "./Studio/StudioServer"
|
||||
import LoginToggle from "./Base/LoginToggle.svelte"
|
||||
import { OsmConnection } from "../Logic/Osm/OsmConnection"
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters"
|
||||
|
||||
import layerSchemaRaw from "../../src/assets/schemas/layerconfigmeta.json"
|
||||
import layoutSchemaRaw from "../../src/assets/schemas/layoutconfigmeta.json"
|
||||
import layerSchemaRaw from "../../src/assets/schemas/layerconfigmeta.json"
|
||||
import layoutSchemaRaw from "../../src/assets/schemas/layoutconfigmeta.json"
|
||||
|
||||
import If from "./Base/If.svelte"
|
||||
import BackButton from "./Base/BackButton.svelte"
|
||||
import ChooseLayerToEdit from "./Studio/ChooseLayerToEdit.svelte"
|
||||
import { LocalStorageSource } from "../Logic/Web/LocalStorageSource"
|
||||
import FloatOver from "./Base/FloatOver.svelte"
|
||||
import Walkthrough from "./Walkthrough/Walkthrough.svelte"
|
||||
import * as intro from "../assets/studio_introduction.json"
|
||||
import * as intro_tagrenderings from "../assets/studio_tagrenderings_intro.json"
|
||||
import If from "./Base/If.svelte"
|
||||
import BackButton from "./Base/BackButton.svelte"
|
||||
import ChooseLayerToEdit from "./Studio/ChooseLayerToEdit.svelte"
|
||||
import FloatOver from "./Base/FloatOver.svelte"
|
||||
import Walkthrough from "./Walkthrough/Walkthrough.svelte"
|
||||
import * as intro from "../assets/studio_introduction.json"
|
||||
import * as intro_tagrenderings from "../assets/studio_tagrenderings_intro.json"
|
||||
|
||||
import { QuestionMarkCircleIcon } from "@babeard/svelte-heroicons/mini"
|
||||
import type { ConfigMeta } from "./Studio/configMeta"
|
||||
import EditTheme from "./Studio/EditTheme.svelte"
|
||||
import * as meta from "../../package.json"
|
||||
import Checkbox from "./Base/Checkbox.svelte"
|
||||
import { Utils } from "../Utils"
|
||||
import Translations from "./i18n/Translations"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import { QuestionMarkCircleIcon } from "@babeard/svelte-heroicons/mini"
|
||||
import type { ConfigMeta } from "./Studio/configMeta"
|
||||
import EditTheme from "./Studio/EditTheme.svelte"
|
||||
import * as meta from "../../package.json"
|
||||
import Checkbox from "./Base/Checkbox.svelte"
|
||||
import { Utils } from "../Utils"
|
||||
import Translations from "./i18n/Translations"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import Add from "../assets/svg/Add.svelte"
|
||||
|
||||
export let studioUrl =
|
||||
export let studioUrl =
|
||||
window.location.hostname === "127.0.0.2"
|
||||
? "http://127.0.0.1:1235"
|
||||
: "https://studio.mapcomplete.org"
|
||||
|
|
@ -196,8 +196,8 @@
|
|||
<QuestionMarkCircleIcon class="h-6 w-6" />
|
||||
Show the introduction again
|
||||
</button>
|
||||
<a class="button flex" href={Utils.HomepageLink()}>
|
||||
<img class="h-6 w-6" src="./assets/svg/add.svg" />
|
||||
<a class="flex button" href={Utils.HomepageLink()}>
|
||||
<Add class="h-6 w-6" />
|
||||
<Tr t={Translations.t.general.backToIndex} />
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
<script lang="ts">
|
||||
import Svg from "../Svg"
|
||||
import Loading from "./Base/Loading.svelte"
|
||||
import ToSvelte from "./Base/ToSvelte.svelte"
|
||||
import Svg from "../Svg"
|
||||
import Loading from "./Base/Loading.svelte"
|
||||
import ToSvelte from "./Base/ToSvelte.svelte"
|
||||
import Community from "../assets/svg/Community.svelte"
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
|
@ -40,16 +41,16 @@
|
|||
|
||||
<div class="flex">
|
||||
<button class="primary">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Main action
|
||||
</button>
|
||||
<button class="primary disabled">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Main action (disabled)
|
||||
</button>
|
||||
|
||||
<button class="small">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Small button
|
||||
</button>
|
||||
|
||||
|
|
@ -58,11 +59,11 @@
|
|||
</div>
|
||||
<div class="flex">
|
||||
<button>
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Secondary action
|
||||
</button>
|
||||
<button class="disabled">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Secondary action (disabled)
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -81,7 +82,7 @@
|
|||
</label>
|
||||
<label for="javascript">
|
||||
<input id="javascript" name="fav_language" type="radio" value="JavaScript" />
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-8 h-8")} />
|
||||
<Community class="w-8 h-8"/>
|
||||
JavaScript
|
||||
</label>
|
||||
</div>
|
||||
|
|
@ -105,26 +106,26 @@
|
|||
|
||||
<div class="flex">
|
||||
<button class="primary">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Main action
|
||||
</button>
|
||||
<button class="primary disabled">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Main action (disabled)
|
||||
</button>
|
||||
<button class="small">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Small button
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<button>
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Secondary action
|
||||
</button>
|
||||
<button class="disabled">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6" />
|
||||
Secondary action (disabled)
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
<script lang="ts">
|
||||
// Testing grounds
|
||||
import { UIEventSource } from "../Logic/UIEventSource"
|
||||
import TabbedGroup from "./Base/TabbedGroup.svelte"
|
||||
|
||||
let tab = new UIEventSource(1)
|
||||
console.log("Tab control", tab)
|
||||
</script>
|
||||
|
||||
<TabbedGroup {tab}>
|
||||
<div slot="title0">Title 0</div>
|
||||
<div slot="content0">Content 0 loaded</div>
|
||||
|
||||
<div slot="title1">Title 1</div>
|
||||
<div slot="content1">Content 1</div>
|
||||
</TabbedGroup>
|
||||
<div class="w-full">
|
||||
No tests
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,62 +1,71 @@
|
|||
<script lang="ts">
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import MaplibreMap from "./Map/MaplibreMap.svelte"
|
||||
import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
|
||||
import MapControlButton from "./Base/MapControlButton.svelte"
|
||||
import ToSvelte from "./Base/ToSvelte.svelte"
|
||||
import If from "./Base/If.svelte"
|
||||
import { GeolocationControl } from "./BigComponents/GeolocationControl"
|
||||
import type { Feature } from "geojson"
|
||||
import SelectedElementView from "./BigComponents/SelectedElementView.svelte"
|
||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
|
||||
import Filterview from "./BigComponents/Filterview.svelte"
|
||||
import ThemeViewState from "../Models/ThemeViewState"
|
||||
import type { MapProperties } from "../Models/MapProperties"
|
||||
import Geosearch from "./BigComponents/Geosearch.svelte"
|
||||
import Translations from "./i18n/Translations"
|
||||
import { CogIcon, EyeIcon, MenuIcon, XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||
import FloatOver from "./Base/FloatOver.svelte"
|
||||
import PrivacyPolicy from "./BigComponents/PrivacyPolicy"
|
||||
import Constants from "../Models/Constants"
|
||||
import TabbedGroup from "./Base/TabbedGroup.svelte"
|
||||
import UserRelatedState from "../Logic/State/UserRelatedState"
|
||||
import LoginToggle from "./Base/LoginToggle.svelte"
|
||||
import LoginButton from "./Base/LoginButton.svelte"
|
||||
import CopyrightPanel from "./BigComponents/CopyrightPanel"
|
||||
import DownloadPanel from "./DownloadFlow/DownloadPanel.svelte"
|
||||
import ModalRight from "./Base/ModalRight.svelte"
|
||||
import { Utils } from "../Utils"
|
||||
import Hotkeys from "./Base/Hotkeys"
|
||||
import { VariableUiElement } from "./Base/VariableUIElement"
|
||||
import SvelteUIElement from "./Base/SvelteUIElement"
|
||||
import OverlayToggle from "./BigComponents/OverlayToggle.svelte"
|
||||
import LevelSelector from "./BigComponents/LevelSelector.svelte"
|
||||
import ExtraLinkButton from "./BigComponents/ExtraLinkButton"
|
||||
import SelectedElementTitle from "./BigComponents/SelectedElementTitle.svelte"
|
||||
import Svg from "../Svg"
|
||||
import ThemeIntroPanel from "./BigComponents/ThemeIntroPanel.svelte"
|
||||
import type { RasterLayerPolygon } from "../Models/RasterLayers"
|
||||
import { AvailableRasterLayers } from "../Models/RasterLayers"
|
||||
import RasterLayerOverview from "./Map/RasterLayerOverview.svelte"
|
||||
import IfHidden from "./Base/IfHidden.svelte"
|
||||
import { onDestroy } from "svelte"
|
||||
import { OpenJosm } from "./BigComponents/OpenJosm"
|
||||
import MapillaryLink from "./BigComponents/MapillaryLink.svelte"
|
||||
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"
|
||||
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"
|
||||
import StateIndicator from "./BigComponents/StateIndicator.svelte"
|
||||
import LanguagePicker from "./LanguagePicker"
|
||||
import Locale from "./i18n/Locale"
|
||||
import ShareScreen from "./BigComponents/ShareScreen.svelte"
|
||||
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"
|
||||
import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte"
|
||||
import Cross from "../assets/svg/Cross.svelte"
|
||||
import Summary from "./BigComponents/Summary.svelte"
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import MaplibreMap from "./Map/MaplibreMap.svelte"
|
||||
import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
|
||||
import MapControlButton from "./Base/MapControlButton.svelte"
|
||||
import ToSvelte from "./Base/ToSvelte.svelte"
|
||||
import If from "./Base/If.svelte"
|
||||
import { GeolocationControl } from "./BigComponents/GeolocationControl"
|
||||
import type { Feature } from "geojson"
|
||||
import SelectedElementView from "./BigComponents/SelectedElementView.svelte"
|
||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig"
|
||||
import Filterview from "./BigComponents/Filterview.svelte"
|
||||
import ThemeViewState from "../Models/ThemeViewState"
|
||||
import type { MapProperties } from "../Models/MapProperties"
|
||||
import Geosearch from "./BigComponents/Geosearch.svelte"
|
||||
import Translations from "./i18n/Translations"
|
||||
import { CogIcon, EyeIcon, MenuIcon, XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||
import FloatOver from "./Base/FloatOver.svelte"
|
||||
import PrivacyPolicy from "./BigComponents/PrivacyPolicy"
|
||||
import Constants from "../Models/Constants"
|
||||
import TabbedGroup from "./Base/TabbedGroup.svelte"
|
||||
import UserRelatedState from "../Logic/State/UserRelatedState"
|
||||
import LoginToggle from "./Base/LoginToggle.svelte"
|
||||
import LoginButton from "./Base/LoginButton.svelte"
|
||||
import CopyrightPanel from "./BigComponents/CopyrightPanel"
|
||||
import DownloadPanel from "./DownloadFlow/DownloadPanel.svelte"
|
||||
import ModalRight from "./Base/ModalRight.svelte"
|
||||
import { Utils } from "../Utils"
|
||||
import Hotkeys from "./Base/Hotkeys"
|
||||
import { VariableUiElement } from "./Base/VariableUIElement"
|
||||
import SvelteUIElement from "./Base/SvelteUIElement"
|
||||
import OverlayToggle from "./BigComponents/OverlayToggle.svelte"
|
||||
import LevelSelector from "./BigComponents/LevelSelector.svelte"
|
||||
import ExtraLinkButton from "./BigComponents/ExtraLinkButton"
|
||||
import SelectedElementTitle from "./BigComponents/SelectedElementTitle.svelte"
|
||||
import ThemeIntroPanel from "./BigComponents/ThemeIntroPanel.svelte"
|
||||
import type { RasterLayerPolygon } from "../Models/RasterLayers"
|
||||
import { AvailableRasterLayers } from "../Models/RasterLayers"
|
||||
import RasterLayerOverview from "./Map/RasterLayerOverview.svelte"
|
||||
import IfHidden from "./Base/IfHidden.svelte"
|
||||
import { onDestroy } from "svelte"
|
||||
import MapillaryLink from "./BigComponents/MapillaryLink.svelte"
|
||||
import OpenIdEditor from "./BigComponents/OpenIdEditor.svelte"
|
||||
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"
|
||||
import StateIndicator from "./BigComponents/StateIndicator.svelte"
|
||||
import ShareScreen from "./BigComponents/ShareScreen.svelte"
|
||||
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"
|
||||
import PendingChangesIndicator from "./BigComponents/PendingChangesIndicator.svelte"
|
||||
import Cross from "../assets/svg/Cross.svelte"
|
||||
import Summary from "./BigComponents/Summary.svelte"
|
||||
import Mastodon from "../assets/svg/Mastodon.svelte"
|
||||
import Bug from "../assets/svg/Bug.svelte"
|
||||
import Liberapay from "../assets/svg/Liberapay.svelte"
|
||||
import Min from "../assets/svg/Min.svelte"
|
||||
import Plus from "../assets/svg/Plus.svelte"
|
||||
import Filter from "../assets/svg/Filter.svelte"
|
||||
import Add from "../assets/svg/Add.svelte"
|
||||
import Statistics from "../assets/svg/Statistics.svelte"
|
||||
import Community from "../assets/svg/Community.svelte"
|
||||
import Download from "../assets/svg/Download.svelte"
|
||||
import Share from "../assets/svg/Share.svelte"
|
||||
import LanguagePicker from "./InputElement/LanguagePicker.svelte"
|
||||
import OpenJosm from "./Base/OpenJosm.svelte"
|
||||
|
||||
export let state: ThemeViewState
|
||||
export let state: ThemeViewState
|
||||
let layout = state.layout
|
||||
|
||||
let maplibremap: UIEventSource<MlMap> = state.map
|
||||
|
|
@ -205,7 +214,7 @@
|
|||
<!-- bottom left elements -->
|
||||
<If condition={state.featureSwitches.featureSwitchFilter}>
|
||||
<MapControlButton on:click={() => state.guistate.openFilterView()}>
|
||||
<ToSvelte construct={Svg.filter_svg().SetClass("h-6 w-6")} />
|
||||
<Filter class="h-6 w-6"/>
|
||||
</MapControlButton>
|
||||
</If>
|
||||
<If condition={state.featureSwitches.featureSwitchBackgroundSelection}>
|
||||
|
|
@ -245,10 +254,10 @@
|
|||
</div>
|
||||
</If>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z + 1)}>
|
||||
<ToSvelte construct={Svg.plus_svg().SetClass("w-8 h-8")} />
|
||||
<Plus class="w-8 h-8" />
|
||||
</MapControlButton>
|
||||
<MapControlButton on:click={() => mapproperties.zoom.update((z) => z - 1)}>
|
||||
<ToSvelte construct={Svg.min_svg().SetClass("w-8 h-8")} />
|
||||
<Min class="w-8 h-8"/>
|
||||
</MapControlButton>
|
||||
<If condition={featureSwitches.featureSwitchGeolocation}>
|
||||
<MapControlButton>
|
||||
|
|
@ -264,7 +273,7 @@
|
|||
</div>
|
||||
|
||||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if $showCrosshair === "yes" && ($currentZoom >= 17 || $arrowKeysWereUsed !== undefined)}
|
||||
{#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $arrowKeysWereUsed !== undefined }
|
||||
<div
|
||||
class="pointer-events-none absolute top-0 left-0 flex h-full w-full items-center justify-center"
|
||||
>
|
||||
|
|
@ -341,7 +350,7 @@
|
|||
</div>
|
||||
|
||||
<div class="flex" slot="title1">
|
||||
<ToSvelte construct={Svg.filter_svg().SetClass("w-4 h-4")} />
|
||||
<Filter class="w-4 h-4"/>
|
||||
<Tr t={Translations.t.general.menu.filter} />
|
||||
</div>
|
||||
|
||||
|
|
@ -365,7 +374,7 @@
|
|||
|
||||
<div class="flex" slot="title2">
|
||||
<If condition={state.featureSwitches.featureSwitchEnableExport}>
|
||||
<ToSvelte construct={Svg.download_svg().SetClass("w-4 h-4")} />
|
||||
<Download class="w-4 h-4"/>
|
||||
<Tr t={Translations.t.general.download.title} />
|
||||
</If>
|
||||
</div>
|
||||
|
|
@ -380,7 +389,7 @@
|
|||
<ToSvelte construct={() => new CopyrightPanel(state)} slot="content3" />
|
||||
|
||||
<div class="flex" slot="title4">
|
||||
<ToSvelte construct={Svg.share_svg().SetClass("w-4 h-4")} />
|
||||
<Share class="w-4 h-4"/>
|
||||
<Tr t={Translations.t.general.sharescreen.title} />
|
||||
</div>
|
||||
<div class="m-2" slot="content4">
|
||||
|
|
@ -432,27 +441,27 @@
|
|||
<Tr t={Translations.t.general.aboutMapComplete.intro} />
|
||||
|
||||
<a class="flex" href={Utils.HomepageLink()}>
|
||||
<img class="h-6 w-6" src="./assets/svg/add.svg" />
|
||||
<Add class="h-6 w-6"/>
|
||||
<Tr t={Translations.t.general.backToIndex} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href="https://github.com/pietervdvn/MapComplete/issues" target="_blank">
|
||||
<img class="h-6 w-6" src="./assets/svg/bug.svg" />
|
||||
<Bug class="h-6 w-6"/>
|
||||
<Tr t={Translations.t.general.attribution.openIssueTracker} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href="https://en.osm.town/@MapComplete" target="_blank">
|
||||
<img class="h-6 w-6" src="./assets/svg/mastodon.svg" />
|
||||
<Mastodon class="w-6 h-6" />
|
||||
<Tr t={Translations.t.general.attribution.followOnMastodon} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href="https://liberapay.com/pietervdvn/" target="_blank">
|
||||
<img class="h-6 w-6" src="./assets/svg/liberapay.svg" />
|
||||
<Liberapay class="h-6 w-6" />
|
||||
<Tr t={Translations.t.general.attribution.donate} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href={Utils.OsmChaLinkFor(7)} target="_blank">
|
||||
<img class="h-6 w-6" src="./assets/svg/statistics.svg" />
|
||||
<Statistics class="h-6 w-6" />
|
||||
<Tr t={Translations.t.general.attribution.openOsmcha.Subs({ theme: "MapComplete" })} />
|
||||
</a>
|
||||
{Constants.vNumber}
|
||||
|
|
@ -467,7 +476,7 @@
|
|||
<!-- All shown components are set by 'usersettings.json', which happily uses some special visualisations created specifically for it -->
|
||||
<LoginToggle {state}>
|
||||
<div class="flex flex-col" slot="not-logged-in">
|
||||
<ToSvelte construct={() => new LanguagePicker(layout.language, Locale.language)} />
|
||||
<LanguagePicker availableLanguages={layout.language} />
|
||||
<Tr cls="alert" t={Translations.t.userinfo.notLoggedIn} />
|
||||
<LoginButton clss="primary" osmConnection={state.osmConnection} />
|
||||
</div>
|
||||
|
|
@ -486,7 +495,7 @@
|
|||
</div>
|
||||
|
||||
<div class="flex" slot="title2">
|
||||
<ToSvelte construct={Svg.community_svg().SetClass("w-6 h-6")} />
|
||||
<Community class="w-6 h-6"/>
|
||||
<Tr t={Translations.t.communityIndex.title} />
|
||||
</div>
|
||||
<div class="m-2" slot="content2">
|
||||
|
|
@ -504,10 +513,7 @@
|
|||
<div class="m-2 flex flex-col" slot="content4">
|
||||
<If condition={featureSwitches.featureSwitchEnableLogin}>
|
||||
<OpenIdEditor mapProperties={state.mapProperties} />
|
||||
<ToSvelte
|
||||
construct={() =>
|
||||
new OpenJosm(state.osmConnection, state.mapProperties.bounds).SetClass("w-full")}
|
||||
/>
|
||||
<OpenJosm {state}/>
|
||||
<MapillaryLink mapProperties={state.mapProperties} />
|
||||
</If>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
on:next={() => step(1)}
|
||||
isFirst={currentPage === 0}
|
||||
islast={currentPage + 1 === pages.length}
|
||||
totalPages={pages.length}
|
||||
pageNumber={currentPage}
|
||||
>
|
||||
<FromHtml src={nmd(pages[currentPage])} />
|
||||
</WalkthroughStep>
|
||||
|
|
|
|||
|
|
@ -1,30 +1,42 @@
|
|||
<script lang="ts">
|
||||
import BackButton from "../Base/BackButton.svelte"
|
||||
import NextButton from "../Base/NextButton.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import BackButton from "../Base/BackButton.svelte";
|
||||
import NextButton from "../Base/NextButton.svelte";
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
const dispatch = createEventDispatcher<{ back; next }>()
|
||||
export let islast = false
|
||||
export let isFirst = false
|
||||
const dispatch = createEventDispatcher<{ back; next }>();
|
||||
export let islast = false;
|
||||
export let isFirst = false;
|
||||
export let pageNumber: number = undefined;
|
||||
export let totalPages: number = undefined;
|
||||
</script>
|
||||
|
||||
<div class="flex h-full w-full flex-col justify-between">
|
||||
<div class="flex h-full w-full flex-col justify-between link-underline">
|
||||
<div class="overflow-y-auto">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<div class="flex w-full">
|
||||
{#if !isFirst}
|
||||
<BackButton clss="w-full" on:click={() => dispatch("back")}>Back</BackButton>
|
||||
{:else}
|
||||
<div class="w-full" />
|
||||
<div class="flex flex-col">
|
||||
|
||||
{#if pageNumber !== undefined && totalPages !== undefined}
|
||||
<div class="flex justify-end">
|
||||
<div class="subtle">{pageNumber+1}/{totalPages}</div>
|
||||
</div>
|
||||
{/if}
|
||||
<NextButton clss="primary w-full" on:click={() => dispatch("next")}>
|
||||
{#if islast}
|
||||
Finish
|
||||
<div class="flex w-full">
|
||||
{#if !isFirst}
|
||||
<BackButton clss="w-full" on:click={() => dispatch("back")}>Back</BackButton>
|
||||
{:else}
|
||||
Next
|
||||
<div class="w-full" />
|
||||
{/if}
|
||||
</NextButton>
|
||||
<NextButton clss="primary w-full" on:click={() => dispatch("next")}>
|
||||
{#if islast}
|
||||
Finish
|
||||
{:else}
|
||||
Next
|
||||
{/if}
|
||||
</NextButton>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
import WikidataPreviewBox from "./WikidataPreviewBox"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Wikipedia from "../../assets/svg/Wikipedia.svelte";
|
||||
|
||||
/**
|
||||
* Shows a wikipedia-article + wikidata preview for the given item
|
||||
|
|
@ -18,7 +19,7 @@
|
|||
|
||||
{#if $wikipediaDetails.articleUrl}
|
||||
<a class="flex" href={$wikipediaDetails.articleUrl} rel="noreferrer" target="_blank">
|
||||
<img class="h-6 w-6" src="./assets/svg/wikipedia.svg" />
|
||||
<Wikipedia class="h-6 w-6"/>
|
||||
<Tr t={Translations.t.general.wikipedia.fromWikipedia} />
|
||||
</a>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ export default class Locale {
|
|||
if (typeof navigator !== "undefined") {
|
||||
browserLanguage = navigator.languages?.[0] ?? navigator.language ?? "en"
|
||||
console.log("Browser language is", browserLanguage)
|
||||
if (browserLanguage === "en-US") {
|
||||
browserLanguage = "en"
|
||||
}
|
||||
}
|
||||
source = LocalStorageSource.Get("language", browserLanguage)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue