Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Improve queryToFilterData
Browse files Browse the repository at this point in the history
Discard other media parameters
  • Loading branch information
obulat committed Mar 18, 2022
1 parent 7f89a35 commit 1c25a5b
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/constants/filters.ts
Expand Up @@ -88,7 +88,7 @@ const filterCodesPerCategory = deepFreeze<Record<FilterCategory, string[]>>({
* }
*```
*/
const initFilters = () =>
export const initFilters = () =>
Object.entries(filterCodesPerCategory).reduce(
(acc, [filterType, filters]) => ({
...acc,
Expand Down
31 changes: 8 additions & 23 deletions src/stores/search.ts
Expand Up @@ -158,28 +158,15 @@ export const useSearchStore = defineStore('search', () => {
}

/**
* Replaces filters with the newFilterData parameter, making sure that
* audio/image provider filters are handled correctly.
* Replaces filters with the newFilterData object that was created using initial filters,
* and setting parameters from the search query to checked.
*
*
*
*/
function replaceFilters(newFilterData: Filters) {
const providerFilters: FilterCategory[] = [
'audioProviders',
'imageProviders',
]

allFilterCategories.forEach((filterCategory) => {
if (providerFilters.includes(filterCategory)) {
newFilterData[filterCategory].forEach((provider) => {
const idx = state.filters[filterCategory].findIndex(
(p) => p.code === provider.code
)
if (idx > -1) {
state.filters[filterCategory][idx].checked = provider.checked
}
})
} else {
state.filters[filterCategory] = newFilterData[filterCategory]
}
state.filters[filterCategory] = newFilterData[filterCategory]
})
}

Expand Down Expand Up @@ -281,10 +268,8 @@ export const useSearchStore = defineStore('search', () => {
if (item.code.includes('nd')) {
dependentFilters.push('modification')
}
return (
state.filters.licenseTypes.some(
(item) => dependentFilters.includes(item.code) && item.checked
)
return state.filters.licenseTypes.some(
(item) => dependentFilters.includes(item.code) && item.checked
)
}
}
Expand Down
1 change: 1 addition & 0 deletions src/utils/get-legacy-source-url.js
Expand Up @@ -40,6 +40,7 @@ export const legacySourceMap = {
Europeana: {
audio(search) {
let query = `${search.q} AND RIGHTS:*creative*` // search cc licensed works

if (search.filters && search.filters.commercial) {
if (search.filters.commercial) query = `${query} AND NOT RIGHTS:*nc*`
if (search.filters.modify) query = `${query} AND NOT RIGHTS:*nd*`
Expand Down
41 changes: 27 additions & 14 deletions src/utils/search-query-transform.ts
Expand Up @@ -104,6 +104,7 @@ export const queryStringToSearchType = (
* `source` - audioProviders/imageProviders
* `extensions` - audioExtensions/imageExtensions
* `categories` - audioCategories/imageCategories
*
* This function sets only filters that are possible for current
* media type. E.g., for queryString `search/audio?extensions=ogg`
* the `audioExtensions.ogg.checked` is set to true,
Expand Down Expand Up @@ -132,7 +133,13 @@ const getMediaTypeApiFilters = (
}

/**
* Converts the browser filter query string into the internal filter store data format
* Converts the browser filter query string into the internal filter store data format.
* For the API parameters that have the same name, but correspond to different filter categories
* (`differentFiltersWithSameApiParams`), only the filters that exist for the selected search type
* are used:
* E.g. when the search type is `audio`, `extension=jpg,mp3` sets the audioExtensions mp3.checked to true,
* and discards `jpg`.
*
* @param query - browser filter query
* @param searchType - search type determines which filters are applied
* @param defaultFilters - default filters for testing purposes
Expand Down Expand Up @@ -160,23 +167,29 @@ export const queryToFilterData = ({
]
filterTypes.forEach((filterDataKey) => {
if (differentFiltersWithSameApiParams.includes(filterDataKey)) {
const parameter = query[filterPropertyMappings[filterDataKey]]
if (parameter) {
filters[filterDataKey] = getMediaTypeApiFilters(
parameter,
filters[filterDataKey]
)
if (filterDataKey.startsWith(searchType)) {
const parameter = query[filterPropertyMappings[filterDataKey]]
if (parameter) {
filters[filterDataKey] = getMediaTypeApiFilters(
parameter,
filters[filterDataKey]
)
}
}
} else {
const queryDataKey = filterPropertyMappings[filterDataKey]
if (query[queryDataKey]) {
const filterValues = query[queryDataKey].split(',')
filterValues.forEach((val: string) => {
const idx = filters[filterDataKey].findIndex((f) => f.code === val)
if (idx >= 0) {
filters[filterDataKey][idx].checked = true
}
})
if (queryDataKey === 'mature' && query[queryDataKey].length > 0) {
filters[filterDataKey][0].checked = true
} else {
const filterValues = query[queryDataKey].split(',')
filterValues.forEach((val: string) => {
const idx = filters[filterDataKey].findIndex((f) => f.code === val)
if (idx >= 0) {
filters[filterDataKey][idx].checked = true
}
})
}
}
}
})
Expand Down
11 changes: 4 additions & 7 deletions test/unit/specs/stores/search-store.spec.js
Expand Up @@ -10,14 +10,9 @@ import {
supportedSearchTypes,
VIDEO,
} from '~/constants/media'
import { warn } from '~/utils/console.ts'

import { useSearchStore } from '~/stores/search'

jest.mock('~/utils/console', () => ({
warn: jest.fn(),
}))

describe('Search Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
Expand Down Expand Up @@ -375,10 +370,12 @@ describe('Search Store', () => {
const searchStore = useSearchStore()
const expectedFilters = searchStore.filters

searchStore.toggleFilter({ filterType: 'licenses' })
expect(warn).toHaveBeenCalledWith(
expect(() =>
searchStore.toggleFilter({ filterType: 'licenses' })
).toThrow(
'Cannot toggle filter of type licenses. Use code or codeIdx parameter'
)

expect(searchStore.filters).toEqual(expectedFilters)
})

Expand Down
54 changes: 53 additions & 1 deletion test/unit/specs/utils/search-query-transform.spec.js
Expand Up @@ -7,7 +7,7 @@ import {
} from '~/utils/search-query-transform'
import { AUDIO, IMAGE } from '~/constants/media'

import { filterData } from '~/constants/filters.ts'
import { filterData, initFilters } from '~/constants/filters.ts'

describe('searchQueryTransform', () => {
it('converts initial filters to query data', () => {
Expand Down Expand Up @@ -270,6 +270,58 @@ describe('searchQueryTransform', () => {
})
expect(result).toEqual(filters) // toEqual checks for value equality
})

it('queryToFilterData discards all image filters when search type is audio', () => {
const filters = initFilters()
filters.audioProviders = [
{ code: 'jamendo', checked: false },
{ code: 'wikimedia_audio', checked: false },
]
/**
* `categories` and `extension` parameter values will not be used because those
* codes (`photograph` and `svg`) only exist for the `imageCategories` and `imageExtensions`
* filter categories.
* `source` will only use the `wikimedia_audio` and `jamendo` parameters because they
* exist in `filters.audioProviders` list before. Other values either exist in
* `filters.imageProviders` list, or do not exist at all, so they are discarded.
* Valid filter items for categories that exist for all search types
* (`license`, `license_type`, `searchBy`, `mature`) are set to checked.
* Invalid filter items for valid categories (`nonexistent` in `license`)
* are discarded.
*/
const query = {
q: 'cat',
license: 'cc0,nonexistent',
license_type: 'commercial',
categories: 'photograph',
extension: 'svg',
duration: 'medium',
source: 'animaldiversity,wikimedia,nonexistent,wikimedia_audio,jamendo',
searchBy: 'creator',
mature: 'true',
}
const expectedFilters = clonedeep(filters)
const setChecked = (code, filterCategory) => {
const idx = expectedFilters[filterCategory].findIndex(
(item) => item.code === code
)
expectedFilters[filterCategory][idx].checked = true
}
setChecked('cc0', 'licenses')
setChecked('commercial', 'licenseTypes')
setChecked('medium', 'durations')
setChecked('creator', 'searchBy')
setChecked('mature', 'mature')
setChecked('jamendo', 'audioProviders')
setChecked('wikimedia_audio', 'audioProviders')

const result = queryToFilterData({
query,
searchType: AUDIO,
defaultFilters: filters,
})
expect(result).toEqual(expectedFilters) // toEqual checks for value equality
})
it('queryStringToQueryData', () => {
const expectedQueryData = {
license: 'cc0',
Expand Down

0 comments on commit 1c25a5b

Please sign in to comment.