forked from MapComplete/MapComplete
refactoring: fix basic flow to add a new point
This commit is contained in:
parent
52a0810ea9
commit
0241f89d3d
109 changed files with 1931 additions and 1446 deletions
|
|
@ -11,18 +11,17 @@
|
|||
let mainElem: HTMLElement;
|
||||
export let hideSignal: Store<any>;
|
||||
function hide(){
|
||||
console.trace("Hiding...")
|
||||
mainElem.style.visibility = "hidden";
|
||||
}
|
||||
if (hideSignal) {
|
||||
onDestroy(hideSignal.addCallbackD(() => {
|
||||
console.trace("Hiding invitation")
|
||||
console.log("Received hide signal")
|
||||
hide()
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
$: {
|
||||
console.log("Binding listeners on", mainElem)
|
||||
mainElem?.addEventListener("click",_ => hide())
|
||||
mainElem?.addEventListener("touchstart",_ => hide())
|
||||
}
|
||||
|
|
@ -30,8 +29,8 @@ $: {
|
|||
|
||||
|
||||
<div bind:this={mainElem} class="absolute bottom-0 right-0 w-full h-full">
|
||||
<div id="hand-container">
|
||||
<ToSvelte construct={Svg.hand_ui}></ToSvelte>
|
||||
<div id="hand-container" class="pointer-events-none">
|
||||
<img src="./assets/svg/hand.svg"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,20 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { XCircleIcon } from "@rgossiaux/svelte-heroicons/solid";
|
||||
|
||||
/**
|
||||
* The slotted element will be shown on top, with a lower-opacity border
|
||||
*/
|
||||
const dispatch = createEventDispatcher<{ close }>();
|
||||
</script>
|
||||
|
||||
<div class="absolute top-0 right-0 w-screen h-screen overflow-auto" style="background-color: #00000088">
|
||||
<div class="flex flex-col m-4 sm:m-6 md:m-8 p-4 sm:p-6 md:m-8 normal-background rounded normal-background">
|
||||
<slot name="close-button">
|
||||
<div class="w-8 h-8 absolute right-10 top-10 cursor-pointer" on:click={() => dispatch("close")}>
|
||||
<XCircleIcon />
|
||||
</div>
|
||||
</slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
15
UI/Base/LoginButton.svelte
Normal file
15
UI/Base/LoginButton.svelte
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<script lang="ts">
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection";
|
||||
import SubtleButton from "./SubtleButton.svelte";
|
||||
import Translations from "../i18n/Translations.js";
|
||||
import Tr from "./Tr.svelte";
|
||||
|
||||
export let osmConnection: OsmConnection
|
||||
</script>
|
||||
|
||||
<SubtleButton on:click={() => osmConnection.AttemptLogin()}>
|
||||
<img slot="image" src="./assets/svg/login.svg" class="w-8"/>
|
||||
<slot name="message" slot="message">
|
||||
<Tr t={Translations.t.general.loginWithOpenStreetMap}/>
|
||||
</slot>
|
||||
</SubtleButton>
|
||||
45
UI/Base/LoginToggle.svelte
Normal file
45
UI/Base/LoginToggle.svelte
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<script lang="ts">
|
||||
import Loading from "./Loading.svelte";
|
||||
import type { SpecialVisualizationState } from "../SpecialVisualization";
|
||||
import type { OsmServiceState } from "../../Logic/Osm/OsmConnection";
|
||||
import { Translation } from "../i18n/Translation";
|
||||
import Translations from "../i18n/Translations";
|
||||
import Tr from "./Tr.svelte";
|
||||
|
||||
export let state: SpecialVisualizationState;
|
||||
/**
|
||||
* If set, 'loading' will act as if we are already logged in.
|
||||
*/
|
||||
export let ignoreLoading: boolean = false
|
||||
let loadingStatus = state.osmConnection.loadingStatus;
|
||||
let badge = state.featureSwitches.featureSwitchUserbadge;
|
||||
const t = Translations.t.general;
|
||||
const offlineModes: Partial<Record<OsmServiceState, Translation>> = {
|
||||
offline: t.loginFailedOfflineMode,
|
||||
unreachable: t.loginFailedUnreachableMode,
|
||||
readonly: t.loginFailedReadonlyMode
|
||||
};
|
||||
const apiState = state.osmConnection.apiIsOnline;
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{#if $badge}
|
||||
{#if !ignoreLoading && $loadingStatus === "loading"}
|
||||
<slot name="loading">
|
||||
<Loading></Loading>
|
||||
</slot>
|
||||
{:else if $loadingStatus === "error"}
|
||||
<div class="flex items-center alert max-w-64">
|
||||
<img src="./assets/svg/invalid.svg" class="w-8 h-8 m-2 shrink-0">
|
||||
<Tr t={offlineModes[$apiState]} />
|
||||
</div>
|
||||
|
||||
{:else if $loadingStatus === "logged-in"}
|
||||
<slot></slot>
|
||||
{:else if $loadingStatus === "not-attempted"}
|
||||
<slot name="not-logged-in">
|
||||
|
||||
</slot>
|
||||
{/if}
|
||||
{/if}
|
||||
|
|
@ -8,6 +8,6 @@
|
|||
</script>
|
||||
|
||||
|
||||
<div on:click={e => dispatch("click", e)} class="subtle-background rounded-full min-w-10 w-fit h-10 m-0.5 md:m-1 p-1">
|
||||
<div on:click={e => dispatch("click", e)} class="subtle-background rounded-full min-w-10 w-fit h-10 m-0.5 md:m-1 p-1 cursor-pointer">
|
||||
<slot class="m-4"></slot>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { createEventDispatcher, onMount } from "svelte";
|
||||
import { Store } from "../../Logic/UIEventSource";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import Img from "./Img";
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
let imgElem: HTMLElement;
|
||||
let msgElem: HTMLElement;
|
||||
let imgClasses = "block justify-center shrink-0 mr-4 " + (options?.imgSize ?? "h-11 w-11");
|
||||
|
||||
const dispatch = createEventDispatcher<{click}>()
|
||||
onMount(() => {
|
||||
// Image
|
||||
if (imgElem && imageUrl) {
|
||||
|
|
@ -47,15 +47,16 @@
|
|||
</script>
|
||||
|
||||
<svelte:element
|
||||
class={(options.extraClasses??"") + 'flex hover:shadow-xl transition-[color,background-color,box-shadow] hover:bg-unsubtle'}
|
||||
class={(options.extraClasses??"") + 'flex hover:shadow-xl transition-[color,background-color,box-shadow] hover:bg-unsubtle cursor-pointer'}
|
||||
href={$href}
|
||||
target={options?.newTab ? "_blank" : ""}
|
||||
this={href === undefined ? "span" : "a"}
|
||||
on:click={(e) => dispatch("click", e)}
|
||||
>
|
||||
<slot name="image">
|
||||
{#if imageUrl !== undefined}
|
||||
{#if typeof imageUrl === "string"}
|
||||
<Img src={imageUrl} class={imgClasses+ " bg-red border border-black"}></Img>
|
||||
<Img src={imageUrl} class={imgClasses}></Img>
|
||||
{:else }
|
||||
<template bind:this={imgElem} />
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -20,11 +20,15 @@ export default class SvelteUIElement<
|
|||
}): SvelteComponentTyped<Props, Events, Slots>
|
||||
}
|
||||
private readonly _props: Props
|
||||
private readonly _events: Events
|
||||
private readonly _slots: Slots
|
||||
|
||||
constructor(svelteElement, props: Props) {
|
||||
constructor(svelteElement, props: Props, events?: Events, slots?: Slots) {
|
||||
super()
|
||||
this._svelteComponent = svelteElement
|
||||
this._props = props
|
||||
this._events = events
|
||||
this._slots = slots
|
||||
}
|
||||
|
||||
protected InnerConstructElement(): HTMLElement {
|
||||
|
|
@ -32,6 +36,8 @@ export default class SvelteUIElement<
|
|||
new this._svelteComponent({
|
||||
target: el,
|
||||
props: this._props,
|
||||
events: this._events,
|
||||
slots: this._slots,
|
||||
})
|
||||
return el
|
||||
}
|
||||
|
|
|
|||
68
UI/Base/TabbedGroup.svelte
Normal file
68
UI/Base/TabbedGroup.svelte
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<script lang="ts">
|
||||
/**
|
||||
* Thin wrapper around 'TabGroup' which binds the state
|
||||
*/
|
||||
|
||||
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from "@rgossiaux/svelte-headlessui";
|
||||
import { UIEventSource } from "../../Logic/UIEventSource";
|
||||
|
||||
export let tab: UIEventSource<number>;
|
||||
let tabElements: HTMLElement[] = [];
|
||||
$: tabElements[$tab]?.click();
|
||||
$: {
|
||||
if (tabElements[tab.data]) {
|
||||
window.setTimeout(() => tabElements[tab.data].click(), 50)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<TabGroup defaultIndex={1} on:change={(e) =>{if(e.detail >= 0){tab.setData( e.detail); }} }>
|
||||
<TabList>
|
||||
<Tab class={({selected}) => selected ? "tab-selected" : "tab-unselected"}>
|
||||
<div bind:this={tabElements[0]} class="flex">
|
||||
<slot name="title0">
|
||||
Tab 0
|
||||
</slot>
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab class={({selected}) => selected ? "tab-selected" : "tab-unselected"}>
|
||||
<div bind:this={tabElements[1]} class="flex">
|
||||
<slot name="title1" />
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab class={({selected}) => selected ? "tab-selected" : "tab-unselected"}>
|
||||
<div bind:this={tabElements[2]} class="flex">
|
||||
<slot name="title2" />
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab class={({selected}) => selected ? "tab-selected" : "tab-unselected"}>
|
||||
<div bind:this={tabElements[3]} class="flex">
|
||||
<slot name="title3" />
|
||||
</div>
|
||||
</Tab>
|
||||
<Tab class={({selected}) => selected ? "tab-selected" : "tab-unselected"}>
|
||||
<div bind:this={tabElements[4]} class="flex">
|
||||
<slot name="title4" />
|
||||
</div>
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels defaultIndex={$tab}>
|
||||
<TabPanel>
|
||||
<slot name="content0">
|
||||
<div>Empty</div>
|
||||
</slot>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<slot name="content1" />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<slot name="content2" />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<slot name="content3" />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<slot name="content4" />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</TabGroup>
|
||||
Loading…
Add table
Add a link
Reference in a new issue