@abi-software/mapintegratedvuer 1.17.1 → 1.17.3-simulation.1
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-BL4B9GZX.js → ConnectivityGraph-9pXPgFJR.js} +2 -2
- package/dist/{ContentMixin-Djmb_gqk.js → ContentMixin-DIqgKIz6.js} +279 -536
- package/dist/Flatmap-D7GVPV7o.js +103422 -0
- package/dist/{Iframe-ByYxT4Yq.js → Iframe-CCEA3d9c.js} +2 -2
- package/dist/{MultiFlatmap-DSkdlRiS.js → MultiFlatmap-Cuke1uNp.js} +3 -3
- package/dist/{Plot-ymkHVq_A.js → Plot-B4oTBVAT.js} +2 -2
- package/dist/{Scaffold-bw7posKm.js → Scaffold-Czz8X5kL.js} +79 -53
- package/dist/Simulation-BKmz8zwm.js +107 -0
- package/dist/{index-CwfUgFL1.js → index-_b4VBGHk.js} +30002 -25408
- package/dist/mapintegratedvuer.js +1 -1
- package/dist/mapintegratedvuer.umd.cjs +4291 -229
- package/dist/style-CM86xE3J.js +119 -0
- package/dist/style.css +1 -1
- package/package.json +10 -5
- package/src/App.vue +285 -258
- package/src/assets/styles.scss +1 -1
- package/src/components/ContextCard.vue +0 -1
- package/src/components/DummyRouteComponent.vue +1 -0
- package/src/components/EventBus.ts +13 -0
- package/src/components/FloatingWindow.vue +142 -0
- package/src/components/MapContent.vue +9 -4
- package/src/components/PlotComponent.vue +56 -0
- package/src/components/SplitDialog.vue +1 -6
- package/src/components/SplitFlow.vue +504 -444
- package/src/components/scripts/utilities.js +1 -1
- package/src/components/viewers/Flatmap.vue +166 -83
- package/src/components/viewers/Simulation.vue +118 -11
- package/src/components.d.ts +3 -0
- package/src/main.js +9 -3
- package/src/mixins/ContentMixin.js +467 -406
- package/src/mixins/DynamicMarkerMixin.js +50 -17
- package/src/services/mapping.js +69 -0
- package/src/services/testData.js +71 -0
- package/src/stores/entries.js +1 -1
- package/src/stores/mapping.js +29 -0
- package/src/stores/settings.js +4 -0
- package/src/stores/simulationPlotStore.js +124 -0
- package/src/stores/splitFlow.js +425 -352
- package/src/types/simulation.js +18 -0
- package/dist/Flatmap-uPEQNDkK.js +0 -202
- package/dist/Simulation-C_gdqDes.js +0 -28
- package/dist/style-Czqe2bTf.js +0 -57
- package/src/components/EventBus.js +0 -3
package/src/assets/styles.scss
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<template></template>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import mitt from 'mitt';
|
|
2
|
+
import type { SimulationRequest, SimulationResponse } from '../types/simulation';
|
|
3
|
+
|
|
4
|
+
// Define the mapping of Event Name -> Event Payload
|
|
5
|
+
type Events = {
|
|
6
|
+
'simulation-data-request': SimulationRequest;
|
|
7
|
+
'simulation-data-ready': SimulationResponse;
|
|
8
|
+
[key: string]: any; // Allow for other events with any payload.
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// Pass the type to mitt
|
|
12
|
+
const EventBus = mitt<Events>();
|
|
13
|
+
export default EventBus;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, toRefs, watch } from 'vue'
|
|
3
|
+
import { useDraggable } from '@vueuse/core'
|
|
4
|
+
|
|
5
|
+
const props = defineProps(['windowData', 'offsetX', 'offsetY'])
|
|
6
|
+
const emit = defineEmits(['closeWindow', 'mouseDown'])
|
|
7
|
+
const { windowData } = toRefs(props)
|
|
8
|
+
|
|
9
|
+
// 1. Create a template ref for the DOM element
|
|
10
|
+
const el = ref(null)
|
|
11
|
+
|
|
12
|
+
// 2. Create a "handle" ref so the user can only drag by the header
|
|
13
|
+
const handle = ref(null)
|
|
14
|
+
|
|
15
|
+
const transform = ref('translate(0px, 0px)')
|
|
16
|
+
const isMinimized = ref(false)
|
|
17
|
+
const toggleMinimize = () => {
|
|
18
|
+
isMinimized.value = !isMinimized.value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const getTitle = () => {
|
|
22
|
+
if (windowData.value.label) {
|
|
23
|
+
let title = windowData.value.label;
|
|
24
|
+
if (windowData.value.data?.title) {
|
|
25
|
+
title += ` (${windowData.value.data?.title})`;
|
|
26
|
+
}
|
|
27
|
+
return title;
|
|
28
|
+
} else {
|
|
29
|
+
return windowData.value.data?.title;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
watch(
|
|
34
|
+
[() => props.offsetX, () => props.offsetY],
|
|
35
|
+
([newX, newY]) => {
|
|
36
|
+
transform.value = `translate(-${newX}px, -${newY}px)`
|
|
37
|
+
},
|
|
38
|
+
{ immediate: true }
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
// 3. Activate draggable logic
|
|
42
|
+
// We set initialValue to the props so it opens where we want
|
|
43
|
+
const { x, y, style } = useDraggable(el, {
|
|
44
|
+
initialValue: { x: windowData.value.x, y: windowData.value.y },
|
|
45
|
+
handle: handle, // Only drag when clicking the header
|
|
46
|
+
preventDefault: true,
|
|
47
|
+
})
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<div
|
|
52
|
+
ref="el"
|
|
53
|
+
class="floating-window"
|
|
54
|
+
:class="{ 'is-minimized': isMinimized }"
|
|
55
|
+
:style="[style, { zIndex: windowData.zIndex, transform: transform }]"
|
|
56
|
+
@mousedown="emit('mouseDown', windowData.id)"
|
|
57
|
+
>
|
|
58
|
+
<div ref="handle" class="window-header">
|
|
59
|
+
<span class="title">{{ getTitle() }}</span>
|
|
60
|
+
<div class="window-controls">
|
|
61
|
+
<button @click.stop="toggleMinimize" class="control-btn">
|
|
62
|
+
{{ isMinimized ? '□' : '_' }}
|
|
63
|
+
</button>
|
|
64
|
+
<button @click.stop="emit('closeWindow', windowData.id)">×</button>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div class="window-body" v-show="!isMinimized">
|
|
69
|
+
<slot></slot>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</template>
|
|
73
|
+
|
|
74
|
+
<style scoped>
|
|
75
|
+
.floating-window {
|
|
76
|
+
position: absolute; /* Fixed relative to viewport */
|
|
77
|
+
width: 400px;
|
|
78
|
+
min-width: 200px;
|
|
79
|
+
height: 300px;
|
|
80
|
+
min-height: 150px;
|
|
81
|
+
background: white;
|
|
82
|
+
border: 1px solid #ccc;
|
|
83
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
resize: both; /* Allow resizing */
|
|
87
|
+
overflow: hidden; /* Prevent content overflow */
|
|
88
|
+
transition: height 0.2s ease, width 0.2s ease;
|
|
89
|
+
|
|
90
|
+
.title {
|
|
91
|
+
align-content: center;
|
|
92
|
+
font-size: 12px;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.window-header {
|
|
97
|
+
background: #f0f0f0;
|
|
98
|
+
padding: 8px;
|
|
99
|
+
cursor: grab; /* Shows user it is draggable */
|
|
100
|
+
display: flex;
|
|
101
|
+
justify-content: space-between;
|
|
102
|
+
border-bottom: 1px solid #ddd;
|
|
103
|
+
user-select: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.window-header:active {
|
|
107
|
+
cursor: grabbing;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.window-body {
|
|
111
|
+
flex-grow: 1;
|
|
112
|
+
width: 100%;
|
|
113
|
+
height: 100%;
|
|
114
|
+
position: relative;
|
|
115
|
+
padding: 10px;
|
|
116
|
+
/* overflow: hidden; Important for Plotly resizing */
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.floating-window.is-minimized {
|
|
120
|
+
height: auto !important;
|
|
121
|
+
min-height: 0 !important;
|
|
122
|
+
resize: none; /* Disable resizing when minimized */
|
|
123
|
+
width: 250px; /* Optional: shrink the width to make a neat little bar */
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.window-controls {
|
|
127
|
+
display: flex;
|
|
128
|
+
gap: 5px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.control-btn {
|
|
132
|
+
background: transparent;
|
|
133
|
+
border: 1px solid #ccc;
|
|
134
|
+
cursor: pointer;
|
|
135
|
+
padding: 0 5px;
|
|
136
|
+
border-radius: 3px;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.control-btn:hover {
|
|
140
|
+
background: #e0e0e0;
|
|
141
|
+
}
|
|
142
|
+
</style>
|
|
@@ -25,6 +25,7 @@ import SplitFlow from './SplitFlow.vue';
|
|
|
25
25
|
import EventBus from './EventBus';
|
|
26
26
|
import { mapStores } from 'pinia';
|
|
27
27
|
import { useSettingsStore } from '../stores/settings';
|
|
28
|
+
import { useSimulationPlotStore } from '../stores/simulationPlotStore'
|
|
28
29
|
import { useSplitFlowStore } from '../stores/splitFlow';
|
|
29
30
|
import { defaultSpecies, findSpeciesKey } from './scripts/utilities.js';
|
|
30
31
|
import { MapSvgSpriteColor} from '@abi-software/svg-sprite';
|
|
@@ -334,7 +335,7 @@ export default {
|
|
|
334
335
|
this.$refs.flow.setState(currentState);
|
|
335
336
|
//Do not create a new entry, instead set the multiflatmap viewer
|
|
336
337
|
//to the primary slot
|
|
337
|
-
this.$refs.flow.
|
|
338
|
+
this.$refs.flow.setIdToPane(entry.id);
|
|
338
339
|
break;
|
|
339
340
|
}
|
|
340
341
|
}
|
|
@@ -389,7 +390,7 @@ export default {
|
|
|
389
390
|
},
|
|
390
391
|
},
|
|
391
392
|
computed: {
|
|
392
|
-
...mapStores(useSettingsStore, useSplitFlowStore),
|
|
393
|
+
...mapStores(useSettingsStore, useSimulationPlotStore, useSplitFlowStore),
|
|
393
394
|
stateToSet() {
|
|
394
395
|
return this.state ? this.state : this.initialState;
|
|
395
396
|
},
|
|
@@ -412,6 +413,7 @@ export default {
|
|
|
412
413
|
this.options.pennsieveApi ? this.settingsStore.updatePennsieveApi(this.options.pennsieveApi) : null;
|
|
413
414
|
this.options.flatmapAPI ? this.settingsStore.updateFlatmapAPI(this.options.flatmapAPI) : null;
|
|
414
415
|
this.options.rootUrl ? this.settingsStore.updateRootUrl(this.options.rootUrl) : null;
|
|
416
|
+
this.options.testDataLocation ? this.settingsStore.updateTestDataLocation(this.options.testDataLocation) : null;
|
|
415
417
|
}
|
|
416
418
|
this.settingsStore.updateAllClosable(this.allClosable);
|
|
417
419
|
this.splitFlowStore?.reset();
|
|
@@ -450,13 +452,16 @@ export default {
|
|
|
450
452
|
this.settingsStore.updateUseHelpModeDialog(this.useHelpModeDialog);
|
|
451
453
|
this.settingsStore.updateConnectivityInfoSidebar(this.connectivityInfoSidebar);
|
|
452
454
|
this.settingsStore.updateAnnotationSidebar(this.annotationSidebar);
|
|
453
|
-
|
|
455
|
+
this.simulationPlotStore.initListeners();
|
|
456
|
+
},
|
|
457
|
+
beforeUnmount: function () {
|
|
458
|
+
this.simulationPlotStore.cleanupListeners();
|
|
459
|
+
},
|
|
454
460
|
}
|
|
455
461
|
|
|
456
462
|
</script>
|
|
457
463
|
|
|
458
464
|
<style scoped lang="scss">
|
|
459
|
-
|
|
460
465
|
:deep(.el-loading-spinner) {
|
|
461
466
|
.path {
|
|
462
467
|
stroke: $app-primary-color;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, onMounted, watch } from 'vue';
|
|
3
|
+
import Plotly from 'plotly.js-dist-min';
|
|
4
|
+
import { useResizeObserver, useDebounceFn } from '@vueuse/core';
|
|
5
|
+
|
|
6
|
+
const props = defineProps(['data']);
|
|
7
|
+
const plotContainer = ref(null);
|
|
8
|
+
|
|
9
|
+
const drawPlot = () => {
|
|
10
|
+
if (!plotContainer.value) return;
|
|
11
|
+
|
|
12
|
+
const plotData = [{
|
|
13
|
+
x: props.data?.x || [],
|
|
14
|
+
y: props.data?.y || [],
|
|
15
|
+
type: 'scatter'
|
|
16
|
+
}];
|
|
17
|
+
|
|
18
|
+
const layout = {
|
|
19
|
+
margin: { t: 20, r: 20, b: 40, l: 40 }, // Tight margins for small windows
|
|
20
|
+
autosize: true
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const config = { responsive: true }; // Helps with window resize, but not enough for container resize
|
|
24
|
+
|
|
25
|
+
Plotly.newPlot(plotContainer.value, plotData, layout, config);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Debounce this so we don't spam Plotly while the user is actively dragging
|
|
29
|
+
const handleResize = useDebounceFn(() => {
|
|
30
|
+
if (plotContainer.value) {
|
|
31
|
+
Plotly.Plots.resize(plotContainer.value);
|
|
32
|
+
}
|
|
33
|
+
}, 50); // 50ms delay
|
|
34
|
+
|
|
35
|
+
// Observe resizes, useResizeObserver automatically cleans up when component unmounts
|
|
36
|
+
useResizeObserver(plotContainer, () => {
|
|
37
|
+
handleResize();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
drawPlot();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
watch(() => props.data, drawPlot, { deep: true });
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<div ref="plotContainer" class="plot-container"></div>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<style scoped>
|
|
52
|
+
.plot-container {
|
|
53
|
+
width: 100%;
|
|
54
|
+
height: 100%;
|
|
55
|
+
}
|
|
56
|
+
</style>
|
|
@@ -109,12 +109,7 @@ export default {
|
|
|
109
109
|
return activeContents;
|
|
110
110
|
},
|
|
111
111
|
isIdVisible: function(id) {
|
|
112
|
-
|
|
113
|
-
let visible = false;
|
|
114
|
-
if (paneName !== undefined) {
|
|
115
|
-
visible = this.splitFlowStore.isPaneActive(paneName);
|
|
116
|
-
}
|
|
117
|
-
return visible;
|
|
112
|
+
return this.splitFlowStore.isIdVisible(id);
|
|
118
113
|
},
|
|
119
114
|
getContentsWithId: function(id) {
|
|
120
115
|
let contents = this.$refs["content"];
|