forked from MapComplete/MapComplete
A11y: improve flow with screenreader, some more refactoring to svelte, see #1181
This commit is contained in:
parent
40067e35d4
commit
48ac539272
15 changed files with 188 additions and 226 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "unit",
|
||||
"description": {
|
||||
"en": "Library layer with all common units"
|
||||
"en": "Library layer with all common units. Units can _only_ be imported from this file."
|
||||
},
|
||||
"source": "special:library",
|
||||
"units": [
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"nl": "Breng jouw buurtnatuur in kaart"
|
||||
},
|
||||
"description": {
|
||||
"nl": "<img style='float:right;margin: 1em;width: 10em;height: auto;' src='./assets/themes/buurtnatuur/groen_logo.svg' alt='logo-groen' class='logo/> <br /><b>Natuur maakt gelukkig.</b> Aan de hand van deze website willen we de natuur dicht bij ons beter inventariseren. Met als doel meer mensen te laten genieten van toegankelijke natuur én te strijden voor meer natuur in onze buurten.<ul><li>In welke natuurgebieden kan jij terecht? Hoe toegankelijk zijn ze?</li><li>In welke bossen kan een gezin in jouw gemeente opnieuw op adem komen?</li><li>Op welke onbekende plekjes is het zalig spelen?</li></ul><p>Samen kleuren we heel Vlaanderen en Brussel groen.Blijf op de hoogte van de resultaten van buurtnatuur.be: <a href='https://www.groen.be/buurtnatuur' target='_blank'>meld je aan voor e-mailupdates</a>."
|
||||
"nl": "<img style='float:right;margin: 1em;width: 10em;height: auto;' src='./assets/themes/buurtnatuur/groen_logo.svg' alt='logo-groen' class='logo'/> <br /><b>Natuur maakt gelukkig.</b> Aan de hand van deze website willen we de natuur dicht bij ons beter inventariseren. Met als doel meer mensen te laten genieten van toegankelijke natuur én te strijden voor meer natuur in onze buurten.<ul><li>In welke natuurgebieden kan jij terecht? Hoe toegankelijk zijn ze?</li><li>In welke bossen kan een gezin in jouw gemeente opnieuw op adem komen?</li><li>Op welke onbekende plekjes is het zalig spelen?</li></ul><p>Samen kleuren we heel Vlaanderen en Brussel groen.Blijf op de hoogte van de resultaten van buurtnatuur.be: <a href='https://www.groen.be/buurtnatuur' target='_blank'>meld je aan voor e-mailupdates</a>."
|
||||
},
|
||||
"shortDescription": {
|
||||
"nl": "Met deze tool kan je natuur in je buurt in kaart brengen en meer informatie geven over je favoriete plekje"
|
||||
|
|
|
@ -182,7 +182,8 @@
|
|||
"backgroundSwitch": "Switch background",
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"customThemeIntro": "<h3>Custom themes</h3>These are previously visited user-generated themes.",
|
||||
"customThemeIntro": "These are previously visited user-generated themes.",
|
||||
"customThemeTitle": "Custom themes",
|
||||
"download": {
|
||||
"downloadAsPdf": "Download a PDF of the current map",
|
||||
"downloadAsPdfHelper": "Ideal to print the current map",
|
||||
|
|
|
@ -10346,4 +10346,4 @@
|
|||
"render": "wind turbine"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -876,16 +876,16 @@ video {
|
|||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.mx-1 {
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.mx-1 {
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
||||
.mx-10 {
|
||||
margin-left: 2.5rem;
|
||||
margin-right: 2.5rem;
|
||||
|
@ -1262,10 +1262,6 @@ video {
|
|||
width: 16rem;
|
||||
}
|
||||
|
||||
.w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.w-14 {
|
||||
width: 3.5rem;
|
||||
}
|
||||
|
@ -1533,6 +1529,10 @@ video {
|
|||
justify-self: end;
|
||||
}
|
||||
|
||||
.justify-self-center {
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
.overflow-auto {
|
||||
overflow: auto;
|
||||
}
|
||||
|
@ -2892,6 +2892,10 @@ a.link-underline {
|
|||
width: 6rem;
|
||||
}
|
||||
|
||||
.sm\:w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.sm\:flex-nowrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
|
|
@ -7,12 +7,18 @@
|
|||
import Translations from "./i18n/Translations"
|
||||
import Logo from "../assets/svg/Logo.svelte"
|
||||
import Tr from "./Base/Tr.svelte"
|
||||
import ToSvelte from "./Base/ToSvelte.svelte"
|
||||
import MoreScreen from "./BigComponents/MoreScreen"
|
||||
import LoginToggle from "./Base/LoginToggle.svelte"
|
||||
import Pencil from "../assets/svg/Pencil.svelte"
|
||||
import Login from "../assets/svg/Login.svelte"
|
||||
import Constants from "../Models/Constants"
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import { placeholder } from "../Utils/placeholder"
|
||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import ThemesList from "./BigComponents/ThemesList.svelte"
|
||||
import { LayoutInformation } from "../Models/ThemeConfig/LayoutConfig"
|
||||
import * as themeOverview from "../assets/generated/theme_overview.json"
|
||||
import UnofficialThemeList from "./BigComponents/UnofficialThemeList.svelte"
|
||||
|
||||
const featureSwitches = new OsmConnectionFeatureSwitches()
|
||||
const osmConnection = new OsmConnection({
|
||||
|
@ -20,17 +26,45 @@
|
|||
oauth_token: QueryParameters.GetQueryParameter(
|
||||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
"Used to complete the login",
|
||||
),
|
||||
})
|
||||
const state = new UserRelatedState(osmConnection)
|
||||
const t = Translations.t.index
|
||||
const tr = Translations.t.general.morescreen
|
||||
|
||||
let userLanguages = osmConnection.userDetails.map((ud) => ud.languages)
|
||||
let themeSearchText: UIEventSource<string | undefined> = new UIEventSource<string>(undefined)
|
||||
|
||||
document.addEventListener("keydown", function(event) {
|
||||
if (event.ctrlKey && event.code === "KeyF") {
|
||||
document.getElementById("theme-search")?.focus()
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
|
||||
let visitedHiddenThemes: Store<LayoutInformation[]>
|
||||
const hiddenThemes: LayoutInformation[] =
|
||||
(themeOverview["default"] ?? themeOverview)?.filter((layout) => layout.hideFromOverview) ?? []
|
||||
{
|
||||
const prefix = "mapcomplete-hidden-theme-"
|
||||
const userPreferences = state.osmConnection.preferencesHandler.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)),
|
||||
)
|
||||
return hiddenThemes.filter((theme) => knownIds.has(theme.id))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div class="m-4 flex flex-col">
|
||||
<LanguagePicker clss="self-end" assignTo={state.language} availableLanguages={t.title.SupportedLanguages()}
|
||||
preferredLanguages={userLanguages} />
|
||||
<LanguagePicker assignTo={state.language} availableLanguages={t.title.SupportedLanguages()} clss="self-end"
|
||||
preferredLanguages={userLanguages} />
|
||||
|
||||
<div class="mt-4 flex">
|
||||
<div class="m-3 flex-none">
|
||||
|
@ -48,9 +82,42 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<ToSvelte construct={new MoreScreen(state, true)} />
|
||||
|
||||
<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}>
|
||||
</label>
|
||||
</form>
|
||||
|
||||
<ThemesList search={themeSearchText} {state} themes={MoreScreen.officialThemes} />
|
||||
|
||||
<LoginToggle {state}>
|
||||
<ThemesList
|
||||
hideThemes={false}
|
||||
isCustom={false}
|
||||
search={themeSearchText}
|
||||
{state}
|
||||
themes={$visitedHiddenThemes}
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<h3>
|
||||
<Tr t={tr.previouslyHiddenTitle} />
|
||||
</h3>
|
||||
<p>
|
||||
<Tr t={tr.hiddenExplanation.Subs({
|
||||
hidden_discovered: $visitedHiddenThemes.length.toString(),
|
||||
total_hidden: hiddenThemes.length.toString(),
|
||||
})} />
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
</ThemesList>
|
||||
|
||||
<UnofficialThemeList search={themeSearchText} {state} />
|
||||
|
||||
<div slot="not-logged-in">
|
||||
<button class="w-full" on:click={() => osmConnection.AttemptLogin()}>
|
||||
<Login class="mr-2 h-6 w-6 " />
|
||||
|
@ -64,9 +131,13 @@
|
|||
<Pencil class="mr-2 h-6 w-6" />
|
||||
<Tr t={Translations.t.general.morescreen.createYourOwnTheme} />
|
||||
</a>
|
||||
|
||||
|
||||
</LoginToggle>
|
||||
|
||||
<Tr cls="link-underline" t={Translations.t.general.aboutMapComplete.intro} />
|
||||
<Tr t={tr.streetcomplete} />
|
||||
|
||||
<div class="subtle mb-16 self-end">
|
||||
v{Constants.vNumber}
|
||||
</div>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import { Translation } from "../i18n/Translation"
|
||||
import WeblateLink from "./WeblateLink.svelte"
|
||||
import { Store } from "../../Logic/UIEventSource"
|
||||
import FromHtml from "./FromHtml.svelte"
|
||||
|
||||
export let t: Translation
|
||||
export let cls: string = ""
|
||||
|
@ -14,9 +15,9 @@
|
|||
|
||||
</script>
|
||||
|
||||
{#if txt}
|
||||
{#if $txt}
|
||||
<span class={cls}>
|
||||
{$txt}
|
||||
<FromHtml src={$txt}/>
|
||||
<WeblateLink context={t.context} />
|
||||
</span>
|
||||
{/if}
|
||||
|
|
|
@ -10,13 +10,13 @@
|
|||
import { BBox } from "../../Logic/BBox"
|
||||
import { GeoIndexedStoreForLayer } from "../../Logic/FeatureSource/Actors/GeoIndexedStore"
|
||||
import { createEventDispatcher, onDestroy } from "svelte"
|
||||
import { placeholder } from "../../Utils/placeholder"
|
||||
|
||||
export let perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer> | undefined = undefined
|
||||
export let bounds: UIEventSource<BBox>
|
||||
export let selectedElement: UIEventSource<Feature> | undefined = undefined
|
||||
|
||||
export let clearAfterView: boolean = true
|
||||
|
||||
let searchContents: string = ""
|
||||
export let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined)
|
||||
onDestroy(
|
||||
|
@ -31,17 +31,6 @@
|
|||
|
||||
let feedback: string = undefined
|
||||
|
||||
let placeholder = Translations.t.general.search.search.current
|
||||
$:{
|
||||
if(inputElement){
|
||||
inputElement.placeholder = placeholder.data
|
||||
}
|
||||
}
|
||||
onDestroy(placeholder.addCallbackAndRunD(placeholder => {
|
||||
if(inputElement){
|
||||
inputElement.placeholder = placeholder
|
||||
}
|
||||
}))
|
||||
|
||||
|
||||
Hotkeys.RegisterHotkey({ ctrl: "F" }, Translations.t.hotkeyDocumentation.selectSearch, () => {
|
||||
|
@ -124,6 +113,7 @@
|
|||
bind:this={inputElement}
|
||||
on:keypress={(keypr) => (keypr.key === "Enter" ? performSearch() : undefined)}
|
||||
bind:value={searchContents}
|
||||
use:placeholder={Translations.t.general.search.search}
|
||||
/>
|
||||
{/if}
|
||||
</form>
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import * as themeOverview from "../../assets/generated/theme_overview.json"
|
||||
import { Utils } from "../../Utils"
|
||||
import ThemesList from "./ThemesList.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import LoginToggle from "../Base/LoginToggle.svelte"
|
||||
|
||||
export let search: UIEventSource<string>
|
||||
export let state: { osmConnection: OsmConnection }
|
||||
export let onMainScreen: boolean = true
|
||||
|
||||
const prefix = "mapcomplete-hidden-theme-"
|
||||
const hiddenThemes: LayoutInformation[] =
|
||||
(themeOverview["default"] ?? themeOverview)?.filter((layout) => layout.hideFromOverview) ?? []
|
||||
const userPreferences = state.osmConnection.preferencesHandler.preferences
|
||||
const t = Translations.t.general.morescreen
|
||||
|
||||
let knownThemesId: string[]
|
||||
$: knownThemesId = Utils.NoNull(
|
||||
Object.keys($userPreferences)
|
||||
.filter((key) => key.startsWith(prefix))
|
||||
.map((key) => key.substring(prefix.length, key.length - "-enabled".length))
|
||||
)
|
||||
$: console.log("Known theme ids:", knownThemesId)
|
||||
$: knownThemes = hiddenThemes.filter((theme) => knownThemesId.includes(theme.id))
|
||||
</script>
|
||||
|
||||
<LoginToggle {state}>
|
||||
<ThemesList
|
||||
hideThemes={false}
|
||||
isCustom={false}
|
||||
{onMainScreen}
|
||||
{search}
|
||||
{state}
|
||||
themes={knownThemes}
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<h3>{t.previouslyHiddenTitle.toString()}</h3>
|
||||
<p>
|
||||
{t.hiddenExplanation.Subs({
|
||||
hidden_discovered: knownThemes.length.toString(),
|
||||
total_hidden: hiddenThemes.length.toString(),
|
||||
})}
|
||||
</p>
|
||||
</svelte:fragment>
|
||||
</ThemesList>
|
||||
</LoginToggle>
|
|
@ -1,109 +1,48 @@
|
|||
import Svg from "../../Svg"
|
||||
import Combine from "../Base/Combine"
|
||||
import Translations from "../i18n/Translations"
|
||||
import LayoutConfig, { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { ImmutableStore, Store } from "../../Logic/UIEventSource"
|
||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
||||
import { Utils } from "../../Utils"
|
||||
import themeOverview from "../../assets/generated/theme_overview.json"
|
||||
import { TextField } from "../Input/TextField"
|
||||
import Locale from "../i18n/Locale"
|
||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||
import ThemesList from "./ThemesList.svelte"
|
||||
import HiddenThemeList from "./HiddenThemeList.svelte"
|
||||
import UnofficialThemeList from "./UnofficialThemeList.svelte"
|
||||
|
||||
export default class MoreScreen extends Combine {
|
||||
private static readonly officialThemes: LayoutInformation[] = themeOverview
|
||||
export default class MoreScreen {
|
||||
public static readonly officialThemes: LayoutInformation[] = themeOverview
|
||||
|
||||
constructor(
|
||||
state: UserRelatedState & {
|
||||
layoutToUse?: LayoutConfig
|
||||
},
|
||||
onMainScreen: boolean = false
|
||||
) {
|
||||
const tr = Translations.t.general.morescreen
|
||||
|
||||
const search = new TextField({
|
||||
placeholder: tr.searchForATheme,
|
||||
})
|
||||
search.enterPressed.addCallbackD((searchTerm) => {
|
||||
searchTerm = searchTerm.toLowerCase()
|
||||
if (!searchTerm) {
|
||||
return
|
||||
}
|
||||
if (searchTerm === "personal") {
|
||||
window.location.href = MoreScreen.createUrlFor(
|
||||
{ id: "personal" },
|
||||
false,
|
||||
state
|
||||
).data
|
||||
}
|
||||
if (searchTerm === "bugs" || searchTerm === "issues") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete/issues"
|
||||
}
|
||||
if (searchTerm === "source") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete"
|
||||
}
|
||||
if (searchTerm === "docs") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete/tree/develop/Docs"
|
||||
}
|
||||
if (searchTerm === "osmcha" || searchTerm === "stats") {
|
||||
window.location.href = Utils.OsmChaLinkFor(7)
|
||||
}
|
||||
// Enter pressed -> search the first _official_ matchin theme and open it
|
||||
const publicTheme = MoreScreen.officialThemes.find(
|
||||
(th) =>
|
||||
th.hideFromOverview == false &&
|
||||
th.id !== "personal" &&
|
||||
MoreScreen.MatchesLayout(th, searchTerm)
|
||||
)
|
||||
if (publicTheme !== undefined) {
|
||||
window.location.href = MoreScreen.createUrlFor(publicTheme, false, state).data
|
||||
}
|
||||
const hiddenTheme = MoreScreen.officialThemes.find(
|
||||
(th) => th.id !== "personal" && MoreScreen.MatchesLayout(th, searchTerm)
|
||||
)
|
||||
if (hiddenTheme !== undefined) {
|
||||
window.location.href = MoreScreen.createUrlFor(hiddenTheme, false, state).data
|
||||
}
|
||||
})
|
||||
|
||||
if (onMainScreen) {
|
||||
search.focus()
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.ctrlKey && event.code === "KeyF") {
|
||||
search.focus()
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
public static applySearch(searchTerm: string) {
|
||||
searchTerm = searchTerm.toLowerCase()
|
||||
if (!searchTerm) {
|
||||
return
|
||||
}
|
||||
if (searchTerm === "personal") {
|
||||
window.location.href = MoreScreen.createUrlFor({ id: "personal" }, false).data
|
||||
}
|
||||
if (searchTerm === "bugs" || searchTerm === "issues") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete/issues"
|
||||
}
|
||||
if (searchTerm === "source") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete"
|
||||
}
|
||||
if (searchTerm === "docs") {
|
||||
window.location.href = "https://github.com/pietervdvn/MapComplete/tree/develop/Docs"
|
||||
}
|
||||
if (searchTerm === "osmcha" || searchTerm === "stats") {
|
||||
window.location.href = Utils.OsmChaLinkFor(7)
|
||||
}
|
||||
// Enter pressed -> search the first _official_ matchin theme and open it
|
||||
const publicTheme = MoreScreen.officialThemes.find(
|
||||
(th) =>
|
||||
th.hideFromOverview == false &&
|
||||
th.id !== "personal" &&
|
||||
MoreScreen.MatchesLayout(th, searchTerm)
|
||||
)
|
||||
if (publicTheme !== undefined) {
|
||||
window.location.href = MoreScreen.createUrlFor(publicTheme, false).data
|
||||
}
|
||||
const hiddenTheme = MoreScreen.officialThemes.find(
|
||||
(th) => th.id !== "personal" && MoreScreen.MatchesLayout(th, searchTerm)
|
||||
)
|
||||
if (hiddenTheme !== undefined) {
|
||||
window.location.href = MoreScreen.createUrlFor(hiddenTheme, false).data
|
||||
}
|
||||
|
||||
const searchBar = new Combine([
|
||||
Svg.search_svg().SetClass("w-8"),
|
||||
search.SetClass("mr-4 w-full"),
|
||||
]).SetClass("flex rounded-full border-2 border-black items-center my-2 w-1/2")
|
||||
|
||||
super([
|
||||
new Combine([searchBar]).SetClass("flex justify-center"),
|
||||
new SvelteUIElement(ThemesList, {
|
||||
state,
|
||||
onMainScreen,
|
||||
search: search.GetValue(),
|
||||
themes: MoreScreen.officialThemes,
|
||||
}),
|
||||
new SvelteUIElement(HiddenThemeList, {
|
||||
state,
|
||||
onMainScreen,
|
||||
search: search.GetValue(),
|
||||
}),
|
||||
new SvelteUIElement(UnofficialThemeList, {
|
||||
state,
|
||||
onMainScreen,
|
||||
search: search.GetValue(),
|
||||
}),
|
||||
tr.streetcomplete.Clone().SetClass("block text-base mx-10 my-3 mb-10"),
|
||||
])
|
||||
}
|
||||
|
||||
public static MatchesLayout(
|
||||
|
@ -139,7 +78,7 @@ export default class MoreScreen extends Combine {
|
|||
return false
|
||||
}
|
||||
|
||||
private static createUrlFor(
|
||||
public static createUrlFor(
|
||||
layout: { id: string; definition?: string },
|
||||
isCustom: boolean,
|
||||
state?: { layoutToUse?: { id } }
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import NextButton from "../Base/NextButton.svelte"
|
||||
import Geosearch from "./Geosearch.svelte"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import { twJoin } from "tailwind-merge"
|
||||
import { Utils } from "../../Utils"
|
||||
|
@ -16,6 +16,7 @@
|
|||
import Add from "../../assets/svg/Add.svelte"
|
||||
import Location_refused from "../../assets/svg/Location_refused.svelte"
|
||||
import Crosshair from "../../assets/svg/Crosshair.svelte"
|
||||
import FromHtml from "../Base/FromHtml.svelte"
|
||||
|
||||
/**
|
||||
* The theme introduction panel
|
||||
|
@ -27,12 +28,12 @@
|
|||
let triggerSearch: UIEventSource<any> = new UIEventSource<any>(undefined)
|
||||
let searchEnabled = false
|
||||
|
||||
let geopermission: Readable<GeolocationPermissionState> =
|
||||
let geopermission: Store<GeolocationPermissionState> =
|
||||
state.geolocation.geolocationState.permission
|
||||
let currentGPSLocation = state.geolocation.geolocationState.currentGPSLocation
|
||||
|
||||
geopermission.addCallback((perm) => console.log(">>>> Permission", perm))
|
||||
|
||||
|
||||
function jumpToCurrentLocation() {
|
||||
const glstate = state.geolocation.geolocationState
|
||||
if (glstate.currentGPSLocation.data !== undefined) {
|
||||
|
@ -57,8 +58,8 @@
|
|||
<Tr t={Translations.t.general.welcomeExplanation.addNew} />
|
||||
{/if}
|
||||
|
||||
<Tr t={layout.descriptionTail} />
|
||||
|
||||
<Tr t={layout.descriptionTail}/>
|
||||
|
||||
<!-- Buttons: open map, go to location, search -->
|
||||
<NextButton clss="primary w-full" on:click={() => state.guistate.themeIsOpened.setData(false)}>
|
||||
<div class="flex w-full justify-center text-2xl">
|
||||
|
@ -110,8 +111,8 @@
|
|||
<Geosearch
|
||||
bounds={state.mapProperties.bounds}
|
||||
on:searchCompleted={() => state.guistate.themeIsOpened.setData(false)}
|
||||
on:searchIsValid={(isValid) => {
|
||||
searchEnabled = isValid
|
||||
on:searchIsValid={(event) => {
|
||||
searchEnabled = event.detail
|
||||
}}
|
||||
perLayer={state.perLayer}
|
||||
{selectedElement}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
export let themes: LayoutInformation[]
|
||||
export let state: { osmConnection: OsmConnection }
|
||||
export let isCustom: boolean = false
|
||||
export let onMainScreen: boolean = true
|
||||
export let hideThemes: boolean = true
|
||||
|
||||
// Filter theme based on search value
|
||||
|
@ -25,34 +24,25 @@
|
|||
|
||||
<section class="w-full">
|
||||
<slot name="title" />
|
||||
{#if onMainScreen}
|
||||
<div class="gap-4 md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3">
|
||||
{#each filteredThemes as theme (theme.id)}
|
||||
{#if theme !== undefined && !(hideThemes && theme?.hideFromOverview)}
|
||||
<!-- TODO: doesn't work if first theme is hidden -->
|
||||
{#if theme === firstTheme && !isCustom && $search !== "" && $search !== undefined}
|
||||
<ThemeButton
|
||||
{theme}
|
||||
{isCustom}
|
||||
userDetails={state.osmConnection.userDetails}
|
||||
{state}
|
||||
selected={true}
|
||||
/>
|
||||
{:else}
|
||||
<ThemeButton {theme} {isCustom} userDetails={state.osmConnection.userDetails} {state} />
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div>
|
||||
{#each filteredThemes as theme (theme.id)}
|
||||
{#if theme !== undefined && !(hideThemes && theme?.hideFromOverview)}
|
||||
<div class="gap-4 md:grid md:grid-flow-row md:grid-cols-2 lg:grid-cols-3">
|
||||
{#each filteredThemes as theme (theme.id)}
|
||||
{#if theme !== undefined && !(hideThemes && theme?.hideFromOverview)}
|
||||
<!-- TODO: doesn't work if first theme is hidden -->
|
||||
{#if theme === firstTheme && !isCustom && $search !== "" && $search !== undefined}
|
||||
<ThemeButton
|
||||
{theme}
|
||||
{isCustom}
|
||||
userDetails={state.osmConnection.userDetails}
|
||||
{state}
|
||||
selected={true}
|
||||
/>
|
||||
{:else}
|
||||
<ThemeButton {theme} {isCustom} userDetails={state.osmConnection.userDetails} {state} />
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
|
||||
{#if filteredThemes.length === 0}
|
||||
<NoThemeResultButton {search} />
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
import ThemesList from "./ThemesList.svelte"
|
||||
import Translations from "../i18n/Translations"
|
||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
||||
import Tr from "../Base/Tr.svelte"
|
||||
|
||||
export let search: UIEventSource<string>
|
||||
export let state: UserRelatedState & {
|
||||
osmConnection: OsmConnection
|
||||
}
|
||||
export let onMainScreen: boolean = true
|
||||
|
||||
const t = Translations.t.general
|
||||
const currentIds: Store<string[]> = state.installedUserThemes
|
||||
|
@ -24,14 +24,15 @@
|
|||
<ThemesList
|
||||
{search}
|
||||
{state}
|
||||
{onMainScreen}
|
||||
themes={customThemes}
|
||||
isCustom={true}
|
||||
hideThemes={false}
|
||||
>
|
||||
<svelte:fragment slot="title">
|
||||
<!-- TODO: Change string to exclude html -->
|
||||
{@html t.customThemeIntro.toString()}
|
||||
<h3>
|
||||
<Tr t={t.customThemeTitle} />
|
||||
</h3>
|
||||
<Tr t={t.customThemeIntro} />
|
||||
</svelte:fragment>
|
||||
</ThemesList>
|
||||
{/if}
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
import { Translation } from "../UI/i18n/Translation"
|
||||
|
||||
export function ariaLabel(htmlElement: Element, t: Translation) {
|
||||
let onDestroy: () => void = undefined
|
||||
let destroy: () => void = undefined
|
||||
|
||||
t.current.map(
|
||||
(label) => {
|
||||
console.log("Setting arialabel", label, "to", htmlElement)
|
||||
htmlElement.setAttribute("aria-label", label)
|
||||
},
|
||||
[],
|
||||
(f) => {
|
||||
onDestroy = f
|
||||
destroy = f
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
destroy() {},
|
||||
}
|
||||
return { destroy }
|
||||
}
|
||||
|
|
17
src/Utils/placeholder.ts
Normal file
17
src/Utils/placeholder.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import { Translation } from "../UI/i18n/Translation"
|
||||
|
||||
export function placeholder(htmlElement: HTMLInputElement, t: Translation) {
|
||||
let destroy: () => void = undefined
|
||||
|
||||
t.current.map(
|
||||
(label) => {
|
||||
htmlElement.setAttribute("placeholder", label)
|
||||
},
|
||||
[],
|
||||
(f) => {
|
||||
destroy = f
|
||||
}
|
||||
)
|
||||
|
||||
return { destroy }
|
||||
}
|
Loading…
Reference in a new issue