forked from MapComplete/MapComplete
Housekeeping: formatting
This commit is contained in:
parent
9d53a45f9a
commit
1528dfaae1
168 changed files with 3332 additions and 4560 deletions
|
|
@ -1,120 +1,120 @@
|
|||
<script lang="ts">
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import LocationInput from "../InputElement/Helpers/LocationInput.svelte"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Tiles } from "../../Models/TileRange"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import type { MapProperties } from "../../Models/MapProperties"
|
||||
import ShowDataLayer from "../Map/ShowDataLayer"
|
||||
import type {
|
||||
FeatureSource,
|
||||
FeatureSourceForLayer,
|
||||
} from "../../Logic/FeatureSource/FeatureSource"
|
||||
import SnappingFeatureSource from "../../Logic/FeatureSource/Sources/SnappingFeatureSource"
|
||||
import FeatureSourceMerger from "../../Logic/FeatureSource/Sources/FeatureSourceMerger"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { Utils } from "../../Utils"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import Move_arrows from "../../assets/svg/Move_arrows.svelte"
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization"
|
||||
import LocationInput from "../InputElement/Helpers/LocationInput.svelte"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Tiles } from "../../Models/TileRange"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import type { MapProperties } from "../../Models/MapProperties"
|
||||
import ShowDataLayer from "../Map/ShowDataLayer"
|
||||
import type {
|
||||
FeatureSource,
|
||||
FeatureSourceForLayer,
|
||||
} from "../../Logic/FeatureSource/FeatureSource"
|
||||
import SnappingFeatureSource from "../../Logic/FeatureSource/Sources/SnappingFeatureSource"
|
||||
import FeatureSourceMerger from "../../Logic/FeatureSource/Sources/FeatureSourceMerger"
|
||||
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:
|
||||
* - Show more layers
|
||||
* - Snap to layers
|
||||
*
|
||||
* This one is mostly used to insert new points, including when importing
|
||||
*/
|
||||
export let state: SpecialVisualizationState
|
||||
/**
|
||||
* The start coordinate
|
||||
*/
|
||||
export let coordinate: { lon: number; lat: number }
|
||||
/**
|
||||
* An advanced location input, which has support to:
|
||||
* - Show more layers
|
||||
* - Snap to layers
|
||||
*
|
||||
* This one is mostly used to insert new points, including when importing
|
||||
*/
|
||||
export let state: SpecialVisualizationState
|
||||
/**
|
||||
* The start coordinate
|
||||
*/
|
||||
export let coordinate: { lon: number; lat: number }
|
||||
|
||||
/**
|
||||
* The center of the map at all times
|
||||
* If undefined at the beginning, 'coordinate' will be used
|
||||
*/
|
||||
export let value: UIEventSource<{ lon: number; lat: number }>
|
||||
if (value.data === undefined) {
|
||||
value.setData(coordinate)
|
||||
/**
|
||||
* The center of the map at all times
|
||||
* If undefined at the beginning, 'coordinate' will be used
|
||||
*/
|
||||
export let value: UIEventSource<{ lon: number; lat: number }>
|
||||
if (value.data === undefined) {
|
||||
value.setData(coordinate)
|
||||
}
|
||||
if (coordinate === undefined) {
|
||||
coordinate = value.data
|
||||
}
|
||||
export let snapToLayers: string[] | undefined
|
||||
export let targetLayer: LayerConfig | undefined
|
||||
export let maxSnapDistance: number = undefined
|
||||
|
||||
export let snappedTo: UIEventSource<string | undefined>
|
||||
|
||||
let preciseLocation: UIEventSource<{ lon: number; lat: number }> = new UIEventSource<{
|
||||
lon: number
|
||||
lat: number
|
||||
}>(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher<{ click: { lon: number; lat: number } }>()
|
||||
|
||||
const xyz = Tiles.embedded_tile(coordinate.lat, coordinate.lon, 16)
|
||||
const map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined)
|
||||
let initialMapProperties: Partial<MapProperties> & { location } = {
|
||||
zoom: new UIEventSource<number>(19),
|
||||
maxbounds: new UIEventSource(undefined),
|
||||
/*If no snapping needed: the value is simply the map location;
|
||||
* If snapping is needed: the value will be set later on by the snapping feature source
|
||||
* */
|
||||
location:
|
||||
snapToLayers?.length > 0
|
||||
? new UIEventSource<{ lon: number; lat: number }>(coordinate)
|
||||
: value,
|
||||
bounds: new UIEventSource<BBox>(undefined),
|
||||
allowMoving: new UIEventSource<boolean>(true),
|
||||
allowZooming: new UIEventSource<boolean>(true),
|
||||
minzoom: new UIEventSource<number>(18),
|
||||
rasterLayer: UIEventSource.feedFrom(state.mapProperties.rasterLayer),
|
||||
}
|
||||
|
||||
if (targetLayer) {
|
||||
const featuresForLayer = state.perLayer.get(targetLayer.id)
|
||||
if (featuresForLayer) {
|
||||
new ShowDataLayer(map, {
|
||||
layer: targetLayer,
|
||||
features: featuresForLayer,
|
||||
})
|
||||
}
|
||||
if (coordinate === undefined) {
|
||||
coordinate = value.data
|
||||
}
|
||||
|
||||
if (snapToLayers?.length > 0) {
|
||||
const snapSources: FeatureSource[] = []
|
||||
for (const layerId of snapToLayers ?? []) {
|
||||
const layer: FeatureSourceForLayer = state.perLayer.get(layerId)
|
||||
snapSources.push(layer)
|
||||
if (layer.features === undefined) {
|
||||
continue
|
||||
}
|
||||
new ShowDataLayer(map, {
|
||||
layer: layer.layer.layerDef,
|
||||
zoomToFeatures: false,
|
||||
features: layer,
|
||||
})
|
||||
}
|
||||
export let snapToLayers: string[] | undefined
|
||||
export let targetLayer: LayerConfig | undefined
|
||||
export let maxSnapDistance: number = undefined
|
||||
const snappedLocation = new SnappingFeatureSource(
|
||||
new FeatureSourceMerger(...Utils.NoNull(snapSources)),
|
||||
// We snap to the (constantly updating) map location
|
||||
initialMapProperties.location,
|
||||
{
|
||||
maxDistance: maxSnapDistance ?? 15,
|
||||
allowUnsnapped: true,
|
||||
snappedTo,
|
||||
snapLocation: value,
|
||||
}
|
||||
)
|
||||
|
||||
export let snappedTo: UIEventSource<string | undefined>
|
||||
|
||||
let preciseLocation: UIEventSource<{ lon: number; lat: number }> = new UIEventSource<{
|
||||
lon: number
|
||||
lat: number
|
||||
}>(undefined)
|
||||
|
||||
const dispatch = createEventDispatcher<{ click: { lon: number; lat: number } }>()
|
||||
|
||||
const xyz = Tiles.embedded_tile(coordinate.lat, coordinate.lon, 16)
|
||||
const map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined)
|
||||
let initialMapProperties: Partial<MapProperties> & {location} = {
|
||||
zoom: new UIEventSource<number>(19),
|
||||
maxbounds: new UIEventSource(undefined),
|
||||
/*If no snapping needed: the value is simply the map location;
|
||||
* If snapping is needed: the value will be set later on by the snapping feature source
|
||||
* */
|
||||
location:
|
||||
snapToLayers?.length > 0
|
||||
? new UIEventSource<{ lon: number; lat: number }>(coordinate)
|
||||
: value,
|
||||
bounds: new UIEventSource<BBox>(undefined),
|
||||
allowMoving: new UIEventSource<boolean>(true),
|
||||
allowZooming: new UIEventSource<boolean>(true),
|
||||
minzoom: new UIEventSource<number>(18),
|
||||
rasterLayer: UIEventSource.feedFrom(state.mapProperties.rasterLayer),
|
||||
}
|
||||
|
||||
if (targetLayer) {
|
||||
const featuresForLayer = state.perLayer.get(targetLayer.id)
|
||||
if (featuresForLayer) {
|
||||
new ShowDataLayer(map, {
|
||||
layer: targetLayer,
|
||||
features: featuresForLayer,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (snapToLayers?.length > 0) {
|
||||
const snapSources: FeatureSource[] = []
|
||||
for (const layerId of snapToLayers ?? []) {
|
||||
const layer: FeatureSourceForLayer = state.perLayer.get(layerId)
|
||||
snapSources.push(layer)
|
||||
if (layer.features === undefined) {
|
||||
continue
|
||||
}
|
||||
new ShowDataLayer(map, {
|
||||
layer: layer.layer.layerDef,
|
||||
zoomToFeatures: false,
|
||||
features: layer,
|
||||
})
|
||||
}
|
||||
const snappedLocation = new SnappingFeatureSource(
|
||||
new FeatureSourceMerger(...Utils.NoNull(snapSources)),
|
||||
// We snap to the (constantly updating) map location
|
||||
initialMapProperties.location,
|
||||
{
|
||||
maxDistance: maxSnapDistance ?? 15,
|
||||
allowUnsnapped: true,
|
||||
snappedTo,
|
||||
snapLocation: value,
|
||||
}
|
||||
)
|
||||
|
||||
new ShowDataLayer(map, {
|
||||
layer: targetLayer,
|
||||
features: snappedLocation,
|
||||
})
|
||||
}
|
||||
new ShowDataLayer(map, {
|
||||
layer: targetLayer,
|
||||
features: snappedLocation,
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<LocationInput
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
<h5>{t.noMatchingThemes.toString()}</h5>
|
||||
<div class="flex justify-center">
|
||||
<button on:click={() => search.setData("")}>
|
||||
<Search_disable class="w-6 mr-2" />
|
||||
<Search_disable class="mr-2 w-6" />
|
||||
<Tr t={t.noSearch} />
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
let result = await Geocoding.reverse(
|
||||
mapProperties.location.data,
|
||||
mapProperties.zoom.data,
|
||||
Locale.language.data,
|
||||
Locale.language.data
|
||||
)
|
||||
let properties = result.features[0].properties
|
||||
currentLocation = properties.display_name
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
() => {
|
||||
displayLocation()
|
||||
},
|
||||
[Translations.t.hotkeyDocumentation.shakePhone],
|
||||
[Translations.t.hotkeyDocumentation.shakePhone]
|
||||
)
|
||||
|
||||
Motion.singleton.startListening()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
export let layer: LayerConfig
|
||||
export let selectedElement: Feature
|
||||
let tags: UIEventSource<Record<string, string>> = state.featureProperties.getStore(
|
||||
selectedElement.properties.id,
|
||||
selectedElement.properties.id
|
||||
)
|
||||
$: {
|
||||
tags = state.featureProperties.getStore(selectedElement.properties.id)
|
||||
|
|
@ -25,9 +25,9 @@
|
|||
{#if $tags._deleted === "yes"}
|
||||
<Tr t={Translations.t.delete.isDeleted} />
|
||||
{:else}
|
||||
<div class="low-interaction border-b-2 border-black px-3 drop-shadow-md flex">
|
||||
<div class="h-fit overflow-auto w-full sm:p-2" style="max-height: 20vh;">
|
||||
<div class="flex flex-col flex-grow w-full h-full ">
|
||||
<div class="low-interaction flex border-b-2 border-black px-3 drop-shadow-md">
|
||||
<div class="h-fit w-full overflow-auto sm:p-2" style="max-height: 20vh;">
|
||||
<div class="flex h-full w-full flex-grow flex-col">
|
||||
<!-- Title element and title icons-->
|
||||
<h3 class="m-0">
|
||||
<a href={`#${$tags.id}`}>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
class="no-weblate title-icons links-as-button mr-2 flex flex-row flex-wrap items-center gap-x-0.5 pt-0.5 sm:pt-1"
|
||||
>
|
||||
{#each layer.titleIcons as titleIconConfig}
|
||||
{#if (titleIconConfig.condition?.matchesProperties($tags) ?? true) && (titleIconConfig.metacondition?.matchesProperties({ ...$metatags, ...$tags }) ?? true) && titleIconConfig.IsKnown($tags)}
|
||||
{#if (titleIconConfig.condition?.matchesProperties($tags) ?? true) && (titleIconConfig.metacondition?.matchesProperties( { ...$metatags, ...$tags } ) ?? true) && titleIconConfig.IsKnown($tags)}
|
||||
<div class={titleIconConfig.renderIconClass ?? "flex h-8 w-8 items-center"}>
|
||||
<TagRenderingAnswer
|
||||
config={titleIconConfig}
|
||||
|
|
@ -59,17 +59,16 @@
|
|||
<button
|
||||
on:click={() => state.selectedElement.setData(undefined)}
|
||||
use:ariaLabel={Translations.t.general.backToMap}
|
||||
class="rounded-full border-none p-0 shrink-0 h-fit mt-2"
|
||||
class="mt-2 h-fit shrink-0 rounded-full border-none p-0"
|
||||
style="border: 0 !important; padding: 0 !important;"
|
||||
>
|
||||
<XCircleIcon aria-hidden={true} class="h-8 w-8" />
|
||||
</button>
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
:global(.title-icons a) {
|
||||
display: block !important;
|
||||
}
|
||||
:global(.title-icons a) {
|
||||
display: block !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@
|
|||
<Tr t={Translations.t.general.returnToTheMap} />
|
||||
</button>
|
||||
{:else}
|
||||
<div class="flex h-full flex-col gap-y-2 overflow-y-auto p-1 px-4 w-full selected-element-view" tabindex="-1">
|
||||
<div
|
||||
class="selected-element-view flex h-full w-full flex-col gap-y-2 overflow-y-auto p-1 px-4"
|
||||
tabindex="-1"
|
||||
>
|
||||
{#each $knownTagRenderings as config (config.id)}
|
||||
<TagRenderingEditable
|
||||
{tags}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
<div class="flex">
|
||||
{#if typeof navigator?.share === "function"}
|
||||
<button class="h-8 w-8 shrink-0 p-1" on:click={shareCurrentLink}>
|
||||
<Share/>
|
||||
<Share />
|
||||
</button>
|
||||
{/if}
|
||||
{#if navigator.clipboard !== undefined}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@
|
|||
whenUploaded?: () => void | Promise<void>
|
||||
} = undefined
|
||||
|
||||
|
||||
let t = Translations.t.general.uploadGpx
|
||||
let currentStep = new UIEventSource<"init" | "please_confirm" | "uploading" | "done" | "error">("init")
|
||||
let currentStep = new UIEventSource<"init" | "please_confirm" | "uploading" | "done" | "error">(
|
||||
"init"
|
||||
)
|
||||
|
||||
let traceVisibilities: {
|
||||
key: "private" | "public"
|
||||
|
|
@ -44,8 +45,9 @@
|
|||
},
|
||||
]
|
||||
|
||||
let gpxServerIsOnline: Store<boolean> = state.osmConnection.gpxServiceIsOnline.map((serviceState) => serviceState === "online")
|
||||
|
||||
let gpxServerIsOnline: Store<boolean> = state.osmConnection.gpxServiceIsOnline.map(
|
||||
(serviceState) => serviceState === "online"
|
||||
)
|
||||
|
||||
/**
|
||||
* More or less the same as the coalescing-operator '??', except that it checks for empty strings too
|
||||
|
|
@ -63,18 +65,17 @@
|
|||
let title: string = undefined
|
||||
let description: string = undefined
|
||||
|
||||
let visibility = <UIEventSource<"public" | "private">>state?.osmConnection?.GetPreference("gps.trace.visibility") ?? new UIEventSource<"public" | "private">("private")
|
||||
let visibility =
|
||||
<UIEventSource<"public" | "private">>(
|
||||
state?.osmConnection?.GetPreference("gps.trace.visibility")
|
||||
) ?? new UIEventSource<"public" | "private">("private")
|
||||
async function uploadTrace() {
|
||||
try {
|
||||
|
||||
currentStep.setData("uploading")
|
||||
const titleStr = createDefault(
|
||||
title,
|
||||
"Track with mapcomplete",
|
||||
)
|
||||
const titleStr = createDefault(title, "Track with mapcomplete")
|
||||
const descriptionStr = createDefault(
|
||||
description,
|
||||
"Track created with MapComplete with theme " + state?.layout?.id,
|
||||
"Track created with MapComplete with theme " + state?.layout?.id
|
||||
)
|
||||
await state?.osmConnection?.uploadGpxTrack(trace(titleStr), {
|
||||
visibility: visibility.data ?? "private",
|
||||
|
|
@ -95,47 +96,58 @@
|
|||
</script>
|
||||
|
||||
<LoginToggle {state}>
|
||||
|
||||
{#if !$gpxServerIsOnline}
|
||||
<div class="flex border alert items-center">
|
||||
<Invalid class="w-8 h-8 m-2" />
|
||||
<div class="alert flex items-center border">
|
||||
<Invalid class="m-2 h-8 w-8" />
|
||||
<Tr t={t.gpxServiceOffline} cls="p-2" />
|
||||
</div>
|
||||
{:else if $currentStep === "error"}
|
||||
<div class="alert flex w-full gap-x-2">
|
||||
<Invalid class="w-8 h-8"/>
|
||||
<Invalid class="h-8 w-8" />
|
||||
<Tr t={Translations.t.general.error} />
|
||||
</div>
|
||||
{:else if $currentStep === "init"}
|
||||
<button class="flex w-full m-0" on:click={() => {currentStep.setData("please_confirm")}}>
|
||||
<Upload class="w-12 h-12" />
|
||||
<button
|
||||
class="m-0 flex w-full"
|
||||
on:click={() => {
|
||||
currentStep.setData("please_confirm")
|
||||
}}
|
||||
>
|
||||
<Upload class="h-12 w-12" />
|
||||
<Tr t={t.title} />
|
||||
</button>
|
||||
{:else if $currentStep === "please_confirm"}
|
||||
<form on:submit|preventDefault={() => uploadTrace()}
|
||||
class="flex flex-col border-interactive interactive px-2 gap-y-1">
|
||||
<form
|
||||
on:submit|preventDefault={() => uploadTrace()}
|
||||
class="border-interactive interactive flex flex-col gap-y-1 px-2"
|
||||
>
|
||||
<h2>
|
||||
<Tr t={t.title} />
|
||||
</h2>
|
||||
<Tr t={t.intro0} />
|
||||
<Tr t={t.intro1} />
|
||||
|
||||
|
||||
<h3>
|
||||
<Tr t={t.meta.title} />
|
||||
</h3>
|
||||
<Tr t={t.meta.intro} />
|
||||
<input type="text" use:ariaLabel={t.meta.titlePlaceholder} use:placeholder={t.meta.titlePlaceholder}
|
||||
bind:value={title} />
|
||||
<input
|
||||
type="text"
|
||||
use:ariaLabel={t.meta.titlePlaceholder}
|
||||
use:placeholder={t.meta.titlePlaceholder}
|
||||
bind:value={title}
|
||||
/>
|
||||
<Tr t={t.meta.descriptionIntro} />
|
||||
|
||||
<textarea use:ariaLabel={t.meta.descriptionPlaceHolder} use:placeholder={t.meta.descriptionPlaceHolder}
|
||||
bind:value={description} />
|
||||
<textarea
|
||||
use:ariaLabel={t.meta.descriptionPlaceHolder}
|
||||
use:placeholder={t.meta.descriptionPlaceHolder}
|
||||
bind:value={description}
|
||||
/>
|
||||
|
||||
<Tr t={t.choosePermission} />
|
||||
|
||||
{#each traceVisibilities as option}
|
||||
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
|
|
@ -151,30 +163,25 @@
|
|||
</label>
|
||||
{/each}
|
||||
|
||||
|
||||
<div class="flex flex-wrap-reverse justify-between items-stretch">
|
||||
<button class="flex gap-x-2 w-1/2 flex-grow" on:click={() => currentStep.setData("init")}>
|
||||
<Close class="w-8 h-8" />
|
||||
<div class="flex flex-wrap-reverse items-stretch justify-between">
|
||||
<button class="flex w-1/2 flex-grow gap-x-2" on:click={() => currentStep.setData("init")}>
|
||||
<Close class="h-8 w-8" />
|
||||
<Tr t={Translations.t.general.cancel} />
|
||||
</button>
|
||||
|
||||
<button class="flex gap-x-2 primary flex-grow" on:click={() => uploadTrace()}>
|
||||
<Upload class="w-8 h-8" />
|
||||
<button class="primary flex flex-grow gap-x-2" on:click={() => uploadTrace()}>
|
||||
<Upload class="h-8 w-8" />
|
||||
<Tr t={t.confirm} />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
{:else if $currentStep === "uploading"}
|
||||
<Loading>
|
||||
<Tr t={t.uploading} />
|
||||
</Loading>
|
||||
|
||||
|
||||
{:else if $currentStep === "done"}
|
||||
<div class="flex p-2 rounded-xl border-2 subtle-border items-center">
|
||||
<Confirm class="w-12 h-12 mr-2" />
|
||||
<div class="subtle-border flex items-center rounded-xl border-2 p-2">
|
||||
<Confirm class="mr-2 h-12 w-12" />
|
||||
<Tr t={t.uploadFinished} />
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue