chore: automated housekeeping...

This commit is contained in:
Pieter Vander Vennet 2024-12-11 02:45:44 +01:00
parent a178de3e03
commit bb6b053429
131 changed files with 7447 additions and 5143 deletions

View file

@ -28,9 +28,9 @@
(s) =>
(s === "yes" &&
state?.userRelatedState?.osmConnection?.userDetails?.data?.csCount >=
Constants.userJourney.tagsVisibleAt) ||
Constants.userJourney.tagsVisibleAt) ||
s === "always" ||
s === "full",
s === "full"
)
/**
@ -80,9 +80,9 @@
<Checkbox selected={getBooleanStateFor(filter)}>
<Tr t={filter.options[0].question} />
{#if $showTags && filter.options[0].osmTags !== undefined}
<span class="subtle">
{filter.options[0].osmTags.asHumanString()}
</span>
<span class="subtle">
{filter.options[0].osmTags.asHumanString()}
</span>
{/if}
</Checkbox>
{/if}

View file

@ -12,25 +12,31 @@
const downloader = new OsmObjectDownloader()
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 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 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 usernamesSet = new Set(onlyShowUsername)
let allDiffs: Store<{
key: string;
value?: string;
oldValue?: string
}[]> = allHistories.mapD(histories => HistoryUtils.fullHistoryDiff(histories, usernamesSet))
let addedImages = allDiffs.mapD(diffs => [].concat(...diffs.filter(({ key }) => imageKeys.has(key))))
let allDiffs: Store<
{
key: string
value?: string
oldValue?: string
}[]
> = allHistories.mapD((histories) => HistoryUtils.fullHistoryDiff(histories, usernamesSet))
let addedImages = allDiffs.mapD((diffs) =>
[].concat(...diffs.filter(({ key }) => imageKeys.has(key)))
)
</script>
{#if $allDiffs === undefined}
<Loading />
{:else if $addedImages.length === 0}
@ -38,7 +44,7 @@
{:else}
<div class="flex">
{#each $addedImages as imgDiff}
<div class="w-48 h-48">
<div class="h-48 w-48">
<AttributedPanoramaxImage hash={imgDiff.value} />
</div>
{/each}

View file

@ -18,26 +18,30 @@
const downloader = new OsmObjectDownloader()
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 => HistoryUtils.fullHistoryDiff(histories, usernames))
let allDiffs: Store<
{
key: string
value?: string
oldValue?: string
}[]
> = allHistories.mapD((histories) => HistoryUtils.fullHistoryDiff(histories, usernames))
const trs = shared_questions.tagRenderings.map(tr => new TagRenderingConfig(tr))
const trs = shared_questions.tagRenderings.map((tr) => new TagRenderingConfig(tr))
function detectQuestion(key: string): TagRenderingConfig {
return trs.find(tr => tr.freeform?.key === key)
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 mergedCount: Store<
{
key: string
tr: TagRenderingConfig
count: number
values: { value: string; count: number }[]
}[]
> = allDiffs.mapD((allDiffs) => {
const keyCounts = new Map<string, Map<string, number>>()
for (const diff of allDiffs) {
const k = diff.key
@ -50,11 +54,13 @@
}
const perKey: {
key: string, tr: TagRenderingConfig, count: number, values:
{ value: string, count: number }[]
key: string
tr: TagRenderingConfig
count: number
values: { value: string; count: number }[]
}[] = []
keyCounts.forEach((values, key) => {
const keyTotal: { value: string, count: number }[] = []
const keyTotal: { value: string; count: number }[] = []
values.forEach((count, value) => {
keyTotal.push({ value, count })
})
@ -72,7 +78,6 @@
})
const t = Translations.t.inspector
</script>
{#if allHistories === undefined}
@ -88,7 +93,7 @@
</h3>
<AccordionSingle>
<span slot="header">
<Tr t={t.answeredCountTimes.Subs(diff)} />
<Tr t={t.answeredCountTimes.Subs(diff)} />
</span>
<ul>
{#each diff.values as value}

View file

@ -5,9 +5,11 @@
import type { ProvidedImage } from "../../Logic/ImageProviders/ImageProvider"
export let hash: string
let image: UIEventSource<ProvidedImage> = UIEventSource.FromPromise(PanoramaxImageProvider.singleton.getInfo(hash))
let image: UIEventSource<ProvidedImage> = UIEventSource.FromPromise(
PanoramaxImageProvider.singleton.getInfo(hash)
)
</script>
{#if $image !== undefined}
<AttributedImage image={$image}></AttributedImage>
<AttributedImage image={$image} />
{/if}

View file

@ -17,41 +17,51 @@
let usernames = new Set(onlyShowChangesBy)
let fullHistory = UIEventSource.FromPromise(new OsmObjectDownloader().downloadHistory(id))
let partOfLayer = fullHistory.mapD(history => history.map(step => ({
step,
layer: HistoryUtils.determineLayer(step.tags)
})))
let filteredHistory = partOfLayer.mapD(history =>
history.filter(({ step }) => {
if (usernames.size == 0) {
return true
}
console.log("Checking if ", step.tags["_last_edit:contributor"],"is contained in", onlyShowChangesBy)
return usernames.has(step.tags["_last_edit:contributor"])
}).map(({ step, layer }) => {
const diff = HistoryUtils.tagHistoryDiff(step, fullHistory.data)
return { step, layer, diff }
let partOfLayer = fullHistory.mapD((history) =>
history.map((step) => ({
step,
layer: HistoryUtils.determineLayer(step.tags),
}))
)
let filteredHistory = partOfLayer.mapD((history) =>
history
.filter(({ step }) => {
if (usernames.size == 0) {
return true
}
console.log(
"Checking if ",
step.tags["_last_edit:contributor"],
"is contained in",
onlyShowChangesBy
)
return usernames.has(step.tags["_last_edit:contributor"])
})
.map(({ step, layer }) => {
const diff = HistoryUtils.tagHistoryDiff(step, fullHistory.data)
return { step, layer, diff }
})
)
let lastStep = filteredHistory.mapD(history => history.at(-1))
let allGeometry = filteredHistory.mapD(all => !all.some(x => x.diff.length > 0))
let lastStep = filteredHistory.mapD((history) => history.at(-1))
let allGeometry = filteredHistory.mapD((all) => !all.some((x) => x.diff.length > 0))
/**
* These layers are only shown if there are tag changes as well
*/
const ignoreLayersIfNoChanges: ReadonlySet<string> = new Set(["walls_and_buildings"])
const t = Translations.t.inspector.previousContributors
</script>
{#if !$allGeometry || !ignoreLayersIfNoChanges.has($lastStep?.layer?.id)}
{#if $lastStep?.layer}
<a href={"https://openstreetmap.org/" + $lastStep.step.tags.id} target="_blank">
<h3 class="flex items-center gap-x-2">
<div class="w-8 h-8 shrink-0 inline-block">
<div class="inline-block h-8 w-8 shrink-0">
<ToSvelte construct={$lastStep.layer?.defaultIcon($lastStep.step.tags)} />
</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>
</a>
{/if}
@ -61,42 +71,48 @@
{:else if $filteredHistory.length === 0}
<Tr t={t.onlyGeometry} />
{:else}
<table class="w-full m-1">
<table class="m-1 w-full">
{#each $filteredHistory as { step, layer }}
{#if step.version === 1}
<tr>
<td colspan="3">
<h3>
<Tr t={t.createdBy.Subs({contributor: step.tags["_last_edit:contributor"]})} />
<Tr t={t.createdBy.Subs({ contributor: step.tags["_last_edit:contributor"] })} />
</h3>
</td>
</tr>
{/if}
{#if HistoryUtils.tagHistoryDiff(step, $fullHistory).length === 0}
<tr>
<td class="font-bold justify-center flex w-full" colspan="3">
<td class="flex w-full justify-center font-bold" colspan="3">
<Tr t={t.onlyGeometry} />
</td>
</tr>
{:else}
{#each HistoryUtils.tagHistoryDiff(step, $fullHistory) as diff}
<tr>
<td><a href={"https://osm.org/changeset/"+step.tags["_last_edit:changeset"]}
target="_blank">{step.version}</a></td>
<td>
<a
href={"https://osm.org/changeset/" + step.tags["_last_edit:changeset"]}
target="_blank"
>
{step.version}
</a>
</td>
<td>{layer?.id ?? "Unknown layer"}</td>
{#if diff.oldValue === undefined}
<td>{diff.key}</td>
<td>{diff.value}</td>
{:else if diff.value === undefined }
{:else if diff.value === undefined}
<td>{diff.key}</td>
<td class="line-through"> {diff.value}</td>
<td class="line-through">{diff.value}</td>
{:else}
<td>{diff.key}</td>
<td><span class="line-through"> {diff.oldValue}</span>{diff.value}</td>
<td>
<span class="line-through">{diff.oldValue}</span>
{diff.value}
</td>
{/if}
</tr>
{/each}
{/if}

View file

@ -3,49 +3,63 @@ import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
import { OsmObject } from "../../Logic/Osm/OsmObject"
export class HistoryUtils {
public static readonly personalTheme = new ThemeConfig(<any> all_layers, true)
public static readonly personalTheme = new ThemeConfig(<any>all_layers, true)
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)
}
public static tagHistoryDiff(step: OsmObject, history: OsmObject[]): {
key: string,
value?: string,
oldValue?: string,
public static tagHistoryDiff(
step: OsmObject,
history: OsmObject[]
): {
key: string
value?: string
oldValue?: string
step: OsmObject
}[] {
const previous = history[step.version - 2]
if (!previous) {
return Object.keys(step.tags).filter(key => !key.startsWith("_") && key !== "id").map(key => ({
key, value: step.tags[key], step
}))
return Object.keys(step.tags)
.filter((key) => !key.startsWith("_") && key !== "id")
.map((key) => ({
key,
value: step.tags[key],
step,
}))
}
const previousTags = previous.tags
return Object.keys(step.tags).filter(key => !key.startsWith("_") )
.map(key => {
return Object.keys(step.tags)
.filter((key) => !key.startsWith("_"))
.map((key) => {
const value = step.tags[key]
const oldValue = previousTags[key]
return {
key, value, oldValue, step
key,
value,
oldValue,
step,
}
}).filter(ch => ch.oldValue !== ch.value)
})
.filter((ch) => ch.oldValue !== ch.value)
}
public static fullHistoryDiff(histories: OsmObject[][], onlyShowUsername?: Set<string>){
const allDiffs: {key: string, oldValue?: string, value?: string}[] = [].concat(...histories.map(
history => {
const filtered = history.filter(step => !onlyShowUsername || onlyShowUsername?.has(step.tags["_last_edit:contributor"] ))
public static fullHistoryDiff(histories: OsmObject[][], onlyShowUsername?: Set<string>) {
const allDiffs: { key: string; oldValue?: string; value?: string }[] = [].concat(
...histories.map((history) => {
const filtered = history.filter(
(step) =>
!onlyShowUsername ||
onlyShowUsername?.has(step.tags["_last_edit:contributor"])
)
const diffs: {
key: string;
value?: string;
key: string
value?: string
oldValue?: string
}[][] = filtered.map(step => HistoryUtils.tagHistoryDiff(step, history))
}[][] = filtered.map((step) => HistoryUtils.tagHistoryDiff(step, history))
return [].concat(...diffs)
}
))
})
)
return allDiffs
}
}

View file

@ -1,5 +1,4 @@
<script lang="ts">
import { UIEventSource } from "../../Logic/UIEventSource"
import { OsmConnection } from "../../Logic/Osm/OsmConnection"
import LoginToggle from "../Base/LoginToggle.svelte"
@ -9,18 +8,23 @@
import Dropdown from "../Base/Dropdown.svelte"
export let osmConnection: OsmConnection
export let inspectedContributors: UIEventSource<{
name: string,
visitedTime: string,
label: string
}[]>
export let inspectedContributors: UIEventSource<
{
name: string
visitedTime: string
label: string
}[]
>
let dispatch = createEventDispatcher<{ selectUser: string }>()
let labels = UIEventSource.asObject<string[]>(osmConnection.getPreference("previously-spied-labels"), [])
let labels = UIEventSource.asObject<string[]>(
osmConnection.getPreference("previously-spied-labels"),
[]
)
let labelField = ""
function remove(user: string) {
inspectedContributors.set(inspectedContributors.data.filter(entry => entry.name !== user))
inspectedContributors.set(inspectedContributors.data.filter((entry) => entry.name !== user))
}
function addLabel() {
@ -39,16 +43,13 @@
}
</script>
<LoginToggle ignoreLoading state={{osmConnection}}>
<LoginToggle ignoreLoading state={{ osmConnection }}>
<table class="w-full">
<tr>
<td>
<button class="as-link cursor-pointer" on:click={() => sort("name")}>
Contributor
</button>
<button class="as-link cursor-pointer" on:click={() => sort("name")}>Contributor</button>
</td>
<td>
<button class="as-link cursor-pointer" on:click={() => sort("visitedTime")}>
Visited time
</button>
@ -75,32 +76,46 @@
</select>
</td>
<td>
<XCircleIcon class="w-6 h-6" on:click={() => remove(c.name)} />
<XCircleIcon class="h-6 w-6" on:click={() => remove(c.name)} />
</td>
</tr>
{/each}
</table>
<AccordionSingle>
<div slot="header">Labels</div>
{#if $labels.length === 0}
No labels
{:else}
{#each $labels as label}
<div class="mx-2">{label}
<button class:disabled={!$inspectedContributors.some(c => c.label === label)} on:click={() => {dispatch("selectUser",
inspectedContributors.data.filter(c =>c.label === label).map(c => c .name).join(";")
)}}>See all changes for these users
<div class="mx-2">
{label}
<button
class:disabled={!$inspectedContributors.some((c) => c.label === label)}
on:click={() => {
dispatch(
"selectUser",
inspectedContributors.data
.filter((c) => c.label === label)
.map((c) => c.name)
.join(";")
)
}}
>
See all changes for these users
</button>
</div>
{/each}
{/if}
<div class="interactive flex m-2 items-center gap-x-2 rounded-lg p-2">
<div class="interactive m-2 flex items-center gap-x-2 rounded-lg p-2">
<div class="shrink-0">Create a new label</div>
<input bind:value={labelField} type="text" />
<button on:click={() => addLabel()} class:disabled={!(labelField?.length > 0) } class="disabled shrink-0">Add
label
<button
on:click={() => addLabel()}
class:disabled={!(labelField?.length > 0)}
class="disabled shrink-0"
>
Add label
</button>
</div>
</AccordionSingle>

View file

@ -39,12 +39,12 @@
}
})
)
if(previewedImage){
onDestroy(
previewedImage.addCallbackAndRun((previewedImage) => {
showBigPreview.set(previewedImage?.id === image.id)
})
)
if (previewedImage) {
onDestroy(
previewedImage.addCallbackAndRun((previewedImage) => {
showBigPreview.set(previewedImage?.id === image.id)
})
)
}
function highlight(entered: boolean = true) {

View file

@ -59,12 +59,12 @@
type: "Feature",
geometry: {
type: "Point",
coordinates: [p4c.coordinates.lng, p4c.coordinates.lat]
coordinates: [p4c.coordinates.lng, p4c.coordinates.lat],
},
properties: {
id: p4c.pictureUrl,
rotation: p4c.direction
}
rotation: p4c.direction,
},
}
)
)
@ -76,14 +76,14 @@
type: "Feature",
geometry: {
type: "Point",
coordinates: [s.coordinates.lng, s.coordinates.lat]
coordinates: [s.coordinates.lng, s.coordinates.lat],
},
properties: {
id: s.pictureUrl,
selected: "yes",
rotation: s.direction
}
}
rotation: s.direction,
},
},
]
})
@ -108,7 +108,7 @@
rotation: state.mapProperties.rotation,
pitch: state.mapProperties.pitch,
zoom: new UIEventSource<number>(16),
location: new UIEventSource({ lon, lat })
location: new UIEventSource({ lon, lat }),
})
const geocodedImageLayer = new LayerConfig(<LayerConfigJson>geocoded_image)
@ -118,7 +118,7 @@
zoomToFeatures: true,
onClick: (feature) => {
highlighted.set(feature.properties.id)
}
},
})
ShowDataLayer.showMultipleLayers(map, new StaticFeatureSource([feature]), state.theme.layers)
@ -141,14 +141,20 @@
layer: geocodedImageLayer,
onClick: (feature) => {
highlighted.set(feature.properties.id)
}
},
})
onDestroy(tags.addCallbackAndRunD(tags => {
if (tags.id.startsWith("node/") || tags.id.startsWith("way/") || tags.id.startsWith("relation/")) {
return
}
linkable = false
}))
onDestroy(
tags.addCallbackAndRunD((tags) => {
if (
tags.id.startsWith("node/") ||
tags.id.startsWith("way/") ||
tags.id.startsWith("relation/")
) {
return
}
linkable = false
})
)
</script>
<div class="flex flex-col">

View file

@ -39,49 +39,49 @@
let maplibremap: MapLibreAdaptor = new MapLibreAdaptor(map, {
zoom,
location: new UIEventSource<{ lon: number; lat: number }>({ lat: lat.data, lon: lon.data })
location: new UIEventSource<{ lon: number; lat: number }>({ lat: lat.data, lon: lon.data }),
})
maplibremap.location.stabilized(500).addCallbackAndRunD(l => {
maplibremap.location.stabilized(500).addCallbackAndRunD((l) => {
lat.set(l.lat)
lon.set(l.lon)
})
let allLayers = HistoryUtils.personalTheme.layers
let layersNoFixme = allLayers.filter(l => l.id !== "fixme")
let fixme = allLayers.find(l => l.id === "fixme")
let layersNoFixme = allLayers.filter((l) => l.id !== "fixme")
let fixme = allLayers.find((l) => l.id === "fixme")
let featuresStore = new UIEventSource<Feature[]>([])
let features = new StaticFeatureSource(featuresStore)
ShowDataLayer.showMultipleLayers(map, features, [...layersNoFixme, fixme] , {
ShowDataLayer.showMultipleLayers(map, features, [...layersNoFixme, fixme], {
zoomToFeatures: true,
onClick: (f: Feature) => {
selectedElement.set(undefined)
Utils.waitFor(200).then(() => {
selectedElement.set(f)
})
}
},
})
let osmConnection = new OsmConnection()
let inspectedContributors: UIEventSource<{
name: string,
visitedTime: string,
label: string
}[]> = UIEventSource.asObject(
osmConnection.getPreference("spied-upon-users"), [])
let inspectedContributors: UIEventSource<
{
name: string
visitedTime: string
label: string
}[]
> = UIEventSource.asObject(osmConnection.getPreference("spied-upon-users"), [])
async function load() {
const user = username.data
if(user.indexOf(";")<0){
if (user.indexOf(";") < 0) {
const inspectedData = inspectedContributors.data
const previousEntry = inspectedData.find(e => e.name === user)
const previousEntry = inspectedData.find((e) => e.name === user)
if (previousEntry) {
previousEntry.visitedTime = new Date().toISOString()
} else {
inspectedData.push({
label: undefined,
visitedTime: new Date().toISOString(),
name: user
name: user,
})
}
inspectedContributors.ping()
@ -89,7 +89,11 @@ let fixme = allLayers.find(l => l.id === "fixme")
step.setData("loading")
featuresStore.set([])
const overpass = new Overpass(undefined, user.split(";").map(user => "nw(user_touched:\"" + user + "\");"), Constants.defaultOverpassUrls[0])
const overpass = new Overpass(
undefined,
user.split(";").map((user) => 'nw(user_touched:"' + user + '");'),
Constants.defaultOverpassUrls[0]
)
if (!maplibremap.bounds.data) {
return
}
@ -114,44 +118,43 @@ let fixme = allLayers.find(l => l.id === "fixme")
let mode: "map" | "table" | "aggregate" | "images" = "map"
let showPreviouslyVisited = new UIEventSource(true)
const t = Translations.t.inspector
const t = Translations.t.inspector
</script>
<div class="flex flex-col w-full h-full">
<div class="flex gap-x-2 items-center low-interaction p-2">
<MagnifyingGlassCircle class="w-12 h-12"/>
<h1 class="flex-shrink-0 m-0 mx-2">
<Tr t={t.title}/>
<div class="flex h-full w-full flex-col">
<div class="low-interaction flex items-center gap-x-2 p-2">
<MagnifyingGlassCircle class="h-12 w-12" />
<h1 class="m-0 mx-2 flex-shrink-0">
<Tr t={t.title} />
</h1>
<ValidatedInput type="string" value={username} on:submit={() => load()} />
{#if loadingData}
<Loading />
{:else}
<button class="primary" on:click={() => load()}>
<Tr t={t.load}/>
<Tr t={t.load} />
</button>
{/if}
<button on:click={() => showPreviouslyVisited.setData(true)}>
<Tr t={t.earlierInspected}/>
<Tr t={t.earlierInspected} />
</button>
<a href="./index.html" class="button">
<Tr t={t.backToIndex}/>
<Tr t={t.backToIndex} />
</a>
</div>
<div class="flex">
<button class:primary={mode === "map"} on:click={() => mode = "map"}>
<Tr t={t.mapView}/>
<button class:primary={mode === "map"} on:click={() => (mode = "map")}>
<Tr t={t.mapView} />
</button>
<button class:primary={mode === "table"} on:click={() => mode = "table"}>
<Tr t={t.tableView}/>
<button class:primary={mode === "table"} on:click={() => (mode = "table")}>
<Tr t={t.tableView} />
</button>
<button class:primary={mode === "aggregate"} on:click={() => mode = "aggregate"}>
<Tr t={t.aggregateView}/>
<button class:primary={mode === "aggregate"} on:click={() => (mode = "aggregate")}>
<Tr t={t.aggregateView} />
</button>
<button class:primary={mode === "images"} on:click={() => mode = "images"}>
<Tr t={t.images}/>
<button class:primary={mode === "images"} on:click={() => (mode = "images")}>
<Tr t={t.images} />
</button>
</div>
@ -167,32 +170,35 @@ const t = Translations.t.inspector
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,
}}
x: 640,
duration: 0,
easing: linear,
}}
divClass="overflow-y-auto z-50 bg-white"
hidden={$selectedElement === undefined}
on:close={() => {
selectedElement.setData(undefined)
}}
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)} />
<a
target="_blank"
rel="noopener"
href={"https://osm.org/" + $selectedElement.properties.id}
>
{$selectedElement.properties.id}
</a>
<XCircleIcon class="h-6 w-6" on:click={() => selectedElement.set(undefined)} />
</div>
<History onlyShowChangesBy={$username} id={$selectedElement.properties.id}></History>
<History onlyShowChangesBy={$username} id={$selectedElement.properties.id} />
</TitledPanel>
</Drawer>
{/if}
<div class="flex-grow overflow-hidden m-1 rounded-xl">
<MaplibreMap map={map} mapProperties={maplibremap} autorecovery={true} />
<div class="m-1 flex-grow overflow-hidden rounded-xl">
<MaplibreMap {map} mapProperties={maplibremap} autorecovery={true} />
</div>
{:else if mode === "table"}
<div class="m-2 h-full overflow-y-auto">
@ -213,7 +219,13 @@ const t = Translations.t.inspector
<Page shown={showPreviouslyVisited}>
<div slot="header">Earlier inspected constributors</div>
<PreviouslySpiedUsers {osmConnection} {inspectedContributors} on:selectUser={(e) => {
username.set(e.detail); load();showPreviouslyVisited.set(false)
}} />
<PreviouslySpiedUsers
{osmConnection}
{inspectedContributors}
on:selectUser={(e) => {
username.set(e.detail)
load()
showPreviouslyVisited.set(false)
}}
/>
</Page>

View file

@ -1,7 +1,11 @@
import { Store, UIEventSource } from "../Logic/UIEventSource"
import BaseUIElement from "./BaseUIElement"
import ThemeConfig from "../Models/ThemeConfig/ThemeConfig"
import { FeatureSource, IndexedFeatureSource, WritableFeatureSource } from "../Logic/FeatureSource/FeatureSource"
import {
FeatureSource,
IndexedFeatureSource,
WritableFeatureSource,
} from "../Logic/FeatureSource/FeatureSource"
import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { Changes } from "../Logic/Osm/Changes"
import { ExportableMap, MapProperties } from "../Models/MapProperties"

View file

@ -46,10 +46,10 @@
) {
lat = exifLat
lon = exifLon
if(tags?.GPSLatitudeRef?.value?.[0] === "S"){
if (tags?.GPSLatitudeRef?.value?.[0] === "S") {
lat *= -1
}
if(tags?.GPSLongitudeRef?.value?.[0] === "W"){
if (tags?.GPSLongitudeRef?.value?.[0] === "W") {
lon *= -1
}
l("Using EXIFLAT + EXIFLON")
@ -57,11 +57,18 @@
l("NOT using exifLat and exifLon: invalid value detected")
}
l("Lat and lon are", lat, lon)
l("ref lat is", tags?.GPSLatitudeRef?.description, JSON.stringify(tags?.GPSLatitudeRef?.value))
l("ref lon is", tags?.GPSLongitudeRef?.description, JSON.stringify(tags?.GPSLongitudeRef?.value))
l(
"ref lat is",
tags?.GPSLatitudeRef?.description,
JSON.stringify(tags?.GPSLatitudeRef?.value)
)
l(
"ref lon is",
tags?.GPSLongitudeRef?.description,
JSON.stringify(tags?.GPSLongitudeRef?.value)
)
l("Direct values are", directValueLat,directValueLon,"corrected:",lat,lon)
l("Direct values are", directValueLat, directValueLon, "corrected:", lat, lon)
l("Datetime value is", JSON.stringify(tags.DateTime))
const [date, time] = tags.DateTime.value[0].split(" ")
datetime = new Date(date.replaceAll(":", "-") + "T" + time).toISOString()