Improvements to index search functionality

This commit is contained in:
pietervdvn 2022-04-28 02:04:25 +02:00
parent 1da799bb5f
commit 14ce4c1846
4 changed files with 89 additions and 80 deletions

View file

@ -36,28 +36,39 @@ export default class MoreScreen extends Combine {
}
const search = new TextField({
placeholder: tr.searchForATheme,
placeholder: tr.searchForATheme,
})
search.GetValue().addCallbackAndRun(d => console.log("Search is ", d))
if (onMainScreen) {
search.focus()
}
document.addEventListener("keydown", function (event) {
console.log("Got a key event: ", event)
if (event.ctrlKey && event.code === "KeyF") {
search.focus()
event.preventDefault();
}
});
const searchBar = new Combine([Svg.search_svg().SetClass("w-8"), search.SetClass("mr-4 w-full")])
.SetClass("flex rounded-full border-2 border-black w-max items-center my-2 w-1/2")
.SetClass("flex rounded-full border-2 border-black items-center my-2 w-1/2")
super([
new Combine([searchBar]).SetClass("flex justify-center"),
super([
new Combine([searchBar]).SetClass("flex justify-center"),
MoreScreen.createOfficialThemesList(state, themeButtonStyle, themeListStyle, search.GetValue()),
MoreScreen.createPreviouslyVistedHiddenList(state, themeButtonStyle, themeListStyle, search.GetValue()),
MoreScreen.createUnofficialThemeList(themeButtonStyle, state, themeListStyle, search.GetValue()),
tr.streetcomplete.Clone().SetClass("block text-base mx-10 my-3 mb-10")
]);
}
private static NothingFound(search: UIEventSource<string>): BaseUIElement{
const t = Translations.t.general.morescreen;
private static NothingFound(search: UIEventSource<string>): BaseUIElement {
const t = Translations.t.general.morescreen;
return new Combine([
new Title(t.noMatchingThemes, 5).SetClass("w-max font-bold"),
new SubtleButton(Svg.search_disable_ui(), t.noSearch,{imgSize: "h-8"}).SetClass("h-12 w-max")
.onClick( () => search.setData(""))
new SubtleButton(Svg.search_disable_ui(), t.noSearch, {imgSize: "h-6"}).SetClass("h-12 w-max")
.onClick(() => search.setData(""))
]).SetClass("flex flex-col items-center w-full")
}
@ -173,7 +184,7 @@ export default class MoreScreen extends Combine {
}
}
private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses: string, search : UIEventSource<string>): BaseUIElement {
private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses: string, search: UIEventSource<string>): BaseUIElement {
const prefix = "mapcomplete-unofficial-theme-";
var currentIds: UIEventSource<string[]> = state.osmConnection.preferencesHandler.preferences
@ -192,11 +203,14 @@ export default class MoreScreen extends Combine {
var stableIds = UIEventSource.ListStabilized<string>(currentIds)
return new VariableUiElement(
stableIds.map(ids => {
const allThemes: { element: BaseUIElement, predicate?: (s:string) => boolean }[] = []
const allThemes: { element: BaseUIElement, predicate?: (s: string) => boolean }[] = []
for (const id of ids) {
const link = this.createUnofficialButtonFor(state, id)
if (link !== undefined) {
allThemes.push({element: link.SetClass(buttonClass), predicate : s => id.toLowerCase().indexOf(s) >= 0})
allThemes.push({
element: link.SetClass(buttonClass),
predicate: s => id.toLowerCase().indexOf(s) >= 0
})
}
}
if (allThemes.length <= 0) {
@ -212,7 +226,7 @@ export default class MoreScreen extends Combine {
}));
}
private static createPreviouslyVistedHiddenList(state: UserRelatedState, buttonClass: string, themeListStyle: string, search: UIEventSource<string>) : BaseUIElement{
private static createPreviouslyVistedHiddenList(state: UserRelatedState, buttonClass: string, themeListStyle: string, search: UIEventSource<string>): BaseUIElement {
const t = Translations.t.general.morescreen
const prefix = "mapcomplete-hidden-theme-"
const hiddenThemes = themeOverview["default"].filter(layout => layout.hideFromOverview)
@ -230,15 +244,18 @@ export default class MoreScreen extends Combine {
}
const knownThemeDescriptions = hiddenThemes.filter(theme => knownThemes.has(theme.id))
.map(theme => ({element: MoreScreen.createLinkButton(state, theme)?.SetClass(buttonClass),
predicate: MoreScreen.MatchesLayoutFunc(theme)
.map(theme => ({
element: MoreScreen.createLinkButton(state, theme)?.SetClass(buttonClass),
predicate: MoreScreen.MatchesLayoutFunc(theme)
}));
const knownLayouts = new FilteredCombine(knownThemeDescriptions,
search,
{innerClasses: themeListStyle,
onEmpty: MoreScreen.NothingFound(search)}
)
{
innerClasses: themeListStyle,
onEmpty: MoreScreen.NothingFound(search)
}
)
return new Combine([
new Title(t.previouslyHiddenTitle),
@ -261,36 +278,28 @@ export default class MoreScreen extends Combine {
private static MatchesLayoutFunc(layout: {
id: string,
title: any,
shortDescription: any
shortDescription: any,
keywords?: any[]
}) {
return (search: string) => {
search = search.toLocaleLowerCase()
if (layout.id.toLowerCase().indexOf(search) >= 0) {
return true;
}
for (const lang in layout.shortDescription) {
if (Locale.language.data !== lang) {
continue
}
if (layout.shortDescription[lang].toLowerCase()?.indexOf(search) >= 0) {
const entitiesToSearch = [layout.shortDescription, layout.title, ...layout.keywords]
for (const entity of entitiesToSearch) {
const term = entity["*"] ?? entity[Locale.language.data]
if (term?.toLowerCase()?.indexOf(search) >= 0) {
return true
}
}
for (const lang in layout.title) {
if (Locale.language.data !== lang) {
continue
}
if (layout.title[lang].toLowerCase()?.indexOf(search) >= 0) {
return true
}
}
return false;
}
}
private static createOfficialThemesList(state: { osmConnection: OsmConnection, locationControl?: UIEventSource<Loc> }, buttonClass: string, themeListStyle: string, search: UIEventSource<string>):BaseUIElement {
private static createOfficialThemesList(state: { osmConnection: OsmConnection, locationControl?: UIEventSource<Loc> }, buttonClass: string, themeListStyle: string, search: UIEventSource<string>): BaseUIElement {
let officialThemes: {
id: string,
icon: string,

View file

@ -7,8 +7,10 @@ export class TextField extends InputElement<string> {
public readonly enterPressed = new UIEventSource<string>(undefined);
private readonly value: UIEventSource<string>;
private _element: HTMLElement;
private _actualField : HTMLElement
private readonly _isValid: (s: string) => boolean;
private _rawValue: UIEventSource<string>
private _isFocused = false;
constructor(options?: {
placeholder?: string | BaseUIElement,
@ -60,7 +62,6 @@ export class TextField extends InputElement<string> {
const field = inputEl;
this.value.addCallbackAndRunD(value => {
// We leave the textfield as is in the case of undefined or null (handled by addCallbackAndRunD) - make sure we do not erase it!
field["value"] = value;
@ -99,7 +100,6 @@ export class TextField extends InputElement<string> {
) {
newCursorPos--;
}
// @ts-ignore
TextField.SetCursorPosition(field, newCursorPos);
};
@ -110,6 +110,12 @@ export class TextField extends InputElement<string> {
self.enterPressed.setData(field.value);
}
});
if(this._isFocused){
field.focus()
}
this._actualField = field;
}
@ -147,4 +153,11 @@ export class TextField extends InputElement<string> {
return this._element;
}
public focus() {
if(this._actualField === undefined){
this._isFocused = true
}else{
this._actualField.focus()
}
}
}

View file

@ -1,19 +1,13 @@
{
"id": "mapcomplete-changes",
"title": {
"en": "Changes made with MapComplete",
"de": "Änderungen mit MapComplete",
"es": "Cambios hechos con MapComplete"
"en": "Changes made with MapComplete"
},
"shortDescription": {
"en": "Shows changes made by MapComplete",
"de": "Zeigt Änderungen von MapComplete",
"es": "Muestra los cambios hechos por MapComplete"
"en": "Shows changes made by MapComplete"
},
"description": {
"en": "This maps shows all the changes made with MapComplete",
"de": "Diese Karte zeigt alle Änderungen die mit MapComplete gemacht wurden",
"es": "Este mapa muestra todos los cambios hechos con MapComplete"
"en": "This maps shows all the changes made with MapComplete"
},
"maintainer": "",
"icon": "./assets/svg/logo.svg",
@ -28,9 +22,7 @@
{
"id": "mapcomplete-changes",
"name": {
"en": "Changeset centers",
"de": "Schwerpunkte von Änderungssätzen",
"es": "Centros de conjuntos de cambios"
"en": "Changeset centers"
},
"minzoom": 0,
"source": {
@ -44,45 +36,35 @@
],
"title": {
"render": {
"en": "Changeset for {theme}",
"de": "Änderungen für {theme}",
"es": "Conjunto de cambios para {theme}"
"en": "Changeset for {theme}"
}
},
"description": {
"en": "Shows all MapComplete changes",
"de": "Zeigt alle MapComplete Änderungen",
"es": "Muestra todos los cambios de MapComplete"
"en": "Shows all MapComplete changes"
},
"tagRenderings": [
{
"id": "render_id",
"render": {
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
"de": "Änderung <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>",
"es": "Conjunto de cambios <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
"en": "Changeset <a href='https://openstreetmap.org/changeset/{id}' target='_blank'>{id}</a>"
}
},
{
"id": "contributor",
"render": {
"en": "Change made by <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a>",
"de": "Änderung wurde von <a href='https://openstreetmap.org/user/{_last_edit:contributor}' target='_blank'>{_last_edit:contributor}</a> gemacht",
"es": "Cambio hecho por <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>"
}
},
{
"id": "theme",
"render": {
"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>"
"en": "Change with theme <a href='https://mapcomplete.osm.be/{theme}'>{theme}</a>"
},
"mappings": [
{
"if": "theme~http.*",
"then": {
"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>"
"en": "Change with <b>unofficial</b> theme <a href='https://mapcomplete.osm.be/theme.html?userlayout={theme}'>{theme}</a>"
}
}
]
@ -346,8 +328,7 @@
}
],
"question": {
"en": "Themename contains {search}",
"de": "Themenname enthält {search}"
"en": "Themename contains {search}"
}
}
]
@ -363,9 +344,7 @@
}
],
"question": {
"en": "Made by contributor {search}",
"de": "Erstellt von {search}",
"es": "Hecho por contributor/a {search}"
"en": "Made by contributor {search}"
}
}
]
@ -381,9 +360,7 @@
}
],
"question": {
"en": "<b>Not</b> made by contributor {search}",
"de": "<b>Nicht</b> erstellt von {search}",
"es": "<b>No</b> hecho por contributor/a {search}"
"en": "<b>Not</b> made by contributor {search}"
}
}
]
@ -398,9 +375,7 @@
{
"id": "link_to_more",
"render": {
"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>",
"es": "Se pueden encontrar más estadísticas <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>aquí</a>"
"en": "More statistics can be found <a href='https://github.com/pietervdvn/MapComplete/tree/develop/Docs/Tools/graphs' target='_blank'>here</a>"
}
},
{

View file

@ -13,22 +13,35 @@ import PointRenderingConfigJson from "../Models/ThemeConfig/Json/PointRenderingC
import {PrepareLayer} from "../Models/ThemeConfig/Conversion/PrepareLayer";
import {PrepareTheme} from "../Models/ThemeConfig/Conversion/PrepareTheme";
import {DesugaringContext} from "../Models/ThemeConfig/Conversion/Conversion";
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
import LayerConfigJsonJSC from "../Docs/Schemas/LayerConfigJsonJSC";
import {Utils} from "../Utils";
// This scripts scans 'assets/layers/*.json' for layer definition files and 'assets/themes/*.json' for theme definition files.
// It spits out an overview of those to be used to load them
class LayerOverviewUtils {
writeSmallOverview(themes: { id: string, title: any, shortDescription: any, icon: string, hideFromOverview: boolean, mustHaveLanguage: boolean }[]) {
writeSmallOverview(themes: { id: string, title: any, shortDescription: any, icon: string, hideFromOverview: boolean, mustHaveLanguage: boolean, layers: (LayerConfigJson | string | {builtin})[] }[]) {
const perId = new Map<string, any>();
for (const theme of themes) {
const keywords : {}[] = []
for (const layer of (theme.layers ?? [])) {
const l = <LayerConfigJson> layer;
keywords.push({"*": l.id})
keywords.push(l.title)
keywords.push(l.description)
}
const data = {
id: theme.id,
title: theme.title,
shortDescription: theme.shortDescription,
icon: theme.icon,
hideFromOverview: theme.hideFromOverview,
mustHaveLanguage: theme.mustHaveLanguage
mustHaveLanguage: theme.mustHaveLanguage,
keywords: Utils.NoNull(keywords)
}
perId.set(theme.id, data);
}
@ -215,13 +228,12 @@ class LayerOverviewUtils {
fixed.set(themeFile.id, themeFile)
}
this.writeSmallOverview(themeFiles.map(tf => {
const t = tf.parsed;
this.writeSmallOverview(Array.from(fixed.values()).map(t => {
return {
...t,
hideFromOverview: t.hideFromOverview ?? false,
shortDescription: t.shortDescription ?? new Translation(t.description).FirstSentence().translations,
mustHaveLanguage: t.mustHaveLanguage?.length > 0
mustHaveLanguage: t.mustHaveLanguage?.length > 0,
}
}));
return fixed;