UX(plantnet): add retry button if detection failed, fix #2148
This commit is contained in:
parent
9b4f59b383
commit
e08ce00850
3 changed files with 24 additions and 8 deletions
|
@ -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 = {
|
||||||
|
|
|
@ -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">
|
||||||
|
|
17
src/Utils.ts
17
src/Utils.ts
|
@ -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 | []>(
|
||||||
|
|
Loading…
Reference in a new issue