forked from MapComplete/MapComplete
More work on inspector
This commit is contained in:
parent
552ea22275
commit
951bd3c0ae
9 changed files with 257 additions and 108 deletions
|
@ -3077,6 +3077,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "name",
|
||||||
|
"question":{
|
||||||
|
"en": "What is the name of this place?"
|
||||||
|
},
|
||||||
|
"render": {
|
||||||
|
"*": "<b>{name}</b>"
|
||||||
|
},
|
||||||
|
"freeform": {
|
||||||
|
"key": "name"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"allowMove": false
|
"allowMove": false
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Panoramax_bw from "../../assets/svg/Panoramax_bw.svelte"
|
||||||
import Link from "../../UI/Base/Link"
|
import Link from "../../UI/Base/Link"
|
||||||
|
|
||||||
export default class PanoramaxImageProvider extends ImageProvider {
|
export default class PanoramaxImageProvider extends ImageProvider {
|
||||||
public static readonly singleton = new PanoramaxImageProvider()
|
public static readonly singleton: PanoramaxImageProvider = new PanoramaxImageProvider()
|
||||||
private static readonly xyz = new PanoramaxXYZ()
|
private static readonly xyz = new PanoramaxXYZ()
|
||||||
private static defaultPanoramax = new AuthorizedPanoramax(
|
private static defaultPanoramax = new AuthorizedPanoramax(
|
||||||
Constants.panoramax.url,
|
Constants.panoramax.url,
|
||||||
|
@ -126,7 +126,11 @@ export default class PanoramaxImageProvider extends ImageProvider {
|
||||||
if (!Panoramax.isId(value)) {
|
if (!Panoramax.isId(value)) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return [await this.getInfoFor(value).then((r) => this.featureToImage(<any>r))]
|
return [await this.getInfo(value)]
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getInfo(hash: string): Promise<ProvidedImage> {
|
||||||
|
return await this.getInfoFor(hash).then((r) => this.featureToImage(<any>r))
|
||||||
}
|
}
|
||||||
|
|
||||||
getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> {
|
getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> {
|
||||||
|
|
43
src/UI/History/AggregateImages.svelte
Normal file
43
src/UI/History/AggregateImages.svelte
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
|
import { HistoryUtils } from "./HistoryUtils"
|
||||||
|
import type { Feature } from "geojson"
|
||||||
|
import OsmObjectDownloader from "../../Logic/Osm/OsmObjectDownloader"
|
||||||
|
import { OsmObject } from "../../Logic/Osm/OsmObject"
|
||||||
|
import Loading from "../Base/Loading.svelte"
|
||||||
|
import AttributedImage from "../Image/AttributedImage.svelte"
|
||||||
|
import AttributedPanoramaxImage from "./AttributedPanoramaxImage.svelte"
|
||||||
|
import History from "./History.svelte"
|
||||||
|
|
||||||
|
export let onlyShowUsername: string
|
||||||
|
export let features: Feature[]
|
||||||
|
|
||||||
|
const downloader = new OsmObjectDownloader()
|
||||||
|
let allHistories: UIEventSource<OsmObject[][]> = UIEventSource.FromPromise(
|
||||||
|
Promise.all(features.map(f => downloader.downloadHistory(f.properties.id)))
|
||||||
|
)
|
||||||
|
let imageKeys = new Set(...["panoramax", "image:streetsign", "image:menu"].map(k => {
|
||||||
|
const result: string[] = [k]
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
result.push(k + ":" + i)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}))
|
||||||
|
let allDiffs: Store<{
|
||||||
|
key: string;
|
||||||
|
value?: string;
|
||||||
|
oldValue?: string
|
||||||
|
}[]> = allHistories.mapD(histories => HistoryUtils.fullHistoryDiff(histories, onlyShowUsername))
|
||||||
|
|
||||||
|
let addedImages = allDiffs.mapD(diffs => [].concat(...diffs.filter(({ key }) => imageKeys.has(key))))
|
||||||
|
|
||||||
|
</script>
|
||||||
|
{#if $allDiffs === undefined}
|
||||||
|
<Loading />
|
||||||
|
{:else if $addedImages.length === 0}
|
||||||
|
No images added by this contributor
|
||||||
|
{:else}
|
||||||
|
{#each $addedImages as imgDiff}
|
||||||
|
<AttributedPanoramaxImage hash={imgDiff.value} />
|
||||||
|
{/each}
|
||||||
|
{/if}
|
|
@ -5,6 +5,11 @@
|
||||||
import { OsmObject } from "../../Logic/Osm/OsmObject"
|
import { OsmObject } from "../../Logic/Osm/OsmObject"
|
||||||
import Loading from "../Base/Loading.svelte"
|
import Loading from "../Base/Loading.svelte"
|
||||||
import { HistoryUtils } from "./HistoryUtils"
|
import { HistoryUtils } from "./HistoryUtils"
|
||||||
|
import * as shared_questions from "../../assets/generated/layers/questions.json"
|
||||||
|
import TagRenderingQuestion from "../Popup/TagRendering/TagRenderingQuestion.svelte"
|
||||||
|
import TagRenderingConfig from "../../Models/ThemeConfig/TagRenderingConfig"
|
||||||
|
import Tr from "../Base/Tr.svelte"
|
||||||
|
import AccordionSingle from "../Flowbite/AccordionSingle.svelte"
|
||||||
|
|
||||||
export let onlyShowUsername: string
|
export let onlyShowUsername: string
|
||||||
export let features: Feature[]
|
export let features: Feature[]
|
||||||
|
@ -13,26 +18,28 @@
|
||||||
let allHistories: UIEventSource<OsmObject[][]> = UIEventSource.FromPromise(
|
let allHistories: UIEventSource<OsmObject[][]> = UIEventSource.FromPromise(
|
||||||
Promise.all(features.map(f => downloader.downloadHistory(f.properties.id)))
|
Promise.all(features.map(f => downloader.downloadHistory(f.properties.id)))
|
||||||
)
|
)
|
||||||
let allDiffs: Store<{ key: string; value?: string; oldValue?: string }[]> = allHistories.mapD(histories => {
|
let allDiffs: Store<{
|
||||||
const allDiffs = [].concat(...histories.map(
|
|
||||||
history => {
|
|
||||||
const filtered = history.filter(step => !onlyShowUsername || step.tags["_last_edit:contributor"] === onlyShowUsername)
|
|
||||||
const diffs: {
|
|
||||||
key: string;
|
key: string;
|
||||||
value?: string;
|
value?: string;
|
||||||
oldValue?: string
|
oldValue?: string
|
||||||
}[][] = filtered.map(step => HistoryUtils.tagHistoryDiff(step, history))
|
}[]> = allHistories.mapD(histories => HistoryUtils.fullHistoryDiff(histories, onlyShowUsername))
|
||||||
return [].concat(...diffs)
|
|
||||||
}
|
|
||||||
))
|
|
||||||
return allDiffs
|
|
||||||
})
|
|
||||||
|
|
||||||
const mergedCount = allDiffs.mapD(allDiffs => {
|
const trs = shared_questions.tagRenderings.map(tr => new TagRenderingConfig(tr))
|
||||||
|
|
||||||
|
function detectQuestion(key: string): TagRenderingConfig {
|
||||||
|
return trs.find(tr => tr.freeform?.key === key)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedCount: Store<{
|
||||||
|
key: string;
|
||||||
|
tr: TagRenderingConfig;
|
||||||
|
count: number;
|
||||||
|
values: { value: string; count: number }[]
|
||||||
|
}[]> = allDiffs.mapD(allDiffs => {
|
||||||
const keyCounts = new Map<string, Map<string, number>>()
|
const keyCounts = new Map<string, Map<string, number>>()
|
||||||
for (const diff of allDiffs) {
|
for (const diff of allDiffs) {
|
||||||
const k = diff.key
|
const k = diff.key
|
||||||
if(!keyCounts.has(k)){
|
if (!keyCounts.has(k)) {
|
||||||
keyCounts.set(k, new Map<string, number>())
|
keyCounts.set(k, new Map<string, number>())
|
||||||
}
|
}
|
||||||
const valueCounts = keyCounts.get(k)
|
const valueCounts = keyCounts.get(k)
|
||||||
|
@ -40,34 +47,57 @@
|
||||||
valueCounts.set(v, 1 + (valueCounts.get(v) ?? 0))
|
valueCounts.set(v, 1 + (valueCounts.get(v) ?? 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
const perKey: {key: string, count: number, values:
|
const perKey: {
|
||||||
{value: string, count: number}[]
|
key: string, tr: TagRenderingConfig, count: number, values:
|
||||||
|
{ value: string, count: number }[]
|
||||||
}[] = []
|
}[] = []
|
||||||
keyCounts.forEach((values, key) => {
|
keyCounts.forEach((values, key) => {
|
||||||
const keyTotal : {value: string, count: number}[] = []
|
const keyTotal: { value: string, count: number }[] = []
|
||||||
values.forEach((count, value) => {
|
values.forEach((count, value) => {
|
||||||
keyTotal.push({value, count})
|
keyTotal.push({ value, count })
|
||||||
})
|
})
|
||||||
let countForKey = 0
|
let countForKey = 0
|
||||||
for (const {count} of keyTotal) {
|
for (const { count } of keyTotal) {
|
||||||
countForKey += count
|
countForKey += count
|
||||||
}
|
}
|
||||||
keyTotal.sort((a, b) => b.count - a.count)
|
keyTotal.sort((a, b) => b.count - a.count)
|
||||||
perKey.push({count: countForKey, key, values: keyTotal})
|
const tr = detectQuestion(key)
|
||||||
|
perKey.push({ count: countForKey, tr, key, values: keyTotal })
|
||||||
})
|
})
|
||||||
perKey.sort((a, b) => b.count - a.count)
|
perKey.sort((a, b) => b.count - a.count)
|
||||||
|
|
||||||
return perKey
|
return perKey
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if allHistories === undefined}
|
{#if allHistories === undefined}
|
||||||
<Loading />
|
<Loading />
|
||||||
{:else if $allDiffs !== undefined}
|
{:else if $allDiffs !== undefined}
|
||||||
{#each $mergedCount as diff}
|
{#each $mergedCount as diff}
|
||||||
<div class="m-1 border-black border p-1">
|
<h3>
|
||||||
{JSON.stringify(diff)}
|
{#if diff.tr}
|
||||||
</div>
|
<Tr t={diff.tr.question} />
|
||||||
|
{:else}
|
||||||
|
{diff.key}
|
||||||
|
{/if}
|
||||||
|
</h3>
|
||||||
|
<AccordionSingle>
|
||||||
|
<span slot="header">
|
||||||
|
|
||||||
|
Answered {diff.count} times
|
||||||
|
</span>
|
||||||
|
<ul>
|
||||||
|
{#each diff.values as value}
|
||||||
|
<li>
|
||||||
|
<b>{value.value}</b>
|
||||||
|
{#if value.count > 1}
|
||||||
|
- {value.count}
|
||||||
|
{/if}
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</AccordionSingle>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
13
src/UI/History/AttributedPanoramaxImage.svelte
Normal file
13
src/UI/History/AttributedPanoramaxImage.svelte
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import AttributedImage from "../Image/AttributedImage.svelte"
|
||||||
|
import PanoramaxImageProvider from "../../Logic/ImageProviders/Panoramax"
|
||||||
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||||
|
import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider"
|
||||||
|
|
||||||
|
export let hash: string
|
||||||
|
let image: UIEventSource<ProvidedImage> = UIEventSource.FromPromise(PanoramaxImageProvider.singleton.getInfo(hash))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $image !== undefined}
|
||||||
|
<AttributedImage image={$image}></AttributedImage>
|
||||||
|
{/if}
|
|
@ -8,7 +8,6 @@
|
||||||
import Loading from "../Base/Loading.svelte"
|
import Loading from "../Base/Loading.svelte"
|
||||||
import { HistoryUtils } from "./HistoryUtils"
|
import { HistoryUtils } from "./HistoryUtils"
|
||||||
import ToSvelte from "../Base/ToSvelte.svelte"
|
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
|
||||||
import Tr from "../Base/Tr.svelte"
|
import Tr from "../Base/Tr.svelte"
|
||||||
|
|
||||||
export let onlyShowChangesBy: string
|
export let onlyShowChangesBy: string
|
||||||
|
@ -28,29 +27,36 @@
|
||||||
console.log("Comparing ", step.tags["_last_edit:contributor"], onlyShowChangesBy, step.tags["_last_edit:contributor"] === onlyShowChangesBy)
|
console.log("Comparing ", step.tags["_last_edit:contributor"], onlyShowChangesBy, step.tags["_last_edit:contributor"] === onlyShowChangesBy)
|
||||||
return step.tags["_last_edit:contributor"] === onlyShowChangesBy
|
return step.tags["_last_edit:contributor"] === onlyShowChangesBy
|
||||||
|
|
||||||
|
}).map(({ step, layer }) => {
|
||||||
|
const diff = HistoryUtils.tagHistoryDiff(step, fullHistory.data)
|
||||||
|
return { step, layer, diff }
|
||||||
}))
|
}))
|
||||||
|
|
||||||
let lastStep = filteredHistory.mapD(history => history.at(-1))
|
let lastStep = filteredHistory.mapD(history => history.at(-1))
|
||||||
let l : LayerConfig
|
let allGeometry = filteredHistory.mapD(all => !all.some(x => x.diff.length > 0))
|
||||||
// l.title.GetRenderValue({}).Subs({})
|
/**
|
||||||
|
* These layers are only shown if there are tag changes as well
|
||||||
|
*/
|
||||||
|
const ignoreLayersIfNoChanges: ReadonlySet<string> = new Set(["walls_and_buildings"])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $lastStep?.layer}
|
{#if !$allGeometry || !ignoreLayersIfNoChanges.has($lastStep?.layer?.id)}
|
||||||
|
{#if $lastStep?.layer}
|
||||||
<a href={"https://openstreetmap.org/" + $lastStep.step.tags.id} target="_blank">
|
<a href={"https://openstreetmap.org/" + $lastStep.step.tags.id} target="_blank">
|
||||||
<h3 class="flex items-center gap-x-2">
|
<h3 class="flex items-center gap-x-2">
|
||||||
<div class="w-8 h-8 shrink-0 inline-block">
|
<div class="w-8 h-8 shrink-0 inline-block">
|
||||||
<ToSvelte construct={$lastStep.layer?.defaultIcon($lastStep.step.tags)} />
|
<ToSvelte construct={$lastStep.layer?.defaultIcon($lastStep.step.tags)} />
|
||||||
</div>
|
</div>
|
||||||
<Tr t={$lastStep.layer?.title?.GetRenderValue($lastStep.step.tags)?.Subs($lastStep.step.tags)}/>
|
<Tr t={$lastStep.layer?.title?.GetRenderValue($lastStep.step.tags)?.Subs($lastStep.step.tags)} />
|
||||||
</h3>
|
</h3>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !$filteredHistory}
|
{#if !$filteredHistory}
|
||||||
<Loading>Loading history...</Loading>
|
<Loading>Loading history...</Loading>
|
||||||
{:else if $filteredHistory.length === 0}
|
{:else if $filteredHistory.length === 0}
|
||||||
Only geometry changes found
|
Only geometry changes found
|
||||||
{:else}
|
{:else}
|
||||||
<table class="w-full m-1">
|
<table class="w-full m-1">
|
||||||
{#each $filteredHistory as { step, layer }}
|
{#each $filteredHistory as { step, layer }}
|
||||||
|
|
||||||
|
@ -92,4 +98,5 @@ let l : LayerConfig
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</table>
|
</table>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { OsmObject } from "../../Logic/Osm/OsmObject"
|
||||||
|
|
||||||
export class HistoryUtils {
|
export class HistoryUtils {
|
||||||
|
|
||||||
private static personalTheme = new ThemeConfig(<any> all_layers, true)
|
public static readonly personalTheme = new ThemeConfig(<any> all_layers, true)
|
||||||
private static ignoredLayers = new Set<string>(["fixme"])
|
private static ignoredLayers = new Set<string>(["fixme"])
|
||||||
public static determineLayer(properties: Record<string, string>){
|
public static determineLayer(properties: Record<string, string>){
|
||||||
return this.personalTheme.getMatchingLayer(properties, this.ignoredLayers)
|
return this.personalTheme.getMatchingLayer(properties, this.ignoredLayers)
|
||||||
|
@ -13,12 +13,13 @@ export class HistoryUtils {
|
||||||
public static tagHistoryDiff(step: OsmObject, history: OsmObject[]): {
|
public static tagHistoryDiff(step: OsmObject, history: OsmObject[]): {
|
||||||
key: string,
|
key: string,
|
||||||
value?: string,
|
value?: string,
|
||||||
oldValue?: string
|
oldValue?: string,
|
||||||
|
step: OsmObject
|
||||||
}[] {
|
}[] {
|
||||||
const previous = history[step.version - 2]
|
const previous = history[step.version - 2]
|
||||||
if (!previous) {
|
if (!previous) {
|
||||||
return Object.keys(step.tags).filter(key => !key.startsWith("_") && key !== "id").map(key => ({
|
return Object.keys(step.tags).filter(key => !key.startsWith("_") && key !== "id").map(key => ({
|
||||||
key, value: step.tags[key]
|
key, value: step.tags[key], step
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
const previousTags = previous.tags
|
const previousTags = previous.tags
|
||||||
|
@ -27,9 +28,24 @@ export class HistoryUtils {
|
||||||
const value = step.tags[key]
|
const value = step.tags[key]
|
||||||
const oldValue = previousTags[key]
|
const oldValue = previousTags[key]
|
||||||
return {
|
return {
|
||||||
key, value, oldValue
|
key, value, oldValue, step
|
||||||
}
|
}
|
||||||
}).filter(ch => ch.oldValue !== ch.value)
|
}).filter(ch => ch.oldValue !== ch.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static fullHistoryDiff(histories: OsmObject[][], onlyShowUsername?: string){
|
||||||
|
const allDiffs: {key: string, oldValue?: string, value?: string}[] = [].concat(...histories.map(
|
||||||
|
history => {
|
||||||
|
const filtered = history.filter(step => !onlyShowUsername || step.tags["_last_edit:contributor"] === onlyShowUsername)
|
||||||
|
const diffs: {
|
||||||
|
key: string;
|
||||||
|
value?: string;
|
||||||
|
oldValue?: string
|
||||||
|
}[][] = filtered.map(step => HistoryUtils.tagHistoryDiff(step, history))
|
||||||
|
return [].concat(...diffs)
|
||||||
|
}
|
||||||
|
))
|
||||||
|
return allDiffs
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,22 +28,24 @@
|
||||||
export let imgClass: string = undefined
|
export let imgClass: string = undefined
|
||||||
export let state: SpecialVisualizationState = undefined
|
export let state: SpecialVisualizationState = undefined
|
||||||
export let attributionFormat: "minimal" | "medium" | "large" = "medium"
|
export let attributionFormat: "minimal" | "medium" | "large" = "medium"
|
||||||
export let previewedImage: UIEventSource<ProvidedImage>
|
export let previewedImage: UIEventSource<ProvidedImage> = undefined
|
||||||
export let canZoom = previewedImage !== undefined
|
export let canZoom = previewedImage !== undefined
|
||||||
let loaded = false
|
let loaded = false
|
||||||
let showBigPreview = new UIEventSource(false)
|
let showBigPreview = new UIEventSource(false)
|
||||||
onDestroy(
|
onDestroy(
|
||||||
showBigPreview.addCallbackAndRun((shown) => {
|
showBigPreview.addCallbackAndRun((shown) => {
|
||||||
if (!shown) {
|
if (!shown) {
|
||||||
previewedImage.set(undefined)
|
previewedImage?.set(undefined)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
if(previewedImage){
|
||||||
onDestroy(
|
onDestroy(
|
||||||
previewedImage.addCallbackAndRun((previewedImage) => {
|
previewedImage.addCallbackAndRun((previewedImage) => {
|
||||||
showBigPreview.set(previewedImage?.id === image.id)
|
showBigPreview.set(previewedImage?.id === image.id)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function highlight(entered: boolean = true) {
|
function highlight(entered: boolean = true) {
|
||||||
if (!entered) {
|
if (!entered) {
|
||||||
|
@ -82,7 +84,7 @@
|
||||||
class="normal-background"
|
class="normal-background"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
console.log("Closing")
|
console.log("Closing")
|
||||||
previewedImage.set(undefined)
|
previewedImage?.set(undefined)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -124,7 +126,7 @@
|
||||||
{#if canZoom && loaded}
|
{#if canZoom && loaded}
|
||||||
<div
|
<div
|
||||||
class="bg-black-transparent absolute right-0 top-0 rounded-bl-full"
|
class="bg-black-transparent absolute right-0 top-0 rounded-bl-full"
|
||||||
on:click={() => previewedImage.set(image)}
|
on:click={() => previewedImage?.set(image)}
|
||||||
>
|
>
|
||||||
<MagnifyingGlassPlusIcon class="h-8 w-8 cursor-zoom-in pl-3 pb-3" color="white" />
|
<MagnifyingGlassPlusIcon class="h-8 w-8 cursor-zoom-in pl-3 pb-3" color="white" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
|
import { XCircleIcon } from "@babeard/svelte-heroicons/solid"
|
||||||
import { Utils } from "../Utils"
|
import { Utils } from "../Utils"
|
||||||
import AggregateView from "./History/AggregateView.svelte"
|
import AggregateView from "./History/AggregateView.svelte"
|
||||||
|
import { HistoryUtils } from "./History/HistoryUtils"
|
||||||
|
import AggregateImages from "./History/AggregateImages.svelte"
|
||||||
|
|
||||||
let username = QueryParameters.GetQueryParameter("user", undefined, "Inspect this user")
|
let username = QueryParameters.GetQueryParameter("user", undefined, "Inspect this user")
|
||||||
let step = new UIEventSource<"waiting" | "loading" | "done">("waiting")
|
let step = new UIEventSource<"waiting" | "loading" | "done">("waiting")
|
||||||
|
@ -49,7 +51,17 @@
|
||||||
|
|
||||||
let featuresStore = new UIEventSource<Feature[]>([])
|
let featuresStore = new UIEventSource<Feature[]>([])
|
||||||
let features = new StaticFeatureSource(featuresStore)
|
let features = new StaticFeatureSource(featuresStore)
|
||||||
new ShowDataLayer(map,
|
ShowDataLayer.showMultipleLayers(map, features, HistoryUtils.personalTheme.layers, {
|
||||||
|
zoomToFeatures: true,
|
||||||
|
onClick: (f: Feature) => {
|
||||||
|
selectedElement.set(undefined)
|
||||||
|
Utils.waitFor(200).then(() => {
|
||||||
|
selectedElement.set(f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/* new ShowDataLayer(map,
|
||||||
{
|
{
|
||||||
layer,
|
layer,
|
||||||
zoomToFeatures: true,
|
zoomToFeatures: true,
|
||||||
|
@ -60,7 +72,7 @@
|
||||||
selectedElement.set(f)
|
selectedElement.set(f)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})*/
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|
||||||
|
@ -87,7 +99,7 @@
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
let mode: "map" | "table" | "aggregate" = "map"
|
let mode: "map" | "table" | "aggregate" | "images" = "map"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col w-full h-full">
|
<div class="flex flex-col w-full h-full">
|
||||||
|
@ -113,6 +125,9 @@
|
||||||
<button class:primary={mode === "aggregate"} on:click={() => mode = "aggregate"}>
|
<button class:primary={mode === "aggregate"} on:click={() => mode = "aggregate"}>
|
||||||
Aggregate
|
Aggregate
|
||||||
</button>
|
</button>
|
||||||
|
<button class:primary={mode === "images"} on:click={() => mode = "images"}>
|
||||||
|
Images
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if mode === "map"}
|
{#if mode === "map"}
|
||||||
|
@ -155,11 +170,18 @@
|
||||||
<MaplibreMap map={map} mapProperties={maplibremap} autorecovery={true} />
|
<MaplibreMap map={map} mapProperties={maplibremap} autorecovery={true} />
|
||||||
</div>
|
</div>
|
||||||
{:else if mode === "table"}
|
{:else if mode === "table"}
|
||||||
|
<div class="m-2 h-full overflow-y-auto">
|
||||||
{#each $featuresStore as f}
|
{#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} />
|
<History onlyShowChangesBy={$username} id={f.properties.id} />
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
</div>
|
||||||
<AggregateView features={$featuresStore} onlyShowUsername={$username}></AggregateView>
|
{:else if mode === "aggregate"}
|
||||||
|
<div class="m-2 h-full overflow-y-auto">
|
||||||
|
<AggregateView features={$featuresStore} onlyShowUsername={$username} />
|
||||||
|
</div>
|
||||||
|
{:else if mode === "images"}
|
||||||
|
<div class="m-2 h-full overflow-y-auto">
|
||||||
|
<AggregateImages features={$featuresStore} onlyShowUsername={$username} />
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue