Skip to content

Commit

Permalink
feat: add support for filtering by years
Browse files Browse the repository at this point in the history
  • Loading branch information
razonyang committed May 12, 2023
1 parent 70e39ae commit dc8567d
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 17 deletions.
36 changes: 25 additions & 11 deletions assets/search/js/dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,35 @@
const item = e.target.closest('.search-dropdown-item')
if (item) {
const dropdown = item.closest('.search-dropdown')
const multiple = dropdown.hasAttribute('multiple')
const value = item.getAttribute('data-value')

if (value) {
dropdown.setAttribute('data-value', value)
dropdown.classList.add('active')
if (multiple) {
if (item.classList.contains('active')) {
item.classList.remove('active')
} else {
item.classList.add('active')
}
if (dropdown.querySelector('.search-dropdown-item.active')) {
dropdown.classList.add('active')
} else {
dropdown.classList.remove('active')
}
} else {
dropdown.removeAttribute('data-value')
dropdown.classList.remove('active')
if (value) {
dropdown.setAttribute('data-value', value)
dropdown.classList.add('active')
} else {
dropdown.removeAttribute('data-value')
dropdown.classList.remove('active')
}
dropdown.querySelector('.search-dropdown-label').innerText = item.innerText

dropdown.querySelectorAll('.search-dropdown-item').forEach((lang) => {
lang.classList.remove('active')
})
item.classList.add('active')
}
dropdown.querySelector('.search-dropdown-label').innerText = item.innerText

dropdown.querySelectorAll('.search-dropdown-item').forEach((lang) => {
lang.classList.remove('active')
})
item.classList.add('active')

// fire a change event.
const e = new CustomEvent('change', {
Expand Down
20 changes: 16 additions & 4 deletions assets/search/js/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class Engine {
}

private keys() {
const keys = ['title', 'summary', 'headings.title', 'lang']
const keys = ['title', 'summary', 'headings.title', 'lang', 'year']

if (params.index_content) {
keys.push('content')
Expand All @@ -88,8 +88,8 @@ class Engine {
* @param {string} sorting language.
* @returns {Promise<Record<string, unknown>>}
*/
search(query: string, sorting = '', lang = ''): Promise<Record<string, unknown>> {
const pattern = this.pattern(query, lang)
search(query: string, sorting = '', lang = '', years: Array<string> = []): Promise<Record<string, unknown>> {
const pattern = this.pattern(query, lang, years)
const start = (new Date()).getTime()
return new Promise((resolve) => {
setTimeout(() => {
Expand Down Expand Up @@ -121,7 +121,7 @@ class Engine {
* @param {string} query
* @param {string} lang
*/
private pattern(query: string, lang: string): string | Record<string, unknown> {
private pattern(query: string, lang: string, years: Array<string> = []): string | Record<string, unknown> {
if (lang === '') {
return query
}
Expand All @@ -146,6 +146,18 @@ class Engine {
})
}

if (years.length > 0) {
const yearsConditions: Array<Record<string, string>> = []
for (const year of years) {
yearsConditions.push({
year: `=${year}`
})
}
p.push({
"$or": yearsConditions
})
}

return {
"$and": p
}
Expand Down
37 changes: 36 additions & 1 deletion assets/search/js/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export default class Form {

private sorting: HTMLElement

private years: HTMLElement

modal = true

constructor(private spinner: Spinner, private renderer: Renderer) {
Expand All @@ -42,6 +44,7 @@ export default class Form {
<div class="search-panel">
${this.renderLanguage()}
${this.renderSorting()}
${this.renderYears()}
<button class="search-panel-action search-expand-toggle${params.expand_results_meta ? ' active' : ''}">
<span class="search-panel-action-icon">${params.icons['expand']}</span>
<span class="search-panel-action-label">${i18n.translate('expand')}</span>
Expand Down Expand Up @@ -100,6 +103,24 @@ export default class Form {
</div>`
}

private renderYears(): string {
if (params.years.length === 0) {
return ''
}

let items = ''
for (const year of params.years) {
items += `<li class="search-dropdown-item" data-value="${year}">${year}</li>`
}

return `<div class="search-dropdown search-panel-action search-years" multiple>
<button class="search-dropdown-toggle" type="button" aria-expanded="false">
${params.icons['year']} <span class="search-dropdown-label">Years</span>
</button>
<ul class="search-dropdown-menu">${items}</ul>
</div>`
}

private initialized = false

// Initialize the form after rendering.
Expand Down Expand Up @@ -139,6 +160,11 @@ export default class Form {
this.submit()
})

this.years = this.ele.querySelector('.search-years') as HTMLElement
this.years.addEventListener('change', () => {
this.submit()
})

engine.init().then(() => {
this.input.removeAttribute('disabled')
}).catch((err) => {
Expand Down Expand Up @@ -193,7 +219,8 @@ export default class Form {
this.spinner.show()
const sorting = this.getSorting()
const lang = this.getLanguage()
engine.search(query, sorting, lang).then(({ results, time }) => {
const years = this.getYears()
engine.search(query, sorting, lang, years).then(({ results, time }) => {
this.renderer.render(query, results, time)
}).finally(() => {
this.spinner.hide()
Expand Down Expand Up @@ -232,5 +259,13 @@ export default class Form {
getSorting(): string {
return this.sorting.getAttribute('data-value') ?? ''
}

getYears(): Array<string> {
const v: Array<string> = []
this.years.querySelectorAll('.search-dropdown-item.active').forEach((item) => {
v.push(item.getAttribute('data-value') ?? '')
})
return v
}
}

14 changes: 13 additions & 1 deletion layouts/partials/search/assets/js-resource.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
{{- range .Site.Languages }}
{{- $langs.Set .Lang (dict "lang" .Lang "name" .LanguageName) }}
{{- end }}
{{/* years. */}}
{{- $years := slice }}
{{- $indexAllPages := default true .Site.Params.search.index_all_pages }}
{{- $pages := cond $indexAllPages .Site.AllPages .Site.AllRegularPages }}
{{- $pages = where $pages "Params.noindex" "ne" true }}
{{- with $pages.GroupByDate "2006" }}
{{- range . }}
{{- $years = $years | append .Key }}
{{- end }}
{{- $years = sort $years }}
{{- end }}
{{/* i18n messages. */}}
{{- $i18n := newScratch }}
{{- range $lang, $messages := .Site.Data.search.i18n }}
Expand All @@ -22,6 +33,7 @@
"lang" (partial "icons/icon" (dict "vendor" "bootstrap" "name" "translate" "width" "1rem" "height" "1rem"))
"sort" (partial "icons/icon" (dict "vendor" "bootstrap" "name" "sort-down" "width" "1rem" "height" "1rem"))
"expand" (partial "icons/icon" (dict "vendor" "bootstrap" "name" "chevron-expand" "width" "1rem" "height" "1rem"))
"year" (partial "icons/icon" (dict "vendor" "bootstrap" "name" "calendar-check" "width" "1rem" "height" "1rem"))
}}
{{/* Include the following icons when necessary. */}}
{{- if default true .Site.Params.search.index_all_pages }}
Expand All @@ -46,7 +58,7 @@
"i18n" $i18n.Values
"defaultLang" $defaultLang
"langs" $langs.Values
)
"years" $years)
}}
{{- $options := dict
"targetPath" "js/search.js"
Expand Down
4 changes: 4 additions & 0 deletions layouts/partials/search/index.json.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{{- $items := slice -}}
{{- $indexContent := default false .Site.Params.search.index_content -}}
{{- $years := true }}
{{- $indexAllPages := default true .Site.Params.search.index_all_pages -}}
{{- $pages := cond $indexAllPages .Site.Pages .Site.RegularPages -}}
{{- $pages = where $pages "Params.noindex" "ne" true -}}
Expand All @@ -15,6 +16,9 @@
{{- $item.Set "lang" .Language.Lang -}}
{{- $item.Set "url" .RelPermalink -}}
{{- $item.Set "date" .Date.Unix -}}
{{- if $years }}
{{- $item.Set "year" (.Date.Format "2006") }}
{{- end }}
{{- $item.Set "headings" (partialCached "search/functions/parse-headings" . .) -}}
{{/* Taxonomies */}}
{{- range $name, $taxonomy := $.Site.Taxonomies -}}
Expand Down

0 comments on commit dc8567d

Please sign in to comment.