forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
15e6fde194
275 changed files with 786405 additions and 39150 deletions
|
@ -13,6 +13,11 @@ export class DropDown<T> extends InputElement<T> {
|
|||
private readonly _value: UIEventSource<T>;
|
||||
private readonly _values: { value: T; shown: string | BaseUIElement }[];
|
||||
|
||||
/**
|
||||
*
|
||||
* const dropdown = new DropDown<number>("test",[{value: 42, shown: "the answer"}])
|
||||
* dropdown.GetValue().data // => 42
|
||||
*/
|
||||
constructor(label: string | BaseUIElement,
|
||||
values: { value: T, shown: string | BaseUIElement }[],
|
||||
value: UIEventSource<T> = undefined,
|
||||
|
@ -21,7 +26,7 @@ export class DropDown<T> extends InputElement<T> {
|
|||
}
|
||||
) {
|
||||
super();
|
||||
value = value ?? new UIEventSource<T>(undefined)
|
||||
value = value ?? new UIEventSource<T>(values[0].value)
|
||||
this._value = value
|
||||
this._values = values;
|
||||
if (values.length <= 1) {
|
||||
|
@ -63,7 +68,7 @@ export class DropDown<T> extends InputElement<T> {
|
|||
|
||||
|
||||
select.onchange = (() => {
|
||||
var index = select.selectedIndex;
|
||||
const index = select.selectedIndex;
|
||||
value.setData(values[index].value);
|
||||
});
|
||||
|
||||
|
|
|
@ -57,7 +57,13 @@ class SelfHidingToggle extends UIElement implements InputElement<boolean> {
|
|||
return true
|
||||
}
|
||||
s = s?.trim()?.toLowerCase()
|
||||
return searchTerms[Locale.language.data].some(t => t.indexOf(s) >= 0);
|
||||
if(searchTerms[Locale.language.data]?.some(t => t.indexOf(s) >= 0)){
|
||||
return true
|
||||
}
|
||||
if(searchTerms["*"]?.some(t => t.indexOf(s) >= 0)){
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
}, [selected, Locale.language])
|
||||
|
||||
const self = this;
|
||||
|
@ -121,10 +127,15 @@ class SelfHidingToggle extends UIElement implements InputElement<boolean> {
|
|||
* A searchfield can be used to filter the values
|
||||
*/
|
||||
export class SearchablePillsSelector<T> extends Combine implements InputElement<T[]> {
|
||||
private selectedElements: UIEventSource<T[]>;
|
||||
private readonly selectedElements: UIEventSource<T[]>;
|
||||
|
||||
public readonly someMatchFound: Store<boolean>;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param values
|
||||
* @param options
|
||||
*/
|
||||
constructor(
|
||||
values: { show: BaseUIElement, value: T, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[],
|
||||
options?: {
|
||||
|
@ -133,13 +144,19 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
|
|||
searchValue?: UIEventSource<string>,
|
||||
onNoMatches?: BaseUIElement,
|
||||
onNoSearchMade?: BaseUIElement,
|
||||
/**
|
||||
* Shows this if there are many (>200) possible mappings
|
||||
*/
|
||||
onManyElements?: BaseUIElement,
|
||||
onManyElementsValue?: UIEventSource<T[]>,
|
||||
selectIfSingle?: false | boolean,
|
||||
searchAreaClass?: string
|
||||
searchAreaClass?: string,
|
||||
hideSearchBar?: false | boolean
|
||||
}) {
|
||||
|
||||
const search = new TextField({value: options?.searchValue})
|
||||
|
||||
const searchBar = new Combine([Svg.search_svg().SetClass("w-8 normal-background"), search.SetClass("w-full")])
|
||||
const searchBar = options?.hideSearchBar ? undefined : new Combine([Svg.search_svg().SetClass("w-8 normal-background"), search.SetClass("w-full")])
|
||||
.SetClass("flex items-center border-2 border-black m-2")
|
||||
|
||||
const searchValue = search.GetValue().map(s => s?.trim()?.toLowerCase())
|
||||
|
@ -188,11 +205,10 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
|
|||
};
|
||||
})
|
||||
|
||||
|
||||
let somethingShown: Store<boolean>
|
||||
let totalShown: Store<number>
|
||||
if (options.selectIfSingle) {
|
||||
let forcedSelection : { value: T, show: SelfHidingToggle } = undefined
|
||||
somethingShown = searchValue.map(_ => {
|
||||
totalShown = searchValue.map(_ => {
|
||||
let totalShown = 0;
|
||||
let lastShownValue: { value: T, show: SelfHidingToggle }
|
||||
for (const mv of mappedValues) {
|
||||
|
@ -203,42 +219,54 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
|
|||
}
|
||||
}
|
||||
if (totalShown == 1) {
|
||||
if (this.selectedElements.data.indexOf(lastShownValue.value) < 0) {
|
||||
this.selectedElements.setData([lastShownValue.value])
|
||||
if (selectedElements.data?.indexOf(lastShownValue.value) < 0) {
|
||||
selectedElements.setData([lastShownValue.value])
|
||||
lastShownValue.show.forceSelected.setData(true)
|
||||
forcedSelection = lastShownValue
|
||||
}
|
||||
} else if (forcedSelection != undefined) {
|
||||
forcedSelection?.show?.forceSelected?.setData(false)
|
||||
forcedSelection = undefined;
|
||||
this.selectedElements.setData([])
|
||||
selectedElements.setData([])
|
||||
}
|
||||
|
||||
return totalShown > 0
|
||||
return totalShown
|
||||
}, mappedValues.map(mv => mv.show.GetValue()))
|
||||
} else {
|
||||
somethingShown = searchValue.map(_ => mappedValues.some(mv => mv.show.isShown.data), mappedValues.map(mv => mv.show.GetValue()))
|
||||
totalShown = searchValue.map(_ => mappedValues.filter(mv => mv.show.isShown.data).length, mappedValues.map(mv => mv.show.GetValue()))
|
||||
|
||||
}
|
||||
const tooMuchElementsCutoff = 200;
|
||||
options?.onManyElementsValue?.map(value => {
|
||||
console.log("Installing toMuchElementsValue", value)
|
||||
if(tooMuchElementsCutoff <= totalShown.data){
|
||||
selectedElements.setData(value)
|
||||
selectedElements.ping()
|
||||
}
|
||||
}, [totalShown])
|
||||
|
||||
super([
|
||||
searchBar,
|
||||
new VariableUiElement(Locale.language.map(lng => {
|
||||
if(totalShown.data >= 200){
|
||||
return options?.onManyElements ?? Translations.t.general.useSearch;
|
||||
}
|
||||
if (options?.onNoSearchMade !== undefined && (searchValue.data === undefined || searchValue.data.length === 0)) {
|
||||
return options?.onNoSearchMade
|
||||
}
|
||||
if (!somethingShown.data) {
|
||||
if (totalShown.data == 0) {
|
||||
return onEmpty
|
||||
}
|
||||
|
||||
mappedValues.sort((a, b) => a.mainTerm[lng] < b.mainTerm[lng] ? -1 : 1)
|
||||
return new Combine(mappedValues.map(e => e.show))
|
||||
.SetClass("flex flex-wrap w-full content-start")
|
||||
.SetClass(options?.searchAreaClass ?? "")
|
||||
}, [somethingShown, searchValue]))
|
||||
}, [totalShown, searchValue]))
|
||||
|
||||
])
|
||||
this.selectedElements = selectedElements;
|
||||
this.someMatchFound = somethingShown;
|
||||
this.someMatchFound = totalShown.map(t => t > 0);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue