@abi-software/mapintegratedvuer 1.22.0 → 1.24.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/{ConnectivityGraph-BBZ3Dgat.js → ConnectivityGraph-CCxk8vcE.js} +6 -6
- package/dist/{ContentMixin-B-O_IwPg.js → ContentMixin-Db8nqZax.js} +303 -247
- package/dist/{DynamicMarkerMixin-B9iqtP_f.js → DynamicMarkerMixin-LB2RYdSY.js} +1 -1
- package/dist/{Flatmap-BoEFI50b.js → Flatmap-CqUzOkdl.js} +5 -5
- package/dist/{Iframe-Slj-LQTF.js → Iframe-I-xdZ2FP.js} +2 -2
- package/dist/{MultiFlatmap-l6aBn6x3.js → MultiFlatmap-11L97ycJ.js} +6 -6
- package/dist/{Plot-CIhEip5b.js → Plot-Bd9RqyVD.js} +2 -2
- package/dist/{Scaffold-D5ZGCDvt.js → Scaffold-CySWXQxI.js} +46 -36
- package/dist/Simulation-ChUbGudZ.js +32 -0
- package/dist/{connectivities-Br3MpoAv.js → connectivities-LtlFwLOp.js} +6399 -5790
- package/dist/es-D-YkSGXX.js +436 -0
- package/dist/mapintegratedvuer.js +13061 -11664
- package/dist/mapintegratedvuer.umd.cjs +191 -190
- package/dist/style.css +1 -1
- package/package.json +7 -7
- package/src/assets/header-icon.scss +9 -3
- package/src/components/ContentBar.vue +172 -92
- package/src/components/ContentVuer.vue +41 -1
- package/src/components/ContextCard.vue +15 -3
- package/src/components/DatasetHeader.vue +4 -1
- package/src/components/DialogToolbarContent.vue +45 -4
- package/src/components/EventBus.js +8 -0
- package/src/components/MapContent.vue +85 -31
- package/src/components/ResizeSensor.vue +7 -9
- package/src/components/ScreenshotPopover.vue +526 -0
- package/src/components/SplitDialog.vue +94 -93
- package/src/components/SplitFlow.vue +158 -96
- package/src/components/scripts/utilities.js +56 -1
- package/src/components/viewers/Flatmap.vue +1 -0
- package/src/components/viewers/MultiFlatmap.vue +3 -0
- package/src/components/viewers/Scaffold.vue +25 -13
- package/src/components/viewers/Simulation.vue +23 -1
- package/src/components.d.ts +2 -0
- package/src/mixins/ContentMixin.js +23 -10
- package/src/services/screenshot.js +1186 -0
- package/src/stores/connectivities.js +38 -5
- package/src/stores/settings.js +18 -0
- package/vite.config.js +27 -4
- package/dist/Simulation-C5o5DXRb.js +0 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abi-software/mapintegratedvuer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^24.20.0"
|
|
@@ -58,18 +58,18 @@
|
|
|
58
58
|
"*.js"
|
|
59
59
|
],
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@abi-software/flatmapvuer": "1.
|
|
62
|
-
"@abi-software/map-side-bar": "2.
|
|
63
|
-
"@abi-software/map-utilities": "1.
|
|
61
|
+
"@abi-software/flatmapvuer": "1.21.0",
|
|
62
|
+
"@abi-software/map-side-bar": "2.20.0",
|
|
63
|
+
"@abi-software/map-utilities": "1.14.0",
|
|
64
64
|
"@abi-software/plotvuer": "1.3.0",
|
|
65
|
-
"@abi-software/scaffoldvuer": "2.
|
|
66
|
-
"@abi-software/simulationvuer": "4.
|
|
65
|
+
"@abi-software/scaffoldvuer": "2.1.0",
|
|
66
|
+
"@abi-software/simulationvuer": "4.4.0",
|
|
67
67
|
"@abi-software/sparc-annotation": "0.3.2",
|
|
68
68
|
"@abi-software/svg-sprite": "1.4.0",
|
|
69
69
|
"@element-plus/icons-vue": "^2.3.2",
|
|
70
70
|
"@vitejs/plugin-vue": "^6.0.8",
|
|
71
|
-
"css-element-queries": "^1.2.3",
|
|
72
71
|
"element-plus": "^2.14.5",
|
|
72
|
+
"html-to-image": "^1.11.13",
|
|
73
73
|
"marked": "^8.0.1",
|
|
74
74
|
"mitt": "^3.0.1",
|
|
75
75
|
"pinia": "^4.0.3",
|
|
@@ -16,9 +16,15 @@
|
|
|
16
16
|
display: flex;
|
|
17
17
|
flex-direction: row;
|
|
18
18
|
justify-content: center;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
align-items: center;
|
|
20
|
+
top: 0;
|
|
21
|
+
right: 1rem;
|
|
22
|
+
gap: 8px;
|
|
23
|
+
height: 31px; // header has 1px border
|
|
24
|
+
|
|
25
|
+
svg.map-icon {
|
|
26
|
+
margin: 0;
|
|
27
|
+
}
|
|
22
28
|
}
|
|
23
29
|
|
|
24
30
|
.icon-group {
|
|
@@ -1,100 +1,113 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<div class="toolbar-flex-container">
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
<div class="toolbar-left shrink">
|
|
5
|
+
<el-select
|
|
6
|
+
v-if="entries.length > 1"
|
|
7
|
+
:teleported="false"
|
|
8
|
+
:model-value="entry.id"
|
|
9
|
+
placeholder="Select"
|
|
10
|
+
class="select-box"
|
|
11
|
+
popper-class="viewer_dropdown"
|
|
12
|
+
@change="viewerChanged($event)"
|
|
13
|
+
>
|
|
14
|
+
<el-option
|
|
15
|
+
v-for="entry in entries"
|
|
16
|
+
:key="entry.id"
|
|
17
|
+
:label="getTitle(entry)"
|
|
18
|
+
:value="entry.id"
|
|
19
|
+
/>
|
|
20
|
+
</el-select>
|
|
21
|
+
<div v-else class="toolbar-title shrink">
|
|
22
|
+
{{ getEntryTitle(entry) }}
|
|
23
|
+
</div>
|
|
24
|
+
<el-button
|
|
25
|
+
v-if="hasSourceInfo"
|
|
26
|
+
round
|
|
27
|
+
size="small"
|
|
28
|
+
class="source-chip shrink"
|
|
29
|
+
@click="openSourceInfo"
|
|
30
|
+
>
|
|
31
|
+
{{ getSourceTitle }}
|
|
32
|
+
</el-button>
|
|
22
33
|
</div>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
|
|
35
|
+
<div class="toolbar-right shrink">
|
|
36
|
+
<div class="information-group shrink">
|
|
37
|
+
<el-popover
|
|
38
|
+
placement="bottom"
|
|
39
|
+
:teleported="false"
|
|
40
|
+
trigger="manual"
|
|
41
|
+
:width="setPopperWidth(slot.id)"
|
|
42
|
+
:offset="0"
|
|
43
|
+
popper-class="context-card-popover"
|
|
44
|
+
:popper-options="popperOptions"
|
|
45
|
+
:visible="contextCardVisible"
|
|
46
|
+
>
|
|
47
|
+
<template #default v-if="contextCardEntry">
|
|
48
|
+
<flatmap-context-card
|
|
49
|
+
class="flatmap-context-card"
|
|
50
|
+
v-if="contextCardEntry.type == 'Flatmap' || contextCardEntry.type == 'MultiFlatmap'"
|
|
51
|
+
:mapImpProv="contextCardEntry.mapImpProv"
|
|
52
|
+
/>
|
|
53
|
+
<context-card
|
|
54
|
+
v-if="contextCardEntry.type.toLowerCase() == 'scaffold'"
|
|
55
|
+
:entry="contextCardEntry"
|
|
56
|
+
:envVars="envVars"
|
|
57
|
+
class="context-card"
|
|
58
|
+
@context-ready="contextCardVisible = true"
|
|
59
|
+
@scaffold-view-clicked="$emit('scaffold-view-clicked', $event)"
|
|
60
|
+
/>
|
|
61
|
+
</template>
|
|
62
|
+
<template #reference>
|
|
63
|
+
<div v-show="contextCardEntry">
|
|
64
|
+
<div
|
|
65
|
+
v-show="contextCardVisible"
|
|
66
|
+
class="information"
|
|
67
|
+
@click="contextCardVisible = false"
|
|
68
|
+
>
|
|
69
|
+
Hide information
|
|
70
|
+
<el-icon><el-icon-arrow-up /></el-icon>
|
|
71
|
+
</div>
|
|
72
|
+
<div
|
|
73
|
+
v-show="!contextCardVisible"
|
|
74
|
+
class="information"
|
|
75
|
+
@click="contextCardVisible = true"
|
|
76
|
+
>
|
|
77
|
+
Show information
|
|
78
|
+
<el-icon><el-icon-arrow-down /></el-icon>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</template>
|
|
82
|
+
</el-popover>
|
|
83
|
+
</div>
|
|
84
|
+
<ScreenshotPopover
|
|
85
|
+
v-if="captureScreenshot"
|
|
86
|
+
:disabled="!viewerReady"
|
|
87
|
+
class="screenshot-button"
|
|
88
|
+
tooltip="Download screenshot of this view"
|
|
89
|
+
:capture="onCaptureScreenshot"
|
|
90
|
+
:getTarget="getScreenshotTarget"
|
|
91
|
+
/>
|
|
33
92
|
<el-popover
|
|
34
|
-
|
|
93
|
+
class="tooltip"
|
|
94
|
+
content="Close and remove"
|
|
95
|
+
placement="bottom-end"
|
|
96
|
+
:show-after="helpDelay"
|
|
35
97
|
:teleported="false"
|
|
36
|
-
trigger="
|
|
37
|
-
|
|
38
|
-
:offset="0"
|
|
39
|
-
popper-class="context-card-popover"
|
|
40
|
-
:popper-options="popperOptions"
|
|
41
|
-
:visible="contextCardVisible"
|
|
98
|
+
trigger="hover"
|
|
99
|
+
popper-class="header-popper"
|
|
42
100
|
>
|
|
43
|
-
<template #default v-if="contextCardEntry">
|
|
44
|
-
<flatmap-context-card
|
|
45
|
-
class="flatmap-context-card"
|
|
46
|
-
v-if="contextCardEntry.type == 'Flatmap' || contextCardEntry.type == 'MultiFlatmap'"
|
|
47
|
-
:mapImpProv="contextCardEntry.mapImpProv"
|
|
48
|
-
/>
|
|
49
|
-
<context-card
|
|
50
|
-
v-if="contextCardEntry.type.toLowerCase() == 'scaffold'"
|
|
51
|
-
:entry="contextCardEntry"
|
|
52
|
-
:envVars="envVars"
|
|
53
|
-
class="context-card"
|
|
54
|
-
@context-ready="contextCardVisible = true"
|
|
55
|
-
@scaffold-view-clicked="$emit('scaffold-view-clicked', $event)"
|
|
56
|
-
/>
|
|
57
|
-
</template>
|
|
58
101
|
<template #reference>
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Hide information
|
|
66
|
-
<el-icon><el-icon-arrow-up /></el-icon>
|
|
67
|
-
</div>
|
|
68
|
-
<div
|
|
69
|
-
v-show="!contextCardVisible"
|
|
70
|
-
class="information"
|
|
71
|
-
@click="contextCardVisible = true"
|
|
72
|
-
>
|
|
73
|
-
Show information
|
|
74
|
-
<el-icon><el-icon-arrow-down /></el-icon>
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
102
|
+
<map-svg-icon
|
|
103
|
+
icon="close-no-bk"
|
|
104
|
+
class="header-icon rightmost"
|
|
105
|
+
v-show="activeView !== 'singlepanel' && (entry.mode !== 'main' || allClosable)"
|
|
106
|
+
@click="closeAndRemove()"
|
|
107
|
+
/>
|
|
77
108
|
</template>
|
|
78
109
|
</el-popover>
|
|
79
110
|
</div>
|
|
80
|
-
<el-popover
|
|
81
|
-
class="tooltip"
|
|
82
|
-
content="Close and remove"
|
|
83
|
-
placement="bottom-end"
|
|
84
|
-
:show-after="helpDelay"
|
|
85
|
-
:teleported="false"
|
|
86
|
-
trigger="hover"
|
|
87
|
-
popper-class="header-popper"
|
|
88
|
-
>
|
|
89
|
-
<template #reference>
|
|
90
|
-
<map-svg-icon
|
|
91
|
-
icon="close-no-bk"
|
|
92
|
-
class="header-icon rightmost"
|
|
93
|
-
v-show="activeView !== 'singlepanel' && (entry.mode !== 'main' || allClosable)"
|
|
94
|
-
@click="closeAndRemove()"
|
|
95
|
-
/>
|
|
96
|
-
</template>
|
|
97
|
-
</el-popover>
|
|
98
111
|
</div>
|
|
99
112
|
</div>
|
|
100
113
|
</template>
|
|
@@ -108,6 +121,7 @@ import { useSettingsStore } from '../stores/settings';
|
|
|
108
121
|
import { useSplitFlowStore } from '../stores/splitFlow';
|
|
109
122
|
import ContextCard from './ContextCard.vue';
|
|
110
123
|
import FlatmapContextCard from './FlatmapContextCard.vue';
|
|
124
|
+
import ScreenshotPopover from './ScreenshotPopover.vue';
|
|
111
125
|
import { ArrowDown as ElIconArrowDown, ArrowUp as ElIconArrowUp } from '@element-plus/icons-vue';
|
|
112
126
|
import tagging from '../services/tagging';
|
|
113
127
|
|
|
@@ -119,9 +133,31 @@ export default {
|
|
|
119
133
|
ContextCard,
|
|
120
134
|
FlatmapContextCard,
|
|
121
135
|
MapSvgIcon,
|
|
136
|
+
ScreenshotPopover,
|
|
122
137
|
},
|
|
123
138
|
props: {
|
|
124
139
|
entry: Object,
|
|
140
|
+
/**
|
|
141
|
+
* Async function capturing a screenshot of this view.
|
|
142
|
+
*/
|
|
143
|
+
captureScreenshot: {
|
|
144
|
+
type: Function,
|
|
145
|
+
default: undefined,
|
|
146
|
+
},
|
|
147
|
+
/**
|
|
148
|
+
* Function returning the element captured, used for size preview.
|
|
149
|
+
*/
|
|
150
|
+
getScreenshotTarget: {
|
|
151
|
+
type: Function,
|
|
152
|
+
default: undefined,
|
|
153
|
+
},
|
|
154
|
+
/**
|
|
155
|
+
* Whether the viewer's content has finished loading.
|
|
156
|
+
*/
|
|
157
|
+
viewerReady: {
|
|
158
|
+
type: Boolean,
|
|
159
|
+
default: false,
|
|
160
|
+
},
|
|
125
161
|
},
|
|
126
162
|
data: function () {
|
|
127
163
|
return {
|
|
@@ -202,6 +238,19 @@ export default {
|
|
|
202
238
|
},
|
|
203
239
|
},
|
|
204
240
|
methods: {
|
|
241
|
+
onCaptureScreenshot: async function (options) {
|
|
242
|
+
const result = await this.captureScreenshot(options);
|
|
243
|
+
|
|
244
|
+
// GA Tracking
|
|
245
|
+
tagging.sendEvent({
|
|
246
|
+
event: 'interaction_event',
|
|
247
|
+
event_name: 'portal_maps_screenshot',
|
|
248
|
+
category: `png_${options.scale}x`,
|
|
249
|
+
location: 'pane_header',
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
return result;
|
|
253
|
+
},
|
|
205
254
|
closeAndRemove: function () {
|
|
206
255
|
this.splitFlowStore.closeSlot({ id: this.entry.id, entries: this.entries });
|
|
207
256
|
EventBus.emit('RemoveEntryRequest', this.entry.id);
|
|
@@ -269,7 +318,7 @@ export default {
|
|
|
269
318
|
target: value,
|
|
270
319
|
});
|
|
271
320
|
this.$nextTick(() => {
|
|
272
|
-
setTimeout(() => {
|
|
321
|
+
this._chooserTimer = setTimeout(() => {
|
|
273
322
|
this.$emit('chooser-changed');
|
|
274
323
|
}, 1200);
|
|
275
324
|
});
|
|
@@ -316,6 +365,9 @@ export default {
|
|
|
316
365
|
mounted: function () {
|
|
317
366
|
this.setupScaffoldContextCard();
|
|
318
367
|
},
|
|
368
|
+
beforeUnmount: function () {
|
|
369
|
+
clearTimeout(this._chooserTimer);
|
|
370
|
+
},
|
|
319
371
|
};
|
|
320
372
|
</script>
|
|
321
373
|
|
|
@@ -327,19 +379,38 @@ export default {
|
|
|
327
379
|
display: flex;
|
|
328
380
|
flex-direction: row;
|
|
329
381
|
align-items: center;
|
|
382
|
+
justify-content: space-between;
|
|
330
383
|
flex-wrap: nowrap;
|
|
331
384
|
width: 100%;
|
|
385
|
+
gap: 16px;
|
|
332
386
|
|
|
333
387
|
.shrink {
|
|
334
388
|
flex-shrink: 1;
|
|
335
389
|
min-width: 0;
|
|
336
390
|
}
|
|
337
391
|
|
|
338
|
-
.
|
|
339
|
-
|
|
340
|
-
|
|
392
|
+
.toolbar-left,
|
|
393
|
+
.toolbar-right {
|
|
394
|
+
display: flex;
|
|
395
|
+
flex-direction: row;
|
|
396
|
+
align-items: center;
|
|
341
397
|
height: 100%;
|
|
398
|
+
gap: 8px;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.toolbar-left {
|
|
402
|
+
justify-content: flex-start;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
.toolbar-right {
|
|
406
|
+
justify-content: flex-end;
|
|
407
|
+
margin-left: auto;
|
|
342
408
|
position: relative;
|
|
409
|
+
margin-right: 1rem; // same as header toolbar
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.information-group {
|
|
413
|
+
height: 100%;
|
|
343
414
|
}
|
|
344
415
|
|
|
345
416
|
.toolbar-title {
|
|
@@ -396,12 +467,14 @@ export default {
|
|
|
396
467
|
color: $lightGrey;
|
|
397
468
|
}
|
|
398
469
|
}
|
|
470
|
+
|
|
399
471
|
i .select-box :deep(.el-input__icon) {
|
|
400
472
|
color: rgb(48, 49, 51);
|
|
401
473
|
height: 24px;
|
|
402
474
|
padding-left: 8px;
|
|
403
475
|
padding-right: 8px;
|
|
404
476
|
}
|
|
477
|
+
|
|
405
478
|
.text {
|
|
406
479
|
margin-left: 8px;
|
|
407
480
|
margin-top: 7px;
|
|
@@ -412,6 +485,7 @@ export default {
|
|
|
412
485
|
user-select: none;
|
|
413
486
|
line-height: 18px;
|
|
414
487
|
}
|
|
488
|
+
|
|
415
489
|
.title {
|
|
416
490
|
width: 140px;
|
|
417
491
|
color: $app-primary-color;
|
|
@@ -428,8 +502,6 @@ export default {
|
|
|
428
502
|
|
|
429
503
|
.source-chip {
|
|
430
504
|
padding: 4px !important;
|
|
431
|
-
margin-left: 2px;
|
|
432
|
-
margin-right: 2px;
|
|
433
505
|
background-color: $app-primary-color;
|
|
434
506
|
border-color: $app-primary-color;
|
|
435
507
|
color: #fff;
|
|
@@ -455,6 +527,10 @@ export default {
|
|
|
455
527
|
flex-shrink: 0;
|
|
456
528
|
}
|
|
457
529
|
|
|
530
|
+
.screenshot-button {
|
|
531
|
+
flex-shrink: 0;
|
|
532
|
+
}
|
|
533
|
+
|
|
458
534
|
.information {
|
|
459
535
|
font-size: 12px;
|
|
460
536
|
margin-top: 0;
|
|
@@ -466,6 +542,10 @@ export default {
|
|
|
466
542
|
cursor: pointer;
|
|
467
543
|
line-height: normal;
|
|
468
544
|
}
|
|
545
|
+
|
|
546
|
+
svg.map-icon {
|
|
547
|
+
margin: 0;
|
|
548
|
+
}
|
|
469
549
|
}
|
|
470
550
|
|
|
471
551
|
.viewer_dropdown {
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
ref="contentBar"
|
|
11
11
|
@chooser-changed="onResize"
|
|
12
12
|
@scaffold-view-clicked="scaffoldViewClicked"
|
|
13
|
+
:captureScreenshot="captureScreenshot"
|
|
14
|
+
:getScreenshotTarget="getScreenshotElement"
|
|
15
|
+
:viewerReady="viewerReady"
|
|
13
16
|
@vue:mounted="setPanesBoundary"
|
|
14
17
|
/>
|
|
15
18
|
<!--
|
|
@@ -31,6 +34,7 @@
|
|
|
31
34
|
@flatmap-provenance-ready="flatmapProvenanceReady"
|
|
32
35
|
@resource-selected="resourceSelected"
|
|
33
36
|
@species-changed="speciesChanged"
|
|
37
|
+
@viewer-ready="viewerReady = $event"
|
|
34
38
|
/>
|
|
35
39
|
</Suspense>
|
|
36
40
|
</div>
|
|
@@ -42,7 +46,9 @@ import { defineAsyncComponent } from 'vue';
|
|
|
42
46
|
import ContentBar from './ContentBar.vue';
|
|
43
47
|
import { mapStores } from 'pinia';
|
|
44
48
|
import { useEntriesStore } from '../stores/entries';
|
|
49
|
+
import { useSettingsStore } from '../stores/settings';
|
|
45
50
|
import { useSplitFlowStore } from '../stores/splitFlow';
|
|
51
|
+
import { captureElement, findLegends } from '../services/screenshot';
|
|
46
52
|
|
|
47
53
|
const Flatmap = defineAsyncComponent(() => import('./viewers/Flatmap.vue'));
|
|
48
54
|
const MapIframe = defineAsyncComponent(() => import('./viewers/Iframe.vue'));
|
|
@@ -87,6 +93,38 @@ export default {
|
|
|
87
93
|
getState: function () {
|
|
88
94
|
return this.$refs.viewer?.getState();
|
|
89
95
|
},
|
|
96
|
+
/**
|
|
97
|
+
* Capture this pane and download it.
|
|
98
|
+
* The header bar is included only if `toolbar` is set.
|
|
99
|
+
* @param {Object} options - { scale, legend, toolbar }
|
|
100
|
+
*/
|
|
101
|
+
captureScreenshot: function (options = {}) {
|
|
102
|
+
const scale = options.scale || this.settingsStore.screenshot.scale;
|
|
103
|
+
const legend = options.legend || this.settingsStore.screenshot.legend;
|
|
104
|
+
const toolbar = options.toolbar ?? this.settingsStore.screenshot.toolbar;
|
|
105
|
+
const title = this.$refs.contentBar?.getEntryTitle(this.entry) || this.entry.type;
|
|
106
|
+
return captureElement(this.getScreenshotElement({ legend, toolbar }), {
|
|
107
|
+
scale,
|
|
108
|
+
legend,
|
|
109
|
+
toolbar,
|
|
110
|
+
title,
|
|
111
|
+
viewers: [this],
|
|
112
|
+
});
|
|
113
|
+
},
|
|
114
|
+
hasLegend: function () {
|
|
115
|
+
return findLegends(this.$refs.container).length > 0;
|
|
116
|
+
},
|
|
117
|
+
/**
|
|
118
|
+
* The whole pane when the header bar is included, otherwise only the viewer.
|
|
119
|
+
* @param {Object} options - { legend, toolbar }
|
|
120
|
+
*/
|
|
121
|
+
getScreenshotElement: function (options = {}) {
|
|
122
|
+
const { legend, toolbar } = options;
|
|
123
|
+
return toolbar && legend !== 'only' ? this.$el : this.$refs.container;
|
|
124
|
+
},
|
|
125
|
+
getScreenshotSources: function (pixelRatio) {
|
|
126
|
+
return this.$refs.viewer?.getScreenshotSources?.(pixelRatio) || [];
|
|
127
|
+
},
|
|
90
128
|
resourceSelected: function (payload) {
|
|
91
129
|
this.$emit('resource-selected', payload);
|
|
92
130
|
},
|
|
@@ -168,10 +206,12 @@ export default {
|
|
|
168
206
|
return {
|
|
169
207
|
mouseHovered: false,
|
|
170
208
|
activeSpecies: 'Rat',
|
|
209
|
+
// Viewers without a ready event are considered ready immediately
|
|
210
|
+
viewerReady: !['Flatmap', 'MultiFlatmap', 'Scaffold'].includes(this.entry.type),
|
|
171
211
|
};
|
|
172
212
|
},
|
|
173
213
|
computed: {
|
|
174
|
-
...mapStores(useEntriesStore, useSplitFlowStore),
|
|
214
|
+
...mapStores(useEntriesStore, useSettingsStore, useSplitFlowStore),
|
|
175
215
|
viewerType() {
|
|
176
216
|
switch (this.entry.type) {
|
|
177
217
|
case 'MapIframe':
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
class="context-card"
|
|
8
8
|
>
|
|
9
9
|
<div class="card-left">
|
|
10
|
-
<img :src="banner" class="context-image" />
|
|
10
|
+
<img :crossorigin="crossorigin" :src="banner" class="context-image" />
|
|
11
11
|
</div>
|
|
12
12
|
<div class="card-right scrollbar">
|
|
13
13
|
<div>
|
|
@@ -54,7 +54,11 @@
|
|
|
54
54
|
</div>
|
|
55
55
|
<template v-for="(view, i) in contextData.views" :key="i + '_1'">
|
|
56
56
|
<div @click="openViewFile(view)" class="context-card-view">
|
|
57
|
-
<img
|
|
57
|
+
<img
|
|
58
|
+
:crossorigin="crossorigin"
|
|
59
|
+
class="view-image"
|
|
60
|
+
:src="getFileFromPath(view.thumbnail)"
|
|
61
|
+
/>
|
|
58
62
|
<div class="view-description">{{ view.description }}</div>
|
|
59
63
|
</div>
|
|
60
64
|
<div class="padding" />
|
|
@@ -72,6 +76,7 @@
|
|
|
72
76
|
:style="'background-color:' + sample.color"
|
|
73
77
|
></div>
|
|
74
78
|
<img
|
|
79
|
+
:crossorigin="crossorigin"
|
|
75
80
|
class="key-image"
|
|
76
81
|
v-else-if="sample.thumbnail"
|
|
77
82
|
:src="getFileFromPath(sample.thumbnail)"
|
|
@@ -99,7 +104,11 @@
|
|
|
99
104
|
</div>
|
|
100
105
|
<template v-for="(view, i) in contextData.views" :key="i + '_1'">
|
|
101
106
|
<span @click="viewClicked(view, i)" class="context-card-view">
|
|
102
|
-
<img
|
|
107
|
+
<img
|
|
108
|
+
:crossorigin="crossorigin"
|
|
109
|
+
class="view-image"
|
|
110
|
+
:src="getFileFromPath(view.thumbnail)"
|
|
111
|
+
/>
|
|
103
112
|
<div class="view-description">
|
|
104
113
|
{{ view.description }}
|
|
105
114
|
<i class="el-icon-warning-outline info"></i>
|
|
@@ -171,6 +180,9 @@ export default {
|
|
|
171
180
|
CopyToClipboard,
|
|
172
181
|
},
|
|
173
182
|
mixins: [S3Bucket],
|
|
183
|
+
inject: {
|
|
184
|
+
crossorigin: { default: 'anonymous' },
|
|
185
|
+
},
|
|
174
186
|
props: {
|
|
175
187
|
/**
|
|
176
188
|
* Object containing information for
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
class="dataset-card"
|
|
19
19
|
ref="card"
|
|
20
20
|
>
|
|
21
|
-
<img :src="entry.datasetImage" class="image" />
|
|
21
|
+
<img :crossorigin="crossorigin" :src="entry.datasetImage" class="image" />
|
|
22
22
|
<div style="padding: 14px">
|
|
23
23
|
<span class="dataset-description">{{ entry.datasetDescription }}</span>
|
|
24
24
|
<div>
|
|
@@ -33,6 +33,9 @@
|
|
|
33
33
|
<script>
|
|
34
34
|
export default {
|
|
35
35
|
name: 'DatasetHeader',
|
|
36
|
+
inject: {
|
|
37
|
+
crossorigin: { default: 'anonymous' },
|
|
38
|
+
},
|
|
36
39
|
props: {
|
|
37
40
|
/**
|
|
38
41
|
* Object containing information for
|
|
@@ -231,6 +231,15 @@
|
|
|
231
231
|
/>
|
|
232
232
|
</template>
|
|
233
233
|
</el-popover>
|
|
234
|
+
<ScreenshotPopover
|
|
235
|
+
v-if="captureScreenshot"
|
|
236
|
+
title="Download screenshot of all views"
|
|
237
|
+
tooltip="Download screenshot"
|
|
238
|
+
:capture="onCaptureScreenshot"
|
|
239
|
+
:getTarget="getScreenshotTarget"
|
|
240
|
+
:disabled="!mapLoaded"
|
|
241
|
+
shortcut
|
|
242
|
+
/>
|
|
234
243
|
<el-popover
|
|
235
244
|
v-if="permalinkRef"
|
|
236
245
|
ref="linkPopover"
|
|
@@ -463,7 +472,7 @@
|
|
|
463
472
|
<el-icon
|
|
464
473
|
ref="globalSettingRef"
|
|
465
474
|
:disabled="!mapLoaded"
|
|
466
|
-
class="header-icon"
|
|
475
|
+
class="header-icon global-settings-icon"
|
|
467
476
|
:class="{ disabled: !mapLoaded }"
|
|
468
477
|
>
|
|
469
478
|
<el-icon-more-filled />
|
|
@@ -476,13 +485,14 @@
|
|
|
476
485
|
|
|
477
486
|
<script>
|
|
478
487
|
import { shallowRef } from 'vue';
|
|
479
|
-
import EventBus from './EventBus';
|
|
488
|
+
import EventBus, { onEvents } from './EventBus';
|
|
480
489
|
import { mapStores } from 'pinia';
|
|
481
490
|
import { useEntriesStore } from '../stores/entries';
|
|
482
491
|
import { useSettingsStore } from '../stores/settings';
|
|
483
492
|
import { useSplitFlowStore } from '../stores/splitFlow';
|
|
484
493
|
import { MapSvgIcon, MapSvgSpriteColor } from '@abi-software/svg-sprite';
|
|
485
494
|
import SearchControls from './SearchControls.vue';
|
|
495
|
+
import ScreenshotPopover from './ScreenshotPopover.vue';
|
|
486
496
|
import { CopyDocument as ElIconCopyDocument } from '@element-plus/icons-vue';
|
|
487
497
|
import tagging from '../services/tagging';
|
|
488
498
|
|
|
@@ -494,6 +504,7 @@ export default {
|
|
|
494
504
|
components: {
|
|
495
505
|
MapSvgIcon,
|
|
496
506
|
MapSvgSpriteColor,
|
|
507
|
+
ScreenshotPopover,
|
|
497
508
|
SearchControls,
|
|
498
509
|
},
|
|
499
510
|
props: {
|
|
@@ -511,6 +522,20 @@ export default {
|
|
|
511
522
|
type: Boolean,
|
|
512
523
|
default: false,
|
|
513
524
|
},
|
|
525
|
+
/**
|
|
526
|
+
* Async function capturing a screenshot of all visible views.
|
|
527
|
+
*/
|
|
528
|
+
captureScreenshot: {
|
|
529
|
+
type: Function,
|
|
530
|
+
default: undefined,
|
|
531
|
+
},
|
|
532
|
+
/**
|
|
533
|
+
* Function returning the element captured, used for size preview.
|
|
534
|
+
*/
|
|
535
|
+
getScreenshotTarget: {
|
|
536
|
+
type: Function,
|
|
537
|
+
default: undefined,
|
|
538
|
+
},
|
|
514
539
|
},
|
|
515
540
|
inject: ['showGlobalSettings'],
|
|
516
541
|
computed: {
|
|
@@ -703,6 +728,19 @@ export default {
|
|
|
703
728
|
this.getShareLink(false);
|
|
704
729
|
}
|
|
705
730
|
},
|
|
731
|
+
onCaptureScreenshot: async function (options) {
|
|
732
|
+
const result = await this.captureScreenshot(options);
|
|
733
|
+
|
|
734
|
+
// GA Tracking
|
|
735
|
+
tagging.sendEvent({
|
|
736
|
+
event: 'interaction_event',
|
|
737
|
+
event_name: 'portal_maps_screenshot',
|
|
738
|
+
category: `png_${options.scale}x`,
|
|
739
|
+
location: options.source === 'shortcut' ? 'keyboard_shortcut' : 'map_toolbar',
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
return result;
|
|
743
|
+
},
|
|
706
744
|
getShareLink: function (withAnnotation) {
|
|
707
745
|
this.displayShareOptions = false;
|
|
708
746
|
this.loadingLink = true;
|
|
@@ -745,8 +783,10 @@ export default {
|
|
|
745
783
|
this.permalinkRef = shallowRef(this.$refs.permalinkRef);
|
|
746
784
|
this.globalSettingRef = shallowRef(this.$refs.globalSettingRef);
|
|
747
785
|
|
|
748
|
-
|
|
749
|
-
|
|
786
|
+
this._offBus = onEvents({
|
|
787
|
+
mapLoaded: () => {
|
|
788
|
+
this.mapLoaded = true;
|
|
789
|
+
},
|
|
750
790
|
});
|
|
751
791
|
|
|
752
792
|
document.addEventListener('fullscreenchange', this.onFullscreenEsc);
|
|
@@ -754,6 +794,7 @@ export default {
|
|
|
754
794
|
this.loadGlobalSettings();
|
|
755
795
|
},
|
|
756
796
|
unmounted: function () {
|
|
797
|
+
this._offBus?.();
|
|
757
798
|
document.removeEventListener('fullscreenchange', this.onFullscreenEsc);
|
|
758
799
|
},
|
|
759
800
|
};
|