forked from MapComplete/MapComplete
WIP: more features in inspector
This commit is contained in:
parent
c34300fae1
commit
552ea22275
19 changed files with 526 additions and 65 deletions
165
src/UI/InspectorGUI.svelte
Normal file
165
src/UI/InspectorGUI.svelte
Normal file
|
@ -0,0 +1,165 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../Logic/UIEventSource"
|
||||
import { QueryParameters } from "../Logic/Web/QueryParameters"
|
||||
import ValidatedInput from "./InputElement/ValidatedInput.svelte"
|
||||
import { Overpass } from "../Logic/Osm/Overpass"
|
||||
import Constants from "../Models/Constants"
|
||||
import MaplibreMap from "./Map/MaplibreMap.svelte"
|
||||
import { MapLibreAdaptor } from "./Map/MapLibreAdaptor"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import ShowDataLayer from "./Map/ShowDataLayer"
|
||||
import * as inspector_theme from "../assets/generated/themes/inspector.json"
|
||||
|
||||
import StaticFeatureSource from "../Logic/FeatureSource/Sources/StaticFeatureSource"
|
||||
import type { Feature } from "geojson"
|
||||
import Loading from "./Base/Loading.svelte"
|
||||
import { linear } from "svelte/easing"
|
||||
import { Drawer } from "flowbite-svelte"
|
||||
import ThemeConfig from "../Models/ThemeConfig/ThemeConfig"
|
||||
import History from "./History/History.svelte"
|
||||
import TitledPanel from "./Base/TitledPanel.svelte"
|
||||
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
|
||||
import { Utils } from "../Utils"
|
||||
import AggregateView from "./History/AggregateView.svelte"
|
||||
|
||||
let username = QueryParameters.GetQueryParameter("user", undefined, "Inspect this user")
|
||||
let step = new UIEventSource<"waiting" | "loading" | "done">("waiting")
|
||||
let map = new UIEventSource<MlMap>(undefined)
|
||||
let zoom = UIEventSource.asFloat(QueryParameters.GetQueryParameter("z", "0"))
|
||||
let lat = UIEventSource.asFloat(QueryParameters.GetQueryParameter("lat", "0"))
|
||||
let lon = UIEventSource.asFloat(QueryParameters.GetQueryParameter("lon", "0"))
|
||||
let theme = new ThemeConfig(<any>inspector_theme, true)
|
||||
let layer = theme.layers.find(l => l.id === "usertouched")
|
||||
theme.getMatchingLayer = () => {
|
||||
// Is this a dirty hack? Yes it is!
|
||||
return layer
|
||||
}
|
||||
let loadingData = false
|
||||
let selectedElement = new UIEventSource<Feature>(undefined)
|
||||
|
||||
let maplibremap: MapLibreAdaptor = new MapLibreAdaptor(map, {
|
||||
zoom,
|
||||
location: new UIEventSource<{ lon: number; lat: number }>({ lat: lat.data, lon: lon.data })
|
||||
})
|
||||
maplibremap.location.stabilized(500).addCallbackAndRunD(l => {
|
||||
lat.set(l.lat)
|
||||
lon.set(l.lon)
|
||||
})
|
||||
|
||||
|
||||
let featuresStore = new UIEventSource<Feature[]>([])
|
||||
let features = new StaticFeatureSource(featuresStore)
|
||||
new ShowDataLayer(map,
|
||||
{
|
||||
layer,
|
||||
zoomToFeatures: true,
|
||||
features,
|
||||
onClick: (f: Feature) => {
|
||||
selectedElement.set(undefined)
|
||||
Utils.waitFor(200).then(() => {
|
||||
selectedElement.set(f)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
async function load() {
|
||||
|
||||
step.setData("loading")
|
||||
const overpass = new Overpass(undefined, ["nw(user_touched:\"" + username.data + "\");"], Constants.defaultOverpassUrls[0])
|
||||
if (!maplibremap.bounds.data) {
|
||||
return
|
||||
}
|
||||
loadingData = true
|
||||
const [data, date] = await overpass.queryGeoJson(maplibremap.bounds.data)
|
||||
console.log("Overpass result:", data)
|
||||
loadingData = false
|
||||
console.log(data, date)
|
||||
featuresStore.set(data.features)
|
||||
console.log("Loaded", data.features.length)
|
||||
}
|
||||
|
||||
map.addCallbackAndRunD(() => {
|
||||
// when the map is loaded: attempt to load the user given via Queryparams
|
||||
if (username.data) {
|
||||
console.log("Current username is", username.data)
|
||||
load()
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
let mode: "map" | "table" | "aggregate" = "map"
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-full h-full">
|
||||
|
||||
<div class="flex gap-x-2 items-center low-interaction p-2">
|
||||
<h1 class="flex-shrink-0">Inspect contributor</h1>
|
||||
<ValidatedInput type="string" value={username} on:submit={() => load()} />
|
||||
{#if loadingData}
|
||||
<Loading />
|
||||
{:else}
|
||||
<button class="primary" on:click={() => load()}>Load</button>
|
||||
{/if}
|
||||
<a href="./index.html" class="button">Back to index</a>
|
||||
</div>
|
||||
|
||||
<div class="flex">
|
||||
<button class:primary={mode === "map"} on:click={() => mode = "map"}>
|
||||
Map view
|
||||
</button>
|
||||
<button class:primary={mode === "table"} on:click={() => mode = "table"}>
|
||||
Table view
|
||||
</button>
|
||||
<button class:primary={mode === "aggregate"} on:click={() => mode = "aggregate"}>
|
||||
Aggregate
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if mode === "map"}
|
||||
{#if $selectedElement !== undefined}
|
||||
<!-- right modal with the selected element view -->
|
||||
<Drawer
|
||||
placement="right"
|
||||
transitionType="fly"
|
||||
activateClickOutside={false}
|
||||
backdrop={false}
|
||||
id="drawer-right"
|
||||
width="w-full md:w-6/12 lg:w-5/12 xl:w-4/12"
|
||||
rightOffset="inset-y-0 right-0"
|
||||
transitionParams={{
|
||||
x: 640,
|
||||
duration: 0,
|
||||
easing: linear,
|
||||
}}
|
||||
divClass="overflow-y-auto z-50 bg-white"
|
||||
hidden={$selectedElement === undefined}
|
||||
on:close={() => {
|
||||
selectedElement.setData(undefined)
|
||||
}}
|
||||
>
|
||||
|
||||
<TitledPanel>
|
||||
<div slot="title" class="flex justify-between">
|
||||
|
||||
<a target="_blank" rel="noopener"
|
||||
href={"https://osm.org/"+$selectedElement.properties.id}>{$selectedElement.properties.id}</a>
|
||||
<XCircleIcon class="w-6 h-6" on:click={() => selectedElement.set(undefined)} />
|
||||
</div>
|
||||
|
||||
<History onlyShowChangesBy={$username} id={$selectedElement.properties.id}></History>
|
||||
</TitledPanel>
|
||||
</Drawer>
|
||||
{/if}
|
||||
|
||||
<div class="flex-grow overflow-hidden m-1 rounded-xl">
|
||||
<MaplibreMap map={map} mapProperties={maplibremap} autorecovery={true} />
|
||||
</div>
|
||||
{:else if mode === "table"}
|
||||
{#each $featuresStore as f}
|
||||
<h3><a href={"https://osm.org/"+f.properties.id} target="_blank">{f.properties.id}</a></h3>
|
||||
<History onlyShowChangesBy={$username} id={f.properties.id} />
|
||||
{/each}
|
||||
{:else}
|
||||
<AggregateView features={$featuresStore} onlyShowUsername={$username}></AggregateView>
|
||||
{/if}
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue