UX: add progress bar to panoramax upload, fix hanging upload in case of multiple selected images, rm old log statements

This commit is contained in:
Pieter Vander Vennet 2025-05-08 11:28:00 +02:00
parent 767bd18234
commit e33d448055
8 changed files with 35 additions and 22 deletions

8
package-lock.json generated
View file

@ -72,7 +72,7 @@
"osm-auth": "^2.6.0",
"osmtogeojson": "^3.0.0-beta.5",
"pannellum": "^2.5.6",
"panoramax-js": "^0.5.5",
"panoramax-js": "^0.6.1",
"panzoom": "^9.4.3",
"papaparse": "^5.5.2",
"pg": "^8.11.3",
@ -22012,9 +22012,9 @@
"license": "MIT"
},
"node_modules/panoramax-js": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.5.5.tgz",
"integrity": "sha512-gIGeBFszIvtW2DhOHHQ9FtTzwkOv8MEBY2Lu9n+QxbGOlkiCbUpfA7afcv6XEbbEJ4HM8ffAVpcZgHLJFIFkvQ==",
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.6.1.tgz",
"integrity": "sha512-aPs+HIkidTBzgNBVoqOKoCB4ksMtC4U86D7DL8dJLTBMlYM/qgbxNlpNTB5f7B2brU1KUKNJDHX8dlva+xHl9w==",
"license": "GPL-3.0-or-later",
"dependencies": {
"@ogcapi-js/features": "^1.1.1",

View file

@ -235,7 +235,7 @@
"osm-auth": "^2.6.0",
"osmtogeojson": "^3.0.0-beta.5",
"pannellum": "^2.5.6",
"panoramax-js": "^0.5.5",
"panoramax-js": "^0.6.1",
"panzoom": "^9.4.3",
"papaparse": "^5.5.2",
"pg": "^8.11.3",

View file

@ -166,8 +166,9 @@ export class ImageUploadManager {
console.log("Checking image upload queue and uploading if needed")
this.uploadingAll = true
try {
for (const imageToUpload of queue) {
await this.handleQueueItem(imageToUpload)
while (queue.length > 0) {
const currentItem = queue[0]
await this.handleQueueItem(currentItem)
}
} catch (e) {
console.error("Error while handling the queue:", e)
@ -183,10 +184,12 @@ export class ImageUploadManager {
* - indicates that the upload is busy
* - Applies the action to the correct element
* - indicates failure
*
* Modifies the queue: if the upload is successfull, deletes the item from the queue
* @private
*/
private async handleQueueItem(args: ImageUploadArguments): Promise<void> {
console.log("Handling queue item", args)
console.log("Handling queue item", args.blob.name, args)
if (!args) {
return
}
@ -197,18 +200,22 @@ export class ImageUploadManager {
while (attempts > 0 && result === undefined) {
attempts--
const doReport = attempts == 0
result = await this.attemptSingleUpload(args, doReport)
try {
result = await this.attemptSingleUpload(args, doReport)
} catch (e) {
console.error("Uploading failed with error", e)
}
if (!result) {
console.log("Upload attempt failed, attempts left:", attempts)
}
}
this._isUploading.set(undefined)
this._fails.set(this._fails.data.filter((a) => a !== args))
if (result === undefined) {
this._fails.data.push(args)
this._fails.ping()
return
}
this._fails.set(this._fails.data.filter((a) => a !== args))
let properties: UIEventSource<Record<string, string>> = this._featureProperties.getStore(
args.featureId
)

View file

@ -11,7 +11,7 @@ export interface ImageUploader {
currentGps: [number, number],
author: string,
noblur: boolean,
progress?: UIEventSource<number>
progress?: UIEventSource<number | undefined>
): Promise<UploadResult>
}

View file

@ -11,6 +11,7 @@ import SvelteUIElement from "../../UI/Base/SvelteUIElement"
import Panoramax_bw from "../../assets/svg/Panoramax_bw.svelte"
import Link from "../../UI/Base/Link"
import { Feature, Point } from "geojson"
import { AddImageOptions } from "panoramax-js/dist/Panoramax"
export default class PanoramaxImageProvider extends ImageProvider {
public static readonly singleton: PanoramaxImageProvider = new PanoramaxImageProvider()
@ -166,7 +167,6 @@ export default class PanoramaxImageProvider extends ImageProvider {
getRelevantUrls(tags: Record<string, string>, prefixes: string[]): Store<ProvidedImage[]> {
const source = UIEventSource.FromPromise(super.getRelevantUrlsFor(tags, prefixes))
console.trace("Getting relevant URLS for panoramax yielded", source.data)
function hasLoading(data: ProvidedImage[]) {
if (data === undefined) {
return true
@ -252,7 +252,7 @@ export class PanoramaxUploader implements ImageUploader {
currentGps: [number, number],
author: string,
noblur: boolean = false,
progress?: UIEventSource<number>,
progress?: UIEventSource<number | undefined>,
sequenceId?: string,
datetime?: string
): Promise<{
@ -320,12 +320,13 @@ export class PanoramaxUploader implements ImageUploader {
const sequence: { id: string; "stats:items": { count: number } } = (
await p.mySequences()
).find((s) => s.id === sequenceId)
const options = {
const options: AddImageOptions = {
lon,
lat,
datetime,
isBlurred: noblur,
onProgress: undefined,
indexInSequence: sequence["stats:items"].count + 1, // stats:items is '1'-indexed, so .count is also the last index
exifOverride: {
Artist: author,
},
@ -337,9 +338,11 @@ export class PanoramaxUploader implements ImageUploader {
progress.set(Math.round(percentage))
}
}
progress.set(0)
}
const img = <ImageData>await p.addImage(blob, sequence, options)
const img = <ImageData>await p.addImage(blob, sequenceId, options)
PanoramaxImageProvider.singleton.addKnownMeta(img)
progress.set(undefined)
return {
key: "panoramax",
value: img.id,

View file

@ -105,7 +105,7 @@ export default class ThemeViewStateHashActor {
if (found.properties.id.startsWith("last_click")) {
return true
}
console.log("Setting selected element based on hash", hash, "; found", found)
console.log("Setting selected element based on hash", hash, "; found", found, "current:", selectedElement.data?.properties?.id)
selectedElement.setData(found)
return true
}

View file

@ -38,7 +38,6 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
// Add the selected element to the recently visited history
this.selectedElement.addCallbackD((selected) => {
console.trace("Selected element is", selected)
const [osm_type, osm_id] = selected.properties.id.split("/")
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
const layer = this.theme.getMatchingLayer(selected.properties)

View file

@ -56,17 +56,21 @@
<Loading>
<div class="w-full flex flex-col">
<div class="w-full flex justify-between">
<div class="w-full flex justify-between gap-x-8">
{#if $pending - $failed === 1}
<Tr t={t.upload.one.uploading} />
{:else if $pending - $failed > 1}
<Tr t={t.upload.multiple.uploading.Subs({ count: $pending })} />
{/if}
{$progress}%
</div>
<div class="w-full low-interaction h-1">
<div class="bg-black h-1" style={`width: calc(${$progress}%)`}></div>
{#if $progress !== undefined}
{$progress}%
{/if}
</div>
{#if $progress !== undefined}
<div class="w-full low-interaction h-1 rounded-full overflow-hidden">
<div class="bg-black h-1" style={`width: calc(${$progress}%)`}></div>
</div>
{/if}
</div>
</Loading>
</div>