@abi-software/map-side-bar 2.7.2-beta.3 → 2.7.2-beta.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.
@@ -213,60 +213,7 @@ export default {
213
213
  )
214
214
  return value
215
215
  },
216
- processOptions: function () {
217
- // create top level of options in cascader
218
- this.options.forEach((facet, i) => {
219
- this.options[i].total = this.countTotalFacet(facet)
220
-
221
- this.options[i].label = convertReadableLabel(facet.label)
222
- this.options[i].value = this.createCascaderItemValue(
223
- facet.key,
224
- undefined
225
- )
226
-
227
- // put "Show all" as first option
228
- this.options[i].children.unshift({
229
- value: this.createCascaderItemValue('Show all'),
230
- label: 'Show all',
231
- })
232
-
233
- // populate second level of options
234
- this.options[i].children.forEach((facetItem, j) => {
235
- // Format labels except funding program
236
- if (this.options[i].children[j].facetPropPath !== 'pennsieve.organization.name') {
237
- this.options[i].children[j].label = convertReadableLabel(
238
- facetItem.label
239
- )
240
- }
241
- this.options[i].children[j].value =
242
- this.createCascaderItemValue(facet.label, facetItem.label)
243
- if (
244
- this.options[i].children[j].children &&
245
- this.options[i].children[j].children.length > 0
246
- ) {
247
- this.options[i].children[j].children.forEach((term, k) => {
248
- this.options[i].children[j].children[k].label =
249
- convertReadableLabel(term.label)
250
- this.options[i].children[j].children[k].value =
251
- this.createCascaderItemValue(
252
- facet.label,
253
- facetItem.label,
254
- term.label
255
- )
256
- })
257
- }
258
- })
259
- })
260
- },
261
216
  populateCascader: function () {
262
- if (this.entry.options) {
263
- return new Promise((resolve) => {
264
- this.facets = this.entry.options
265
- this.options = this.entry.options
266
- this.processOptions()
267
- resolve();
268
- });
269
- }
270
217
  return new Promise((resolve) => {
271
218
  // Algolia facet serach
272
219
  this.algoliaClient
@@ -275,7 +222,50 @@ export default {
275
222
  this.facets = data
276
223
  EventBus.emit('available-facets', data)
277
224
  this.options = data
278
- this.processOptions()
225
+
226
+ // create top level of options in cascader
227
+ this.options.forEach((facet, i) => {
228
+ this.options[i].total = this.countTotalFacet(facet)
229
+
230
+ this.options[i].label = convertReadableLabel(facet.label)
231
+ this.options[i].value = this.createCascaderItemValue(
232
+ facet.key,
233
+ undefined
234
+ )
235
+
236
+ // put "Show all" as first option
237
+ this.options[i].children.unshift({
238
+ value: this.createCascaderItemValue('Show all'),
239
+ label: 'Show all',
240
+ })
241
+
242
+ // populate second level of options
243
+ this.options[i].children.forEach((facetItem, j) => {
244
+ // Format labels except funding program
245
+ if (this.options[i].children[j].facetPropPath !== 'pennsieve.organization.name') {
246
+ this.options[i].children[j].label = convertReadableLabel(
247
+ facetItem.label
248
+ )
249
+ }
250
+ this.options[i].children[j].value =
251
+ this.createCascaderItemValue(facet.label, facetItem.label)
252
+ if (
253
+ this.options[i].children[j].children &&
254
+ this.options[i].children[j].children.length > 0
255
+ ) {
256
+ this.options[i].children[j].children.forEach((term, k) => {
257
+ this.options[i].children[j].children[k].label =
258
+ convertReadableLabel(term.label)
259
+ this.options[i].children[j].children[k].value =
260
+ this.createCascaderItemValue(
261
+ facet.label,
262
+ facetItem.label,
263
+ term.label
264
+ )
265
+ })
266
+ }
267
+ })
268
+ })
279
269
  })
280
270
  .finally(() => {
281
271
  resolve()
@@ -745,18 +735,13 @@ export default {
745
735
  removeTopLevelCascaderCheckboxes: function () {
746
736
  // Next tick allows the cascader menu to change
747
737
  this.$nextTick(() => {
748
- const cascadePanels = document.querySelectorAll('.sidebar-cascader-popper .el-cascader-menu__list');
749
-
750
- cascadePanels.forEach(panel => {
751
- const panelText = panel.textContent;
752
- const expandArrow = panel.querySelector('.el-icon.arrow-right');
753
-
754
- if (!panelText.includes('Show all') && expandArrow) {
755
- panel.querySelectorAll('.el-checkbox__input').forEach(checkbox => {
756
- checkbox.style.display = 'none';
757
- });
758
- }
759
- });
738
+ let cascadePanels = document.querySelectorAll(
739
+ '.sidebar-cascader-popper .el-cascader-menu__list'
740
+ )
741
+ // Hide the checkboxes on the first level of the cascader
742
+ cascadePanels[0]
743
+ .querySelectorAll('.el-checkbox__input')
744
+ .forEach((el) => (el.style.display = 'none'))
760
745
  })
761
746
  },
762
747
  /*
@@ -164,22 +164,12 @@ function generateUUID() {
164
164
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
165
165
  }
166
166
 
167
- const capitalise = function (txt) {
168
- return txt.charAt(0).toUpperCase() + txt.slice(1)
169
- }
170
-
171
167
  export default {
172
168
  name: 'SearchHistory',
173
169
  components: {
174
170
  Tag,
175
171
  Select
176
172
  },
177
- props: {
178
- localStorageKey: {
179
- type: String,
180
- default: '',
181
- },
182
- },
183
173
  data() {
184
174
  return {
185
175
  searchHistory: [],
@@ -196,14 +186,16 @@ export default {
196
186
  },
197
187
  methods: {
198
188
  getSearchHistory() {
199
- if (localStorage.getItem(this.localStorageKey)) {
200
- this.searchHistory = JSON.parse(localStorage.getItem(this.localStorageKey))
189
+ if (localStorage.getItem('sparc.science-sidebar-search-history')) {
190
+ this.searchHistory = JSON.parse(
191
+ localStorage.getItem('sparc.science-sidebar-search-history')
192
+ )
201
193
  } else {
202
194
  this.searchHistory = []
203
195
  }
204
196
  },
205
197
  clearSearchHistory() {
206
- localStorage.removeItem(this.localStorageKey)
198
+ localStorage.removeItem('sparc.science-sidebar-search-history')
207
199
  this.searchHistory = []
208
200
  },
209
201
  sortFilters(a, b) {
@@ -227,7 +219,7 @@ export default {
227
219
  }
228
220
  return filterItem;
229
221
  },
230
- addSearchToHistory(filters = [], search = '', data = []) {
222
+ addSearchToHistory(filters = [], search = '') {
231
223
  search = search.trim() // remove whitespace
232
224
 
233
225
  const isExistingItem = this.searchHistory.some((item) => {
@@ -252,11 +244,10 @@ export default {
252
244
  });
253
245
 
254
246
  if (!isExistingItem) {
255
- const {label, longLabel} = this.searchHistoryItemLabel(search, filters, data);
247
+ const {label, longLabel} = this.searchHistoryItemLabel(search, filters);
256
248
  const newItem = {
257
249
  filters: filters,
258
250
  search: search,
259
- data: data,
260
251
  saved: false,
261
252
  label: label,
262
253
  longLabel: longLabel,
@@ -272,7 +263,10 @@ export default {
272
263
  this.trimSearchHistory();
273
264
 
274
265
  // Save new data
275
- localStorage.setItem(this.localStorageKey, JSON.stringify(this.searchHistory));
266
+ localStorage.setItem(
267
+ 'sparc.science-sidebar-search-history',
268
+ JSON.stringify(this.searchHistory)
269
+ );
276
270
  }
277
271
  },
278
272
  /**
@@ -331,7 +325,7 @@ export default {
331
325
  }
332
326
 
333
327
  if (!item.label) {
334
- const {label, longLabel} = this.searchHistoryItemLabel(item.search, item.filters, item.data);
328
+ const {label, longLabel} = this.searchHistoryItemLabel(item.search, item.filters);
335
329
  item['label'] = label;
336
330
  item['longLabel'] = longLabel;
337
331
  }
@@ -362,33 +356,28 @@ export default {
362
356
  this.trimSearchHistory();
363
357
 
364
358
  // Save updated data
365
- localStorage.setItem(this.localStorageKey, JSON.stringify(this.searchHistory))
359
+ localStorage.setItem(
360
+ 'sparc.science-sidebar-search-history',
361
+ JSON.stringify(this.searchHistory)
362
+ )
366
363
  },
367
364
  search: function (item) {
368
365
  this.$emit('search', item)
369
366
  },
370
- searchHistoryItemLabel: function (search, filters, data) {
367
+ searchHistoryItemLabel: function (search, filters) {
371
368
  let label = search ? `"${search.trim()}"` : '';
372
369
  let longLabel = '';
373
370
  let filterItems = [];
374
371
  let filterLabels = [];
375
- let dataLabels = [];
376
372
 
377
373
  if (filters) {
378
374
  filterItems = filters.filter((filterItem) => filterItem.facet !== 'Show all');
379
375
  filterLabels = filterItems.map((item) => item.facet2 || item.facet);
380
- if (data) {
381
- dataLabels = data.map((item) => capitalise(item.label));
382
- }
383
376
  }
384
-
385
377
 
386
378
  if (label && filterItems.length) {
387
379
  longLabel += label;
388
380
  longLabel += `, ${filterLabels.join(', ')}`;
389
- if (data.length) {
390
- longLabel += `(${dataLabels.join(', ')})`;
391
- }
392
381
  label += ` (+${filterItems.length})`;
393
382
  }
394
383
 
@@ -447,6 +436,7 @@ export default {
447
436
  display: flex;
448
437
  align-items: center;
449
438
  gap: 6px;
439
+ transform: translateZ(0);
450
440
  }
451
441
 
452
442
  .search-tag.el-tag {
@@ -22,15 +22,29 @@
22
22
  </div>
23
23
  <div class="sidebar-container">
24
24
  <Tabs
25
- v-if="tabEntries.length > 1"
26
- :tabEntries="tabEntries"
25
+ v-if="activeTabs.length > 1"
26
+ :tabTitles="activeTabs"
27
27
  :activeId="activeTabId"
28
- @tabClicked="tabClicked"
29
- @tabClosed="tabClosed"
28
+ @titleClicked="tabClicked"
29
+ @tab-close="tabClose"
30
30
  />
31
31
  <template v-for="tab in tabs" key="tab.id">
32
- <template v-if="tab.type === 'annotation'">
33
- <AnnotationTool
32
+ <!-- Connectivity Info -->
33
+ <template v-if="tab.type === 'connectivity' && connectivityInfo">
34
+ <connectivity-info
35
+ :entry="connectivityInfo"
36
+ :availableAnatomyFacets="availableAnatomyFacets"
37
+ v-if="tab.id === activeTabId"
38
+ :envVars="envVars"
39
+ :ref="'connectivityTab_' + tab.id"
40
+ :useDOIFormatter="useDOIFormatter"
41
+ @show-connectivity="showConnectivity"
42
+ @show-reference-connectivities="onShowReferenceConnectivities"
43
+ @connectivity-component-click="onConnectivityComponentClick"
44
+ />
45
+ </template>
46
+ <template v-else-if="tab.type === 'annotation'">
47
+ <annotation-tool
34
48
  :ref="'annotationTab_' + tab.id"
35
49
  v-show="tab.id === activeTabId"
36
50
  :annotationEntry="annotationEntry"
@@ -41,23 +55,6 @@
41
55
  @confirm-delete="$emit('confirm-delete', $event)"
42
56
  />
43
57
  </template>
44
- <template v-else-if="tab.type === 'connectivityExplorer'">
45
- <ConnectivityExplorer
46
- :ref="'connectivityExplorerTab_' + tab.id"
47
- v-show="tab.id === activeTabId"
48
- :connectivityKnowledge="connectivityKnowledge"
49
- :envVars="envVars"
50
- :connectivityEntry="connectivityEntry"
51
- :availableAnatomyFacets="availableAnatomyFacets"
52
- @search-changed="searchChanged(tab.id, $event)"
53
- @hover-changed="hoverChanged($event)"
54
- @show-connectivity="showConnectivity"
55
- @show-reference-connectivities="onShowReferenceConnectivities"
56
- @connectivity-clicked="onConnectivityClicked"
57
- @connectivity-hovered="onConnectivityHovered"
58
- @connectivity-explorer-clicked="onConnectivityExplorerClicked"
59
- />
60
- </template>
61
58
  <template v-else>
62
59
  <SidebarContent
63
60
  class="sidebar-content-container"
@@ -87,7 +84,7 @@ import SidebarContent from './SidebarContent.vue'
87
84
  import EventBus from './EventBus.js'
88
85
  import Tabs from './Tabs.vue'
89
86
  import AnnotationTool from './AnnotationTool.vue'
90
- import ConnectivityExplorer from './ConnectivityExplorer.vue'
87
+ import ConnectivityInfo from './ConnectivityInfo.vue'
91
88
 
92
89
  /**
93
90
  * Aims to provide a sidebar for searching capability for SPARC portal.
@@ -100,8 +97,8 @@ export default {
100
97
  ElIconArrowRight,
101
98
  Drawer,
102
99
  Icon,
100
+ ConnectivityInfo,
103
101
  AnnotationTool,
104
- ConnectivityExplorer,
105
102
  },
106
103
  name: 'SideBar',
107
104
  props: {
@@ -122,6 +119,24 @@ export default {
122
119
  type: Object,
123
120
  default: () => {},
124
121
  },
122
+ /**
123
+ * The array of objects to show multiple sidebar contents.
124
+ */
125
+ tabs: {
126
+ type: Array,
127
+ default: () => [
128
+ { id: 1, title: 'Search', type: 'search' },
129
+ { id: 2, title: 'Connectivity', type: 'connectivity' },
130
+ { id: 3, title: 'Annotation', type: 'annotation' }
131
+ ],
132
+ },
133
+ /**
134
+ * The active tab id for default tab.
135
+ */
136
+ activeTabId: {
137
+ type: Number,
138
+ default: 1,
139
+ },
125
140
  /**
126
141
  * The option to show or hide sidebar on page load.
127
142
  */
@@ -132,16 +147,16 @@ export default {
132
147
  /**
133
148
  * The connectivity info data to show in sidebar.
134
149
  */
135
- connectivityEntry: {
150
+ connectivityInfo: {
136
151
  type: Object,
137
- default: {},
152
+ default: null,
138
153
  },
139
154
  /**
140
155
  * The annotation data to show in sidebar.
141
156
  */
142
157
  annotationEntry: {
143
158
  type: Object,
144
- default: {},
159
+ default: null,
145
160
  },
146
161
  createData: {
147
162
  type: Object,
@@ -153,27 +168,23 @@ export default {
153
168
  y: 0,
154
169
  },
155
170
  },
156
- connectivityKnowledge: {
157
- type: Array,
158
- default: [],
171
+ /**
172
+ * The option to use DOI.org as citation formatter.
173
+ * If set to `false`, citation.js will be used.
174
+ * Default is `true`.
175
+ */
176
+ useDOIFormatter: {
177
+ type: Boolean,
178
+ default: true,
159
179
  },
160
180
  },
161
181
  data: function () {
162
182
  return {
163
183
  drawerOpen: false,
164
- availableAnatomyFacets: [],
165
- activeTabId: 1,
166
- tabs: [
167
- { title: 'Search', id: 1, type: 'search', closable: false },
168
- { title: 'Connectivity Explorer', id: 2, type: 'connectivityExplorer', closable: false },
169
- { title: 'Annotation', id: 3, type: 'annotation', closable: true },
170
- ]
184
+ availableAnatomyFacets: []
171
185
  }
172
186
  },
173
187
  methods: {
174
- onConnectivityExplorerClicked: function (data) {
175
- this.$emit('connectivity-explorer-clicked', data)
176
- },
177
188
  /**
178
189
  * This event is emitted when the mouse hover are changed.
179
190
  * @arg data
@@ -196,18 +207,11 @@ export default {
196
207
  this.$emit('show-reference-connectivities', refSource);
197
208
  },
198
209
  /**
199
- * This function is triggered after connectivity term is clicked.
200
- * @arg data
201
- */
202
- onConnectivityClicked: function (data) {
203
- this.$emit('connectivity-clicked', data);
204
- },
205
- /**
206
- * This function is triggered after connectivity term is hovered.
210
+ * This function is triggered after a connectivity component is clicked.
207
211
  * @arg data
208
212
  */
209
- onConnectivityHovered: function (data) {
210
- this.$emit('connectivity-hovered', data);
213
+ onConnectivityComponentClick: function (data) {
214
+ this.$emit('connectivity-component-click', data);
211
215
  },
212
216
  /**
213
217
  * This event is emitted when the search filters are changed.
@@ -230,31 +234,43 @@ export default {
230
234
  toggleDrawer: function () {
231
235
  this.drawerOpen = !this.drawerOpen
232
236
  },
233
- openConnectivitySearch: function (facets, query) {
234
- this.drawerOpen = true;
235
- // Because refs are in v-for, nextTick is needed here
236
- this.$nextTick(() => {
237
- const connectivityExplorerTabRef = this.getTabRef(2, 'connectivityExplorer', true);
238
- connectivityExplorerTabRef.openSearch(facets, query);
239
- })
240
- },
241
237
  openSearch: function (facets, query) {
242
238
  this.drawerOpen = true
243
239
  // Because refs are in v-for, nextTick is needed here
244
240
  this.$nextTick(() => {
245
- const searchTabRef = this.getTabRef(1, 'search', true);
241
+ const searchTabRef = this.getSearchTabRefById(1);
246
242
  searchTabRef.openSearch(facets, query);
247
243
  })
248
244
  },
245
+ /**
246
+ * Get the tab object by tab id and type.
247
+ * If not found, return the first available tab.
248
+ */
249
+ getTabByIdAndType: function (id, type) {
250
+ const tabId = id || this.activeTabId;
251
+ const tabType = type || 'search'; // default to search tab
252
+ const tabObj = this.activeTabs.find((tab) => tab.id === tabId && tab.type === tabType);
253
+ const firstAvailableTab = this.activeTabs[0];
254
+ return tabObj || firstAvailableTab;
255
+ },
249
256
  /**
250
257
  * Get the ref id of the tab by id and type.
251
258
  */
252
- getTabRef: function (id = 1, type = 'search', open = false) {
253
- const matchedTab = this.tabEntries.filter((tab) => tab.id === id && tab.type === type);
254
- const tabInfo = matchedTab.length ? matchedTab : this.tabEntries;
255
- const tabRef = type + 'Tab_' + tabInfo[0].id;
256
- if (open) this.tabClicked({ id, type });
257
- return this.$refs[tabRef][0];
259
+ getTabRefId: function (id, type) {
260
+ let refIdPrefix = 'searchTab_'; // default to search tab
261
+ if (type === 'connectivity') {
262
+ refIdPrefix = 'connectivityTab_';
263
+ } else if (type === 'annotation') {
264
+ refIdPrefix = 'annotationTab_';
265
+ }
266
+ const tabObj = this.getTabByIdAndType(id, type);
267
+ const tabRefId = refIdPrefix + tabObj.id;
268
+ return tabRefId;
269
+ },
270
+ getSearchTabRefById: function (id) {
271
+ const searchTabId = id || 1; // to use id when there are multiple search tabs
272
+ const searchTabRefId = this.getTabRefId(searchTabId, 'search');
273
+ return this.$refs[searchTabRefId][0];
258
274
  },
259
275
  /**
260
276
  * The function to add filters to sidebar search.
@@ -268,7 +284,7 @@ export default {
268
284
 
269
285
  // Because refs are in v-for, nextTick is needed here
270
286
  this.$nextTick(() => {
271
- const searchTabRef = this.getTabRef(1, 'search', true);
287
+ const searchTabRef = this.getSearchTabRefById(1);
272
288
  searchTabRef.addFilter(filter)
273
289
  })
274
290
  },
@@ -276,7 +292,7 @@ export default {
276
292
  this.drawerOpen = true
277
293
  // Because refs are in v-for, nextTick is needed here
278
294
  this.$nextTick(() => {
279
- const searchTabRef = this.getTabRef(1, 'search', true);
295
+ const searchTabRef = this.getSearchTabRefById(1);
280
296
  searchTabRef.openSearch(
281
297
  '',
282
298
  undefined,
@@ -286,17 +302,27 @@ export default {
286
302
  })
287
303
  },
288
304
  getAlgoliaFacets: async function () {
289
- const searchTabRef = this.getTabRef(1, 'search');
305
+ const searchTabRef = this.getSearchTabRefById(1);
290
306
  return await searchTabRef.getAlgoliaFacets()
291
307
  },
292
308
  setDrawerOpen: function (value = true) {
293
309
  this.drawerOpen = value
294
310
  },
295
- tabClicked: function (tab) {
296
- this.activeTabId = tab.id
311
+ /**
312
+ * The function to emit 'tabClicked' event with tab's `id` and tab's `type`
313
+ * when user clicks the sidebar tab.
314
+ * @param {Object} {id, type}
315
+ * @public
316
+ */
317
+ tabClicked: function ({id, type}) {
318
+ /**
319
+ * This event is emitted when user click sidebar's tab.
320
+ * @arg {Object} {id, type}
321
+ */
322
+ this.$emit('tabClicked', {id, type});
297
323
  },
298
- tabClosed: function (tab) {
299
- this.$emit('tabClosed', tab);
324
+ tabClose: function (id) {
325
+ this.$emit('tab-close', id);
300
326
  },
301
327
  /**
302
328
  * To receive error message for connectivity graph
@@ -308,12 +334,22 @@ export default {
308
334
  },
309
335
  computed: {
310
336
  // This should respect the information provided by the property
311
- tabEntries: function () {
312
- return this.tabs.filter((tab) =>
313
- tab.type === "search" ||
314
- tab.type === "connectivityExplorer" ||
315
- (tab.type === "annotation" && this.annotationEntry && Object.keys(this.annotationEntry).length > 0)
316
- );
337
+ activeTabs: function() {
338
+ const tabs = []
339
+ this.tabs.forEach((tab) => {
340
+ if (tab.type === "search") {
341
+ tabs.push(tab)
342
+ } else if (tab.type === "connectivity") {
343
+ if (this.connectivityInfo) {
344
+ tabs.push(tab);
345
+ }
346
+ } else if (tab.type === "annotation") {
347
+ if (this.annotationEntry && Object.keys(this.annotationEntry).length > 0) {
348
+ tabs.push(tab);
349
+ }
350
+ }
351
+ })
352
+ return tabs;
317
353
  },
318
354
  },
319
355
  created: function () {
@@ -369,6 +405,7 @@ export default {
369
405
  EventBus.on('available-facets', (payLoad) => {
370
406
  this.availableAnatomyFacets = payLoad.find((facet) => facet.label === 'Anatomical Structure').children
371
407
  })
408
+
372
409
  },
373
410
  }
374
411
  </script>
@@ -32,7 +32,6 @@
32
32
  ></SearchFilters>
33
33
  <SearchHistory
34
34
  ref="searchHistory"
35
- localStorageKey="sparc.science-dataset-search-history"
36
35
  @search="searchHistorySearch"
37
36
  ></SearchHistory>
38
37
  <div class="content scrollbar" v-loading="loadingCards" ref="content">
@@ -165,8 +164,7 @@ export default {
165
164
  },
166
165
  methods: {
167
166
  hoverChanged: function (data) {
168
- const payload = data ? { ...data, type: 'dataset' } : data
169
- this.$emit('hover-changed', payload)
167
+ this.$emit('hover-changed', data)
170
168
  },
171
169
  resetSearch: function () {
172
170
  this.numberOfHits = 0