mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-15 06:35:20 -07:00
refactor(search): extract shared filter helper
Share filter parsing and provider mapping logic between Stork and upcoming search adapters. This keeps the existing Stork API stable while adding Pagefind-oriented filter serialization under test.
This commit is contained in:
parent
e5f28b16ee
commit
727f84e4c2
3 changed files with 135 additions and 120 deletions
119
helpers/search/filters.js
Normal file
119
helpers/search/filters.js
Normal file
|
|
@ -0,0 +1,119 @@
|
||||||
|
import { filterSeparator } from '~/helpers/constants.js'
|
||||||
|
import { isString } from '~/helpers/check-types.js'
|
||||||
|
|
||||||
|
export class SearchFilters {
|
||||||
|
constructor({
|
||||||
|
initialFilters = {}
|
||||||
|
} = {}) {
|
||||||
|
this.initialFilters = initialFilters
|
||||||
|
|
||||||
|
this.filters = {
|
||||||
|
...initialFilters
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get list () {
|
||||||
|
return Object.entries( this.filters ).map( ([ filterKey, filterValue ]) => {
|
||||||
|
return `${ filterKey }${ filterSeparator }${ filterValue }`
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
|
||||||
|
get asQuery () {
|
||||||
|
return this.list.join(' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
get asPagefindFilters () {
|
||||||
|
return Object.fromEntries( Object.entries( this.filters ).map( ([ filterKey, filterValue ]) => {
|
||||||
|
return [ filterKey, [ filterValue ] ]
|
||||||
|
}) )
|
||||||
|
}
|
||||||
|
|
||||||
|
getByKey ( key ) {
|
||||||
|
return `${ key }${ filterSeparator }${ this.filters[ key ] }`
|
||||||
|
}
|
||||||
|
|
||||||
|
isQueryValue ( filterNameOrQueryValue ) {
|
||||||
|
return filterNameOrQueryValue.includes( filterSeparator )
|
||||||
|
}
|
||||||
|
|
||||||
|
getKeyAndValue ( filterQueryValue ) {
|
||||||
|
const key = filterQueryValue.substring(0, filterQueryValue.indexOf( filterSeparator ))
|
||||||
|
const value = filterQueryValue.substring(filterQueryValue.indexOf( filterSeparator )+1)
|
||||||
|
|
||||||
|
return { key, value }
|
||||||
|
}
|
||||||
|
|
||||||
|
getFilterNameAndValueFromString ( filterNameOrQueryValue ) {
|
||||||
|
if ( this.isQueryValue( filterNameOrQueryValue ) ) {
|
||||||
|
return this.getKeyAndValue( filterNameOrQueryValue )
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: filterNameOrQueryValue,
|
||||||
|
value: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remove ( filterName ) {
|
||||||
|
if ( this.isQueryValue( filterName ) ) throw new Error(`${ filterName } is not a valid filter name`)
|
||||||
|
|
||||||
|
delete this.filters[ filterName ]
|
||||||
|
}
|
||||||
|
|
||||||
|
setFromStringArray ( filterStringArray ) {
|
||||||
|
filterStringArray.forEach( filterString => {
|
||||||
|
const { key, value } = this.getFilterNameAndValueFromString( filterString )
|
||||||
|
|
||||||
|
this.filters[ key ] = value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setFromString ( filterNameOrQueryValue ) {
|
||||||
|
const {
|
||||||
|
key,
|
||||||
|
value = ''
|
||||||
|
} = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
||||||
|
|
||||||
|
if ( value.trim().length === 0 ) throw new Error(`${ filterNameOrQueryValue } is not a valid filter value`)
|
||||||
|
|
||||||
|
this.set( key, value )
|
||||||
|
}
|
||||||
|
|
||||||
|
set ( filterName, filterValue ) {
|
||||||
|
if ( this.isQueryValue( filterName ) ) throw new Error(`${ filterName } is not a valid filter name`)
|
||||||
|
|
||||||
|
this.filters[ filterName ] = filterValue
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleFilter ( filterNameOrQueryValue, filterValue = null ) {
|
||||||
|
const fromString = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
||||||
|
|
||||||
|
const filterName = fromString.key
|
||||||
|
filterValue = filterValue || fromString.value
|
||||||
|
|
||||||
|
if ( this.has( filterNameOrQueryValue ) ) {
|
||||||
|
this.remove( filterName )
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof filterValue !== 'string' ) {
|
||||||
|
throw new Error(`Filter value must be a string. Got ${ typeof filterValue }`)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set( filterName, filterValue )
|
||||||
|
}
|
||||||
|
|
||||||
|
has ( filterNameOrQueryValue ) {
|
||||||
|
const {
|
||||||
|
key : filterName,
|
||||||
|
value : filterValue = null
|
||||||
|
} = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
||||||
|
|
||||||
|
if ( isString( filterValue ) ) {
|
||||||
|
return !!this.filters[ filterName ] && this.filters[ filterName ] === filterValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!this.filters[ filterName ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { filterSeparator } from '~/helpers/constants.js'
|
|
||||||
|
|
||||||
import { isString } from '~/helpers/check-types.js'
|
import { isString } from '~/helpers/check-types.js'
|
||||||
|
import { SearchFilters } from '~/helpers/search/filters.js'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
storkIndexRelativeURL,
|
storkIndexRelativeURL,
|
||||||
|
|
@ -276,121 +275,4 @@ export class StorkClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StorkFilters {
|
export class StorkFilters extends SearchFilters {}
|
||||||
constructor({
|
|
||||||
initialFilters = {}
|
|
||||||
} = {}) {
|
|
||||||
this.initialFilters = initialFilters
|
|
||||||
|
|
||||||
this.filters = {
|
|
||||||
...initialFilters
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get list () {
|
|
||||||
return Object.entries( this.filters ).map( ([ filterKey, filterValue ]) => {
|
|
||||||
return `${ filterKey }${ filterSeparator }${ filterValue }`
|
|
||||||
} )
|
|
||||||
}
|
|
||||||
|
|
||||||
get asQuery () {
|
|
||||||
return this.list.join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
getByKey ( key ) {
|
|
||||||
return `${ key }${ filterSeparator }${ this.filters[ key ] }`
|
|
||||||
}
|
|
||||||
|
|
||||||
isQueryValue ( filterNameOrQueryValue ) {
|
|
||||||
return filterNameOrQueryValue.includes( filterSeparator )
|
|
||||||
}
|
|
||||||
|
|
||||||
getKeyAndValue ( filterQueryValue ) {
|
|
||||||
const key = filterQueryValue.substring(0, filterQueryValue.indexOf( filterSeparator ))
|
|
||||||
const value = filterQueryValue.substring(filterQueryValue.indexOf( filterSeparator )+1)
|
|
||||||
|
|
||||||
return { key, value }
|
|
||||||
}
|
|
||||||
|
|
||||||
getFilterNameAndValueFromString ( filterNameOrQueryValue ) {
|
|
||||||
if ( this.isQueryValue( filterNameOrQueryValue ) ) {
|
|
||||||
return this.getKeyAndValue( filterNameOrQueryValue )
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
key: filterNameOrQueryValue,
|
|
||||||
value: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
remove ( filterName ) {
|
|
||||||
// Throw error if it's not a valid filter name
|
|
||||||
if ( this.isQueryValue( filterName ) ) throw new Error(`${ filterName } is not a valid filter name`)
|
|
||||||
|
|
||||||
delete this.filters[ filterName ]
|
|
||||||
}
|
|
||||||
|
|
||||||
setFromStringArray ( filterStringArray ) {
|
|
||||||
filterStringArray.forEach( filterString => {
|
|
||||||
const { key, value } = this.getFilterNameAndValueFromString( filterString )
|
|
||||||
|
|
||||||
this.filters[ key ] = value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setFromString ( filterNameOrQueryValue ) {
|
|
||||||
const {
|
|
||||||
key,
|
|
||||||
value = ''
|
|
||||||
} = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
|
||||||
|
|
||||||
// Throw for empty values
|
|
||||||
if ( value.trim().length === 0 ) throw new Error(`${ filterNameOrQueryValue } is not a valid filter value`)
|
|
||||||
|
|
||||||
this.set( key, value )
|
|
||||||
}
|
|
||||||
|
|
||||||
set ( filterName, filterValue ) {
|
|
||||||
// Throw error if it's not a valid filter name
|
|
||||||
if ( this.isQueryValue( filterName ) ) throw new Error(`${ filterName } is not a valid filter name`)
|
|
||||||
|
|
||||||
this.filters[ filterName ] = filterValue
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleFilter ( filterNameOrQueryValue, filterValue = null ) {
|
|
||||||
|
|
||||||
const fromString = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
|
||||||
|
|
||||||
const filterName = fromString.key
|
|
||||||
filterValue = filterValue || fromString.value
|
|
||||||
|
|
||||||
// If the filter is already set, remove it
|
|
||||||
if ( this.has( filterNameOrQueryValue ) ) {
|
|
||||||
this.remove( filterName )
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Throw error if filter value is not a string
|
|
||||||
if ( typeof filterValue !== 'string' ) {
|
|
||||||
throw new Error(`Filter value must be a string. Got ${ typeof filterValue }`)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set( filterName, filterValue )
|
|
||||||
}
|
|
||||||
|
|
||||||
has ( filterNameOrQueryValue ) {
|
|
||||||
|
|
||||||
const {
|
|
||||||
key : filterName,
|
|
||||||
value : filterValue = null
|
|
||||||
} = this.getFilterNameAndValueFromString( filterNameOrQueryValue )
|
|
||||||
|
|
||||||
// If this filter is a name and value, check if it's set
|
|
||||||
if ( isString( filterValue ) ) {
|
|
||||||
return !!this.filters[ filterName ] && this.filters[ filterName ] === filterValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return !!this.filters[ filterName ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -84,5 +84,19 @@ describe('StorkFilters', () => {
|
||||||
filters.setFromString('test_works_yes')
|
filters.setFromString('test_works_yes')
|
||||||
expect(filters.asQuery).toBe('test_works_yes')
|
expect(filters.asQuery).toBe('test_works_yes')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should map filters for Pagefind', () => {
|
||||||
|
const filters = new StorkFilters()
|
||||||
|
|
||||||
|
filters.setFromStringArray([
|
||||||
|
'status_native',
|
||||||
|
'category_system_tools'
|
||||||
|
])
|
||||||
|
|
||||||
|
expect(filters.asPagefindFilters).toEqual({
|
||||||
|
status: [ 'native' ],
|
||||||
|
category: [ 'system_tools' ]
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue