@abi-software/map-side-bar 2.0.0-response.1 → 2.0.1
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/.eslintrc.js +12 -0
- package/.postcssrc.json +6 -0
- package/README.md +49 -27
- package/dist/favicon.ico +0 -0
- package/dist/map-side-bar.js +21143 -0
- package/dist/map-side-bar.umd.cjs +462 -0
- package/dist/style.css +1 -0
- package/package.json +48 -45
- package/src/App.vue +121 -55
- package/src/algolia/algolia.js +36 -9
- package/src/algolia/utils.js +45 -13
- package/src/assets/styles.scss +0 -1
- package/src/components/BadgesGroup.vue +56 -80
- package/src/components/DatasetCard.vue +143 -143
- package/src/components/EventBus.js +2 -2
- package/src/components/ImageGallery.vue +184 -228
- package/src/components/SearchFilters.vue +687 -296
- package/src/components/SearchHistory.vue +175 -0
- package/src/components/SideBar.vue +183 -97
- package/src/components/SidebarContent.vue +233 -241
- package/src/components/Tabs.vue +24 -24
- package/src/components.d.ts +35 -0
- package/src/main.js +6 -5
- package/src/mixins/S3Bucket.vue +6 -0
- package/vite.config.js +56 -0
- package/vuese-generator.js +65 -0
- package/babel.config.js +0 -14
- package/dist/demo.html +0 -10
- package/dist/fonts/element-icons.535877f5.woff +0 -0
- package/dist/fonts/element-icons.732389de.ttf +0 -0
- package/dist/img/missing-image.1878d8b8.svg +0 -1
- package/dist/map-side-bar.common.js +0 -7794
- package/dist/map-side-bar.common.js.map +0 -1
- package/dist/map-side-bar.css +0 -1
- package/dist/map-side-bar.umd.js +0 -7804
- package/dist/map-side-bar.umd.js.map +0 -1
- package/dist/map-side-bar.umd.min.js +0 -2
- package/dist/map-side-bar.umd.min.js.map +0 -1
- package/package-lock.json +0 -14428
- package/public/index.html +0 -17
- package/src/components/Cascader.vue +0 -49
- package/src/components/ContextCard.vue +0 -397
- package/src/components/hardcoded-context-info.js +0 -80
- package/src/demo/AlternateResponse.js +0 -141
- package/vue.config.js +0 -21
|
@@ -1,105 +1,146 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="filters">
|
|
3
|
-
<
|
|
3
|
+
<MapSvgSpriteColor />
|
|
4
|
+
<div class="cascader-tag" v-if="presentTags.length > 0">
|
|
5
|
+
<el-tag
|
|
6
|
+
class="ml-2"
|
|
7
|
+
type="info"
|
|
8
|
+
closable
|
|
9
|
+
@close="cascadeTagClose(presentTags[0])"
|
|
10
|
+
>
|
|
11
|
+
{{ presentTags[0] }}
|
|
12
|
+
</el-tag>
|
|
13
|
+
<el-popover
|
|
14
|
+
v-if="presentTags.length > 1"
|
|
15
|
+
placement="bottom-start"
|
|
16
|
+
:width="200"
|
|
17
|
+
trigger="hover"
|
|
18
|
+
>
|
|
19
|
+
<template #default>
|
|
20
|
+
<div class="el-tags-container">
|
|
21
|
+
<el-tag
|
|
22
|
+
v-for="(tag, i) in presentTags.slice(1)"
|
|
23
|
+
:key="i"
|
|
24
|
+
class="ml-2"
|
|
25
|
+
type="info"
|
|
26
|
+
closable
|
|
27
|
+
@close="cascadeTagClose(tag)"
|
|
28
|
+
>
|
|
29
|
+
{{ tag }}
|
|
30
|
+
</el-tag>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
<template #reference>
|
|
34
|
+
<div class="el-tags-container">
|
|
35
|
+
<el-tag
|
|
36
|
+
v-if="presentTags.length > 1"
|
|
37
|
+
class="ml-2"
|
|
38
|
+
type="info"
|
|
39
|
+
>
|
|
40
|
+
+{{ presentTags.length - 1 }}
|
|
41
|
+
</el-tag>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
44
|
+
</el-popover>
|
|
45
|
+
</div>
|
|
4
46
|
<transition name="el-zoom-in-top">
|
|
5
|
-
<span v-show="showFilters" class="search-filters transition-box">
|
|
6
|
-
<
|
|
47
|
+
<span v-show="showFilters" v-loading="!cascaderIsReady" class="search-filters transition-box">
|
|
48
|
+
<el-cascader
|
|
7
49
|
class="cascader"
|
|
8
50
|
ref="cascader"
|
|
9
51
|
v-model="cascadeSelected"
|
|
10
|
-
|
|
52
|
+
size="large"
|
|
53
|
+
placeholder=" "
|
|
11
54
|
:collapse-tags="true"
|
|
55
|
+
collapse-tags-tooltip
|
|
12
56
|
:options="options"
|
|
13
57
|
:props="props"
|
|
14
58
|
@change="cascadeEvent($event)"
|
|
15
59
|
@expand-change="cascadeExpandChange"
|
|
16
|
-
:show-all-levels="
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
<div v-if="showFiltersText" class="filter-default-value">
|
|
21
|
-
Filters
|
|
22
|
-
</div>
|
|
60
|
+
:show-all-levels="true"
|
|
61
|
+
popper-class="sidebar-cascader-popper"
|
|
62
|
+
/>
|
|
63
|
+
<div v-if="showFiltersText" class="filter-default-value">Filters</div>
|
|
23
64
|
<el-popover
|
|
24
65
|
title="How do filters work?"
|
|
25
66
|
width="250"
|
|
26
67
|
trigger="hover"
|
|
27
|
-
:append-to-body=false
|
|
68
|
+
:append-to-body="false"
|
|
28
69
|
popper-class="popover"
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
70
|
+
>
|
|
71
|
+
<template #reference>
|
|
72
|
+
<MapSvgIcon icon="help" class="help" />
|
|
73
|
+
</template>
|
|
74
|
+
<div>
|
|
75
|
+
<strong>Within categories:</strong> OR
|
|
76
|
+
<br />
|
|
34
77
|
example: 'heart' OR 'colon'
|
|
35
|
-
<br/>
|
|
36
|
-
<br/>
|
|
78
|
+
<br />
|
|
79
|
+
<br />
|
|
37
80
|
<strong>Between categories:</strong> AND
|
|
38
|
-
<br/>
|
|
81
|
+
<br />
|
|
39
82
|
example: 'rat' AND 'lung'
|
|
40
83
|
</div>
|
|
41
84
|
</el-popover>
|
|
42
|
-
|
|
43
85
|
</span>
|
|
44
86
|
</transition>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
87
|
+
<div class="dataset-shown">
|
|
88
|
+
<span class="dataset-results-feedback">{{ numberOfResultsText }}</span>
|
|
89
|
+
<el-select
|
|
90
|
+
class="number-shown-select"
|
|
91
|
+
v-model="numberShown"
|
|
92
|
+
placeholder="10"
|
|
93
|
+
@change="numberShownChanged($event)"
|
|
94
|
+
>
|
|
95
|
+
<el-option
|
|
96
|
+
v-for="item in numberDatasetsShown"
|
|
97
|
+
:key="item"
|
|
98
|
+
:label="item"
|
|
99
|
+
:value="item"
|
|
100
|
+
></el-option>
|
|
101
|
+
</el-select>
|
|
102
|
+
</div>
|
|
60
103
|
</div>
|
|
61
104
|
</template>
|
|
62
105
|
|
|
63
|
-
|
|
64
106
|
<script>
|
|
65
107
|
/* eslint-disable no-alert, no-console */
|
|
66
|
-
import
|
|
67
|
-
import {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
108
|
+
import { markRaw } from 'vue'
|
|
109
|
+
import {
|
|
110
|
+
ElOption as Option,
|
|
111
|
+
ElSelect as Select,
|
|
112
|
+
ElPopover as Popover,
|
|
113
|
+
ElCascader as Cascader,
|
|
114
|
+
} from 'element-plus'
|
|
115
|
+
import speciesMap from './species-map.js'
|
|
72
116
|
import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
|
|
117
|
+
import '@abi-software/svg-sprite/dist/style.css'
|
|
73
118
|
|
|
74
|
-
import {AlgoliaClient} from
|
|
75
|
-
import {facetPropPathMapping} from
|
|
76
|
-
|
|
77
|
-
locale.use(lang);
|
|
78
|
-
Vue.use(Option);
|
|
79
|
-
Vue.use(Select);
|
|
80
|
-
Vue.use(Popover)
|
|
119
|
+
import { AlgoliaClient } from '../algolia/algolia.js'
|
|
120
|
+
import { facetPropPathMapping } from '../algolia/utils.js'
|
|
81
121
|
|
|
82
122
|
const capitalise = function (txt) {
|
|
83
|
-
return txt.charAt(0).toUpperCase() + txt.slice(1)
|
|
84
|
-
}
|
|
123
|
+
return txt.charAt(0).toUpperCase() + txt.slice(1)
|
|
124
|
+
}
|
|
85
125
|
|
|
86
126
|
const convertReadableLabel = function (original) {
|
|
87
|
-
const name = original.toLowerCase()
|
|
127
|
+
const name = original.toLowerCase()
|
|
88
128
|
if (speciesMap[name]) {
|
|
89
|
-
return capitalise(speciesMap[name])
|
|
129
|
+
return capitalise(speciesMap[name])
|
|
90
130
|
} else {
|
|
91
|
-
return capitalise(name)
|
|
131
|
+
return capitalise(name)
|
|
92
132
|
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
133
|
+
}
|
|
96
134
|
|
|
97
135
|
export default {
|
|
98
|
-
name:
|
|
136
|
+
name: 'SearchFilters',
|
|
99
137
|
components: {
|
|
100
|
-
CustomCascader,
|
|
101
138
|
MapSvgIcon,
|
|
102
139
|
MapSvgSpriteColor,
|
|
140
|
+
Option,
|
|
141
|
+
Select,
|
|
142
|
+
Popover,
|
|
143
|
+
Cascader
|
|
103
144
|
},
|
|
104
145
|
props: {
|
|
105
146
|
/**
|
|
@@ -109,12 +150,7 @@ export default {
|
|
|
109
150
|
entry: Object,
|
|
110
151
|
envVars: {
|
|
111
152
|
type: Object,
|
|
112
|
-
default: ()=>{}
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
inject: {
|
|
116
|
-
'alternateSearch' : {
|
|
117
|
-
default: undefined,
|
|
153
|
+
default: () => {},
|
|
118
154
|
},
|
|
119
155
|
},
|
|
120
156
|
data: function () {
|
|
@@ -129,152 +165,377 @@ export default {
|
|
|
129
165
|
showFilters: true,
|
|
130
166
|
showFiltersText: true,
|
|
131
167
|
cascadeSelected: [],
|
|
132
|
-
cascadeSelectedWithBoolean: [],
|
|
168
|
+
cascadeSelectedWithBoolean: [],
|
|
133
169
|
numberShown: 10,
|
|
134
170
|
filters: [],
|
|
135
|
-
|
|
171
|
+
facets: ['Species', 'Gender', 'Organ', 'Datasets'],
|
|
172
|
+
numberDatasetsShown: ['10', '20', '50'],
|
|
136
173
|
props: { multiple: true },
|
|
137
174
|
options: [
|
|
138
175
|
{
|
|
139
|
-
value:
|
|
140
|
-
label:
|
|
176
|
+
value: 'Species',
|
|
177
|
+
label: 'Species',
|
|
141
178
|
children: [{}],
|
|
142
179
|
},
|
|
143
180
|
],
|
|
144
|
-
|
|
181
|
+
presentTags:[],
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
setup() {
|
|
185
|
+
const cascaderTags = markRaw({});
|
|
186
|
+
const correctnessCheck = markRaw({
|
|
187
|
+
term: new Set(),
|
|
188
|
+
facet: new Set(),
|
|
189
|
+
facet2: new Set()
|
|
190
|
+
});
|
|
191
|
+
return { cascaderTags, correctnessCheck }
|
|
145
192
|
},
|
|
146
193
|
computed: {
|
|
147
194
|
numberOfResultsText: function () {
|
|
148
|
-
return `${this.entry.numberOfHits} results | Showing
|
|
195
|
+
return `${this.entry.numberOfHits} results | Showing`
|
|
149
196
|
},
|
|
150
197
|
},
|
|
151
198
|
methods: {
|
|
152
|
-
createCascaderItemValue: function (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
// put "Show all" as first option
|
|
167
|
-
this.options[i].children.unshift({
|
|
168
|
-
value: this.createCascaderItemValue("Show all"),
|
|
169
|
-
label: "Show all",
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// populate second level of options
|
|
173
|
-
this.options[i].children.forEach((facetItem, j) => {
|
|
174
|
-
this.options[i].children[j].label = convertReadableLabel(
|
|
175
|
-
facetItem.label
|
|
176
|
-
);
|
|
177
|
-
this.options[i].children[j].value =
|
|
178
|
-
this.createCascaderItemValue(facet.label, facetItem.label);
|
|
179
|
-
});
|
|
180
|
-
});
|
|
199
|
+
createCascaderItemValue: function (
|
|
200
|
+
term,
|
|
201
|
+
facet1 = undefined,
|
|
202
|
+
facet2 = undefined
|
|
203
|
+
) {
|
|
204
|
+
let value = term
|
|
205
|
+
if (facet1) value = `${term}>${facet1}`
|
|
206
|
+
if (facet1 && facet2) value = `${term}>${facet1}>${facet2}`
|
|
207
|
+
if (!facet1 && facet2)
|
|
208
|
+
console.warn(
|
|
209
|
+
`Warning: ${facet2} provided without its parent, this will not be shown in the cascader`
|
|
210
|
+
)
|
|
211
|
+
return value
|
|
181
212
|
},
|
|
182
|
-
|
|
213
|
+
populateCascader: function () {
|
|
183
214
|
return new Promise((resolve) => {
|
|
184
215
|
// Algolia facet serach
|
|
185
|
-
this.algoliaClient
|
|
216
|
+
this.algoliaClient
|
|
217
|
+
.getAlgoliaFacets(facetPropPathMapping)
|
|
186
218
|
.then((data) => {
|
|
187
|
-
this.
|
|
219
|
+
this.facets = data
|
|
220
|
+
this.options = data
|
|
221
|
+
|
|
222
|
+
// create top level of options in cascader
|
|
223
|
+
this.options.forEach((facet, i) => {
|
|
224
|
+
this.options[i].total = this.countTotalFacet(facet)
|
|
225
|
+
|
|
226
|
+
this.options[i].label = convertReadableLabel(facet.label)
|
|
227
|
+
this.options[i].value = this.createCascaderItemValue(
|
|
228
|
+
facet.key,
|
|
229
|
+
undefined
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
// put "Show all" as first option
|
|
233
|
+
this.options[i].children.unshift({
|
|
234
|
+
value: this.createCascaderItemValue('Show all'),
|
|
235
|
+
label: 'Show all',
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
// populate second level of options
|
|
239
|
+
this.options[i].children.forEach((facetItem, j) => {
|
|
240
|
+
this.options[i].children[j].label = convertReadableLabel(
|
|
241
|
+
facetItem.label
|
|
242
|
+
)
|
|
243
|
+
this.options[i].children[j].value =
|
|
244
|
+
this.createCascaderItemValue(facet.label, facetItem.label)
|
|
245
|
+
if (
|
|
246
|
+
this.options[i].children[j].children &&
|
|
247
|
+
this.options[i].children[j].children.length > 0
|
|
248
|
+
) {
|
|
249
|
+
this.options[i].children[j].children.forEach((term, k) => {
|
|
250
|
+
this.options[i].children[j].children[k].label =
|
|
251
|
+
convertReadableLabel(term.label)
|
|
252
|
+
this.options[i].children[j].children[k].value =
|
|
253
|
+
this.createCascaderItemValue(
|
|
254
|
+
facet.label,
|
|
255
|
+
facetItem.label,
|
|
256
|
+
term.label
|
|
257
|
+
)
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
})
|
|
188
262
|
})
|
|
189
263
|
.finally(() => {
|
|
190
|
-
resolve()
|
|
191
|
-
})
|
|
192
|
-
})
|
|
193
|
-
},
|
|
194
|
-
setCascaderReady:function() {
|
|
195
|
-
this.cascaderIsReady = true;
|
|
196
|
-
this.checkShowAllBoxes();
|
|
197
|
-
this.setCascader(this.entry.filterFacets);
|
|
198
|
-
this.makeCascadeLabelsClickable();
|
|
199
|
-
this.$emit("cascaderReady");
|
|
264
|
+
resolve()
|
|
265
|
+
})
|
|
266
|
+
})
|
|
200
267
|
},
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
268
|
+
/**
|
|
269
|
+
* Create manual events when cascader tag is closed
|
|
270
|
+
*/
|
|
271
|
+
cascadeTagClose: function (tag) {
|
|
272
|
+
let manualEvent = []
|
|
273
|
+
|
|
274
|
+
Object.entries(this.cascaderTags).map((entry) => {
|
|
275
|
+
const term = entry[0], facet = entry[1] // Either "Array" or "Object", depends on the cascader item level
|
|
276
|
+
const option = this.options.filter((option) => option.label == term)[0]
|
|
277
|
+
const key = option.key
|
|
278
|
+
|
|
279
|
+
for (let index = 0; index < option.children.length; index++) {
|
|
280
|
+
const child = option.children[index]
|
|
281
|
+
const label = child.label, value = child.value
|
|
282
|
+
|
|
283
|
+
if (Array.isArray(facet)) {
|
|
284
|
+
// push "Show all" if there is no item checked
|
|
285
|
+
if (facet.length === 0 && label.toLowerCase() === "show all") {
|
|
286
|
+
manualEvent.push([key, value])
|
|
287
|
+
break
|
|
288
|
+
// push all checked items
|
|
289
|
+
} else if (label !== tag && facet.includes(label))
|
|
290
|
+
manualEvent.push([key, value])
|
|
291
|
+
} else {
|
|
292
|
+
// loop nested cascader items
|
|
293
|
+
Object.entries(facet).map((entry2) => {
|
|
294
|
+
const term2 = entry2[0], facet2 = entry2[1] // object key, object value
|
|
295
|
+
|
|
296
|
+
if (term2 === label) {
|
|
297
|
+
child.children.map((child2) => {
|
|
298
|
+
const label2 = child2.label, value2 = child2.value
|
|
299
|
+
// push all checked items
|
|
300
|
+
if (label2 !== tag && facet2.includes(label2))
|
|
301
|
+
manualEvent.push([key, value2])
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
this.cascadeEvent(manualEvent)
|
|
204
309
|
},
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Re-generate 'cascaderTags' and 'presentTags'
|
|
312
|
+
* Not able to avoid wrong facet at the moment
|
|
313
|
+
*/
|
|
314
|
+
tagsChangedCallback: function (event) {
|
|
315
|
+
if (this.correctnessCheck.term && this.correctnessCheck.facet && this.correctnessCheck.facet2) {
|
|
316
|
+
this.options.map((option) => {
|
|
317
|
+
this.correctnessCheck.term.add(option.label)
|
|
318
|
+
option.children.map((child) => {
|
|
319
|
+
this.correctnessCheck.facet.add(child.label)
|
|
320
|
+
if (option.label === 'Anatomical structure' && child.label !== 'Show all') {
|
|
321
|
+
child.children.map((child2) => {
|
|
322
|
+
this.correctnessCheck.facet2.add(child2.label)
|
|
323
|
+
})
|
|
324
|
+
}
|
|
325
|
+
})
|
|
326
|
+
})
|
|
212
327
|
}
|
|
328
|
+
|
|
329
|
+
this.cascaderTags = {}
|
|
330
|
+
this.presentTags = []
|
|
331
|
+
event.map((item) => {
|
|
332
|
+
const { facet, facet2, term } = item
|
|
333
|
+
if (this.correctnessCheck.term.has(term) && this.correctnessCheck.facet.has(facet)) {
|
|
334
|
+
if (facet2) {
|
|
335
|
+
if (this.correctnessCheck.facet2.has(facet2)) {
|
|
336
|
+
if (term in this.cascaderTags) {
|
|
337
|
+
if (facet in this.cascaderTags[term]) this.cascaderTags[term][facet].push(facet2)
|
|
338
|
+
else this.cascaderTags[term][facet] = [facet2]
|
|
339
|
+
} else {
|
|
340
|
+
this.cascaderTags[term] = {}
|
|
341
|
+
this.cascaderTags[term][facet] = [facet2]
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
// If 'cascaderTags' has key 'Anatomical structure',
|
|
346
|
+
// it's value type will be Object (because it has nested facets),
|
|
347
|
+
// in this case 'push' action will not available.
|
|
348
|
+
if (term in this.cascaderTags && term !== 'Anatomical structure')
|
|
349
|
+
this.cascaderTags[term].push(facet)
|
|
350
|
+
else {
|
|
351
|
+
if (facet.toLowerCase() !== "show all") this.cascaderTags[term] = [facet]
|
|
352
|
+
else this.cascaderTags[term] = []
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
Object.values(this.cascaderTags).map((value) => {
|
|
359
|
+
const extend = Array.isArray(value) ? value : Object.values(value).flat(1)
|
|
360
|
+
this.presentTags = [...this.presentTags, ...extend]
|
|
361
|
+
})
|
|
362
|
+
this.presentTags = [...new Set(this.presentTags)]
|
|
363
|
+
if (this.presentTags.length > 0) this.showFiltersText = false
|
|
364
|
+
else this.showFiltersText = true
|
|
213
365
|
},
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
366
|
+
/**
|
|
367
|
+
* Support for function 'showAllEventModifierForAutoCheckAll'
|
|
368
|
+
* Called in function 'populateCascader'
|
|
369
|
+
*/
|
|
370
|
+
countTotalFacet: function (facet) {
|
|
371
|
+
if (['anatomy.organ.category.name'].includes(facet.key)) {
|
|
372
|
+
const count = facet.children.reduce((total, num) => {
|
|
373
|
+
// The first 'total' will be an object
|
|
374
|
+
total = typeof total == 'number' ? total : total.children.length
|
|
375
|
+
return total + num.children.length
|
|
376
|
+
})
|
|
377
|
+
return count
|
|
219
378
|
}
|
|
379
|
+
return facet.children.length
|
|
380
|
+
},
|
|
381
|
+
/**
|
|
382
|
+
* When check/uncheck all child items, automatically check "Show all"
|
|
383
|
+
*/
|
|
384
|
+
showAllEventModifierForAutoCheckAll: function (event) {
|
|
385
|
+
const currentKeys = {}
|
|
386
|
+
event.map((e) => {
|
|
387
|
+
const eventKey = e[0]
|
|
388
|
+
if (eventKey in currentKeys) currentKeys[eventKey] += 1
|
|
389
|
+
else currentKeys[eventKey] = 1
|
|
390
|
+
})
|
|
391
|
+
this.options.map((option) => {
|
|
392
|
+
const key = option.key
|
|
393
|
+
const value = option.children.filter((child) => child.label === "Show all")[0].value
|
|
394
|
+
const total = option.total
|
|
395
|
+
// Remove events if all child items is checked
|
|
396
|
+
if (currentKeys[key] === total) {
|
|
397
|
+
event = event.filter((e) => e[0] !== option.key)
|
|
398
|
+
delete currentKeys[key]
|
|
399
|
+
}
|
|
400
|
+
// Add 'Show all' if facet type not exist in event
|
|
401
|
+
if (!(key in currentKeys)) event.unshift([key, value])
|
|
402
|
+
})
|
|
403
|
+
return event
|
|
220
404
|
},
|
|
221
405
|
// cascadeEvent: initiate searches based off cascader changes
|
|
222
|
-
cascadeEvent: function (
|
|
406
|
+
cascadeEvent: function (eventIn) {
|
|
407
|
+
let event = [...eventIn]
|
|
223
408
|
if (event) {
|
|
224
409
|
// Check for show all in selected cascade options
|
|
225
|
-
event = this.showAllEventModifier(event);
|
|
226
|
-
|
|
227
|
-
// Create results for the filter update
|
|
228
|
-
let filterKeys = event.filter( selection => selection !== undefined).map( fs => ({
|
|
229
|
-
facetPropPath: fs[0],
|
|
230
|
-
facet: fs[1].split(">")[1],
|
|
231
|
-
term: fs[1].split(">")[0],
|
|
232
|
-
AND: fs[2] // for setting the boolean
|
|
233
|
-
}))
|
|
234
410
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
411
|
+
event = this.showAllEventModifier(event)
|
|
412
|
+
|
|
413
|
+
event = this.showAllEventModifierForAutoCheckAll(event)
|
|
414
|
+
/**
|
|
415
|
+
* Move the new added event to the beginning
|
|
416
|
+
* Otherwise, cascader will show different expand item
|
|
417
|
+
*/
|
|
418
|
+
if (this.__expandItem__) {
|
|
419
|
+
let position = 0
|
|
420
|
+
if (this.__expandItem__.length > 1) {
|
|
421
|
+
position = 1
|
|
243
422
|
}
|
|
244
|
-
|
|
423
|
+
const current = event.filter((e) => e[position] == this.__expandItem__[position]);
|
|
424
|
+
const rest = event.filter((e) => e[position] !== this.__expandItem__[position]);
|
|
425
|
+
event = [...current, ...rest]
|
|
426
|
+
}
|
|
427
|
+
// Create results for the filter update
|
|
428
|
+
let filterKeys = event
|
|
429
|
+
.filter((selection) => selection !== undefined)
|
|
430
|
+
.map((fs) => {
|
|
431
|
+
let { hString, bString } =
|
|
432
|
+
this.findHierarachyStringAndBooleanString(fs)
|
|
433
|
+
let { facet, facet2, term } =
|
|
434
|
+
this.getFacetsFromHierarchyString(hString)
|
|
435
|
+
return {
|
|
436
|
+
facetPropPath: fs[0],
|
|
437
|
+
facet: facet,
|
|
438
|
+
facet2: facet2,
|
|
439
|
+
term: term,
|
|
440
|
+
AND: bString, // for setting the boolean
|
|
441
|
+
}
|
|
442
|
+
})
|
|
245
443
|
|
|
444
|
+
// Move results from arrays to object for use on scicrunch (note that we remove 'duplicate' as that is only needed for filter keys)
|
|
445
|
+
let filters = event
|
|
446
|
+
.filter((selection) => selection !== undefined)
|
|
447
|
+
.map((fs) => {
|
|
448
|
+
let facetSubPropPath = undefined
|
|
449
|
+
let propPath = fs[0].includes('duplicate')
|
|
450
|
+
? fs[0].split('duplicate')[0]
|
|
451
|
+
: fs[0]
|
|
452
|
+
let { hString, bString } =
|
|
453
|
+
this.findHierarachyStringAndBooleanString(fs)
|
|
454
|
+
let { facet, facet2, term } =
|
|
455
|
+
this.getFacetsFromHierarchyString(hString)
|
|
456
|
+
if (facet2) {
|
|
457
|
+
// We need to change the propPath if we are at the third level of the cascader
|
|
458
|
+
facet = facet2
|
|
459
|
+
facetSubPropPath = 'anatomy.organ.name'
|
|
460
|
+
}
|
|
461
|
+
return {
|
|
462
|
+
facetPropPath: propPath,
|
|
463
|
+
facet: facet,
|
|
464
|
+
term: term,
|
|
465
|
+
AND: bString, // for setting the boolean
|
|
466
|
+
facetSubPropPath: facetSubPropPath, // will be used for filters if we are at the third level of the cascader
|
|
467
|
+
}
|
|
468
|
+
})
|
|
469
|
+
|
|
246
470
|
this.$emit('loading', true) // let sidebarcontent wait for the requests
|
|
247
|
-
|
|
248
|
-
this
|
|
249
|
-
this.
|
|
250
|
-
this.makeCascadeLabelsClickable();
|
|
471
|
+
this.$emit('filterResults', filters) // emit filters for apps above sidebar
|
|
472
|
+
this.setCascader(filterKeys) //update our cascader v-model if we modified the event
|
|
473
|
+
this.cssMods() // update css for the cascader
|
|
251
474
|
}
|
|
252
475
|
},
|
|
476
|
+
//this fucntion is needed as we previously stored booleans in the array of event that
|
|
477
|
+
// are stored in the cascader
|
|
478
|
+
findHierarachyStringAndBooleanString(cascadeEventItem) {
|
|
479
|
+
let hString, bString
|
|
480
|
+
if (cascadeEventItem.length >= 3) {
|
|
481
|
+
if (cascadeEventItem[2] &&
|
|
482
|
+
(typeof cascadeEventItem[2] === 'string' ||
|
|
483
|
+
cascadeEventItem[2] instanceof String) &&
|
|
484
|
+
cascadeEventItem[2].split('>').length > 2) {
|
|
485
|
+
hString = cascadeEventItem[2]
|
|
486
|
+
bString = cascadeEventItem.length == 4 ? cascadeEventItem[3] : undefined
|
|
487
|
+
} else {
|
|
488
|
+
hString = cascadeEventItem[1]
|
|
489
|
+
bString = cascadeEventItem[2]
|
|
490
|
+
}
|
|
491
|
+
} else {
|
|
492
|
+
hString = cascadeEventItem[1]
|
|
493
|
+
bString = undefined
|
|
494
|
+
}
|
|
495
|
+
return { hString, bString }
|
|
496
|
+
},
|
|
497
|
+
// Splits the terms and facets from the string stored in the cascader
|
|
498
|
+
getFacetsFromHierarchyString(hierarchyString) {
|
|
499
|
+
let facet,
|
|
500
|
+
term,
|
|
501
|
+
facet2 = undefined
|
|
502
|
+
let fsSplit = hierarchyString.split('>')
|
|
503
|
+
if (fsSplit.length == 3) {
|
|
504
|
+
// if we are at the third level of the cascader
|
|
505
|
+
facet2 = fsSplit[2]
|
|
506
|
+
facet = fsSplit[1]
|
|
507
|
+
term = fsSplit[0]
|
|
508
|
+
} else {
|
|
509
|
+
facet = fsSplit[1]
|
|
510
|
+
term = fsSplit[0]
|
|
511
|
+
}
|
|
512
|
+
return { facet, facet2, term }
|
|
513
|
+
},
|
|
253
514
|
// showAllEventModifier: Modifies a cascade event to unclick all selections in category if "show all" is clicked. Also unchecks "Show all" if any secection is clicked
|
|
254
515
|
// *NOTE* Does NOT remove 'Show all' selections from showing in 'cascadeSelected'
|
|
255
516
|
showAllEventModifier: function (event) {
|
|
256
517
|
// check if show all is in the cascader checked option list
|
|
257
518
|
let hasShowAll = event
|
|
258
|
-
.map((ev) => (ev ? ev[1].toLowerCase().includes(
|
|
259
|
-
.includes(true)
|
|
519
|
+
.map((ev) => (ev ? ev[1].toLowerCase().includes('show all') : false))
|
|
520
|
+
.includes(true)
|
|
260
521
|
// remove all selected options below the show all if checked
|
|
261
522
|
if (hasShowAll) {
|
|
262
|
-
let modifiedEvent = []
|
|
263
|
-
let facetMaps = {}
|
|
523
|
+
let modifiedEvent = []
|
|
524
|
+
let facetMaps = {}
|
|
264
525
|
//catagorised different facet items
|
|
265
526
|
for (const i in event) {
|
|
266
|
-
if (facetMaps[event[i][0]] === undefined) facetMaps[event[i][0]] = []
|
|
267
|
-
facetMaps[event[i][0]].push(event[i])
|
|
527
|
+
if (facetMaps[event[i][0]] === undefined) facetMaps[event[i][0]] = []
|
|
528
|
+
facetMaps[event[i][0]].push(event[i])
|
|
268
529
|
}
|
|
269
530
|
// go through each facets
|
|
270
531
|
for (const facet in facetMaps) {
|
|
271
|
-
let showAll = undefined
|
|
532
|
+
let showAll = undefined
|
|
272
533
|
// Find the show all item if any
|
|
273
534
|
for (let i = facetMaps[facet].length - 1; i >= 0; i--) {
|
|
274
|
-
if (facetMaps[facet][i][1].toLowerCase().includes(
|
|
535
|
+
if (facetMaps[facet][i][1].toLowerCase().includes('show all')) {
|
|
275
536
|
//seperate the showAll item and the rest
|
|
276
|
-
showAll = facetMaps[facet].splice(i, 1)[0]
|
|
277
|
-
break
|
|
537
|
+
showAll = facetMaps[facet].splice(i, 1)[0]
|
|
538
|
+
break
|
|
278
539
|
}
|
|
279
540
|
}
|
|
280
541
|
if (showAll) {
|
|
@@ -282,14 +543,14 @@ export default {
|
|
|
282
543
|
//Unset the show all if it was present previously
|
|
283
544
|
//and there are other items
|
|
284
545
|
if (facetMaps[facet].length > 0)
|
|
285
|
-
modifiedEvent.push(...facetMaps[facet])
|
|
286
|
-
else modifiedEvent.push(showAll)
|
|
546
|
+
modifiedEvent.push(...facetMaps[facet])
|
|
547
|
+
else modifiedEvent.push(showAll)
|
|
287
548
|
} else {
|
|
288
549
|
//showAll is turned on
|
|
289
|
-
modifiedEvent.push(showAll)
|
|
550
|
+
modifiedEvent.push(showAll)
|
|
290
551
|
}
|
|
291
552
|
} else {
|
|
292
|
-
modifiedEvent.push(...facetMaps[facet])
|
|
553
|
+
modifiedEvent.push(...facetMaps[facet])
|
|
293
554
|
}
|
|
294
555
|
}
|
|
295
556
|
//Make sure the expanded item are sorted first.
|
|
@@ -297,41 +558,41 @@ export default {
|
|
|
297
558
|
if (this.__expandItem__) {
|
|
298
559
|
if (a[0] == this.__expandItem__) {
|
|
299
560
|
if (b[0] == this.__expandItem__) {
|
|
300
|
-
return 0
|
|
561
|
+
return 0
|
|
301
562
|
} else {
|
|
302
|
-
return -1
|
|
563
|
+
return -1
|
|
303
564
|
}
|
|
304
565
|
} else if (b[0] == this.__expandItem__) {
|
|
305
566
|
if (a[0] == this.__expandItem__) {
|
|
306
|
-
return 0
|
|
567
|
+
return 0
|
|
307
568
|
} else {
|
|
308
|
-
return 1
|
|
569
|
+
return 1
|
|
309
570
|
}
|
|
310
571
|
} else {
|
|
311
|
-
return 0
|
|
572
|
+
return 0
|
|
312
573
|
}
|
|
313
|
-
} else return 0
|
|
314
|
-
})
|
|
574
|
+
} else return 0
|
|
575
|
+
})
|
|
315
576
|
}
|
|
316
|
-
return event
|
|
577
|
+
return event
|
|
317
578
|
},
|
|
318
579
|
cascadeExpandChange: function (event) {
|
|
319
580
|
//work around as the expand item may change on modifying the cascade props
|
|
320
|
-
this.__expandItem__ = event
|
|
321
|
-
this.
|
|
581
|
+
this.__expandItem__ = event
|
|
582
|
+
this.cssMods()
|
|
322
583
|
},
|
|
323
584
|
numberShownChanged: function (event) {
|
|
324
|
-
this.$emit(
|
|
585
|
+
this.$emit('numberPerPage', parseInt(event))
|
|
325
586
|
},
|
|
326
587
|
updatePreviousShowAllChecked: function (options) {
|
|
327
588
|
//Reset the states
|
|
328
589
|
for (const facet in this.previousShowAllChecked) {
|
|
329
|
-
this.previousShowAllChecked[facet] = false
|
|
590
|
+
this.previousShowAllChecked[facet] = false
|
|
330
591
|
}
|
|
331
592
|
options.forEach((element) => {
|
|
332
|
-
if (element[1].toLowerCase().includes(
|
|
333
|
-
this.previousShowAllChecked[element[0]] = true
|
|
334
|
-
})
|
|
593
|
+
if (element[1].toLowerCase().includes('show all'))
|
|
594
|
+
this.previousShowAllChecked[element[0]] = true
|
|
595
|
+
})
|
|
335
596
|
},
|
|
336
597
|
// setCascader: Clears previous selections and takes in an array of facets to select: filterFacets
|
|
337
598
|
// facets are in the form:
|
|
@@ -344,48 +605,82 @@ export default {
|
|
|
344
605
|
setCascader: function (filterFacets) {
|
|
345
606
|
//Do not set the value unless it is ready
|
|
346
607
|
if (this.cascaderIsReady && filterFacets && filterFacets.length != 0) {
|
|
347
|
-
|
|
348
|
-
|
|
608
|
+
//An inner function only used by this function
|
|
609
|
+
const createFilter = (e) => {
|
|
610
|
+
let filters = [
|
|
349
611
|
e.facetPropPath,
|
|
350
612
|
this.createCascaderItemValue(capitalise(e.term), e.facet),
|
|
351
613
|
]
|
|
352
|
-
|
|
614
|
+
// Add the third level of the cascader if it exists
|
|
615
|
+
if (e.facet2) {
|
|
616
|
+
filters.push(
|
|
617
|
+
this.createCascaderItemValue(
|
|
618
|
+
capitalise(e.term),
|
|
619
|
+
e.facet,
|
|
620
|
+
e.facet2
|
|
621
|
+
)
|
|
622
|
+
)
|
|
623
|
+
}
|
|
624
|
+
return filters;
|
|
625
|
+
}
|
|
353
626
|
|
|
627
|
+
this.cascadeSelected = filterFacets.map((e) => {
|
|
628
|
+
let filters = createFilter(e)
|
|
629
|
+
return filters
|
|
630
|
+
})
|
|
631
|
+
|
|
354
632
|
// Unforttunately the cascader is very particular about it's v-model
|
|
355
633
|
// to get around this we create a clone of it and use this clone for adding our boolean information
|
|
356
|
-
this.cascadeSelectedWithBoolean= filterFacets.map(e => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
});
|
|
363
|
-
this.updatePreviousShowAllChecked(this.cascadeSelected);
|
|
634
|
+
this.cascadeSelectedWithBoolean = filterFacets.map((e) => {
|
|
635
|
+
let filters = createFilter(e)
|
|
636
|
+
filters.push(e.AND)
|
|
637
|
+
return filters
|
|
638
|
+
})
|
|
639
|
+
this.updatePreviousShowAllChecked(this.cascadeSelected)
|
|
364
640
|
}
|
|
641
|
+
this.tagsChangedCallback(filterFacets);
|
|
365
642
|
},
|
|
366
|
-
addFilter: function (
|
|
643
|
+
addFilter: function (filterToAdd) {
|
|
367
644
|
//Do not set the value unless it is ready
|
|
368
|
-
if (this.cascaderIsReady &&
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
this.cascadeSelected.
|
|
372
|
-
this.
|
|
645
|
+
if (this.cascaderIsReady && filterToAdd) {
|
|
646
|
+
let filter = this.validateAndConvertFilterToHierarchical(filterToAdd)
|
|
647
|
+
if (filter) {
|
|
648
|
+
this.cascadeSelected.filter((f) => f.term != filter.term)
|
|
649
|
+
this.cascadeSelected.push([
|
|
650
|
+
filter.facetPropPath,
|
|
651
|
+
this.createCascaderItemValue(filter.term, filter.facet),
|
|
652
|
+
this.createCascaderItemValue(
|
|
653
|
+
filter.term,
|
|
654
|
+
filter.facet,
|
|
655
|
+
filter.facet2
|
|
656
|
+
),
|
|
657
|
+
])
|
|
658
|
+
this.cascadeSelectedWithBoolean.push([
|
|
659
|
+
filter.facetPropPath,
|
|
660
|
+
this.createCascaderItemValue(filter.term, filter.facet),
|
|
661
|
+
this.createCascaderItemValue(
|
|
662
|
+
filter.term,
|
|
663
|
+
filter.facet,
|
|
664
|
+
filter.facet2
|
|
665
|
+
),
|
|
666
|
+
filter.AND,
|
|
667
|
+
])
|
|
373
668
|
// The 'AND' her is to set the boolean value when we search on the filters. It can be undefined without breaking anything
|
|
374
|
-
return true
|
|
669
|
+
return true
|
|
375
670
|
}
|
|
376
671
|
}
|
|
377
672
|
},
|
|
378
|
-
initiateSearch: function() {
|
|
673
|
+
initiateSearch: function () {
|
|
379
674
|
this.cascadeEvent(this.cascadeSelectedWithBoolean)
|
|
380
675
|
},
|
|
381
676
|
// checkShowAllBoxes: Checks each 'Show all' cascade option by using the setCascader function
|
|
382
|
-
checkShowAllBoxes: function(){
|
|
677
|
+
checkShowAllBoxes: function () {
|
|
383
678
|
this.setCascader(
|
|
384
|
-
this.options.map(option => {
|
|
679
|
+
this.options.map((option) => {
|
|
385
680
|
return {
|
|
386
681
|
facetPropPath: option.value,
|
|
387
682
|
term: option.label,
|
|
388
|
-
facet: 'Show all'
|
|
683
|
+
facet: 'Show all',
|
|
389
684
|
}
|
|
390
685
|
})
|
|
391
686
|
)
|
|
@@ -393,70 +688,140 @@ export default {
|
|
|
393
688
|
makeCascadeLabelsClickable: function () {
|
|
394
689
|
// Next tick allows the cascader menu to change
|
|
395
690
|
this.$nextTick(() => {
|
|
396
|
-
|
|
397
|
-
.querySelectorAll(
|
|
691
|
+
document
|
|
692
|
+
.querySelectorAll('.sidebar-cascader-popper .el-cascader-node__label')
|
|
398
693
|
.forEach((el) => {
|
|
399
694
|
// step through each cascade label
|
|
400
695
|
el.onclick = function () {
|
|
401
|
-
const checkbox = this.previousElementSibling
|
|
696
|
+
const checkbox = this.previousElementSibling
|
|
402
697
|
if (checkbox) {
|
|
403
|
-
if (!checkbox.parentElement.attributes[
|
|
698
|
+
if (!checkbox.parentElement.attributes['aria-owns']) {
|
|
404
699
|
// check if we are at the lowest level of cascader
|
|
405
|
-
this.previousElementSibling.click()
|
|
700
|
+
this.previousElementSibling.click() // Click the checkbox
|
|
406
701
|
}
|
|
407
702
|
}
|
|
408
|
-
}
|
|
409
|
-
})
|
|
410
|
-
})
|
|
703
|
+
}
|
|
704
|
+
})
|
|
705
|
+
})
|
|
411
706
|
},
|
|
412
|
-
|
|
413
|
-
|
|
707
|
+
|
|
708
|
+
cssMods: function () {
|
|
709
|
+
this.makeCascadeLabelsClickable()
|
|
710
|
+
this.removeTopLevelCascaderCheckboxes()
|
|
711
|
+
},
|
|
712
|
+
|
|
713
|
+
removeTopLevelCascaderCheckboxes: function () {
|
|
714
|
+
// Next tick allows the cascader menu to change
|
|
715
|
+
this.$nextTick(() => {
|
|
716
|
+
let cascadePanels = document.querySelectorAll(
|
|
717
|
+
'.sidebar-cascader-popper .el-cascader-menu__list'
|
|
718
|
+
)
|
|
719
|
+
// Hide the checkboxes on the first level of the cascader
|
|
720
|
+
cascadePanels[0]
|
|
721
|
+
.querySelectorAll('.el-checkbox__input')
|
|
722
|
+
.forEach((el) => (el.style.display = 'none'))
|
|
723
|
+
})
|
|
724
|
+
},
|
|
725
|
+
/*
|
|
726
|
+
* Given a filter, the function below returns the filter in the format of the cascader, returns false if facet is not found
|
|
414
727
|
*/
|
|
415
|
-
|
|
728
|
+
validateAndConvertFilterToHierarchical: function (filter) {
|
|
416
729
|
if (filter && filter.facet && filter.term) {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
|
|
422
|
-
|
|
730
|
+
if (filter.facet2) {
|
|
731
|
+
return filter // if it has a second term we will assume it is hierarchical and return it as is
|
|
732
|
+
} else {
|
|
733
|
+
for (const firstLayer of this.options) {
|
|
734
|
+
if (firstLayer.value === filter.facetPropPath) {
|
|
735
|
+
for (const secondLayer of firstLayer.children) {
|
|
736
|
+
if (secondLayer.label === filter.facet) {
|
|
737
|
+
// if we find a match on the second level, the filter will already be correct
|
|
738
|
+
return filter
|
|
739
|
+
} else {
|
|
740
|
+
if (secondLayer.children && secondLayer.children.length > 0) {
|
|
741
|
+
for (const thirdLayer of secondLayer.children) {
|
|
742
|
+
if (thirdLayer.label === filter.facet) {
|
|
743
|
+
// If we find a match on the third level, we need to switch facet1 to facet2
|
|
744
|
+
// and populate facet1 with its parents label.
|
|
745
|
+
filter.facet2 = thirdLayer.label
|
|
746
|
+
filter.facet = secondLayer.label
|
|
747
|
+
return filter
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
423
755
|
}
|
|
424
756
|
}
|
|
425
|
-
return false
|
|
757
|
+
return false
|
|
426
758
|
},
|
|
427
|
-
|
|
428
|
-
* Return a list of valid filers given a list of filters,
|
|
429
|
-
*/
|
|
430
|
-
getValidatedFilters: function (filters) {
|
|
759
|
+
getHierarchicalValidatedFilters: function (filters) {
|
|
431
760
|
if (filters) {
|
|
432
761
|
if (this.cascaderIsReady) {
|
|
433
|
-
const result = []
|
|
434
|
-
filters.forEach(filter => {
|
|
435
|
-
|
|
436
|
-
|
|
762
|
+
const result = []
|
|
763
|
+
filters.forEach((filter) => {
|
|
764
|
+
const validatedFilter =
|
|
765
|
+
this.validateAndConvertFilterToHierarchical(filter)
|
|
766
|
+
if (validatedFilter) {
|
|
767
|
+
result.push(validatedFilter)
|
|
437
768
|
}
|
|
438
|
-
})
|
|
439
|
-
return result
|
|
440
|
-
} else return filters
|
|
769
|
+
})
|
|
770
|
+
return result
|
|
771
|
+
} else return filters
|
|
441
772
|
}
|
|
442
|
-
return []
|
|
773
|
+
return []
|
|
443
774
|
},
|
|
444
775
|
},
|
|
445
776
|
mounted: function () {
|
|
446
|
-
|
|
447
|
-
this.
|
|
448
|
-
this.
|
|
449
|
-
|
|
450
|
-
|
|
777
|
+
this.algoliaClient = new AlgoliaClient(
|
|
778
|
+
this.envVars.ALGOLIA_ID,
|
|
779
|
+
this.envVars.ALGOLIA_KEY,
|
|
780
|
+
this.envVars.PENNSIEVE_API_LOCATION
|
|
781
|
+
)
|
|
782
|
+
this.algoliaClient.initIndex(this.envVars.ALGOLIA_INDEX)
|
|
783
|
+
this.populateCascader().then(() => {
|
|
784
|
+
this.cascaderIsReady = true
|
|
785
|
+
this.checkShowAllBoxes()
|
|
786
|
+
this.setCascader(this.entry.filterFacets)
|
|
787
|
+
this.cssMods()
|
|
788
|
+
this.$emit('cascaderReady')
|
|
789
|
+
})
|
|
451
790
|
},
|
|
452
|
-
}
|
|
791
|
+
}
|
|
453
792
|
</script>
|
|
454
793
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
794
|
+
<style lang="scss" scoped>
|
|
795
|
+
|
|
796
|
+
.cascader-tag {
|
|
797
|
+
position: absolute;
|
|
798
|
+
top: 110px;
|
|
799
|
+
left: 50px;
|
|
800
|
+
z-index: 1;
|
|
801
|
+
display: flex;
|
|
802
|
+
gap: 4px;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
.el-tags-container {
|
|
806
|
+
display: flex;
|
|
807
|
+
flex-wrap: wrap;
|
|
808
|
+
gap: 4px;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.el-tag {
|
|
812
|
+
.cascader-tag &,
|
|
813
|
+
.el-tags-container & {
|
|
814
|
+
font-family: 'Asap', sans-serif;
|
|
815
|
+
font-size: 12px;
|
|
816
|
+
color: #303133 !important;
|
|
817
|
+
background-color: #fff;
|
|
818
|
+
border-color: #dcdfe6 !important;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
:deep(.el-cascader__tags) {
|
|
823
|
+
display: none;
|
|
824
|
+
}
|
|
460
825
|
|
|
461
826
|
.filter-default-value {
|
|
462
827
|
pointer-events: none;
|
|
@@ -501,21 +866,16 @@ export default {
|
|
|
501
866
|
padding-bottom: 6px;
|
|
502
867
|
}
|
|
503
868
|
|
|
504
|
-
.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
margin-bottom: 2px !important;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
.cascader ::v-deep li[aria-owns*="cascader"] > .el-checkbox {
|
|
514
|
-
display: none;
|
|
869
|
+
.dataset-shown {
|
|
870
|
+
display: flex;
|
|
871
|
+
flex-direction: row;
|
|
872
|
+
float: right;
|
|
873
|
+
padding-bottom: 6px;
|
|
874
|
+
gap: 8px;
|
|
515
875
|
}
|
|
516
876
|
|
|
517
877
|
.dataset-results-feedback {
|
|
518
|
-
|
|
878
|
+
white-space:nowrap;
|
|
519
879
|
text-align: right;
|
|
520
880
|
color: rgb(48, 49, 51);
|
|
521
881
|
font-family: Asap;
|
|
@@ -528,82 +888,113 @@ export default {
|
|
|
528
888
|
position: relative;
|
|
529
889
|
float: left;
|
|
530
890
|
padding-right: 15px;
|
|
531
|
-
padding-bottom: 12px;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.number-shown-select {
|
|
535
|
-
float: right;
|
|
536
891
|
}
|
|
537
892
|
|
|
538
|
-
.number-shown-select
|
|
893
|
+
.number-shown-select :deep(.el-select__wrapper) {
|
|
539
894
|
width: 68px;
|
|
540
895
|
height: 40px;
|
|
541
896
|
color: rgb(48, 49, 51);
|
|
542
897
|
}
|
|
543
898
|
|
|
544
|
-
.
|
|
545
|
-
color:
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
.search-filters ::v-deep .el-cascader-node.in-active-path {
|
|
549
|
-
color: $app-primary-color;
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
.search-filters ::v-deep .el-checkbox__input.is-checked > .el-checkbox__inner {
|
|
553
|
-
background-color: $app-primary-color;
|
|
554
|
-
border-color: $app-primary-color;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
.cascader ::v-deep .el-cascader-menu:nth-child(2) .el-cascader-node:first-child {
|
|
558
|
-
border-bottom: 1px solid #e4e7ed;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
.cascader ::v-deep .el-cascader-node__label {
|
|
562
|
-
text-align: left;
|
|
899
|
+
.el-select-dropdown__item.is-selected {
|
|
900
|
+
color: #8300BF;
|
|
563
901
|
}
|
|
564
902
|
|
|
565
|
-
.filters
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
903
|
+
.filters :deep(.el-popover) {
|
|
904
|
+
background: #f3ecf6 !important;
|
|
905
|
+
border: 1px solid $app-primary-color;
|
|
906
|
+
border-radius: 4px;
|
|
907
|
+
color: #303133 !important;
|
|
908
|
+
font-size: 12px;
|
|
909
|
+
line-height: 18px;
|
|
572
910
|
}
|
|
573
911
|
|
|
574
|
-
.filters
|
|
912
|
+
.filters :deep(.el-popover[x-placement^='top'] .popper__arrow) {
|
|
575
913
|
border-top-color: $app-primary-color;
|
|
576
914
|
border-bottom-width: 0;
|
|
577
915
|
}
|
|
578
|
-
.filters
|
|
916
|
+
.filters :deep(.el-popover[x-placement^='top'] .popper__arrow::after) {
|
|
579
917
|
border-top-color: #f3ecf6;
|
|
580
918
|
border-bottom-width: 0;
|
|
581
919
|
}
|
|
582
920
|
|
|
583
|
-
.filters
|
|
921
|
+
.filters :deep(.el-popover[x-placement^='bottom'] .popper__arrow) {
|
|
584
922
|
border-top-width: 0;
|
|
585
923
|
border-bottom-color: $app-primary-color;
|
|
586
924
|
}
|
|
587
|
-
.filters
|
|
925
|
+
.filters :deep(.el-popover[x-placement^='bottom'] .popper__arrow::after) {
|
|
588
926
|
border-top-width: 0;
|
|
589
927
|
border-bottom-color: #f3ecf6;
|
|
590
928
|
}
|
|
591
929
|
|
|
592
|
-
.filters
|
|
930
|
+
.filters :deep(.el-popover[x-placement^='right'] .popper__arrow) {
|
|
593
931
|
border-right-color: $app-primary-color;
|
|
594
932
|
border-left-width: 0;
|
|
595
933
|
}
|
|
596
|
-
.filters
|
|
934
|
+
.filters :deep(.el-popover[x-placement^='right'] .popper__arrow::after) {
|
|
597
935
|
border-right-color: #f3ecf6;
|
|
598
936
|
border-left-width: 0;
|
|
599
937
|
}
|
|
600
938
|
|
|
601
|
-
.filters
|
|
939
|
+
.filters :deep(.el-popover[x-placement^='left'] .popper__arrow) {
|
|
602
940
|
border-right-width: 0;
|
|
603
941
|
border-left-color: $app-primary-color;
|
|
604
942
|
}
|
|
605
|
-
.filters
|
|
943
|
+
.filters :deep(.el-popover[x-placement^='left'] .popper__arrow::after) {
|
|
606
944
|
border-right-width: 0;
|
|
607
945
|
border-left-color: #f3ecf6;
|
|
608
946
|
}
|
|
609
947
|
</style>
|
|
948
|
+
|
|
949
|
+
<style lang="scss">
|
|
950
|
+
.sidebar-cascader-popper {
|
|
951
|
+
font-family: Asap;
|
|
952
|
+
font-size: 14px;
|
|
953
|
+
font-weight: 500;
|
|
954
|
+
font-stretch: normal;
|
|
955
|
+
font-style: normal;
|
|
956
|
+
line-height: normal;
|
|
957
|
+
letter-spacing: normal;
|
|
958
|
+
color: #292b66;
|
|
959
|
+
text-align: center;
|
|
960
|
+
padding-bottom: 6px;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
.sidebar-cascader-popper .el-cascader-node.is-active {
|
|
964
|
+
color: $app-primary-color;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
.sidebar-cascader-popper .el-cascader-node.in-active-path {
|
|
968
|
+
color: $app-primary-color;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.sidebar-cascader-popper .el-checkbox__input.is-checked > .el-checkbox__inner {
|
|
972
|
+
background-color: $app-primary-color;
|
|
973
|
+
border-color: $app-primary-color;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.sidebar-cascader-popper
|
|
977
|
+
.el-cascader-menu:nth-child(2)
|
|
978
|
+
.el-cascader-node:first-child {
|
|
979
|
+
border-bottom: 1px solid #e4e7ed;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.sidebar-cascader-popper .el-cascader-node__label {
|
|
983
|
+
text-align: left;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.sidebar-cascader-popper .el-cascder-panel {
|
|
987
|
+
max-height: 500px;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
.sidebar-cascader-popper .el-scrollbar__wrap {
|
|
991
|
+
overflow-x: hidden;
|
|
992
|
+
margin-bottom: 2px !important;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
.sidebar-cascader-popper .el-checkbox__input.is-checked .el-checkbox__inner,
|
|
996
|
+
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
|
997
|
+
background-color: $app-primary-color;
|
|
998
|
+
border-color: $app-primary-color;
|
|
999
|
+
}
|
|
1000
|
+
</style>
|