Studio: Add deeplinks, fix #1926
This commit is contained in:
parent
204027b4e9
commit
504cc1fe33
5 changed files with 82 additions and 40 deletions
|
@ -20,12 +20,16 @@
|
|||
import NextButton from "../Base/NextButton.svelte"
|
||||
import BackButton from "../Base/BackButton.svelte"
|
||||
import DeleteButton from "./DeleteButton.svelte"
|
||||
import StudioHashSetter from "./StudioHashSetter"
|
||||
|
||||
const layerSchema: ConfigMeta[] = <any>layerSchemaRaw
|
||||
|
||||
export let state: EditLayerState
|
||||
|
||||
export let backToStudio: () => void
|
||||
|
||||
new StudioHashSetter("layer", state.selectedTab, state.getStoreFor(["id"]))
|
||||
|
||||
let messages = state.messages
|
||||
let hasErrors = messages.mapD(
|
||||
(m: ConversionMessage[]) => m.filter((m) => m.level === "error").length
|
||||
|
@ -127,7 +131,7 @@
|
|||
{/each}
|
||||
{:else}
|
||||
<div class="m4 h-full overflow-y-auto">
|
||||
<TabbedGroup>
|
||||
<TabbedGroup tab={state.selectedTab}>
|
||||
<div slot="title0" class="flex">
|
||||
General properties
|
||||
<ErrorIndicatorForRegion firstPaths={firstPathsFor("Basic")} {state} />
|
||||
|
|
|
@ -42,6 +42,11 @@ export abstract class EditJsonState<T> {
|
|||
public readonly configuration: UIEventSource<Partial<T>> = new UIEventSource<Partial<T>>({})
|
||||
public readonly messages: Store<ConversionMessage[]>
|
||||
|
||||
/**
|
||||
* The tab in the UI that is selected, used for deeplinks
|
||||
*/
|
||||
public readonly selectedTab: UIEventSource<number> = new UIEventSource<number>(0)
|
||||
|
||||
/**
|
||||
* The EditLayerUI shows a 'schemaBasedInput' for this path to pop advanced questions out
|
||||
*/
|
||||
|
|
|
@ -9,12 +9,15 @@
|
|||
import RawEditor from "./RawEditor.svelte"
|
||||
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
|
||||
import DeleteButton from "./DeleteButton.svelte"
|
||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||
import StudioHashSetter from "./StudioHashSetter"
|
||||
|
||||
export let state: EditThemeState
|
||||
export let osmConnection: OsmConnection
|
||||
export let backToStudio: () => void
|
||||
|
||||
let schema: ConfigMeta[] = state.schema.filter((schema) => schema.path.length > 0)
|
||||
new StudioHashSetter("theme", state.selectedTab, state.getStoreFor(["id"]))
|
||||
|
||||
export let selfLayers: { owner: number; id: string }[]
|
||||
export let otherLayers: { owner: number; id: string }[]
|
||||
|
@ -94,7 +97,7 @@
|
|||
|
||||
<div class="m4 h-full overflow-y-auto">
|
||||
<!-- {Object.keys(perRegion).join(";")} -->
|
||||
<TabbedGroup>
|
||||
<TabbedGroup tab={state.selectedTab}>
|
||||
<div slot="title0">Basic properties</div>
|
||||
<div slot="content0" class="mb-8">
|
||||
<Region configs={perRegion["basic"]} path={[]} {state} title="Basic properties" />
|
||||
|
|
11
src/UI/Studio/StudioHashSetter.ts
Normal file
11
src/UI/Studio/StudioHashSetter.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import Hash from "../../Logic/Web/Hash"
|
||||
|
||||
export default class StudioHashSetter {
|
||||
constructor(mode: "layer" | "theme", tab: Store<number>, name: Store<string>) {
|
||||
tab.mapD(tab => {
|
||||
Hash.hash.setData(mode + "/" + name.data + "/" + tab)
|
||||
}
|
||||
, [name])
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import NextButton from "./Base/NextButton.svelte"
|
||||
import { Store, UIEventSource } from "../Logic/UIEventSource"
|
||||
import EditLayerState, { EditThemeState } from "./Studio/EditLayerState"
|
||||
import EditLayerState, { EditJsonState, EditThemeState } from "./Studio/EditLayerState"
|
||||
import EditLayer from "./Studio/EditLayer.svelte"
|
||||
import Loading from "../assets/svg/Loading.svelte"
|
||||
import StudioServer from "./Studio/StudioServer"
|
||||
|
@ -30,6 +30,7 @@
|
|||
import Tr from "./Base/Tr.svelte"
|
||||
import Add from "../assets/svg/Add.svelte"
|
||||
import { SearchIcon } from "@rgossiaux/svelte-heroicons/solid"
|
||||
import Hash from "../Logic/Web/Hash"
|
||||
|
||||
export let studioUrl =
|
||||
window.location.hostname === "127.0.0.2"
|
||||
|
@ -43,11 +44,11 @@
|
|||
)
|
||||
let osmConnection = new OsmConnection({
|
||||
oauth_token,
|
||||
checkOnlineRegularly: true,
|
||||
checkOnlineRegularly: true
|
||||
})
|
||||
const expertMode = UIEventSource.asBoolean(
|
||||
osmConnection.GetPreference("studio-expert-mode", "false", {
|
||||
documentation: "Indicates if more options are shown in mapcomplete studio",
|
||||
documentation: "Indicates if more options are shown in mapcomplete studio"
|
||||
})
|
||||
)
|
||||
expertMode.addCallbackAndRunD((expert) => console.log("Expert mode is", expert))
|
||||
|
@ -61,12 +62,12 @@
|
|||
l["success"]?.filter((l) => l.category === "layers")
|
||||
)
|
||||
$: selfLayers = layers.mapD(
|
||||
(ls) =>
|
||||
ls.filter(
|
||||
(l) => l.owner === uid.data && l.id.toLowerCase().includes(layerFilterTerm.toLowerCase())
|
||||
),
|
||||
[uid]
|
||||
)
|
||||
(ls) =>
|
||||
ls.filter(
|
||||
(l) => l.owner === uid.data && l.id.toLowerCase().includes(layerFilterTerm.toLowerCase())
|
||||
),
|
||||
[uid]
|
||||
)
|
||||
$: otherLayers = layers.mapD(
|
||||
(ls) =>
|
||||
ls.filter(
|
||||
|
@ -132,16 +133,17 @@
|
|||
|
||||
const version = meta.version
|
||||
|
||||
async function editLayer(event: Event) {
|
||||
async function editLayer(event: { detail }): Promise<EditLayerState> {
|
||||
const layerId: { owner: number; id: string } = event["detail"]
|
||||
state = "loading"
|
||||
editLayerState.startSavingUpdates(false)
|
||||
editLayerState.configuration.setData(await studio.fetch(layerId.id, "layers", layerId.owner))
|
||||
editLayerState.startSavingUpdates()
|
||||
state = "editing_layer"
|
||||
return editLayerState
|
||||
}
|
||||
|
||||
async function editTheme(event: Event) {
|
||||
async function editTheme(event: { detail }): Promise<EditThemeState> {
|
||||
const id: { id: string; owner: number } = event["detail"]
|
||||
state = "loading"
|
||||
editThemeState.startSavingUpdates(false)
|
||||
|
@ -149,6 +151,7 @@
|
|||
editThemeState.configuration.setData(layout)
|
||||
editThemeState.startSavingUpdates()
|
||||
state = "editing_theme"
|
||||
return editThemeState
|
||||
}
|
||||
|
||||
async function createNewLayer() {
|
||||
|
@ -162,23 +165,50 @@
|
|||
marker: [
|
||||
{
|
||||
icon: "circle",
|
||||
color: "white",
|
||||
},
|
||||
],
|
||||
},
|
||||
color: "white"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
tagRenderings: ["images"],
|
||||
lineRendering: [
|
||||
{
|
||||
width: 1,
|
||||
color: "blue",
|
||||
},
|
||||
],
|
||||
color: "blue"
|
||||
}
|
||||
]
|
||||
}
|
||||
editLayerState.configuration.setData(initialLayerConfig)
|
||||
editLayerState.startSavingUpdates()
|
||||
state = "editing_layer"
|
||||
}
|
||||
|
||||
async function selectStateBasedOnHash() {
|
||||
const hash = Hash.hash.data
|
||||
if (!hash) {
|
||||
return
|
||||
}
|
||||
console.log("Selecting state based on ", hash)
|
||||
const [mode, id, tab] = hash.split("/")
|
||||
// Not really an event, we just set the 'detail'
|
||||
const event = {
|
||||
detail: {
|
||||
id,
|
||||
owner: uid.data
|
||||
}
|
||||
}
|
||||
const statePromise: Promise<EditJsonState<any>> = mode === "layer" ? editLayer(event) : editTheme(event)
|
||||
const state = await statePromise
|
||||
state.selectedTab.setData(Number(tab))
|
||||
}
|
||||
|
||||
selectStateBasedOnHash()
|
||||
|
||||
function backToStudio() {
|
||||
console.log("Back to studio")
|
||||
state = undefined
|
||||
Hash.hash.setData(undefined)
|
||||
}
|
||||
</script>
|
||||
|
||||
<If condition={layersWithErr.map((d) => d?.["error"] !== undefined)}>
|
||||
|
@ -191,8 +221,8 @@
|
|||
<li>Try again in a few minutes</li>
|
||||
<li>
|
||||
Contact <a href="https://app.element.io/#/room/#MapComplete:matrix.org">
|
||||
the MapComplete community via the chat.
|
||||
</a>
|
||||
the MapComplete community via the chat.
|
||||
</a>
|
||||
Someone might be able to help you
|
||||
</li>
|
||||
<li>
|
||||
|
@ -257,9 +287,7 @@
|
|||
<BackButton
|
||||
clss="small p-1"
|
||||
imageClass="w-8 h-8"
|
||||
on:click={() => {
|
||||
state = undefined
|
||||
}}
|
||||
on:click={() => backToStudio()}
|
||||
>
|
||||
MapComplete Studio
|
||||
</BackButton>
|
||||
|
@ -306,9 +334,7 @@
|
|||
<BackButton
|
||||
clss="small p-1"
|
||||
imageClass="w-8 h-8"
|
||||
on:click={() => {
|
||||
state = undefined
|
||||
}}
|
||||
on:click={() => backToStudio()}
|
||||
>
|
||||
MapComplete Studio
|
||||
</BackButton>
|
||||
|
@ -348,30 +374,23 @@
|
|||
{:else if state === "editing_layer"}
|
||||
<EditLayer
|
||||
state={editLayerState}
|
||||
backToStudio={() => {
|
||||
state = undefined
|
||||
}}
|
||||
{backToStudio}
|
||||
>
|
||||
<BackButton
|
||||
clss="small p-1"
|
||||
imageClass="w-8 h-8"
|
||||
on:click={() => {
|
||||
state = undefined
|
||||
}}
|
||||
on:click={() => backToStudio()}
|
||||
>
|
||||
MapComplete Studio
|
||||
</BackButton>
|
||||
</EditLayer>
|
||||
{:else if state === "editing_theme"}
|
||||
<EditTheme state={editThemeState} selfLayers={$selfLayers} otherLayers={$otherLayers} {osmConnection} backToStudio={() => {
|
||||
state = undefined
|
||||
}}>
|
||||
<EditTheme state={editThemeState} selfLayers={$selfLayers} otherLayers={$otherLayers} {osmConnection}
|
||||
{backToStudio}>
|
||||
<BackButton
|
||||
clss="small p-1"
|
||||
imageClass="w-8 h-8"
|
||||
on:click={() => {
|
||||
state = undefined
|
||||
}}
|
||||
on:click={() => backToStudio()}
|
||||
>
|
||||
MapComplete Studio
|
||||
</BackButton>
|
||||
|
|
Loading…
Reference in a new issue