@abi-software/map-side-bar 1.3.0 → 1.3.3
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/LICENSE +201 -201
- package/README.md +53 -53
- package/babel.config.js +14 -14
- package/dist/map-side-bar.common.js +293 -212
- package/dist/map-side-bar.common.js.map +1 -1
- package/dist/map-side-bar.css +1 -1
- package/dist/map-side-bar.umd.js +293 -212
- package/dist/map-side-bar.umd.js.map +1 -1
- package/dist/map-side-bar.umd.min.js +1 -1
- package/dist/map-side-bar.umd.min.js.map +1 -1
- package/package-lock.json +13698 -13698
- package/package.json +65 -65
- package/public/index.html +17 -17
- package/scaffold_context_info.json +30 -0
- package/src/App.vue +137 -133
- package/src/algolia/algolia.js +173 -127
- package/src/algolia/utils.js +60 -51
- package/src/components/BadgesGroup.vue +141 -141
- package/src/components/Cascader.vue +49 -49
- package/src/components/ContextCard.vue +265 -240
- package/src/components/DatasetCard.vue +325 -324
- package/src/components/EventBus.js +3 -3
- package/src/components/ImageGallery.vue +505 -502
- package/src/components/SearchFilters.vue +557 -557
- package/src/components/SideBar.vue +245 -239
- package/src/components/SidebarContent.vue +482 -476
- package/src/components/Tabs.vue +78 -78
- package/src/components/hardcoded-context-info.js +79 -79
- package/src/components/index.js +8 -8
- package/src/components/processFilters.js +22 -0
- package/src/components/species-map.js +8 -8
- package/src/main.js +8 -8
- package/static.json +6 -6
- package/vue.config.js +11 -11
|
@@ -1,557 +1,557 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="filters">
|
|
3
|
-
<map-svg-sprite-color />
|
|
4
|
-
<transition name="el-zoom-in-top">
|
|
5
|
-
<span v-show="showFilters" class="search-filters transition-box">
|
|
6
|
-
<custom-cascader
|
|
7
|
-
class="cascader"
|
|
8
|
-
ref="cascader"
|
|
9
|
-
v-model="cascadeSelected"
|
|
10
|
-
placeholder
|
|
11
|
-
:collapse-tags="true"
|
|
12
|
-
:options="options"
|
|
13
|
-
:props="props"
|
|
14
|
-
@change="cascadeEvent($event)"
|
|
15
|
-
@expand-change="cascadeExpandChange"
|
|
16
|
-
:show-all-levels="false"
|
|
17
|
-
:append-to-body="false"
|
|
18
|
-
@tags-changed="tagsChangedCallback"
|
|
19
|
-
></custom-cascader>
|
|
20
|
-
<div v-if="showFiltersText" class="filter-default-value">
|
|
21
|
-
Filters
|
|
22
|
-
</div>
|
|
23
|
-
<el-popover
|
|
24
|
-
title="How do filters work?"
|
|
25
|
-
width="250"
|
|
26
|
-
trigger="hover"
|
|
27
|
-
:append-to-body=false
|
|
28
|
-
popper-class="popover"
|
|
29
|
-
>
|
|
30
|
-
<map-svg-icon slot="reference" icon="help" class="help"/>
|
|
31
|
-
<div >
|
|
32
|
-
<strong>Within categories:</strong> OR
|
|
33
|
-
<br/>
|
|
34
|
-
example: 'heart' OR 'colon'
|
|
35
|
-
<br/>
|
|
36
|
-
<br/>
|
|
37
|
-
<strong>Between categories:</strong> AND
|
|
38
|
-
<br/>
|
|
39
|
-
example: 'rat' AND 'lung'
|
|
40
|
-
</div>
|
|
41
|
-
</el-popover>
|
|
42
|
-
|
|
43
|
-
</span>
|
|
44
|
-
</transition>
|
|
45
|
-
|
|
46
|
-
<el-select
|
|
47
|
-
class="number-shown-select"
|
|
48
|
-
v-model="numberShown"
|
|
49
|
-
placeholder="10"
|
|
50
|
-
@change="numberShownChanged($event)"
|
|
51
|
-
>
|
|
52
|
-
<el-option
|
|
53
|
-
v-for="item in numberDatasetsShown"
|
|
54
|
-
:key="item"
|
|
55
|
-
:label="item"
|
|
56
|
-
:value="item"
|
|
57
|
-
></el-option>
|
|
58
|
-
</el-select>
|
|
59
|
-
<span class="dataset-results-feedback">{{ this.numberOfResultsText }}</span>
|
|
60
|
-
</div>
|
|
61
|
-
</template>
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
<script>
|
|
65
|
-
/* eslint-disable no-alert, no-console */
|
|
66
|
-
import Vue from "vue";
|
|
67
|
-
import { Option, Select, Popover } from "element-ui";
|
|
68
|
-
import CustomCascader from "./Cascader";
|
|
69
|
-
import lang from "element-ui/lib/locale/lang/en";
|
|
70
|
-
import locale from "element-ui/lib/locale";
|
|
71
|
-
import speciesMap from "./species-map";
|
|
72
|
-
import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
|
|
73
|
-
|
|
74
|
-
import {AlgoliaClient} from "../algolia/algolia.js";
|
|
75
|
-
import {
|
|
76
|
-
|
|
77
|
-
locale.use(lang);
|
|
78
|
-
Vue.use(Option);
|
|
79
|
-
Vue.use(Select);
|
|
80
|
-
Vue.use(Popover)
|
|
81
|
-
|
|
82
|
-
const capitalise = function (txt) {
|
|
83
|
-
return txt.charAt(0).toUpperCase() + txt.slice(1);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const convertReadableLabel = function (original) {
|
|
87
|
-
const name = original.toLowerCase();
|
|
88
|
-
if (speciesMap[name]) {
|
|
89
|
-
return capitalise(speciesMap[name]);
|
|
90
|
-
} else {
|
|
91
|
-
return capitalise(name);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export default {
|
|
96
|
-
name: "SearchFilters",
|
|
97
|
-
components: {
|
|
98
|
-
CustomCascader,
|
|
99
|
-
MapSvgIcon,
|
|
100
|
-
MapSvgSpriteColor,
|
|
101
|
-
},
|
|
102
|
-
props: {
|
|
103
|
-
/**
|
|
104
|
-
* Object containing information for
|
|
105
|
-
* the required viewing.
|
|
106
|
-
*/
|
|
107
|
-
entry: Object,
|
|
108
|
-
envVars: {
|
|
109
|
-
type: Object,
|
|
110
|
-
default: ()=>{}
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
data: function () {
|
|
114
|
-
return {
|
|
115
|
-
cascaderIsReady: false,
|
|
116
|
-
previousShowAllChecked: {
|
|
117
|
-
species: false,
|
|
118
|
-
gender: false,
|
|
119
|
-
organ: false,
|
|
120
|
-
datasets: false,
|
|
121
|
-
},
|
|
122
|
-
showFilters: true,
|
|
123
|
-
showFiltersText: true,
|
|
124
|
-
cascadeSelected: [],
|
|
125
|
-
numberShown: 10,
|
|
126
|
-
filters: [],
|
|
127
|
-
facets: ["Species", "Gender", "Organ", "Datasets"],
|
|
128
|
-
numberDatasetsShown: ["10", "20", "50"],
|
|
129
|
-
props: { multiple: true },
|
|
130
|
-
options: [
|
|
131
|
-
{
|
|
132
|
-
value: "Species",
|
|
133
|
-
label: "Species",
|
|
134
|
-
children: [{}],
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
};
|
|
138
|
-
},
|
|
139
|
-
computed: {
|
|
140
|
-
numberOfResultsText: function () {
|
|
141
|
-
return `${this.entry.numberOfHits} results | Showing`;
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
methods: {
|
|
145
|
-
createCascaderItemValue: function (term, facet) {
|
|
146
|
-
if (facet) return term + "/" + facet;
|
|
147
|
-
else return term;
|
|
148
|
-
},
|
|
149
|
-
populateCascader: function () {
|
|
150
|
-
return new Promise((resolve) => {
|
|
151
|
-
// Algolia facet serach
|
|
152
|
-
this.algoliaClient.getAlgoliaFacets(
|
|
153
|
-
.then((data) => {
|
|
154
|
-
this.facets = data;
|
|
155
|
-
this.options = data;
|
|
156
|
-
|
|
157
|
-
// create top level of options in cascader
|
|
158
|
-
this.options.forEach((facet, i) => {
|
|
159
|
-
this.options[i].label = convertReadableLabel(facet.label);
|
|
160
|
-
this.options[i].value = this.createCascaderItemValue(
|
|
161
|
-
facet.key,
|
|
162
|
-
undefined
|
|
163
|
-
);
|
|
164
|
-
|
|
165
|
-
// put "Show all" as first option
|
|
166
|
-
this.options[i].children.unshift({
|
|
167
|
-
value: this.createCascaderItemValue("Show all"),
|
|
168
|
-
label: "Show all",
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// populate second level of options
|
|
172
|
-
this.options[i].children.forEach((facetItem, j) => {
|
|
173
|
-
this.options[i].children[j].label = convertReadableLabel(
|
|
174
|
-
facetItem.label
|
|
175
|
-
);
|
|
176
|
-
this.options[i].children[j].value =
|
|
177
|
-
this.createCascaderItemValue(facet.label, facetItem.label);
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
this.createDataTypeFacet()
|
|
181
|
-
})
|
|
182
|
-
.finally(() => {
|
|
183
|
-
resolve();
|
|
184
|
-
});
|
|
185
|
-
});
|
|
186
|
-
},
|
|
187
|
-
tagsChangedCallback: function (presentTags) {
|
|
188
|
-
if (presentTags.length > 0) {
|
|
189
|
-
this.showFiltersText = false;
|
|
190
|
-
} else {
|
|
191
|
-
this.showFiltersText = true;
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
// cascadeEvent: initiate searches based off cascader changes
|
|
195
|
-
cascadeEvent: function (event) {
|
|
196
|
-
if (event) {
|
|
197
|
-
// Check for show all in selected cascade options
|
|
198
|
-
event = this.showAllEventModifier(event);
|
|
199
|
-
|
|
200
|
-
// Create results for the filter update
|
|
201
|
-
let filterKeys = event.filter( selection => selection !== undefined).map( fs => ({
|
|
202
|
-
facetPropPath: fs[0],
|
|
203
|
-
facet: fs[1].split("/")[1],
|
|
204
|
-
term: fs[1].split("/")[0],
|
|
205
|
-
}))
|
|
206
|
-
|
|
207
|
-
// Move results from arrays to object for use on scicrunch (note that we remove 'duplicate' as that is only needed for filter keys)
|
|
208
|
-
let filters = event.filter( selection => selection !== undefined).map( fs => {
|
|
209
|
-
let propPath = fs[0].includes('duplicate') ? fs[0].split('duplicate')[0] : fs[0]
|
|
210
|
-
return {
|
|
211
|
-
facetPropPath: propPath,
|
|
212
|
-
facet: fs[1].split("/")[1],
|
|
213
|
-
term: fs[1].split("/")[0],
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
this.$emit('loading', true) // let sidebarcontent wait for the requests
|
|
219
|
-
|
|
220
|
-
this.$emit("filterResults", filters); // emit filters for apps above sidebar
|
|
221
|
-
this.setCascader(filterKeys); //update our cascader v-model if we modified the event
|
|
222
|
-
this.makeCascadeLabelsClickable();
|
|
223
|
-
}
|
|
224
|
-
},
|
|
225
|
-
// showAllEventModifier: Modifies a cascade event to unlick all selections in category if "show all" is clicked. Also unchecks "Show all" if any secection is clicked
|
|
226
|
-
// *NOTE* Does NOT remove 'Show all' selections from showing in 'cascadeSelected'
|
|
227
|
-
showAllEventModifier: function (event) {
|
|
228
|
-
// check if show all is in the cascader checked option list
|
|
229
|
-
let hasShowAll = event
|
|
230
|
-
.map((ev) => (ev ? ev[1].toLowerCase().includes("show all") : false))
|
|
231
|
-
.includes(true);
|
|
232
|
-
// remove all selected options below the show all if checked
|
|
233
|
-
if (hasShowAll) {
|
|
234
|
-
let modifiedEvent = [];
|
|
235
|
-
let facetMaps = {};
|
|
236
|
-
//catagorised different facet items
|
|
237
|
-
for (const i in event) {
|
|
238
|
-
if (facetMaps[event[i][0]] === undefined) facetMaps[event[i][0]] = [];
|
|
239
|
-
facetMaps[event[i][0]].push(event[i]);
|
|
240
|
-
}
|
|
241
|
-
// go through each facets
|
|
242
|
-
for (const facet in facetMaps) {
|
|
243
|
-
let showAll = undefined;
|
|
244
|
-
// Find the show all item if any
|
|
245
|
-
for (let i = facetMaps[facet].length - 1; i >= 0; i--) {
|
|
246
|
-
if (facetMaps[facet][i][1].toLowerCase().includes("show all")) {
|
|
247
|
-
//seperate the showAll item and the rest
|
|
248
|
-
showAll = facetMaps[facet].splice(i, 1)[0];
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
if (showAll) {
|
|
253
|
-
if (this.previousShowAllChecked[facet]) {
|
|
254
|
-
//Unset the show all if it was present previously
|
|
255
|
-
//and there are other items
|
|
256
|
-
if (facetMaps[facet].length > 0)
|
|
257
|
-
modifiedEvent.push(...facetMaps[facet]);
|
|
258
|
-
else modifiedEvent.push(showAll);
|
|
259
|
-
} else {
|
|
260
|
-
//showAll is turned on
|
|
261
|
-
modifiedEvent.push(showAll);
|
|
262
|
-
}
|
|
263
|
-
} else {
|
|
264
|
-
modifiedEvent.push(...facetMaps[facet]);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
//Make sure the expanded item are sorted first.
|
|
268
|
-
return modifiedEvent.sort((a, b) => {
|
|
269
|
-
if (this.__expandItem__) {
|
|
270
|
-
if (a[0] == this.__expandItem__) {
|
|
271
|
-
if (b[0] == this.__expandItem__) {
|
|
272
|
-
return 0;
|
|
273
|
-
} else {
|
|
274
|
-
return -1;
|
|
275
|
-
}
|
|
276
|
-
} else if (b[0] == this.__expandItem__) {
|
|
277
|
-
if (a[0] == this.__expandItem__) {
|
|
278
|
-
return 0;
|
|
279
|
-
} else {
|
|
280
|
-
return 1;
|
|
281
|
-
}
|
|
282
|
-
} else {
|
|
283
|
-
return 0;
|
|
284
|
-
}
|
|
285
|
-
} else return 0;
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
return event;
|
|
289
|
-
},
|
|
290
|
-
createDataTypeFacet: function(){
|
|
291
|
-
let dataFacet = {...this.facets[2]} // copy the 'Experiemental approach' facet
|
|
292
|
-
let count = this.facets.at(-1).id // get the last id count
|
|
293
|
-
|
|
294
|
-
// Step through the children that are valid data types, switch thier values
|
|
295
|
-
let newChildren = dataFacet.children.filter( el=> {
|
|
296
|
-
if (el.label === 'Scaffold' || el.label === 'Simulation' || el.label === 'Show all'){
|
|
297
|
-
el.key = el.label
|
|
298
|
-
el.id = count
|
|
299
|
-
el.value = el.value.replace('Experimental approach', 'Data type')
|
|
300
|
-
count++
|
|
301
|
-
return el
|
|
302
|
-
}
|
|
303
|
-
})
|
|
304
|
-
dataFacet.id = count
|
|
305
|
-
dataFacet.key = 'Data type'
|
|
306
|
-
// Add 'duplicate' so that the key is unique. This is removed in the cascade event for filtering
|
|
307
|
-
dataFacet.value += 'duplicate'
|
|
308
|
-
dataFacet.children = newChildren
|
|
309
|
-
dataFacet.label = 'Data type'
|
|
310
|
-
this.facets.push(dataFacet)
|
|
311
|
-
},
|
|
312
|
-
cascadeExpandChange: function (event) {
|
|
313
|
-
//work around as the expand item may change on modifying the cascade props
|
|
314
|
-
this.__expandItem__ = event;
|
|
315
|
-
this.makeCascadeLabelsClickable();
|
|
316
|
-
},
|
|
317
|
-
numberShownChanged: function (event) {
|
|
318
|
-
this.$emit("numberPerPage", parseInt(event));
|
|
319
|
-
},
|
|
320
|
-
updatePreviousShowAllChecked: function (options) {
|
|
321
|
-
//Reset the states
|
|
322
|
-
for (const facet in this.previousShowAllChecked) {
|
|
323
|
-
this.previousShowAllChecked[facet] = false;
|
|
324
|
-
}
|
|
325
|
-
options.forEach((element) => {
|
|
326
|
-
if (element[1].toLowerCase().includes("show all"))
|
|
327
|
-
this.previousShowAllChecked[element[0]] = true;
|
|
328
|
-
});
|
|
329
|
-
},
|
|
330
|
-
// setCascader: Clears previous selections and takes in an array of facets to select: filterFacets
|
|
331
|
-
// facets are in the form:
|
|
332
|
-
// {
|
|
333
|
-
// facetPropPath: 'anatomy.organ.name',
|
|
334
|
-
// term: 'Sex',
|
|
335
|
-
// facet: 'Male'
|
|
336
|
-
// }
|
|
337
|
-
setCascader: function (filterFacets) {
|
|
338
|
-
//Do not set the value unless it is ready
|
|
339
|
-
if (this.cascaderIsReady && filterFacets && filterFacets.length != 0) {
|
|
340
|
-
this.cascadeSelected = filterFacets.map(e => {
|
|
341
|
-
return [
|
|
342
|
-
e.facetPropPath,
|
|
343
|
-
this.createCascaderItemValue(capitalise(e.term), e.facet),
|
|
344
|
-
]
|
|
345
|
-
});
|
|
346
|
-
this.updatePreviousShowAllChecked(this.cascadeSelected);
|
|
347
|
-
}
|
|
348
|
-
},
|
|
349
|
-
addFilter: function (filter) {
|
|
350
|
-
//Do not set the value unless it is ready
|
|
351
|
-
if (this.cascaderIsReady && filter) {
|
|
352
|
-
this.cascadeSelected.filter(f=>f.term != filter.term)
|
|
353
|
-
this.cascadeSelected.push([filter.facetPropPath, this.createCascaderItemValue(filter.term, filter.facet)])
|
|
354
|
-
}
|
|
355
|
-
},
|
|
356
|
-
initiateSearch: function() {
|
|
357
|
-
this.cascadeEvent(this.cascadeSelected)
|
|
358
|
-
},
|
|
359
|
-
// checkShowAllBoxes: Checks each 'Show all' cascade option by using the setCascader function
|
|
360
|
-
checkShowAllBoxes: function(){
|
|
361
|
-
this.setCascader(
|
|
362
|
-
this.options.map(option => {
|
|
363
|
-
return {
|
|
364
|
-
facetPropPath: option.value,
|
|
365
|
-
term: option.label,
|
|
366
|
-
facet: 'Show all'
|
|
367
|
-
}
|
|
368
|
-
})
|
|
369
|
-
)
|
|
370
|
-
},
|
|
371
|
-
makeCascadeLabelsClickable: function () {
|
|
372
|
-
// Next tick allows the cascader menu to change
|
|
373
|
-
this.$nextTick(() => {
|
|
374
|
-
this.$refs.cascader.$el
|
|
375
|
-
.querySelectorAll(".el-cascader-node__label")
|
|
376
|
-
.forEach((el) => {
|
|
377
|
-
// step through each cascade label
|
|
378
|
-
el.onclick = function () {
|
|
379
|
-
const checkbox = this.previousElementSibling;
|
|
380
|
-
if (checkbox) {
|
|
381
|
-
if (!checkbox.parentElement.attributes["aria-owns"]) {
|
|
382
|
-
// check if we are at the lowest level of cascader
|
|
383
|
-
this.previousElementSibling.click(); // Click the checkbox
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
},
|
|
390
|
-
},
|
|
391
|
-
mounted: function () {
|
|
392
|
-
this.algoliaClient = new AlgoliaClient(this.envVars.ALGOLIA_ID, this.envVars.ALGOLIA_KEY, this.envVars.PENNSIEVE_API_LOCATION);
|
|
393
|
-
this.algoliaClient.initIndex(this.envVars.ALGOLIA_INDEX);
|
|
394
|
-
this.populateCascader().then(() => {
|
|
395
|
-
this.cascaderIsReady = true;
|
|
396
|
-
this.checkShowAllBoxes()
|
|
397
|
-
this.setCascader(this.entry.filterFacets);
|
|
398
|
-
this.makeCascadeLabelsClickable();
|
|
399
|
-
});
|
|
400
|
-
},
|
|
401
|
-
};
|
|
402
|
-
</script>
|
|
403
|
-
|
|
404
|
-
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
405
|
-
<style scoped>
|
|
406
|
-
.filter-default-value {
|
|
407
|
-
pointer-events: none;
|
|
408
|
-
position: absolute;
|
|
409
|
-
top: 0;
|
|
410
|
-
left: 0;
|
|
411
|
-
padding-top: 10px;
|
|
412
|
-
padding-left: 16px;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.help {
|
|
416
|
-
width: 24px !important;
|
|
417
|
-
height: 24px;
|
|
418
|
-
transform: scale(1.1);
|
|
419
|
-
color: #8300bf;
|
|
420
|
-
cursor: pointer;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
.popover {
|
|
424
|
-
color: rgb(48, 49, 51);
|
|
425
|
-
font-family: Asap;
|
|
426
|
-
margin: 12px;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
.filter-icon-inside {
|
|
430
|
-
width: 12px !important;
|
|
431
|
-
height: 12px !important;
|
|
432
|
-
color: #292b66;
|
|
433
|
-
transform: scale(2) !important;
|
|
434
|
-
margin-bottom: 0px !important;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
.cascader {
|
|
438
|
-
font-family: Asap;
|
|
439
|
-
font-size: 14px;
|
|
440
|
-
font-weight: 500;
|
|
441
|
-
font-stretch: normal;
|
|
442
|
-
font-style: normal;
|
|
443
|
-
line-height: normal;
|
|
444
|
-
letter-spacing: normal;
|
|
445
|
-
color: #292b66;
|
|
446
|
-
text-align: center;
|
|
447
|
-
padding-bottom: 6px;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
.cascader >>> .el-cascder-panel {
|
|
451
|
-
max-height: 500px;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
.cascader >>> .el-scrollbar__wrap {
|
|
455
|
-
overflow-x: hidden;
|
|
456
|
-
margin-bottom: 2px !important;
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
.cascader >>> li[aria-owns*="cascader"] > .el-checkbox {
|
|
460
|
-
display: none;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
.dataset-results-feedback {
|
|
464
|
-
float: right;
|
|
465
|
-
text-align: right;
|
|
466
|
-
color: rgb(48, 49, 51);
|
|
467
|
-
font-family: Asap;
|
|
468
|
-
font-size: 18px;
|
|
469
|
-
font-weight: 500;
|
|
470
|
-
padding-top: 8px;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
.search-filters {
|
|
474
|
-
position: relative;
|
|
475
|
-
float: left;
|
|
476
|
-
padding-right: 15px;
|
|
477
|
-
padding-bottom: 12px;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
.number-shown-select {
|
|
481
|
-
float: right;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
.number-shown-select >>> .el-input__inner {
|
|
485
|
-
width: 68px;
|
|
486
|
-
height: 40px;
|
|
487
|
-
color: rgb(48, 49, 51);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
.search-filters >>> .el-cascader-node.is-active {
|
|
491
|
-
color: #8300bf;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
.search-filters >>> .el-cascader-node.in-active-path {
|
|
495
|
-
color: #8300bf;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
.search-filters >>> .el-checkbox__input.is-checked > .el-checkbox__inner {
|
|
499
|
-
background-color: #8300bf;
|
|
500
|
-
border-color: #8300bf;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
.cascader >>> .el-cascader-menu:nth-child(2) .el-cascader-node:first-child {
|
|
504
|
-
border-bottom: 1px solid #e4e7ed;
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
.cascader >>> .el-cascader-node__label {
|
|
508
|
-
text-align: left;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
.filters >>> .el-popover {
|
|
512
|
-
background: #f3ecf6 !important;
|
|
513
|
-
border: 1px solid #8300BF;
|
|
514
|
-
border-radius: 4px;
|
|
515
|
-
color: #303133 !important;
|
|
516
|
-
font-size: 12px;
|
|
517
|
-
line-height: 18px;
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
.filters >>> .el-popover[x-placement^="top"] .popper__arrow {
|
|
523
|
-
border-top-color: #8300BF;
|
|
524
|
-
border-bottom-width: 0;
|
|
525
|
-
}
|
|
526
|
-
.filters >>> .el-popover[x-placement^="top"] .popper__arrow::after {
|
|
527
|
-
border-top-color: #f3ecf6;
|
|
528
|
-
border-bottom-width: 0;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
.filters >>> .el-popover[x-placement^="bottom"] .popper__arrow {
|
|
532
|
-
border-top-width: 0;
|
|
533
|
-
border-bottom-color: #8300BF;
|
|
534
|
-
}
|
|
535
|
-
.filters >>> .el-popover[x-placement^="bottom"] .popper__arrow::after {
|
|
536
|
-
border-top-width: 0;
|
|
537
|
-
border-bottom-color: #f3ecf6;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
.filters >>> .el-popover[x-placement^="right"] .popper__arrow {
|
|
541
|
-
border-right-color: #8300BF;
|
|
542
|
-
border-left-width: 0;
|
|
543
|
-
}
|
|
544
|
-
.filters >>> .el-popover[x-placement^="right"] .popper__arrow::after {
|
|
545
|
-
border-right-color: #f3ecf6;
|
|
546
|
-
border-left-width: 0;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
.filters >>> .el-popover[x-placement^="left"] .popper__arrow {
|
|
550
|
-
border-right-width: 0;
|
|
551
|
-
border-left-color: #8300BF;
|
|
552
|
-
}
|
|
553
|
-
.filters >>> .el-popover[x-placement^="left"] .popper__arrow::after {
|
|
554
|
-
border-right-width: 0;
|
|
555
|
-
border-left-color: #f3ecf6;
|
|
556
|
-
}
|
|
557
|
-
</style>
|
|
1
|
+
<template>
|
|
2
|
+
<div class="filters">
|
|
3
|
+
<map-svg-sprite-color />
|
|
4
|
+
<transition name="el-zoom-in-top">
|
|
5
|
+
<span v-show="showFilters" class="search-filters transition-box">
|
|
6
|
+
<custom-cascader
|
|
7
|
+
class="cascader"
|
|
8
|
+
ref="cascader"
|
|
9
|
+
v-model="cascadeSelected"
|
|
10
|
+
placeholder
|
|
11
|
+
:collapse-tags="true"
|
|
12
|
+
:options="options"
|
|
13
|
+
:props="props"
|
|
14
|
+
@change="cascadeEvent($event)"
|
|
15
|
+
@expand-change="cascadeExpandChange"
|
|
16
|
+
:show-all-levels="false"
|
|
17
|
+
:append-to-body="false"
|
|
18
|
+
@tags-changed="tagsChangedCallback"
|
|
19
|
+
></custom-cascader>
|
|
20
|
+
<div v-if="showFiltersText" class="filter-default-value">
|
|
21
|
+
Filters
|
|
22
|
+
</div>
|
|
23
|
+
<el-popover
|
|
24
|
+
title="How do filters work?"
|
|
25
|
+
width="250"
|
|
26
|
+
trigger="hover"
|
|
27
|
+
:append-to-body=false
|
|
28
|
+
popper-class="popover"
|
|
29
|
+
>
|
|
30
|
+
<map-svg-icon slot="reference" icon="help" class="help"/>
|
|
31
|
+
<div >
|
|
32
|
+
<strong>Within categories:</strong> OR
|
|
33
|
+
<br/>
|
|
34
|
+
example: 'heart' OR 'colon'
|
|
35
|
+
<br/>
|
|
36
|
+
<br/>
|
|
37
|
+
<strong>Between categories:</strong> AND
|
|
38
|
+
<br/>
|
|
39
|
+
example: 'rat' AND 'lung'
|
|
40
|
+
</div>
|
|
41
|
+
</el-popover>
|
|
42
|
+
|
|
43
|
+
</span>
|
|
44
|
+
</transition>
|
|
45
|
+
|
|
46
|
+
<el-select
|
|
47
|
+
class="number-shown-select"
|
|
48
|
+
v-model="numberShown"
|
|
49
|
+
placeholder="10"
|
|
50
|
+
@change="numberShownChanged($event)"
|
|
51
|
+
>
|
|
52
|
+
<el-option
|
|
53
|
+
v-for="item in numberDatasetsShown"
|
|
54
|
+
:key="item"
|
|
55
|
+
:label="item"
|
|
56
|
+
:value="item"
|
|
57
|
+
></el-option>
|
|
58
|
+
</el-select>
|
|
59
|
+
<span class="dataset-results-feedback">{{ this.numberOfResultsText }}</span>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
<script>
|
|
65
|
+
/* eslint-disable no-alert, no-console */
|
|
66
|
+
import Vue from "vue";
|
|
67
|
+
import { Option, Select, Popover } from "element-ui";
|
|
68
|
+
import CustomCascader from "./Cascader";
|
|
69
|
+
import lang from "element-ui/lib/locale/lang/en";
|
|
70
|
+
import locale from "element-ui/lib/locale";
|
|
71
|
+
import speciesMap from "./species-map";
|
|
72
|
+
import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
|
|
73
|
+
|
|
74
|
+
import {AlgoliaClient} from "../algolia/algolia.js";
|
|
75
|
+
import { shownFilters } from "../algolia/utils.js";
|
|
76
|
+
|
|
77
|
+
locale.use(lang);
|
|
78
|
+
Vue.use(Option);
|
|
79
|
+
Vue.use(Select);
|
|
80
|
+
Vue.use(Popover)
|
|
81
|
+
|
|
82
|
+
const capitalise = function (txt) {
|
|
83
|
+
return txt.charAt(0).toUpperCase() + txt.slice(1);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const convertReadableLabel = function (original) {
|
|
87
|
+
const name = original.toLowerCase();
|
|
88
|
+
if (speciesMap[name]) {
|
|
89
|
+
return capitalise(speciesMap[name]);
|
|
90
|
+
} else {
|
|
91
|
+
return capitalise(name);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export default {
|
|
96
|
+
name: "SearchFilters",
|
|
97
|
+
components: {
|
|
98
|
+
CustomCascader,
|
|
99
|
+
MapSvgIcon,
|
|
100
|
+
MapSvgSpriteColor,
|
|
101
|
+
},
|
|
102
|
+
props: {
|
|
103
|
+
/**
|
|
104
|
+
* Object containing information for
|
|
105
|
+
* the required viewing.
|
|
106
|
+
*/
|
|
107
|
+
entry: Object,
|
|
108
|
+
envVars: {
|
|
109
|
+
type: Object,
|
|
110
|
+
default: ()=>{}
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
data: function () {
|
|
114
|
+
return {
|
|
115
|
+
cascaderIsReady: false,
|
|
116
|
+
previousShowAllChecked: {
|
|
117
|
+
species: false,
|
|
118
|
+
gender: false,
|
|
119
|
+
organ: false,
|
|
120
|
+
datasets: false,
|
|
121
|
+
},
|
|
122
|
+
showFilters: true,
|
|
123
|
+
showFiltersText: true,
|
|
124
|
+
cascadeSelected: [],
|
|
125
|
+
numberShown: 10,
|
|
126
|
+
filters: [],
|
|
127
|
+
facets: ["Species", "Gender", "Organ", "Datasets"],
|
|
128
|
+
numberDatasetsShown: ["10", "20", "50"],
|
|
129
|
+
props: { multiple: true },
|
|
130
|
+
options: [
|
|
131
|
+
{
|
|
132
|
+
value: "Species",
|
|
133
|
+
label: "Species",
|
|
134
|
+
children: [{}],
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
computed: {
|
|
140
|
+
numberOfResultsText: function () {
|
|
141
|
+
return `${this.entry.numberOfHits} results | Showing`;
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
methods: {
|
|
145
|
+
createCascaderItemValue: function (term, facet) {
|
|
146
|
+
if (facet) return term + "/" + facet;
|
|
147
|
+
else return term;
|
|
148
|
+
},
|
|
149
|
+
populateCascader: function () {
|
|
150
|
+
return new Promise((resolve) => {
|
|
151
|
+
// Algolia facet serach
|
|
152
|
+
this.algoliaClient.getAlgoliaFacets(shownFilters)
|
|
153
|
+
.then((data) => {
|
|
154
|
+
this.facets = data;
|
|
155
|
+
this.options = data;
|
|
156
|
+
|
|
157
|
+
// create top level of options in cascader
|
|
158
|
+
this.options.forEach((facet, i) => {
|
|
159
|
+
this.options[i].label = convertReadableLabel(facet.label);
|
|
160
|
+
this.options[i].value = this.createCascaderItemValue(
|
|
161
|
+
facet.key,
|
|
162
|
+
undefined
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// put "Show all" as first option
|
|
166
|
+
this.options[i].children.unshift({
|
|
167
|
+
value: this.createCascaderItemValue("Show all"),
|
|
168
|
+
label: "Show all",
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// populate second level of options
|
|
172
|
+
this.options[i].children.forEach((facetItem, j) => {
|
|
173
|
+
this.options[i].children[j].label = convertReadableLabel(
|
|
174
|
+
facetItem.label
|
|
175
|
+
);
|
|
176
|
+
this.options[i].children[j].value =
|
|
177
|
+
this.createCascaderItemValue(facet.label, facetItem.label);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
this.createDataTypeFacet()
|
|
181
|
+
})
|
|
182
|
+
.finally(() => {
|
|
183
|
+
resolve();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
tagsChangedCallback: function (presentTags) {
|
|
188
|
+
if (presentTags.length > 0) {
|
|
189
|
+
this.showFiltersText = false;
|
|
190
|
+
} else {
|
|
191
|
+
this.showFiltersText = true;
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
// cascadeEvent: initiate searches based off cascader changes
|
|
195
|
+
cascadeEvent: function (event) {
|
|
196
|
+
if (event) {
|
|
197
|
+
// Check for show all in selected cascade options
|
|
198
|
+
event = this.showAllEventModifier(event);
|
|
199
|
+
|
|
200
|
+
// Create results for the filter update
|
|
201
|
+
let filterKeys = event.filter( selection => selection !== undefined).map( fs => ({
|
|
202
|
+
facetPropPath: fs[0],
|
|
203
|
+
facet: fs[1].split("/")[1],
|
|
204
|
+
term: fs[1].split("/")[0],
|
|
205
|
+
}))
|
|
206
|
+
|
|
207
|
+
// Move results from arrays to object for use on scicrunch (note that we remove 'duplicate' as that is only needed for filter keys)
|
|
208
|
+
let filters = event.filter( selection => selection !== undefined).map( fs => {
|
|
209
|
+
let propPath = fs[0].includes('duplicate') ? fs[0].split('duplicate')[0] : fs[0]
|
|
210
|
+
return {
|
|
211
|
+
facetPropPath: propPath,
|
|
212
|
+
facet: fs[1].split("/")[1],
|
|
213
|
+
term: fs[1].split("/")[0],
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
this.$emit('loading', true) // let sidebarcontent wait for the requests
|
|
219
|
+
|
|
220
|
+
this.$emit("filterResults", filters); // emit filters for apps above sidebar
|
|
221
|
+
this.setCascader(filterKeys); //update our cascader v-model if we modified the event
|
|
222
|
+
this.makeCascadeLabelsClickable();
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
// showAllEventModifier: Modifies a cascade event to unlick all selections in category if "show all" is clicked. Also unchecks "Show all" if any secection is clicked
|
|
226
|
+
// *NOTE* Does NOT remove 'Show all' selections from showing in 'cascadeSelected'
|
|
227
|
+
showAllEventModifier: function (event) {
|
|
228
|
+
// check if show all is in the cascader checked option list
|
|
229
|
+
let hasShowAll = event
|
|
230
|
+
.map((ev) => (ev ? ev[1].toLowerCase().includes("show all") : false))
|
|
231
|
+
.includes(true);
|
|
232
|
+
// remove all selected options below the show all if checked
|
|
233
|
+
if (hasShowAll) {
|
|
234
|
+
let modifiedEvent = [];
|
|
235
|
+
let facetMaps = {};
|
|
236
|
+
//catagorised different facet items
|
|
237
|
+
for (const i in event) {
|
|
238
|
+
if (facetMaps[event[i][0]] === undefined) facetMaps[event[i][0]] = [];
|
|
239
|
+
facetMaps[event[i][0]].push(event[i]);
|
|
240
|
+
}
|
|
241
|
+
// go through each facets
|
|
242
|
+
for (const facet in facetMaps) {
|
|
243
|
+
let showAll = undefined;
|
|
244
|
+
// Find the show all item if any
|
|
245
|
+
for (let i = facetMaps[facet].length - 1; i >= 0; i--) {
|
|
246
|
+
if (facetMaps[facet][i][1].toLowerCase().includes("show all")) {
|
|
247
|
+
//seperate the showAll item and the rest
|
|
248
|
+
showAll = facetMaps[facet].splice(i, 1)[0];
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (showAll) {
|
|
253
|
+
if (this.previousShowAllChecked[facet]) {
|
|
254
|
+
//Unset the show all if it was present previously
|
|
255
|
+
//and there are other items
|
|
256
|
+
if (facetMaps[facet].length > 0)
|
|
257
|
+
modifiedEvent.push(...facetMaps[facet]);
|
|
258
|
+
else modifiedEvent.push(showAll);
|
|
259
|
+
} else {
|
|
260
|
+
//showAll is turned on
|
|
261
|
+
modifiedEvent.push(showAll);
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
modifiedEvent.push(...facetMaps[facet]);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
//Make sure the expanded item are sorted first.
|
|
268
|
+
return modifiedEvent.sort((a, b) => {
|
|
269
|
+
if (this.__expandItem__) {
|
|
270
|
+
if (a[0] == this.__expandItem__) {
|
|
271
|
+
if (b[0] == this.__expandItem__) {
|
|
272
|
+
return 0;
|
|
273
|
+
} else {
|
|
274
|
+
return -1;
|
|
275
|
+
}
|
|
276
|
+
} else if (b[0] == this.__expandItem__) {
|
|
277
|
+
if (a[0] == this.__expandItem__) {
|
|
278
|
+
return 0;
|
|
279
|
+
} else {
|
|
280
|
+
return 1;
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
return 0;
|
|
284
|
+
}
|
|
285
|
+
} else return 0;
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
return event;
|
|
289
|
+
},
|
|
290
|
+
createDataTypeFacet: function(){
|
|
291
|
+
let dataFacet = {...this.facets[2]} // copy the 'Experiemental approach' facet
|
|
292
|
+
let count = this.facets.at(-1).id // get the last id count
|
|
293
|
+
|
|
294
|
+
// Step through the children that are valid data types, switch thier values
|
|
295
|
+
let newChildren = dataFacet.children.filter( el=> {
|
|
296
|
+
if (el.label === 'Scaffold' || el.label === 'Simulation' || el.label === 'Show all'){
|
|
297
|
+
el.key = el.label
|
|
298
|
+
el.id = count
|
|
299
|
+
el.value = el.value.replace('Experimental approach', 'Data type')
|
|
300
|
+
count++
|
|
301
|
+
return el
|
|
302
|
+
}
|
|
303
|
+
})
|
|
304
|
+
dataFacet.id = count
|
|
305
|
+
dataFacet.key = 'Data type'
|
|
306
|
+
// Add 'duplicate' so that the key is unique. This is removed in the cascade event for filtering
|
|
307
|
+
dataFacet.value += 'duplicate'
|
|
308
|
+
dataFacet.children = newChildren
|
|
309
|
+
dataFacet.label = 'Data type'
|
|
310
|
+
this.facets.push(dataFacet)
|
|
311
|
+
},
|
|
312
|
+
cascadeExpandChange: function (event) {
|
|
313
|
+
//work around as the expand item may change on modifying the cascade props
|
|
314
|
+
this.__expandItem__ = event;
|
|
315
|
+
this.makeCascadeLabelsClickable();
|
|
316
|
+
},
|
|
317
|
+
numberShownChanged: function (event) {
|
|
318
|
+
this.$emit("numberPerPage", parseInt(event));
|
|
319
|
+
},
|
|
320
|
+
updatePreviousShowAllChecked: function (options) {
|
|
321
|
+
//Reset the states
|
|
322
|
+
for (const facet in this.previousShowAllChecked) {
|
|
323
|
+
this.previousShowAllChecked[facet] = false;
|
|
324
|
+
}
|
|
325
|
+
options.forEach((element) => {
|
|
326
|
+
if (element[1].toLowerCase().includes("show all"))
|
|
327
|
+
this.previousShowAllChecked[element[0]] = true;
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
// setCascader: Clears previous selections and takes in an array of facets to select: filterFacets
|
|
331
|
+
// facets are in the form:
|
|
332
|
+
// {
|
|
333
|
+
// facetPropPath: 'anatomy.organ.name',
|
|
334
|
+
// term: 'Sex',
|
|
335
|
+
// facet: 'Male'
|
|
336
|
+
// }
|
|
337
|
+
setCascader: function (filterFacets) {
|
|
338
|
+
//Do not set the value unless it is ready
|
|
339
|
+
if (this.cascaderIsReady && filterFacets && filterFacets.length != 0) {
|
|
340
|
+
this.cascadeSelected = filterFacets.map(e => {
|
|
341
|
+
return [
|
|
342
|
+
e.facetPropPath,
|
|
343
|
+
this.createCascaderItemValue(capitalise(e.term), e.facet),
|
|
344
|
+
]
|
|
345
|
+
});
|
|
346
|
+
this.updatePreviousShowAllChecked(this.cascadeSelected);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
addFilter: function (filter) {
|
|
350
|
+
//Do not set the value unless it is ready
|
|
351
|
+
if (this.cascaderIsReady && filter) {
|
|
352
|
+
this.cascadeSelected.filter(f=>f.term != filter.term)
|
|
353
|
+
this.cascadeSelected.push([filter.facetPropPath, this.createCascaderItemValue(filter.term, filter.facet)])
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
initiateSearch: function() {
|
|
357
|
+
this.cascadeEvent(this.cascadeSelected)
|
|
358
|
+
},
|
|
359
|
+
// checkShowAllBoxes: Checks each 'Show all' cascade option by using the setCascader function
|
|
360
|
+
checkShowAllBoxes: function(){
|
|
361
|
+
this.setCascader(
|
|
362
|
+
this.options.map(option => {
|
|
363
|
+
return {
|
|
364
|
+
facetPropPath: option.value,
|
|
365
|
+
term: option.label,
|
|
366
|
+
facet: 'Show all'
|
|
367
|
+
}
|
|
368
|
+
})
|
|
369
|
+
)
|
|
370
|
+
},
|
|
371
|
+
makeCascadeLabelsClickable: function () {
|
|
372
|
+
// Next tick allows the cascader menu to change
|
|
373
|
+
this.$nextTick(() => {
|
|
374
|
+
this.$refs.cascader.$el
|
|
375
|
+
.querySelectorAll(".el-cascader-node__label")
|
|
376
|
+
.forEach((el) => {
|
|
377
|
+
// step through each cascade label
|
|
378
|
+
el.onclick = function () {
|
|
379
|
+
const checkbox = this.previousElementSibling;
|
|
380
|
+
if (checkbox) {
|
|
381
|
+
if (!checkbox.parentElement.attributes["aria-owns"]) {
|
|
382
|
+
// check if we are at the lowest level of cascader
|
|
383
|
+
this.previousElementSibling.click(); // Click the checkbox
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
mounted: function () {
|
|
392
|
+
this.algoliaClient = new AlgoliaClient(this.envVars.ALGOLIA_ID, this.envVars.ALGOLIA_KEY, this.envVars.PENNSIEVE_API_LOCATION);
|
|
393
|
+
this.algoliaClient.initIndex(this.envVars.ALGOLIA_INDEX);
|
|
394
|
+
this.populateCascader().then(() => {
|
|
395
|
+
this.cascaderIsReady = true;
|
|
396
|
+
this.checkShowAllBoxes()
|
|
397
|
+
this.setCascader(this.entry.filterFacets);
|
|
398
|
+
this.makeCascadeLabelsClickable();
|
|
399
|
+
});
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
</script>
|
|
403
|
+
|
|
404
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
405
|
+
<style scoped>
|
|
406
|
+
.filter-default-value {
|
|
407
|
+
pointer-events: none;
|
|
408
|
+
position: absolute;
|
|
409
|
+
top: 0;
|
|
410
|
+
left: 0;
|
|
411
|
+
padding-top: 10px;
|
|
412
|
+
padding-left: 16px;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.help {
|
|
416
|
+
width: 24px !important;
|
|
417
|
+
height: 24px;
|
|
418
|
+
transform: scale(1.1);
|
|
419
|
+
color: #8300bf;
|
|
420
|
+
cursor: pointer;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.popover {
|
|
424
|
+
color: rgb(48, 49, 51);
|
|
425
|
+
font-family: Asap;
|
|
426
|
+
margin: 12px;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.filter-icon-inside {
|
|
430
|
+
width: 12px !important;
|
|
431
|
+
height: 12px !important;
|
|
432
|
+
color: #292b66;
|
|
433
|
+
transform: scale(2) !important;
|
|
434
|
+
margin-bottom: 0px !important;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.cascader {
|
|
438
|
+
font-family: Asap;
|
|
439
|
+
font-size: 14px;
|
|
440
|
+
font-weight: 500;
|
|
441
|
+
font-stretch: normal;
|
|
442
|
+
font-style: normal;
|
|
443
|
+
line-height: normal;
|
|
444
|
+
letter-spacing: normal;
|
|
445
|
+
color: #292b66;
|
|
446
|
+
text-align: center;
|
|
447
|
+
padding-bottom: 6px;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.cascader >>> .el-cascder-panel {
|
|
451
|
+
max-height: 500px;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.cascader >>> .el-scrollbar__wrap {
|
|
455
|
+
overflow-x: hidden;
|
|
456
|
+
margin-bottom: 2px !important;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.cascader >>> li[aria-owns*="cascader"] > .el-checkbox {
|
|
460
|
+
display: none;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.dataset-results-feedback {
|
|
464
|
+
float: right;
|
|
465
|
+
text-align: right;
|
|
466
|
+
color: rgb(48, 49, 51);
|
|
467
|
+
font-family: Asap;
|
|
468
|
+
font-size: 18px;
|
|
469
|
+
font-weight: 500;
|
|
470
|
+
padding-top: 8px;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.search-filters {
|
|
474
|
+
position: relative;
|
|
475
|
+
float: left;
|
|
476
|
+
padding-right: 15px;
|
|
477
|
+
padding-bottom: 12px;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.number-shown-select {
|
|
481
|
+
float: right;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.number-shown-select >>> .el-input__inner {
|
|
485
|
+
width: 68px;
|
|
486
|
+
height: 40px;
|
|
487
|
+
color: rgb(48, 49, 51);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.search-filters >>> .el-cascader-node.is-active {
|
|
491
|
+
color: #8300bf;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.search-filters >>> .el-cascader-node.in-active-path {
|
|
495
|
+
color: #8300bf;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
.search-filters >>> .el-checkbox__input.is-checked > .el-checkbox__inner {
|
|
499
|
+
background-color: #8300bf;
|
|
500
|
+
border-color: #8300bf;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.cascader >>> .el-cascader-menu:nth-child(2) .el-cascader-node:first-child {
|
|
504
|
+
border-bottom: 1px solid #e4e7ed;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
.cascader >>> .el-cascader-node__label {
|
|
508
|
+
text-align: left;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.filters >>> .el-popover {
|
|
512
|
+
background: #f3ecf6 !important;
|
|
513
|
+
border: 1px solid #8300BF;
|
|
514
|
+
border-radius: 4px;
|
|
515
|
+
color: #303133 !important;
|
|
516
|
+
font-size: 12px;
|
|
517
|
+
line-height: 18px;
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.filters >>> .el-popover[x-placement^="top"] .popper__arrow {
|
|
523
|
+
border-top-color: #8300BF;
|
|
524
|
+
border-bottom-width: 0;
|
|
525
|
+
}
|
|
526
|
+
.filters >>> .el-popover[x-placement^="top"] .popper__arrow::after {
|
|
527
|
+
border-top-color: #f3ecf6;
|
|
528
|
+
border-bottom-width: 0;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.filters >>> .el-popover[x-placement^="bottom"] .popper__arrow {
|
|
532
|
+
border-top-width: 0;
|
|
533
|
+
border-bottom-color: #8300BF;
|
|
534
|
+
}
|
|
535
|
+
.filters >>> .el-popover[x-placement^="bottom"] .popper__arrow::after {
|
|
536
|
+
border-top-width: 0;
|
|
537
|
+
border-bottom-color: #f3ecf6;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
.filters >>> .el-popover[x-placement^="right"] .popper__arrow {
|
|
541
|
+
border-right-color: #8300BF;
|
|
542
|
+
border-left-width: 0;
|
|
543
|
+
}
|
|
544
|
+
.filters >>> .el-popover[x-placement^="right"] .popper__arrow::after {
|
|
545
|
+
border-right-color: #f3ecf6;
|
|
546
|
+
border-left-width: 0;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.filters >>> .el-popover[x-placement^="left"] .popper__arrow {
|
|
550
|
+
border-right-width: 0;
|
|
551
|
+
border-left-color: #8300BF;
|
|
552
|
+
}
|
|
553
|
+
.filters >>> .el-popover[x-placement^="left"] .popper__arrow::after {
|
|
554
|
+
border-right-width: 0;
|
|
555
|
+
border-left-color: #f3ecf6;
|
|
556
|
+
}
|
|
557
|
+
</style>
|