forked from MapComplete/MapComplete
Experimenting with Svelte: build a wrapper to convert 'old' components into Svelte, add a community index overview
This commit is contained in:
parent
dfc7ba2114
commit
02da80c311
11 changed files with 250 additions and 55 deletions
17
UI/Base/ToSvelte.svelte
Normal file
17
UI/Base/ToSvelte.svelte
Normal file
|
@ -0,0 +1,17 @@
|
|||
<script lang="ts">
|
||||
import BaseUIElement from "../BaseUIElement.js";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
export let construct: BaseUIElement | (() => BaseUIElement);
|
||||
let elem: HTMLElement;
|
||||
onMount(() => {
|
||||
let html: HTMLElement
|
||||
if (typeof construct === "function") {
|
||||
html = construct().ConstructElement();
|
||||
} else {
|
||||
html = construct.ConstructElement();
|
||||
}
|
||||
elem.appendChild(html)
|
||||
});
|
||||
</script>
|
||||
<span bind:this={elem}></span>
|
|
@ -1,14 +1,44 @@
|
|||
<script lang="ts">
|
||||
import {BBox} from "../../Logic/BBox";
|
||||
import {Store} from "../../Logic/UIEventSource";
|
||||
import Loc from "../../Models/Loc";
|
||||
import { Store, UIEventSource } from "../../Logic/UIEventSource";
|
||||
import { Tiles } from "../../Models/TileRange";
|
||||
import { Utils } from "../../Utils";
|
||||
import global_community from "../../assets/community_index_global_resources.json";
|
||||
import ContactLink from "./ContactLink.svelte";
|
||||
import { GeoOperations } from "../../Logic/GeoOperations";
|
||||
import Translations from "../i18n/Translations";
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import { ImmutableStore } from "../../Logic/UIEventSource.js";
|
||||
|
||||
export let locationControl: Store<{ lat: number, lon: number }>;
|
||||
const tileToFetch: Store<string> = locationControl.mapD(l => {
|
||||
const t = Tiles.embedded_tile(l.lat, l.lon, 6);
|
||||
return `https://raw.githubusercontent.com/pietervdvn/MapComplete-data/main/community_index/tile_${t.z}_${t.x}_${t.y}.geojson`;
|
||||
});
|
||||
const t = Translations.t.communityIndex
|
||||
const resources = new UIEventSource<[]>([]);
|
||||
|
||||
tileToFetch.addCallbackAndRun(async url => {
|
||||
const data = await Utils.downloadJsonCached(url, 24 * 60 * 60);
|
||||
if (data === undefined) {
|
||||
return;
|
||||
}
|
||||
resources.setData(data.features);
|
||||
}
|
||||
);
|
||||
|
||||
const filteredResources = resources.map(features => features.filter(f => {
|
||||
return GeoOperations.inside([locationControl.data.lon, locationControl.data.lat], f)
|
||||
}),
|
||||
[locationControl]);
|
||||
|
||||
|
||||
export let bbox: Store<BBox>
|
||||
export let currentLocation: Store<Loc>
|
||||
bbox.mapD(bbox => {
|
||||
if(currentLocation.data.zoom <= 6){
|
||||
// only return the global data
|
||||
}
|
||||
return bbox.expandToTileBounds(6);
|
||||
}, [currentLocation])
|
||||
</script>
|
||||
|
||||
|
||||
<div>
|
||||
<ToSvelte construct={t.intro} />
|
||||
{#each $filteredResources as feature}
|
||||
<ContactLink country={feature.properties} />
|
||||
{/each}
|
||||
<ContactLink country={{resources:global_community, nameEn: "Global resources"}} />
|
||||
</div>
|
||||
|
|
|
@ -1,34 +1,46 @@
|
|||
<script lang="ts">
|
||||
import {Store} from "../../Logic/UIEventSource";
|
||||
// A contact link indicates how a mapper can contact their local community
|
||||
// The _properties_ of a community feature
|
||||
export let country: Store<{ resources; nameEn: string }>
|
||||
let resources : Store<{ id: string, resolved: Record<string, string> }[]> = country.map(country => {
|
||||
if(country === undefined){
|
||||
return []
|
||||
}
|
||||
return Array.from(Object.values(country?.resources ?? {}))
|
||||
})
|
||||
// A contact link indicates how a mapper can contact their local community
|
||||
// The _properties_ of a community feature
|
||||
import Locale from "../i18n/Locale.js";
|
||||
import Translations from "../i18n/Translations";
|
||||
import ToSvelte from "../Base/ToSvelte.svelte";
|
||||
import * as native from "../../assets/language_native.json";
|
||||
import { TypedTranslation } from "../i18n/Translation";
|
||||
|
||||
const availableTranslationTyped: TypedTranslation<{ native: string }> = Translations.t.communityIndex.available;
|
||||
const availableTranslation = availableTranslationTyped.OnEveryLanguage((s, ln) => s.replace("{native}", native[ln] ?? ln));
|
||||
export let country: { resources; nameEn: string };
|
||||
let resources: { id: string, resolved: Record<string, string>, languageCodes: string[] }[] = []
|
||||
$: resources = Array.from(Object.values(country?.resources ?? {}));
|
||||
|
||||
const language = Locale.language;
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
{#if $country?.nameEn}
|
||||
<h3>{$country?.nameEn}</h3>
|
||||
{/if}
|
||||
{#each $resources as resource}
|
||||
<div class="flex link-underline items-center">
|
||||
<img
|
||||
class="w-8 h-8 m-2"
|
||||
src={"https://raw.githubusercontent.com/osmlab/osm-community-index/main/dist/img/" +
|
||||
{#if country?.nameEn}
|
||||
<h3>{country?.nameEn}</h3>
|
||||
{/if}
|
||||
{#each resources as resource}
|
||||
<div class="flex link-underline items-center my-4">
|
||||
<img
|
||||
class="w-8 h-8 m-2"
|
||||
src={"https://raw.githubusercontent.com/osmlab/osm-community-index/main/dist/img/" +
|
||||
resource.type +
|
||||
".svg"}
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<a href={resource.resolved.url} target="_blank" class="font-bold">
|
||||
{resource.resolved.name ?? resource.resolved.url}
|
||||
</a>
|
||||
{resource.resolved?.description}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
/>
|
||||
<div class="flex flex-col">
|
||||
<a href={resource.resolved.url} target="_blank" rel="noreferrer nofollow" class="font-bold">
|
||||
{resource.resolved.name ?? resource.resolved.url}
|
||||
</a>
|
||||
{resource.resolved?.description}
|
||||
{#if (resource.languageCodes?.indexOf($language) >= 0)}
|
||||
<span class="border-2 rounded-full border-lime-500 text-sm w-fit px-2">
|
||||
<ToSvelte construct={() => availableTranslation.Clone()} />
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
@ -34,6 +34,8 @@ import { GeoLocationState } from "../Logic/State/GeoLocationState"
|
|||
import Hotkeys from "./Base/Hotkeys"
|
||||
import AvailableBaseLayers from "../Logic/Actors/AvailableBaseLayers"
|
||||
import CopyrightPanel from "./BigComponents/CopyrightPanel"
|
||||
import SvelteUIElement from "./Base/SvelteUIElement"
|
||||
import CommunityIndexView from "./BigComponents/CommunityIndexView.svelte"
|
||||
|
||||
/**
|
||||
* The default MapComplete GUI initializer
|
||||
|
@ -237,6 +239,20 @@ export default class DefaultGUI {
|
|||
const welcomeMessageMapControl = Toggle.If(state.featureSwitchWelcomeMessage, () =>
|
||||
self.InitWelcomeMessage()
|
||||
)
|
||||
|
||||
const communityIndex = Toggle.If(state.featureSwitchCommunityIndex, () => {
|
||||
const communityIndexControl = new MapControlButton(Svg.community_svg())
|
||||
const communityIndex = new ScrollableFullScreen(
|
||||
() => Translations.t.communityIndex.title,
|
||||
() => new SvelteUIElement(CommunityIndexView, { ...state }),
|
||||
"community_index"
|
||||
)
|
||||
communityIndexControl.onClick(() => {
|
||||
communityIndex.Activate()
|
||||
})
|
||||
return communityIndexControl
|
||||
})
|
||||
|
||||
const testingBadge = Toggle.If(state.featureSwitchIsTesting, () =>
|
||||
new FixedUiElement("TESTING").SetClass("alert m-2 border-2 border-black")
|
||||
)
|
||||
|
@ -253,6 +269,7 @@ export default class DefaultGUI {
|
|||
welcomeMessageMapControl,
|
||||
userInfoMapControl,
|
||||
copyright,
|
||||
communityIndex,
|
||||
extraLink,
|
||||
testingBadge,
|
||||
])
|
||||
|
|
|
@ -2,6 +2,7 @@ import Locale from "./Locale"
|
|||
import { Utils } from "../../Utils"
|
||||
import BaseUIElement from "../BaseUIElement"
|
||||
import LinkToWeblate from "../Base/LinkToWeblate"
|
||||
import { SvelteComponent } from "svelte"
|
||||
|
||||
export class Translation extends BaseUIElement {
|
||||
public static forcedLanguage = undefined
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue