forked from MapComplete/MapComplete
Merge master
This commit is contained in:
commit
214ba40dfa
66 changed files with 2226 additions and 1578 deletions
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
|
||||
import { Utils } from "../../Utils"
|
||||
import Share from "@babeard/svelte-heroicons/solid/Share"
|
||||
import { DocumentDuplicateIcon } from "@rgossiaux/svelte-heroicons/outline"
|
||||
|
|
@ -30,8 +29,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-full">
|
||||
|
||||
<div class="flex w-full flex-col">
|
||||
<div class="flex w-full">
|
||||
<div class="literal-code w-full" on:click={(e) => Utils.selectTextIn(e.target)}>
|
||||
{text}
|
||||
|
|
@ -48,11 +46,8 @@
|
|||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex justify-center">
|
||||
{#if isCopied}
|
||||
<Tr t={tr.copiedToClipboard} cls="thanks m-2" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
<script lang="ts">
|
||||
|
||||
import Translations from "../i18n/Translations"
|
||||
import { Utils } from "../../Utils"
|
||||
import Hotkeys from "../Base/Hotkeys"
|
||||
|
|
@ -24,7 +23,6 @@
|
|||
|
||||
let layout = state.layout
|
||||
let featureSwitches = state.featureSwitches
|
||||
|
||||
</script>
|
||||
|
||||
<div class="link-underline links-w-full m-2 flex flex-col gap-y-1">
|
||||
|
|
@ -51,16 +49,14 @@
|
|||
|
||||
<a
|
||||
class="flex"
|
||||
href={"https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Themes/" +
|
||||
layout.id +
|
||||
".md"}
|
||||
href={"https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Themes/" + layout.id + ".md"}
|
||||
target="_blank"
|
||||
>
|
||||
<DocumentChartBar class="h-6 w-6" />
|
||||
<Tr
|
||||
t={Translations.t.general.attribution.openThemeDocumentation.Subs({
|
||||
name: layout.title,
|
||||
})}
|
||||
name: layout.title,
|
||||
})}
|
||||
/>
|
||||
</a>
|
||||
|
||||
|
|
@ -74,10 +70,7 @@
|
|||
<Tr t={Translations.t.general.attribution.donate} />
|
||||
</a>
|
||||
|
||||
<button
|
||||
class="as-link"
|
||||
on:click={() => state.guistate.communityIndexPanelIsOpened.setData(true)}
|
||||
>
|
||||
<button class="as-link" on:click={() => state.guistate.communityIndexPanelIsOpened.setData(true)}>
|
||||
<Community class="h-6 w-6" />
|
||||
<Tr t={Translations.t.communityIndex.title} />
|
||||
</button>
|
||||
|
|
@ -88,10 +81,7 @@
|
|||
<MapillaryLink large={false} mapProperties={state.mapProperties} />
|
||||
</If>
|
||||
|
||||
<button
|
||||
class="as-link"
|
||||
on:click={() => state.guistate.privacyPanelIsOpened.setData(true)}
|
||||
>
|
||||
<button class="as-link" on:click={() => state.guistate.privacyPanelIsOpened.setData(true)}>
|
||||
<EyeIcon class="h-6 w-6 pr-1" />
|
||||
<Tr t={Translations.t.privacy.title} />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ export default class CopyrightPanel extends Combine {
|
|||
const t = Translations.t.general.attribution
|
||||
const layoutToUse = state.layout
|
||||
|
||||
const iconAttributions: BaseUIElement[] =layoutToUse.getUsedImages().map(
|
||||
CopyrightPanel.IconAttribution
|
||||
)
|
||||
const iconAttributions: BaseUIElement[] = layoutToUse
|
||||
.getUsedImages()
|
||||
.map(CopyrightPanel.IconAttribution)
|
||||
|
||||
let maintainer: BaseUIElement = undefined
|
||||
if (layoutToUse.credits !== undefined && layoutToUse.credits !== "") {
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@
|
|||
*/
|
||||
let needsThemeRedirect = url.port !== "" || url.hostname.match(/^[0-9]/) || !state.layout.official
|
||||
let layoutId = state.layout.id
|
||||
let baseLink =
|
||||
`${url.protocol}//${url.host}/${needsThemeRedirect ? "theme.html" : layoutId}?`
|
||||
let baseLink = `${url.protocol}//${url.host}/${needsThemeRedirect ? "theme.html" : layoutId}?`
|
||||
|
||||
let showWelcomeMessage = true
|
||||
let enableLogin = true
|
||||
|
|
@ -45,7 +44,8 @@
|
|||
enableLogin: boolean,
|
||||
enableFilters: boolean,
|
||||
enableBackground: boolean,
|
||||
enableGeolocation: boolean) {
|
||||
enableGeolocation: boolean
|
||||
) {
|
||||
const layout = state.layout
|
||||
let excluded = Utils.NoNull([
|
||||
showWelcomeMessage ? undefined : "fs-welcome-message",
|
||||
|
|
@ -53,7 +53,6 @@
|
|||
enableFilters ? undefined : "fs-filter",
|
||||
enableBackground ? undefined : "fs-background",
|
||||
enableGeolocation ? undefined : "fs-geolocation",
|
||||
|
||||
])
|
||||
const layerParamsWhitelist: string[] = ["fs-layers-enabled=false"]
|
||||
const layerParamsBlacklist: string[] = []
|
||||
|
|
@ -79,9 +78,10 @@
|
|||
|
||||
const layersBlack = layerParamsBlacklist.join("&")
|
||||
const layersWhite = layerParamsWhitelist.join("&")
|
||||
const layers = layersBlack.length < layersWhite.length ? layerParamsBlacklist : layerParamsWhitelist
|
||||
const layers =
|
||||
layersBlack.length < layersWhite.length ? layerParamsBlacklist : layerParamsWhitelist
|
||||
const params = QueryParameters.GetParts(new Set(excluded))
|
||||
.filter(part => !part.startsWith("layer-"))
|
||||
.filter((part) => !part.startsWith("layer-"))
|
||||
.concat(...layers)
|
||||
.concat(excluded.map((k) => k + "=" + false))
|
||||
linkToShare = baseLink + Utils.Dedup(params).join("&")
|
||||
|
|
@ -91,30 +91,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
$: calculateLinkToShare(showWelcomeMessage, enableLogin, enableFilters, enableBackground, enableGeolocation)
|
||||
$: calculateLinkToShare(
|
||||
showWelcomeMessage,
|
||||
enableLogin,
|
||||
enableFilters,
|
||||
enableBackground,
|
||||
enableGeolocation
|
||||
)
|
||||
|
||||
let iframeCode: string
|
||||
$: iframeCode = `<iframe src="${linkToShare}"
|
||||
${enableGeolocation ? 'allow="geolocation"' : ""} width="100%" height="100%" style="min-width: 250px; min-height: 250px"
|
||||
${
|
||||
enableGeolocation ? 'allow="geolocation"' : ""
|
||||
} width="100%" height="100%" style="min-width: 250px; min-height: 250px"
|
||||
title="${state.layout.title?.txt ?? "MapComplete"} with MapComplete">
|
||||
</iframe>`
|
||||
|
||||
Array.from(state.layerState.filteredLayers.values()).forEach(flayer => flayer.isDisplayed.addCallbackAndRunD(_ => {
|
||||
calculateLinkToShare(showWelcomeMessage, enableLogin, enableFilters, enableBackground, enableGeolocation)
|
||||
}))
|
||||
|
||||
Array.from(state.layerState.filteredLayers.values()).forEach((flayer) =>
|
||||
flayer.isDisplayed.addCallbackAndRunD((_) => {
|
||||
calculateLinkToShare(
|
||||
showWelcomeMessage,
|
||||
enableLogin,
|
||||
enableFilters,
|
||||
enableBackground,
|
||||
enableGeolocation
|
||||
)
|
||||
})
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<Tr t={tr.intro} />
|
||||
|
||||
<Copyable {state} text={linkToShare}/>
|
||||
|
||||
|
||||
<Copyable {state} text={linkToShare} />
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
|
||||
<ToSvelte
|
||||
construct={() => new Img(new Qr(linkToShare).toImageElement(125)).SetStyle("width: 125px")}
|
||||
/>
|
||||
|
|
@ -122,11 +134,11 @@
|
|||
|
||||
<Tr t={tr.embedIntro} />
|
||||
|
||||
<Copyable text={iframeCode}/>
|
||||
<Copyable text={iframeCode} />
|
||||
|
||||
<AccordionSingle>
|
||||
<div slot="header">
|
||||
<Tr t={tr.options}/>
|
||||
<Tr t={tr.options} />
|
||||
</div>
|
||||
<div class="link-underline my-1 flex flex-col">
|
||||
<label>
|
||||
|
|
@ -139,13 +151,11 @@
|
|||
<Tr t={tr.fsUserbadge} />
|
||||
</label>
|
||||
|
||||
|
||||
<label>
|
||||
<input bind:checked={enableFilters} type="checkbox" id="share_enable_filter" />
|
||||
<Tr t={tr.fsFilter} />
|
||||
</label>
|
||||
|
||||
|
||||
<label>
|
||||
<input bind:checked={enableBackground} type="checkbox" id="share_enable_background" />
|
||||
<Tr t={tr.fsBackground} />
|
||||
|
|
@ -157,15 +167,16 @@
|
|||
</label>
|
||||
|
||||
<span>
|
||||
|
||||
<Tr t={tr.stateIsIncluded}/>
|
||||
<a class="inline-block w-fit cursor-pointer" on:click={() => state.guistate.filtersPanelIsOpened.set(true)}>
|
||||
<Tr t={tr.openLayers}/>
|
||||
</a>
|
||||
<Tr t={tr.stateIsIncluded} />
|
||||
<a
|
||||
class="inline-block w-fit cursor-pointer"
|
||||
on:click={() => state.guistate.filtersPanelIsOpened.set(true)}
|
||||
>
|
||||
<Tr t={tr.openLayers} />
|
||||
</a>
|
||||
</span>
|
||||
|
||||
<Tr cls="link-underline" t={tr.documentation} />
|
||||
|
||||
</div>
|
||||
</AccordionSingle>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@
|
|||
</script>
|
||||
|
||||
{#if theme.id !== personal.id || $unlockedPersonal}
|
||||
<a class="my-1 flex w-full items-center text-ellipsis rounded low-interaction p-1" href={$href}>
|
||||
<a class="low-interaction my-1 flex w-full items-center text-ellipsis rounded p-1" href={$href}>
|
||||
<Marker icons={theme.icon} size="block h-8 w-8 sm:h-11 sm:w-11 m-1 sm:mx-2 md:mx-4 shrink-0" />
|
||||
|
||||
<span class="flex flex-col overflow-hidden text-ellipsis text-xl font-bold">
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@
|
|||
|
||||
<!-- Buttons: open map, go to location, search -->
|
||||
<NextButton clss="primary w-full" on:click={() => state.guistate.themeIsOpened.setData(false)}>
|
||||
<div class="flex flex-col w-full items-center">
|
||||
<div class="flex w-full flex-col items-center">
|
||||
<div class="flex w-full justify-center text-2xl">
|
||||
<Tr t={Translations.t.general.openTheMap} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
tags.data["closed_at"] = new Date().toISOString()
|
||||
NoteCommentElement.addCommentTo(txt.data, tags, state)
|
||||
tags.ping()
|
||||
|
||||
}
|
||||
|
||||
async function reopenNote() {
|
||||
|
|
@ -67,7 +66,6 @@
|
|||
NoteCommentElement.addCommentTo(txt.data, tags, state)
|
||||
tags.ping()
|
||||
isProcessing.set(false)
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -89,43 +87,43 @@
|
|||
</label>
|
||||
|
||||
{#if $isProcessing}
|
||||
<Loading/>
|
||||
{:else}
|
||||
<div class="flex flex-col">
|
||||
{#if $txt?.length > 0}
|
||||
<button class="primary flex" on:click|preventDefault={() => addComment()}>
|
||||
<!-- Add a comment -->
|
||||
<Speech_bubble class="h-7 w-7 pr-2" />
|
||||
<Tr t={t.addCommentPlaceholder} />
|
||||
</button>
|
||||
{:else}
|
||||
<div class="alert w-full">
|
||||
<Tr t={t.typeText} />
|
||||
</div>
|
||||
{/if}
|
||||
<Loading />
|
||||
{:else}
|
||||
<div class="flex flex-col">
|
||||
{#if $txt?.length > 0}
|
||||
<button class="primary flex" on:click|preventDefault={() => addComment()}>
|
||||
<!-- Add a comment -->
|
||||
<Speech_bubble class="h-7 w-7 pr-2" />
|
||||
<Tr t={t.addCommentPlaceholder} />
|
||||
</button>
|
||||
{:else}
|
||||
<div class="alert w-full">
|
||||
<Tr t={t.typeText} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$isClosed}
|
||||
<button class="flex items-center" on:click|preventDefault={() => closeNote()}>
|
||||
<Resolved class="h-8 w-8 pr-2" />
|
||||
<!-- Close note -->
|
||||
{#if $txt === undefined || $txt === ""}
|
||||
<Tr t={t.closeNote} />
|
||||
{:else}
|
||||
<Tr t={t.addCommentAndClose} />
|
||||
{/if}
|
||||
</button>
|
||||
{:else}
|
||||
<button class="flex items-center" on:click|preventDefault={() => reopenNote()}>
|
||||
<!-- Reopen -->
|
||||
<Note class="h-7 w-7 pr-2" />
|
||||
{#if $txt === undefined || $txt === ""}
|
||||
<Tr t={t.reopenNote} />
|
||||
{:else}
|
||||
<Tr t={t.reopenNoteAndComment} />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if !$isClosed}
|
||||
<button class="flex items-center" on:click|preventDefault={() => closeNote()}>
|
||||
<Resolved class="h-8 w-8 pr-2" />
|
||||
<!-- Close note -->
|
||||
{#if $txt === undefined || $txt === ""}
|
||||
<Tr t={t.closeNote} />
|
||||
{:else}
|
||||
<Tr t={t.addCommentAndClose} />
|
||||
{/if}
|
||||
</button>
|
||||
{:else}
|
||||
<button class="flex items-center" on:click|preventDefault={() => reopenNote()}>
|
||||
<!-- Reopen -->
|
||||
<Note class="h-7 w-7 pr-2" />
|
||||
{#if $txt === undefined || $txt === ""}
|
||||
<Tr t={t.reopenNote} />
|
||||
{:else}
|
||||
<Tr t={t.reopenNoteAndComment} />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</form>
|
||||
</LoginToggle>
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@
|
|||
|
||||
<div class="flex">
|
||||
<div class="m-4 flex w-full flex-col">
|
||||
|
||||
<NextButton clss="primary" on:click={() => state.highlightedItem.setData({ path, schema })}>
|
||||
{#if schema.hints.question}
|
||||
{schema.hints.question}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,9 @@
|
|||
return `${singular} ${i}`
|
||||
}
|
||||
|
||||
let genIconF: (x: any) => ({ icon: string, color: string }) = <any>Function("value", "return " + schema.hints.icon)
|
||||
let genIconF: (x: any) => { icon: string; color: string } = <any>(
|
||||
Function("value", "return " + schema.hints.icon)
|
||||
)
|
||||
console.log("Icon lambda is", schema.hints.icon, path, genIconF("test"))
|
||||
|
||||
function genIcon(value: any): string {
|
||||
|
|
@ -117,7 +119,6 @@
|
|||
}
|
||||
return genIconF(value)?.color
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="pl-2">
|
||||
|
|
@ -160,13 +161,14 @@
|
|||
{#if schema.hints.icon}
|
||||
<Icon clss="w-6 h-6" icon={genIcon(value)} color={genColor(value)} />
|
||||
{/if}
|
||||
{singular} {i}
|
||||
{singular}
|
||||
{i}
|
||||
|
||||
{#if schema.hints.title}
|
||||
<div class="subtle ml-2">
|
||||
<Tr t={Translations.T(genTitle(value, singular, i))}/>
|
||||
<Tr t={Translations.T(genTitle(value, singular, i))} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</h3>
|
||||
<button
|
||||
class="h-fit w-fit rounded-full border border-black p-1"
|
||||
|
|
@ -177,9 +179,9 @@
|
|||
<TrashIcon class="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
{:else if typeof value === "string"}
|
||||
{:else if typeof value === "string"}
|
||||
Builtin: <b>{value}</b>
|
||||
{:else}
|
||||
{:else}
|
||||
<Tr cls="font-bold" t={Translations.T(value?.question ?? value?.render)}/>
|
||||
{/if}
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -128,8 +128,11 @@
|
|||
on:submit
|
||||
/>
|
||||
</div>
|
||||
<a target="_blank" href="https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md">
|
||||
<QuestionMarkCircle class="w-6 h-6"/>
|
||||
<a
|
||||
target="_blank"
|
||||
href="https://github.com/pietervdvn/MapComplete/blob/develop/Docs/Tags_format.md"
|
||||
>
|
||||
<QuestionMarkCircle class="h-6 w-6" />
|
||||
</a>
|
||||
|
||||
{#if $feedbackKey}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export interface ConfigMeta {
|
|||
typesdefault?: string
|
||||
suggestions?: []
|
||||
title?: string
|
||||
multianswer?: "true" | string,
|
||||
multianswer?: "true" | string
|
||||
icon?: string
|
||||
}
|
||||
required: boolean
|
||||
|
|
|
|||
|
|
@ -203,9 +203,7 @@
|
|||
state.selectedTab.setData(Number(tab))
|
||||
}
|
||||
|
||||
uid.AsPromise().then(
|
||||
uid => selectStateBasedOnHash(uid)
|
||||
)
|
||||
uid.AsPromise().then((uid) => selectStateBasedOnHash(uid))
|
||||
|
||||
function backToStudio() {
|
||||
console.log("Back to studio")
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@
|
|||
if (id.startsWith("current_view")) {
|
||||
return currentViewLayer
|
||||
}
|
||||
if(id.startsWith("summary_")){
|
||||
if (id.startsWith("summary_")) {
|
||||
console.log("Not selecting a summary object. The summary object is", element)
|
||||
return undefined
|
||||
}
|
||||
|
|
@ -125,11 +125,11 @@
|
|||
state.mapProperties.installCustomKeyboardHandler(viewport)
|
||||
let canZoomIn = mapproperties.maxzoom.map(
|
||||
(mz) => mapproperties.zoom.data < mz,
|
||||
[mapproperties.zoom],
|
||||
[mapproperties.zoom]
|
||||
)
|
||||
let canZoomOut = mapproperties.minzoom.map(
|
||||
(mz) => mapproperties.zoom.data > mz,
|
||||
[mapproperties.zoom],
|
||||
[mapproperties.zoom]
|
||||
)
|
||||
|
||||
function updateViewport() {
|
||||
|
|
@ -166,7 +166,7 @@
|
|||
onDestroy(
|
||||
rasterLayer.addCallbackAndRunD((l) => {
|
||||
rasterLayerName = l.properties.name
|
||||
}),
|
||||
})
|
||||
)
|
||||
let previewedImage = state.previewedImage
|
||||
|
||||
|
|
@ -197,7 +197,7 @@
|
|||
let openMapButton: UIEventSource<HTMLElement> = new UIEventSource<HTMLElement>(undefined)
|
||||
let openMenuButton: UIEventSource<HTMLElement> = new UIEventSource<HTMLElement>(undefined)
|
||||
let openCurrentViewLayerButton: UIEventSource<HTMLElement> = new UIEventSource<HTMLElement>(
|
||||
undefined,
|
||||
undefined
|
||||
)
|
||||
let _openNewElementButton: HTMLButtonElement
|
||||
let openNewElementButton: UIEventSource<HTMLElement> = new UIEventSource<HTMLElement>(undefined)
|
||||
|
|
@ -257,7 +257,9 @@
|
|||
on:keydown={forwardEventToMap}
|
||||
htmlElem={openMapButton}
|
||||
>
|
||||
<div class="m-0.5 mx-1 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1 md:mx-2">
|
||||
<div
|
||||
class="m-0.5 mx-1 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1 md:mx-2"
|
||||
>
|
||||
<Marker icons={layout.icon} size="h-4 w-4 md:h-8 md:w-8 mr-0.5 sm:mr-1 md:mr-2" />
|
||||
<b class="mr-1">
|
||||
<Tr t={layout.title} />
|
||||
|
|
@ -354,10 +356,10 @@
|
|||
<a
|
||||
class="bg-black-transparent pointer-events-auto ml-1 h-fit max-h-12 cursor-pointer self-end self-center overflow-hidden rounded-2xl px-1 text-white opacity-50 hover:opacity-100"
|
||||
on:click={() => {
|
||||
if(featureSwitches.featureSwitchWelcomeMessage.data){
|
||||
state.guistate.themeViewTab.setData("copyright")
|
||||
state.guistate.themeIsOpened.setData(true)
|
||||
}else{
|
||||
if (featureSwitches.featureSwitchWelcomeMessage.data) {
|
||||
state.guistate.themeViewTab.setData("copyright")
|
||||
state.guistate.themeIsOpened.setData(true)
|
||||
} else {
|
||||
state.guistate.copyrightPanelIsOpened.setData(true)
|
||||
}
|
||||
}}
|
||||
|
|
@ -520,11 +522,10 @@
|
|||
<Tr t={Translations.t.general.attribution.title} />
|
||||
</div>
|
||||
|
||||
<div slot="content2" class="flex flex-col m-2">
|
||||
<div slot="content2" class="m-2 flex flex-col">
|
||||
<ToSvelte construct={() => new CopyrightPanel(state)} />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex" slot="title3">
|
||||
<Share class="h-4 w-4" />
|
||||
<Tr t={Translations.t.general.sharescreen.title} />
|
||||
|
|
@ -650,15 +651,14 @@
|
|||
<FloatOver on:close={() => state.guistate.privacyPanelIsOpened.setData(false)}>
|
||||
<div class="flex h-full flex-col overflow-hidden">
|
||||
<h1 class="low-interaction m-0 flex items-center p-4 drop-shadow-md">
|
||||
<Tr t= {Translations.t.general.attribution.title}/>
|
||||
<Tr t={Translations.t.general.attribution.title} />
|
||||
</h1>
|
||||
<div class="overflow-auto p-4">
|
||||
<h2>
|
||||
|
||||
<Tr t={Translations.t.general.menu.aboutMapComplete} />
|
||||
<Tr t={Translations.t.general.menu.aboutMapComplete} />
|
||||
</h2>
|
||||
<AboutMapComplete {state} />
|
||||
<ToSvelte construct={() => new CopyrightPanel(state)} />
|
||||
<AboutMapComplete {state} />
|
||||
<ToSvelte construct={() => new CopyrightPanel(state)} />
|
||||
</div>
|
||||
</div>
|
||||
</FloatOver>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue