@abi-software/scaffoldvuer 1.4.0 → 1.4.1-image.0

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/scaffoldvuer",
3
- "version": "1.4.0",
3
+ "version": "1.4.1-image.0",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",
@@ -41,7 +41,7 @@
41
41
  "*.js"
42
42
  ],
43
43
  "dependencies": {
44
- "@abi-software/map-utilities": "^1.1.0",
44
+ "@abi-software/map-utilities": "^1.1.0-beta.2",
45
45
  "@abi-software/sparc-annotation": "^0.3.1",
46
46
  "@abi-software/svg-sprite": "^1.0.0",
47
47
  "@element-plus/icons-vue": "^2.3.1",
@@ -55,12 +55,12 @@
55
55
  "vue": "^3.4.15",
56
56
  "vue-router": "^4.2.5",
57
57
  "vue3-component-svg-sprite": "^0.0.1",
58
- "zincjs": "^1.11.1"
58
+ "zincjs": "^1.11.4"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@vitejs/plugin-vue": "^4.6.2",
62
62
  "@vuese/markdown-render": "^2.11.3",
63
- "@vuese/parser": "^2.10.3",
63
+ "@vuese/parser": "^2.9.1",
64
64
  "auto-changelog": "^2.4.0",
65
65
  "babel-eslint": "^10.1.0",
66
66
  "babel-plugin-component": "^1.1.1",
@@ -92,5 +92,8 @@
92
92
  "browserslist": [
93
93
  "> 1%",
94
94
  "last 2 versions"
95
- ]
95
+ ],
96
+ "optionalDependencies": {
97
+ "@rollup/rollup-linux-x64-gnu": "^4.21.1"
98
+ }
96
99
  }
package/src/App.vue CHANGED
@@ -28,6 +28,7 @@
28
28
  :format="format"
29
29
  :marker-labels="markerLabels"
30
30
  :enableLocalAnnotations="false"
31
+ :sparcAPI="sparcAPI"
31
32
  @open-map="openMap"
32
33
  @on-ready="onReady"
33
34
  @scaffold-selected="onSelected"
@@ -321,6 +322,9 @@ import {
321
322
  import { useRoute, useRouter } from 'vue-router'
322
323
  import { HelpModeDialog } from '@abi-software/map-utilities'
323
324
  import '@abi-software/map-utilities/dist/style.css'
325
+ import { mapStores } from 'pinia';
326
+ import { useSettingsStore } from '@/stores/settings';
327
+ import { getOrganCuries } from '@/services/scicrunchQueries'
324
328
 
325
329
  let texture_prefix = undefined;
326
330
 
@@ -358,7 +362,7 @@ export default {
358
362
  },
359
363
  data: function () {
360
364
  return {
361
- consoleOn: true,
365
+ consoleOn: false,
362
366
  createLinesWithNormal: false,
363
367
  url: undefined,
364
368
  input: undefined,
@@ -406,9 +410,13 @@ export default {
406
410
  router: useRouter(),
407
411
  ElIconSetting: shallowRef(ElIconSetting),
408
412
  ElIconFolderOpened: shallowRef(ElIconFolderOpened),
409
- auto: NaN
413
+ auto: NaN,
414
+ sparcAPI: import.meta.env.VITE_SPARC_API,
410
415
  };
411
416
  },
417
+ computed: {
418
+ ...mapStores(useSettingsStore),
419
+ },
412
420
  watch: {
413
421
  input: function () {
414
422
  this.parseInput();
@@ -422,7 +430,7 @@ export default {
422
430
  "body proper": 9,
423
431
  "Spinal cord": 8,
424
432
  "lung": 11,
425
- "stomach": {number:12, imgURL: 'https://mapcore-bucket1.s3.us-west-2.amazonaws.com/texture/arm1/jpg/0984.jpg'},
433
+ "stomach": 12,
426
434
  "urinary bladder": 11,
427
435
  "Brainstem": 11,
428
436
  "heart": 9,
@@ -454,6 +462,9 @@ export default {
454
462
  },
455
463
  mounted: function () {
456
464
  this._objects = [];
465
+ if (this.sparcAPI) {
466
+ getOrganCuries(this.sparcAPI).then((organCuries) => this.settingsStore.updateOrganCuries(organCuries))
467
+ }
457
468
  },
458
469
  created: function () {
459
470
  texture_prefix = import.meta.env.VITE_TEXTURE_FOOT_PREFIX;
@@ -14,7 +14,7 @@
14
14
  <template #default>
15
15
  <div class="tooltip-text">{{ label }}</div>
16
16
  <div class="tooltip-text" v-if="region">Region: {{ region }}</div>
17
- <CreateTooltiipContent
17
+ <CreateTooltipContent
18
18
  v-show="createData.toBeConfirmed"
19
19
  :createData="createData"
20
20
  @confirm-create="$emit('confirm-create', $event)"
@@ -22,10 +22,14 @@
22
22
  />
23
23
  <Tooltip
24
24
  class="p-tooltip"
25
- v-show="annotationDisplay && !createData.toBeConfirmed"
26
- ref="annotationTooltip"
27
- :annotationDisplay="true"
25
+ v-show="
26
+ (annotationDisplay && !createData.toBeConfirmed) ||
27
+ imageEntry.length
28
+ "
29
+ ref="tooltip"
30
+ :tooltipType="annotationDisplay ? 'annotation' : 'image'"
28
31
  :annotationEntry="annotationEntry"
32
+ :imageEntry="imageEntry"
29
33
  />
30
34
  <div v-if="createData.toBeDeleted" class="delete-container">
31
35
  <el-row>
@@ -66,9 +70,9 @@ import {
66
70
  import {
67
71
  Delete as ElIconDelete,
68
72
  } from '@element-plus/icons-vue'
69
- import CreateTooltiipContent from "./CreateTooltipContent.vue";
70
73
  import { mapState } from 'pinia';
71
- import { useMainStore } from "@/store/index";
74
+ import { useMainStore } from "@/stores/index";
75
+ import CreateTooltipContent from "./CreateTooltipContent.vue";
72
76
  import { Tooltip } from '@abi-software/map-utilities'
73
77
  import '@abi-software/map-utilities/dist/style.css'
74
78
 
@@ -79,7 +83,7 @@ export default {
79
83
  name: "ScaffoldTooltip",
80
84
  components: {
81
85
  Col,
82
- CreateTooltiipContent,
86
+ CreateTooltipContent,
83
87
  ElIconDelete,
84
88
  Icon,
85
89
  Popover,
@@ -121,6 +125,14 @@ export default {
121
125
  type: Number,
122
126
  default: 200,
123
127
  },
128
+ imageThumbnails: {
129
+ type: Object,
130
+ default: {},
131
+ },
132
+ imageThumbnailSidebar: {
133
+ type: Boolean,
134
+ default: false,
135
+ },
124
136
  },
125
137
  inject: ['scaffoldUrl'],
126
138
  provide() {
@@ -130,7 +142,6 @@ export default {
130
142
  },
131
143
  data: function () {
132
144
  return {
133
- display: false,
134
145
  annotationEntry: { },
135
146
  ElIconDelete: shallowRef(ElIconDelete),
136
147
  };
@@ -145,11 +156,27 @@ export default {
145
156
  const x = this.x - 40;
146
157
  return { left: x + "px", top: this.y - yOffset + "px" };
147
158
  },
159
+ imageEntry: function () {
160
+ let imageEntries = []
161
+ const imageThumbnailsEntries = Object.assign({},
162
+ Object.fromEntries(
163
+ Object.entries(this.imageThumbnails)
164
+ .filter(([key, value]) => value.length > 0)
165
+ .map(([key, value]) => [key.toLowerCase(), value])))
166
+ const lowerCaseLabel = this.label.toLowerCase()
167
+ if (lowerCaseLabel in imageThumbnailsEntries) {
168
+ imageEntries = imageThumbnailsEntries[lowerCaseLabel];
169
+ }
170
+ if (this.imageThumbnailSidebar) {
171
+ this.$emit('image-thumbnail-open', imageEntries)
172
+ return [];
173
+ }
174
+ return imageEntries;
175
+ },
148
176
  },
149
177
  methods: {
150
178
  checkForDisplay: function () {
151
179
  if (this.visible && this.label && this.label !== "") {
152
- this.display = true;
153
180
  if (this.annotationDisplay) {
154
181
  const region = this.region ? this.region +"/" : "";
155
182
  this.annotationEntry = {
@@ -158,9 +185,7 @@ export default {
158
185
  "resource": encodeURIComponent(this.scaffoldUrl),
159
186
  };
160
187
  }
161
- }
162
- else {
163
- this.display = false;
188
+ } else {
164
189
  this.annotationEntry = { };
165
190
  }
166
191
  },
@@ -15,9 +15,12 @@
15
15
  :x="tData.x"
16
16
  :y="tData.y"
17
17
  :annotationDisplay="annotationDisplay"
18
+ :imageThumbnailSidebar="imageThumbnailSidebar"
19
+ :imageThumbnails="imageThumbnailsEntry"
18
20
  @confirm-create="confirmCreate($event)"
19
21
  @cancel-create="cancelCreate()"
20
22
  @confirm-delete="confirmDelete($event)"
23
+ @image-thumbnail-open="onImageThumbnailOpen"
21
24
  />
22
25
  <div
23
26
  id="organsDisplayArea"
@@ -284,7 +287,7 @@
284
287
  ref="backgroundPopover"
285
288
  :virtual-ref="backgroundIconRef"
286
289
  placement="top-start"
287
- width="128"
290
+ width="330"
288
291
  :teleported="false"
289
292
  trigger="click"
290
293
  popper-class="background-popper non-selectable h-auto"
@@ -292,7 +295,7 @@
292
295
  >
293
296
  <div>
294
297
  <el-row class="backgroundText">Viewing Mode</el-row>
295
- <el-row class="backgroundControl">
298
+ <el-row class="backgroundChooser">
296
299
  <div style="margin-bottom: 2px;">
297
300
  <template
298
301
  v-for="(value, key, index) in viewingModes"
@@ -310,6 +313,45 @@
310
313
  {{ viewingModes[viewingMode] }}
311
314
  </el-row>
312
315
  </el-row>
316
+ <template v-if="viewingMode === 'Exploration' && sparcAPI">
317
+ <el-row class="backgroundSpacer"></el-row>
318
+ <el-row class="backgroundText">Markers display</el-row>
319
+ <el-row class="backgroundChooser">
320
+ <el-col :span="14">
321
+ <el-radio-group
322
+ v-model="imageRadio"
323
+ class="flatmap-radio"
324
+ :disabled="imagesDownloading"
325
+ @change="setImage"
326
+ >
327
+ <el-radio :value="false">Standard</el-radio>
328
+ <el-radio :value="true">Image</el-radio>
329
+ </el-radio-group>
330
+ </el-col>
331
+ <el-col :span="10" v-if="imageRadio">
332
+ <el-select
333
+ :teleported="false"
334
+ v-model="imageType"
335
+ placeholder="Select"
336
+ class="scaffold-select-box imageSelector"
337
+ popper-class="scaffold_viewer_dropdown"
338
+ :disabled="imagesDownloading"
339
+ @change="setImageType"
340
+ >
341
+ <el-option
342
+ v-for="item in imageTypes"
343
+ :key="item"
344
+ :label="item"
345
+ :value="item"
346
+ >
347
+ <el-row>
348
+ <el-col :span="12">{{ item }}</el-col>
349
+ </el-row>
350
+ </el-option>
351
+ </el-select>
352
+ </el-col>
353
+ </el-row>
354
+ </template>
313
355
  <el-row class="backgroundSpacer"></el-row>
314
356
  <el-row class="backgroundText"> Change background </el-row>
315
357
  <el-row class="backgroundChooser">
@@ -382,7 +424,7 @@
382
424
 
383
425
  <script>
384
426
  /* eslint-disable no-alert, no-console */
385
- import { markRaw, shallowRef } from 'vue';
427
+ import { markRaw, toRaw, shallowRef } from 'vue';
386
428
  import {
387
429
  WarningFilled as ElIconWarningFilled,
388
430
  ArrowDown as ElIconArrowDown,
@@ -421,8 +463,16 @@ import { AnnotationService } from '@abi-software/sparc-annotation';
421
463
  import { EventNotifier } from "../scripts/EventNotifier.js";
422
464
  import { OrgansViewer } from "../scripts/OrgansRenderer.js";
423
465
  import { SearchIndex } from "../scripts/Search.js";
424
- import { mapState } from 'pinia';
425
- import { useMainStore } from "@/store/index";
466
+ import { mapState, mapStores } from 'pinia';
467
+ import { useMainStore } from "@/stores/index";
468
+ import { useSettingsStore } from '@/stores/settings'
469
+ import {
470
+ getBiolucidaThumbnails,
471
+ getSegmentationThumbnails,
472
+ getScaffoldThumbnails,
473
+ getPlotThumbnails
474
+ } from '../services/scicrunchQueries'
475
+ import imageMixin from '../mixins/imageMixin.js'
426
476
 
427
477
  /**
428
478
  * A vue component of the scaffold viewer.
@@ -432,6 +482,7 @@ import { useMainStore } from "@/store/index";
432
482
  */
433
483
  export default {
434
484
  name: "ScaffoldVuer",
485
+ mixins: [imageMixin],
435
486
  components: {
436
487
  Button,
437
488
  Col,
@@ -570,12 +621,12 @@ export default {
570
621
  * GroupName to value pair.
571
622
  * The value can be a single number or and object in the following
572
623
  * form:
573
- *
624
+ *
574
625
  * {
575
626
  * number: Number,
576
627
  * imgURL: String
577
628
  * }
578
- *
629
+ *
579
630
  * When imgURL is specified, scaffoldvuer will attempt to render
580
631
  * the image in imgURL as marker instead.
581
632
  *
@@ -689,10 +740,24 @@ export default {
689
740
  /**
690
741
  * Enable local annotations
691
742
  */
692
- enableLocalAnnotations: {
743
+ enableLocalAnnotations: {
693
744
  type: Boolean,
694
745
  default: false
695
746
  },
747
+ /**
748
+ * Specify the endpoint of the SPARC API.
749
+ */
750
+ sparcAPI: {
751
+ type: String,
752
+ default: '',
753
+ },
754
+ /**
755
+ * The option to show image thumbnail in sidebar
756
+ */
757
+ imageThumbnailSidebar: {
758
+ type: Boolean,
759
+ default: false,
760
+ },
696
761
  },
697
762
  provide() {
698
763
  return {
@@ -700,6 +765,7 @@ export default {
700
765
  scaffoldUrl: this.url,
701
766
  $annotator: this.annotator,
702
767
  boundingDims: this.boundingDims,
768
+ getFeaturesAlert: () => undefined,
703
769
  };
704
770
  },
705
771
  data: function () {
@@ -743,6 +809,7 @@ export default {
743
809
  inHelp: false,
744
810
  helpModeActiveIndex: this.helpModeInitialIndex,
745
811
  loading: false,
812
+ imagesDownloading: false,
746
813
  duration: 3000,
747
814
  drawerOpen: true,
748
815
  currentBackground: "white",
@@ -790,7 +857,8 @@ export default {
790
857
  active: false,
791
858
  },
792
859
  fileFormat: "metadata",
793
- previousMarkerLabels: markRaw({}),
860
+ markerLabelEntry: markRaw({}),
861
+ previousMarkerLabelEntry: markRaw({}),
794
862
  viewingMode: "Exploration",
795
863
  viewingModes: {
796
864
  "Exploration": "View and explore detailed visualization of 3D scaffolds",
@@ -812,6 +880,14 @@ export default {
812
880
  centre: [0, 0, 0],
813
881
  size:[1, 1, 1],
814
882
  },
883
+ imageRadio: false,
884
+ imageType: 'Image',
885
+ imageTypes: ['Image', 'Segmentation', 'Scaffold', 'Plot'],
886
+ imageClicked: '',
887
+ /**
888
+ * List of group names
889
+ */
890
+ groupNames: markRaw([]),
815
891
  };
816
892
  },
817
893
  watch: {
@@ -891,14 +967,20 @@ export default {
891
967
  },
892
968
  immediate: true,
893
969
  },
894
- markerLabels: function(labels) {
895
- for (const [key, value] of Object.entries(this.previousMarkerLabels)) {
970
+ markerLabels: function (labels) {
971
+ if (this.imageRadio === false) {
972
+ //Only updates the following if marker mode is standard
973
+ this.markerLabelEntry = markRaw({...labels});
974
+ }
975
+ },
976
+ markerLabelEntry: function (entry) {
977
+ for (const [key, value] of Object.entries(this.previousMarkerLabelEntry)) {
896
978
  this.setMarkerModeForObjectsWithName(key, value, "off");
897
979
  }
898
- for (const [key, value] of Object.entries(labels)) {
980
+ for (const [key, value] of Object.entries(entry)) {
899
981
  this.setMarkerModeForObjectsWithName(key, value, "on");
900
982
  }
901
- this.previousMarkerLabels = markRaw({...labels});
983
+ this.previousMarkerLabelEntry = markRaw({...entry});
902
984
  },
903
985
  },
904
986
  beforeCreate: function () {
@@ -938,9 +1020,13 @@ export default {
938
1020
  },
939
1021
  computed: {
940
1022
  ...mapState(useMainStore, ['userToken']),
1023
+ ...mapStores(useSettingsStore),
941
1024
  annotationDisplay: function() {
942
1025
  return this.viewingMode === 'Annotation' && this.tData.active === true &&
943
1026
  (this.activeDrawMode === 'Edit' || this.activeDrawMode === 'Delete');
1027
+ },
1028
+ imageThumbnailsEntry: function() {
1029
+ return this.imageClicked ? this.convertUberonToName() : {};
944
1030
  }
945
1031
  },
946
1032
  methods: {
@@ -966,6 +1052,9 @@ export default {
966
1052
  if (this.timeVarying === false && zincObject.isTimeVarying()) {
967
1053
  this.timeVarying = true;
968
1054
  }
1055
+ if (zincObject.groupName) {
1056
+ this.groupNames.push(zincObject.groupName.toLowerCase());
1057
+ }
969
1058
  //Emit when a new object is added to the scene
970
1059
  //@arg The object added to the sceene
971
1060
  this.$emit("zinc-object-added", zincObject);
@@ -1077,7 +1166,7 @@ export default {
1077
1166
  region, group, this.url, comment);
1078
1167
  if (this.enableLocalAnnotations) {
1079
1168
  annotation.group = group;
1080
- let regionPath = region;
1169
+ let regionPath = region;
1081
1170
  if (regionPath.slice(-1) === "/") {
1082
1171
  regionPath = regionPath.slice(0, -1);
1083
1172
  }
@@ -1180,7 +1269,7 @@ export default {
1180
1269
  }
1181
1270
  }
1182
1271
  this.cancelCreate();
1183
- },
1272
+ },
1184
1273
  formatTooltip(val) {
1185
1274
  if (this.timeMax >= 1000) {
1186
1275
  if (val) {
@@ -1267,7 +1356,7 @@ export default {
1267
1356
  return objects;
1268
1357
  },
1269
1358
  /**
1270
- * Switch active drawing type
1359
+ * Switch active drawing type
1271
1360
  * @arg shapeName shape to toggle
1272
1361
  *
1273
1362
  * @vuese
@@ -1392,7 +1481,7 @@ export default {
1392
1481
  this.createData.points.push(coords);
1393
1482
  }
1394
1483
  }
1395
- },
1484
+ },
1396
1485
  /**
1397
1486
  * Return renderer information
1398
1487
  *
@@ -1480,6 +1569,9 @@ export default {
1480
1569
  ? identifier.data.id
1481
1570
  : identifier.data.group;
1482
1571
  names.push(id);
1572
+ if (identifier.data) {
1573
+ identifier.data.imageType = this.imageRadio ? this.imageType : "Standard"
1574
+ }
1483
1575
  }
1484
1576
  });
1485
1577
  zincObjects = event.zincObjects;
@@ -1503,6 +1595,13 @@ export default {
1503
1595
  this.$refs.scaffoldTreeControls.removeActive(false);
1504
1596
  }
1505
1597
  }
1598
+ if (this.imageRadio && event.identifiers.length && event.identifiers[0]) {
1599
+ this.imageClicked = event.identifiers[0].data.id
1600
+ ? event.identifiers[0].data.id
1601
+ : event.identifiers[0].data.group;
1602
+ } else {
1603
+ this.imageClicked = ''
1604
+ }
1506
1605
  //Emit when an object is selected
1507
1606
  //@arg Identifier of selected objects
1508
1607
  this.$emit("scaffold-selected", event.identifiers);
@@ -1553,6 +1652,12 @@ export default {
1553
1652
  this.createEditTemporaryLines(event.identifiers[0].extraData.worldCoords);
1554
1653
  }
1555
1654
  this.createEditTemporaryLines(event.identifiers[0].extraData.worldCoords);
1655
+ const id = event.identifiers[0].data.id
1656
+ ? event.identifiers[0].data.id
1657
+ : event.identifiers[0].data.group;
1658
+ if (this.imageClicked !== id) {
1659
+ this.imageClicked = ''
1660
+ }
1556
1661
  }
1557
1662
  }
1558
1663
  }
@@ -1939,7 +2044,7 @@ export default {
1939
2044
  /**
1940
2045
  * Set the marker modes for objects with the provided name, mode can
1941
2046
  * be "on", "off" or "inherited".
1942
- * Value can either be number or an object containing number and
2047
+ * Value can either be number or an object containing number and
1943
2048
  * imgURL.
1944
2049
  */
1945
2050
  setMarkerModeForObjectsWithName: function (name, value, mode) {
@@ -2198,7 +2303,7 @@ export default {
2198
2303
  const region = annotation.region;
2199
2304
  let fullName = region.slice(-1) === "/" ? region : region + "/";
2200
2305
  const noSlash = fullName.slice(0, -1);
2201
- annotation.region = noSlash;
2306
+ annotation.region = noSlash;
2202
2307
  fullName = fullName + group;
2203
2308
  const featureID = encodeURIComponent(fullName);
2204
2309
  annotation.item.id = featureID;
@@ -2240,6 +2345,7 @@ export default {
2240
2345
  visibility: visibility,
2241
2346
  })
2242
2347
  );
2348
+ this.groupNames.length = 0;
2243
2349
  if (this.fileFormat === "gltf") {
2244
2350
  this.$module.loadGLTFFromURL(newValue, "scene", true);
2245
2351
  } else {
@@ -2327,15 +2433,72 @@ export default {
2327
2433
  this.$module.toggleSyncControl(flag, rotateMode);
2328
2434
  this.$module.setSyncControlCallback(this.syncControlCallback);
2329
2435
  },
2330
-
2331
2436
  /**
2332
2437
  * Set the markers for the scene.
2333
2438
  */
2334
2439
  setMarkers: function () {
2335
- for (const [key, value] of Object.entries(this.markerLabels)) {
2440
+ for (const [key, value] of Object.entries(this.markerLabelEntry)) {
2336
2441
  this.setMarkerModeForObjectsWithName(key, value, "on");
2337
2442
  }
2338
2443
  },
2444
+ removeImageThumbnails: function () {
2445
+ this.imageThumbnails = {};
2446
+ this.markerLabelEntry = markRaw(this.markerLabels);
2447
+ },
2448
+ setImage: async function (flag) {
2449
+ if (flag) {
2450
+ await this.setImageType(this.imageType);
2451
+ this.$module.scene.enableMarkerCluster(false);
2452
+ } else {
2453
+ this.removeImageThumbnails();
2454
+ this.$module.scene.enableMarkerCluster(this.markerCluster);
2455
+ }
2456
+ },
2457
+ setImageType: async function (type) {
2458
+ this.imageType = type;
2459
+ this.imagesDownloading = true;
2460
+ if (!this.settingsStore.imageTypeCached(type)) {
2461
+ this.loading = true;
2462
+ await this.fetchImageThumbnails(type);
2463
+ this.loading = false;
2464
+ }
2465
+ this.populateImageThumbnails(type);
2466
+ },
2467
+ fetchImageThumbnails: async function (type) {
2468
+ let thumbnails = {};
2469
+ const organCuries = this.settingsStore.organCuries;
2470
+ if (type === 'Image') {
2471
+ thumbnails = await getBiolucidaThumbnails(this.sparcAPI, organCuries, type);
2472
+ } else if (type === 'Segmentation') {
2473
+ thumbnails = await getSegmentationThumbnails(this.sparcAPI, organCuries, type);
2474
+ } else if (type === 'Scaffold') {
2475
+ thumbnails = await getScaffoldThumbnails(this.sparcAPI, organCuries, type);
2476
+ } else if (type === 'Plot') {
2477
+ thumbnails = await getPlotThumbnails(this.sparcAPI, organCuries, type);
2478
+ }
2479
+ this.settingsStore.updateImageThumbnails(type, thumbnails);
2480
+ },
2481
+ convertUberonToName: function () {
2482
+ const organCuries = this.settingsStore.organCuries;
2483
+ const identifiers = organCuries.filter(
2484
+ (curie) => this.groupNames.includes(curie.name.toLowerCase())
2485
+ ).map((curie) => curie.id);
2486
+ const imageThumbnails = this.settingsStore.getImageThumbnails(this.imageType, identifiers);
2487
+ return Object.fromEntries(
2488
+ Object.entries(imageThumbnails)
2489
+ .map(([key, value]) => [organCuries.filter((curie) => curie.id === key)[0].name, value]));
2490
+ },
2491
+ populateImageThumbnails: async function (type) {
2492
+ this.removeImageThumbnails();
2493
+ const thumbnails = this.convertUberonToName();
2494
+ this.loading = true;
2495
+ this.markerLabelEntry = markRaw(await this.populateMapWithImages(thumbnails, type));
2496
+ this.loading = false;
2497
+ this.imagesDownloading = false;
2498
+ },
2499
+ onImageThumbnailOpen: function (payload) {
2500
+ this.$emit('image-thumbnail-open', payload);
2501
+ },
2339
2502
  },
2340
2503
  };
2341
2504
  </script>
@@ -2495,7 +2658,7 @@ export default {
2495
2658
  background-color: #ffffff;
2496
2659
  border: 1px solid $app-primary-color;
2497
2660
  box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
2498
- height: 140px;
2661
+ height: fit-content;
2499
2662
  min-width: 200px;
2500
2663
  .el-popper__arrow {
2501
2664
  &:before {
@@ -2752,6 +2915,10 @@ export default {
2752
2915
  min-height: 24px
2753
2916
  }
2754
2917
  }
2918
+
2919
+ &.imageSelector {
2920
+ width: 125px!important;
2921
+ }
2755
2922
  }
2756
2923
 
2757
2924
  :deep(.scaffold_viewer_dropdown) {
@@ -26,6 +26,8 @@ declare module 'vue' {
26
26
  ElMain: typeof import('element-plus/es')['ElMain']
27
27
  ElOption: typeof import('element-plus/es')['ElOption']
28
28
  ElPopover: typeof import('element-plus/es')['ElPopover']
29
+ ElRadio: typeof import('element-plus/es')['ElRadio']
30
+ ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
29
31
  ElRow: typeof import('element-plus/es')['ElRow']
30
32
  ElSelect: typeof import('element-plus/es')['ElSelect']
31
33
  ElSlider: typeof import('element-plus/es')['ElSlider']
package/src/main.js CHANGED
@@ -2,7 +2,7 @@ import { createApp } from 'vue'
2
2
  import { createPinia } from 'pinia'
3
3
  import * as VueRouter from 'vue-router'
4
4
  import App from './App.vue'
5
- import { useMainStore } from '@/store/index'
5
+ import { useMainStore } from '@/stores/index'
6
6
 
7
7
  const routes = [
8
8
  { path: '/'},