@abi-software/map-side-bar 1.3.2 → 1.3.5
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/map-side-bar.common.js +183 -108
- 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 +183 -108
- 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 +1 -1
- package/package.json +1 -1
- package/src/App.vue +5 -1
- package/src/algolia/algolia.js +46 -0
- package/src/algolia/utils.js +9 -1
- package/src/components/ContextCard.vue +22 -16
- package/src/components/SearchFilters.vue +2 -2
- package/src/components/SideBar.vue +6 -0
- package/src/components/SidebarContent.vue +4 -0
package/package-lock.json
CHANGED
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<el-button @click="singleFacets">Add to Filter</el-button>
|
|
8
8
|
<el-button @click="multiFacets">multiple facets</el-button>
|
|
9
9
|
<el-button @click="neuronSearch">open neuron search</el-button>
|
|
10
|
+
<el-button @click="keywordSearch">keyword search</el-button>
|
|
10
11
|
<SideBar :envVars="envVars" class="side-bar" ref="sideBar" :visible="sideBarVisibility"
|
|
11
12
|
:tabs="tabs" :activeId="activeId" @tabClicked="tabClicked"
|
|
12
13
|
@search-changed="searchChanged($event)" @actionClick="action"/>
|
|
@@ -113,8 +114,11 @@ export default {
|
|
|
113
114
|
multiFacets: function(){
|
|
114
115
|
this.$refs.sideBar.openSearch([{facet: 'Male', term:'Sex', facetPropPath:'attributes.subject.sex.value'}, {facet: 'Heart', term:'Anatomical structure', facetPropPath: 'anatomy.organ.name'}], '')
|
|
115
116
|
},
|
|
117
|
+
keywordSearch: function(){
|
|
118
|
+
this.$refs.sideBar.openSearch([{facet: 'http://purl.obolibrary.org/obo/UBERON_0001103', term:'Keywords', facetPropPath:'item.keywords.keyword'}])
|
|
119
|
+
},
|
|
116
120
|
neuronSearch: function(){
|
|
117
|
-
this.$refs.sideBar.openNeuronSearch('neuron-type-keast-10')
|
|
121
|
+
this.$refs.sideBar.openNeuronSearch('ilxtr:neuron-type-keast-10')
|
|
118
122
|
}
|
|
119
123
|
}
|
|
120
124
|
}
|
package/src/algolia/algolia.js
CHANGED
|
@@ -90,6 +90,28 @@ export class AlgoliaClient {
|
|
|
90
90
|
}
|
|
91
91
|
return newResults
|
|
92
92
|
}
|
|
93
|
+
|
|
94
|
+
_processKeywords(hits){
|
|
95
|
+
let foundKeyWords = []
|
|
96
|
+
let uniqueKeywords = []
|
|
97
|
+
hits.forEach(hit=>{
|
|
98
|
+
if ( hit.item && hit.item.keywords) {
|
|
99
|
+
hit.item.keywords.forEach(keywordObj=>{
|
|
100
|
+
let keyword = keywordObj.keyword
|
|
101
|
+
if (keyword.includes('UBERON') || keyword.includes('ilxtr') || keyword.includes('ILX')) {
|
|
102
|
+
foundKeyWords.push(this._processUberonURL(keyword))
|
|
103
|
+
uniqueKeywords = [...new Set(foundKeyWords)]
|
|
104
|
+
}
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
return uniqueKeywords
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_processUberonURL(url){
|
|
112
|
+
let ub = url.split('/').pop()
|
|
113
|
+
ub.replace('_',':')
|
|
114
|
+
}
|
|
93
115
|
|
|
94
116
|
/**
|
|
95
117
|
* Get Search results
|
|
@@ -124,4 +146,28 @@ export class AlgoliaClient {
|
|
|
124
146
|
})
|
|
125
147
|
})
|
|
126
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get key words
|
|
152
|
+
* This is used to return all keywords for a given search. Note that you often want the hits per page to be maxed out
|
|
153
|
+
*/
|
|
154
|
+
keywordsInSearch (filter, query='', hitsperPage=999999, page=1) {
|
|
155
|
+
return new Promise(resolve => {
|
|
156
|
+
this.index
|
|
157
|
+
.search(query, {
|
|
158
|
+
facets:['*'],
|
|
159
|
+
hitsPerPage: hitsperPage,
|
|
160
|
+
page: page-1,
|
|
161
|
+
filters: filter,
|
|
162
|
+
attributesToHighlight: [],
|
|
163
|
+
attributesToRetrieve: [
|
|
164
|
+
'item.keywords.keyword',
|
|
165
|
+
],
|
|
166
|
+
})
|
|
167
|
+
.then(response => {
|
|
168
|
+
let keywords = this._processKeywords(response.hits)
|
|
169
|
+
resolve(keywords)
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
}
|
|
127
173
|
}
|
package/src/algolia/utils.js
CHANGED
|
@@ -8,13 +8,21 @@ export const facetPropPathMapping = {
|
|
|
8
8
|
'item.modalities.keyword' : 'Experimental Approach',
|
|
9
9
|
'attributes.subject.sex.value' : 'Sex',
|
|
10
10
|
'attributes.subject.ageCategory.value' : 'Age Categories',
|
|
11
|
+
'item.keywords.keyword' : 'Keywords'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const shownFilters = {
|
|
15
|
+
'anatomy.organ.name' : 'Anatomical Structure',
|
|
16
|
+
'organisms.primary.species.name' : 'Species',
|
|
17
|
+
'item.modalities.keyword' : 'Experimental Approach',
|
|
18
|
+
'attributes.subject.sex.value' : 'Sex',
|
|
19
|
+
'attributes.subject.ageCategory.value' : 'Age Categories',
|
|
11
20
|
}
|
|
12
21
|
|
|
13
22
|
/* Returns filter for searching algolia. All facets of the same category are joined with OR,
|
|
14
23
|
* and each of those results is then joined with an AND.
|
|
15
24
|
* i.e. (color:blue OR color:red) AND (shape:circle OR shape:red) */
|
|
16
25
|
export function getFilters(selectedFacetArray=undefined) {
|
|
17
|
-
|
|
18
26
|
// return all datasets if no filter
|
|
19
27
|
if (selectedFacetArray === undefined) {
|
|
20
28
|
return 'NOT item.published.status:embargo'
|
|
@@ -9,20 +9,20 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
<div class="card-right scrollbar">
|
|
11
11
|
<div class="title">{{contextData.heading}}</div>
|
|
12
|
-
<div
|
|
12
|
+
<div v-html="contextData.description"/>
|
|
13
13
|
<br/>
|
|
14
14
|
<div v-if="contextData.views && contextData.views.length > 0" class="subtitle">Scaffold Views</div>
|
|
15
15
|
<template v-for="(view, i) in contextData.views">
|
|
16
|
-
<
|
|
17
|
-
<img class="
|
|
18
|
-
{{view.description}}
|
|
19
|
-
</
|
|
20
|
-
<
|
|
16
|
+
<div v-bind:key="i+'_1'" @click="openViewFile(view)" class="context-card-view">
|
|
17
|
+
<img class="view-image" :src="getFileFromPath(view.thumbnail)">
|
|
18
|
+
<div class="view-description">{{view.description}}</div>
|
|
19
|
+
</div>
|
|
20
|
+
<div v-bind:key="i" class="padding"/>
|
|
21
21
|
</template>
|
|
22
22
|
<div style="margin-bottom: 16px;"/>
|
|
23
23
|
<div v-if="contextData.samples && contextData.samples.length > 0" class="subtitle">Samples on Scaffold</div>
|
|
24
24
|
<template v-for="(sample, i) in contextData.samples">
|
|
25
|
-
<span v-bind:key="i+'_3'" class="context-card-item" @click="toggleSampleDetails(i)">
|
|
25
|
+
<span v-bind:key="i+'_3'" class="context-card-item cursor-pointer" @click="toggleSampleDetails(i)">
|
|
26
26
|
<div v-bind:key="i+'_6'" style="display: flex">
|
|
27
27
|
<div v-if="sample.color" class="color-box" :style="'background-color:'+ sample.color"></div>
|
|
28
28
|
<img class="key-image" v-else-if="sample.thumbnail" :src="getFileFromPath(sample.thumbnail)">
|
|
@@ -30,11 +30,9 @@
|
|
|
30
30
|
<i class="el-icon-warning-outline info"></i>
|
|
31
31
|
</div>
|
|
32
32
|
</span>
|
|
33
|
-
<div v-bind:key="i+'_4'" v-if="sampleDetails[i]"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</div>
|
|
37
|
-
<br v-bind:key="i+'_2'"/>
|
|
33
|
+
<div v-bind:key="i+'_4'" v-if="sampleDetails[i]" v-html="sample.description"/>
|
|
34
|
+
<a v-bind:key="i+'_5'" v-if="sampleDetails[i]" :href="generateFileLink(sample.path)" target="_blank">View Source</a>
|
|
35
|
+
<div v-bind:key="i+'_2'" class="padding"/>
|
|
38
36
|
</template>
|
|
39
37
|
</div>
|
|
40
38
|
</el-card>
|
|
@@ -110,7 +108,6 @@ export default {
|
|
|
110
108
|
})
|
|
111
109
|
.then((data) => {
|
|
112
110
|
this.contextData = data
|
|
113
|
-
console.log(data)
|
|
114
111
|
this.loading = false
|
|
115
112
|
})
|
|
116
113
|
.catch(() => {
|
|
@@ -179,14 +176,20 @@ export default {
|
|
|
179
176
|
max-height: 258px;
|
|
180
177
|
}
|
|
181
178
|
|
|
182
|
-
.context-card-
|
|
179
|
+
.context-card-view{
|
|
183
180
|
cursor: pointer;
|
|
184
181
|
padding-bottom: 8px;
|
|
182
|
+
display: flex;
|
|
185
183
|
}
|
|
186
184
|
|
|
187
|
-
.
|
|
185
|
+
.view-image {
|
|
188
186
|
width: 25px;
|
|
189
187
|
height: auto;
|
|
188
|
+
flex: 1;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.view-descriptions {
|
|
192
|
+
flex: 8;
|
|
190
193
|
}
|
|
191
194
|
|
|
192
195
|
.context-card >>> .el-card__body {
|
|
@@ -221,7 +224,6 @@ export default {
|
|
|
221
224
|
|
|
222
225
|
.cursor-pointer {
|
|
223
226
|
cursor: pointer;
|
|
224
|
-
height: 25px;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
.info{
|
|
@@ -230,6 +232,10 @@ export default {
|
|
|
230
232
|
margin-left: 8px;
|
|
231
233
|
}
|
|
232
234
|
|
|
235
|
+
.padding {
|
|
236
|
+
padding-bottom: 8px;
|
|
237
|
+
}
|
|
238
|
+
|
|
233
239
|
.title{
|
|
234
240
|
font-weight: bold;
|
|
235
241
|
}
|
|
@@ -72,7 +72,7 @@ import speciesMap from "./species-map";
|
|
|
72
72
|
import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
|
|
73
73
|
|
|
74
74
|
import {AlgoliaClient} from "../algolia/algolia.js";
|
|
75
|
-
import {
|
|
75
|
+
import { shownFilters } from "../algolia/utils.js";
|
|
76
76
|
|
|
77
77
|
locale.use(lang);
|
|
78
78
|
Vue.use(Option);
|
|
@@ -149,7 +149,7 @@ export default {
|
|
|
149
149
|
populateCascader: function () {
|
|
150
150
|
return new Promise((resolve) => {
|
|
151
151
|
// Algolia facet serach
|
|
152
|
-
this.algoliaClient.getAlgoliaFacets(
|
|
152
|
+
this.algoliaClient.getAlgoliaFacets(shownFilters)
|
|
153
153
|
.then((data) => {
|
|
154
154
|
this.facets = data;
|
|
155
155
|
this.options = data;
|
|
@@ -139,6 +139,12 @@ export default {
|
|
|
139
139
|
EventBus.$on("PopoverActionClick", (payLoad) => {
|
|
140
140
|
this.$emit("actionClick", payLoad);
|
|
141
141
|
})
|
|
142
|
+
EventBus.$on('keywordsFound', (payLoad)=> {
|
|
143
|
+
this.$emit('search-changed', {
|
|
144
|
+
type: 'keyword-update',
|
|
145
|
+
value: payLoad
|
|
146
|
+
})
|
|
147
|
+
})
|
|
142
148
|
}
|
|
143
149
|
};
|
|
144
150
|
</script>
|
|
@@ -61,6 +61,7 @@ import locale from "element-ui/lib/locale";
|
|
|
61
61
|
import SearchFilters from "./SearchFilters";
|
|
62
62
|
import DatasetCard from "./DatasetCard";
|
|
63
63
|
import ContextCard from "./ContextCard.vue";
|
|
64
|
+
import EventBus from "./EventBus"
|
|
64
65
|
|
|
65
66
|
import {AlgoliaClient} from "../algolia/algolia.js";
|
|
66
67
|
import {getFilters} from "../algolia/utils.js"
|
|
@@ -191,6 +192,9 @@ export default {
|
|
|
191
192
|
searchAlgolia(filters, query=''){
|
|
192
193
|
// Algolia search
|
|
193
194
|
this.loadingCards = true
|
|
195
|
+
this.algoliaClient.keywordsInSearch(getFilters(filters), query).then(keywords => {
|
|
196
|
+
EventBus.$emit("keywordsFound", keywords)
|
|
197
|
+
})
|
|
194
198
|
this.algoliaClient.search(getFilters(filters), query, this.numberPerPage, this.page).then(searchData => {
|
|
195
199
|
this.numberOfHits = searchData.total
|
|
196
200
|
this.discoverIds = searchData.discoverIds
|