forked from MapComplete/MapComplete
Fix search behaviour of theme index, fix #1385
This commit is contained in:
parent
aa6902a25c
commit
102fe2c5e8
2 changed files with 90 additions and 104 deletions
|
@ -1,17 +1,17 @@
|
||||||
import Svg from "../../Svg"
|
import Svg from "../../Svg"
|
||||||
import Combine from "../Base/Combine"
|
import Combine from "../Base/Combine"
|
||||||
import { SubtleButton } from "../Base/SubtleButton"
|
import {SubtleButton} from "../Base/SubtleButton"
|
||||||
import Translations from "../i18n/Translations"
|
import Translations from "../i18n/Translations"
|
||||||
import BaseUIElement from "../BaseUIElement"
|
import BaseUIElement from "../BaseUIElement"
|
||||||
import LayoutConfig, { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
import LayoutConfig, {LayoutInformation} from "../../Models/ThemeConfig/LayoutConfig"
|
||||||
import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
|
import {ImmutableStore, Store, UIEventSource} from "../../Logic/UIEventSource"
|
||||||
import Loc from "../../Models/Loc"
|
import Loc from "../../Models/Loc"
|
||||||
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
import UserRelatedState from "../../Logic/State/UserRelatedState"
|
||||||
import { Utils } from "../../Utils"
|
import {Utils} from "../../Utils"
|
||||||
import Title from "../Base/Title"
|
import Title from "../Base/Title"
|
||||||
import themeOverview from "../../assets/generated/theme_overview.json"
|
import themeOverview from "../../assets/generated/theme_overview.json"
|
||||||
import { Translation } from "../i18n/Translation"
|
import {Translation} from "../i18n/Translation"
|
||||||
import { TextField } from "../Input/TextField"
|
import {TextField} from "../Input/TextField"
|
||||||
import Locale from "../i18n/Locale"
|
import Locale from "../i18n/Locale"
|
||||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||||
import ThemesList from "./ThemesList.svelte"
|
import ThemesList from "./ThemesList.svelte"
|
||||||
|
@ -37,7 +37,7 @@ export default class MoreScreen extends Combine {
|
||||||
searchTerm = searchTerm.toLowerCase()
|
searchTerm = searchTerm.toLowerCase()
|
||||||
if (searchTerm === "personal") {
|
if (searchTerm === "personal") {
|
||||||
window.location.href = MoreScreen.createUrlFor(
|
window.location.href = MoreScreen.createUrlFor(
|
||||||
{ id: "personal" },
|
{id: "personal"},
|
||||||
false,
|
false,
|
||||||
state
|
state
|
||||||
).data
|
).data
|
||||||
|
@ -59,13 +59,13 @@ export default class MoreScreen extends Combine {
|
||||||
(th) =>
|
(th) =>
|
||||||
th.hideFromOverview == false &&
|
th.hideFromOverview == false &&
|
||||||
th.id !== "personal" &&
|
th.id !== "personal" &&
|
||||||
MoreScreen.MatchesLayoutFunc(th)(searchTerm)
|
MoreScreen.MatchesLayout(th, searchTerm)
|
||||||
)
|
)
|
||||||
if (publicTheme !== undefined) {
|
if (publicTheme !== undefined) {
|
||||||
window.location.href = MoreScreen.createUrlFor(publicTheme, false, state).data
|
window.location.href = MoreScreen.createUrlFor(publicTheme, false, state).data
|
||||||
}
|
}
|
||||||
const hiddenTheme = MoreScreen.officialThemes.find(
|
const hiddenTheme = MoreScreen.officialThemes.find(
|
||||||
(th) => th.id !== "personal" && MoreScreen.MatchesLayoutFunc(th)(searchTerm)
|
(th) => th.id !== "personal" && MoreScreen.MatchesLayout(th, searchTerm)
|
||||||
)
|
)
|
||||||
if (hiddenTheme !== undefined) {
|
if (hiddenTheme !== undefined) {
|
||||||
window.location.href = MoreScreen.createUrlFor(hiddenTheme, false, state).data
|
window.location.href = MoreScreen.createUrlFor(hiddenTheme, false, state).data
|
||||||
|
@ -109,6 +109,85 @@ export default class MoreScreen extends Combine {
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a button linking to the given theme
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
public static createLinkButton(
|
||||||
|
state: {
|
||||||
|
locationControl?: UIEventSource<Loc>
|
||||||
|
layoutToUse?: LayoutConfig
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
id: string
|
||||||
|
icon: string
|
||||||
|
title: any
|
||||||
|
shortDescription: any
|
||||||
|
definition?: any
|
||||||
|
mustHaveLanguage?: boolean
|
||||||
|
},
|
||||||
|
isCustom: boolean = false
|
||||||
|
): BaseUIElement {
|
||||||
|
const url = MoreScreen.createUrlFor(layout, isCustom, state)
|
||||||
|
let content = new Combine([
|
||||||
|
new Translation(
|
||||||
|
layout.title,
|
||||||
|
!isCustom && !layout.mustHaveLanguage ? "themes:" + layout.id + ".title" : undefined
|
||||||
|
),
|
||||||
|
new Translation(layout.shortDescription)?.SetClass("subtle") ?? "",
|
||||||
|
]).SetClass("overflow-hidden flex flex-col")
|
||||||
|
|
||||||
|
if (state.layoutToUse === undefined) {
|
||||||
|
// Currently on the index screen: we style the buttons equally large
|
||||||
|
content = new Combine([content]).SetClass("flex flex-col justify-center h-24")
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SubtleButton(layout.icon, content, {url, newTab: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CreateProffessionalSerivesButton() {
|
||||||
|
const t = Translations.t.professional.indexPage
|
||||||
|
return new Combine([
|
||||||
|
new Title(t.hook, 4),
|
||||||
|
t.hookMore,
|
||||||
|
new SubtleButton(undefined, t.button, {url: "./professional.html"}),
|
||||||
|
]).SetClass("flex flex-col border border-gray-300 p-2 rounded-lg")
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MatchesLayout(layout: {
|
||||||
|
id: string
|
||||||
|
title: any
|
||||||
|
shortDescription: any
|
||||||
|
keywords?: any[]
|
||||||
|
}, search: string): boolean {
|
||||||
|
if(search === undefined){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
search = search.toLocaleLowerCase()
|
||||||
|
if (search.length > 3 && layout.id.toLowerCase().indexOf(search) >= 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if(layout.id === "personal"){
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const entitiesToSearch = [
|
||||||
|
layout.shortDescription,
|
||||||
|
layout.title,
|
||||||
|
...(layout.keywords ?? []),
|
||||||
|
]
|
||||||
|
for (const entity of entitiesToSearch) {
|
||||||
|
if (entity === undefined) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const term = entity["*"] ?? entity[Locale.language.data]
|
||||||
|
if (term?.toLowerCase()?.indexOf(search) >= 0) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private static createUrlFor(
|
private static createUrlFor(
|
||||||
layout: { id: string; definition?: string },
|
layout: { id: string; definition?: string },
|
||||||
isCustom: boolean,
|
isCustom: boolean,
|
||||||
|
@ -164,79 +243,4 @@ export default class MoreScreen extends Combine {
|
||||||
}) ?? new ImmutableStore<string>(`${linkPrefix}`)
|
}) ?? new ImmutableStore<string>(`${linkPrefix}`)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a button linking to the given theme
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
public static createLinkButton(
|
|
||||||
state: {
|
|
||||||
locationControl?: UIEventSource<Loc>
|
|
||||||
layoutToUse?: LayoutConfig
|
|
||||||
},
|
|
||||||
layout: {
|
|
||||||
id: string
|
|
||||||
icon: string
|
|
||||||
title: any
|
|
||||||
shortDescription: any
|
|
||||||
definition?: any
|
|
||||||
mustHaveLanguage?: boolean
|
|
||||||
},
|
|
||||||
isCustom: boolean = false
|
|
||||||
): BaseUIElement {
|
|
||||||
const url = MoreScreen.createUrlFor(layout, isCustom, state)
|
|
||||||
let content = new Combine([
|
|
||||||
new Translation(
|
|
||||||
layout.title,
|
|
||||||
!isCustom && !layout.mustHaveLanguage ? "themes:" + layout.id + ".title" : undefined
|
|
||||||
),
|
|
||||||
new Translation(layout.shortDescription)?.SetClass("subtle") ?? "",
|
|
||||||
]).SetClass("overflow-hidden flex flex-col")
|
|
||||||
|
|
||||||
if (state.layoutToUse === undefined) {
|
|
||||||
// Currently on the index screen: we style the buttons equally large
|
|
||||||
content = new Combine([content]).SetClass("flex flex-col justify-center h-24")
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SubtleButton(layout.icon, content, { url, newTab: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CreateProffessionalSerivesButton() {
|
|
||||||
const t = Translations.t.professional.indexPage
|
|
||||||
return new Combine([
|
|
||||||
new Title(t.hook, 4),
|
|
||||||
t.hookMore,
|
|
||||||
new SubtleButton(undefined, t.button, { url: "./professional.html" }),
|
|
||||||
]).SetClass("flex flex-col border border-gray-300 p-2 rounded-lg")
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MatchesLayoutFunc(layout: {
|
|
||||||
id: string
|
|
||||||
title: any
|
|
||||||
shortDescription: any
|
|
||||||
keywords?: any[]
|
|
||||||
}): (search: string) => boolean {
|
|
||||||
return (search: string) => {
|
|
||||||
search = search.toLocaleLowerCase()
|
|
||||||
if (layout.id.toLowerCase().indexOf(search) >= 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
const entitiesToSearch = [
|
|
||||||
layout.shortDescription,
|
|
||||||
layout.title,
|
|
||||||
...(layout.keywords ?? []),
|
|
||||||
]
|
|
||||||
for (const entity of entitiesToSearch) {
|
|
||||||
if (entity === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const term = entity["*"] ?? entity[Locale.language.data]
|
|
||||||
if (term?.toLowerCase()?.indexOf(search) >= 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import ProfessionalServicesButton from "./ProfessionalServicesButton.svelte"
|
import ProfessionalServicesButton from "./ProfessionalServicesButton.svelte"
|
||||||
import ThemeButton from "./ThemeButton.svelte"
|
import ThemeButton from "./ThemeButton.svelte"
|
||||||
import { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
import { LayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||||
|
import MoreScreen from "./MoreScreen";
|
||||||
|
|
||||||
export let search: UIEventSource<string>
|
export let search: UIEventSource<string>
|
||||||
export let themes: LayoutInformation[]
|
export let themes: LayoutInformation[]
|
||||||
|
@ -18,26 +19,7 @@
|
||||||
export let hideThemes: boolean = true
|
export let hideThemes: boolean = true
|
||||||
|
|
||||||
// Filter theme based on search value
|
// Filter theme based on search value
|
||||||
$: filteredThemes = themes.filter((theme) => {
|
$: filteredThemes = themes.filter((theme) => MoreScreen.MatchesLayout(theme, $search))
|
||||||
if ($search === undefined || $search === "") return true
|
|
||||||
|
|
||||||
const srch = $search.toLocaleLowerCase()
|
|
||||||
if (theme.id.toLowerCase().indexOf(srch) >= 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
const entitiesToSearch = [theme.shortDescription, theme.title, ...(theme.keywords ?? [])]
|
|
||||||
for (const entity of entitiesToSearch) {
|
|
||||||
if (entity === undefined) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const term = entity["*"] ?? entity[Locale.language.data]
|
|
||||||
if (term?.toLowerCase()?.indexOf(search) >= 0) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
Loading…
Reference in a new issue