henry-search 1.0.30 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/HenrySearch.js +11870 -11801
- package/dist/HenrySearch.umd.cjs +105 -105
- package/package.json +1 -1
- package/src/components/Search.vue +9 -4
- package/src/components/SearchTab.vue +439 -426
|
@@ -1,470 +1,483 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import pSelect from '@vueform/multiselect'
|
|
28
|
-
import { truncate } from 'lodash';
|
|
2
|
+
import { useTemplateRef, ref, defineEmits } from 'vue'
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import {
|
|
5
|
+
AisClearRefinements,
|
|
6
|
+
AisCurrentRefinements,
|
|
7
|
+
AisHits,
|
|
8
|
+
AisInstantSearch,
|
|
9
|
+
AisMenuSelect,
|
|
10
|
+
AisPagination,
|
|
11
|
+
AisRangeInput,
|
|
12
|
+
AisRefinementList,
|
|
13
|
+
AisSearchBox,
|
|
14
|
+
AisStats
|
|
15
|
+
} from 'vue-instantsearch/vue3/es'
|
|
16
|
+
import TypesenseInstantSearchAdapter from 'typesense-instantsearch-adapter'
|
|
17
|
+
import { history as historyRouter } from 'instantsearch.js/es/lib/routers'
|
|
18
|
+
import { simple as simpleStateMapping } from 'instantsearch.js/es/lib/stateMappings'
|
|
19
|
+
import VueDatePicker from '@vuepic/vue-datepicker'
|
|
20
|
+
import { useDebounceFn } from "@vueuse/core"
|
|
21
|
+
|
|
22
|
+
import slugify from '../composables/slugify'
|
|
23
|
+
import PAccordion from './PAccordion.vue'
|
|
24
|
+
import formatDate from '../composables/formatDate'
|
|
25
|
+
import formatSearchTitle from '../composables/formatSearchTitle'
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
27
|
+
const props = defineProps({
|
|
28
|
+
indexName: {
|
|
29
|
+
type: String,
|
|
30
|
+
default: "archived_performances"
|
|
31
|
+
},
|
|
32
|
+
mainRefinements: {
|
|
33
|
+
type: Object,
|
|
34
|
+
require: true
|
|
35
|
+
},
|
|
36
|
+
addlRefinements: {
|
|
37
|
+
type: Object,
|
|
38
|
+
default: null
|
|
39
|
+
},
|
|
40
|
+
queryByFields: {
|
|
41
|
+
type: String,
|
|
42
|
+
default: "works, season, venue, event_types, notes, event_title, ensembles, conductors"
|
|
43
|
+
},
|
|
44
|
+
includeFields: {
|
|
45
|
+
type: String,
|
|
46
|
+
default: "works, season, venue, event_types, notes, event_title, orchestras, conductors"
|
|
47
|
+
},
|
|
48
|
+
sortField: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: "performance_date"
|
|
51
|
+
},
|
|
52
|
+
searchPlaceholder: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: "Search for performances..."
|
|
55
|
+
},
|
|
56
|
+
resultsTitle: {
|
|
57
|
+
type: String,
|
|
58
|
+
default: "Performances"
|
|
59
|
+
},
|
|
60
|
+
searchKey: {
|
|
61
|
+
type: String,
|
|
62
|
+
require: true
|
|
63
|
+
},
|
|
64
|
+
searchHost: {
|
|
65
|
+
type: String,
|
|
66
|
+
require: true
|
|
67
|
+
}
|
|
68
|
+
})
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const updateNow = ref(0)
|
|
70
|
+
const sortView = ref('Most Recent')
|
|
71
|
+
const showNumHits = ref(false)
|
|
72
|
+
const showByWorks = ref(false)
|
|
73
|
+
const workFilters = ref(null)
|
|
74
|
+
const currentQuery = ref(null)
|
|
75
|
+
const filtersClosed = ref(false)
|
|
76
|
+
const mobileFiltersClosed = ref(true)
|
|
82
77
|
|
|
83
|
-
|
|
84
|
-
router: historyRouter({
|
|
85
|
-
// Disable scroll restoration to prevent erratic behavior
|
|
86
|
-
writeDelay: 0,
|
|
87
|
-
parseURL({ qsModule, location }) {
|
|
88
|
-
const uiState = qsModule.parse(location.search.slice(1))
|
|
78
|
+
const updateNow = ref(0)
|
|
89
79
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
return uiState
|
|
93
|
-
},
|
|
94
|
-
createURL({ qsModule, location, routeState }) {
|
|
95
|
-
const { origin, pathname, hash } = location;
|
|
96
|
-
const indexState = routeState["instant_search"] || {};
|
|
97
|
-
const queryString = qsModule.stringify(routeState);
|
|
98
|
-
|
|
99
|
-
const uiState = qsModule.parse(location.search.slice(1))
|
|
100
|
-
sessionStorage.setItem('previousPageUrl', window.location.href)
|
|
101
|
-
|
|
102
|
-
updateSearchHistory(uiState)
|
|
80
|
+
const emit = defineEmits(['push'])
|
|
103
81
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
82
|
+
const routing = ref({
|
|
83
|
+
router: historyRouter({
|
|
84
|
+
// Disable scroll restoration to prevent erratic behavior
|
|
85
|
+
writeDelay: 0,
|
|
86
|
+
parseURL({ qsModule, location }) {
|
|
87
|
+
const uiState = qsModule.parse(location.search.slice(1))
|
|
107
88
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
89
|
+
updateStateRefs(uiState)
|
|
90
|
+
|
|
91
|
+
return uiState
|
|
92
|
+
},
|
|
93
|
+
createURL({ qsModule, location, routeState }) {
|
|
94
|
+
const { origin, pathname, hash } = location;
|
|
95
|
+
const indexState = routeState["instant_search"] || {};
|
|
96
|
+
const queryString = qsModule.stringify(routeState);
|
|
97
|
+
|
|
98
|
+
const uiState = qsModule.parse(location.search.slice(1))
|
|
99
|
+
sessionStorage.setItem('previousPageUrl', window.location.href)
|
|
100
|
+
|
|
101
|
+
updateSearchHistory(uiState)
|
|
114
102
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
nodes: [
|
|
121
|
-
{
|
|
122
|
-
host: props.searchHost,
|
|
123
|
-
path: '',
|
|
124
|
-
port: '443',
|
|
125
|
-
protocol: 'https',
|
|
103
|
+
// if (!indexState.query) {
|
|
104
|
+
// return `${origin}${pathname}${hash}`;
|
|
105
|
+
// }
|
|
106
|
+
|
|
107
|
+
return `${origin}${pathname}?${queryString}${hash}`;
|
|
126
108
|
},
|
|
127
|
-
|
|
128
|
-
|
|
109
|
+
}),
|
|
110
|
+
|
|
111
|
+
stateMapping: simpleStateMapping()
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const mainRefinementList = ref({})
|
|
115
|
+
const refinementSearchBoxes = ref([])
|
|
116
|
+
|
|
117
|
+
const server = {
|
|
118
|
+
connectionTimeoutSeconds: 20,
|
|
119
|
+
apiKey: props.searchKey,
|
|
120
|
+
nodes: [
|
|
121
|
+
{
|
|
122
|
+
host: props.searchHost,
|
|
123
|
+
path: '',
|
|
124
|
+
port: '443',
|
|
125
|
+
protocol: 'https',
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
cacheSearchResultsForSeconds: 0,
|
|
129
|
+
}
|
|
130
|
+
const adapter = new TypesenseInstantSearchAdapter({
|
|
131
|
+
server: server,
|
|
132
|
+
additionalSearchParameters: {
|
|
133
|
+
query_by: props.queryByFields,
|
|
134
|
+
sort_by: `${props.sortField}:desc`,
|
|
135
|
+
include_fields: props.includeFields,
|
|
136
|
+
highlight_fields: 'none'
|
|
137
|
+
},
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
const searchClient = adapter.searchClient
|
|
141
|
+
|
|
142
|
+
const toggleFilters = () => {
|
|
143
|
+
filtersClosed.value = !filtersClosed.value
|
|
144
|
+
const wrapper = document.getElementById(`${props.indexName}_filterRail`)
|
|
145
|
+
const allNestedElements = wrapper.querySelectorAll("*")
|
|
146
|
+
if (wrapper && wrapper.classList.contains('closed')) {
|
|
147
|
+
allNestedElements.forEach((el) => {
|
|
148
|
+
el.setAttribute("tabindex", -1)
|
|
149
|
+
})
|
|
150
|
+
} else {
|
|
151
|
+
allNestedElements.forEach((el) => {
|
|
152
|
+
el.removeAttribute("tabindex")
|
|
153
|
+
})
|
|
129
154
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const toggleFiltersMobile = () => {
|
|
159
|
+
mobileFiltersClosed.value = !mobileFiltersClosed.value
|
|
160
|
+
const wrapper = document.getElementById(`${props.indexName}_filterRail`)
|
|
161
|
+
const leftPane = document.getElementById(`${props.indexName}_eventsSearch__results`)
|
|
162
|
+
const containers = document.querySelectorAll('.container')
|
|
163
|
+
const otherHiddenEls = document.querySelectorAll('.mobileHide')
|
|
164
|
+
wrapper.classList.remove('closed')
|
|
165
|
+
wrapper.classList.toggle('openMobile')
|
|
166
|
+
leftPane.classList.toggle('openMobile')
|
|
167
|
+
containers.forEach((el) => {
|
|
168
|
+
if (el.style.display != "none") {
|
|
169
|
+
el.style.display = "none"
|
|
170
|
+
} else {
|
|
171
|
+
el.style.display = "grid"
|
|
172
|
+
}
|
|
173
|
+
|
|
138
174
|
})
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const toggleFilters = () => {
|
|
143
|
-
filtersClosed.value = !filtersClosed.value
|
|
144
|
-
const wrapper = document.getElementById(`${props.indexName}_filterRail`)
|
|
145
|
-
const allNestedElements = wrapper.querySelectorAll("*")
|
|
146
|
-
if (wrapper && wrapper.classList.contains('closed')) {
|
|
147
|
-
allNestedElements.forEach((el) => {
|
|
148
|
-
el.setAttribute("tabindex", -1)
|
|
149
|
-
})
|
|
175
|
+
otherHiddenEls.forEach((el) => {
|
|
176
|
+
if (el.style.display != "none") {
|
|
177
|
+
el.style.display = "none"
|
|
150
178
|
} else {
|
|
151
|
-
|
|
152
|
-
el.removeAttribute("tabindex")
|
|
153
|
-
})
|
|
179
|
+
el.style.display = "grid"
|
|
154
180
|
}
|
|
155
181
|
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
182
|
+
})
|
|
183
|
+
const detailsEls = document.querySelectorAll('details')
|
|
184
|
+
detailsEls.forEach((el) => {
|
|
185
|
+
const summary = el.querySelector('summary:first-of-type')
|
|
186
|
+
const summaryHeight = summary?.clientHeight
|
|
187
|
+
el.classList.add('-closing')
|
|
188
|
+
el.style.setProperty('--accordion-height-closed', `${summaryHeight}px`)
|
|
189
|
+
|
|
190
|
+
setTimeout(() => {
|
|
191
|
+
el.open = false
|
|
192
|
+
el.classList.remove('-closing')
|
|
193
|
+
el.style.setProperty('--accordion-height-closed', 'auto')
|
|
194
|
+
}, 0)
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const updateStateRefs = (uiState) => {
|
|
199
|
+
if (uiState && uiState[props.indexName]) {
|
|
200
|
+
currentQuery.value = uiState[props.indexName].query
|
|
201
|
+
if (currentQuery.value) {
|
|
202
|
+
if (sortView.value != 'Most Relevant') {
|
|
203
|
+
sortView.value = 'Most Relevant'
|
|
172
204
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (el.style.display != "none") {
|
|
177
|
-
el.style.display = "none"
|
|
178
|
-
} else {
|
|
179
|
-
el.style.display = "grid"
|
|
205
|
+
} else {
|
|
206
|
+
if (sortView.value != 'Most Recent') {
|
|
207
|
+
sortView.value = 'Most Recent'
|
|
180
208
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
el.classList.remove('-closing')
|
|
193
|
-
el.style.setProperty('--accordion-height-closed', 'auto')
|
|
194
|
-
}, 0)
|
|
195
|
-
})
|
|
209
|
+
}
|
|
210
|
+
setView()
|
|
211
|
+
showNumHits.value = currentQuery.value || uiState[props.indexName].refinementList || uiState[props.indexName].range || uiState[props.indexName].menu
|
|
212
|
+
workFilters.value = uiState[props.indexName].refinementList && Object.keys(uiState[props.indexName].refinementList).length !== 0 ? getWorkFilters(uiState[props.indexName].refinementList) : []
|
|
213
|
+
showByWorks.value = Object.keys(workFilters.value).length !== 0
|
|
214
|
+
|
|
215
|
+
// update search history
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
updateTitle(uiState[props.indexName])
|
|
219
|
+
|
|
196
220
|
}
|
|
221
|
+
}
|
|
197
222
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
223
|
+
const updateSearchHistory = (uiState) => {
|
|
224
|
+
let searchHistory = sessionStorage.getItem('searchHistory') ? JSON.parse(sessionStorage.getItem('searchHistory')) : []
|
|
225
|
+
// if only pagination, don't add to search history
|
|
226
|
+
if (!uiState[props.indexName]) {
|
|
227
|
+
return
|
|
228
|
+
}
|
|
229
|
+
if (uiState[props.indexName].page && !uiState[props.indexName].query && !uiState[props.indexName].refinementList && !uiState[props.indexName].menu) {
|
|
230
|
+
return
|
|
231
|
+
}
|
|
232
|
+
searchHistory = searchHistory.map((item) => {
|
|
233
|
+
// make sure that all queries aren't entered into the history as a user types each letter
|
|
234
|
+
if (uiState[props.indexName].query?.includes(item.query) && uiState[props.indexName].query != item.query) {
|
|
235
|
+
return {
|
|
236
|
+
date: new Date(),
|
|
237
|
+
uiState: uiState,
|
|
238
|
+
query: uiState[props.indexName].query,
|
|
239
|
+
link: document.location.href
|
|
209
240
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
workFilters.value = uiState[props.indexName].refinementList && Object.keys(uiState[props.indexName].refinementList).length !== 0 ? getWorkFilters(uiState[props.indexName].refinementList) : []
|
|
213
|
-
showByWorks.value = Object.keys(workFilters.value).length !== 0
|
|
214
|
-
|
|
215
|
-
// update search history
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
updateTitle(uiState[props.indexName])
|
|
219
|
-
|
|
241
|
+
} else {
|
|
242
|
+
return item
|
|
220
243
|
}
|
|
221
|
-
}
|
|
244
|
+
})
|
|
222
245
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (
|
|
246
|
+
//make sure we're not just adding pagination
|
|
247
|
+
let addState = true
|
|
248
|
+
searchHistory.forEach((item) => {
|
|
249
|
+
if (item.link.replace(/\&page=\d*/, "") == document.location.href.replace(/\&page=\d*/, "")) {
|
|
250
|
+
addState = false
|
|
227
251
|
return
|
|
228
252
|
}
|
|
229
|
-
if (
|
|
253
|
+
if (_.isEqual(item.uiState[props.indexName], uiState[props.indexName])) {
|
|
254
|
+
addState = false
|
|
230
255
|
return
|
|
231
256
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
return item
|
|
243
|
-
}
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if (addState && !(searchHistory.map((a) => a.link)).includes(document.location.href) &&
|
|
261
|
+
document.location.search != '') {
|
|
262
|
+
searchHistory.push({
|
|
263
|
+
date: new Date(),
|
|
264
|
+
uiState: uiState,
|
|
265
|
+
query: uiState[props.indexName].query,
|
|
266
|
+
link: document.location.href
|
|
244
267
|
})
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
sessionStorage.setItem('searchHistory', JSON.stringify(searchHistory))
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const getWorkFilters = (refinementList) => {
|
|
274
|
+
let returnFilters = {}
|
|
275
|
+
Object.entries(refinementList).forEach(([k, v]) => {
|
|
276
|
+
if (k.includes('works')) {
|
|
277
|
+
let workAttribute = k.substring(k.indexOf('works.') + 6, k.length)
|
|
278
|
+
const subFilter = {}
|
|
279
|
+
if (workAttribute.includes('.')) {
|
|
280
|
+
const workSubAttribute = workAttribute.substring(workAttribute.indexOf('.') + 1, workAttribute.length)
|
|
281
|
+
workAttribute = workAttribute.substring(0, workAttribute.indexOf('.'))
|
|
282
|
+
const subSubFilter = {}
|
|
283
|
+
subSubFilter[workSubAttribute] = v
|
|
284
|
+
subFilter[workAttribute] = subSubFilter
|
|
285
|
+
|
|
286
|
+
} else {
|
|
287
|
+
subFilter[workAttribute] = v
|
|
256
288
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (addState && !(searchHistory.map((a) => a.link)).includes(document.location.href) &&
|
|
261
|
-
document.location.search != '') {
|
|
262
|
-
searchHistory.push({
|
|
263
|
-
date: new Date(),
|
|
264
|
-
uiState: uiState,
|
|
265
|
-
query: uiState[props.indexName].query,
|
|
266
|
-
link: document.location.href
|
|
267
|
-
})
|
|
289
|
+
returnFilters = {...returnFilters, ...subFilter}
|
|
268
290
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
291
|
+
})
|
|
292
|
+
return returnFilters
|
|
293
|
+
}
|
|
272
294
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
let workAttribute = k.substring(k.indexOf('works.') + 6, k.length)
|
|
278
|
-
const subFilter = {}
|
|
279
|
-
if (workAttribute.includes('.')) {
|
|
280
|
-
const workSubAttribute = workAttribute.substring(workAttribute.indexOf('.') + 1, workAttribute.length)
|
|
281
|
-
workAttribute = workAttribute.substring(0, workAttribute.indexOf('.'))
|
|
282
|
-
const subSubFilter = {}
|
|
283
|
-
subSubFilter[workSubAttribute] = v
|
|
284
|
-
subFilter[workAttribute] = subSubFilter
|
|
285
|
-
|
|
286
|
-
} else {
|
|
287
|
-
subFilter[workAttribute] = v
|
|
288
|
-
}
|
|
289
|
-
returnFilters = {...returnFilters, ...subFilter}
|
|
290
|
-
}
|
|
291
|
-
})
|
|
292
|
-
return returnFilters
|
|
293
|
-
}
|
|
295
|
+
const onStateChange = ({ uiState, setUiState }) => {
|
|
296
|
+
updateStateRefs(uiState)
|
|
297
|
+
setUiState(uiState)
|
|
298
|
+
}
|
|
294
299
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
// console.log('before', new Date())
|
|
300
|
+
const updateTitle = (state) => {
|
|
301
|
+
document.title = "BSO HENRY | " + formatSearchTitle(state)
|
|
302
|
+
}
|
|
300
303
|
|
|
301
|
-
|
|
302
|
-
|
|
304
|
+
const setView = () => {
|
|
305
|
+
if (sortView.value == 'Oldest First') {
|
|
306
|
+
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
307
|
+
query_by: props.queryByFields,
|
|
308
|
+
sort_by: `${props.sortField}:asc`
|
|
309
|
+
}})
|
|
310
|
+
} else if (sortView.value == 'Most Relevant') {
|
|
311
|
+
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
312
|
+
query_by: props.queryByFields,
|
|
313
|
+
sort_by: `_text_match:desc,${props.sortField}:desc`
|
|
314
|
+
}})
|
|
315
|
+
} else {
|
|
316
|
+
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
317
|
+
query_by: props.queryByFields,
|
|
318
|
+
sort_by: `${props.sortField}:desc`
|
|
319
|
+
}})
|
|
303
320
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
321
|
+
updateNow.value++
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const formatRefinement = (refinement) => {
|
|
325
|
+
const attributeMap = {
|
|
326
|
+
"works.composers" : "Composer",
|
|
327
|
+
"works.title" : "Work",
|
|
328
|
+
"works.conductors" : "Conductor",
|
|
329
|
+
"ensembles" : "Orchestra",
|
|
330
|
+
"works.ensembles" : "Orchestra",
|
|
331
|
+
"works.artists.name" : "Artist",
|
|
332
|
+
"query" : "Keyword",
|
|
333
|
+
'works.artists.role': 'Instrument/Role',
|
|
334
|
+
'works.additional_creators.name': 'Additional Creator',
|
|
335
|
+
'works.additional_creators.role': 'Creator Role',
|
|
336
|
+
'season': 'Season',
|
|
337
|
+
'event_title': 'Event Title',
|
|
338
|
+
'event_types': 'Series',
|
|
339
|
+
'venue': 'Venue',
|
|
340
|
+
'works.commission': 'Commission',
|
|
341
|
+
'works.premiere': 'Premiere',
|
|
342
|
+
'location.city': 'City',
|
|
343
|
+
'location.country': 'Country',
|
|
344
|
+
'location.state': 'State',
|
|
345
|
+
'artist_name': 'Artist',
|
|
346
|
+
'artist_role': 'Instrument/Role',
|
|
347
|
+
'title': 'Work Title',
|
|
348
|
+
'composers': 'Composer',
|
|
349
|
+
'composer': 'Composer',
|
|
350
|
+
'media': 'Media',
|
|
351
|
+
'creators.name': 'Additional Creator',
|
|
352
|
+
'creators.role': 'Creator Role'
|
|
307
353
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
if (sortView.value == 'Oldest First') {
|
|
311
|
-
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
312
|
-
query_by: props.queryByFields,
|
|
313
|
-
sort_by: `${props.sortField}:asc`
|
|
314
|
-
}})
|
|
315
|
-
} else if (sortView.value == 'Most Relevant') {
|
|
316
|
-
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
317
|
-
query_by: props.queryByFields,
|
|
318
|
-
sort_by: `_text_match:desc,${props.sortField}:desc`
|
|
319
|
-
}})
|
|
320
|
-
} else {
|
|
321
|
-
adapter.updateConfiguration({...adapter.configuration, additionalSearchParameters: {
|
|
322
|
-
query_by: props.queryByFields,
|
|
323
|
-
sort_by: `${props.sortField}:desc`
|
|
324
|
-
}})
|
|
325
|
-
}
|
|
326
|
-
updateNow.value++
|
|
354
|
+
if (refinement.attribute == 'performance_date' || refinement.attribute == 'last_performance_date') {
|
|
355
|
+
return 'Date: ' + refinement.label[0] + ' ' + formatDate(refinement.value) + ' ×'
|
|
327
356
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
"works.title" : "Work",
|
|
333
|
-
"works.conductors" : "Conductor",
|
|
334
|
-
"ensembles" : "Orchestra",
|
|
335
|
-
"works.ensembles" : "Orchestra",
|
|
336
|
-
"works.artists.name" : "Artist",
|
|
337
|
-
"query" : "Keyword",
|
|
338
|
-
'works.artists.role': 'Instrument/Role',
|
|
339
|
-
'works.additional_creators.name': 'Additional Creator',
|
|
340
|
-
'works.additional_creators.role': 'Creator Role',
|
|
341
|
-
'season': 'Season',
|
|
342
|
-
'event_title': 'Event Title',
|
|
343
|
-
'event_types': 'Series',
|
|
344
|
-
'venue': 'Venue',
|
|
345
|
-
'works.commission': 'Commission',
|
|
346
|
-
'works.premiere': 'Premiere',
|
|
347
|
-
'location.city': 'City',
|
|
348
|
-
'location.country': 'Country',
|
|
349
|
-
'location.state': 'State',
|
|
350
|
-
'artist_name': 'Artist',
|
|
351
|
-
'artist_role': 'Instrument/Role',
|
|
352
|
-
'title': 'Work Title',
|
|
353
|
-
'composers': 'Composer',
|
|
354
|
-
'composer': 'Composer',
|
|
355
|
-
'media': 'Media',
|
|
356
|
-
'creators.name': 'Additional Creator',
|
|
357
|
-
'creators.role': 'Creator Role'
|
|
358
|
-
}
|
|
359
|
-
if (refinement.attribute == 'performance_date' || refinement.attribute == 'last_performance_date') {
|
|
360
|
-
return 'Date: ' + refinement.label[0] + ' ' + formatDate(refinement.value) + ' ×'
|
|
361
|
-
}
|
|
362
|
-
if (attributeMap[refinement.attribute]) {
|
|
363
|
-
return attributeMap[refinement.attribute] + ': ' + refinement.value + ' <span="activeFilters__removeIcon">×</span>'
|
|
364
|
-
} else {
|
|
365
|
-
return refinement.attribute + ': ' + refinement.value + ' ×'
|
|
366
|
-
}
|
|
367
|
-
|
|
357
|
+
if (attributeMap[refinement.attribute]) {
|
|
358
|
+
return attributeMap[refinement.attribute] + ': ' + refinement.value + ' <span="activeFilters__removeIcon">×</span>'
|
|
359
|
+
} else {
|
|
360
|
+
return refinement.attribute + ': ' + refinement.value + ' ×'
|
|
368
361
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
362
|
+
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const intersect = (filters, work) => {
|
|
366
|
+
let intersectKeys = Object.keys(filters).filter(k => Object.hasOwn(work, k))
|
|
367
|
+
let intersectArray = []
|
|
368
|
+
intersectKeys.forEach((key) => {
|
|
369
|
+
if (typeof filters[key] == 'object' && typeof work[key] == 'object') {
|
|
370
|
+
if (Array.isArray(work[key]) && Array.isArray(filters[key])) {
|
|
371
|
+
work[key].forEach((w) => {
|
|
372
|
+
filters[key].forEach((f) => {
|
|
373
|
+
if (w == f) {
|
|
374
|
+
intersectArray.push(w)
|
|
375
|
+
}
|
|
382
376
|
})
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
})
|
|
396
|
-
}
|
|
397
|
-
} else if (filters[key].includes(work[key])) {
|
|
398
|
-
intersectArray.push(work[key])
|
|
377
|
+
})
|
|
378
|
+
} else if (Array.isArray(work[key])) {
|
|
379
|
+
Object.entries(filters[key])?.forEach(([k1, v1]) => {
|
|
380
|
+
work[key]?.forEach((workvalue) => {
|
|
381
|
+
if (typeof workvalue == 'object') {
|
|
382
|
+
Object.entries(workvalue).forEach(([k2, v2]) => {
|
|
383
|
+
if (k1 == k2 && v1.includes(v2)) {
|
|
384
|
+
intersectArray.push(workvalue[k2])
|
|
385
|
+
}
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
})
|
|
390
|
+
})
|
|
399
391
|
}
|
|
400
|
-
})
|
|
401
|
-
|
|
392
|
+
} else if (filters[key].includes(work[key])) {
|
|
393
|
+
intersectArray.push(work[key])
|
|
394
|
+
}
|
|
395
|
+
})
|
|
396
|
+
return intersectArray
|
|
402
397
|
|
|
403
|
-
|
|
398
|
+
}
|
|
404
399
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
400
|
+
const filterItems = (items) => {
|
|
401
|
+
if (!items.length) {
|
|
402
|
+
emit('push', {event: 'no_results', data: currentQuery.value})
|
|
403
|
+
}
|
|
404
|
+
if (showByWorks.value && props.indexName == "dev_henry_perfs") {
|
|
405
|
+
|
|
406
|
+
let returnItems = items
|
|
407
|
+
let itemIndex = 0
|
|
408
|
+
returnItems.forEach((item) => {
|
|
409
|
+
let shownWorks = []
|
|
410
|
+
item?.works?.forEach((work) => {
|
|
411
|
+
let workAdded = false
|
|
412
|
+
if (intersect(workFilters.value, work)?.length) {
|
|
413
|
+
shownWorks.push(work)
|
|
414
|
+
workAdded = true
|
|
415
|
+
}
|
|
416
|
+
if (!workAdded && currentQuery.value && JSON.stringify(work).includes(currentQuery.value)) {
|
|
417
|
+
shownWorks.push(work)
|
|
418
|
+
}
|
|
424
419
|
})
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
420
|
+
returnItems[itemIndex].works = shownWorks
|
|
421
|
+
itemIndex++
|
|
422
|
+
})
|
|
423
|
+
return returnItems
|
|
424
|
+
} else {
|
|
425
|
+
return items
|
|
429
426
|
}
|
|
427
|
+
}
|
|
430
428
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
429
|
+
const refineAndScroll = (refine, params, scrollId) => {
|
|
430
|
+
refine(params)
|
|
431
|
+
document.getElementById(scrollId).scrollIntoView()
|
|
432
|
+
}
|
|
435
433
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
434
|
+
const toMinValue = (value, range) => {
|
|
435
|
+
return typeof value.min === "number" && value.min != 0 ? value.min * 1000 : range.min * 1000
|
|
436
|
+
}
|
|
439
437
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
438
|
+
const toMaxValue = (value, range) => {
|
|
439
|
+
return typeof value.max === "number" && value.max != 0 ? value.max * 1000 : range.max * 1000
|
|
440
|
+
}
|
|
443
441
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const formatMaxValue = (maxValue, maxRange) => {
|
|
449
|
-
return typeof maxValue === "number" && maxValue !== null && maxValue !== maxRange ? maxValue : maxRange
|
|
450
|
-
}
|
|
442
|
+
const formatMinValue = (minValue, minRange) => {
|
|
443
|
+
return typeof minValue === "number" && minValue !== null && minValue !== minRange ? minValue : minRange
|
|
444
|
+
}
|
|
451
445
|
|
|
446
|
+
const formatMaxValue = (maxValue, maxRange) => {
|
|
447
|
+
return typeof maxValue === "number" && maxValue !== null && maxValue !== maxRange ? maxValue : maxRange
|
|
448
|
+
}
|
|
452
449
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
} else {
|
|
459
|
-
return '-gray'
|
|
460
|
-
}
|
|
461
|
-
} catch (e) {
|
|
450
|
+
|
|
451
|
+
const getHeadingStyle = (attribute) => {
|
|
452
|
+
if (mainRefinementList.value && typeof(mainRefinementList.value[attribute]) !== 'undefined' && mainRefinementList.value[attribute]) {
|
|
453
|
+
try {
|
|
454
|
+
if (mainRefinementList.value[attribute] && typeof(mainRefinementList.value[attribute].items) !== 'undefined' && mainRefinementList.value[attribute].items.length) {
|
|
462
455
|
return ''
|
|
456
|
+
} else {
|
|
457
|
+
return '-gray'
|
|
463
458
|
}
|
|
459
|
+
} catch (e) {
|
|
460
|
+
return ''
|
|
464
461
|
}
|
|
465
|
-
return ''
|
|
466
462
|
}
|
|
463
|
+
return ''
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const clearRefinementSearches = () => {
|
|
467
|
+
if (refinementSearchBoxes.value && refinementSearchBoxes.value.length) {
|
|
468
|
+
refinementSearchBoxes.value.forEach((el) => {
|
|
469
|
+
if (el) {
|
|
470
|
+
el.value = ""
|
|
471
|
+
}
|
|
472
|
+
})
|
|
473
|
+
}
|
|
474
|
+
}
|
|
467
475
|
|
|
476
|
+
const emitQuery = useDebounceFn(() => {
|
|
477
|
+
if (currentQuery.value) {
|
|
478
|
+
emit('push', {event: 'search_form', data: currentQuery.value})
|
|
479
|
+
}
|
|
480
|
+
}, 1000)
|
|
468
481
|
|
|
469
482
|
</script>
|
|
470
483
|
|
|
@@ -493,7 +506,7 @@ import { truncate } from 'lodash';
|
|
|
493
506
|
id="searchbox"
|
|
494
507
|
type="search"
|
|
495
508
|
:value="currentRefinement"
|
|
496
|
-
@input="refine($event.currentTarget.value)"
|
|
509
|
+
@input="refine($event.currentTarget.value);emitQuery()"
|
|
497
510
|
:placeholder="props.searchPlaceholder"
|
|
498
511
|
>
|
|
499
512
|
|
|
@@ -606,7 +619,7 @@ import { truncate } from 'lodash';
|
|
|
606
619
|
<div class="ais-SearchBox searchBox -filter">
|
|
607
620
|
<label class="label__hidden" :for="refinement.attribute">{{ refinement.placeholder }}</label>
|
|
608
621
|
<form class="searchBox__form" @submit="$event.preventDefault()" @reset="searchForItems('')">
|
|
609
|
-
<input type="text" :id="refinement.attribute" @input="searchForItems($event.currentTarget.value)" :placeholder="refinement.placeholder" class="ais-SearchBox-input -filter" v-if="!refinement.hideSearch">
|
|
622
|
+
<input type="text" :id="refinement.attribute" :ref="(el) => refinementSearchBoxes.push(el)" @input="searchForItems($event.currentTarget.value)" :placeholder="refinement.placeholder" class="ais-SearchBox-input -filter" v-if="!refinement.hideSearch">
|
|
610
623
|
<button v-if="isFromSearch"
|
|
611
624
|
class="ais-SearchBox-reset"
|
|
612
625
|
type="reset"
|
|
@@ -628,7 +641,7 @@ import { truncate } from 'lodash';
|
|
|
628
641
|
:id="slugify(refinement.title + ' ' + item.value)"
|
|
629
642
|
:value="item.value"
|
|
630
643
|
:checked="item.isRefined"
|
|
631
|
-
@click="refine(item.value)" />
|
|
644
|
+
@click="refine(item.value);$emit('push', {event: item.isRefined ? 'unfilter' : 'search_filter', filter_category: refinement.title, filter_value : item.value})" />
|
|
632
645
|
<label :for="slugify(refinement.title + ' ' + item.value)">{{ item.value }}</label><span class="eventsSearch__refinementCount">{{ item.count }}</span>
|
|
633
646
|
</label>
|
|
634
647
|
</div>
|
|
@@ -676,7 +689,7 @@ import { truncate } from 'lodash';
|
|
|
676
689
|
<div class="checkBoxes">
|
|
677
690
|
<span class="checkBoxes__alert" v-if="!items.length"><span class="checkBoxes__alertIcon">!</span>No matches found</span>
|
|
678
691
|
<label v-for="item in items" class="checkBoxes__boxLabel" :for="slugify(refinement.title + ' ' + item.value)">
|
|
679
|
-
<input :class="`checkbox ${item.isRefined ? '-boxChecked' : ''}`" type="checkbox" :id="slugify(refinement.title + ' ' + item.value)" :value="item.value" :checked="item.isRefined" @click="refine(item.value)">
|
|
692
|
+
<input :class="`checkbox ${item.isRefined ? '-boxChecked' : ''}`" type="checkbox" :id="slugify(refinement.title + ' ' + item.value)" :value="item.value" :checked="item.isRefined" @click="refine(item.value);$emit('push', {event: item.isRefined ? 'unfilter' : 'filter', type: refinement.title, data: item.value})">
|
|
680
693
|
<label :for="slugify(refinement.title + ' ' + item.value)">{{ item.value }}</label><span class="eventsSearch__refinementCount">{{ item.count }}</span>
|
|
681
694
|
</label>
|
|
682
695
|
</div>
|
|
@@ -696,7 +709,7 @@ import { truncate } from 'lodash';
|
|
|
696
709
|
<div class="accordion__content">
|
|
697
710
|
<ais-menu-select v-if="refinement.type == 'location'" :attribute="'location.country'" operator="and" :limit="100" >
|
|
698
711
|
<template v-slot="{ items, refine }">
|
|
699
|
-
<select @change="refine($event.currentTarget.value)">
|
|
712
|
+
<select @change="refine($event.currentTarget.value);$emit('push', {event: 'filter', type: 'location.country', data: $event.currentTarget.value})">
|
|
700
713
|
<option value="">Select Country</option>
|
|
701
714
|
<option v-for="item in items" :selected="item.isRefined" :key="item.value" :value="item.value">{{ item.label }}</option>
|
|
702
715
|
</select>
|
|
@@ -704,7 +717,7 @@ import { truncate } from 'lodash';
|
|
|
704
717
|
</ais-menu-select>
|
|
705
718
|
<ais-menu-select v-if="refinement.type == 'location'" :attribute="'location.state'" operator="and" :limit="100">
|
|
706
719
|
<template v-slot="{ items, refine }">
|
|
707
|
-
<select @change="refine($event.currentTarget.value)">
|
|
720
|
+
<select @change="refine($event.currentTarget.value);$emit('push', {event: 'filter', type: 'location.state', data: $event.currentTarget.value})">
|
|
708
721
|
<option value="">Select State</option>
|
|
709
722
|
<option v-for="item in items" :selected="item.isRefined" :key="item.value" :value="item.value">{{ item.label }}</option>
|
|
710
723
|
</select>
|
|
@@ -712,7 +725,7 @@ import { truncate } from 'lodash';
|
|
|
712
725
|
</ais-menu-select>
|
|
713
726
|
<ais-menu-select placeholder="Select City" v-if="refinement.type == 'location'" :attribute="'location.city'" operator="and" :limit="100">
|
|
714
727
|
<template v-slot="{ items, refine }">
|
|
715
|
-
<select @change="refine($event.currentTarget.value)">
|
|
728
|
+
<select @change="refine($event.currentTarget.value);$emit('push', {event: 'filter', type: 'location.city', data: $event.currentTarget.value})">
|
|
716
729
|
<option value="">Select City</option>
|
|
717
730
|
<option v-for="item in items" :selected="item.isRefined" :key="item.value" :value="item.value">{{ item.label }}</option>
|
|
718
731
|
</select>
|
|
@@ -730,7 +743,7 @@ import { truncate } from 'lodash';
|
|
|
730
743
|
<template v-slot="{ refine, createURL }">
|
|
731
744
|
<a
|
|
732
745
|
:href="createURL()"
|
|
733
|
-
@click.prevent="refine"
|
|
746
|
+
@click.prevent="refine();clearRefinementSearches()"
|
|
734
747
|
>
|
|
735
748
|
<button @click="toggleFiltersMobile()" class="filterClear">Clear</button>
|
|
736
749
|
|
|
@@ -802,7 +815,7 @@ import { truncate } from 'lodash';
|
|
|
802
815
|
</div>
|
|
803
816
|
<div v-if="showNumHits" class="resultActions__buttons">
|
|
804
817
|
<div class="toolTip">
|
|
805
|
-
<a onclick="navigator.clipboard.writeText(window.location.href);">
|
|
818
|
+
<a onclick="navigator.clipboard.writeText(window.location.href);" id="shareActions__icon">
|
|
806
819
|
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="resultActions__icon" outline="black">
|
|
807
820
|
<!-- <circle cx="12" cy="12" stroke="none" r="12"/> -->
|
|
808
821
|
<path d="M11.3334 12.5068C11.5012 12.7435 11.7153 12.9393 11.9611 13.081C12.2069 13.2227 12.4788 13.307 12.7582 13.3281C13.0376 13.3492 13.3181 13.3066 13.5806 13.2034C13.8431 13.1001 14.0814 12.9384 14.2795 12.7294L15.4516 11.4928C15.8075 11.1041 16.0044 10.5835 16 10.0431C15.9955 9.50271 15.7901 8.98578 15.4278 8.60365C15.0656 8.22153 14.5756 8.00477 14.0634 8.00008C13.5511 7.99538 13.0577 8.20312 12.6892 8.57855L12.0171 9.28341" stroke-linecap="round" stroke-linejoin="round"/>
|
|
@@ -812,7 +825,7 @@ import { truncate } from 'lodash';
|
|
|
812
825
|
<span class="toolTip__text">Copy Link</span>
|
|
813
826
|
</div>
|
|
814
827
|
<div class="toolTip">
|
|
815
|
-
<a :href="`/actions/csvexport/csv-export${ routing.router.getLocation().search }`" >
|
|
828
|
+
<a :href="`/actions/csvexport/csv-export${ routing.router.getLocation().search }`" id="downloadActions__icon">
|
|
816
829
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="resultActions__icon">
|
|
817
830
|
<!-- <circle cx="12" cy="12" r="12" stroke="none "/> -->
|
|
818
831
|
<path d="M15.9785 17.41L9.00049 17.41" stroke-linecap="round" stroke-linejoin="round"/>
|
|
@@ -834,7 +847,7 @@ import { truncate } from 'lodash';
|
|
|
834
847
|
<template v-slot="{ canRefine, refine, createURL }">
|
|
835
848
|
<a
|
|
836
849
|
:href="createURL()"
|
|
837
|
-
@click.prevent="refine"
|
|
850
|
+
@click.prevent="refine();clearRefinementSearches()"
|
|
838
851
|
v-if="canRefine"
|
|
839
852
|
class="activeFilters__clearFilters"
|
|
840
853
|
>
|