Add priority-search to the searchable element
This commit is contained in:
parent
c916d5fe66
commit
07973e37a6
14 changed files with 5349 additions and 244 deletions
|
@ -107,10 +107,18 @@ export interface MappingConfigJson {
|
||||||
addExtraTags?: string[]
|
addExtraTags?: string[]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searchterms (per language) to easily find an option if there are many options
|
* If there are many options, the mappings-radiobuttons will be replaced by an element with a searchfunction
|
||||||
|
*
|
||||||
|
* Searchterms (per language) allow to easily find an option if there are many options
|
||||||
*/
|
*/
|
||||||
searchTerms?: Record<string, string[]>
|
searchTerms?: Record<string, string[]>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the searchable selector is picked, mappings with this item will have priority and show up even if the others are hidden
|
||||||
|
* Use this sparingly
|
||||||
|
*/
|
||||||
|
priorityIf?: string | AndOrTagConfigJson
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,6 +14,7 @@ import List from "../../UI/Base/List";
|
||||||
import {MappingConfigJson, QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson";
|
import {MappingConfigJson, QuestionableTagRenderingConfigJson} from "./Json/QuestionableTagRenderingConfigJson";
|
||||||
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
|
import {FixedUiElement} from "../../UI/Base/FixedUiElement";
|
||||||
import {Paragraph} from "../../UI/Base/Paragraph";
|
import {Paragraph} from "../../UI/Base/Paragraph";
|
||||||
|
import UserDetails from "../../Logic/Osm/OsmConnection";
|
||||||
|
|
||||||
export interface Mapping {
|
export interface Mapping {
|
||||||
readonly if: TagsFilter,
|
readonly if: TagsFilter,
|
||||||
|
@ -23,7 +24,8 @@ export interface Mapping {
|
||||||
readonly iconClass: string | "small" | "medium" | "large" | "small-height" | "medium-height" | "large-height",
|
readonly iconClass: string | "small" | "medium" | "large" | "small-height" | "medium-height" | "large-height",
|
||||||
readonly hideInAnswer: boolean | TagsFilter
|
readonly hideInAnswer: boolean | TagsFilter
|
||||||
readonly addExtraTags: Tag[],
|
readonly addExtraTags: Tag[],
|
||||||
readonly searchTerms?: Record<string, string[]>
|
readonly searchTerms?: Record<string, string[]>,
|
||||||
|
readonly priorityIf?: TagsFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -287,6 +289,11 @@ export default class TagRenderingConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* const tr = TagRenderingConfig.ExtractMapping({if: "a=b", then: "x", priorityIf: "_country=be"}, 0, "test","test", false,true)
|
||||||
|
* tr.if // => new Tag("a","b")
|
||||||
|
* tr.priorityIf // => new Tag("_country","be")
|
||||||
|
*/
|
||||||
public static ExtractMapping(mapping: MappingConfigJson, i: number, translationKey: string,
|
public static ExtractMapping(mapping: MappingConfigJson, i: number, translationKey: string,
|
||||||
context: string,
|
context: string,
|
||||||
multiAnswer?: boolean, isQuestionable?: boolean, commonSize: string = "small") {
|
multiAnswer?: boolean, isQuestionable?: boolean, commonSize: string = "small") {
|
||||||
|
@ -337,6 +344,7 @@ export default class TagRenderingConfig {
|
||||||
iconClass = mapping.icon["class"] ?? iconClass
|
iconClass = mapping.icon["class"] ?? iconClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const prioritySearch = mapping.priorityIf !== undefined ? TagUtils.Tag(mapping.priorityIf) : undefined;
|
||||||
const mp = <Mapping>{
|
const mp = <Mapping>{
|
||||||
if: TagUtils.Tag(mapping.if, `${ctx}.if`),
|
if: TagUtils.Tag(mapping.if, `${ctx}.if`),
|
||||||
ifnot: (mapping.ifnot !== undefined ? TagUtils.Tag(mapping.ifnot, `${ctx}.ifnot`) : undefined),
|
ifnot: (mapping.ifnot !== undefined ? TagUtils.Tag(mapping.ifnot, `${ctx}.ifnot`) : undefined),
|
||||||
|
@ -345,7 +353,8 @@ export default class TagRenderingConfig {
|
||||||
icon,
|
icon,
|
||||||
iconClass,
|
iconClass,
|
||||||
addExtraTags,
|
addExtraTags,
|
||||||
searchTerms: mapping.searchTerms
|
searchTerms: mapping.searchTerms,
|
||||||
|
priorityIf: prioritySearch
|
||||||
};
|
};
|
||||||
if (isQuestionable) {
|
if (isQuestionable) {
|
||||||
if (hideInAnswer !== true && mp.if !== undefined && !mp.if.isUsableAsAnswer()) {
|
if (hideInAnswer !== true && mp.if !== undefined && !mp.if.isUsableAsAnswer()) {
|
||||||
|
|
|
@ -57,7 +57,13 @@ class SelfHidingToggle extends UIElement implements InputElement<boolean> {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
s = s?.trim()?.toLowerCase()
|
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])
|
}, [selected, Locale.language])
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
|
@ -142,13 +148,15 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
|
||||||
* Shows this if there are many (>200) possible mappings
|
* Shows this if there are many (>200) possible mappings
|
||||||
*/
|
*/
|
||||||
onManyElements?: BaseUIElement,
|
onManyElements?: BaseUIElement,
|
||||||
|
onManyElementsValue?: UIEventSource<T[]>,
|
||||||
selectIfSingle?: false | boolean,
|
selectIfSingle?: false | boolean,
|
||||||
searchAreaClass?: string
|
searchAreaClass?: string,
|
||||||
|
hideSearchBar?: false | boolean
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
const search = new TextField({value: options?.searchValue})
|
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")
|
.SetClass("flex items-center border-2 border-black m-2")
|
||||||
|
|
||||||
const searchValue = search.GetValue().map(s => s?.trim()?.toLowerCase())
|
const searchValue = search.GetValue().map(s => s?.trim()?.toLowerCase())
|
||||||
|
@ -228,19 +236,28 @@ export class SearchablePillsSelector<T> extends Combine implements InputElement<
|
||||||
totalShown = searchValue.map(_ => mappedValues.filter(mv => mv.show.isShown.data).length, 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([
|
super([
|
||||||
searchBar,
|
searchBar,
|
||||||
new VariableUiElement(Locale.language.map(lng => {
|
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)) {
|
if (options?.onNoSearchMade !== undefined && (searchValue.data === undefined || searchValue.data.length === 0)) {
|
||||||
return options?.onNoSearchMade
|
return options?.onNoSearchMade
|
||||||
}
|
}
|
||||||
if (totalShown.data == 0) {
|
if (totalShown.data == 0) {
|
||||||
return onEmpty
|
return onEmpty
|
||||||
}
|
}
|
||||||
if(totalShown.data >= 200){
|
|
||||||
return options?.onManyElements ?? Translations.t.general.useSearch;
|
|
||||||
}
|
|
||||||
mappedValues.sort((a, b) => a.mainTerm[lng] < b.mainTerm[lng] ? -1 : 1)
|
mappedValues.sort((a, b) => a.mainTerm[lng] < b.mainTerm[lng] ? -1 : 1)
|
||||||
return new Combine(mappedValues.map(e => e.show))
|
return new Combine(mappedValues.map(e => e.show))
|
||||||
.SetClass("flex flex-wrap w-full content-start")
|
.SetClass("flex flex-wrap w-full content-start")
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {SaveButton} from "./SaveButton";
|
||||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||||
import Translations from "../i18n/Translations";
|
import Translations from "../i18n/Translations";
|
||||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||||
import {Translation, TypedTranslation} from "../i18n/Translation";
|
import {Translation} from "../i18n/Translation";
|
||||||
import Constants from "../../Models/Constants";
|
import Constants from "../../Models/Constants";
|
||||||
import {SubstitutedTranslation} from "../SubstitutedTranslation";
|
import {SubstitutedTranslation} from "../SubstitutedTranslation";
|
||||||
import {TagsFilter} from "../../Logic/Tags/TagsFilter";
|
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
|
* // Should return the search as freeform value
|
||||||
|
@ -305,24 +328,9 @@ export default class TagRenderingQuestion extends Combine {
|
||||||
options?: {
|
options?: {
|
||||||
search: UIEventSource<string>
|
search: UIEventSource<string>
|
||||||
}): InputElement<TagsFilter> {
|
}): InputElement<TagsFilter> {
|
||||||
const values: { show: BaseUIElement, value: number, mainTerm: Record<string, string>, searchTerms?: Record<string, string[]> }[] = []
|
|
||||||
const addIcons = applicableMappings.some(m => m.icon !== undefined)
|
|
||||||
for (let i = 0; i < applicableMappings.length; i++) {
|
const values = TagRenderingQuestion.MappingToPillValue(applicableMappings, tagsSource, state)
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const searchValue: UIEventSource<string> = options?.search ?? new UIEventSource<string>(undefined)
|
const searchValue: UIEventSource<string> = options?.search ?? new UIEventSource<string>(undefined)
|
||||||
const ff = configuration.freeform
|
const ff = configuration.freeform
|
||||||
|
@ -330,14 +338,39 @@ export default class TagRenderingQuestion extends Combine {
|
||||||
if (ff !== undefined) {
|
if (ff !== undefined) {
|
||||||
onEmpty = new VariableUiElement(searchValue.map(search => configuration.render.Subs({[ff.key]: search})))
|
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"
|
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, {
|
const presetSearch = new SearchablePillsSelector<number>(values, {
|
||||||
selectIfSingle: true,
|
selectIfSingle: true,
|
||||||
mode: configuration.multiAnswer ? "select-many" : "select-one",
|
mode,
|
||||||
searchValue,
|
searchValue,
|
||||||
onNoMatches: onEmpty?.SetClass(classes).SetClass("flex justify-center items-center"),
|
onNoMatches: onEmpty?.SetClass(classes).SetClass("flex justify-center items-center"),
|
||||||
searchAreaClass: classes,
|
searchAreaClass: classes,
|
||||||
|
onManyElementsValue: tooMuchElementsValue,
|
||||||
|
onManyElements: priorityPresets
|
||||||
})
|
})
|
||||||
const fallbackTag = searchValue.map(s => {
|
const fallbackTag = searchValue.map(s => {
|
||||||
if (s === undefined || ff?.key === undefined) {
|
if (s === undefined || ff?.key === undefined) {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,13 +1,19 @@
|
||||||
{
|
{
|
||||||
"id": "mapcomplete-changes",
|
"id": "mapcomplete-changes",
|
||||||
"title": {
|
"title": {
|
||||||
"en": "Changes made with MapComplete"
|
"en": "Changes made with MapComplete",
|
||||||
|
"de": "Mit MapComplete vorgenommene Änderungen",
|
||||||
|
"nl": "Wijzigingen gemaakt met MapComplete"
|
||||||
},
|
},
|
||||||
"shortDescription": {
|
"shortDescription": {
|
||||||
"en": "Shows changes made by MapComplete"
|
"en": "Shows changes made by MapComplete",
|
||||||
|
"de": "Zeigt die mit MapComplete vorgenommenen Änderungen",
|
||||||
|
"nl": "Toont wijzigingen gemaakt met MapComplete"
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"en": "This maps shows all the changes made with MapComplete"
|
"en": "This maps shows all the changes made with MapComplete",
|
||||||
|
"de": "Diese Karte zeigt alle mit MapComplete vorgenommenen Änderungen",
|
||||||
|
"nl": "Deze kaart toont alle wijzigingen die met MapComplete werden gemaakt"
|
||||||
},
|
},
|
||||||
"maintainer": "",
|
"maintainer": "",
|
||||||
"icon": "./assets/svg/logo.svg",
|
"icon": "./assets/svg/logo.svg",
|
||||||
|
@ -22,7 +28,8 @@
|
||||||
{
|
{
|
||||||
"id": "mapcomplete-changes",
|
"id": "mapcomplete-changes",
|
||||||
"name": {
|
"name": {
|
||||||
"en": "Changeset centers"
|
"en": "Changeset centers",
|
||||||
|
"de": "Zentrum der Änderungssätze"
|
||||||
},
|
},
|
||||||
"minzoom": 0,
|
"minzoom": 0,
|
||||||
"source": {
|
"source": {
|
||||||
|
@ -36,35 +43,47 @@
|
||||||
],
|
],
|
||||||
"title": {
|
"title": {
|
||||||
"render": {
|
"render": {
|
||||||
"en": "Changeset for {theme}"
|
"en": "Changeset for {theme}",
|
||||||
|
"de": "Änderungssatz für {theme}",
|
||||||
|
"nl": "Wijzigingset voor {theme}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"description": {
|
"description": {
|
||||||
"en": "Shows all MapComplete changes"
|
"en": "Shows all MapComplete changes",
|
||||||
|
"de": "Zeigt alle MapComplete Änderungen",
|
||||||
|
"nl": "Toont alle wijzigingen met MapComplete"
|
||||||
},
|
},
|
||||||
"tagRenderings": [
|
"tagRenderings": [
|
||||||
{
|
{
|
||||||
"id": "render_id",
|
"id": "render_id",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
|
||||||
|
"de": "Änderungssatz <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
|
||||||
|
"nl": "Wijzigingset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "contributor",
|
"id": "contributor",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "Change made by <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>"
|
"en": "Change made by <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>",
|
||||||
|
"de": "Geändert von <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>",
|
||||||
|
"nl": "Wijziging gemaakt door <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "theme",
|
"id": "theme",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "Change with theme <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
|
"en": "Change with theme <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>",
|
||||||
|
"de": "Änderung mit Thema <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>",
|
||||||
|
"nl": "Wijziging met thema <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
|
||||||
},
|
},
|
||||||
"mappings": [
|
"mappings": [
|
||||||
{
|
{
|
||||||
"if": "theme~http.*",
|
"if": "theme~http.*",
|
||||||
"then": {
|
"then": {
|
||||||
"en": "Change with <b>unofficial</b> theme <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>"
|
"en": "Change with <b>unofficial</b> theme <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>",
|
||||||
|
"de": "Änderung mit <b>inoffiziellem</b> Thema <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>",
|
||||||
|
"nl": "Wijziging met <b>officieus</b> thema <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -360,7 +379,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"question": {
|
"question": {
|
||||||
"en": "Themename contains {search}"
|
"en": "Themename contains {search}",
|
||||||
|
"de": "Themenname enthält {search}",
|
||||||
|
"nl": "Themanaam bevat {search}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -376,7 +397,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"question": {
|
"question": {
|
||||||
"en": "Made by contributor {search}"
|
"en": "Made by contributor {search}",
|
||||||
|
"de": "Erstellt von {search}",
|
||||||
|
"nl": "Gemaakt door bijdrager {search}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -392,7 +415,9 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"question": {
|
"question": {
|
||||||
"en": "<b>Not</b> made by contributor {search}"
|
"en": "<b>Not</b> made by contributor {search}",
|
||||||
|
"de": "<b>Nicht</b> erstellt von {search}",
|
||||||
|
"nl": "<b>Niet</b> gemaakt door bijdrager {search}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -407,7 +432,9 @@
|
||||||
{
|
{
|
||||||
"id": "link_to_more",
|
"id": "link_to_more",
|
||||||
"render": {
|
"render": {
|
||||||
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
|
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>",
|
||||||
|
"de": "Weitere Statistiken finden Sie <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a>",
|
||||||
|
"nl": "Meer statistieken kunnen <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>hier</a> gevonden worden"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -236,6 +236,7 @@
|
||||||
"skippedQuestions": "Some questions are skipped",
|
"skippedQuestions": "Some questions are skipped",
|
||||||
"testing": "Testing - changes won't be saved",
|
"testing": "Testing - changes won't be saved",
|
||||||
"useSearch": "Use the search above to see presets",
|
"useSearch": "Use the search above to see presets",
|
||||||
|
"useSearchForMore": "Use the search function to search within {total} more values....",
|
||||||
"weekdays": {
|
"weekdays": {
|
||||||
"abbreviations": {
|
"abbreviations": {
|
||||||
"friday": "Fri",
|
"friday": "Fri",
|
||||||
|
|
|
@ -5122,6 +5122,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tagRenderings": {
|
"tagRenderings": {
|
||||||
|
"8": {
|
||||||
|
"override": {
|
||||||
|
"question": "Was ist die Hauptsprache dieser Schule?<div class='subtle'>Welche Sprache wird mit den Schülern in den nicht sprachbezogenen Kursen und mit der Verwaltung gesprochen?</div>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"question": "Wie viele Schüler können sich maximal an dieser Schule anmelden?",
|
"question": "Wie viele Schüler können sich maximal an dieser Schule anmelden?",
|
||||||
"render": "Diese Schule kann höchstens {capacity} Schüler aufnehmen"
|
"render": "Diese Schule kann höchstens {capacity} Schüler aufnehmen"
|
||||||
|
@ -5169,30 +5174,6 @@
|
||||||
},
|
},
|
||||||
"question": "Welche Geschlechter können sich an dieser Schule anmelden?"
|
"question": "Welche Geschlechter können sich an dieser Schule anmelden?"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"freeform": {
|
|
||||||
"placeholder": "Sprache in Englisch in Kleinbuchstaben"
|
|
||||||
},
|
|
||||||
"mappings": {
|
|
||||||
"0": {
|
|
||||||
"then": "Die Hauptsprache dieser Schule ist unbekannt"
|
|
||||||
},
|
|
||||||
"1": {
|
|
||||||
"then": "Französisch ist die Hauptsprache von {name}"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"then": "Niederländisch ist die Hauptsprache von {name}"
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"then": "Deutsch ist die Hauptsprache von {name}"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"then": "Die Hauptsprache dieser Schule ist unbekannt"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"question": "Was ist die Hauptsprache dieser Schule?<div class='subtle'>Welche Sprache wird mit den Schülern in den nicht sprachbezogenen Kursen und mit der Verwaltung gesprochen?</div>",
|
|
||||||
"render": "{school:language} ist die Hauptsprache von {title()}"
|
|
||||||
},
|
|
||||||
"school-name": {
|
"school-name": {
|
||||||
"question": "Wie lautet der Name dieser Schule?",
|
"question": "Wie lautet der Name dieser Schule?",
|
||||||
"render": "Diese Schule heißt {name}"
|
"render": "Diese Schule heißt {name}"
|
||||||
|
|
|
@ -5303,6 +5303,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tagRenderings": {
|
"tagRenderings": {
|
||||||
|
"8": {
|
||||||
|
"override": {
|
||||||
|
"+mappings": {
|
||||||
|
"0": {
|
||||||
|
"then": "The main language of this school is unknown"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"question": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"question": "How much students can at most enroll in this school?",
|
"question": "How much students can at most enroll in this school?",
|
||||||
"render": "This school can enroll at most {capacity} students"
|
"render": "This school can enroll at most {capacity} students"
|
||||||
|
@ -5350,30 +5360,6 @@
|
||||||
},
|
},
|
||||||
"question": "Which genders can enroll at this school?"
|
"question": "Which genders can enroll at this school?"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"freeform": {
|
|
||||||
"placeholder": "Language in lowercase English"
|
|
||||||
},
|
|
||||||
"mappings": {
|
|
||||||
"0": {
|
|
||||||
"then": "The main language of this school is unknown"
|
|
||||||
},
|
|
||||||
"1": {
|
|
||||||
"then": "French is the main language of {name}"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"then": "Dutch is the main language of {name}"
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"then": "German is the main language of {name}"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"then": "The main language of this school is unknown"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"question": "What is the main language of this school?<div class='subtle'>What language is spoken with the students in non-language related courses and with the administration?</div>",
|
|
||||||
"render": "{school:language} is the main language of {title()}"
|
|
||||||
},
|
|
||||||
"school-name": {
|
"school-name": {
|
||||||
"question": "What is the name of this school?",
|
"question": "What is the name of this school?",
|
||||||
"render": "This school is named {name}"
|
"render": "This school is named {name}"
|
||||||
|
|
|
@ -2419,6 +2419,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tagRenderings": {
|
"tagRenderings": {
|
||||||
|
"8": {
|
||||||
|
"override": {
|
||||||
|
"question": "Quelle est la langue principale de cette école ?<div class='subtle'>Quelle langue est parlée avec les élèves des cours non linguistiques et avec l'administration ?</div>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"question": "Combien d'élèves peuvent s'inscrire au maximum dans cette école ?",
|
"question": "Combien d'élèves peuvent s'inscrire au maximum dans cette école ?",
|
||||||
"render": "Cette école peut accueillir au maximum {capacity} étudiants"
|
"render": "Cette école peut accueillir au maximum {capacity} étudiants"
|
||||||
|
@ -2466,18 +2471,6 @@
|
||||||
},
|
},
|
||||||
"question": "Quels genres de personnes peuvent s'inscrire dans cette école ?"
|
"question": "Quels genres de personnes peuvent s'inscrire dans cette école ?"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"mappings": {
|
|
||||||
"0": {
|
|
||||||
"then": "La langue principale de cette école est inconnue"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"then": "La langue principale de cette école est inconnue"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"question": "Quelle est la langue principale de cette école ?<div class='subtle'>Quelle langue est parlée avec les élèves des cours non linguistiques et avec l'administration ?</div>",
|
|
||||||
"render": "{school:language} est la langue principale de {title()}"
|
|
||||||
},
|
|
||||||
"school-name": {
|
"school-name": {
|
||||||
"question": "Quel est le nom de cet établissement scolaire?",
|
"question": "Quel est le nom de cet établissement scolaire?",
|
||||||
"render": "Cet établissement scolaire s'appelle {name}"
|
"render": "Cet établissement scolaire s'appelle {name}"
|
||||||
|
|
|
@ -5112,6 +5112,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tagRenderings": {
|
"tagRenderings": {
|
||||||
|
"8": {
|
||||||
|
"override": {
|
||||||
|
"+mappings": {
|
||||||
|
"0": {
|
||||||
|
"then": "De voertaal van deze school is niet gekend"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"question": "Wat is de voertaal van deze school?<div class='subtle'>Welke taal wordt met de studenten gesproken in niet-taal-gerelateerde vakken en met de administratie?</div>"
|
||||||
|
}
|
||||||
|
},
|
||||||
"capacity": {
|
"capacity": {
|
||||||
"question": "Ten hoogste hoeveel studenten kunnen er les volgen in deze school?",
|
"question": "Ten hoogste hoeveel studenten kunnen er les volgen in deze school?",
|
||||||
"render": "Deze school kan maximaal {capacity} studenten lesgeven"
|
"render": "Deze school kan maximaal {capacity} studenten lesgeven"
|
||||||
|
@ -5159,30 +5169,6 @@
|
||||||
},
|
},
|
||||||
"question": "Mogen jongens en meisjes les volgen op deze school?"
|
"question": "Mogen jongens en meisjes les volgen op deze school?"
|
||||||
},
|
},
|
||||||
"language": {
|
|
||||||
"freeform": {
|
|
||||||
"placeholder": "Taal in lowercase Engel"
|
|
||||||
},
|
|
||||||
"mappings": {
|
|
||||||
"0": {
|
|
||||||
"then": "De voertaal van deze school is niet gekend"
|
|
||||||
},
|
|
||||||
"1": {
|
|
||||||
"then": "Frans is de voertaal van {name}"
|
|
||||||
},
|
|
||||||
"2": {
|
|
||||||
"then": "Nederlands is de voertaal van {name}"
|
|
||||||
},
|
|
||||||
"3": {
|
|
||||||
"then": "Duits is de voertaal van {name}"
|
|
||||||
},
|
|
||||||
"4": {
|
|
||||||
"then": "De voertaal van deze school is niet gekend"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"question": "Wat is de voertaal van deze school?<div class='subtle'>Welke taal wordt met de studenten gesproken in niet-taal-gerelateerde vakken en met de administratie?</div>",
|
|
||||||
"render": "{school:language} is de voertaal van {title()}"
|
|
||||||
},
|
|
||||||
"school-name": {
|
"school-name": {
|
||||||
"question": "Wat is de naam van deze school?",
|
"question": "Wat is de naam van deze school?",
|
||||||
"render": "Deze school heet <b>{name}</b>"
|
"render": "Deze school heet <b>{name}</b>"
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
"weblate-fix-heavy": "git remote rm weblate-layers; git remote add weblate-layers https://hosted.weblate.org/git/mapcomplete/layers/; git remote update weblate-layers; git merge weblate-layers/master",
|
"weblate-fix-heavy": "git remote rm weblate-layers; git remote add weblate-layers https://hosted.weblate.org/git/mapcomplete/layers/; git remote update weblate-layers; git merge weblate-layers/master",
|
||||||
"housekeeping": "npm run generate && npm run generate:docs && npm run generate:contributor-list && git add Docs/* && git commit assets/ langs/ Docs/ -m 'Housekeeping...'",
|
"housekeeping": "npm run generate && npm run generate:docs && npm run generate:contributor-list && git add Docs/* && git commit assets/ langs/ Docs/ -m 'Housekeeping...'",
|
||||||
"parseSchools": "ts-node scripts/schools/amendSchoolData.ts",
|
"parseSchools": "ts-node scripts/schools/amendSchoolData.ts",
|
||||||
"steal": "ts-node scripts/readIdPresets.ts"
|
"steal": "ts-node scripts/thieves/stealLanguages.ts"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"OpenStreetMap",
|
"OpenStreetMap",
|
||||||
|
|
|
@ -234,11 +234,11 @@ class LayerOverviewUtils {
|
||||||
this.checkAllSvgs()
|
this.checkAllSvgs()
|
||||||
|
|
||||||
if(AllKnownLayouts.getSharedLayersConfigs().size == 0){
|
if(AllKnownLayouts.getSharedLayersConfigs().size == 0){
|
||||||
throw "This was a bootstrapping-run. Run generate layeroverview again!"
|
console.error( "This was a bootstrapping-run. Run generate layeroverview again!")
|
||||||
|
}else{
|
||||||
|
const green = s => '\x1b[92m' + s + '\x1b[0m'
|
||||||
|
console.log(green("All done!"))
|
||||||
}
|
}
|
||||||
|
|
||||||
const green = s => '\x1b[92m' + s + '\x1b[0m'
|
|
||||||
console.log(green("All done!"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildLayerIndex(doesImageExist: DoesImageExist, forceReload: boolean): Map<string, LayerConfigJson> {
|
private buildLayerIndex(doesImageExist: DoesImageExist, forceReload: boolean): Map<string, LayerConfigJson> {
|
||||||
|
|
|
@ -7,14 +7,18 @@ import {existsSync, mkdirSync, readFileSync, writeFileSync} from "fs";
|
||||||
import {LayerConfigJson} from "../../Models/ThemeConfig/Json/LayerConfigJson";
|
import {LayerConfigJson} from "../../Models/ThemeConfig/Json/LayerConfigJson";
|
||||||
import {MappingConfigJson} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
|
import {MappingConfigJson} from "../../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson";
|
||||||
import LanguageUtils from "../../Utils/LanguageUtils";
|
import LanguageUtils from "../../Utils/LanguageUtils";
|
||||||
|
import * as perCountry from "../../assets/language_in_country.json"
|
||||||
|
import {Utils} from "../../Utils";
|
||||||
function main(){
|
function main(){
|
||||||
const sourcepath = "assets/generated/languages-wd.json";
|
const sourcepath = "assets/generated/languages-wd.json";
|
||||||
console.log(`Converting language data file '${sourcepath}' into a tagMapping`)
|
console.log(`Converting language data file '${sourcepath}' into a tagMapping`)
|
||||||
const languages = WikidataUtils.extractLanguageData(JSON.parse(readFileSync(sourcepath, "utf8")), {})
|
const languages = WikidataUtils.extractLanguageData(JSON.parse(readFileSync(sourcepath, "utf8")), {})
|
||||||
const mappings : MappingConfigJson[] = []
|
const mappings : MappingConfigJson[] = []
|
||||||
const schoolmappings : MappingConfigJson[] = []
|
const schoolmappings : MappingConfigJson[] = []
|
||||||
|
|
||||||
|
const countryToLanguage : Record<string, string[]> = perCountry
|
||||||
|
const officialLanguagesPerCountry = Utils.TransposeMap(countryToLanguage);
|
||||||
|
|
||||||
languages.forEach((l, code) => {
|
languages.forEach((l, code) => {
|
||||||
const then : Record<string, string>= {}
|
const then : Record<string, string>= {}
|
||||||
l.forEach((tr, lng) => {
|
l.forEach((tr, lng) => {
|
||||||
|
@ -24,18 +28,26 @@ function main(){
|
||||||
}
|
}
|
||||||
then[languageCodeWeblate] = tr
|
then[languageCodeWeblate] = tr
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const officialCountries = Utils.Dedup(officialLanguagesPerCountry[code]?.map(s => s.toLowerCase()) ?? [])
|
||||||
|
const prioritySearch = officialCountries.length > 0 ? "_country~" + officialCountries.map(c => "((^|;)"+c+"($|;))").join("|") : undefined
|
||||||
mappings.push(<MappingConfigJson>{
|
mappings.push(<MappingConfigJson>{
|
||||||
if: "language:" + code + "=yes",
|
if: "language:" + code + "=yes",
|
||||||
ifnot: "language:" + code + "=",
|
ifnot: "language:" + code + "=",
|
||||||
searchTerms: {
|
searchTerms: {
|
||||||
"*": [code]
|
"*": [code]
|
||||||
},
|
},
|
||||||
then
|
then,
|
||||||
|
priorityIf: prioritySearch
|
||||||
})
|
})
|
||||||
|
|
||||||
schoolmappings.push(<MappingConfigJson>{
|
schoolmappings.push(<MappingConfigJson>{
|
||||||
if: "school:language=" + code,
|
if: "school:language=" + code,
|
||||||
then
|
then,
|
||||||
|
priorityIf: prioritySearch,
|
||||||
|
searchTerms: {
|
||||||
|
"*":[code]
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue