@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/dist/scaffoldvuer.js +14834 -14121
- package/dist/scaffoldvuer.umd.cjs +184 -179
- package/dist/style.css +1 -1
- package/package.json +8 -5
- package/src/App.vue +14 -3
- package/src/components/ScaffoldTooltip.vue +37 -12
- package/src/components/ScaffoldVuer.vue +189 -22
- package/src/components.d.ts +2 -0
- package/src/main.js +1 -1
- package/src/mixins/imageMixin.js +87 -0
- package/src/services/scicrunchQueries.js +280 -0
- package/src/stores/settings.js +46 -0
- /package/src/{store → stores}/index.js +0 -0
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.
|
|
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.
|
|
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:
|
|
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":
|
|
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
|
-
<
|
|
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="
|
|
26
|
-
|
|
27
|
-
|
|
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 "@/
|
|
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
|
-
|
|
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="
|
|
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="
|
|
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 "@/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
980
|
+
for (const [key, value] of Object.entries(entry)) {
|
|
899
981
|
this.setMarkerModeForObjectsWithName(key, value, "on");
|
|
900
982
|
}
|
|
901
|
-
this.
|
|
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.
|
|
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:
|
|
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) {
|
package/src/components.d.ts
CHANGED
|
@@ -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 '@/
|
|
5
|
+
import { useMainStore } from '@/stores/index'
|
|
6
6
|
|
|
7
7
|
const routes = [
|
|
8
8
|
{ path: '/'},
|