| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | import Combine from "../Base/Combine"; | 
					
						
							|  |  |  | import {InputElement} from "../Input/InputElement"; | 
					
						
							|  |  |  | import {TextField} from "../Input/TextField"; | 
					
						
							|  |  |  | import Translations from "../i18n/Translations"; | 
					
						
							|  |  |  | import {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"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default class WikidataSearchBox extends InputElement<string> { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |     private static readonly _searchCache = new Map<string, Promise<WikidataResponse[]>>() | 
					
						
							|  |  |  |     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-04-22 01:45:54 +02:00
										 |  |  |     private readonly instanceOf?: number[]; | 
					
						
							|  |  |  |     private readonly notInstanceOf?: number[]; | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constructor(options?: { | 
					
						
							|  |  |  |         searchText?: UIEventSource<string>, | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |         value?: UIEventSource<string>, | 
					
						
							|  |  |  |         notInstanceOf?: number[], | 
					
						
							|  |  |  |         instanceOf?: number[] | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     }) { | 
					
						
							|  |  |  |         super(); | 
					
						
							|  |  |  |         this.searchText = options?.searchText | 
					
						
							|  |  |  |         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> { | 
					
						
							|  |  |  |         return this.wikidataId; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |     IsValid(t: string): boolean { | 
					
						
							|  |  |  |         return t.startsWith("Q") && !isNaN(Number(t.substring(1))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const searchField = new TextField({ | 
					
						
							|  |  |  |             placeholder: Translations.t.general.wikipedia.searchWikidata, | 
					
						
							|  |  |  |             value: this.searchText, | 
					
						
							|  |  |  |             inputStyle: "width: calc(100% - 0.5rem); border: 1px solid black" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         const selectedWikidataId = this.wikidataId | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const lastSearchResults = new UIEventSource<WikidataResponse[]>([]) | 
					
						
							|  |  |  |         const searchFailMessage = new UIEventSource(undefined) | 
					
						
							|  |  |  |         searchField.GetValue().addCallbackAndRunD(searchText => { | 
					
						
							|  |  |  |             if (searchText.length < 3) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             searchFailMessage.setData(undefined) | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const lang = Locale.language.data | 
					
						
							|  |  |  |             const key = lang + ":" + searchText | 
					
						
							|  |  |  |             let promise = WikidataSearchBox._searchCache.get(key) | 
					
						
							|  |  |  |             if (promise === undefined) { | 
					
						
							|  |  |  |                 promise = Wikidata.searchAndFetch(searchText, { | 
					
						
							|  |  |  |                         lang, | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |                         maxCount: 5, | 
					
						
							|  |  |  |                         notInstanceOf: this.notInstanceOf, | 
					
						
							|  |  |  |                         instanceOf: this.instanceOf | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  |                 ) | 
					
						
							|  |  |  |                 WikidataSearchBox._searchCache.set(key, promise) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             lastSearchResults.WaitForPromise(promise, err => searchFailMessage.setData(err)) | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const previews = new VariableUiElement(lastSearchResults.map(searchResults => { | 
					
						
							|  |  |  |             if (searchFailMessage.data !== undefined) { | 
					
						
							|  |  |  |                 return new Combine([Translations.t.general.wikipedia.failed.Clone().SetClass("alert"), searchFailMessage.data]) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |             if (searchField.GetValue().data.length === 0) { | 
					
						
							|  |  |  |                 return Translations.t.general.wikipedia.doSearch | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-07 02:23:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |             if (searchResults.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  |                 return Translations.t.general.wikipedia.noResults.Subs({search: searchField.GetValue().data ?? ""}) | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-22 01:45:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +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") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         }, [searchFailMessage])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const full = new Combine([ | 
					
						
							|  |  |  |             new Title(Translations.t.general.wikipedia.searchWikidata, 3).SetClass("m-2"), | 
					
						
							|  |  |  |             new Combine([ | 
					
						
							|  |  |  |                 Svg.search_ui().SetStyle("width: 1.5rem"), | 
					
						
							|  |  |  |                 searchField.SetClass("m-2 w-full")]).SetClass("flex"), | 
					
						
							|  |  |  |             previews | 
					
						
							|  |  |  |         ]).SetClass("flex flex-col border-2 border-black rounded-xl m-2 p-2") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return new Combine([ | 
					
						
							|  |  |  |             new VariableUiElement(selectedWikidataId.map(wid => { | 
					
						
							|  |  |  |                 if (wid === undefined) { | 
					
						
							|  |  |  |                     return undefined | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-10-09 22:40:52 +02:00
										 |  |  |                 return new WikipediaBox(wid.split(";")); | 
					
						
							| 
									
										
										
										
											2021-10-08 04:33:39 +02:00
										 |  |  |             })).SetStyle("max-height:12.5rem"), | 
					
						
							|  |  |  |             full | 
					
						
							|  |  |  |         ]).ConstructElement(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |