Merge branch 'develop' into feature/maproulette

This commit is contained in:
Robin van der Linde 2022-07-18 09:41:38 +02:00
commit 1ce88c18c5
Signed by untrusted user: Robin-van-der-Linde
GPG key ID: 53956B3252478F0D
194 changed files with 755275 additions and 38277 deletions

View file

@ -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) ?? false;
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;
@ -138,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())
@ -193,10 +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) {
@ -218,31 +230,43 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
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);
}

View file

@ -11,7 +11,7 @@ import {SaveButton} from "./SaveButton";
import {VariableUiElement} from "../Base/VariableUIElement";
import Translations from "../i18n/Translations";
import {FixedUiElement} from "../Base/FixedUiElement";
import {Translation, TypedTranslation} from "../i18n/Translation";
import {Translation} from "../i18n/Translation";
import Constants from "../../Models/Constants";
import {SubstitutedTranslation} from "../SubstitutedTranslation";
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
@ -232,6 +232,29 @@ export default class TagRenderingQuestion extends Combine {
}
private static MappingToPillValue(applicableMappings: Mapping[], tagsSource: UIEventSource<OsmTags>, state: FeaturePipelineState): { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]>, original: Mapping }[] {
const values: { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]>, original: Mapping }[] = []
const addIcons = applicableMappings.some(m => m.icon !== undefined)
for (let i = 0; i < applicableMappings.length; i++) {
const mapping = applicableMappings[i];
const tr = mapping.then.Subs(tagsSource.data)
const patchedMapping = <Mapping>{
...mapping,
iconClass: `small-height`,
icon: mapping.icon ?? (addIcons ? "./assets/svg/none.svg" : undefined)
}
const fancy = TagRenderingQuestion.GenerateMappingContent(patchedMapping, tagsSource, state).SetClass("normal-background")
values.push({
show: fancy,
value: i,
mainTerm: tr.translations,
searchTerms: mapping.searchTerms,
original: mapping
})
}
return values
}
/**
*
* // Should return the search as freeform value
@ -305,23 +328,9 @@ export default class TagRenderingQuestion extends Combine {
options?: {
search: UIEventSource<string>
}): InputElement<TagsFilter> {
const values: { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[] = []
for (let i = 0; i < applicableMappings.length; i++) {
const mapping = applicableMappings[i];
const tr = mapping.then.Subs(tagsSource.data)
const patchedMapping = <Mapping>{
...mapping,
iconClass: `small-height`,
icon: mapping.icon ?? "./assets/svg/none.svg"
}
const fancy = TagRenderingQuestion.GenerateMappingContent(patchedMapping, tagsSource, state).SetClass("normal-background")
values.push({
show: fancy,
value: i,
mainTerm: tr.translations,
searchTerms: mapping.searchTerms
})
}
const values = TagRenderingQuestion.MappingToPillValue(applicableMappings, tagsSource, state)
const searchValue: UIEventSource<string> = options?.search ?? new UIEventSource<string>(undefined)
const ff = configuration.freeform
@ -329,14 +338,39 @@ export default class TagRenderingQuestion extends Combine {
if (ff !== undefined) {
onEmpty = new VariableUiElement(searchValue.map(search => configuration.render.Subs({[ff.key]: search})))
}
const mode = configuration.multiAnswer ? "select-many" : "select-one";
const tooMuchElementsValue = new UIEventSource<number[]>([]);
let priorityPresets: BaseUIElement = undefined;
const classes = "h-64 overflow-scroll"
if (applicableMappings.some(m => m.priorityIf !== undefined)) {
const priorityValues = tagsSource.map(tags =>
TagRenderingQuestion.MappingToPillValue(applicableMappings, tagsSource, state)
.filter(v => v.original.priorityIf?.matchesProperties(tags)))
priorityPresets = new VariableUiElement(priorityValues.map(priority => {
if (priority.length === 0) {
return Translations.t.general.useSearch;
}
return new Combine([
Translations.t.general.useSearchForMore.Subs({total: applicableMappings.length}),
new SearchablePillsSelector(priority, {
selectedElements: tooMuchElementsValue,
hideSearchBar: true,
mode
})]).SetClass("flex flex-col items-center ").SetClass(classes);
}));
}
const presetSearch = new SearchablePillsSelector<number>(values, {
selectIfSingle: true,
mode: configuration.multiAnswer ? "select-many" : "select-one",
mode,
searchValue,
onNoMatches: onEmpty?.SetClass(classes).SetClass("flex justify-center items-center"),
searchAreaClass: classes,
onManyElementsValue: tooMuchElementsValue,
onManyElements: priorityPresets
})
const fallbackTag = searchValue.map(s => {
if (s === undefined || ff?.key === undefined) {