forked from MapComplete/MapComplete
Refactoring: fix delete indication, fix splitroad, fix addition of multiple new points snapped onto the same way (all will properly attach now)
This commit is contained in:
parent
1f9aacfb29
commit
4172af6a72
118 changed files with 1422 additions and 1357 deletions
|
@ -4,7 +4,6 @@ import Combine from "./Base/Combine"
|
|||
import MoreScreen from "./BigComponents/MoreScreen"
|
||||
import Translations from "./i18n/Translations"
|
||||
import Constants from "../Models/Constants"
|
||||
import { Utils } from "../Utils"
|
||||
import LanguagePicker from "./LanguagePicker"
|
||||
import IndexText from "./BigComponents/IndexText"
|
||||
import { ImportViewerLinks } from "./BigComponents/UserInformation"
|
||||
|
@ -31,10 +30,8 @@ export default class AllThemesGui {
|
|||
featureSwitchUserbadge: new ImmutableStore(true),
|
||||
}),
|
||||
new ImportViewerLinks(state.osmConnection),
|
||||
Translations.t.general.aboutMapcomplete
|
||||
.Subs({ osmcha_link: Utils.OsmChaLinkFor(7) })
|
||||
.SetClass("link-underline"),
|
||||
new FixedUiElement("v" + Constants.vNumber),
|
||||
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")
|
||||
|
|
|
@ -99,14 +99,23 @@ export default class Hotkeys {
|
|||
}
|
||||
|
||||
static generateDocumentation(): BaseUIElement {
|
||||
const byKey: [string, string | Translation][] = Hotkeys._docs.data
|
||||
let byKey: [string, string | Translation][] = Hotkeys._docs.data
|
||||
.map(({ key, documentation }) => {
|
||||
const modifiers = Object.keys(key).filter((k) => k !== "nomod" && k !== "onUp")
|
||||
const keycode: string = key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"]
|
||||
let keycode: string = key["ctrl"] ?? key["shift"] ?? key["alt"] ?? key["nomod"]
|
||||
if (keycode.length == 1) {
|
||||
keycode = keycode.toUpperCase()
|
||||
}
|
||||
modifiers.push(keycode)
|
||||
return <[string, string | Translation]>[modifiers.join("+"), documentation]
|
||||
})
|
||||
.sort()
|
||||
byKey = Utils.NoNull(byKey)
|
||||
for (let i = byKey.length - 1; i > 0; i--) {
|
||||
if (byKey[i - 1][0] === byKey[i][0]) {
|
||||
byKey.splice(i, 1)
|
||||
}
|
||||
}
|
||||
const t = Translations.t.hotkeyDocumentation
|
||||
return new Combine([
|
||||
new Title(t.title, 1),
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
import Combine from "../Base/Combine"
|
||||
import { Store } from "../../Logic/UIEventSource"
|
||||
import Translations from "../i18n/Translations"
|
||||
import { SubtleButton } from "../Base/SubtleButton"
|
||||
import Svg from "../../Svg"
|
||||
import { Utils } from "../../Utils"
|
||||
import { MapillaryLink } from "./MapillaryLink"
|
||||
import { OpenIdEditor, OpenJosm } from "./CopyrightPanel"
|
||||
import Toggle from "../Input/Toggle"
|
||||
import { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
|
||||
export class BackToThemeOverview extends Toggle {
|
||||
constructor(
|
||||
state: {
|
||||
readonly featureSwitchMoreQuests: Store<boolean>
|
||||
},
|
||||
options: {
|
||||
imgSize: string
|
||||
}
|
||||
) {
|
||||
const t = Translations.t.general
|
||||
const button = new SubtleButton(Svg.add_ui(), t.backToIndex, options).onClick(() => {
|
||||
const path = window.location.href.split("/")
|
||||
path.pop()
|
||||
path.push("index.html")
|
||||
window.location.href = path.join("/")
|
||||
})
|
||||
|
||||
super(button, undefined, state.featureSwitchMoreQuests)
|
||||
}
|
||||
}
|
||||
|
||||
export class ActionButtons extends Combine {
|
||||
constructor(state:SpecialVisualizationState) {
|
||||
const imgSize = "h-6 w-6"
|
||||
const iconStyle = "height: 1.5rem; width: 1.5rem"
|
||||
const t = Translations.t.general.attribution
|
||||
|
||||
super([
|
||||
new BackToThemeOverview(state, { imgSize }),
|
||||
|
||||
new SubtleButton(Svg.liberapay_ui(), t.donate, {
|
||||
url: "https://liberapay.com/pietervdvn/",
|
||||
newTab: true,
|
||||
imgSize,
|
||||
}),
|
||||
new SubtleButton(Svg.bug_ui(), t.openIssueTracker, {
|
||||
url: "https://github.com/pietervdvn/MapComplete/issues",
|
||||
newTab: true,
|
||||
imgSize,
|
||||
}),
|
||||
new SubtleButton(
|
||||
Svg.statistics_ui(),
|
||||
t.openOsmcha.Subs({ theme: state.layoutToUse.title }),
|
||||
{
|
||||
url: Utils.OsmChaLinkFor(31, state.layoutToUse.id),
|
||||
newTab: true,
|
||||
imgSize,
|
||||
}
|
||||
),
|
||||
new SubtleButton(Svg.mastodon_ui(), t.followOnMastodon, {
|
||||
url: "https://en.osm.town/@MapComplete",
|
||||
newTab: true,
|
||||
imgSize,
|
||||
}),
|
||||
new OpenIdEditor(state, iconStyle),
|
||||
new MapillaryLink(state, iconStyle),
|
||||
new OpenJosm(state.osmConnection,state.mapProperties.bounds, iconStyle).SetClass("hidden-on-mobile"),
|
||||
])
|
||||
this.SetClass("block w-full link-no-underline")
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import Translations from "../i18n/Translations"
|
|||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import Toggle from "../Input/Toggle"
|
||||
import { DownloadPanel } from "./DownloadPanel"
|
||||
import { SubtleButton } from "../Base/SubtleButton"
|
||||
import Svg from "../../Svg"
|
||||
import ExportPDF from "../ExportPDF"
|
||||
|
@ -79,13 +78,6 @@ export default class AllDownloads extends ScrollableFullScreen {
|
|||
isExporting
|
||||
)
|
||||
|
||||
const pdf = new Toggle(
|
||||
new SubtleButton(icon, text),
|
||||
undefined,
|
||||
|
||||
state.featureSwitchExportAsPdf
|
||||
)
|
||||
|
||||
|
||||
return pdf
|
||||
return new SubtleButton(icon, text)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
import TagRenderingAnswer from "../Popup/TagRendering/TagRenderingAnswer.svelte";
|
||||
import TagRenderingEditable from "../Popup/TagRendering/TagRenderingEditable.svelte";
|
||||
import { onDestroy } from "svelte";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
|
||||
export let state: SpecialVisualizationState;
|
||||
export let layer: LayerConfig;
|
||||
|
@ -18,39 +20,45 @@
|
|||
onDestroy(tags.addCallbackAndRun(tags => {
|
||||
_tags = tags;
|
||||
}));
|
||||
|
||||
let _metatags: Record<string, string>
|
||||
onDestroy(state.userRelatedState.preferencesAsTags .addCallbackAndRun(tags => {
|
||||
|
||||
let _metatags: Record<string, string>;
|
||||
onDestroy(state.userRelatedState.preferencesAsTags.addCallbackAndRun(tags => {
|
||||
_metatags = tags;
|
||||
}));
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="flex flex-col sm:flex-row flex-grow justify-between">
|
||||
<!-- Title element-->
|
||||
<h3>
|
||||
<TagRenderingAnswer config={layer.title} {selectedElement} {state} {tags} {layer}></TagRenderingAnswer>
|
||||
</h3>
|
||||
|
||||
<div class="flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2">
|
||||
{#each layer.titleIcons as titleIconConfig (titleIconConfig.id)}
|
||||
<div class="w-8 h-8">
|
||||
<TagRenderingAnswer config={titleIconConfig} {tags} {selectedElement} {state} {layer}></TagRenderingAnswer>
|
||||
</div>
|
||||
{#if _tags._deleted === "yes"}
|
||||
<Tr t={ Translations.t.delete.isDeleted} />
|
||||
{:else}
|
||||
<div>
|
||||
<div class="flex flex-col sm:flex-row flex-grow justify-between">
|
||||
<!-- Title element-->
|
||||
<h3>
|
||||
<TagRenderingAnswer config={layer.title} {selectedElement} {state} {tags} {layer}></TagRenderingAnswer>
|
||||
</h3>
|
||||
|
||||
<div class="flex flex-row flex-wrap pt-0.5 sm:pt-1 items-center mr-2">
|
||||
{#each layer.titleIcons as titleIconConfig (titleIconConfig.id)}
|
||||
<div class="w-8 h-8">
|
||||
<TagRenderingAnswer config={titleIconConfig} {tags} {selectedElement} {state} {layer}></TagRenderingAnswer>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
{#each layer.tagRenderings as config (config.id)}
|
||||
{#if (config.condition === undefined || config.condition.matchesProperties(_tags)) && (config.metacondition === undefined || config.metacondition.matchesProperties({ ..._tags, ..._metatags }))}
|
||||
{#if config.IsKnown(_tags)}
|
||||
<TagRenderingEditable {tags} {config} {state} {selectedElement} {layer}
|
||||
{highlightedRendering}></TagRenderingEditable>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col">
|
||||
{#each layer.tagRenderings as config (config.id)}
|
||||
{#if (config.condition === undefined || config.condition.matchesProperties(_tags)) && (config.metacondition === undefined || config.metacondition.matchesProperties(_metatags))}
|
||||
{#if config.IsKnown(_tags)}
|
||||
<TagRenderingEditable {tags} {config} {state} {selectedElement} {layer} {highlightedRendering}></TagRenderingEditable>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -8,7 +8,6 @@ import { LoginToggle } from "../Popup/LoginButton"
|
|||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import LoggedInUserIndicator from "../LoggedInUserIndicator"
|
||||
import { ActionButtons } from "./ActionButtons"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import Loc from "../../Models/Loc"
|
||||
import { DefaultGuiState } from "../DefaultGuiState"
|
||||
|
@ -80,7 +79,6 @@ export default class ThemeIntroductionPanel extends Combine {
|
|||
layout.descriptionTail?.Clone().SetClass("block mt-4"),
|
||||
|
||||
languagePicker?.SetClass("block mt-4 pb-8 border-b-2 border-dotted border-gray-400"),
|
||||
new ActionButtons(state),
|
||||
|
||||
...layout.CustomCodeSnippets(),
|
||||
])
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/**
|
||||
* Called when setup is done, can be used to add more layers to the map
|
||||
*/
|
||||
export let onCreated : (value: Store<{lon: number, lat: number}> , map: Store<MlMap>, mapProperties: MapProperties ) => void
|
||||
export let onCreated : (value: Store<{lon: number, lat: number}> , map: Store<MlMap>, mapProperties: MapProperties ) => void = undefined
|
||||
|
||||
export let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined);
|
||||
let mla = new MapLibreAdaptor(map, mapProperties);
|
||||
|
|
|
@ -240,13 +240,10 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
container.style.height = document.documentElement.clientHeight + "px"
|
||||
}
|
||||
|
||||
await html2canvas(
|
||||
map.getCanvasContainer(),
|
||||
{
|
||||
backgroundColor: "#00000000",
|
||||
canvas: drawOn,
|
||||
}
|
||||
)
|
||||
await html2canvas(map.getCanvasContainer(), {
|
||||
backgroundColor: "#00000000",
|
||||
canvas: drawOn,
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
} finally {
|
||||
|
@ -261,7 +258,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
|
||||
private updateStores() {
|
||||
const map = this._maplibreMap.data
|
||||
if (map === undefined) {
|
||||
if (!map) {
|
||||
return
|
||||
}
|
||||
const dt = this.location.data
|
||||
|
|
|
@ -9,7 +9,6 @@ import { OsmTags } from "../../Models/OsmFeature"
|
|||
import { FeatureSource } from "../../Logic/FeatureSource/FeatureSource"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import { Feature, Point } from "geojson"
|
||||
import ScrollableFullScreen from "../Base/ScrollableFullScreen"
|
||||
import LineRenderingConfig from "../../Models/ThemeConfig/LineRenderingConfig"
|
||||
import { Utils } from "../../Utils"
|
||||
import * as range_layer from "../../assets/layers/range/range.json"
|
||||
|
@ -360,7 +359,6 @@ export default class ShowDataLayer {
|
|||
drawMarkers?: true | boolean
|
||||
drawLines?: true | boolean
|
||||
}
|
||||
private readonly _popupCache: Map<string, ScrollableFullScreen>
|
||||
|
||||
constructor(
|
||||
map: Store<MlMap>,
|
||||
|
@ -372,7 +370,6 @@ export default class ShowDataLayer {
|
|||
) {
|
||||
this._map = map
|
||||
this._options = options
|
||||
this._popupCache = new Map()
|
||||
const self = this
|
||||
map.addCallbackAndRunD((map) => self.initDrawFeatures(map))
|
||||
}
|
||||
|
|
|
@ -88,16 +88,18 @@
|
|||
changeType: "create",
|
||||
snapOnto: snapToWay
|
||||
});
|
||||
await state.changes.applyAction(newElementAction);
|
||||
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);
|
||||
{
|
||||
// Set some metainfo
|
||||
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}"]`;
|
||||
}
|
||||
properties["_backend"] = state.osmConnection.Backend()
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import QuestionBox from "./QuestionBox"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import Combine from "../Base/Combine"
|
||||
import TagRenderingAnswer from "./TagRenderingAnswer"
|
||||
import ScrollableFullScreen from "../Base/ScrollableFullScreen"
|
||||
import Constants from "../../Models/Constants"
|
||||
import SharedTagRenderings from "../../Customizations/SharedTagRenderings"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import { VariableUiElement } from "../Base/VariableUIElement"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import Toggle from "../Input/Toggle"
|
||||
import Lazy from "../Base/Lazy"
|
||||
import FeaturePipelineState from "../../Logic/State/FeaturePipelineState"
|
||||
import Svg from "../../Svg"
|
||||
import Translations from "../i18n/Translations"
|
||||
|
@ -31,7 +25,7 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
)
|
||||
super(
|
||||
() => undefined,
|
||||
() => FeatureInfoBox.GenerateContent(tags, layerConfig, state, showAllQuestions),
|
||||
() => FeatureInfoBox.GenerateContent(tags, layerConfig),
|
||||
options?.hashToShow ?? tags.data.id ?? "item",
|
||||
options?.isShown,
|
||||
options
|
||||
|
@ -42,60 +36,14 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
|||
}
|
||||
}
|
||||
|
||||
public static GenerateContent(
|
||||
tags: UIEventSource<any>,
|
||||
layerConfig: LayerConfig
|
||||
): BaseUIElement {
|
||||
public static GenerateContent(tags: UIEventSource<any>): BaseUIElement {
|
||||
return new Toggle(
|
||||
new Combine([
|
||||
Svg.delete_icon_svg().SetClass("w-8 h-8"),
|
||||
Translations.t.delete.isDeleted,
|
||||
]).SetClass("flex justify-center font-bold items-center"),
|
||||
FeatureInfoBox.GenerateMainContent(tags, layerConfig),
|
||||
new Combine([]).SetClass("block"),
|
||||
tags.map((t) => t["_deleted"] == "yes")
|
||||
)
|
||||
}
|
||||
private static GenerateMainContent(
|
||||
tags: UIEventSource<any>,
|
||||
layerConfig: LayerConfig
|
||||
): BaseUIElement {
|
||||
const t = Translations.t.general
|
||||
|
||||
const withQuestion = layerConfig.tagRenderings.filter(
|
||||
(tr) => tr.question !== undefined
|
||||
).length
|
||||
|
||||
const allRenderings: BaseUIElement[] = [
|
||||
new VariableUiElement(
|
||||
tags
|
||||
.map((data) => data["_newly_created"])
|
||||
.map((isCreated) => {
|
||||
if (isCreated === undefined) {
|
||||
return undefined
|
||||
}
|
||||
const createdDate = new Date(isCreated)
|
||||
const secondsSinceCreation = (Date.now() - createdDate.getTime()) / 1000
|
||||
if (secondsSinceCreation >= 60 * 5) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const els = []
|
||||
const thanks = new Combine([
|
||||
Svg.party_svg().SetClass(
|
||||
"w-12 h-12 shrink-0 p-1 m-1 bg-white rounded-full block"
|
||||
),
|
||||
t.newlyCreated,
|
||||
]).SetClass("flex w-full thanks content-center")
|
||||
els.push(thanks)
|
||||
if (withQuestion > 0) {
|
||||
els.push(t.feelFreeToSkip)
|
||||
}
|
||||
|
||||
return new Combine(els).SetClass("pb-4 mb-4 border-b block border-black")
|
||||
})
|
||||
),
|
||||
]
|
||||
|
||||
return new Combine(allRenderings).SetClass("block")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ export default class SplitRoadWizard extends Combine {
|
|||
leafletMap.setData(mapComponent.SetClass("w-full h-80"))
|
||||
)
|
||||
}
|
||||
initMap()
|
||||
|
||||
// Toggle between splitmap
|
||||
const splitButton = new SubtleButton(
|
||||
|
@ -94,7 +93,6 @@ export default class SplitRoadWizard extends Combine {
|
|||
await state.changes?.applyAction(splitAction)
|
||||
// We throw away the old map and splitpoints, and create a new map from scratch
|
||||
splitPoints.setData([])
|
||||
initMap()
|
||||
|
||||
// Close the popup. The contributor has to select a segment again to make sure they continue editing the correct segment; see #1219
|
||||
state.selectedElement?.setData(undefined)
|
||||
|
@ -134,6 +132,11 @@ export default class SplitRoadWizard extends Combine {
|
|||
),
|
||||
new Toggle(mapView, splitToggle, splitClicked),
|
||||
])
|
||||
splitClicked.addCallback((view) => {
|
||||
if (view) {
|
||||
initMap()
|
||||
}
|
||||
})
|
||||
this.dialogIsOpened = splitClicked
|
||||
const self = this
|
||||
splitButton.onClick(() => {
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
|
||||
let questionsToAsk = tags.map(tags => {
|
||||
const baseQuestions = (layer.tagRenderings ?? [])?.filter(tr => allowed(tr.labels) && tr.question !== undefined);
|
||||
console.log("Determining questions for", baseQuestions)
|
||||
const questionsToAsk: TagRenderingConfig[] = [];
|
||||
for (const baseQuestion of baseQuestions) {
|
||||
if (skippedQuestions.data.has(baseQuestion.id) > 0) {
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
export let layer: LayerConfig;
|
||||
let trs: { then: Translation; icon?: string; iconClass?: string }[];
|
||||
$: trs = Utils.NoNull(config?.GetRenderValues(_tags));
|
||||
let classes = ""
|
||||
$:classes = config?.classes?.join(" ") ?? "";
|
||||
</script>
|
||||
|
||||
{#if config !== undefined && (config?.condition === undefined || config.condition.matchesProperties(_tags))}
|
||||
<div class="flex flex-col w-full">
|
||||
<div class={"flex flex-col w-full "+classes}>
|
||||
{#if trs.length === 1}
|
||||
<TagRenderingMapping mapping={trs[0]} {tags} {state} {selectedElement} {layer}></TagRenderingMapping>
|
||||
{/if}
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte";
|
||||
import FloatOver from "./Base/FloatOver.svelte";
|
||||
import PrivacyPolicy from "./BigComponents/PrivacyPolicy";
|
||||
import { Utils } from "../Utils";
|
||||
import Constants from "../Models/Constants";
|
||||
import TabbedGroup from "./Base/TabbedGroup.svelte";
|
||||
import UserRelatedState from "../Logic/State/UserRelatedState";
|
||||
|
@ -31,6 +30,8 @@
|
|||
import CopyrightPanel from "./BigComponents/CopyrightPanel";
|
||||
import { DownloadPanel } from "./BigComponents/DownloadPanel";
|
||||
import ModalRight from "./Base/ModalRight.svelte";
|
||||
import { Utils } from "../Utils";
|
||||
import Hotkeys from "./Base/Hotkeys";
|
||||
|
||||
export let state: ThemeViewState;
|
||||
let layout = state.layout;
|
||||
|
@ -95,7 +96,8 @@
|
|||
|
||||
<div class="absolute top-0 right-0 mt-4 mr-4">
|
||||
<If condition={state.featureSwitches.featureSwitchSearch}>
|
||||
<Geosearch bounds={state.mapProperties.bounds} {selectedElement} {selectedLayer} perLayer={state.perLayer}></Geosearch>
|
||||
<Geosearch bounds={state.mapProperties.bounds} perLayer={state.perLayer} {selectedElement}
|
||||
{selectedLayer}></Geosearch>
|
||||
</If>
|
||||
</div>
|
||||
|
||||
|
@ -152,20 +154,22 @@
|
|||
<RasterLayerPicker {availableLayers} value={mapproperties.rasterLayer}></RasterLayerPicker>
|
||||
</If>
|
||||
</div>
|
||||
<div slot="title2" class="flex">
|
||||
<img src="./assets/svg/download.svg" class="w-4 h-4"/>
|
||||
<Tr t={Translations.t.general.download.title}/>
|
||||
<div class="flex" slot="title2">
|
||||
<If condition={state.featureSwitches.featureSwitchEnableExport}>
|
||||
<img class="w-4 h-4" src="./assets/svg/download.svg" />
|
||||
<Tr t={Translations.t.general.download.title} />
|
||||
</If>
|
||||
</div>
|
||||
<div slot="content2">
|
||||
<ToSvelte construct={() => new DownloadPanel(state)}/>
|
||||
<ToSvelte construct={() => new DownloadPanel(state)} />
|
||||
</div>
|
||||
|
||||
|
||||
<div slot="title3">
|
||||
<Tr t={Translations.t.general.attribution.title}/>
|
||||
<Tr t={Translations.t.general.attribution.title} />
|
||||
</div>
|
||||
|
||||
<ToSvelte slot="content3" construct={() => new CopyrightPanel(state)}></ToSvelte>
|
||||
|
||||
|
||||
<ToSvelte construct={() => new CopyrightPanel(state)} slot="content3"></ToSvelte>
|
||||
|
||||
|
||||
</TabbedGroup>
|
||||
</FloatOver>
|
||||
|
@ -177,17 +181,43 @@
|
|||
<FloatOver on:close={() => state.guistate.menuIsOpened.setData(false)}>
|
||||
<TabbedGroup tab={state.guistate.menuViewTabIndex}>
|
||||
<div class="flex" slot="title0">
|
||||
<Tr t={Translations.t.general.aboutMapcompleteTitle}></Tr>
|
||||
<Tr t={Translations.t.general.menu.aboutMapComplete} />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col" slot="content0">
|
||||
<Tr t={Translations.t.general.aboutMapcomplete.Subs({
|
||||
osmcha_link: Utils.OsmChaLinkFor(7),
|
||||
})}></Tr>
|
||||
|
||||
<Tr t={Translations.t.general.aboutMapComplete.intro} />
|
||||
|
||||
<a class="flex" href={Utils.HomepageLink()}>
|
||||
<img class="w-6 h-6" src="./assets/svg/add.svg">
|
||||
<Tr t={Translations.t.general.backToIndex} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href="https://github.com/pietervdvn/MapComplete/issues" target="_blank">
|
||||
<img class="w-6 h-6" src="./assets/svg/bug.svg">
|
||||
<Tr t={Translations.t.general.attribution.openIssueTracker} />
|
||||
</a>
|
||||
|
||||
|
||||
<a class="flex" href="https://en.osm.town/@MapComplete" target="_blank">
|
||||
<img class="w-6 h-6" src="./assets/svg/mastodon.svg">
|
||||
<Tr t={Translations.t.general.attribution.followOnMastodon} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href="https://liberapay.com/pietervdvn/" target="_blank">
|
||||
<img class="w-6 h-6" src="./assets/svg/liberapay.svg">
|
||||
<Tr t={Translations.t.general.attribution.donate} />
|
||||
</a>
|
||||
|
||||
<a class="flex" href={Utils.OsmChaLinkFor(7)} target="_blank">
|
||||
<img class="w-6 h-6" src="./assets/svg/statistics.svg">
|
||||
<Tr t={Translations.t.general.attribution.openOsmcha.Subs({theme: "MapComplete"})} />
|
||||
</a>
|
||||
{Constants.vNumber}
|
||||
<ToSvelte construct={Hotkeys.generateDocumentationDynamic}></ToSvelte>
|
||||
</div>
|
||||
|
||||
|
||||
<If condition={state.osmConnection.isLoggedIn} slot="title1">
|
||||
<div class="flex">
|
||||
<CogIcon class="w-6 h-6" />
|
||||
|
@ -199,16 +229,16 @@
|
|||
<!-- All shown components are set by 'usersettings.json', which happily uses some special visualisations created specifically for it -->
|
||||
<LoginToggle {state}>
|
||||
<div slot="not-logged-in">
|
||||
<Tr class="alert" t={Translations.t.userinfo.notLoggedIn}/>
|
||||
<Tr class="alert" t={Translations.t.userinfo.notLoggedIn} />
|
||||
<LoginButton osmConnection={state.osmConnection}></LoginButton>
|
||||
</div>
|
||||
<SelectedElementView
|
||||
layer={UserRelatedState.usersettingsConfig}
|
||||
selectedElement={({
|
||||
highlightedRendering={state.guistate.highlightedUserSetting}
|
||||
layer={UserRelatedState.usersettingsConfig} selectedElement={({
|
||||
type:"Feature",properties: {}, geometry: {type:"Point", coordinates: [0,0]}
|
||||
})} {state}
|
||||
tags={state.userRelatedState.preferencesAsTags}
|
||||
highlightedRendering={state.guistate.highlightedUserSetting}
|
||||
})}
|
||||
{state}
|
||||
tags={state.userRelatedState.preferencesAsTags}
|
||||
/>
|
||||
</LoginToggle>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,7 @@ import CompiledTranslations from "../../assets/generated/CompiledTranslations"
|
|||
import LanguageUtils from "../../Utils/LanguageUtils"
|
||||
|
||||
export default class Translations {
|
||||
static readonly t: typeof CompiledTranslations.t & Readonly<typeof CompiledTranslations.t> =
|
||||
CompiledTranslations.t
|
||||
static readonly t: Readonly<typeof CompiledTranslations.t> = CompiledTranslations.t
|
||||
private static knownLanguages = LanguageUtils.usedLanguages
|
||||
constructor() {
|
||||
throw "Translations is static. If you want to intitialize a new translation, use the singular form"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue