forked from MapComplete/MapComplete
Chore: Housekeeping
This commit is contained in:
parent
ef0ba091eb
commit
319c0e2573
77 changed files with 2485 additions and 1727 deletions
|
|
@ -27,7 +27,7 @@
|
|||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login",
|
||||
"Used to complete the login"
|
||||
),
|
||||
})
|
||||
const state = new UserRelatedState(osmConnection)
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
let userLanguages = osmConnection.userDetails.map((ud) => ud.languages)
|
||||
let themeSearchText: UIEventSource<string | undefined> = new UIEventSource<string>(undefined)
|
||||
|
||||
document.addEventListener("keydown", function(event) {
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.ctrlKey && event.code === "KeyF") {
|
||||
document.getElementById("theme-search")?.focus()
|
||||
event.preventDefault()
|
||||
|
|
@ -50,17 +50,15 @@
|
|||
{
|
||||
const prefix = "mapcomplete-hidden-theme-"
|
||||
const userPreferences = state.osmConnection.preferencesHandler.preferences
|
||||
visitedHiddenThemes = userPreferences.map(preferences => {
|
||||
visitedHiddenThemes = userPreferences.map((preferences) => {
|
||||
const knownIds = new Set<string>(
|
||||
Object.keys(preferences)
|
||||
.filter((key) => key.startsWith(prefix))
|
||||
.map((key) => key.substring(prefix.length, key.length - "-enabled".length)),
|
||||
.map((key) => key.substring(prefix.length, key.length - "-enabled".length))
|
||||
)
|
||||
return hiddenThemes.filter((theme) => knownIds.has(theme.id))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="m-4 flex flex-col">
|
||||
|
|
@ -87,14 +85,22 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="flex justify-center" on:submit|preventDefault={_ => MoreScreen.applySearch(themeSearchText.data)}>
|
||||
<form
|
||||
class="flex justify-center"
|
||||
on:submit|preventDefault={(_) => MoreScreen.applySearch(themeSearchText.data)}
|
||||
>
|
||||
<label
|
||||
class="flex rounded-full border-2 border-black items-center my-2 w-full sm:w-1/2 neutral-label">
|
||||
<SearchIcon aria-hidden="true" class="w-8 h-8" />
|
||||
<input autofocus bind:value={$themeSearchText} class="mr-4 w-full" id="theme-search"
|
||||
type="search"
|
||||
use:placeholder={tr.searchForATheme}>
|
||||
class="neutral-label my-2 flex w-full items-center rounded-full border-2 border-black sm:w-1/2"
|
||||
>
|
||||
<SearchIcon aria-hidden="true" class="h-8 w-8" />
|
||||
<input
|
||||
autofocus
|
||||
bind:value={$themeSearchText}
|
||||
class="mr-4 w-full"
|
||||
id="theme-search"
|
||||
type="search"
|
||||
use:placeholder={tr.searchForATheme}
|
||||
/>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
|
|
@ -113,10 +119,12 @@
|
|||
<Tr t={tr.previouslyHiddenTitle} />
|
||||
</h3>
|
||||
<p>
|
||||
<Tr t={tr.hiddenExplanation.Subs({
|
||||
hidden_discovered: $visitedHiddenThemes.length.toString(),
|
||||
total_hidden: hiddenThemes.length.toString(),
|
||||
})} />
|
||||
<Tr
|
||||
t={tr.hiddenExplanation.Subs({
|
||||
hidden_discovered: $visitedHiddenThemes.length.toString(),
|
||||
total_hidden: hiddenThemes.length.toString(),
|
||||
})}
|
||||
/>
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
</ThemesList>
|
||||
|
|
@ -144,8 +152,6 @@
|
|||
<Eye class="mr-2 h-6 w-6" />
|
||||
<Tr t={Translations.t.privacy.title} />
|
||||
</a>
|
||||
|
||||
|
||||
</LoginToggle>
|
||||
|
||||
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro} />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
const dispatch = createEventDispatcher<{ close }>()
|
||||
|
||||
export let extraClasses = "p-4 md:p-6"
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Draw the background over the total screen -->
|
||||
|
|
@ -27,17 +26,14 @@
|
|||
style="z-index: 21"
|
||||
use:trapFocus
|
||||
>
|
||||
<div
|
||||
class="content normal-background"
|
||||
on:click|stopPropagation={() => {}}
|
||||
>
|
||||
<div class="content normal-background" on:click|stopPropagation={() => {}}>
|
||||
<div class="h-full rounded-xl">
|
||||
<slot />
|
||||
</div>
|
||||
<slot name="close-button">
|
||||
<!-- The close button is placed _after_ the default slot in order to always paint it on top -->
|
||||
<button
|
||||
class="absolute right-10 top-10 h-8 w-8 cursor-pointer border-none bg-white rounded-full p-0"
|
||||
class="absolute right-10 top-10 h-8 w-8 cursor-pointer rounded-full border-none bg-white p-0"
|
||||
on:click={() => dispatch("close")}
|
||||
>
|
||||
<XCircleIcon />
|
||||
|
|
@ -47,10 +43,10 @@
|
|||
</div>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
height: 100%;
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: hidden;
|
||||
box-shadow: 0 0 1rem #00000088;
|
||||
}
|
||||
.content {
|
||||
height: 100%;
|
||||
border-radius: 0.5rem;
|
||||
overflow-x: hidden;
|
||||
box-shadow: 0 0 1rem #00000088;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
<script lang="ts">
|
||||
export let text : string
|
||||
export let href : string
|
||||
export let classnames : string = undefined
|
||||
export let download : string = undefined
|
||||
export let ariaLabel : string = undefined
|
||||
|
||||
export let text: string
|
||||
export let href: string
|
||||
export let classnames: string = undefined
|
||||
export let download: string = undefined
|
||||
export let ariaLabel: string = undefined
|
||||
|
||||
export let newTab: boolean = false
|
||||
</script>
|
||||
|
||||
<a {href} aria-label={ariaLabel} target={newTab ? "_blank" : undefined} {download} class={classnames}>
|
||||
{@html text}</a>
|
||||
<a
|
||||
{href}
|
||||
aria-label={ariaLabel}
|
||||
target={newTab ? "_blank" : undefined}
|
||||
{download}
|
||||
class={classnames}
|
||||
>
|
||||
{@html text}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -9,15 +9,14 @@
|
|||
*/
|
||||
const dispatch = createEventDispatcher()
|
||||
export let cls = "m-0.5 p-0.5 sm:p-1 md:m-1"
|
||||
export let arialabel: Translation = undefined
|
||||
export let arialabel: Translation = undefined
|
||||
</script>
|
||||
|
||||
|
||||
<button
|
||||
on:click={(e) => dispatch("click", e)}
|
||||
on:keydown
|
||||
use:ariaLabel={arialabel}
|
||||
class={twJoin("relative pointer-events-auto h-fit w-fit rounded-full", cls)}
|
||||
class={twJoin("pointer-events-auto relative h-fit w-fit rounded-full", cls)}
|
||||
>
|
||||
<slot />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<div
|
||||
aria-modal="true"
|
||||
autofocus
|
||||
class="absolute top-0 right-0 h-screen w-full overflow-y-auto drop-shadow-2xl md:w-6/12 lg:w-5/12 xl:w-4/12 normal-background flex flex-col"
|
||||
class="normal-background absolute top-0 right-0 flex h-screen w-full flex-col overflow-y-auto drop-shadow-2xl md:w-6/12 lg:w-5/12 xl:w-4/12"
|
||||
role="dialog"
|
||||
style="max-width: 100vw; max-height: 100vh"
|
||||
tabindex="-1"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined))
|
||||
|
||||
const showButton = state.osmConnection.userDetails.map(
|
||||
(ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible,
|
||||
(ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible
|
||||
)
|
||||
|
||||
function openJosm() {
|
||||
|
|
@ -35,8 +35,7 @@
|
|||
|
||||
{#if $showButton}
|
||||
<div class="flex">
|
||||
|
||||
<button class="flex items-center small soft grow" on:click={openJosm}>
|
||||
<button class="small soft flex grow items-center" on:click={openJosm}>
|
||||
<Josm_logo class="h-6 w-6 pr-2" />
|
||||
<Tr t={t.editJosm} />
|
||||
</button>
|
||||
|
|
@ -49,5 +48,4 @@
|
|||
<Tr cls="alert shrink-0 w-fit" t={t.josmNotOpened} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -11,13 +11,11 @@
|
|||
export let cls: string = ""
|
||||
// Text for the current language
|
||||
let txt: Store<string | undefined> = t?.current
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{#if $txt}
|
||||
<span class={cls}>
|
||||
<FromHtml src={$txt}/>
|
||||
<FromHtml src={$txt} />
|
||||
<WeblateLink context={t.context} />
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
</script>
|
||||
|
||||
<div class="m-2 flex flex-col">
|
||||
|
||||
<h2 class="flex items-center">
|
||||
<Filter class="h-6 w-6 pr-2" />
|
||||
<Tr t={Translations.t.general.menu.filter} />
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
return state.sync(
|
||||
(f) => f === 0,
|
||||
[],
|
||||
(b) => (b ? 0 : undefined),
|
||||
(b) => (b ? 0 : undefined)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +48,7 @@
|
|||
} else {
|
||||
mainElem?.classList?.remove("glowing-shadow")
|
||||
}
|
||||
}),
|
||||
})
|
||||
)
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
export let state: ThemeViewState
|
||||
let geolocationstate = state.geolocation.geolocationState
|
||||
let geopermission: Store<GeolocationPermissionState> = state.geolocation.geolocationState.permission
|
||||
let geopermission: Store<GeolocationPermissionState> =
|
||||
state.geolocation.geolocationState.permission
|
||||
let allowMoving = geolocationstate.allowMoving
|
||||
let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation
|
||||
let geolocationControlState = state.geolocationControl
|
||||
|
|
@ -18,7 +19,7 @@
|
|||
|
||||
{#if !$allowMoving}
|
||||
<Location_locked class="h-8 w-8" />
|
||||
{:else if $currentGPSLocation !== undefined }
|
||||
{:else if $currentGPSLocation !== undefined}
|
||||
<!-- If we have a location; this implies that the location access was granted -->
|
||||
{#if $lastClickWasRecent}
|
||||
<Location_unlocked class="h-8 w-8" />
|
||||
|
|
@ -29,15 +30,9 @@
|
|||
<Location class="h-8 w-8" />
|
||||
{:else if $geopermission === "requested"}
|
||||
<!-- Even though disabled, when clicking we request the location again in case the contributor dismissed the location popup -->
|
||||
<Location
|
||||
class="h-8 w-8"
|
||||
style="animation: 3s linear 0s infinite normal none running spin;"
|
||||
/>
|
||||
<Location class="h-8 w-8" style="animation: 3s linear 0s infinite normal none running spin;" />
|
||||
{:else if $geopermission === "denied"}
|
||||
<Location_refused class="h-8 w-8" />
|
||||
{:else}
|
||||
<Location
|
||||
class="h-8 w-8"
|
||||
style="animation: 3s linear 0s infinite normal none running spin;"
|
||||
/>
|
||||
<Location class="h-8 w-8" style="animation: 3s linear 0s infinite normal none running spin;" />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
onDestroy(
|
||||
triggerSearch.addCallback((_) => {
|
||||
performSearch()
|
||||
}),
|
||||
})
|
||||
)
|
||||
|
||||
let isRunning: boolean = false
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
new BBox([
|
||||
[lon0, lat0],
|
||||
[lon1, lat1],
|
||||
]).pad(0.01),
|
||||
]).pad(0.01)
|
||||
)
|
||||
if (perLayer !== undefined) {
|
||||
const id = poi.osm_type + "/" + poi.osm_id
|
||||
|
|
@ -102,7 +102,7 @@
|
|||
</script>
|
||||
|
||||
<div class="normal-background flex justify-between rounded-full pl-2">
|
||||
<form class="w-full flex flex-wrap">
|
||||
<form class="flex w-full flex-wrap">
|
||||
{#if isRunning}
|
||||
<Loading>{Translations.t.general.search.searching}</Loading>
|
||||
{:else}
|
||||
|
|
@ -110,13 +110,16 @@
|
|||
type="search"
|
||||
class="w-full"
|
||||
bind:this={inputElement}
|
||||
on:keypress={(keypr) =>{ feedback = undefined; return (keypr.key === "Enter" ? performSearch() : undefined); }}
|
||||
on:keypress={(keypr) => {
|
||||
feedback = undefined
|
||||
return keypr.key === "Enter" ? performSearch() : undefined
|
||||
}}
|
||||
bind:value={searchContents}
|
||||
use:placeholder={Translations.t.general.search.search}
|
||||
/>
|
||||
{#if feedback !== undefined}
|
||||
<!-- The feedback is _always_ shown for screenreaders and to make sure that the searchfield can still be selected by tabbing-->
|
||||
<div class="alert " role="alert" aria-live="assertive">
|
||||
<div class="alert" role="alert" aria-live="assertive">
|
||||
{feedback}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
</script>
|
||||
|
||||
<a class="flex items-center" href={mapillaryLink} target="_blank">
|
||||
<Mapillary_black class={twMerge("shrink-0",large ? "m-2 mr-4 h-12 w-12" : "w-6 h-6 pr-2")} />
|
||||
<Mapillary_black class={twMerge("shrink-0", large ? "m-2 mr-4 h-12 w-12" : "h-6 w-6 pr-2")} />
|
||||
{#if large}
|
||||
<div class="flex flex-col">
|
||||
<Tr t={Translations.t.general.attribution.openMapillary} />
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@
|
|||
export let hideTooltip = false
|
||||
</script>
|
||||
|
||||
<MapControlButton arialabel={Translations.t.general.labels.background}
|
||||
on:click={() => state.guistate.backgroundLayerSelectionIsOpened.setData(true)}>
|
||||
<MapControlButton
|
||||
arialabel={Translations.t.general.labels.background}
|
||||
on:click={() => state.guistate.backgroundLayerSelectionIsOpened.setData(true)}
|
||||
>
|
||||
<Square3Stack3dIcon class="h-6 w-6" />
|
||||
{#if !hideTooltip}
|
||||
<Tr cls="mx-2" t={Translations.t.general.backgroundSwitch} />
|
||||
|
|
|
|||
|
|
@ -1,52 +1,58 @@
|
|||
<script lang="ts">/**
|
||||
* Shows the current address when shaken
|
||||
**/
|
||||
import Motion from "../../Sensors/Motion"
|
||||
import { Geocoding } from "../../Logic/Osm/Geocoding"
|
||||
import type { MapProperties } from "../../Models/MapProperties"
|
||||
import Hotkeys from "../Base/Hotkeys"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Locale from "../i18n/Locale"
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Shows the current address when shaken
|
||||
**/
|
||||
import Motion from "../../Sensors/Motion"
|
||||
import { Geocoding } from "../../Logic/Osm/Geocoding"
|
||||
import type { MapProperties } from "../../Models/MapProperties"
|
||||
import Hotkeys from "../Base/Hotkeys"
|
||||
import Translations from "../i18n/Translations"
|
||||
import Locale from "../i18n/Locale"
|
||||
|
||||
export let mapProperties: MapProperties
|
||||
let lastDisplayed: Date = undefined
|
||||
let currentLocation: string = undefined
|
||||
export let mapProperties: MapProperties
|
||||
let lastDisplayed: Date = undefined
|
||||
let currentLocation: string = undefined
|
||||
|
||||
async function displayLocation() {
|
||||
lastDisplayed = new Date()
|
||||
let result = await Geocoding.reverse(
|
||||
mapProperties.location.data,
|
||||
mapProperties.zoom.data,
|
||||
Locale.language.data
|
||||
)
|
||||
let properties = result.features[0].properties
|
||||
currentLocation = properties.display_name
|
||||
window.setTimeout(() => {
|
||||
if(properties.display_name !== currentLocation){
|
||||
async function displayLocation() {
|
||||
lastDisplayed = new Date()
|
||||
let result = await Geocoding.reverse(
|
||||
mapProperties.location.data,
|
||||
mapProperties.zoom.data,
|
||||
Locale.language.data
|
||||
)
|
||||
let properties = result.features[0].properties
|
||||
currentLocation = properties.display_name
|
||||
window.setTimeout(() => {
|
||||
if (properties.display_name !== currentLocation) {
|
||||
return
|
||||
}
|
||||
currentLocation = undefined
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
Motion.singleton.lastShakeEvent.addCallbackD((shaken) => {
|
||||
if (lastDisplayed !== undefined && shaken.getTime() - lastDisplayed.getTime() < 2000) {
|
||||
return
|
||||
}
|
||||
currentLocation = undefined
|
||||
}, 5000)
|
||||
}
|
||||
|
||||
Motion.singleton.lastShakeEvent.addCallbackD(shaken => {
|
||||
if (lastDisplayed !== undefined && shaken.getTime() - lastDisplayed.getTime() < 2000) {
|
||||
return
|
||||
}
|
||||
displayLocation()
|
||||
})
|
||||
Hotkeys.RegisterHotkey({ nomod: "q" },
|
||||
Translations.t.hotkeyDocumentation.queryCurrentLocation,
|
||||
() => {
|
||||
displayLocation()
|
||||
})
|
||||
Hotkeys.RegisterHotkey(
|
||||
{ nomod: "q" },
|
||||
Translations.t.hotkeyDocumentation.queryCurrentLocation,
|
||||
() => {
|
||||
displayLocation()
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Motion.singleton.startListening()
|
||||
Motion.singleton.startListening()
|
||||
</script>
|
||||
|
||||
{#if currentLocation}
|
||||
<div role="alert" aria-live="assertive" class="normal-background rounded-full border-interactive px-2">
|
||||
<div
|
||||
role="alert"
|
||||
aria-live="assertive"
|
||||
class="normal-background border-interactive rounded-full px-2"
|
||||
>
|
||||
{currentLocation}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
class="no-weblate title-icons links-as-button mr-2 flex flex-row flex-wrap items-center gap-x-0.5 p-1 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}
|
||||
|
|
@ -53,16 +53,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<button on:click={() => state.selectedElement.setData(undefined)}
|
||||
use:ariaLabel={Translations.t.general.backToMap}
|
||||
class="border-none p-0 rounded-full">
|
||||
<button
|
||||
on:click={() => state.selectedElement.setData(undefined)}
|
||||
use:ariaLabel={Translations.t.general.backToMap}
|
||||
class="rounded-full border-none p-0"
|
||||
>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -19,22 +19,23 @@
|
|||
state.selectedElement.setData(feature)
|
||||
}
|
||||
|
||||
let bearingAndDist: Store<{ bearing: number, dist: number }> = state.mapProperties.location.map(l => {
|
||||
let bearingAndDist: Store<{ bearing: number; dist: number }> = state.mapProperties.location.map(
|
||||
(l) => {
|
||||
let fcenter = GeoOperations.centerpointCoordinates(feature)
|
||||
let mapCenter = [l.lon, l.lat]
|
||||
|
||||
let bearing = Math.round(GeoOperations.bearing(fcenter, mapCenter))
|
||||
let dist = Math.round(GeoOperations.distanceBetween(fcenter, mapCenter))
|
||||
return { bearing, dist }
|
||||
},
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="cursor-pointer small flex" on:click={() => select()}>
|
||||
<div class="small flex cursor-pointer" on:click={() => select()}>
|
||||
<span class="flex">
|
||||
{#if i !== undefined}
|
||||
<span class="font-bold">{i + 1}.</span>
|
||||
{/if}
|
||||
{#if i !== undefined}
|
||||
<span class="font-bold">{i + 1}.</span>
|
||||
{/if}
|
||||
<TagRenderingAnswer config={layer.title} {layer} selectedElement={feature} {state} {tags} />
|
||||
{$bearingAndDist.dist}m {$bearingAndDist.bearing}°
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@
|
|||
|
||||
<If condition={state.featureSwitches.featureSwitchSearch}>
|
||||
<div
|
||||
class=".button low-interaction m-1 flex flex-wrap h-fit w-full items-center justify-end gap-x-2 gap-y-2 rounded border p-1"
|
||||
class=".button low-interaction m-1 flex h-fit w-full flex-wrap items-center justify-end gap-x-2 gap-y-2 rounded border p-1"
|
||||
>
|
||||
<div style="min-width: 16rem; " class="grow">
|
||||
<Geosearch
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
</div>
|
||||
<button
|
||||
class={twJoin(
|
||||
"flex shrink-0 w-fit items-center justify-between gap-x-2 small",
|
||||
"small flex w-fit shrink-0 items-center justify-between gap-x-2",
|
||||
!searchEnabled && "disabled"
|
||||
)}
|
||||
on:click={() => triggerSearch.ping()}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
{#if filteredThemes.length === 0}
|
||||
<NoThemeResultButton {search} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,7 @@
|
|||
</script>
|
||||
|
||||
{#if customThemes.length > 0}
|
||||
<ThemesList
|
||||
{search}
|
||||
{state}
|
||||
themes={customThemes}
|
||||
isCustom={true}
|
||||
hideThemes={false}
|
||||
>
|
||||
<ThemesList {search} {state} themes={customThemes} isCustom={true} hideThemes={false}>
|
||||
<svelte:fragment slot="title">
|
||||
<h3>
|
||||
<Tr t={t.customThemeTitle} />
|
||||
|
|
|
|||
|
|
@ -17,26 +17,27 @@
|
|||
const t = Translations.t.general.visualFeedback
|
||||
let centerFeatures = state.closestFeatures.features
|
||||
|
||||
let lastAction: UIEventSource<KeyNavigationEvent> = new UIEventSource<KeyNavigationEvent>(undefined)
|
||||
let lastAction: UIEventSource<KeyNavigationEvent> = new UIEventSource<KeyNavigationEvent>(
|
||||
undefined
|
||||
)
|
||||
state.mapProperties.onKeyNavigationEvent((event) => {
|
||||
lastAction.setData(event)
|
||||
})
|
||||
lastAction.stabilized(750).addCallbackAndRunD(_ => lastAction.setData(undefined))
|
||||
lastAction.stabilized(750).addCallbackAndRunD((_) => lastAction.setData(undefined))
|
||||
</script>
|
||||
<div aria-live="assertive" class="p-1" role="alert">
|
||||
|
||||
<div aria-live="assertive" class="p-1" role="alert">
|
||||
{#if $lastAction !== undefined}
|
||||
<Tr t={t[$lastAction.key]} />
|
||||
{:else if $centerFeatures.length === 0}
|
||||
<Tr t={t.noCloseFeatures} />
|
||||
{:else}
|
||||
<div class="pointer-events-auto">
|
||||
<Tr t={t.closestFeaturesAre.Subs({n: $featuresInViewPort?.length})} />
|
||||
<Tr t={t.closestFeaturesAre.Subs({ n: $featuresInViewPort?.length })} />
|
||||
<ol class="list-none">
|
||||
{#each $centerFeatures as feat, i (feat.properties.id)}
|
||||
<li class="flex">
|
||||
|
||||
<Summary {state} feature={feat} {i}/>
|
||||
<Summary {state} feature={feat} {i} />
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
let gotMeasurement = o.gotMeasurement
|
||||
o.startMeasurements()
|
||||
</script>
|
||||
|
||||
{#if !$gotMeasurement}
|
||||
No device orientation data available
|
||||
{:else}
|
||||
|
|
|
|||
|
|
@ -19,16 +19,20 @@
|
|||
</script>
|
||||
|
||||
<div class="relative">
|
||||
<img bind:this={imgEl}
|
||||
class={imgClass ?? ""}
|
||||
class:cursor-pointer={previewedImage !== undefined}
|
||||
on:click={() => {previewedImage?.setData(image)}}
|
||||
on:error={(event) => {
|
||||
if(fallbackImage){
|
||||
imgEl.src = fallbackImage
|
||||
}
|
||||
}}
|
||||
src={image.url}>
|
||||
<img
|
||||
bind:this={imgEl}
|
||||
class={imgClass ?? ""}
|
||||
class:cursor-pointer={previewedImage !== undefined}
|
||||
on:click={() => {
|
||||
previewedImage?.setData(image)
|
||||
}}
|
||||
on:error={(event) => {
|
||||
if (fallbackImage) {
|
||||
imgEl.src = fallbackImage
|
||||
}
|
||||
}}
|
||||
src={image.url}
|
||||
/>
|
||||
|
||||
<div class="absolute bottom-0 left-0">
|
||||
<ImageAttribution {image} />
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@
|
|||
<div class="flex flex-col">
|
||||
{#if $license.title}
|
||||
{#if $license.informationLocation}
|
||||
<a href={$license.informationLocation.href} target="_blank" rel="noopener nofollower">{$license.title}</a>
|
||||
<a href={$license.informationLocation.href} target="_blank" rel="noopener nofollower">
|
||||
{$license.title}
|
||||
</a>
|
||||
{:else}
|
||||
$license.title
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,11 @@
|
|||
|
||||
<div class="flex w-fit shrink-0 flex-col">
|
||||
<div class="cursor-zoom-in" on:click={() => state.previewedImage.setData(providedImage)}>
|
||||
<AttributedImage image={providedImage} imgClass="max-h-64 w-auto" previewedImage="{state.previewedImage}"/>
|
||||
<AttributedImage
|
||||
image={providedImage}
|
||||
imgClass="max-h-64 w-auto"
|
||||
previewedImage={state.previewedImage}
|
||||
/>
|
||||
</div>
|
||||
{#if linkable}
|
||||
<label>
|
||||
|
|
|
|||
|
|
@ -28,13 +28,14 @@
|
|||
<LoginToggle {state}>
|
||||
{#if expanded}
|
||||
<NearbyImages {tags} {state} {lon} {lat} {feature} {linkable} {layer}>
|
||||
<button slot="corner"
|
||||
class="h-6 w-6 cursor-pointer no-image-background p-0 border-none"
|
||||
use:ariaLabel={t.close}
|
||||
|
||||
on:click={() => {
|
||||
expanded = false
|
||||
}}>
|
||||
<button
|
||||
slot="corner"
|
||||
class="no-image-background h-6 w-6 cursor-pointer border-none p-0"
|
||||
use:ariaLabel={t.close}
|
||||
on:click={() => {
|
||||
expanded = false
|
||||
}}
|
||||
>
|
||||
<XCircleIcon />
|
||||
</button>
|
||||
</NearbyImages>
|
||||
|
|
@ -42,8 +43,8 @@
|
|||
<button
|
||||
class="flex w-full items-center"
|
||||
on:click={() => {
|
||||
expanded = true
|
||||
}}
|
||||
expanded = true
|
||||
}}
|
||||
aria-expanded={expanded}
|
||||
>
|
||||
<Camera_plus class="mr-2 block h-8 w-8 p-1" />
|
||||
|
|
|
|||
|
|
@ -17,18 +17,16 @@
|
|||
let featureBearing: number = 45
|
||||
if (feature?.geometry?.type === "LineString") {
|
||||
/* Bearing between -180 and + 180, positive is clockwise*/
|
||||
featureBearing = Math.round(GeoOperations.bearing(
|
||||
feature.geometry.coordinates[0],
|
||||
feature.geometry.coordinates.at(-1),
|
||||
))
|
||||
featureBearing = Math.round(
|
||||
GeoOperations.bearing(feature.geometry.coordinates[0], feature.geometry.coordinates.at(-1))
|
||||
)
|
||||
}
|
||||
|
||||
let previewDegrees: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
let previewPercentage: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
|
||||
|
||||
function degreesToPercentage(beta: number): string {
|
||||
const perc = Math.tan(beta * Math.PI / 180) * 100
|
||||
const perc = Math.tan((beta * Math.PI) / 180) * 100
|
||||
const rounded = Math.round(perc / 2.5) * 2.5
|
||||
return rounded + "%"
|
||||
}
|
||||
|
|
@ -40,7 +38,7 @@
|
|||
|
||||
let gotMeasurement = orientation.gotMeasurement
|
||||
|
||||
let valuesign = alpha.map(phoneBearing => {
|
||||
let valuesign = alpha.map((phoneBearing) => {
|
||||
if (featureBearing === undefined) {
|
||||
return 1
|
||||
}
|
||||
|
|
@ -56,31 +54,30 @@
|
|||
} else {
|
||||
return -1
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
beta.map(beta => {
|
||||
// As one moves forward on a way, a positive incline gets higher, and a negative incline gets lower.
|
||||
let valueSign = valuesign.data
|
||||
beta.map(
|
||||
(beta) => {
|
||||
// As one moves forward on a way, a positive incline gets higher, and a negative incline gets lower.
|
||||
let valueSign = valuesign.data
|
||||
|
||||
if (mode === "degrees") {
|
||||
value.setData(valueSign * beta + "°")
|
||||
} else {
|
||||
value.setData(degreesToPercentage(valueSign * beta))
|
||||
}
|
||||
|
||||
previewDegrees.setData(beta + "°")
|
||||
previewPercentage.setData(degreesToPercentage(beta))
|
||||
|
||||
}, [valuesign, beta])
|
||||
if (mode === "degrees") {
|
||||
value.setData(valueSign * beta + "°")
|
||||
} else {
|
||||
value.setData(degreesToPercentage(valueSign * beta))
|
||||
}
|
||||
|
||||
previewDegrees.setData(beta + "°")
|
||||
previewPercentage.setData(degreesToPercentage(beta))
|
||||
},
|
||||
[valuesign, beta]
|
||||
)
|
||||
</script>
|
||||
{#if $gotMeasurement}
|
||||
<div class="flex flex-col m-2">
|
||||
<div class="flex w-full">
|
||||
|
||||
<div class="font-bold w-full flex justify-around items-center text-5xl">
|
||||
{#if $gotMeasurement}
|
||||
<div class="m-2 flex flex-col">
|
||||
<div class="flex w-full">
|
||||
<div class="flex w-full items-center justify-around text-5xl font-bold">
|
||||
<div>
|
||||
{$previewDegrees}
|
||||
</div>
|
||||
|
|
@ -88,7 +85,6 @@
|
|||
{$previewPercentage}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
|
@ -96,14 +92,14 @@
|
|||
</div>
|
||||
|
||||
<If condition={state?.featureSwitchIsTesting ?? new ImmutableStore(true)}>
|
||||
<span class="subtle">
|
||||
Way: {featureBearing}°, compass: {$alpha}°, diff: {(featureBearing - $alpha)}
|
||||
{#if $valuesign === 1}
|
||||
Forward
|
||||
{:else}
|
||||
Backward
|
||||
{/if}
|
||||
</span>
|
||||
<span class="subtle">
|
||||
Way: {featureBearing}°, compass: {$alpha}°, diff: {featureBearing - $alpha}
|
||||
{#if $valuesign === 1}
|
||||
Forward
|
||||
{:else}
|
||||
Backward
|
||||
{/if}
|
||||
</span>
|
||||
</If>
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
|
||||
{#if availableLanguages?.length > 1}
|
||||
<form class={twMerge("flex max-w-full items-center pr-4", clss)}>
|
||||
<label class="flex neutral-label" use:ariaLabel={Translations.t.general.pickLanguage}>
|
||||
<LanguageIcon class="h-4 w-4 mr-1 shrink-0" aria-hidden="true" />
|
||||
<label class="neutral-label flex" use:ariaLabel={Translations.t.general.pickLanguage}>
|
||||
<LanguageIcon class="mr-1 h-4 w-4 shrink-0" aria-hidden="true" />
|
||||
<Dropdown cls="max-w-full" value={assignTo}>
|
||||
{#if preferredFiltered}
|
||||
{#each preferredFiltered as language}
|
||||
|
|
@ -54,12 +54,12 @@
|
|||
<option disabled />
|
||||
{/if}
|
||||
|
||||
{#each availableLanguages.filter(l => l !== "_context") as language}
|
||||
{#each availableLanguages.filter((l) => l !== "_context") as language}
|
||||
<option value={language} class="font-bold">
|
||||
{native[language] ?? ""}
|
||||
{#if language !== $current}
|
||||
{#if language_translations[language]?.[$current] !== undefined}
|
||||
({ language_translations[language]?.[$current] + " - " + language ?? language})
|
||||
({language_translations[language]?.[$current] + " - " + language ?? language})
|
||||
{:else}
|
||||
({language})
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,102 +1,102 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
import type { ValidatorType } from "./Validators";
|
||||
import Validators from "./Validators";
|
||||
import { ExclamationIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
import { Translation } from "../i18n/Translation";
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
import { Validator } from "./Validator";
|
||||
import { Unit } from "../../Models/Unit";
|
||||
import UnitInput from "../Popup/UnitInput.svelte";
|
||||
import { Utils } from "../../Utils";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { ValidatorType } from "./Validators"
|
||||
import Validators from "./Validators"
|
||||
import { ExclamationIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import { Translation } from "../i18n/Translation"
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import { Validator } from "./Validator"
|
||||
import { Unit } from "../../Models/Unit"
|
||||
import UnitInput from "../Popup/UnitInput.svelte"
|
||||
import { Utils } from "../../Utils"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export let type: ValidatorType;
|
||||
export let feedback: UIEventSource<Translation> | undefined = undefined;
|
||||
export let cls: string = undefined;
|
||||
export let getCountry: () => string | undefined;
|
||||
export let placeholder: string | Translation | undefined;
|
||||
export let unit: Unit = undefined;
|
||||
export let type: ValidatorType
|
||||
export let feedback: UIEventSource<Translation> | undefined = undefined
|
||||
export let cls: string = undefined
|
||||
export let getCountry: () => string | undefined
|
||||
export let placeholder: string | Translation | undefined
|
||||
export let unit: Unit = undefined
|
||||
/**
|
||||
* Valid state, exported to the calling component
|
||||
*/
|
||||
export let value: UIEventSource<string | undefined>;
|
||||
export let value: UIEventSource<string | undefined>
|
||||
/**
|
||||
* Internal state bound to the input element.
|
||||
*
|
||||
* This is only copied to 'value' when appropriate so that no invalid values leak outside;
|
||||
* Additionally, the unit is added when copying
|
||||
*/
|
||||
let _value = new UIEventSource(value.data ?? "");
|
||||
let _value = new UIEventSource(value.data ?? "")
|
||||
|
||||
let validator: Validator = Validators.get(type ?? "string");
|
||||
let validator: Validator = Validators.get(type ?? "string")
|
||||
if (validator === undefined) {
|
||||
console.warn("Didn't find a validator for type", type);
|
||||
console.warn("Didn't find a validator for type", type)
|
||||
}
|
||||
let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined);
|
||||
let _placeholder = placeholder ?? validator?.getPlaceholder() ?? type;
|
||||
let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
let _placeholder = placeholder ?? validator?.getPlaceholder() ?? type
|
||||
|
||||
function initValueAndDenom() {
|
||||
if (unit && value.data) {
|
||||
const [v, denom] = unit?.findDenomination(value.data, getCountry);
|
||||
const [v, denom] = unit?.findDenomination(value.data, getCountry)
|
||||
if (denom) {
|
||||
_value.setData(v);
|
||||
selectedUnit.setData(denom.canonical);
|
||||
_value.setData(v)
|
||||
selectedUnit.setData(denom.canonical)
|
||||
} else {
|
||||
_value.setData(value.data ?? "");
|
||||
_value.setData(value.data ?? "")
|
||||
}
|
||||
} else {
|
||||
_value.setData(value.data ?? "");
|
||||
_value.setData(value.data ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
initValueAndDenom();
|
||||
initValueAndDenom()
|
||||
|
||||
$: {
|
||||
// The type changed -> reset some values
|
||||
validator = Validators.get(type ?? "string");
|
||||
validator = Validators.get(type ?? "string")
|
||||
|
||||
_placeholder = placeholder ?? validator?.getPlaceholder() ?? type;
|
||||
feedback?.setData(validator?.getFeedback(_value.data, getCountry));
|
||||
_placeholder = placeholder ?? validator?.getPlaceholder() ?? type
|
||||
feedback?.setData(validator?.getFeedback(_value.data, getCountry))
|
||||
|
||||
initValueAndDenom();
|
||||
initValueAndDenom()
|
||||
}
|
||||
|
||||
function setValues() {
|
||||
// Update the value stores
|
||||
const v = _value.data;
|
||||
const v = _value.data
|
||||
if (!validator?.isValid(v, getCountry) || v === "") {
|
||||
feedback?.setData(validator?.getFeedback(v, getCountry));
|
||||
value.setData("");
|
||||
return;
|
||||
feedback?.setData(validator?.getFeedback(v, getCountry))
|
||||
value.setData("")
|
||||
return
|
||||
}
|
||||
|
||||
if (unit !== undefined && isNaN(Number(v))) {
|
||||
value.setData(undefined);
|
||||
return;
|
||||
value.setData(undefined)
|
||||
return
|
||||
}
|
||||
|
||||
feedback?.setData(undefined);
|
||||
feedback?.setData(undefined)
|
||||
if (selectedUnit.data) {
|
||||
value.setData(unit.toOsm(v, selectedUnit.data))
|
||||
} else {
|
||||
value.setData(v);
|
||||
value.setData(v)
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(_value.addCallbackAndRun((_) => setValues()));
|
||||
onDestroy(_value.addCallbackAndRun((_) => setValues()))
|
||||
if (unit === undefined) {
|
||||
onDestroy(
|
||||
value.addCallbackAndRunD((fromUpstream) => {
|
||||
if (_value.data !== fromUpstream && fromUpstream !== "") {
|
||||
_value.setData(fromUpstream);
|
||||
_value.setData(fromUpstream)
|
||||
}
|
||||
})
|
||||
);
|
||||
}else{
|
||||
// Handled by the UnitInput
|
||||
)
|
||||
} else {
|
||||
// Handled by the UnitInput
|
||||
}
|
||||
onDestroy(selectedUnit.addCallback((_) => setValues()));
|
||||
onDestroy(selectedUnit.addCallback((_) => setValues()))
|
||||
if (validator === undefined) {
|
||||
throw (
|
||||
"Not a valid type (no validator found) for type '" +
|
||||
|
|
@ -109,17 +109,17 @@
|
|||
)
|
||||
.slice(0, 5)
|
||||
.join(", ")
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
const isValid = _value.map((v) => validator?.isValid(v, getCountry) ?? true);
|
||||
const isValid = _value.map((v) => validator?.isValid(v, getCountry) ?? true)
|
||||
|
||||
let htmlElem: HTMLInputElement;
|
||||
let htmlElem: HTMLInputElement
|
||||
|
||||
let dispatch = createEventDispatcher<{ selected; submit }>();
|
||||
let dispatch = createEventDispatcher<{ selected; submit }>()
|
||||
$: {
|
||||
if (htmlElem !== undefined) {
|
||||
htmlElem.onfocus = () => dispatch("selected");
|
||||
htmlElem.onfocus = () => dispatch("selected")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,9 +128,9 @@
|
|||
*/
|
||||
function sendSubmit() {
|
||||
if (feedback?.data) {
|
||||
console.log("Not sending a submit as there is feedback");
|
||||
console.log("Not sending a submit as there is feedback")
|
||||
}
|
||||
dispatch("submit");
|
||||
dispatch("submit")
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@
|
|||
window.requestAnimationFrame(() => {
|
||||
_map.resize()
|
||||
})
|
||||
_map.on("load", function() {
|
||||
_map.on("load", function () {
|
||||
_map.resize()
|
||||
const canvas = _map.getCanvas()
|
||||
ariaLabel(canvas, Translations.t.general.visualFeedback.navigation)
|
||||
canvas.role="application"
|
||||
canvas.role = "application"
|
||||
canvas.tabIndex = 0
|
||||
})
|
||||
map.set(_map)
|
||||
|
|
@ -62,16 +62,10 @@
|
|||
if (_map) _map.remove()
|
||||
map = null
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<link href="./maplibre-gl.css" rel="stylesheet" />
|
||||
</svelte:head>
|
||||
|
||||
<div
|
||||
bind:this={container}
|
||||
class="map relative top-0 left-0 w-full h-full"
|
||||
id="map"
|
||||
/>
|
||||
<div bind:this={container} class="map relative top-0 left-0 h-full w-full" id="map" />
|
||||
|
|
|
|||
|
|
@ -26,13 +26,19 @@
|
|||
|
||||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if $isFavourite}
|
||||
<button class="p-0 m-0 h-8 w-8" on:click={() => markFavourite(false)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isMarkedShort}>
|
||||
<button
|
||||
class="m-0 h-8 w-8 p-0"
|
||||
on:click={() => markFavourite(false)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isMarkedShort}
|
||||
>
|
||||
<HeartSolidIcon aria-hidden={true} />
|
||||
</button>
|
||||
{:else}
|
||||
<button class="p-0 m-0 h-8 w-8 no-image-background soft" on:click={() => markFavourite(true)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isNotMarkedShort}>
|
||||
<button
|
||||
class="no-image-background soft m-0 h-8 w-8 p-0"
|
||||
on:click={() => markFavourite(true)}
|
||||
use:ariaLabel={Translations.t.favouritePoi.button.isNotMarkedShort}
|
||||
>
|
||||
<HeartOutlineIcon aria-hidden={true} />
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -119,12 +119,18 @@
|
|||
{/if}
|
||||
|
||||
<div class="flex flex-wrap">
|
||||
<If condition={currentMapProperties.zoom.mapD(zoom => zoom >= Constants.minZoomLevelToAddNewPoint)}>
|
||||
<button class="flex primary w-full"
|
||||
on:click={() => {
|
||||
moveWizardState.moveFeature(newLocation.data, reason.data, featureToMove);
|
||||
currentStep = "moved"
|
||||
}}>
|
||||
<If
|
||||
condition={currentMapProperties.zoom.mapD(
|
||||
(zoom) => zoom >= Constants.minZoomLevelToAddNewPoint
|
||||
)}
|
||||
>
|
||||
<button
|
||||
class="primary flex w-full"
|
||||
on:click={() => {
|
||||
moveWizardState.moveFeature(newLocation.data, reason.data, featureToMove)
|
||||
currentStep = "moved"
|
||||
}}
|
||||
>
|
||||
<Move class="mr-2 h-6 w-6" />
|
||||
<Tr t={t.confirmMove} />
|
||||
</button>
|
||||
|
|
@ -148,8 +154,12 @@
|
|||
{:else if currentStep === "moved"}
|
||||
<div class="flex flex-col">
|
||||
<Tr cls="thanks" t={t.pointIsMoved} />
|
||||
<button on:click={() => {currentStep = "reason"}}>
|
||||
<Move class="w-6 h-6 pr-2" />
|
||||
<button
|
||||
on:click={() => {
|
||||
currentStep = "reason"
|
||||
}}
|
||||
>
|
||||
<Move class="h-6 w-6 pr-2" />
|
||||
<Tr t={t.inviteToMoveAgain} />
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
export let layer: LayerConfig
|
||||
export let config: TagRenderingConfig
|
||||
export let extraClasses: string | undefined = undefined
|
||||
|
||||
export let id : string = undefined
|
||||
|
||||
export let id: string = undefined
|
||||
|
||||
if (config === undefined) {
|
||||
throw "Config is undefined in tagRenderingAnswer"
|
||||
|
|
|
|||
|
|
@ -75,13 +75,20 @@
|
|||
onDestroy(highlightedRendering?.addCallbackAndRun(() => setHighlighting()))
|
||||
onDestroy(_htmlElement.addCallbackAndRun(() => setHighlighting()))
|
||||
}
|
||||
let answerId = "answer-"+Utils.randomString(5)
|
||||
let answerId = "answer-" + Utils.randomString(5)
|
||||
</script>
|
||||
|
||||
<div bind:this={htmlElem} class={twMerge(clss, "tr-" + config.id)}>
|
||||
{#if config.question && (!editingEnabled || $editingEnabled)}
|
||||
{#if editMode}
|
||||
<TagRenderingQuestion {config} {tags} {selectedElement} {state} {layer} on:saved={() => editMode = false}>
|
||||
<TagRenderingQuestion
|
||||
{config}
|
||||
{tags}
|
||||
{selectedElement}
|
||||
{state}
|
||||
{layer}
|
||||
on:saved={() => (editMode = false)}
|
||||
>
|
||||
<button
|
||||
slot="cancel"
|
||||
class="secondary"
|
||||
|
|
@ -104,7 +111,7 @@
|
|||
</TagRenderingQuestion>
|
||||
{:else}
|
||||
<div class="low-interaction flex items-center justify-between overflow-hidden rounded px-2">
|
||||
<TagRenderingAnswer id={answerId} {config} {tags} {selectedElement} {state} {layer} />
|
||||
<TagRenderingAnswer id={answerId} {config} {tags} {selectedElement} {state} {layer} />
|
||||
<button
|
||||
on:click={() => {
|
||||
editMode = true
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
{#if mapping.icon !== undefined}
|
||||
<div class="inline-flex items-center">
|
||||
<Icon icon={mapping.icon} clss={twJoin(`mapping-icon-${mapping.iconClass}`, "mx-2")}/>
|
||||
<Icon icon={mapping.icon} clss={twJoin(`mapping-icon-${mapping.iconClass}`, "mx-2")} />
|
||||
<SpecialTranslation t={mapping.then} {tags} {state} {layer} feature={selectedElement} />
|
||||
</div>
|
||||
{:else if mapping.then !== undefined}
|
||||
|
|
|
|||
|
|
@ -239,8 +239,12 @@
|
|||
{#if config.mappings?.length >= 8}
|
||||
<div class="sticky flex w-full" aria-hidden="true">
|
||||
<Search class="h-6 w-6" />
|
||||
<input type="text" bind:value={$searchTerm} class="w-full"
|
||||
use:placeholder={Translations.t.general.searchAnswer} />
|
||||
<input
|
||||
type="text"
|
||||
bind:value={$searchTerm}
|
||||
class="w-full"
|
||||
use:placeholder={Translations.t.general.searchAnswer}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,67 +1,67 @@
|
|||
<script lang="ts">
|
||||
import { Unit } from "../../Models/Unit";
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource";
|
||||
import Tr from "../Base/Tr.svelte";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
import { Denomination } from "../../Models/Denomination";
|
||||
import { Unit } from "../../Models/Unit"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
import { onDestroy, onMount } from "svelte"
|
||||
import { Denomination } from "../../Models/Denomination"
|
||||
|
||||
export let unit: Unit;
|
||||
export let unit: Unit
|
||||
|
||||
/**
|
||||
* The current value of the input field
|
||||
* Not necessarily a correct number, should not contain the denomination
|
||||
*/
|
||||
export let textValue: UIEventSource<string>;
|
||||
export let textValue: UIEventSource<string>
|
||||
/**
|
||||
* The actual _valid_ value that is upstreamed, including the denomination
|
||||
*/
|
||||
export let upstreamValue: Store<string>;
|
||||
export let upstreamValue: Store<string>
|
||||
|
||||
let isSingle: Store<boolean> = textValue.map((v) => Number(v) === 1);
|
||||
let isSingle: Store<boolean> = textValue.map((v) => Number(v) === 1)
|
||||
|
||||
export let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined)
|
||||
export let getCountry = () => "?"
|
||||
|
||||
export let selectedUnit: UIEventSource<string> = new UIEventSource<string>(undefined);
|
||||
export let getCountry = () => "?";
|
||||
|
||||
onMount(() => {
|
||||
console.log("Setting selected unit based on country", getCountry(), upstreamValue.data)
|
||||
if(upstreamValue.data === undefined || upstreamValue.data === ""){
|
||||
if (upstreamValue.data === undefined || upstreamValue.data === "") {
|
||||
// Init the selected unit
|
||||
let denomination: Denomination = unit.getDefaultDenomination(getCountry);
|
||||
let denomination: Denomination = unit.getDefaultDenomination(getCountry)
|
||||
console.log("Found denom", denomination.canonical)
|
||||
selectedUnit.setData(denomination.canonical)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
onDestroy(
|
||||
upstreamValue.addCallbackAndRun((v) => {
|
||||
if(v === undefined || v === ""){
|
||||
if (v === undefined || v === "") {
|
||||
return
|
||||
}
|
||||
let denomination: Denomination = unit.getDefaultDenomination(getCountry);
|
||||
const selected = unit.findDenomination(v, getCountry);
|
||||
if(selected){
|
||||
denomination = selected[1];
|
||||
let denomination: Denomination = unit.getDefaultDenomination(getCountry)
|
||||
const selected = unit.findDenomination(v, getCountry)
|
||||
if (selected) {
|
||||
denomination = selected[1]
|
||||
}
|
||||
selectedUnit.setData(denomination.canonical);
|
||||
selectedUnit.setData(denomination.canonical)
|
||||
})
|
||||
);
|
||||
)
|
||||
|
||||
onDestroy(
|
||||
textValue.addCallbackAndRunD((v) => {
|
||||
// Fallback in case that the user manually types a denomination
|
||||
const [value, denomination] = unit.findDenomination(v, getCountry);
|
||||
const [value, denomination] = unit.findDenomination(v, getCountry)
|
||||
if (value === undefined || denomination === undefined) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if(value === v){
|
||||
if (value === v) {
|
||||
// The input value actually didn't have a denomination typed out - so lets ignore this one
|
||||
// If a denomination is given, it is the default value anyway
|
||||
return;
|
||||
return
|
||||
}
|
||||
textValue.setData(value);
|
||||
selectedUnit.setData(denomination.canonical);
|
||||
textValue.setData(value)
|
||||
selectedUnit.setData(denomination.canonical)
|
||||
})
|
||||
);
|
||||
)
|
||||
</script>
|
||||
|
||||
<select bind:value={$selectedUnit}>
|
||||
|
|
@ -70,7 +70,7 @@
|
|||
{#if $isSingle}
|
||||
<Tr t={denom.humanSingular} />
|
||||
{:else}
|
||||
<Tr t={denom.human.Subs({quantity: ""})} />
|
||||
<Tr t={denom.human.Subs({ quantity: "" })} />
|
||||
{/if}
|
||||
</option>
|
||||
{/each}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@
|
|||
import Add from "../assets/svg/Add.svelte"
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col p-4 h-screen overflow-hidden">
|
||||
<div class="flex h-screen flex-col overflow-hidden p-4">
|
||||
<h2 class="flex items-center">
|
||||
<EyeIcon class="w-6 pr-2" />
|
||||
<Tr t={Translations.t.privacy.title} />
|
||||
</h2>
|
||||
<div class="overflow-auto h-full border border-gray-500 p-4">
|
||||
<div class="h-full overflow-auto border border-gray-500 p-4">
|
||||
<PrivacyPolicy />
|
||||
</div>
|
||||
<a class="flex button" href={Utils.HomepageLink()}>
|
||||
<a class="button flex" href={Utils.HomepageLink()}>
|
||||
<Add class="h-6 w-6" />
|
||||
<Tr t={Translations.t.general.backToIndex} />
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
import { Store, Stores } from "../Logic/UIEventSource"
|
||||
|
||||
let maxAcc = Motion.singleton.maxAcc
|
||||
let shaken =Motion.singleton.lastShakeEvent
|
||||
let recentlyShaken = Stores.Chronic(250).mapD(now => now.getTime() - 3000 < shaken.data?.getTime())
|
||||
let shaken = Motion.singleton.lastShakeEvent
|
||||
let recentlyShaken = Stores.Chronic(250).mapD(
|
||||
(now) => now.getTime() - 3000 < shaken.data?.getTime()
|
||||
)
|
||||
</script>
|
||||
|
||||
Acc: {$maxAcc}
|
||||
{#if $recentlyShaken}
|
||||
<div class="text-red-500 text-5xl">
|
||||
SHAKEN
|
||||
</div>
|
||||
{/if}
|
||||
<div class="text-5xl text-red-500">SHAKEN</div>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,13 @@
|
|||
import type { MapProperties } from "../Models/MapProperties"
|
||||
import Geosearch from "./BigComponents/Geosearch.svelte"
|
||||
import Translations from "./i18n/Translations"
|
||||
import { CogIcon, EyeIcon, HeartIcon, MenuIcon, XCircleIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import {
|
||||
CogIcon,
|
||||
EyeIcon,
|
||||
HeartIcon,
|
||||
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"
|
||||
|
|
@ -75,14 +81,11 @@
|
|||
let maplibremap: UIEventSource<MlMap> = state.map
|
||||
let selectedElement: UIEventSource<Feature> = new UIEventSource<Feature>(undefined)
|
||||
|
||||
|
||||
let compass = Orientation.singleton.alpha
|
||||
let compassLoaded = Orientation.singleton.gotMeasurement
|
||||
Orientation.singleton.startMeasurements()
|
||||
|
||||
|
||||
state.selectedElement.addCallback((selected) => {
|
||||
|
||||
if (!selected) {
|
||||
selectedElement.setData(selected)
|
||||
return
|
||||
|
|
@ -93,20 +96,20 @@
|
|||
}
|
||||
// ... we give svelte some time to update with requestAnimationFrame ...
|
||||
window.requestAnimationFrame(() => {
|
||||
// ... and we force a fresh popup window
|
||||
// ... and we force a fresh popup window
|
||||
selectedElement.setData(selected)
|
||||
})
|
||||
})
|
||||
|
||||
let selectedLayer: Store<LayerConfig> = state.selectedElement.mapD((element) =>
|
||||
state.layout.getMatchingLayer(element.properties),
|
||||
state.layout.getMatchingLayer(element.properties)
|
||||
)
|
||||
let currentZoom = state.mapProperties.zoom
|
||||
let showCrosshair = state.userRelatedState.showCrosshair
|
||||
let visualFeedback = state.visualFeedback
|
||||
let viewport: UIEventSource<HTMLDivElement> = new UIEventSource<HTMLDivElement>(undefined)
|
||||
let featuresInViewPort: UIEventSource<Feature[]> = new UIEventSource<Feature[]>(undefined)
|
||||
viewport.addCallbackAndRunD(viewport => {
|
||||
viewport.addCallbackAndRunD((viewport) => {
|
||||
state.featuresInView.features.addCallbackAndRunD((features: Feature[]) => {
|
||||
const rect = viewport.getBoundingClientRect()
|
||||
const mlmap = state.map.data
|
||||
|
|
@ -115,17 +118,19 @@
|
|||
}
|
||||
const topLeft = mlmap.unproject([rect.left, rect.top])
|
||||
const bottomRight = mlmap.unproject([rect.right, rect.bottom])
|
||||
const bbox = new BBox([[topLeft.lng, topLeft.lat], [bottomRight.lng, bottomRight.lat]])
|
||||
const bbox = new BBox([
|
||||
[topLeft.lng, topLeft.lat],
|
||||
[bottomRight.lng, bottomRight.lat],
|
||||
])
|
||||
const bboxGeo = bbox.asGeoJson({})
|
||||
console.log("BBOX:", bboxGeo)
|
||||
|
||||
|
||||
const filtered = features.filter((f: Feature) => {
|
||||
console.log(f, bboxGeo)
|
||||
return GeoOperations.calculateOverlap(bboxGeo, [f]).length > 0
|
||||
})
|
||||
featuresInViewPort.setData(filtered)
|
||||
})
|
||||
|
||||
})
|
||||
let mapproperties: MapProperties = state.mapProperties
|
||||
let featureSwitches: FeatureSwitchState = state.featureSwitches
|
||||
|
|
@ -137,7 +142,7 @@
|
|||
onDestroy(
|
||||
rasterLayer.addCallbackAndRunD((l) => {
|
||||
rasterLayerName = l.properties.name
|
||||
}),
|
||||
})
|
||||
)
|
||||
let previewedImage = state.previewedImage
|
||||
|
||||
|
|
@ -159,9 +164,10 @@
|
|||
</div>
|
||||
|
||||
{#if $visualFeedback}
|
||||
<div class="absolute top-0 left-0 h-screen w-screen overflow-hidden flex items-center justify-center">
|
||||
|
||||
<div bind:this={$viewport} style="border: 2px solid #ff000044; width: 300px; height: 300px"></div>
|
||||
<div
|
||||
class="absolute top-0 left-0 flex h-screen w-screen items-center justify-center overflow-hidden"
|
||||
>
|
||||
<div bind:this={$viewport} style="border: 2px solid #ff000044; width: 300px; height: 300px" />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
|
@ -171,15 +177,19 @@
|
|||
<div class="pointer-events-auto float-right mt-1 px-1 max-[480px]:w-full sm:m-2">
|
||||
<Geosearch
|
||||
bounds={state.mapProperties.bounds}
|
||||
on:searchCompleted={() => {state.map?.data?.getCanvas()?.focus()}}
|
||||
on:searchCompleted={() => {
|
||||
state.map?.data?.getCanvas()?.focus()
|
||||
}}
|
||||
perLayer={state.perLayer}
|
||||
selectedElement={state.selectedElement}
|
||||
/>
|
||||
</div>
|
||||
</If>
|
||||
<div class="float-left m-1 flex flex-col sm:mt-2">
|
||||
<MapControlButton on:click={() => state.guistate.themeIsOpened.setData(true)}
|
||||
on:keydown={forwardEventToMap}>
|
||||
<MapControlButton
|
||||
on:click={() => state.guistate.themeIsOpened.setData(true)}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<div class="m-0.5 mx-1 flex cursor-pointer items-center max-[480px]:w-full sm:mx-1 md:mx-2">
|
||||
<img class="mr-0.5 block h-6 w-6 sm:mr-1 md:mr-2 md:h-8 md:w-8" src={layout.icon} />
|
||||
<b class="mr-1">
|
||||
|
|
@ -215,7 +225,7 @@
|
|||
<div class="alert w-fit">Testmode</div>
|
||||
</If>
|
||||
</div>
|
||||
<div class="flex flex-col w-full justify-center items-center">
|
||||
<div class="flex w-full flex-col items-center justify-center">
|
||||
<!-- Flex and w-full are needed for the positioning -->
|
||||
<!-- Centermessage -->
|
||||
<StateIndicator {state} />
|
||||
|
|
@ -248,9 +258,10 @@
|
|||
<div class="flex">
|
||||
<!-- bottom left elements -->
|
||||
<If condition={state.featureSwitches.featureSwitchFilter}>
|
||||
<MapControlButton arialabel={Translations.t.general.labels.filter}
|
||||
on:click={() => state.guistate.openFilterView()}
|
||||
on:keydown={forwardEventToMap}
|
||||
<MapControlButton
|
||||
arialabel={Translations.t.general.labels.filter}
|
||||
on:click={() => state.guistate.openFilterView()}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<Filter class="h-6 w-6" />
|
||||
</MapControlButton>
|
||||
|
|
@ -284,41 +295,44 @@
|
|||
/>
|
||||
</div>
|
||||
</If>
|
||||
<MapControlButton arialabel={Translations.t.general.labels.zoomIn}
|
||||
on:click={() => mapproperties.zoom.update((z) => z + 1)}
|
||||
on:keydown={forwardEventToMap}
|
||||
<MapControlButton
|
||||
arialabel={Translations.t.general.labels.zoomIn}
|
||||
on:click={() => mapproperties.zoom.update((z) => z + 1)}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<Plus class="h-8 w-8" />
|
||||
</MapControlButton>
|
||||
<MapControlButton arialabel={Translations.t.general.labels.zoomOut}
|
||||
on:click={() => mapproperties.zoom.update((z) => z - 1)}
|
||||
on:keydown={forwardEventToMap}
|
||||
<MapControlButton
|
||||
arialabel={Translations.t.general.labels.zoomOut}
|
||||
on:click={() => mapproperties.zoom.update((z) => z - 1)}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<Min class="h-8 w-8" />
|
||||
</MapControlButton>
|
||||
<If condition={featureSwitches.featureSwitchGeolocation}>
|
||||
<div class="relative m-0">
|
||||
<MapControlButton arialabel={Translations.t.general.labels.jumpToLocation}
|
||||
on:click={() => state.geolocationControl.handleClick()}
|
||||
on:keydown={forwardEventToMap}
|
||||
<MapControlButton
|
||||
arialabel={Translations.t.general.labels.jumpToLocation}
|
||||
on:click={() => state.geolocationControl.handleClick()}
|
||||
on:keydown={forwardEventToMap}
|
||||
>
|
||||
<GeolocationControl {state} /> <!-- h-8 w-8 + p-0.5 sm:p-1 + 2px border => 9 sm: 10 in total-->
|
||||
<GeolocationControl {state} />
|
||||
<!-- h-8 w-8 + p-0.5 sm:p-1 + 2px border => 9 sm: 10 in total-->
|
||||
</MapControlButton>
|
||||
{#if $compassLoaded}
|
||||
<div class="absolute top-0 left-0 w-0 h-0 m-0.5 sm:m-1">
|
||||
<Compass_arrow class="compass_arrow"
|
||||
style={`rotate: calc(${-$compass}deg + 45deg); transform-origin: 50% 50%;`} />
|
||||
<div class="absolute top-0 left-0 m-0.5 h-0 w-0 sm:m-1">
|
||||
<Compass_arrow
|
||||
class="compass_arrow"
|
||||
style={`rotate: calc(${-$compass}deg + 45deg); transform-origin: 50% 50%;`}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</If>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<LoginToggle ignoreLoading={true} {state}>
|
||||
{#if ($showCrosshair === "yes" && $currentZoom >= 17) || $showCrosshair === "always" || $visualFeedback}
|
||||
<div
|
||||
|
|
@ -327,7 +341,8 @@
|
|||
<Cross class="h-4 w-4" />
|
||||
</div>
|
||||
{/if}
|
||||
<svelte:fragment slot="error" /> <!-- Add in an empty container to remove errors -->
|
||||
<svelte:fragment slot="error" />
|
||||
<!-- Add in an empty container to remove errors -->
|
||||
</LoginToggle>
|
||||
|
||||
<If condition={state.previewedImage.map((i) => i !== undefined)}>
|
||||
|
|
@ -365,7 +380,7 @@
|
|||
selectedElement.setData(undefined)
|
||||
}}
|
||||
>
|
||||
<div class="h-full w-full flex">
|
||||
<div class="flex h-full w-full">
|
||||
<SelectedElementView {state} layer={$selectedLayer} selectedElement={$selectedElement} />
|
||||
</div>
|
||||
</FloatOver>
|
||||
|
|
@ -428,7 +443,6 @@
|
|||
</FloatOver>
|
||||
</If>
|
||||
|
||||
|
||||
<IfHidden condition={state.guistate.backgroundLayerSelectionIsOpened}>
|
||||
<!-- background layer selector -->
|
||||
<FloatOver
|
||||
|
|
@ -448,7 +462,6 @@
|
|||
</FloatOver>
|
||||
</IfHidden>
|
||||
|
||||
|
||||
<If condition={state.guistate.menuIsOpened}>
|
||||
<!-- Menu page -->
|
||||
<FloatOver on:close={() => state.guistate.menuIsOpened.setData(false)}>
|
||||
|
|
@ -491,22 +504,25 @@
|
|||
<Tr t={Translations.t.general.attribution.donate} />
|
||||
</a>
|
||||
|
||||
<button class="small soft flex" on:click={() => state.guistate.communityIndexPanelIsOpened.setData(true)}>
|
||||
<button
|
||||
class="small soft flex"
|
||||
on:click={() => state.guistate.communityIndexPanelIsOpened.setData(true)}
|
||||
>
|
||||
<Community class="h-6 w-6" />
|
||||
<Tr t={Translations.t.communityIndex.title} />
|
||||
</button>
|
||||
|
||||
|
||||
<If condition={featureSwitches.featureSwitchEnableLogin}>
|
||||
<OpenIdEditor mapProperties={state.mapProperties} />
|
||||
<OpenJosm {state} />
|
||||
<MapillaryLink large={false} mapProperties={state.mapProperties} />
|
||||
</If>
|
||||
|
||||
<button class="small soft flex"
|
||||
on:click={() => state.guistate.privacyPanelIsOpened.setData(true)}
|
||||
<button
|
||||
class="small soft flex"
|
||||
on:click={() => state.guistate.privacyPanelIsOpened.setData(true)}
|
||||
>
|
||||
<EyeIcon class="w-6 h-6 pr-1" />
|
||||
<EyeIcon class="h-6 w-6 pr-1" />
|
||||
<Tr t={Translations.t.privacy.title} />
|
||||
</button>
|
||||
<div class="m-2 flex flex-col">
|
||||
|
|
@ -553,16 +569,14 @@
|
|||
</h3>
|
||||
<Favourites {state} />
|
||||
</div>
|
||||
|
||||
|
||||
</TabbedGroup>
|
||||
</FloatOver>
|
||||
</If>
|
||||
|
||||
<If condition={state.guistate.privacyPanelIsOpened}>
|
||||
<FloatOver on:close={() => state.guistate.privacyPanelIsOpened.setData(false)}>
|
||||
<div class="h-full flex flex-col overflow-hidden">
|
||||
<h2 class="flex items-center low-interaction p-4 m-0">
|
||||
<div class="flex h-full flex-col overflow-hidden">
|
||||
<h2 class="low-interaction m-0 flex items-center p-4">
|
||||
<EyeIcon class="w-6 pr-2" />
|
||||
<Tr t={Translations.t.privacy.title} />
|
||||
</h2>
|
||||
|
|
@ -573,11 +587,10 @@
|
|||
</FloatOver>
|
||||
</If>
|
||||
|
||||
|
||||
<If condition={state.guistate.communityIndexPanelIsOpened}>
|
||||
<FloatOver on:close={() => state.guistate.communityIndexPanelIsOpened.setData(false)}>
|
||||
<div class="h-full flex flex-col overflow-hidden">
|
||||
<h2 class="flex items-center low-interaction p-4 m-0">
|
||||
<div class="flex h-full flex-col overflow-hidden">
|
||||
<h2 class="low-interaction m-0 flex items-center p-4">
|
||||
<Community class="h-6 w-6" />
|
||||
<Tr t={Translations.t.communityIndex.title} />
|
||||
</h2>
|
||||
|
|
@ -585,8 +598,5 @@
|
|||
<CommunityIndexView location={state.mapProperties.location} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</FloatOver>
|
||||
</If>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue