@abi-software/map-side-bar 2.7.0 → 2.7.1-isan.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-side-bar",
3
- "version": "2.7.0",
3
+ "version": "2.7.1-isan.1",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
package/src/App.vue CHANGED
@@ -6,6 +6,7 @@
6
6
  />
7
7
  <div class="options-container">
8
8
  <div>Click arrow to open sidebar</div>
9
+ <el-button @click="openPMRSearch">PMR Search</el-button>
9
10
  <el-button @click="openSearch">search Uberon from refs</el-button>
10
11
  <el-button @click="singleFacets">Add heart to Filter (facet2 set)</el-button>
11
12
  <el-button @click="addStomach">Add stomach to Filter</el-button>
@@ -114,7 +115,6 @@ export default {
114
115
  { title: 'Flatmap', id: 1, type: 'search'},
115
116
  { title: 'Connectivity', id: 2, type: 'connectivity' },
116
117
  { title: 'Annotation', id: 3, type: 'annotation' },
117
- { title: 'Connectivity Explorer', id: 4, type: 'connectivityExplorer' }
118
118
  ],
119
119
  sideBarVisibility: true,
120
120
  envVars: {
@@ -126,7 +126,7 @@ export default {
126
126
  BL_SERVER_URL: import.meta.env.VITE_APP_BL_SERVER_URL,
127
127
  NL_LINK_PREFIX: import.meta.env.VITE_APP_NL_LINK_PREFIX,
128
128
  ROOT_URL: import.meta.env.VITE_APP_ROOT_URL,
129
- FLATMAPAPI_LOCATION: import.meta.env.VITE_FLATMAPAPI_LOCATION,
129
+ FLATMAP_API_LOCATION: import.meta.env.VITE_APP_FLATMAP_API_LOCATION,
130
130
  },
131
131
  connectivityInput: exampleConnectivityInput,
132
132
  activeId: 1,
@@ -142,7 +142,7 @@ export default {
142
142
  },
143
143
  methods: {
144
144
  hoverChanged: function (data) {
145
- console.log('hoverChanged', data)
145
+ // console.log('hoverChanged', data)
146
146
  },
147
147
  searchChanged: function (data) {
148
148
  console.log(data)
@@ -154,18 +154,32 @@ export default {
154
154
  action: function (action) {
155
155
  console.log('action fired: ', action)
156
156
  let facets = [];
157
- facets.push(
158
- ...action.labels.map(val => ({
159
- facet: capitalise(val),
160
- term: "Anatomical structure",
161
- facetPropPath: "anatomy.organ.category.name",
162
- }))
163
- );
164
- if (this.$refs.sideBar) {
165
- console.log('openSearch', facets)
166
- this.$refs.sideBar.openSearch(facets, "");
157
+ if (action.labels) {
158
+ facets.push(
159
+ ...action.labels.map(val => ({
160
+ facet: capitalise(val),
161
+ term: "Anatomical structure",
162
+ facetPropPath: "anatomy.organ.category.name",
163
+ }))
164
+ );
165
+ if (this.$refs.sideBar) {
166
+ console.log('openSearch', facets)
167
+ this.$refs.sideBar.openSearch(facets, "");
168
+ }
167
169
  }
168
170
  },
171
+ openPMRSearch: function () {
172
+ this.$refs.sideBar.openSearch(
173
+ [
174
+ {
175
+ facet: "PMR",
176
+ term: "Data type",
177
+ facetPropPath: "item.types.name",
178
+ }
179
+ ],
180
+ 'cardiovascular multiscale model'
181
+ );
182
+ },
169
183
  openSearch: function () {
170
184
  this.$refs.sideBar.openSearch(
171
185
  [],
@@ -100,6 +100,7 @@ export class AlgoliaClient {
100
100
  for (let res of results) {
101
101
  newResult = { ...res }
102
102
  newResult = {
103
+ dataSource: 'SPARC',
103
104
  anatomy: res.anatomy ? res.anatomy.organ.map((organ => organ.curie)) : undefined,
104
105
  doi: res.item.curie.split(':')[1],
105
106
  name: res.item.name,
@@ -152,35 +153,48 @@ export class AlgoliaClient {
152
153
  * Get Search results
153
154
  * This is using fetch from the Algolia API
154
155
  */
155
- search(filter, query = '', hitsperPage = 10, page = 1) {
156
- return new Promise(resolve => {
157
- this.index
158
- .search(query, {
159
- facets: ['*'],
160
- hitsPerPage: hitsperPage,
161
- page: page - 1,
162
- filters: filter,
163
- attributesToHighlight: [],
164
- attributesToRetrieve: [
165
- 'pennsieve.publishDate',
166
- 'pennsieve.updatedAt',
167
- 'item.curie',
168
- 'item.name',
169
- 'item.description',
170
- 'objectID',
171
- 'anatomy.organ.curie'
172
- ],
173
- })
174
- .then(response => {
175
- let searchData = {
176
- items: this._processResultsForCards(response.hits),
177
- total: response.nbHits,
178
- discoverIds: response.hits.map(r => r.pennsieve ? r.pennsieve.identifier : r.objectID),
179
- dois: response.hits.map(r => r.item.curie.split(':')[1])
180
- }
181
- resolve(searchData)
156
+ search(filter, query = '', offset = 0, length = 8) {
157
+ console.log('searching', filter, query, offset, length)
158
+ // If the length is 0, return an empty result
159
+ if (length === 0) {
160
+ return new Promise(resolve => {
161
+ resolve({
162
+ items: [],
163
+ total: 0,
164
+ discoverIds: [],
165
+ dois: []
182
166
  })
183
- })
167
+ })
168
+ } else {
169
+ return new Promise(resolve => {
170
+ this.index
171
+ .search(query, {
172
+ facets: ['*'],
173
+ offset: offset,
174
+ length: length,
175
+ filters: filter,
176
+ attributesToHighlight: [],
177
+ attributesToRetrieve: [
178
+ 'pennsieve.publishDate',
179
+ 'pennsieve.updatedAt',
180
+ 'item.curie',
181
+ 'item.name',
182
+ 'item.description',
183
+ 'objectID',
184
+ 'anatomy.organ.curie'
185
+ ],
186
+ })
187
+ .then(response => {
188
+ let searchData = {
189
+ items: this._processResultsForCards(response.hits),
190
+ total: response.nbHits,
191
+ discoverIds: response.hits.map(r => r.pennsieve ? r.pennsieve.identifier : r.objectID),
192
+ dois: response.hits.map(r => r.item.curie.split(':')[1])
193
+ }
194
+ resolve(searchData)
195
+ })
196
+ })
197
+ }
184
198
  }
185
199
 
186
200
  /**
@@ -70,7 +70,6 @@ export function getFilters(selectedFacetArray=undefined) {
70
70
  // Switch the 'term' attribute to 'label' if 'label' does not exist
71
71
  selectedFacetArray.forEach(f=>f.label=f.facet)
72
72
 
73
-
74
73
  let facets = removeShowAllFacets(selectedFacetArray)
75
74
 
76
75
  let filters = "NOT item.published.status:embargo";
@@ -19,6 +19,7 @@
19
19
  />
20
20
  </span>
21
21
  <div class="card-right">
22
+ <el-tag type="primary" class="source-tag">SPARC Dataset</el-tag>
22
23
  <div class="title" @click="cardClicked">{{ entry.name }}</div>
23
24
  <div class="details">
24
25
  {{ contributors }} {{ entry.publishDate ? `(${publishYear})` : '' }}
@@ -371,6 +372,15 @@ export default {
371
372
  color: #484848;
372
373
  cursor: pointer;
373
374
  }
375
+
376
+ .source-tag {
377
+ margin-bottom: 0.75rem;
378
+ margin-right: 2rem;
379
+ position: absolute;
380
+ bottom: 0;
381
+ right: 0;
382
+ }
383
+
374
384
  .card {
375
385
  padding-top: 18px;
376
386
  position: relative;
@@ -0,0 +1,317 @@
1
+ <template>
2
+ <div class="dataset-card-container" ref="container">
3
+ <div class="dataset-card" ref="card">
4
+ <div class="seperator-path"></div>
5
+ <div v-loading="loading" class="card" >
6
+ <span class="card-left">
7
+ <a class="card-image-container" :href="entry.exposure" target="_blank">
8
+ <img
9
+ class="card-image"
10
+ :src="thumbnail"
11
+ width="210"
12
+ height="210"
13
+ :alt="entry.title"
14
+ loading="lazy"
15
+ />
16
+ </a>
17
+ </span>
18
+ <div class="card-right">
19
+ <el-tag type="primary" class="source-tag">PMR</el-tag>
20
+ <div>
21
+ <h4 class="title">{{ entry.title }}</h4>
22
+ <div class="details">
23
+ {{ entry.authors }}
24
+ </div>
25
+ </div>
26
+ <div class="details" v-if="entry.description">
27
+ {{ entry.description }}
28
+ </div>
29
+ <div class="buttons-group">
30
+ <a
31
+ :href="entry.exposure"
32
+ target="_blank"
33
+ class="el-button el-button--small button"
34
+ >
35
+ Exposure
36
+ </a>
37
+ <a
38
+ v-if="entry.omex"
39
+ :href="entry.omex"
40
+ target="_blank"
41
+ class="el-button el-button--small button"
42
+ >
43
+ COMBINE archive
44
+ </a>
45
+ <el-button v-if="entry.flatmap"
46
+ size="small"
47
+ class="button"
48
+ @click="onFlatmapClick(entry.flatmap)"
49
+ >
50
+ Flatmap
51
+ </el-button>
52
+ <el-button v-if="entry.simulation"
53
+ size="small"
54
+ class="button"
55
+ @click="onSimulationClick(entry.simulation)"
56
+ >
57
+ Simulation
58
+ </el-button>
59
+ </div>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ </template>
65
+
66
+
67
+ <script>
68
+ /* eslint-disable no-alert, no-console */
69
+ import {
70
+ ElButton,
71
+ ElIcon,
72
+ ElTag
73
+ } from 'element-plus'
74
+
75
+ /**
76
+ * Entry Object - Data types
77
+ * ---------------------------------------
78
+ "exposure"
79
+ type: String
80
+ description: The exposure URL
81
+
82
+ "title"
83
+ type: String
84
+ description: The title
85
+
86
+ "sha"
87
+ type: String
88
+ description:
89
+
90
+ "workspace"
91
+ type: String
92
+ description: The workspace URL
93
+
94
+ "omex"
95
+ type: String
96
+ description:
97
+
98
+ "image"
99
+ type: String
100
+ description: The image URL
101
+
102
+ "authors"
103
+ type: String
104
+ description: Comma separated values if more than one
105
+
106
+ "description"
107
+ type: String
108
+ description: The description
109
+
110
+ "flatmap"
111
+ type: String
112
+ descriptin: (Optional) to link to flatmap
113
+
114
+ "simulation"
115
+ type: String
116
+ descriptin: (Optional) simulation resource
117
+ * ---------------------------------------
118
+ */
119
+
120
+ const placeholderThumbnail = 'assets/missing-image.svg';
121
+
122
+ export default {
123
+ name: "PMRDatasetCard",
124
+ components: {
125
+ ElButton,
126
+ ElIcon,
127
+ ElTag
128
+ },
129
+ props: {
130
+ /**
131
+ * Object containing information for
132
+ * the required viewing.
133
+ */
134
+ entry: {
135
+ type: Object,
136
+ default: () => {}
137
+ },
138
+ envVars: {
139
+ type: Object,
140
+ default: () => {}
141
+ },
142
+ },
143
+ data: function () {
144
+ return {
145
+ thumbnail: this.entry.image || placeholderThumbnail,
146
+ loading: false,
147
+ };
148
+ },
149
+ methods: {
150
+ onFlatmapClick: function (data) {
151
+ this.emitPMRActionClick({
152
+ type: 'Flatmap',
153
+ resource: data
154
+ });
155
+ },
156
+ onSimulationClick: function (data) {
157
+ this.emitPMRActionClick({
158
+ type: 'Simulation',
159
+ resource: data,
160
+ });
161
+ },
162
+ emitPMRActionClick: function (data) {
163
+ const payload = {
164
+ ...data,
165
+ name: this.entry.title,
166
+ description: this.entry.description,
167
+ apiLocation: this.envVars.API_LOCATION,
168
+ };
169
+ this.$emit('pmr-action-click', payload);
170
+ },
171
+ }
172
+ };
173
+ </script>
174
+
175
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
176
+ <style scoped lang="scss">
177
+
178
+ .dataset-card-container {
179
+ padding: 0 1rem;
180
+ }
181
+
182
+ .dataset-card {
183
+ position: relative;
184
+ min-height:17rem;
185
+ }
186
+
187
+ .title {
188
+ padding-bottom: 0.75rem;
189
+ font-family: Asap;
190
+ font-size: 14px;
191
+ font-weight: bold;
192
+ font-stretch: normal;
193
+ font-style: normal;
194
+ line-height: 1.5;
195
+ letter-spacing: 1.05px;
196
+ color: #484848;
197
+ }
198
+ .card {
199
+ font-family: Asap;
200
+ padding-top: 18px;
201
+ position: relative;
202
+ display: flex;
203
+
204
+ h4,
205
+ p {
206
+ margin: 0;
207
+ }
208
+ }
209
+
210
+ .card-left{
211
+ flex: 1;
212
+ }
213
+
214
+ .card-right {
215
+ flex: 1.3;
216
+ display: flex;
217
+ flex-direction: column;
218
+ gap: 1rem;
219
+ min-height: 17rem;
220
+ }
221
+
222
+ .details {
223
+ font-family: Asap;
224
+ font-size: 14px;
225
+ font-weight: normal;
226
+ font-stretch: normal;
227
+ font-style: normal;
228
+ line-height: 1.5;
229
+ letter-spacing: 1.05px;
230
+ color: #484848;
231
+ }
232
+
233
+ .el-button {
234
+ font-family: Asap;
235
+ font-size: 14px;
236
+ font-weight: normal;
237
+ font-stretch: normal;
238
+ font-style: normal;
239
+ line-height: normal;
240
+ letter-spacing: normal;
241
+ text-decoration: none;
242
+ }
243
+
244
+ .button {
245
+ background-color: $app-primary-color;
246
+ border: $app-primary-color;
247
+ color: white;
248
+ transition: all 0.3s ease;
249
+
250
+ &:hover,
251
+ &:focus {
252
+ color: white;
253
+ background-color: $app-primary-color;
254
+ outline: none;
255
+ }
256
+ }
257
+
258
+ .card-image-container {
259
+ display: block;
260
+ width: 244px; // gallery image full-size width
261
+ }
262
+
263
+ .card-image {
264
+ max-width: 100%;
265
+ height: auto;
266
+ object-fit: cover;
267
+ }
268
+
269
+ .buttons-group {
270
+ display: flex;
271
+ flex-direction: row;
272
+ flex-wrap: wrap;
273
+ gap: 0.75rem;
274
+
275
+ .el-button {
276
+ border-radius: 4px!important;
277
+ font-size: 0.75rem!important;
278
+ padding: 0.2rem 0.2rem!important;
279
+ background: #f9f2fc!important;
280
+ border: 1px solid $app-primary-color!important;
281
+ color: $app-primary-color!important;
282
+
283
+ &.active {
284
+ background: $app-primary-color!important;
285
+ border: 1px solid $app-primary-color!important;
286
+ color: #fff!important;
287
+ }
288
+ }
289
+
290
+ .el-button + .el-button {
291
+ margin: 0;
292
+ }
293
+ }
294
+
295
+ .source-tag {
296
+ margin-bottom: 0.75rem;
297
+ margin-right: 2rem;
298
+ position: absolute;
299
+ bottom: 0;
300
+ right: 0;
301
+ }
302
+
303
+ .loading-icon {
304
+ z-index: 20;
305
+ width: 40px;
306
+ height: 40px;
307
+ left: 80px;
308
+ }
309
+
310
+ .loading-icon ::v-deep(.el-loading-mask) {
311
+ background-color: rgba(117, 190, 218, 0.0) !important;
312
+ }
313
+
314
+ .loading-icon ::v-deep(.el-loading-spinner .path) {
315
+ stroke: $app-primary-color;
316
+ }
317
+ </style>
@@ -266,12 +266,29 @@ export default {
266
266
  }
267
267
  })
268
268
  })
269
+
270
+ this.populatePMRinCascader();
269
271
  })
270
272
  .finally(() => {
271
273
  resolve()
272
274
  })
273
275
  })
274
276
  },
277
+ /**
278
+ * Add PMR checkbox in filters (cascader)
279
+ */
280
+ populatePMRinCascader: function () {
281
+ for (let i = 0; i < this.options.length; i += 1) {
282
+ const option = this.options[i];
283
+ // match with "Data type"'s' key
284
+ if (option.key === 'item.types.name') {
285
+ option.children.push({
286
+ label: 'PMR',
287
+ value: this.createCascaderItemValue("Data type", "PMR"),
288
+ });
289
+ }
290
+ }
291
+ },
275
292
  /**
276
293
  * Create manual events when cascader tag is closed
277
294
  */
@@ -54,13 +54,6 @@
54
54
  @confirm-delete="$emit('confirm-delete', $event)"
55
55
  />
56
56
  </template>
57
- <template v-else-if="tab.type === 'connectivityExplorer'">
58
- <connectivity-explorer
59
- :ref="'connectivityExplorerTab_' + tab.id"
60
- v-show="tab.id === activeTabId"
61
- :envVars="envVars"
62
- />
63
- </template>
64
57
  <template v-else>
65
58
  <SidebarContent
66
59
  class="sidebar-content-container"
@@ -70,6 +63,7 @@
70
63
  :ref="'searchTab_' + tab.id"
71
64
  @search-changed="searchChanged(tab.id, $event)"
72
65
  @hover-changed="hoverChanged($event)"
66
+ @pmr-action-click="onPmrActionClick"
73
67
  />
74
68
  </template>
75
69
  </template>
@@ -91,7 +85,6 @@ import EventBus from './EventBus.js'
91
85
  import Tabs from './Tabs.vue'
92
86
  import AnnotationTool from './AnnotationTool.vue'
93
87
  import ConnectivityInfo from './ConnectivityInfo.vue'
94
- import ConnectivityExplorer from './ConnectivityExplorer.vue'
95
88
 
96
89
  /**
97
90
  * Aims to provide a sidebar for searching capability for SPARC portal.
@@ -106,7 +99,6 @@ export default {
106
99
  Icon,
107
100
  ConnectivityInfo,
108
101
  AnnotationTool,
109
- ConnectivityExplorer,
110
102
  },
111
103
  name: 'SideBar',
112
104
  props: {
@@ -135,8 +127,7 @@ export default {
135
127
  default: () => [
136
128
  { id: 1, title: 'Search', type: 'search' },
137
129
  { id: 2, title: 'Connectivity', type: 'connectivity' },
138
- { id: 3, title: 'Annotation', type: 'annotation' },
139
- { id: 4, title: 'Connectivity Explorer', type: 'connectivityExplorer' }
130
+ { id: 3, title: 'Annotation', type: 'annotation' }
140
131
  ],
141
132
  },
142
133
  /**
@@ -181,6 +172,7 @@ export default {
181
172
  data: function () {
182
173
  return {
183
174
  drawerOpen: false,
175
+ initFilters: { filter: [], searchInput: '' },
184
176
  availableAnatomyFacets: []
185
177
  }
186
178
  },
@@ -235,7 +227,9 @@ export default {
235
227
  this.drawerOpen = !this.drawerOpen
236
228
  },
237
229
  openSearch: function (facets, query) {
238
- this.drawerOpen = true
230
+ this.initFilters.filter = facets;
231
+ this.initFilters.searchInput = query;
232
+ this.drawerOpen = true;
239
233
  // Because refs are in v-for, nextTick is needed here
240
234
  this.$nextTick(() => {
241
235
  const searchTabRef = this.getSearchTabRefById(1);
@@ -262,8 +256,6 @@ export default {
262
256
  refIdPrefix = 'connectivityTab_';
263
257
  } else if (type === 'annotation') {
264
258
  refIdPrefix = 'annotationTab_';
265
- } else if (type === 'connectivityExplorer') {
266
- refIdPrefix = 'connectivityExplorerTab_';
267
259
  }
268
260
  const tabObj = this.getTabByIdAndType(id, type);
269
261
  const tabRefId = refIdPrefix + tabObj.id;
@@ -310,6 +302,9 @@ export default {
310
302
  setDrawerOpen: function (value = true) {
311
303
  this.drawerOpen = value
312
304
  },
305
+ onPmrActionClick: function (payload) {
306
+ this.$emit('actionClick', payload);
307
+ },
313
308
  /**
314
309
  * The function to emit 'tabClicked' event with tab's `id` and tab's `type`
315
310
  * when user clicks the sidebar tab.
@@ -339,7 +334,7 @@ export default {
339
334
  activeTabs: function() {
340
335
  const tabs = []
341
336
  this.tabs.forEach((tab) => {
342
- if (tab.type === "search" || tab.type === "connectivityExplorer") {
337
+ if (tab.type === "search") {
343
338
  tabs.push(tab)
344
339
  } else if (tab.type === "connectivity") {
345
340
  if (this.connectivityInfo) {