forked from MapComplete/MapComplete
UX: add progress bar for uploading images
This commit is contained in:
parent
bb33c43950
commit
221b572a1f
8 changed files with 45 additions and 18 deletions
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -72,7 +72,7 @@
|
||||||
"osm-auth": "^2.6.0",
|
"osm-auth": "^2.6.0",
|
||||||
"osmtogeojson": "^3.0.0-beta.5",
|
"osmtogeojson": "^3.0.0-beta.5",
|
||||||
"pannellum": "^2.5.6",
|
"pannellum": "^2.5.6",
|
||||||
"panoramax-js": "^0.4.12",
|
"panoramax-js": "^0.5.5",
|
||||||
"panzoom": "^9.4.3",
|
"panzoom": "^9.4.3",
|
||||||
"papaparse": "^5.5.2",
|
"papaparse": "^5.5.2",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
|
@ -22012,9 +22012,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/panoramax-js": {
|
"node_modules/panoramax-js": {
|
||||||
"version": "0.4.12",
|
"version": "0.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.4.12.tgz",
|
"resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.5.5.tgz",
|
||||||
"integrity": "sha512-BFNMGFumMmBfL7QC3IQxgWjy1nr2AWrcNcQY9n1y0UGGNLrDxv9+i6EzuZ3slgGP+qvb7tKx8mqfZaN6U/O/4g==",
|
"integrity": "sha512-gIGeBFszIvtW2DhOHHQ9FtTzwkOv8MEBY2Lu9n+QxbGOlkiCbUpfA7afcv6XEbbEJ4HM8ffAVpcZgHLJFIFkvQ==",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ogcapi-js/features": "^1.1.1",
|
"@ogcapi-js/features": "^1.1.1",
|
||||||
|
|
|
@ -235,7 +235,7 @@
|
||||||
"osm-auth": "^2.6.0",
|
"osm-auth": "^2.6.0",
|
||||||
"osmtogeojson": "^3.0.0-beta.5",
|
"osmtogeojson": "^3.0.0-beta.5",
|
||||||
"pannellum": "^2.5.6",
|
"pannellum": "^2.5.6",
|
||||||
"panoramax-js": "^0.4.12",
|
"panoramax-js": "^0.5.5",
|
||||||
"panzoom": "^9.4.3",
|
"panzoom": "^9.4.3",
|
||||||
"papaparse": "^5.5.2",
|
"papaparse": "^5.5.2",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
|
|
|
@ -57,6 +57,9 @@ export class ImageUploadManager {
|
||||||
extramessage?: string
|
extramessage?: string
|
||||||
) => Promise<void>
|
) => Promise<void>
|
||||||
|
|
||||||
|
private readonly _progressCurrentImage: UIEventSource<number> = new UIEventSource(0)
|
||||||
|
public readonly progressCurrentImage: Store<number> = this._progressCurrentImage
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
layout: ThemeConfig,
|
layout: ThemeConfig,
|
||||||
uploader: ImageUploader,
|
uploader: ImageUploader,
|
||||||
|
@ -276,11 +279,12 @@ export class ImageUploadManager {
|
||||||
let absoluteUrl: string
|
let absoluteUrl: string
|
||||||
|
|
||||||
try {
|
try {
|
||||||
;({ key, value, absoluteUrl } = await this._uploader.uploadImage(
|
({ key, value, absoluteUrl } = await this._uploader.uploadImage(
|
||||||
blob,
|
blob,
|
||||||
location,
|
location,
|
||||||
author,
|
author,
|
||||||
noblur
|
noblur,
|
||||||
|
this._progressCurrentImage
|
||||||
))
|
))
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Could again not upload image due to", e)
|
console.error("Could again not upload image due to", e)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { UIEventSource } from "../UIEventSource"
|
||||||
|
|
||||||
export interface ImageUploader {
|
export interface ImageUploader {
|
||||||
maxFileSizeInMegabytes?: number
|
maxFileSizeInMegabytes?: number
|
||||||
/**
|
/**
|
||||||
|
@ -8,7 +10,8 @@ export interface ImageUploader {
|
||||||
blob: File,
|
blob: File,
|
||||||
currentGps: [number, number],
|
currentGps: [number, number],
|
||||||
author: string,
|
author: string,
|
||||||
noblur: boolean
|
noblur: boolean,
|
||||||
|
progress?: UIEventSource<number>
|
||||||
): Promise<UploadResult>
|
): Promise<UploadResult>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -252,6 +252,7 @@ export class PanoramaxUploader implements ImageUploader {
|
||||||
currentGps: [number, number],
|
currentGps: [number, number],
|
||||||
author: string,
|
author: string,
|
||||||
noblur: boolean = false,
|
noblur: boolean = false,
|
||||||
|
progress?: UIEventSource<number>,
|
||||||
sequenceId?: string,
|
sequenceId?: string,
|
||||||
datetime?: string
|
datetime?: string
|
||||||
): Promise<{
|
): Promise<{
|
||||||
|
@ -319,15 +320,25 @@ export class PanoramaxUploader implements ImageUploader {
|
||||||
const sequence: { id: string; "stats:items": { count: number } } = (
|
const sequence: { id: string; "stats:items": { count: number } } = (
|
||||||
await p.mySequences()
|
await p.mySequences()
|
||||||
).find((s) => s.id === sequenceId)
|
).find((s) => s.id === sequenceId)
|
||||||
const img = <ImageData>await p.addImage(blob, sequence, {
|
const options = {
|
||||||
lon,
|
lon,
|
||||||
lat,
|
lat,
|
||||||
datetime,
|
datetime,
|
||||||
isBlurred: noblur,
|
isBlurred: noblur,
|
||||||
|
onProgress: undefined,
|
||||||
exifOverride: {
|
exifOverride: {
|
||||||
Artist: author,
|
Artist: author,
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if (progress) {
|
||||||
|
options.onProgress = (e: ProgressEvent) => {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const percentage = (e.loaded / e.total) * 100
|
||||||
|
progress.set(Math.round(percentage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const img = <ImageData>await p.addImage(blob, sequence, options)
|
||||||
PanoramaxImageProvider.singleton.addKnownMeta(img)
|
PanoramaxImageProvider.singleton.addKnownMeta(img)
|
||||||
return {
|
return {
|
||||||
key: "panoramax",
|
key: "panoramax",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { twMerge } from "tailwind-merge"
|
|
||||||
import Loading from "../../assets/svg/Loading.svelte"
|
import Loading from "../../assets/svg/Loading.svelte"
|
||||||
|
|
||||||
export let cls: string = "flex p-1 pl-2"
|
export let cls: string = "flex p-1 pl-2"
|
||||||
|
@ -9,7 +8,7 @@
|
||||||
<div class="h-6 w-6 min-w-6 shrink-0 animate-spin self-center">
|
<div class="h-6 w-6 min-w-6 shrink-0 animate-spin self-center">
|
||||||
<Loading />
|
<Loading />
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-2">
|
<div class="ml-2 w-full">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
failed.addCallbackAndRun((failed) => {
|
failed.addCallbackAndRun((failed) => {
|
||||||
dismissed = Math.min(failed, dismissed)
|
dismissed = Math.min(failed, dismissed)
|
||||||
})
|
})
|
||||||
|
let progress = state.imageUploadManager.progressCurrentImage
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $debugging}
|
{#if $debugging}
|
||||||
|
@ -53,11 +54,20 @@
|
||||||
{#if $pending - $failed > 0}
|
{#if $pending - $failed > 0}
|
||||||
<div class="alert">
|
<div class="alert">
|
||||||
<Loading>
|
<Loading>
|
||||||
{#if $pending - $failed === 1}
|
<div class="w-full flex flex-col">
|
||||||
<Tr t={t.upload.one.uploading} />
|
|
||||||
{:else if $pending - $failed > 1}
|
<div class="w-full flex justify-between">
|
||||||
<Tr t={t.upload.multiple.uploading.Subs({ count: $pending })} />
|
{#if $pending - $failed === 1}
|
||||||
{/if}
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Loading>
|
</Loading>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
import LevelSelector from "./BigComponents/LevelSelector.svelte"
|
import LevelSelector from "./BigComponents/LevelSelector.svelte"
|
||||||
import type { RasterLayerPolygon } from "../Models/RasterLayers"
|
import type { RasterLayerPolygon } from "../Models/RasterLayers"
|
||||||
import { AvailableRasterLayers } from "../Models/RasterLayers"
|
import { AvailableRasterLayers } from "../Models/RasterLayers"
|
||||||
import { onDestroy, setContext } from "svelte"
|
import { onDestroy } from "svelte"
|
||||||
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"
|
import OpenBackgroundSelectorButton from "./BigComponents/OpenBackgroundSelectorButton.svelte"
|
||||||
import StateIndicator from "./BigComponents/StateIndicator.svelte"
|
import StateIndicator from "./BigComponents/StateIndicator.svelte"
|
||||||
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"
|
import UploadingImageCounter from "./Image/UploadingImageCounter.svelte"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue