forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			137 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { VariableUiElement } from "../Base/VariableUIElement"
 | 
						|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
 | 
						|
import PlantNet from "../../Logic/Web/PlantNet"
 | 
						|
import Loading from "../Base/Loading"
 | 
						|
import Wikidata from "../../Logic/Web/Wikidata"
 | 
						|
import WikidataPreviewBox from "../Wikipedia/WikidataPreviewBox"
 | 
						|
import { Button } from "../Base/Button"
 | 
						|
import Combine from "../Base/Combine"
 | 
						|
import Title from "../Base/Title"
 | 
						|
import WikipediaBox from "../Wikipedia/WikipediaBox"
 | 
						|
import Translations from "../i18n/Translations"
 | 
						|
import List from "../Base/List"
 | 
						|
import Svg from "../../Svg"
 | 
						|
 | 
						|
export default class PlantNetSpeciesSearch extends VariableUiElement {
 | 
						|
    /***
 | 
						|
     * Given images, queries plantnet to search a species matching those images.
 | 
						|
     * A list of species will be presented to the user, after which they can confirm an item.
 | 
						|
     * The wikidata-url is returned in the callback when the user selects one
 | 
						|
     */
 | 
						|
    constructor(images: Store<string[]>, onConfirm: (wikidataUrl: string) => Promise<void>) {
 | 
						|
        const t = Translations.t.plantDetection
 | 
						|
        super(
 | 
						|
            images
 | 
						|
                .bind((images) => {
 | 
						|
                    if (images.length === 0) {
 | 
						|
                        return null
 | 
						|
                    }
 | 
						|
                    return UIEventSource.FromPromiseWithErr(PlantNet.query(images.slice(0, 5)))
 | 
						|
                })
 | 
						|
                .map((result) => {
 | 
						|
                    if (images.data.length === 0) {
 | 
						|
                        return new Combine([
 | 
						|
                            t.takeImages,
 | 
						|
                            t.howTo.intro,
 | 
						|
                            new List([t.howTo.li0, t.howTo.li1, t.howTo.li2, t.howTo.li3]),
 | 
						|
                        ]).SetClass("flex flex-col")
 | 
						|
                    }
 | 
						|
                    if (result === undefined) {
 | 
						|
                        return new Loading(t.querying.Subs(images.data))
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (result["error"] !== undefined) {
 | 
						|
                        return t.error.Subs(<any>result).SetClass("alert")
 | 
						|
                    }
 | 
						|
                    console.log(result)
 | 
						|
                    const success = result["success"]
 | 
						|
 | 
						|
                    const selectedSpecies = new UIEventSource<string>(undefined)
 | 
						|
                    const speciesInformation = success.results
 | 
						|
                        .filter((species) => species.score >= 0.005)
 | 
						|
                        .map((species) => {
 | 
						|
                            const wikidata = UIEventSource.FromPromise(
 | 
						|
                                Wikidata.Sparql<{ species }>(
 | 
						|
                                    ["?species", "?speciesLabel"],
 | 
						|
                                    ['?species wdt:P846 "' + species.gbif.id + '"']
 | 
						|
                                )
 | 
						|
                            )
 | 
						|
 | 
						|
                            const confirmButton = new Button(t.seeInfo, async () => {
 | 
						|
                                await selectedSpecies.setData(wikidata.data[0].species?.value)
 | 
						|
                            }).SetClass("btn")
 | 
						|
 | 
						|
                            const match = t.matchPercentage
 | 
						|
                                .Subs({ match: Math.round(species.score * 100) })
 | 
						|
                                .SetClass("font-bold")
 | 
						|
 | 
						|
                            const extraItems = new Combine([match, confirmButton]).SetClass(
 | 
						|
                                "flex flex-col"
 | 
						|
                            )
 | 
						|
 | 
						|
                            return new WikidataPreviewBox(
 | 
						|
                                wikidata.map((wd) =>
 | 
						|
                                    wd == undefined ? undefined : wd[0]?.species?.value
 | 
						|
                                ),
 | 
						|
                                {
 | 
						|
                                    whileLoading: new Loading(
 | 
						|
                                        t.loadingWikidata.Subs({
 | 
						|
                                            species: species.species.scientificNameWithoutAuthor,
 | 
						|
                                        })
 | 
						|
                                    ),
 | 
						|
                                    extraItems: [new Combine([extraItems])],
 | 
						|
 | 
						|
                                    imageStyle: "max-width: 8rem; width: unset; height: 8rem",
 | 
						|
                                }
 | 
						|
                            ).SetClass("border-2 border-subtle rounded-xl block mb-2")
 | 
						|
                        })
 | 
						|
                    const plantOverview = new Combine([
 | 
						|
                        new Title(t.overviewTitle),
 | 
						|
                        t.overviewIntro,
 | 
						|
                        t.overviewVerify.SetClass("font-bold"),
 | 
						|
                        ...speciesInformation,
 | 
						|
                    ]).SetClass("flex flex-col")
 | 
						|
 | 
						|
                    return new VariableUiElement(
 | 
						|
                        selectedSpecies.map((wikidataSpecies) => {
 | 
						|
                            if (wikidataSpecies === undefined) {
 | 
						|
                                return plantOverview
 | 
						|
                            }
 | 
						|
                            const buttons = new Combine([
 | 
						|
                                new Button(
 | 
						|
                                    new Combine([
 | 
						|
                                        Svg.back_svg().SetClass(
 | 
						|
                                            "w-6 mr-1 bg-white rounded-full p-1"
 | 
						|
                                        ),
 | 
						|
                                        t.back,
 | 
						|
                                    ]).SetClass("flex"),
 | 
						|
                                    () => {
 | 
						|
                                        selectedSpecies.setData(undefined)
 | 
						|
                                    }
 | 
						|
                                ).SetClass("btn btn-secondary"),
 | 
						|
 | 
						|
                                new Button(
 | 
						|
                                    new Combine([
 | 
						|
                                        Svg.confirm_svg().SetClass("w-6 mr-1"),
 | 
						|
                                        t.confirm,
 | 
						|
                                    ]).SetClass("flex"),
 | 
						|
                                    () => {
 | 
						|
                                        onConfirm(wikidataSpecies)
 | 
						|
                                    }
 | 
						|
                                ).SetClass("btn"),
 | 
						|
                            ]).SetClass("flex justify-between")
 | 
						|
 | 
						|
                            return new Combine([
 | 
						|
                                new WikipediaBox([wikidataSpecies], {
 | 
						|
                                    firstParagraphOnly: false,
 | 
						|
                                    noImages: false,
 | 
						|
                                    addHeader: false,
 | 
						|
                                }).SetClass("h-96"),
 | 
						|
                                buttons,
 | 
						|
                            ]).SetClass("flex flex-col self-end")
 | 
						|
                        })
 | 
						|
                    )
 | 
						|
                })
 | 
						|
        )
 | 
						|
    }
 | 
						|
}
 |