@abi-software/map-side-bar 1.2.0-beta.1 → 1.2.0-beta.10

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.
@@ -5,7 +5,7 @@
5
5
  :cardWidth="10"
6
6
  :items="galleryItems"
7
7
  :max-width="maxWidth"
8
- :show-indicator-bar="true"
8
+ :show-indicator-bar="false"
9
9
  :show-card-details="true"
10
10
  :highlight-active="false"
11
11
  :image-style="imageStyle"
@@ -13,6 +13,7 @@
13
13
  :body-style="bodyStyle"
14
14
  :shadow="shadow"
15
15
  @card-clicked="cardClicked"
16
+ ref="gallery"
16
17
  />
17
18
  </div>
18
19
  </template>
@@ -35,12 +36,6 @@ export default {
35
36
  components: { Gallery },
36
37
  mixins: [GalleryHelper],
37
38
  props: {
38
- datasetScicrunch: {
39
- type: Object,
40
- default: () => {
41
- return {};
42
- },
43
- },
44
39
  datasetBiolucida: {
45
40
  type: Object,
46
41
  default: () => {
@@ -55,54 +50,12 @@ export default {
55
50
  type: String,
56
51
  default: "",
57
52
  },
58
- images: {
59
- type: Array,
60
- default: () => {
61
- return [];
62
- },
63
- },
64
53
  plots: {
65
54
  type: Array,
66
55
  default: () => {
67
56
  return [];
68
57
  },
69
58
  },
70
- scaffolds: {
71
- type: Array,
72
- default: () => {
73
- return [];
74
- },
75
- },
76
- scaffoldViews: {
77
- type: Array,
78
- default: () => {
79
- return [];
80
- },
81
- },
82
- segmentations: {
83
- type: Array,
84
- default: () => {
85
- return [];
86
- },
87
- },
88
- additionalLinks: {
89
- type: Array,
90
- default: () => {
91
- return [];
92
- },
93
- },
94
- thumbnails: {
95
- type: Array,
96
- default: () => {
97
- return [];
98
- },
99
- },
100
- videos: {
101
- type: Array,
102
- default: () => {
103
- return [];
104
- },
105
- },
106
59
  datasetId: {
107
60
  type: Number,
108
61
  default: -1,
@@ -115,19 +68,44 @@ export default {
115
68
  type: String,
116
69
  default: "",
117
70
  },
71
+ category: {
72
+ type: String,
73
+ default: "All",
74
+ },
75
+ entry: {
76
+ type: Object,
77
+ default: () => {
78
+ return {};
79
+ },
80
+ },
118
81
  },
119
82
  data() {
120
83
  return {
121
84
  currentIndex: 0,
122
85
  ro: null,
123
86
  maxWidth: 3,
124
- scicrunchItems: [],
125
- biolucidaItems: [],
87
+ items: {
88
+ "Biolucida Images": [],
89
+ 'Dataset': [],
90
+ 'Images': [],
91
+ 'Scaffolds': [],
92
+ 'Segmentations': [],
93
+ 'Simulations': [],
94
+ 'Videos': [],
95
+ 'Plots': [],
96
+ },
126
97
  bodyStyle: { padding: '0px', background: '#ffffff' },
127
- imageContainerStyle: { width: '160px', height: '160px'},
98
+ imageContainerStyle: {
99
+ width: '160px',
100
+ height: '160px',
101
+ display: 'flex',
102
+ alignItems: 'center',
103
+ justifyContent: 'center',
104
+ },
128
105
  imageStyle: { maxWidth: '160px', maxHeight: '160px'},
129
106
  shadow: "never",
130
107
  bottomSpacer: { minHeight: '1.5rem' },
108
+ resetIndex: false
131
109
  };
132
110
  },
133
111
  methods: {
@@ -140,43 +118,47 @@ export default {
140
118
  this.createSimulationItems();
141
119
  this.createPlotItems();
142
120
  this.createSegmentationItems();
121
+ /* Disable these two
143
122
  this.createImageItems();
144
123
  this.createVideoItems();
124
+ */
145
125
  },
146
126
  createDatasetItem: function () {
147
127
  const link = `${this.envVars.ROOT_URL}/datasets/${this.datasetId}?type=dataset`
148
128
  if (this.datasetThumbnail) {
149
- this.scicrunchItems.push({
129
+ this.items['Dataset'].push({
150
130
  id: -1,
151
- title: link,
131
+ //Work around gallery requires a truthy string
132
+ title: " ",
152
133
  type: `Dataset ${this.datasetId}`,
153
134
  thumbnail: this.datasetThumbnail,
154
135
  link,
136
+ hideType: true,
155
137
  });
156
138
  }
157
139
  },
158
140
  createImageItems: function () {
159
- if (this.images) {
160
- this.images.forEach((image) => {
141
+ if (this.entry.images) {
142
+ this.entry.images.forEach((image) => {
161
143
  const filePath = image.dataset.path;
162
144
  const id = image.identifier;
163
145
  const linkUrl = `${this.envVars.ROOT_URL}/datasets/imageviewer?dataset_id=${this.datasetId}&dataset_version=${this.datasetVersion}&file_path=${filePath}&mimetype=${image.mimetype.name}`;
164
- this.scicrunchItems.push({
146
+ this.items['Images'].push({
165
147
  id,
166
148
  title: baseName(filePath),
167
149
  type: "Image",
168
- thumbnail: this.defaultImg,
169
150
  link: linkUrl,
151
+ hideType: true,
170
152
  });
171
153
  });
172
154
  }
173
155
  },
174
156
  createPlotItems: function () {
175
- if (this.plots) {
176
- this.plots.forEach((plot) => {
157
+ if (this.entry.plots) {
158
+ this.entry.plots.forEach((plot) => {
177
159
  const filePath = plot.dataset.path;
178
160
  const id = plot.identifier;
179
- const thumbnail = this.getThumbnailForPlot(plot, this.thumbnails);
161
+ const thumbnail = this.getThumbnailForPlot(plot, this.entry.thumbnails);
180
162
  let thumbnailURL = undefined;
181
163
  let mimetype = '';
182
164
  if (thumbnail) {
@@ -188,35 +170,57 @@ export default {
188
170
  });
189
171
  mimetype = thumbnail.mimetype.name;
190
172
  }
173
+ const plotAnnotation = plot.datacite;
174
+ const filePathPrefix = `${this.envVars.API_LOCATION}/s3-resource/${this.datasetId}/${this.datasetVersion}/files/`;
175
+ const sourceUrl = filePathPrefix + plot.dataset.path;
176
+
177
+ const metadata = JSON.parse(
178
+ plotAnnotation.supplemental_json_metadata.description
179
+ );
180
+
181
+ let supplementalData = [];
182
+ if (plotAnnotation.isDescribedBy) {
183
+ supplementalData.push({
184
+ url: filePathPrefix + plotAnnotation.isDescribedBy.path
185
+ });
186
+ }
187
+
188
+ const resource = {
189
+ dataSource: {url: sourceUrl},
190
+ metadata,
191
+ supplementalData
192
+ }
193
+
191
194
  let action = {
192
195
  label: capitalise(this.label),
193
- resource: `${this.envVars.API_LOCATION}s3-resource/${this.datasetId}/${this.datasetVersion}/files/${filePath}`,
196
+ resource: resource,
194
197
  title: "View plot",
195
198
  type: "Plot",
196
199
  discoverId: this.discoverId,
197
200
  version: this.datasetVersion,
198
201
  };
199
- this.scicrunchItems.push({
202
+ this.items['Plots'].push({
200
203
  id,
201
204
  title: baseName(filePath),
202
205
  type: "Plot",
203
206
  thumbnail: thumbnailURL,
204
207
  userData: action,
208
+ hideType: true,
205
209
  mimetype
206
210
  });
207
211
  });
208
212
  }
209
213
  },
210
214
  createScaffoldItems: function () {
211
- if (this.scaffolds) {
215
+ if (this.entry.scaffolds) {
212
216
  let index = 0;
213
- this.scaffolds.forEach((scaffold) => {
217
+ this.entry.scaffolds.forEach((scaffold) => {
214
218
  const filePath = scaffold.dataset.path;
215
219
  const id = scaffold.identifier;
216
220
  const thumbnail = this.getThumbnailForScaffold(
217
221
  scaffold,
218
- this.scaffoldViews,
219
- this.thumbnails,
222
+ this.entry.scaffoldViews,
223
+ this.entry.thumbnails,
220
224
  index
221
225
  );
222
226
  let mimetype = '';
@@ -239,27 +243,28 @@ export default {
239
243
  apiLocation: this.envVars.API_LOCATION,
240
244
  version: this.datasetVersion,
241
245
  };
242
- this.scicrunchItems.push({
246
+ this.items['Scaffolds'].push({
243
247
  id,
244
248
  title: baseName(filePath),
245
249
  type: "Scaffold",
246
250
  thumbnail: thumbnailURL,
247
251
  userData: action,
252
+ hideType: true,
248
253
  mimetype
249
254
  });
250
255
  });
251
256
  }
252
257
  },
253
258
  createSegmentationItems: function () {
254
- if (this.segmentations) {
255
- this.segmentations.forEach((segmentation) => {
259
+ if (this.entry.segmentation) {
260
+ this.entry.segmentation.forEach((segmentation) => {
256
261
  const id = segmentation.id;
257
262
  let filePath = segmentation.dataset.path;
258
263
  filePath = filePath.replaceAll(" ", "_");
259
264
  filePath = filePath.replaceAll(",", "_");
260
265
  const prefix = this.envVars.NL_LINK_PREFIX;
261
266
  const resource = {
262
- share_link: `${prefix}/dataviewer?datasetId=${this.datasetId}&version=${this.datasetVersion}&path=${filePath}`,
267
+ share_link: `${prefix}/dataviewer?datasetId=${this.datasetId}&version=${this.datasetVersion}&path=files/${filePath}`,
263
268
  };
264
269
  let action = {
265
270
  label: capitalise(this.label),
@@ -277,60 +282,54 @@ export default {
277
282
  segmentationFilePath: filePath,
278
283
  }
279
284
  );
280
- this.scicrunchItems.push({
285
+ this.items['Segmentations'].push({
281
286
  id,
282
287
  title: baseName(filePath),
283
288
  type: "Segmentation",
284
289
  thumbnail: thumbnailURL,
285
290
  userData: action,
291
+ hideType: true,
286
292
  mimetype: 'image/png',
287
293
  });
288
294
  });
289
295
  }
290
296
  },
291
297
  createSimulationItems: function () {
292
- let isSedmlResource = false;
293
- let resource = undefined;
294
- if (this.additionalLinks) {
295
- this.additionalLinks.forEach(function(el) {
296
- if (el.description == "SED-ML file") {
297
- isSedmlResource = true;
298
- resource = el.uri;
299
- } else if (!isSedmlResource && (el.description == "CellML file")) {
300
- resource = el.uri;
301
- }
298
+ if (this.entry.simulation && this.entry.simulation.length > 0) {
299
+ let action = {
300
+ label: undefined,
301
+ apiLocation: this.envVars.API_LOCATION,
302
+ version: this.datasetVersion,
303
+ title: "View simulation",
304
+ type: "Simulation",
305
+ name: this.entry.name,
306
+ description: this.entry.description,
307
+ discoverId: this.datasetId,
308
+ dataset: `${this.envVars.ROOT_URL}/datasets/${this.datasetId}?type=dataset`
309
+ };
310
+ this.items['Simulations'].push({
311
+ id: "simulation",
312
+ title: " ",
313
+ type: "Simulation",
314
+ hideType: true,
315
+ userData: action,
302
316
  });
303
- if (resource) {
304
- let action = {
305
- label: undefined,
306
- resource: resource,
307
- apiLocation: this.envVars.API_LOCATION,
308
- version: this.datasetVersion,
309
- title: "View simulation",
310
- type: "Simulation"
311
- };
312
- this.scicrunchItems.push({
313
- id: "simulation",
314
- title: resource,
315
- type: "Simulation",
316
- userData: action,
317
- });
318
- }
319
317
  }
320
318
  },
321
319
  createVideoItems: function () {
322
- if (this.videos) {
323
- this.videos.forEach((video) => {
320
+ if (this.entry.videos) {
321
+ this.entry.videos.forEach((video) => {
324
322
  const filePath = this.getS3FilePath(
325
323
  this.datasetId,
326
324
  this.datasetVersion,
327
325
  video.dataset.path
328
326
  );
329
327
  const linkUrl = `${this.envVars.ROOT_URL}/datasets/videoviewer?dataset_version=${this.datasetVersion}&dataset_id=${this.datasetId}&file_path=${filePath}&mimetype=${video.mimetype.name}`;
330
- this.scicrunchItems.push({
328
+ this.items['Videos'].push({
331
329
  title: video.name,
332
330
  type: "Video",
333
331
  thumbnail: this.defaultVideoImg,
332
+ hideType: true,
334
333
  link: linkUrl,
335
334
  });
336
335
  });
@@ -343,13 +342,31 @@ export default {
343
342
  },
344
343
  computed: {
345
344
  galleryItems() {
346
- return this.scicrunchItems.concat(this.biolucidaItems);
345
+ if (this.resetIndex) {
346
+ this.$refs.gallery.indicatorClicked(0);
347
+ }
348
+ let items = [...this.items["Dataset"]];
349
+ if (this.category === "All") {
350
+ for (const [key, value] of Object.entries(this.items)) {
351
+ if (key !== "Dataset")
352
+ items = items.concat(value);
353
+ }
354
+ return items;
355
+ }
356
+ else
357
+ return this.items[this.category];
347
358
  },
348
359
  },
349
360
  created: function () {
350
361
  this.createSciCurnchItems();
351
362
  },
352
363
  watch: {
364
+ category: function() {
365
+ this.resetIndex = true;
366
+ },
367
+ galleryItems: function() {
368
+ this.resetIndex = false;
369
+ },
353
370
  datasetBiolucida: {
354
371
  deep: true,
355
372
  immediate: true,
@@ -364,14 +381,6 @@ export default {
364
381
  id: dataset_image.image_id,
365
382
  }
366
383
  );
367
- this.getImageInfoFromBiolucida(
368
- this.envVars.API_LOCATION,
369
- items,
370
- {
371
- id: dataset_image.image_id,
372
- fetchAttempts: 0,
373
- }
374
- );
375
384
  const resource = {
376
385
  share_link: dataset_image.share_link,
377
386
  id: dataset_image.image_id,
@@ -387,16 +396,17 @@ export default {
387
396
  };
388
397
  return {
389
398
  id: dataset_image.image_id,
390
- title: null,
399
+ title: `Biolucida Image`,
391
400
  type: "Image",
392
401
  thumbnail: thumbnailURL,
393
402
  userData: action,
394
- mimetype: 'image/png'
403
+ mimetype: 'image/png',
404
+ hideType: true,
395
405
  };
396
406
  })
397
407
  );
398
408
  }
399
- this.biolucidaItems = items;
409
+ this.items['Biolucida Images'] = items;
400
410
  },
401
411
  },
402
412
  },
@@ -411,8 +421,8 @@ export default {
411
421
 
412
422
  <style scoped>
413
423
  .full-size {
414
- width: 100%;
415
424
  height: 100%;
425
+ width: 244px;
416
426
  }
417
427
 
418
428
  .key-image-span.active {
@@ -24,11 +24,10 @@
24
24
  <div class="content scrollbar" v-loading="loadingCards" ref="content">
25
25
  <div
26
26
  class="error-feedback"
27
- v-if="results.length === 0 && !loadingCards && !sciCrunchError"
27
+ v-if="results.length === 0 && !loadingCards"
28
28
  >No results found - Please change your search / filter criteria.</div>
29
- <div class="error-feedback" v-if="sciCrunchError">{{sciCrunchError}}</div>
30
- <div v-for="o in results" :key="o.id" class="step-item">
31
- <DatasetCard :entry="o" :envVars="envVars" @contextUpdate="contextCardUpdate"></DatasetCard>
29
+ <div v-for="result in results" :key="result.doi" class="step-item">
30
+ <DatasetCard :entry="result" :envVars="envVars" @contextUpdate="contextCardUpdate"></DatasetCard>
32
31
  </div>
33
32
  <el-pagination
34
33
  class="pagination"
@@ -101,9 +100,9 @@ var initial_state = {
101
100
  pageModel: 1,
102
101
  start: 0,
103
102
  hasSearched: false,
104
- sciCrunchError: false,
105
103
  contextCardEntry: undefined,
106
- contextCardEnabled: false
104
+ contextCardEnabled: true,
105
+ loadingScicrunch: false,
107
106
  };
108
107
 
109
108
  export default {
@@ -152,7 +151,7 @@ export default {
152
151
  },
153
152
  methods: {
154
153
  contextCardUpdate: function(val){
155
- this.contextCardEntry = val
154
+ this.contextCardEntry = val
156
155
  },
157
156
  openSearch: function(filter, search='') {
158
157
  this.searchInput = search;
@@ -192,12 +191,19 @@ export default {
192
191
  },
193
192
  searchAlgolia(filters, query=''){
194
193
  // Algolia search
194
+ this.loadingCards = true
195
195
  this.algoliaClient.search(getFilters(filters), query, this.numberPerPage, this.page).then(searchData => {
196
196
  this.numberOfHits = searchData.total
197
197
  this.discoverIds = searchData.discoverIds
198
- this.dois = searchData.dois
198
+ this._dois = searchData.dois
199
199
  this.results = searchData.items
200
- this.searchSciCrunch({'dois': this.dois})
200
+ this.loadingCards = false
201
+ this.scrollToTop()
202
+ this.$emit("search-changed", { value: this.searchInput, type: "query-update" })
203
+ //Search ongoing, let the current flow progress
204
+ if (!this.loadingScicrunch) {
205
+ this.perItemSearch()
206
+ }
201
207
  })
202
208
  },
203
209
  filtersLoading: function (val) {
@@ -212,31 +218,36 @@ export default {
212
218
  this.page = page
213
219
  this.searchAlgolia(this.filters, this.searchInput, this.numberPerPage, this.page)
214
220
  },
215
- searchSciCrunch: function(params) {
216
- this.loadingCards = true;
217
- this.results = [];
218
- this.disableCards();
219
- this.$emit("search-changed", { value: this.searchInput, type: "query-update" });
220
- this.callSciCrunch(this.envVars.API_LOCATION, params)
221
- .then(result => {
222
- //Only process if the search term is the same as the last search term.
223
- //This avoid old search being displayed.
224
- this.sciCrunchError = false;
225
- this.resultsProcessing(result);
226
- this.$refs.content.style["overflow-y"] = "scroll";
227
- this.loadingCards = false;
228
- })
229
- .catch(result => {
230
- if (result.name !== 'AbortError') {
231
- this.loadingCards = false;
232
- this.sciCrunchError = result.message;
233
- }
234
- })
221
+ handleMissingData: function(doi) {
222
+ let i = this.results.findIndex(res=> res.doi === doi)
223
+ if (this.results[i])
224
+ this.results[i].detailsReady = true;
235
225
  },
236
- disableCards: function() {
226
+ perItemSearch: function() {
227
+ const doi = this._dois.shift();
228
+ if (doi) {
229
+ this.loadingScicrunch = true;
230
+ this.callSciCrunch(this.envVars.API_LOCATION, {'dois': [doi]})
231
+ .then(result => {
232
+ if (result.numberOfHits === 0)
233
+ this.handleMissingData(doi)
234
+ else
235
+ this.resultsProcessing(result);
236
+ this.$refs.content.style["overflow-y"] = "scroll";
237
+ })
238
+ .catch(result => {
239
+ if (result.name !== 'AbortError') {
240
+ this.handleMissingData(doi);
241
+ }
242
+ })
243
+ .finally(() => this.perItemSearch());
244
+ } else {
245
+ this.loadingScicrunch = false;
246
+ }
247
+ },
248
+ scrollToTop: function() {
237
249
  if (this.$refs.content) {
238
250
  this.$refs.content.scroll({ top: 0, behavior: "smooth" });
239
- this.$refs.content.style["overflow-y"] = "hidden";
240
251
  }
241
252
  },
242
253
  resetPageNavigation: function() {
@@ -245,16 +256,17 @@ export default {
245
256
  },
246
257
  resultsProcessing: function(data) {
247
258
  this.lastSearch = this.searchInput;
248
- this.results = [];
259
+
249
260
  if (data.results.length === 0) {
250
261
  return;
251
262
  }
252
263
  data.results.forEach(element => {
253
- // this.results.push(element) below should be once backend is ready
254
- let datasetInfo = {
255
- name: element.name,
256
- description: element.description,
257
- contributors: element.contributors,
264
+ // match the scicrunch result with algolia result
265
+ let i = this.results.findIndex(res=> res.name === element.name)
266
+ // Assign scicrunch results to the object
267
+ Object.assign(this.results[i], element)
268
+ // Assign the attributes that need some processing
269
+ Object.assign(this.results[i],{
258
270
  numberSamples: element.sampleSize
259
271
  ? parseInt(element.sampleSize)
260
272
  : 0,
@@ -269,28 +281,24 @@ export default {
269
281
  organs: (element.organs && element.organs.length > 0)
270
282
  ? [...new Set(element.organs.map(v => v.name))]
271
283
  : undefined,
272
- species: element.organisms
284
+ species: element.organisms
273
285
  ? element.organisms[0].species
274
286
  ? [...new Set(element.organisms.map((v) =>v.species ? v.species.name : null))]
275
287
  : undefined
276
288
  : undefined, // This processing only includes each gender once into 'sexes'
277
- doi: element.doi,
278
- publishDate: element.publishDate,
279
289
  scaffolds: element['abi-scaffold-metadata-file'],
280
290
  thumbnails: element['abi-thumbnail'] ? element['abi-thumbnail']: element['abi-scaffold-thumbnail'],
281
291
  scaffoldViews: element['abi-scaffold-view-file'],
282
292
  videos: element.video,
283
- plots: element.plot,
293
+ plots: element['abi-plot'],
284
294
  images: element['common-images'],
285
295
  contextualInformation: element['abi-contextual-information'].length > 0 ? element['abi-contextual-information'] : undefined,
286
- additionalLinks: element.additionalLinks,
287
296
  segmentation: element['mbf-segmentation'],
288
- simulation: element.additionalLinks
289
- ? element.additionalLinks[0].description == 'Repository'
290
- : false,
291
- s3uri: element.s3uri
292
- };
293
- this.results.push(datasetInfo);
297
+ simulation: element['abi-simulation-file'],
298
+ additionalLinks: element.additionalLinks,
299
+ detailsReady: true,
300
+ })
301
+ Vue.set(this.results, i, this.results[i])
294
302
  });
295
303
  },
296
304
  createfilterParams: function(params) {
@@ -309,14 +317,9 @@ export default {
309
317
  },
310
318
  callSciCrunch: function(apiLocation, params = {}) {
311
319
  return new Promise((resolve, reject) => {
312
- // the following controller will abort current search
313
- // if a new one has been started
314
- if (this._controller) this._controller.abort();
315
- this._controller = new AbortController();
316
- let signal = this._controller.signal;
317
320
  // Add parameters if we are sent them
318
321
  let fullEndpoint = this.envVars.API_LOCATION + this.searchEndpoint + "?" + this.createfilterParams(params);
319
- fetch(fullEndpoint, { signal })
322
+ fetch(fullEndpoint)
320
323
  .then(handleErrors)
321
324
  .then(response => response.json())
322
325
  .then(data => resolve(data))
@@ -328,7 +331,6 @@ export default {
328
331
  // initialise algolia
329
332
  this.algoliaClient = new AlgoliaClient(this.envVars.ALGOLIA_ID, this.envVars.ALGOLIA_KEY, this.envVars.PENNSIEVE_API_LOCATION);
330
333
  this.algoliaClient.initIndex(this.envVars.ALGOLIA_INDEX);
331
- console.log('Algolia initialised in sidebar')
332
334
 
333
335
  // temporarily disable flatmap search since there are no datasets
334
336
  if (this.firstSearch === "Flatmap" || this.firstSearch === "flatmap") {
@@ -420,6 +422,10 @@ export default {
420
422
  scrollbar-width: thin;
421
423
  }
422
424
 
425
+ .content >>> .el-loading-spinner .path {
426
+ stroke: #8300bf;
427
+ }
428
+
423
429
  .content >>> .step-item:first-child .seperator-path{
424
430
  display: none;
425
431
  }