UX(plantnet): add retry button if detection failed, fix #2148

This commit is contained in:
Pieter Vander Vennet 2024-09-16 17:33:56 +02:00
parent 9b4f59b383
commit e08ce00850
3 changed files with 24 additions and 8 deletions

View file

@ -15,7 +15,7 @@ export default class PlantNet {
for (const image of imageUrls) { for (const image of imageUrls) {
url += "&images=" + encodeURIComponent(image) url += "&images=" + encodeURIComponent(image)
} }
return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000) return Utils.downloadJsonCached(url, 365 * 24 * 60 * 60 * 1000, undefined, true)
} }
public static exampleResult: PlantNetResult = { public static exampleResult: PlantNetResult = {

View file

@ -9,8 +9,8 @@
import BackButton from "../Base/BackButton.svelte" import BackButton from "../Base/BackButton.svelte"
import NextButton from "../Base/NextButton.svelte" import NextButton from "../Base/NextButton.svelte"
import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte" import WikipediaPanel from "../Wikipedia/WikipediaPanel.svelte"
import { createEventDispatcher } from "svelte"
import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte" import Plantnet_logo from "../../assets/svg/Plantnet_logo.svelte"
import ArrowPath from "@babeard/svelte-heroicons/mini/ArrowPath"
/** /**
* The main entry point for the plantnet wizard * The main entry point for the plantnet wizard
@ -23,7 +23,6 @@
*/ */
export let imageUrls: Store<string[]> export let imageUrls: Store<string[]>
export let onConfirm: (wikidataId: string) => void export let onConfirm: (wikidataId: string) => void
const dispatch = createEventDispatcher<{ selected: string }>()
let collapsedMode = true let collapsedMode = true
let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>( let options: UIEventSource<PlantNetSpeciesMatch[]> = new UIEventSource<PlantNetSpeciesMatch[]>(
undefined undefined
@ -38,18 +37,20 @@
let done = false let done = false
function speciesSelected(species: PlantNetSpeciesMatch) { function speciesSelected(species: string) {
console.log("Selected:", species) console.log("Selected:", species)
selectedOption = species selectedOption = species
} }
async function detectSpecies() { async function detectSpecies() {
error = undefined
collapsedMode = false collapsedMode = false
try { try {
const result = await PlantNet.query(imageUrls.data.slice(0, 5)) const result = await PlantNet.query(imageUrls.data.slice(0, 5))
options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8)) options.set(result.results.filter((r) => r.score > 0.005).slice(0, 8))
} catch (e) { } catch (e) {
console.error("Caught", e)
error = e error = e
} }
} }
@ -60,8 +61,12 @@
<button class="w-full" on:click={detectSpecies}> <button class="w-full" on:click={detectSpecies}>
<Tr t={t.button} /> <Tr t={t.button} />
</button> </button>
{:else if $error !== undefined} {:else if error !== undefined}
<Tr cls="alert" t={t.error.Subs({ error })} /> <Tr cls="alert" t={t.error.Subs({ error })} />
<button on:click={() => detectSpecies()}>
<ArrowPath class="w-6 h-6"/>
<Tr t={Translations.t.general.retry}/>
</button>
{:else if $imageUrls.length === 0} {:else if $imageUrls.length === 0}
<!-- No urls are available, show the explanation instead--> <!-- No urls are available, show the explanation instead-->
<div class=" border-region relative mb-1 p-2"> <div class=" border-region relative mb-1 p-2">

View file

@ -1073,19 +1073,22 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
public static async downloadJsonCached<T = object | []>( public static async downloadJsonCached<T = object | []>(
url: string, url: string,
maxCacheTimeMs: number, maxCacheTimeMs: number,
headers?: Record<string, string> headers?: Record<string, string>,
dontCacheErrors: boolean = false
): Promise<T> { ): Promise<T> {
const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers) const result = await Utils.downloadJsonCachedAdvanced(url, maxCacheTimeMs, headers, dontCacheErrors)
if (result["content"]) { if (result["content"]) {
return result["content"] return result["content"]
} }
throw result["error"] throw result["error"]
} }
public static async downloadJsonCachedAdvanced<T = object | []>( public static async downloadJsonCachedAdvanced<T = object | []>(
url: string, url: string,
maxCacheTimeMs: number, maxCacheTimeMs: number,
headers?: Record<string, string> headers?: Record<string, string>,
dontCacheErrors = false
): Promise<{ content: T } | { error: string; url: string; statuscode?: number }> { ): Promise<{ content: T } | { error: string; url: string; statuscode?: number }> {
const cached = Utils._download_cache.get(url) const cached = Utils._download_cache.get(url)
if (cached !== undefined) { if (cached !== undefined) {
@ -1099,7 +1102,15 @@ In the case that MapComplete is pointed to the testing grounds, the edit will be
headers headers
) )
Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() }) Utils._download_cache.set(url, { promise, timestamp: new Date().getTime() })
try {
return await promise return await promise
}catch (e) {
if(dontCacheErrors){
Utils._download_cache.delete(url)
}
throw e
}
} }
public static async downloadJson<T = object | []>( public static async downloadJson<T = object | []>(