| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import Combine from "../Base/Combine" | 
					
						
							|  |  |  | import { InputElement } from "../Input/InputElement" | 
					
						
							|  |  |  | import { TextField } from "../Input/TextField" | 
					
						
							|  |  |  | import Translations from "../i18n/Translations" | 
					
						
							|  |  |  | import { ImmutableStore, Store, Stores, UIEventSource } from "../../Logic/UIEventSource" | 
					
						
							|  |  |  | import Wikidata, { WikidataResponse } from "../../Logic/Web/Wikidata" | 
					
						
							|  |  |  | import Locale from "../i18n/Locale" | 
					
						
							|  |  |  | import { VariableUiElement } from "../Base/VariableUIElement" | 
					
						
							|  |  |  | import WikidataPreviewBox from "./WikidataPreviewBox" | 
					
						
							|  |  |  | import Title from "../Base/Title" | 
					
						
							|  |  |  | import WikipediaBox from "./WikipediaBox" | 
					
						
							|  |  |  | import Svg from "../../Svg" | 
					
						
							|  |  |  | import Loading from "../Base/Loading" | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class WikidataSearchBox extends InputElement<string> { | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |     private static readonly _searchCache = new Map<string, Promise<WikidataResponse[]>>() | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false) | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     private readonly wikidataId: UIEventSource<string> | 
					
						
							|  |  |  |     private readonly searchText: UIEventSource<string> | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private readonly instanceOf?: number[] | 
					
						
							|  |  |  |     private readonly notInstanceOf?: number[] | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constructor(options?: { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         searchText?: UIEventSource<string> | 
					
						
							|  |  |  |         value?: UIEventSource<string> | 
					
						
							|  |  |  |         notInstanceOf?: number[] | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |         instanceOf?: number[] | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     }) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         super() | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |         this.searchText = options?.searchText | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         this.wikidataId = options?.value ?? new UIEventSource<string>(undefined) | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |         this.instanceOf = options?.instanceOf | 
					
						
							|  |  |  |         this.notInstanceOf = options?.notInstanceOf | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GetValue(): UIEventSource<string> { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return this.wikidataId | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |     IsValid(t: string): boolean { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         return t.startsWith("Q") && !isNaN(Number(t.substring(1))) | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							|  |  |  |         const searchField = new TextField({ | 
					
						
							|  |  |  |             placeholder: Translations.t.general.wikipedia.searchWikidata, | 
					
						
							|  |  |  |             value: this.searchText, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             inputStyle: "width: calc(100% - 0.5rem); border: 1px solid black", | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  |         const selectedWikidataId = this.wikidataId | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const tooShort = new ImmutableStore<{ success: WikidataResponse[] }>({ success: undefined }) | 
					
						
							|  |  |  |         const searchResult: Store<{ success?: WikidataResponse[]; error?: any }> = searchField | 
					
						
							|  |  |  |             .GetValue() | 
					
						
							|  |  |  |             .bind((searchText) => { | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |                 if (searchText.length < 3) { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return tooShort | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |                 const lang = Locale.language.data | 
					
						
							|  |  |  |                 const key = lang + ":" + searchText | 
					
						
							|  |  |  |                 let promise = WikidataSearchBox._searchCache.get(key) | 
					
						
							|  |  |  |                 if (promise === undefined) { | 
					
						
							|  |  |  |                     promise = Wikidata.searchAndFetch(searchText, { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                         lang, | 
					
						
							|  |  |  |                         maxCount: 5, | 
					
						
							|  |  |  |                         notInstanceOf: this.notInstanceOf, | 
					
						
							|  |  |  |                         instanceOf: this.instanceOf, | 
					
						
							|  |  |  |                     }) | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  |                     WikidataSearchBox._searchCache.set(key, promise) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return Stores.FromPromiseWithErr(promise) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         const previews = new VariableUiElement( | 
					
						
							|  |  |  |             searchResult.map( | 
					
						
							|  |  |  |                 (searchResultsOrFail) => { | 
					
						
							|  |  |  |                     if (searchField.GetValue().data.length === 0) { | 
					
						
							|  |  |  |                         return Translations.t.general.wikipedia.doSearch | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-06-05 02:24:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     if (searchField.GetValue().data.length < 3) { | 
					
						
							|  |  |  |                         return Translations.t.general.wikipedia.searchToShort | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     if (searchResultsOrFail === undefined) { | 
					
						
							|  |  |  |                         return new Loading(Translations.t.general.loading) | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     if (searchResultsOrFail.error !== undefined) { | 
					
						
							|  |  |  |                         return new Combine([ | 
					
						
							|  |  |  |                             Translations.t.general.wikipedia.failed.Clone().SetClass("alert"), | 
					
						
							|  |  |  |                             searchResultsOrFail.error, | 
					
						
							|  |  |  |                         ]) | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     const searchResults = searchResultsOrFail.success | 
					
						
							|  |  |  |                     if (searchResults.length === 0) { | 
					
						
							|  |  |  |                         return Translations.t.general.wikipedia.noResults.Subs({ | 
					
						
							|  |  |  |                             search: searchField.GetValue().data ?? "", | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     return new Combine( | 
					
						
							|  |  |  |                         searchResults.map((wikidataresponse) => { | 
					
						
							|  |  |  |                             const el = WikidataPreviewBox.WikidataResponsePreview( | 
					
						
							|  |  |  |                                 wikidataresponse | 
					
						
							|  |  |  |                             ).SetClass( | 
					
						
							|  |  |  |                                 "rounded-xl p-1 sm:p-2 md:p-3 m-px border-2 sm:border-4 transition-colors" | 
					
						
							|  |  |  |                             ) | 
					
						
							|  |  |  |                             el.onClick(() => { | 
					
						
							|  |  |  |                                 selectedWikidataId.setData(wikidataresponse.id) | 
					
						
							|  |  |  |                             }) | 
					
						
							|  |  |  |                             selectedWikidataId.addCallbackAndRunD((selected) => { | 
					
						
							|  |  |  |                                 if (selected === wikidataresponse.id) { | 
					
						
							|  |  |  |                                     el.SetClass("subtle-background border-attention") | 
					
						
							|  |  |  |                                 } else { | 
					
						
							|  |  |  |                                     el.RemoveClass("subtle-background") | 
					
						
							|  |  |  |                                     el.RemoveClass("border-attention") | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  |                             }) | 
					
						
							|  |  |  |                             return el | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                     ).SetClass("flex flex-col") | 
					
						
							|  |  |  |                 }, | 
					
						
							|  |  |  |                 [searchField.GetValue()] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const full = new Combine([ | 
					
						
							|  |  |  |             new Title(Translations.t.general.wikipedia.searchWikidata, 3).SetClass("m-2"), | 
					
						
							|  |  |  |             new Combine([ | 
					
						
							|  |  |  |                 Svg.search_ui().SetStyle("width: 1.5rem"), | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                 searchField.SetClass("m-2 w-full"), | 
					
						
							|  |  |  |             ]).SetClass("flex"), | 
					
						
							|  |  |  |             previews, | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |         ]).SetClass("flex flex-col border-2 border-black rounded-xl m-2 p-2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new Combine([ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             new VariableUiElement( | 
					
						
							|  |  |  |                 selectedWikidataId.map((wid) => { | 
					
						
							|  |  |  |                     if (wid === undefined) { | 
					
						
							|  |  |  |                         return undefined | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     return new WikipediaBox(wid.split(";")) | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             ).SetStyle("max-height:12.5rem"), | 
					
						
							|  |  |  |             full, | 
					
						
							|  |  |  |         ]).ConstructElement() | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |