@abi-software/flatmapvuer 1.13.0 → 1.13.1-simulation.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.
@@ -11,7 +11,11 @@
11
11
  style="height: 100%; width: 100%; position: relative; overflow-y: none"
12
12
  >
13
13
  <!-- flatmap-display -->
14
- <div style="height: 100%; width: 100%" ref="display" class="flatmap-display"></div>
14
+ <div
15
+ style="height: 100%; width: 100%"
16
+ ref="display"
17
+ class="flatmap-display"
18
+ ></div>
15
19
  <!-- flatmap-error -->
16
20
  <FlatmapError v-if="flatmapError" :flatmapError="flatmapError" />
17
21
 
@@ -25,7 +29,7 @@
25
29
  :visible="hoverVisibilities[7].value"
26
30
  ref="warningPopover"
27
31
  >
28
- <!--
32
+ <!--
29
33
  What magic meaning do the numbers 6, 7, etc have?
30
34
 
31
35
  Please use `const` to assign meaningful names to them...
@@ -59,10 +63,7 @@ Please use `const` to assign meaningful names to them...
59
63
  SCKAN </a
60
64
  >.
61
65
  </p>
62
- <p v-else
63
- @mouseover="showTooltip(7)"
64
- @mouseout="hideTooltip(7)"
65
- >
66
+ <p v-else @mouseover="showTooltip(7)" @mouseout="hideTooltip(7)">
66
67
  This map displays the connectivity of neuron populations.
67
68
  Specifically, those from the primarily rat-based
68
69
  <a
@@ -86,7 +87,9 @@ Please use `const` to assign meaningful names to them...
86
87
  @mouseover="showTooltip(7)"
87
88
  @mouseout="hideTooltip(7)"
88
89
  >
89
- <el-icon v-if="displayWarning || isLegacy"><el-icon-warning-filled /></el-icon>
90
+ <el-icon v-if="displayWarning || isLegacy"
91
+ ><el-icon-warning-filled
92
+ /></el-icon>
90
93
  <template v-if="isLegacy">
91
94
  <span class="warning-text">Legacy Map</span>
92
95
  <div class="latest-map-text" @click="viewLatestMap">
@@ -123,13 +126,13 @@ Please use `const` to assign meaningful names to them...
123
126
  <template #default>
124
127
  <b>Connectivity References</b>
125
128
  <p>
126
- Connectivity references have been improved and available
127
- in various formats.
129
+ Connectivity references have been improved and available in
130
+ various formats.
128
131
  </p>
129
132
  <b>Improved state storing</b>
130
133
  <p>
131
- Current selection and visibility filters are now stored
132
- when creating a permalink.
134
+ Current selection and visibility filters are now stored when
135
+ creating a permalink.
133
136
  </p>
134
137
  </template>
135
138
  </el-popover>
@@ -147,7 +150,11 @@ Please use `const` to assign meaningful names to them...
147
150
  </el-icon>
148
151
 
149
152
  <DrawToolbar
150
- v-if="viewingMode === 'Annotation' && (authorisedUser || offlineAnnotationEnabled) && !disableUI"
153
+ v-if="
154
+ viewingMode === 'Annotation' &&
155
+ (authorisedUser || offlineAnnotationEnabled) &&
156
+ !disableUI
157
+ "
151
158
  :mapCanvas="{
152
159
  containerHTML: this.$el,
153
160
  class: '.maplibregl-canvas',
@@ -166,7 +173,79 @@ Please use `const` to assign meaningful names to them...
166
173
  @hideTooltip="hideTooltip"
167
174
  ref="toolbarPopover"
168
175
  />
169
-
176
+ <!-- <div class="top-left-control" v-if="simulationInfo.length > 0"> -->
177
+ <el-popover
178
+ content="Open simulation protocols"
179
+ v-if="simulationInfo.length > 0"
180
+ placement="right"
181
+ :teleported="false"
182
+ trigger="manual"
183
+ :offset="-18"
184
+ popper-class="flatmap-popper"
185
+ :visible="hoverVisibilities[16].value"
186
+ ref="simulationPopover"
187
+ >
188
+ <template #reference>
189
+ <div
190
+ class="popover-location top"
191
+ :class="{
192
+ open: simulationDrawerOpen,
193
+ close: !simulationDrawerOpen,
194
+ }"
195
+ v-show="!disableUI"
196
+ >
197
+ <div
198
+ class="pathway-container"
199
+ :class="{
200
+ open: simulationDrawerOpen,
201
+ close: !simulationDrawerOpen,
202
+ }"
203
+ v-popover:simulationPopover
204
+ >
205
+ <h4 style="margin-top: 0; margin-bottom: 10px">
206
+ Available Protocols
207
+ </h4>
208
+ <el-select
209
+ v-model="selectedSimulation"
210
+ placeholder="Select a simulation"
211
+ size="default"
212
+ style="width: 100%; margin-bottom: 10px"
213
+ value-key="path"
214
+ >
215
+ <el-option
216
+ v-for="info in simulationInfo"
217
+ :key="info.path"
218
+ :label="getSimulationLabel(info)"
219
+ :value="info"
220
+ />
221
+ </el-select>
222
+ <el-button
223
+ type="primary"
224
+ @click="openSimulation"
225
+ :disabled="!selectedSimulation"
226
+ style="width: 100%"
227
+ >
228
+ Open Simulation
229
+ </el-button>
230
+ </div>
231
+ <div
232
+ @click="simulationDrawerOpen = !simulationDrawerOpen"
233
+ class="drawer-button"
234
+ :class="{
235
+ open: simulationDrawerOpen,
236
+ close: !simulationDrawerOpen,
237
+ }"
238
+ title="Toggle Simulation Panel"
239
+ >
240
+ <!-- Arrow icons for open/close state -->
241
+ <el-icon>
242
+ <el-icon-arrow-left />
243
+ </el-icon>
244
+ </div>
245
+ </div>
246
+ </template>
247
+ </el-popover>
248
+ <!-- </div> -->
170
249
  <div class="bottom-right-control" v-show="!disableUI">
171
250
  <el-popover
172
251
  content="Zoom in"
@@ -185,10 +264,7 @@ Please use `const` to assign meaningful names to them...
185
264
  @mouseover="showTooltip(1)"
186
265
  @mouseout="hideTooltip(1)"
187
266
  >
188
- <map-svg-icon
189
- class="icon-button zoomIn"
190
- icon="zoomIn"
191
- />
267
+ <map-svg-icon class="icon-button zoomIn" icon="zoomIn" />
192
268
  </div>
193
269
  </template>
194
270
  </el-popover>
@@ -196,23 +272,14 @@ Please use `const` to assign meaningful names to them...
196
272
  content="Zoom out"
197
273
  placement="top-end"
198
274
  :teleported="false"
199
- trigger="manual"
275
+ :auto-close="1300"
200
276
  width="70"
201
277
  popper-class="flatmap-popper"
202
- :visible="hoverVisibilities[2].value"
203
278
  ref="zoomOutPopover"
204
279
  >
205
280
  <template #reference>
206
- <div
207
- class="icon-button-container"
208
- @click="zoomOut()"
209
- @mouseover="showTooltip(2)"
210
- @mouseout="hideTooltip(2)"
211
- >
212
- <map-svg-icon
213
- class="icon-button zoomOut"
214
- icon="zoomOut"
215
- />
281
+ <div class="icon-button-container" @click="zoomOut()">
282
+ <map-svg-icon class="icon-button zoomOut" icon="zoomOut" />
216
283
  </div>
217
284
  </template>
218
285
  </el-popover>
@@ -238,16 +305,14 @@ Please use `const` to assign meaningful names to them...
238
305
  @mouseover="showTooltip(3)"
239
306
  @mouseout="hideTooltip(3)"
240
307
  >
241
- <map-svg-icon
242
- class="icon-button fitWindow"
243
- icon="fitWindow"
244
- />
308
+ <map-svg-icon class="icon-button fitWindow" icon="fitWindow" />
245
309
  </div>
246
310
  </template>
247
311
  </el-popover>
248
312
  </div>
249
313
  <el-popover
250
314
  content="Change pathway visibility"
315
+ class="somerandomclass"
251
316
  placement="right"
252
317
  :teleported="false"
253
318
  trigger="manual"
@@ -258,7 +323,7 @@ Please use `const` to assign meaningful names to them...
258
323
  >
259
324
  <template #reference>
260
325
  <div
261
- class="pathway-location"
326
+ class="popover-location bottom"
262
327
  :class="{ open: drawerOpen, close: !drawerOpen }"
263
328
  v-show="!disableUI && requiresDrawer"
264
329
  >
@@ -268,7 +333,7 @@ Please use `const` to assign meaningful names to them...
268
333
  :style="{ 'max-height': pathwaysMaxHeight + 'px' }"
269
334
  v-popover:checkBoxPopover
270
335
  >
271
- <dynamic-legends
336
+ <DynamicLegends
272
337
  v-if="legendEntry.length"
273
338
  identifierKey="prompt"
274
339
  colourKey="colour"
@@ -366,7 +431,11 @@ Please use `const` to assign meaningful names to them...
366
431
  key="pathwaysSelection"
367
432
  />
368
433
  <selections-group
369
- v-if="taxonConnectivity && taxonConnectivity.length > 0 && showPathwayFilter"
434
+ v-if="
435
+ taxonConnectivity &&
436
+ taxonConnectivity.length > 0 &&
437
+ showPathwayFilter
438
+ "
370
439
  title="Studied in"
371
440
  labelKey="label"
372
441
  identifierKey="taxon"
@@ -408,9 +477,7 @@ Please use `const` to assign meaningful names to them...
408
477
  @event open-map
409
478
  @arg {String} `mapOption.key`
410
479
  -->
411
- <el-button type="primary" plain
412
- @click="$emit('open-map', item.key)"
413
- >
480
+ <el-button type="primary" plain @click="$emit('open-map', item.key)">
414
481
  {{ item.display }}
415
482
  </el-button>
416
483
  </el-row>
@@ -428,23 +495,29 @@ Please use `const` to assign meaningful names to them...
428
495
  <div>
429
496
  <el-row class="backgroundText">Viewing Mode</el-row>
430
497
  <el-row class="backgroundControl">
431
- <div style="margin-bottom: 2px;">
432
- <template
433
- v-for="(value, key, index) in viewingModes"
434
- :key="key"
435
- >
436
- <template v-if="key === viewingMode">
437
- <span class="viewing-mode-title"><b >{{ key }}</b></span>
438
- </template>
439
- <template v-else>
440
- <span class="viewing-mode-unselected" @click="changeViewingMode(key)">{{ key }}</span>
441
- </template>
498
+ <div style="margin-bottom: 2px">
499
+ <template v-for="(value, key, index) in viewingModes" :key="key">
500
+ <template v-if="key === viewingMode">
501
+ <span class="viewing-mode-title"
502
+ ><b>{{ key }}</b></span
503
+ >
504
+ </template>
505
+ <template v-else>
506
+ <span
507
+ class="viewing-mode-unselected"
508
+ @click="changeViewingMode(key)"
509
+ >{{ key }}</span
510
+ >
511
+ </template>
442
512
  </template>
443
513
  </div>
444
514
  <el-row class="viewing-mode-description">
445
515
  {{ modeDescription }}
446
516
  </el-row>
447
- <el-row v-if="viewingMode === 'Annotation' && offlineAnnotationEnabled" class="viewing-mode-description">
517
+ <el-row
518
+ v-if="viewingMode === 'Annotation' && offlineAnnotationEnabled"
519
+ class="viewing-mode-description"
520
+ >
448
521
  (Anonymous annotate)
449
522
  </el-row>
450
523
  </el-row>
@@ -472,16 +545,21 @@ Please use `const` to assign meaningful names to them...
472
545
  </el-select>
473
546
  </el-row>
474
547
  </template>
475
- <el-row class="backgroundSpacer" v-if="displayFlightPathOption"></el-row>
476
- <el-row class="backgroundText" v-if="displayFlightPathOption">Flight path display</el-row>
548
+ <el-row
549
+ class="backgroundSpacer"
550
+ v-if="displayFlightPathOption"
551
+ ></el-row>
552
+ <el-row class="backgroundText" v-if="displayFlightPathOption"
553
+ >Flight path display</el-row
554
+ >
477
555
  <el-row class="backgroundControl" v-if="displayFlightPathOption">
478
556
  <el-radio-group
479
557
  v-model="flightPath3DRadio"
480
558
  class="flatmap-radio"
481
559
  @change="setFlightPath3D"
482
560
  >
483
- <el-radio :value="false">2D</el-radio>
484
- <el-radio :value="true">3D</el-radio>
561
+ <el-radio :value="false">2D</el-radio>
562
+ <el-radio :value="true">3D</el-radio>
485
563
  </el-radio-group>
486
564
  </el-row>
487
565
  <el-row class="backgroundSpacer"></el-row>
@@ -571,10 +649,7 @@ Please use `const` to assign meaningful names to them...
571
649
  @mouseover="showTooltip(5)"
572
650
  @mouseout="hideTooltip(5)"
573
651
  >
574
- <map-svg-icon
575
- icon="changeBckgd"
576
- class="icon-button"
577
- />
652
+ <map-svg-icon icon="changeBckgd" class="icon-button" />
578
653
  </div>
579
654
  </template>
580
655
  </el-popover>
@@ -636,24 +711,24 @@ import ResizeSensor from 'css-element-queries/src/ResizeSensor'
636
711
  import flatmap from '../services/flatmapLoader.js'
637
712
  import { AnnotationService } from '@abi-software/sparc-annotation'
638
713
  import { mapState } from 'pinia'
639
- import { useMainStore } from '@/store/index'
714
+ import { useMainStore } from '../store/index.js'
640
715
  import {
641
716
  fetchLabels,
642
717
  DrawToolbar,
643
718
  Tooltip,
644
719
  TreeControls,
645
- getFlatmapFilterOptions
720
+ getFlatmapFilterOptions,
646
721
  } from '@abi-software/map-utilities'
647
722
  import '@abi-software/map-utilities/dist/style.css'
648
723
  import EventBus from './EventBus.js'
649
724
  import FlatmapError from './FlatmapError.vue'
650
725
 
651
- const ERROR_MESSAGE = 'cannot be found on the map.';
726
+ const ERROR_MESSAGE = 'cannot be found on the map.'
652
727
 
653
728
  const centroid = (geometry) => {
654
- let featureGeometry = { lng: 0, lat: 0, }
729
+ let featureGeometry = { lng: 0, lat: 0 }
655
730
  let coordinates
656
- if (geometry.type === "Polygon") {
731
+ if (geometry.type === 'Polygon') {
657
732
  if (geometry.coordinates.length) {
658
733
  coordinates = geometry.coordinates[0]
659
734
  }
@@ -727,6 +802,7 @@ export default {
727
802
  ElIconArrowDown,
728
803
  ElIconArrowLeft,
729
804
  DrawToolbar,
805
+ DynamicLegends,
730
806
  FlatmapError,
731
807
  },
732
808
  beforeCreate: function () {
@@ -738,7 +814,7 @@ export default {
738
814
  setup(props) {
739
815
  let annotator = inject('$annotator')
740
816
  if (!annotator) {
741
- annotator = markRaw(new AnnotationService(`${props.flatmapAPI}annotator`));
817
+ annotator = markRaw(new AnnotationService(`${props.flatmapAPI}annotator`))
742
818
  provide('$annotator', annotator)
743
819
  }
744
820
  return { annotator }
@@ -763,17 +839,17 @@ export default {
763
839
  if (this.mapImp) {
764
840
  if (this.mapImp.contextLost) {
765
841
  if (filter) {
766
- this.filterToRestore = markRaw(JSON.parse(JSON.stringify(filter)));
842
+ this.filterToRestore = markRaw(JSON.parse(JSON.stringify(filter)))
767
843
  } else {
768
- this.filterToRestore = undefined;
844
+ this.filterToRestore = undefined
769
845
  }
770
846
  } else {
771
847
  if (filter) {
772
- this.mapImp.setVisibilityFilter(filter);
848
+ this.mapImp.setVisibilityFilter(filter)
773
849
  } else {
774
- this.mapImp.clearVisibilityFilter();
850
+ this.mapImp.clearVisibilityFilter()
775
851
  }
776
- this.filterToRestore = undefined;
852
+ this.filterToRestore = undefined
777
853
  }
778
854
  }
779
855
  },
@@ -782,7 +858,7 @@ export default {
782
858
  * Function to manually send aborted signal when annotation tooltip popup or sidebar tab closed.
783
859
  */
784
860
  manualAbortedOnClose: function () {
785
- if (this.annotationSidebar) this.$emit("annotation-close")
861
+ if (this.annotationSidebar) this.$emit('annotation-close')
786
862
  this.closeTooltip()
787
863
  this.annotationEventCallback({}, { type: 'aborted' })
788
864
  this.initialiseDrawing()
@@ -803,12 +879,14 @@ export default {
803
879
  */
804
880
  cancelDrawnFeature: function () {
805
881
  if (this.isValidDrawnCreated) {
806
- if (this.annotationSidebar) this.$emit("annotation-close")
882
+ if (this.annotationSidebar) this.$emit('annotation-close')
807
883
  this.closeTooltip()
808
- this.annotationEntry = [{
809
- ...this.drawnCreatedEvent.feature,
810
- resourceId: this.serverURL,
811
- }]
884
+ this.annotationEntry = [
885
+ {
886
+ ...this.drawnCreatedEvent.feature,
887
+ resourceId: this.serverURL,
888
+ },
889
+ ]
812
890
  this.rollbackAnnotationEvent()
813
891
  this.initialiseDrawing()
814
892
  }
@@ -824,7 +902,11 @@ export default {
824
902
  const numericId = Number(value)
825
903
  const featureObject = numericId
826
904
  ? this.mapImp.featureProperties(numericId)
827
- : { feature: this.existDrawnFeatures.find(feature => feature.id === value.trim()) };
905
+ : {
906
+ feature: this.existDrawnFeatures.find(
907
+ (feature) => feature.id === value.trim()
908
+ ),
909
+ }
828
910
  let payload = { feature: featureObject }
829
911
  this.checkAndCreatePopups([payload], false)
830
912
  } else {
@@ -855,7 +937,7 @@ export default {
855
937
  * @arg {String} `name`
856
938
  */
857
939
  toolbarEvent: function (type, name) {
858
- if (this.isValidDrawnCreated) return;
940
+ if (this.isValidDrawnCreated) return
859
941
  this.manualAbortedOnClose()
860
942
  this.doubleClickedFeature = false
861
943
  // Deselect any feature when draw mode/tool is changed
@@ -866,7 +948,10 @@ export default {
866
948
  // Remove any unsubmitted drawn
867
949
  this.cancelDrawnFeature()
868
950
  if (name) {
869
- const tool = name.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
951
+ const tool = name.replace(
952
+ /[A-Z]/g,
953
+ (letter) => `_${letter.toLowerCase()}`
954
+ )
870
955
  this.changeAnnotationDrawMode({ mode: `draw${tool}` })
871
956
  }
872
957
  this.activeDrawTool = name
@@ -884,7 +969,7 @@ export default {
884
969
  if (data.feature.feature.geometry.type !== 'Point') {
885
970
  this.changeAnnotationDrawMode({
886
971
  mode: 'direct_select',
887
- options: { featureId: data.feature.feature.id }
972
+ options: { featureId: data.feature.feature.id },
888
973
  })
889
974
  this.modifyAnnotationFeature()
890
975
  }
@@ -893,7 +978,7 @@ export default {
893
978
  } else if (this.activeDrawMode === 'Delete') {
894
979
  this.changeAnnotationDrawMode({
895
980
  mode: 'simple_select',
896
- options: { featureIds: [data.feature.feature.id] }
981
+ options: { featureIds: [data.feature.feature.id] },
897
982
  })
898
983
  this.modifyAnnotationFeature()
899
984
  }
@@ -908,7 +993,9 @@ export default {
908
993
  type: 'connectivity',
909
994
  source: features[0],
910
995
  target: features[features.length - 1],
911
- intermediates: features.filter((f, index) => index !== 0 && index !== features.length - 1),
996
+ intermediates: features.filter(
997
+ (f, index) => index !== 0 && index !== features.length - 1
998
+ ),
912
999
  }
913
1000
  this.annotationEntry[0].body = body
914
1001
  }
@@ -932,12 +1019,12 @@ export default {
932
1019
  this.mapImp.clearAnnotationFeature()
933
1020
  }
934
1021
  },
935
- forceContextLoss: function() {
1022
+ forceContextLoss: function () {
936
1023
  if (this.mapImp && !this.mapImp.contextLost && !this.loading) {
937
1024
  this.mapImp.forceContextLoss()
938
1025
  }
939
1026
  },
940
- forceContextRestore: function() {
1027
+ forceContextRestore: function () {
941
1028
  if (this.mapImp) {
942
1029
  this.flatmapError = null
943
1030
  this.mapImp.forceContextRestore()
@@ -979,22 +1066,35 @@ export default {
979
1066
  commitAnnotationEvent: function (annotation) {
980
1067
  if (this.mapImp) {
981
1068
  if (this.offlineAnnotationEnabled) {
982
- this.offlineAnnotations = JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
1069
+ this.offlineAnnotations =
1070
+ JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
983
1071
  this.offlineAnnotations.push(annotation)
984
1072
  if (this.annotationEntry[0].type === 'deleted') {
985
- this.offlineAnnotations = this.offlineAnnotations.filter((offline) => {
986
- return offline.resource !== this.serverURL || offline.item.id !== annotation.item.id
987
- })
1073
+ this.offlineAnnotations = this.offlineAnnotations.filter(
1074
+ (offline) => {
1075
+ return (
1076
+ offline.resource !== this.serverURL ||
1077
+ offline.item.id !== annotation.item.id
1078
+ )
1079
+ }
1080
+ )
988
1081
  }
989
- sessionStorage.setItem('anonymous-annotation', JSON.stringify(this.offlineAnnotations))
1082
+ sessionStorage.setItem(
1083
+ 'anonymous-annotation',
1084
+ JSON.stringify(this.offlineAnnotations)
1085
+ )
990
1086
  }
991
- if (['created', 'updated', 'deleted'].includes(this.annotationEntry[0].type)) {
1087
+ if (
1088
+ ['created', 'updated', 'deleted'].includes(
1089
+ this.annotationEntry[0].type
1090
+ )
1091
+ ) {
992
1092
  this.featureAnnotationSubmitted = true
993
1093
  this.mapImp.commitAnnotationEvent(this.annotationEntry[0])
994
- if (annotation.body.comment === "Position Updated") {
1094
+ if (annotation.body.comment === 'Position Updated') {
995
1095
  this.annotationEntry[0].positionUpdated = false
996
1096
  } else if (this.annotationEntry[0].type === 'deleted') {
997
- if (this.annotationSidebar) this.$emit("annotation-close")
1097
+ if (this.annotationSidebar) this.$emit('annotation-close')
998
1098
  this.closeTooltip()
999
1099
  // Only delete need, keep the annotation tooltip/sidebar open if created/updated
1000
1100
  this.annotationEntry = []
@@ -1009,17 +1109,29 @@ export default {
1009
1109
  * @arg {String} `userId`,
1010
1110
  * @arg {String} `participated`
1011
1111
  */
1012
- fetchAnnotatedItemIds: async function (userId = undefined, participated = undefined) {
1112
+ fetchAnnotatedItemIds: async function (
1113
+ userId = undefined,
1114
+ participated = undefined
1115
+ ) {
1013
1116
  let annotatedItemIds
1014
1117
  if (this.offlineAnnotationEnabled) {
1015
- this.offlineAnnotations = JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
1016
- annotatedItemIds = this.offlineAnnotations.filter((offline) => {
1017
- return offline.resource === this.serverURL
1018
- }).map(offline => offline.item.id)
1118
+ this.offlineAnnotations =
1119
+ JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
1120
+ annotatedItemIds = this.offlineAnnotations
1121
+ .filter((offline) => {
1122
+ return offline.resource === this.serverURL
1123
+ })
1124
+ .map((offline) => offline.item.id)
1019
1125
  } else {
1020
- annotatedItemIds = await this.annotator.annotatedItemIds(this.userToken, this.serverURL, userId, participated)
1126
+ annotatedItemIds = await this.annotator.annotatedItemIds(
1127
+ this.userToken,
1128
+ this.serverURL,
1129
+ userId,
1130
+ participated
1131
+ )
1021
1132
  // The annotator has `resource` and `items` fields
1022
- if ('resource' in annotatedItemIds) annotatedItemIds = annotatedItemIds.itemIds
1133
+ if ('resource' in annotatedItemIds)
1134
+ annotatedItemIds = annotatedItemIds.itemIds
1023
1135
  }
1024
1136
  return annotatedItemIds
1025
1137
  },
@@ -1044,13 +1156,23 @@ export default {
1044
1156
  fetchDrawnFeatures: async function (userId, participated) {
1045
1157
  let drawnFeatures
1046
1158
  if (this.offlineAnnotationEnabled) {
1047
- this.offlineAnnotations = JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
1048
- drawnFeatures = this.offlineAnnotations.filter((offline) => {
1049
- return offline.feature && offline.resource === this.serverURL
1050
- }).map(offline => offline.feature)
1159
+ this.offlineAnnotations =
1160
+ JSON.parse(sessionStorage.getItem('anonymous-annotation')) || []
1161
+ drawnFeatures = this.offlineAnnotations
1162
+ .filter((offline) => {
1163
+ return offline.feature && offline.resource === this.serverURL
1164
+ })
1165
+ .map((offline) => offline.feature)
1051
1166
  } else {
1052
- const annotatedItemIds = await this.fetchAnnotatedItemIds(userId, participated)
1053
- drawnFeatures = await this.annotator.drawnFeatures(this.userToken, this.serverURL, annotatedItemIds)
1167
+ const annotatedItemIds = await this.fetchAnnotatedItemIds(
1168
+ userId,
1169
+ participated
1170
+ )
1171
+ drawnFeatures = await this.annotator.drawnFeatures(
1172
+ this.userToken,
1173
+ this.serverURL,
1174
+ annotatedItemIds
1175
+ )
1054
1176
  // The annotator has `resource` and `features` fields
1055
1177
  if ('resource' in drawnFeatures) drawnFeatures = drawnFeatures.features
1056
1178
  }
@@ -1066,13 +1188,22 @@ export default {
1066
1188
  this.clearAnnotationFeature()
1067
1189
  this.loading = true
1068
1190
  }
1069
- const userId = this.annotationFrom === 'Anyone' ?
1070
- undefined : this.authorisedUser.orcid ?
1071
- this.authorisedUser.orcid : '0000-0000-0000-0000'
1072
- const participated = this.annotationFrom === 'Anyone' ?
1073
- undefined : this.annotationFrom === 'Me' ?
1074
- true : false
1075
- const drawnFeatures = await this.fetchDrawnFeatures(userId, participated)
1191
+ const userId =
1192
+ this.annotationFrom === 'Anyone'
1193
+ ? undefined
1194
+ : this.authorisedUser.orcid
1195
+ ? this.authorisedUser.orcid
1196
+ : '0000-0000-0000-0000'
1197
+ const participated =
1198
+ this.annotationFrom === 'Anyone'
1199
+ ? undefined
1200
+ : this.annotationFrom === 'Me'
1201
+ ? true
1202
+ : false
1203
+ const drawnFeatures = await this.fetchDrawnFeatures(
1204
+ userId,
1205
+ participated
1206
+ )
1076
1207
  this.existDrawnFeatures = drawnFeatures
1077
1208
  this.loading = false
1078
1209
  if (!this.featureAnnotationSubmitted) {
@@ -1111,7 +1242,10 @@ export default {
1111
1242
  * Function to emit offline annotation enabled status
1112
1243
  */
1113
1244
  emitOfflineAnnotationUpdate: function () {
1114
- this.$emit('update-offline-annotation-enabled', this.offlineAnnotationEnabled);
1245
+ this.$emit(
1246
+ 'update-offline-annotation-enabled',
1247
+ this.offlineAnnotationEnabled
1248
+ )
1115
1249
  },
1116
1250
  /**
1117
1251
  * @public
@@ -1193,15 +1327,20 @@ export default {
1193
1327
  entityLabels.forEach((entityLabel) => {
1194
1328
  let enabled = true
1195
1329
  if (state) {
1196
- enabled = state.checkAll ? true : state.checked.includes(entityLabel.taxon)
1330
+ enabled = state.checkAll
1331
+ ? true
1332
+ : state.checked.includes(entityLabel.taxon)
1197
1333
  }
1198
- this.taxonConnectivity.push({...entityLabel, enabled});
1334
+ this.taxonConnectivity.push({ ...entityLabel, enabled })
1199
1335
  if (this.mapImp) {
1200
- this.mapImp.enableConnectivityByTaxonIds(entityLabel.taxon, enabled)
1336
+ this.mapImp.enableConnectivityByTaxonIds(
1337
+ entityLabel.taxon,
1338
+ enabled
1339
+ )
1201
1340
  }
1202
- });
1341
+ })
1203
1342
  }
1204
- });
1343
+ })
1205
1344
  },
1206
1345
  /**
1207
1346
  * @public
@@ -1236,19 +1375,19 @@ export default {
1236
1375
  },
1237
1376
  setInitMapState: function () {
1238
1377
  if (this.mapImp) {
1239
- const map = this.mapImp.map;
1240
- const bounds = this.mapImp.options.bounds;
1378
+ const map = this.mapImp.map
1379
+ const bounds = this.mapImp.options.bounds
1241
1380
  const initBounds = [
1242
1381
  [bounds[0], bounds[1]],
1243
- [bounds[2], bounds[3]]
1244
- ];
1382
+ [bounds[2], bounds[3]],
1383
+ ]
1245
1384
 
1246
- map.setMaxBounds(null); // override default
1247
- map.setRenderWorldCopies(false);
1385
+ map.setMaxBounds(null) // override default
1386
+ map.setRenderWorldCopies(false)
1248
1387
 
1249
1388
  this.initMapState = markRaw({
1250
1389
  initBounds,
1251
- });
1390
+ })
1252
1391
  }
1253
1392
  },
1254
1393
  /**
@@ -1259,17 +1398,17 @@ export default {
1259
1398
  resetView: function () {
1260
1399
  if (this.mapImp) {
1261
1400
  // fit to window
1262
- const map = this.mapImp.map;
1263
- const { initBounds } = this.initMapState;
1401
+ const map = this.mapImp.map
1402
+ const { initBounds } = this.initMapState
1264
1403
  // reset rotation
1265
1404
  map.resetNorthPitch({
1266
1405
  animate: false,
1267
- });
1406
+ })
1268
1407
  if (initBounds) {
1269
1408
  // reset zoom and position
1270
1409
  map.fitBounds(initBounds, {
1271
- animate: false
1272
- });
1410
+ animate: false,
1411
+ })
1273
1412
  }
1274
1413
  if (this.$refs.skcanSelection) {
1275
1414
  this.$refs.skcanSelection.reset()
@@ -1306,7 +1445,7 @@ export default {
1306
1445
  }
1307
1446
  },
1308
1447
  onSelectionsDataChanged: function (data) {
1309
- this.$emit('pathway-selection-changed', data);
1448
+ this.$emit('pathway-selection-changed', data)
1310
1449
  },
1311
1450
  /**
1312
1451
  * // Currently not in use
@@ -1349,76 +1488,94 @@ export default {
1349
1488
  retrieveConnectedPaths: async function (payload, options = {}) {
1350
1489
  // query all connected paths from flatmap
1351
1490
  if (this.mapImp) {
1352
- let connectedPaths = [];
1353
- let connectedTarget = options.target?.length ? options.target : [];
1491
+ let connectedPaths = []
1492
+ let connectedTarget = options.target?.length ? options.target : []
1354
1493
  // The line below is to get the path features from the geojson ids
1355
- const nodeFeatureIds = [...this.mapImp.pathModelNodes(payload)];
1356
- const pathsOfEntities = await this.mapImp.queryPathsForFeatures(payload);
1494
+ const nodeFeatureIds = [...this.mapImp.pathModelNodes(payload)]
1495
+ const pathsOfEntities = await this.mapImp.queryPathsForFeatures(payload)
1357
1496
  if (nodeFeatureIds.length) {
1358
1497
  if (!connectedTarget.length) {
1359
- const connectedType = options.type?.length ? options.type : ["all"];
1360
- const connectivity = await this.flatmapQueries.queryForConnectivityNew(this.mapImp, payload[0]);
1361
- const originsFlat = connectivity?.ids?.dendrites.flat(Infinity);
1362
- const componentsFlat = connectivity?.ids?.components.flat(Infinity);
1363
- const destinationsFlat = connectivity?.ids?.axons.flat(Infinity);
1364
- let connected = [];
1365
- if (connectedType.includes("origins")) connected.push(...originsFlat);
1366
- if (connectedType.includes("components")) connected.push(...componentsFlat);
1367
- if (connectedType.includes("destinations")) connected.push(...destinationsFlat);
1368
- if (connectedType.includes("all")) connected.push(...originsFlat, ...componentsFlat, ...destinationsFlat);
1369
- connectedTarget = [...new Set(connected)];
1498
+ const connectedType = options.type?.length ? options.type : ['all']
1499
+ const connectivity =
1500
+ await this.flatmapQueries.queryForConnectivityNew(
1501
+ this.mapImp,
1502
+ payload[0]
1503
+ )
1504
+ const originsFlat = connectivity?.ids?.dendrites.flat(Infinity)
1505
+ const componentsFlat = connectivity?.ids?.components.flat(Infinity)
1506
+ const destinationsFlat = connectivity?.ids?.axons.flat(Infinity)
1507
+ let connected = []
1508
+ if (connectedType.includes('origins'))
1509
+ connected.push(...originsFlat)
1510
+ if (connectedType.includes('components'))
1511
+ connected.push(...componentsFlat)
1512
+ if (connectedType.includes('destinations'))
1513
+ connected.push(...destinationsFlat)
1514
+ if (connectedType.includes('all'))
1515
+ connected.push(
1516
+ ...originsFlat,
1517
+ ...componentsFlat,
1518
+ ...destinationsFlat
1519
+ )
1520
+ connectedTarget = [...new Set(connected)]
1370
1521
  }
1371
1522
  // Loop through the node features and check if we have certain nodes
1372
1523
  nodeFeatureIds.forEach((featureId) => {
1373
1524
  // Get the paths from each node feature
1374
- const pathsL2 = this.mapImp.nodePathModels(featureId);
1525
+ const pathsL2 = this.mapImp.nodePathModels(featureId)
1375
1526
  pathsL2.forEach((path) => {
1376
1527
  // nodes of the second level path
1377
- const nodeFeatureIdsL2 = this.mapImp.pathModelNodes(path);
1528
+ const nodeFeatureIdsL2 = this.mapImp.pathModelNodes(path)
1378
1529
  const nodeModelsL2 = nodeFeatureIdsL2.map((featureIdL2) => {
1379
- return this.mapImp.featureProperties(featureIdL2).models;
1380
- });
1381
- const intersection = connectedTarget.filter(element => nodeModelsL2.includes(element));
1382
- if (intersection.length && !connectedPaths.includes(path)) connectedPaths.push(path);
1383
- });
1384
- });
1530
+ return this.mapImp.featureProperties(featureIdL2).models
1531
+ })
1532
+ const intersection = connectedTarget.filter((element) =>
1533
+ nodeModelsL2.includes(element)
1534
+ )
1535
+ if (intersection.length && !connectedPaths.includes(path))
1536
+ connectedPaths.push(path)
1537
+ })
1538
+ })
1385
1539
  } else if (pathsOfEntities.length) {
1386
1540
  if (connectedTarget.length) {
1387
1541
  pathsOfEntities.forEach((path) => {
1388
- const nodeFeatureIds = this.mapImp.pathModelNodes(path);
1542
+ const nodeFeatureIds = this.mapImp.pathModelNodes(path)
1389
1543
  const nodeModels = nodeFeatureIds.map((featureId) => {
1390
- return this.mapImp.featureProperties(featureId).models;
1391
- });
1392
- const intersection = connectedTarget.filter(element => nodeModels.includes(element));
1393
- if (intersection.length && !connectedPaths.includes(path)) connectedPaths.push(path);
1394
- });
1544
+ return this.mapImp.featureProperties(featureId).models
1545
+ })
1546
+ const intersection = connectedTarget.filter((element) =>
1547
+ nodeModels.includes(element)
1548
+ )
1549
+ if (intersection.length && !connectedPaths.includes(path))
1550
+ connectedPaths.push(path)
1551
+ })
1395
1552
  } else {
1396
- connectedPaths = pathsOfEntities;
1553
+ connectedPaths = pathsOfEntities
1397
1554
  }
1398
1555
  }
1399
- connectedPaths = [...new Set([...connectedPaths, ...payload])];
1400
- return connectedPaths;
1556
+ connectedPaths = [...new Set([...connectedPaths, ...payload])]
1557
+ return connectedPaths
1401
1558
  }
1402
1559
  },
1403
- resetMapFilter: function() {
1404
- const alert = this.mapFilters.alert;
1405
- let filter;
1406
- const isPathways = { 'tile-layer': 'pathways' };
1407
- const notPathways = { NOT: isPathways };
1560
+ resetMapFilter: function () {
1561
+ const alert = this.mapFilters.alert
1562
+ let filter
1563
+ const isPathways = { 'tile-layer': 'pathways' }
1564
+ const notPathways = { NOT: isPathways }
1408
1565
 
1409
1566
  if (alert.with && !alert.without) {
1410
1567
  // Show pathways with alert
1411
1568
  filter = {
1412
- OR: [notPathways, { AND: [isPathways, { HAS: 'alert' }] }]
1413
- };
1569
+ OR: [notPathways, { AND: [isPathways, { HAS: 'alert' }] }],
1570
+ }
1414
1571
  } else if (!alert.with && alert.without) {
1415
1572
  // Show pathways without alert
1416
1573
  filter = {
1417
- OR: [notPathways, { AND: [isPathways, { NOT: { HAS: 'alert' } }] }]
1418
- };
1574
+ OR: [notPathways, { AND: [isPathways, { NOT: { HAS: 'alert' } }] }],
1575
+ }
1419
1576
  } else if (!alert.with && !alert.without) {
1420
1577
  // Hide all pathways
1421
- filter = notPathways;
1578
+ filter = notPathways
1422
1579
  }
1423
1580
  this.setVisibilityFilter(filter)
1424
1581
  },
@@ -1431,16 +1588,17 @@ export default {
1431
1588
  alertMouseEnterEmitted: function (payload) {
1432
1589
  if (this.mapImp) {
1433
1590
  if (payload.value) {
1434
- let filter;
1435
- const isPathways = { 'tile-layer': 'pathways' };
1436
- const notPathways = { NOT: isPathways };
1591
+ let filter
1592
+ const isPathways = { 'tile-layer': 'pathways' }
1593
+ const notPathways = { NOT: isPathways }
1437
1594
 
1438
- if (payload.key === "alert" || payload.key === "withoutAlert") {
1439
- const hasAlert = payload.key === "alert" ?
1440
- { HAS: 'alert' } :
1441
- { NOT: { HAS: 'alert' } };
1595
+ if (payload.key === 'alert' || payload.key === 'withoutAlert') {
1596
+ const hasAlert =
1597
+ payload.key === 'alert'
1598
+ ? { HAS: 'alert' }
1599
+ : { NOT: { HAS: 'alert' } }
1442
1600
 
1443
- filter = { OR: [notPathways, { AND: [isPathways, hasAlert] }] };
1601
+ filter = { OR: [notPathways, { AND: [isPathways, hasAlert] }] }
1444
1602
  }
1445
1603
  this.setVisibilityFilter(filter)
1446
1604
  } else {
@@ -1456,13 +1614,13 @@ export default {
1456
1614
  */
1457
1615
  alertSelected: function (payload) {
1458
1616
  if (this.mapImp) {
1459
- if (payload.key === "alert") {
1617
+ if (payload.key === 'alert') {
1460
1618
  if (payload.value) {
1461
1619
  this.mapFilters.alert.with = true
1462
1620
  } else {
1463
1621
  this.mapFilters.alert.with = false
1464
1622
  }
1465
- } else if (payload.key === "withoutAlert") {
1623
+ } else if (payload.key === 'withoutAlert') {
1466
1624
  if (payload.value) {
1467
1625
  this.mapFilters.alert.without = true
1468
1626
  } else {
@@ -1563,7 +1721,7 @@ export default {
1563
1721
  clearTimeout(this.taxonLeaveDelay)
1564
1722
  let gid = this.mapImp.taxonFeatureIds(payload.key)
1565
1723
  this.mapImp.enableConnectivityByTaxonIds(payload.key, payload.value) // make sure path is visible
1566
- this.mapImp.zoomToGeoJSONFeatures(gid, {noZoomIn: true})
1724
+ this.mapImp.zoomToGeoJSONFeatures(gid, { noZoomIn: true })
1567
1725
  } else {
1568
1726
  this.taxonLeaveDelay = setTimeout(() => {
1569
1727
  // reset visibility of paths
@@ -1572,7 +1730,7 @@ export default {
1572
1730
  let show = payload.checked.includes(item.taxon)
1573
1731
  this.mapImp.enableConnectivityByTaxonIds(item.taxon, show)
1574
1732
  })
1575
- }, 1000);
1733
+ }, 1000)
1576
1734
  }
1577
1735
  }
1578
1736
  },
@@ -1634,15 +1792,23 @@ export default {
1634
1792
  else this.featureAnnotationSubmitted = false
1635
1793
  this.annotationEntry = []
1636
1794
  } else if (data.type === 'modeChanged') {
1637
- if (data.feature.mode === 'direct_select') this.doubleClickedFeature = true
1638
- if (this.annotationSidebar && data.feature.mode === 'simple_select' && this.activeDrawMode === 'Deleted') {
1795
+ if (data.feature.mode === 'direct_select')
1796
+ this.doubleClickedFeature = true
1797
+ if (
1798
+ this.annotationSidebar &&
1799
+ data.feature.mode === 'simple_select' &&
1800
+ this.activeDrawMode === 'Deleted'
1801
+ ) {
1639
1802
  this.annotationEventCallback({}, { type: 'aborted' })
1640
1803
  }
1641
1804
  } else if (data.type === 'selectionChanged') {
1642
- this.selectedDrawnFeature = data.feature.features.length === 0 ?
1643
- undefined : data.feature.features[0]
1805
+ this.selectedDrawnFeature =
1806
+ data.feature.features.length === 0
1807
+ ? undefined
1808
+ : data.feature.features[0]
1644
1809
  payload.feature.feature = this.selectedDrawnFeature
1645
- if (!this.activeDrawTool) { // Make sure dialog content doesn't change
1810
+ if (!this.activeDrawTool) {
1811
+ // Make sure dialog content doesn't change
1646
1812
  this.connectionEntry = {}
1647
1813
  // For exist drawn annotation features
1648
1814
  if (this.selectedDrawnFeature) {
@@ -1656,11 +1822,16 @@ export default {
1656
1822
  }
1657
1823
  this.annotationDrawModeEvent(payload)
1658
1824
  } else {
1659
- if (this.annotationSidebar && this.previousEditEvent.type === 'updated') {
1660
- this.annotationEntry = [{
1661
- ...this.previousEditEvent,
1662
- resourceId: this.serverURL
1663
- }]
1825
+ if (
1826
+ this.annotationSidebar &&
1827
+ this.previousEditEvent.type === 'updated'
1828
+ ) {
1829
+ this.annotationEntry = [
1830
+ {
1831
+ ...this.previousEditEvent,
1832
+ resourceId: this.serverURL,
1833
+ },
1834
+ ]
1664
1835
  this.annotationEventCallback({}, { type: 'aborted' })
1665
1836
  }
1666
1837
  this.previousEditEvent = {}
@@ -1671,7 +1842,9 @@ export default {
1671
1842
  if (data.type === 'updated' && data.feature.action) {
1672
1843
  data.positionUpdated = data.feature.action === 'move'
1673
1844
  }
1674
- const feature = this.mapImp.refreshAnnotationFeatureGeometry(data.feature)
1845
+ const feature = this.mapImp.refreshAnnotationFeatureGeometry(
1846
+ data.feature
1847
+ )
1675
1848
  payload.feature.feature = feature
1676
1849
  // NB. this might now be `null` if user has deleted it (before OK/Submit)
1677
1850
  // so maybe then no `service.addAnnotation` ??
@@ -1725,36 +1898,39 @@ export default {
1725
1898
  const biologicalSex = this.biologicalSex
1726
1899
  const featuresAlert = data.alert
1727
1900
  const taxons = this.getTaxons(data)
1728
- let payload = [{
1729
- dataset: data.dataset,
1730
- biologicalSex: biologicalSex,
1731
- taxonomy: taxonomy,
1732
- resource: resource,
1733
- label: label,
1734
- feature: data,
1735
- userData: args,
1736
- eventType: eventType,
1737
- provenanceTaxonomy: taxons,
1738
- alert: featuresAlert
1739
- }]
1901
+ let payload = [
1902
+ {
1903
+ dataset: data.dataset,
1904
+ biologicalSex: biologicalSex,
1905
+ taxonomy: taxonomy,
1906
+ resource: resource,
1907
+ label: label,
1908
+ feature: data,
1909
+ protocol: this.selectedSimulation,
1910
+ userData: args,
1911
+ eventType: eventType,
1912
+ provenanceTaxonomy: taxons,
1913
+ alert: featuresAlert,
1914
+ },
1915
+ ]
1740
1916
  if (eventType === 'click') {
1741
1917
  // If multiple paths overlap at the click location,
1742
1918
  // `data` is an object with numeric keys for each feature (e.g., {0: {...}, 1: {...}, ..., mapUUID: '...'}).
1743
1919
  // If only one feature or path is clicked,
1744
1920
  // `data` is a single object (e.g., {featureId: '...', mapUUID: '...'}).
1745
- const singleSelection = !data[0];
1921
+ const singleSelection = !data[0]
1746
1922
  if (!singleSelection) {
1747
1923
  payload = []
1748
1924
  const mapuuid = data.mapUUID
1749
- const seenIds = new Set();
1925
+ const seenIds = new Set()
1750
1926
  for (let [key, value] of Object.entries(data)) {
1751
1927
  if (key !== 'mapUUID') {
1752
1928
  const id = value.featureId
1753
1929
  const label = value.label
1754
1930
  const resource = [value.models]
1755
1931
  const taxons = this.getTaxons(value)
1756
- if (seenIds.has(id)) continue;
1757
- seenIds.add(id);
1932
+ if (seenIds.has(id)) continue
1933
+ seenIds.add(id)
1758
1934
  payload.push({
1759
1935
  dataset: value.dataset,
1760
1936
  biologicalSex: biologicalSex,
@@ -1766,13 +1942,13 @@ export default {
1766
1942
  eventType: eventType,
1767
1943
  provenanceTaxonomy: taxons,
1768
1944
  alert: value.alert,
1769
- mapUUID: mapuuid
1945
+ mapUUID: mapuuid,
1770
1946
  })
1771
1947
  }
1772
1948
  }
1773
1949
  }
1774
1950
  const clickedItem = singleSelection ? data : data[0]
1775
- this.setConnectivityDataSource(this.viewingMode, clickedItem);
1951
+ this.setConnectivityDataSource(this.viewingMode, clickedItem)
1776
1952
  if (this.viewingMode === 'Neuron Connection') {
1777
1953
  // do nothing here
1778
1954
  // the method to highlight paths is moved to checkAndCreatePopups function
@@ -1781,20 +1957,33 @@ export default {
1781
1957
  // This is for annotation mode - draw connectivity between features/paths
1782
1958
  if (this.activeDrawTool && !this.isValidDrawnCreated) {
1783
1959
  // Check if flatmap features or existing drawn features
1784
- const validDrawnFeature = clickedItem.featureId || this.existDrawnFeatures.find(
1785
- (feature) => feature.id === clickedItem.id
1786
- )
1960
+ const validDrawnFeature =
1961
+ clickedItem.featureId ||
1962
+ this.existDrawnFeatures.find(
1963
+ (feature) => feature.id === clickedItem.id
1964
+ )
1787
1965
  // Only the linestring will have connection
1788
1966
  if (this.activeDrawTool === 'LineString' && validDrawnFeature) {
1789
- const key = clickedItem.featureId ? clickedItem.featureId : clickedItem.id
1790
- const nodeLabel = clickedItem.label ? clickedItem.label : `Feature ${clickedItem.id}`
1967
+ const key = clickedItem.featureId
1968
+ ? clickedItem.featureId
1969
+ : clickedItem.id
1970
+ const nodeLabel = clickedItem.label
1971
+ ? clickedItem.label
1972
+ : `Feature ${clickedItem.id}`
1791
1973
  // Add space before key to make sure properties follows adding order
1792
1974
  this.connectionEntry[` ${key}`] = Object.assign(
1793
1975
  { label: nodeLabel },
1794
1976
  Object.fromEntries(
1795
1977
  Object.entries(clickedItem)
1796
- .filter(([key]) => ['featureId', 'models'].includes(key))
1797
- .map(([key, value]) => [(key === 'featureId') ? 'id' : key, value])))
1978
+ .filter(([key]) =>
1979
+ ['featureId', 'models'].includes(key)
1980
+ )
1981
+ .map(([key, value]) => [
1982
+ key === 'featureId' ? 'id' : key,
1983
+ value,
1984
+ ])
1985
+ )
1986
+ )
1798
1987
  }
1799
1988
  }
1800
1989
  }
@@ -1803,7 +1992,10 @@ export default {
1803
1992
  if (data && data.type !== 'marker' && !this.activeDrawTool) {
1804
1993
  this.checkAndCreatePopups(payload)
1805
1994
  }
1806
- } else if (eventType === 'mouseenter' && this.viewingMode !== 'Neuron Connection') {
1995
+ } else if (
1996
+ eventType === 'mouseenter' &&
1997
+ this.viewingMode !== 'Neuron Connection'
1998
+ ) {
1807
1999
  this.currentHover = data.models ? data.models : ''
1808
2000
  }
1809
2001
 
@@ -1823,11 +2015,13 @@ export default {
1823
2015
  setConnectivityDataSource: function (viewingMode, data) {
1824
2016
  // Exploration mode, only path click will be used as data source
1825
2017
  if (viewingMode === 'Exploration') {
1826
- this.connectivityDataSource = data.models?.startsWith('ilxtr:') ? data.models : '';
2018
+ this.connectivityDataSource = data.models?.startsWith('ilxtr:')
2019
+ ? data.models
2020
+ : ''
1827
2021
  } else {
1828
2022
  // Other modes, it can be anything
1829
2023
  // (annotation drawing doesn't have featureId or models)
1830
- this.connectivityDataSource = data.featureId || data.id;
2024
+ this.connectivityDataSource = data.featureId || data.id
1831
2025
  }
1832
2026
  },
1833
2027
  /**
@@ -1850,12 +2044,12 @@ export default {
1850
2044
  removeActiveTooltips: function () {
1851
2045
  // Remove active tooltip/popup on map
1852
2046
  if (this.mapImp) {
1853
- this.mapImp.removePopup();
2047
+ this.mapImp.removePopup()
1854
2048
  }
1855
2049
 
1856
2050
  // Fallback: remove any existing toolitp on DOM
1857
- const tooltips = this.$el.querySelectorAll('.flatmap-tooltip-popup');
1858
- tooltips.forEach((tooltip) => tooltip.remove());
2051
+ const tooltips = this.$el.querySelectorAll('.flatmap-tooltip-popup')
2052
+ tooltips.forEach((tooltip) => tooltip.remove())
1859
2053
  },
1860
2054
  /**
1861
2055
  * Function to create tooltip for the provided connectivity data.
@@ -1864,28 +2058,24 @@ export default {
1864
2058
  createTooltipForConnectivity: function (connectivityData, geojsonId) {
1865
2059
  // combine all labels to show together
1866
2060
  // content type must be DOM object to use HTML
1867
- const labelsContainer = document.createElement('div');
1868
- labelsContainer.classList.add('flatmap-feature-label');
2061
+ const labelsContainer = document.createElement('div')
2062
+ labelsContainer.classList.add('flatmap-feature-label')
1869
2063
 
1870
2064
  connectivityData.forEach((connectivity, i) => {
1871
- const { label } = connectivity;
1872
- labelsContainer.append(capitalise(label));
2065
+ const { label } = connectivity
2066
+ labelsContainer.append(capitalise(label))
1873
2067
 
1874
- if ((i + 1) < connectivityData.length) {
1875
- const hr = document.createElement('hr');
1876
- labelsContainer.appendChild(hr);
2068
+ if (i + 1 < connectivityData.length) {
2069
+ const hr = document.createElement('hr')
2070
+ labelsContainer.appendChild(hr)
1877
2071
  }
1878
- });
2072
+ })
1879
2073
 
1880
- this.mapImp.showPopup(
1881
- geojsonId,
1882
- labelsContainer,
1883
- {
1884
- className: 'custom-popup flatmap-tooltip-popup',
1885
- positionAtLastClick: false,
1886
- preserveSelection: true,
1887
- }
1888
- );
2074
+ this.mapImp.showPopup(geojsonId, labelsContainer, {
2075
+ className: 'custom-popup flatmap-tooltip-popup',
2076
+ positionAtLastClick: false,
2077
+ preserveSelection: true,
2078
+ })
1889
2079
  },
1890
2080
  /**
1891
2081
  * Function to show connectivity tooltips on the map
@@ -1893,53 +2083,53 @@ export default {
1893
2083
  * @arg {Object} `payload`
1894
2084
  */
1895
2085
  showConnectivityTooltips: function (payload) {
1896
- const { connectivityInfo, data } = payload;
1897
- const featuresToHighlight = [];
1898
- const geojsonHighlights = [];
1899
- const connectivityData = [];
1900
- const errorData = [];
2086
+ const { connectivityInfo, data } = payload
2087
+ const featuresToHighlight = []
2088
+ const geojsonHighlights = []
2089
+ const connectivityData = []
2090
+ const errorData = []
1901
2091
 
1902
2092
  // to keep the highlighted path on map
1903
2093
  if (connectivityInfo && connectivityInfo.featureId) {
1904
- featuresToHighlight.push(...connectivityInfo.featureId);
2094
+ featuresToHighlight.push(...connectivityInfo.featureId)
1905
2095
  }
1906
2096
 
1907
2097
  if (this.mapImp) {
1908
2098
  // search the features on the map first
1909
2099
  data.forEach((connectivity) => {
1910
- const response = this.mapImp.search(connectivity.id);
2100
+ const response = this.mapImp.search(connectivity.id)
1911
2101
 
1912
2102
  if (response?.results.length) {
1913
- const featureId = response?.results[0].featureId;
1914
- connectivityData.push({ featureId, ...connectivity });
2103
+ const featureId = response?.results[0].featureId
2104
+ connectivityData.push({ featureId, ...connectivity })
1915
2105
  } else {
1916
- errorData.push(connectivity);
2106
+ errorData.push(connectivity)
1917
2107
  }
1918
- });
2108
+ })
1919
2109
 
1920
2110
  if (connectivityData.length) {
1921
- let geojsonId = connectivityData[0].featureId;
2111
+ let geojsonId = connectivityData[0].featureId
1922
2112
 
1923
2113
  this.mapImp.annotations.forEach((annotation) => {
1924
- const anatomicalNodes = annotation['anatomical-nodes'];
2114
+ const anatomicalNodes = annotation['anatomical-nodes']
1925
2115
 
1926
2116
  if (anatomicalNodes) {
1927
- const anatomicalNodesString = anatomicalNodes.join('');
1928
- const foundItem = connectivityData.every((item) =>
1929
- anatomicalNodesString.indexOf(item.id) !== -1
1930
- );
2117
+ const anatomicalNodesString = anatomicalNodes.join('')
2118
+ const foundItem = connectivityData.every(
2119
+ (item) => anatomicalNodesString.indexOf(item.id) !== -1
2120
+ )
1931
2121
 
1932
2122
  if (foundItem) {
1933
- geojsonId = annotation.featureId;
1934
- geojsonHighlights.push(geojsonId);
2123
+ geojsonId = annotation.featureId
2124
+ geojsonHighlights.push(geojsonId)
1935
2125
  }
1936
2126
  }
1937
- });
2127
+ })
1938
2128
 
1939
- this.createTooltipForConnectivity(connectivityData, geojsonId);
2129
+ this.createTooltipForConnectivity(connectivityData, geojsonId)
1940
2130
  } else {
1941
2131
  // Close all tooltips on the current flatmap element
1942
- this.removeActiveTooltips();
2132
+ this.removeActiveTooltips()
1943
2133
  }
1944
2134
 
1945
2135
  // Emit error message for connectivity
@@ -1949,75 +2139,86 @@ export default {
1949
2139
 
1950
2140
  // highlight all available features
1951
2141
  const connectivityFeatures = featuresToHighlight.reduce((arr, path) => {
1952
- const connectivityObj = this.mapImp.pathways.paths[path];
1953
- const connectivities = connectivityObj ? connectivityObj.connectivity : null;
2142
+ const connectivityObj = this.mapImp.pathways.paths[path]
2143
+ const connectivities = connectivityObj
2144
+ ? connectivityObj.connectivity
2145
+ : null
1954
2146
  if (connectivities) {
1955
- const flatFeatures = connectivities.flat(Infinity);
1956
- arr.push(...flatFeatures);
2147
+ const flatFeatures = connectivities.flat(Infinity)
2148
+ arr.push(...flatFeatures)
1957
2149
  }
1958
- return arr;
1959
- }, []);
1960
- const uniqueConnectivityFeatures = [...new Set(connectivityFeatures)];
1961
- const combinedFeatures = [...featuresToHighlight, ...uniqueConnectivityFeatures];
1962
- const featureIdsToHighlight = this.mapImp.modelFeatureIdList(combinedFeatures);
2150
+ return arr
2151
+ }, [])
2152
+ const uniqueConnectivityFeatures = [...new Set(connectivityFeatures)]
2153
+ const combinedFeatures = [
2154
+ ...featuresToHighlight,
2155
+ ...uniqueConnectivityFeatures,
2156
+ ]
2157
+ const featureIdsToHighlight =
2158
+ this.mapImp.modelFeatureIdList(combinedFeatures)
1963
2159
  const allFeaturesToHighlight = [
1964
2160
  ...featureIdsToHighlight,
1965
- ...geojsonHighlights
1966
- ];
2161
+ ...geojsonHighlights,
2162
+ ]
1967
2163
 
1968
- this.mapImp.selectGeoJSONFeatures(allFeaturesToHighlight);
2164
+ this.mapImp.selectGeoJSONFeatures(allFeaturesToHighlight)
1969
2165
  }
1970
2166
  },
1971
2167
  showConnectivitiesByReference: function (resource) {
1972
2168
  this.searchConnectivitiesByReference(resource).then((featureIds) => {
1973
- this.mapImp.selectFeatures(featureIds);
1974
- });
2169
+ this.mapImp.selectFeatures(featureIds)
2170
+ })
1975
2171
  },
1976
2172
  searchConnectivitiesByReference: async function (resource) {
1977
- const flatmapKnowledge = sessionStorage.getItem('flatmap-knowledge');
1978
- let featureIds = [];
2173
+ const flatmapKnowledge = sessionStorage.getItem('flatmap-knowledge')
2174
+ let featureIds = []
1979
2175
 
1980
2176
  if (flatmapKnowledge) {
1981
- featureIds = await getReferenceConnectivitiesFromStorage(resource);
2177
+ featureIds = await getReferenceConnectivitiesFromStorage(resource)
1982
2178
  } else {
1983
- featureIds = await getReferenceConnectivitiesByAPI(this.mapImp, resource, this.flatmapQueries);
1984
- }
1985
- return featureIds;
1986
- },
1987
- getFlatmapKnowledge: function () {
1988
- let flatmapKnowledge = [];
1989
- const flatmapKnowledgeRaw = sessionStorage.getItem('flatmap-knowledge');
1990
- if (flatmapKnowledgeRaw) {
1991
- flatmapKnowledge = JSON.parse(flatmapKnowledgeRaw);
2179
+ featureIds = await getReferenceConnectivitiesByAPI(
2180
+ this.mapImp,
2181
+ resource,
2182
+ this.flatmapQueries
2183
+ )
1992
2184
  }
1993
- return flatmapKnowledge;
2185
+ return featureIds
1994
2186
  },
1995
2187
  emitConnectivityError: function (errorData) {
1996
2188
  this.$emit('connectivity-error', {
1997
2189
  data: {
1998
2190
  errorData: errorData,
1999
2191
  errorMessage: ERROR_MESSAGE,
2000
- }
2001
- });
2192
+ },
2193
+ })
2002
2194
  },
2003
- checkConnectivityTooltipEntry: function(tooltipEntry) {
2195
+ checkConnectivityTooltipEntry: function (tooltipEntry) {
2004
2196
  if (tooltipEntry?.length) {
2005
- return undefined !== (tooltipEntry.find(entry => entry?.destinations?.length || entry?.components?.length))
2197
+ return (
2198
+ undefined !==
2199
+ tooltipEntry.find(
2200
+ (entry) => entry?.destinations?.length || entry?.components?.length
2201
+ )
2202
+ )
2006
2203
  }
2007
2204
  return false
2008
2205
  },
2009
2206
  changeConnectivitySource: async function (payload) {
2010
- const { entry, connectivitySource } = payload;
2207
+ const { entry, connectivitySource } = payload
2011
2208
  if (entry.mapId === this.mapImp.id) {
2012
- await this.flatmapQueries.queryForConnectivityNew(this.mapImp, entry.featureId[0], connectivitySource);
2209
+ await this.flatmapQueries.queryForConnectivityNew(
2210
+ this.mapImp,
2211
+ entry.featureId[0],
2212
+ connectivitySource
2213
+ )
2013
2214
  this.tooltipEntry = this.tooltipEntry.map((tooltip) => {
2014
2215
  if (tooltip.featureId[0] === entry.featureId[0]) {
2015
- return this.flatmapQueries.updateTooltipData(tooltip);
2216
+ return this.flatmapQueries.updateTooltipData(tooltip)
2016
2217
  }
2017
- return tooltip;
2218
+ return tooltip
2018
2219
  })
2019
2220
  if (this.checkConnectivityTooltipEntry(this.tooltipEntry)) {
2020
- this.$emit('connectivity-info-open', this.tooltipEntry);
2221
+ this.$emit('connectivity-info-open', this.tooltipEntry)
2021
2222
  }
2022
2223
  }
2023
2224
  },
@@ -2030,28 +2231,39 @@ export default {
2030
2231
  checkAndCreatePopups: async function (data, mapclick = true) {
2031
2232
  // Call flatmap database to get the connection data
2032
2233
  if (this.viewingMode === 'Annotation') {
2033
- const features = data.filter(d => d.feature).map(d => d.feature)
2234
+ const features = data.filter((d) => d.feature).map((d) => d.feature)
2034
2235
  if (features.length > 0) {
2035
- if (this.annotationSidebar && this.previousDeletedEvent.type === 'deleted') {
2036
- this.annotationEntry = [{
2037
- ...this.previousDeletedEvent,
2038
- resourceId: this.serverURL
2039
- }]
2236
+ if (
2237
+ this.annotationSidebar &&
2238
+ this.previousDeletedEvent.type === 'deleted'
2239
+ ) {
2240
+ this.annotationEntry = [
2241
+ {
2242
+ ...this.previousDeletedEvent,
2243
+ resourceId: this.serverURL,
2244
+ },
2245
+ ]
2040
2246
  this.annotationEventCallback({}, { type: 'aborted' })
2041
2247
  }
2042
2248
  this.annotationEntry = []
2043
- features.forEach(feature => {
2249
+ features.forEach((feature) => {
2044
2250
  this.annotationEntry.push({
2045
2251
  ...feature,
2046
2252
  resourceId: this.serverURL,
2047
- featureId: feature.featureId ? feature.featureId : feature.feature?.id,
2048
- offline: this.offlineAnnotationEnabled
2253
+ featureId: feature.featureId
2254
+ ? feature.featureId
2255
+ : feature.feature?.id,
2256
+ offline: this.offlineAnnotationEnabled,
2049
2257
  })
2050
- });
2258
+ })
2051
2259
  // Drawn feature annotationEntry will always have length of 1
2052
2260
  if (features[0].feature) {
2053
2261
  // in drawing or edit/delete mode is on or valid drawn
2054
- if (this.activeDrawTool || this.activeDrawMode || this.isValidDrawnCreated) {
2262
+ if (
2263
+ this.activeDrawTool ||
2264
+ this.activeDrawMode ||
2265
+ this.isValidDrawnCreated
2266
+ ) {
2055
2267
  this.featureAnnotationSubmitted = false
2056
2268
  if (this.activeDrawTool) {
2057
2269
  this.createConnectivityBody()
@@ -2065,8 +2277,8 @@ export default {
2065
2277
  }
2066
2278
  } else {
2067
2279
  const featureIds = this.annotationEntry
2068
- .filter(annotation => annotation.featureId && annotation.models)
2069
- .map(annotation => annotation.models)
2280
+ .filter((annotation) => annotation.featureId && annotation.models)
2281
+ .map((annotation) => annotation.models)
2070
2282
  if (featureIds.length > 0) {
2071
2283
  this.displayTooltip(featureIds)
2072
2284
  }
@@ -2078,115 +2290,131 @@ export default {
2078
2290
  // clicking on a connectivity explorer card will be the same as exploration mode
2079
2291
  // the card should be opened without doing other functions
2080
2292
  else if (this.viewingMode === 'Neuron Connection' && mapclick) {
2081
- const resources = data.map(tooltip => tooltip.resource[0]);
2293
+ const resources = data.map((tooltip) => tooltip.resource[0])
2082
2294
 
2083
2295
  // filter out paths
2084
- const featureId = resources.find(resource => !resource.startsWith('ilxtr:'));
2296
+ const featureId = resources.find(
2297
+ (resource) => !resource.startsWith('ilxtr:')
2298
+ )
2085
2299
  if (featureId) {
2086
2300
  // fallback if it cannot find in anatomical nodes
2087
- const transformResources = Array.isArray(resources) ? [...resources] : [resources];
2301
+ const transformResources = Array.isArray(resources)
2302
+ ? [...resources]
2303
+ : [resources]
2088
2304
  if (transformResources.length === 1) {
2089
- transformResources.push([]);
2305
+ transformResources.push([])
2090
2306
  }
2091
2307
 
2092
- const featureId = data[0].feature?.featureId;
2093
- const annotation = this.mapImp.annotations.get(featureId);
2094
- const anatomicalNodes = annotation?.['anatomical-nodes'];
2095
- const annotationModels = annotation?.['models'];
2096
- let anatomicalNode;
2097
- let uniqueResource = transformResources;
2098
- const models = annotation?.['models'];
2308
+ const featureId = data[0].feature?.featureId
2309
+ const annotation = this.mapImp.annotations.get(featureId)
2310
+ const anatomicalNodes = annotation?.['anatomical-nodes']
2311
+ const annotationModels = annotation?.['models']
2312
+ let anatomicalNode
2313
+ let uniqueResource = transformResources
2314
+ const models = annotation?.['models']
2099
2315
  if (anatomicalNodes?.length) {
2100
2316
  // get the node which match the feature in a location
2101
2317
  // [feature, location]
2102
- anatomicalNode = anatomicalNodes.find((node) =>
2103
- JSON.parse(node)[0] === annotationModels
2104
- );
2318
+ anatomicalNode = anatomicalNodes.find(
2319
+ (node) => JSON.parse(node)[0] === annotationModels
2320
+ )
2105
2321
  }
2106
2322
  if (anatomicalNode) {
2107
- uniqueResource = JSON.parse(anatomicalNode);
2323
+ uniqueResource = JSON.parse(anatomicalNode)
2108
2324
  } else if (models) {
2109
- uniqueResource = [models, []];
2325
+ uniqueResource = [models, []]
2110
2326
  }
2111
2327
 
2112
- const knowledgeSource = this.mapImp.knowledgeSource;
2113
- const terms = uniqueResource.flat(Infinity);
2114
- const uniqueTerms = [...new Set(terms)];
2115
- const fetchResults = await fetchLabels(this.flatmapAPI, uniqueTerms);
2328
+ const knowledgeSource = this.mapImp.knowledgeSource
2329
+ const terms = uniqueResource.flat(Infinity)
2330
+ const uniqueTerms = [...new Set(terms)]
2331
+ const fetchResults = await fetchLabels(this.flatmapAPI, uniqueTerms)
2116
2332
  const objectResults = fetchResults.reduce((arr, item) => {
2117
- const id = item[0];
2118
- const valObj = JSON.parse(item[1]);
2119
- arr.push({ id, label: valObj.label, source: valObj.source });
2120
- return arr;
2121
- }, []);
2333
+ const id = item[0]
2334
+ const valObj = JSON.parse(item[1])
2335
+ arr.push({ id, label: valObj.label, source: valObj.source })
2336
+ return arr
2337
+ }, [])
2122
2338
 
2123
2339
  // sort matched knowledgeSource items for same id
2124
2340
  objectResults.sort((a, b) => {
2125
2341
  if (a.id === b.id) {
2126
- if (a.source === knowledgeSource && b.source !== knowledgeSource) return -1;
2127
- if (a.source !== knowledgeSource && b.source === knowledgeSource) return 1;
2128
- return 0;
2342
+ if (a.source === knowledgeSource && b.source !== knowledgeSource)
2343
+ return -1
2344
+ if (a.source !== knowledgeSource && b.source === knowledgeSource)
2345
+ return 1
2346
+ return 0
2129
2347
  }
2130
- return a.id.localeCompare(b.id);
2131
- });
2348
+ return a.id.localeCompare(b.id)
2349
+ })
2132
2350
 
2133
- const labels = [];
2351
+ const labels = []
2134
2352
  for (let i = 0; i < uniqueTerms.length; i++) {
2135
- const foundObj = objectResults.find((obj) => obj.id === uniqueTerms[i])
2353
+ const foundObj = objectResults.find(
2354
+ (obj) => obj.id === uniqueTerms[i]
2355
+ )
2136
2356
  if (foundObj) {
2137
- labels.push(foundObj.label);
2357
+ labels.push(foundObj.label)
2138
2358
  }
2139
2359
  }
2140
- const filterItemLabel = capitalise(labels.join(', '));
2360
+ const filterItemLabel = capitalise(labels.join(', '))
2141
2361
  const newConnectivityfilter = {
2142
2362
  facet: JSON.stringify(uniqueResource),
2143
2363
  facetPropPath: `flatmap.connectivity.source.${this.connectionType.toLowerCase()}`,
2144
2364
  tagLabel: filterItemLabel, // used tagLabel here instead of label since the label and value are different
2145
- term: this.connectionType
2146
- };
2365
+ term: this.connectionType,
2366
+ }
2147
2367
  // check for existing item
2148
- const isNewFilterItemExist = this.connectivityFilters.some((connectivityfilter) => (
2149
- connectivityfilter.facet === newConnectivityfilter.facet &&
2150
- connectivityfilter.facetPropPath === newConnectivityfilter.facetPropPath
2151
- ));
2368
+ const isNewFilterItemExist = this.connectivityFilters.some(
2369
+ (connectivityfilter) =>
2370
+ connectivityfilter.facet === newConnectivityfilter.facet &&
2371
+ connectivityfilter.facetPropPath ===
2372
+ newConnectivityfilter.facetPropPath
2373
+ )
2152
2374
 
2153
2375
  if (!isNewFilterItemExist) {
2154
- this.connectivityFilters.push(newConnectivityfilter);
2376
+ this.connectivityFilters.push(newConnectivityfilter)
2155
2377
  }
2156
2378
 
2157
2379
  this.$emit('neuron-connection-feature-click', {
2158
2380
  filters: this.connectivityFilters,
2159
2381
  search: '',
2160
- });
2382
+ })
2161
2383
  } else {
2162
2384
  // clicking on paths
2163
2385
  await this.openConnectivityInfo(data);
2164
2386
  }
2165
2387
  } else {
2166
- await this.openConnectivityInfo(data);
2388
+ await this.openConnectivityInfo(data)
2167
2389
  }
2168
2390
  },
2169
2391
  openConnectivityInfo: async function (data) {
2170
2392
  // load and store knowledge
2171
- loadAndStoreKnowledge(this.mapImp, this.flatmapQueries);
2393
+ loadAndStoreKnowledge(this.mapImp, this.flatmapQueries)
2172
2394
  let prom1 = []
2173
2395
  // Emit placeholders first.
2174
2396
  // This may contain invalid connectivity.
2175
2397
  this.tooltipEntry = data
2176
- .filter(tooltip => tooltip.resource[0] in this.mapImp.pathways.paths)
2398
+ .filter((tooltip) => tooltip.resource[0] in this.mapImp.pathways.paths)
2177
2399
  .map((tooltip) => {
2178
- return { title: tooltip.label, featureId: tooltip.resource, ready: false }
2400
+ return {
2401
+ title: tooltip.label,
2402
+ featureId: tooltip.resource,
2403
+ ready: false,
2404
+ }
2179
2405
  })
2180
2406
  // this should only for flatmap paths not all features
2181
2407
  if (this.tooltipEntry.length) {
2182
- this.$emit('connectivity-info-open', this.tooltipEntry);
2408
+ this.$emit('connectivity-info-open', this.tooltipEntry)
2183
2409
 
2184
2410
  // While having placeholders displayed, get details for all paths and then replace.
2185
2411
  for (let index = 0; index < data.length; index++) {
2186
2412
  prom1.push(await this.getKnowledgeTooltip(data[index]))
2187
2413
  }
2188
2414
  this.tooltipEntry = await Promise.all(prom1)
2189
- const featureIds = this.tooltipEntry.map(tooltip => tooltip.featureId[0])
2415
+ const featureIds = this.tooltipEntry.map(
2416
+ (tooltip) => tooltip.featureId[0]
2417
+ )
2190
2418
  if (featureIds.length > 0) {
2191
2419
  this.displayTooltip(featureIds)
2192
2420
  }
@@ -2198,79 +2426,93 @@ export default {
2198
2426
  * @param {Array} payload - The array of filter items to update.
2199
2427
  */
2200
2428
  updateConnectivityFilters: function (payload) {
2201
- if (!payload.length) return;
2202
- this.connectivityFilters = payload.filter((filterItem) => (
2203
- filterItem.facet.toLowerCase() !== 'show all'
2204
- ));
2429
+ if (!payload.length) return
2430
+ this.connectivityFilters = payload.filter(
2431
+ (filterItem) => filterItem.facet.toLowerCase() !== 'show all'
2432
+ )
2205
2433
  },
2206
2434
  resetConnectivityfilters: function (payload) {
2207
2435
  if (payload.length) {
2208
2436
  // remove not found items
2209
- this.connectivityFilters = this.connectivityFilters.filter((connectivityfilter) =>
2210
- payload.some((notFoundItem) => (
2211
- notFoundItem.facetPropPath === connectivityfilter.facetPropPath &&
2212
- notFoundItem.facet !== connectivityfilter.facet
2213
- ))
2437
+ this.connectivityFilters = this.connectivityFilters.filter(
2438
+ (connectivityfilter) =>
2439
+ payload.some(
2440
+ (notFoundItem) =>
2441
+ notFoundItem.facetPropPath ===
2442
+ connectivityfilter.facetPropPath &&
2443
+ notFoundItem.facet !== connectivityfilter.facet
2444
+ )
2214
2445
  )
2215
2446
  } else {
2216
2447
  // full reset
2217
- this.connectivityFilters = [];
2448
+ this.connectivityFilters = []
2218
2449
  }
2219
2450
  },
2220
2451
  getKnowledgeTooltip: async function (data) {
2221
2452
  //require data.resource && data.feature.source
2222
- const results = await this.flatmapQueries.retrieveFlatmapKnowledgeForEvent(this.mapImp, data)
2223
- let tooltip = await this.flatmapQueries.createTooltipData(this.mapImp, data)
2453
+ const results =
2454
+ await this.flatmapQueries.retrieveFlatmapKnowledgeForEvent(
2455
+ this.mapImp,
2456
+ data
2457
+ )
2458
+ let tooltip = await this.flatmapQueries.createTooltipData(
2459
+ this.mapImp,
2460
+ data
2461
+ )
2462
+
2224
2463
  // The line below only creates the tooltip if some data was found on the path
2225
2464
  // the pubmed URLs are in knowledge response.references
2226
- if ((results && results[0]) || (data.feature.hyperlinks && data.feature.hyperlinks.length > 0)) {
2227
- tooltip['featuresAlert'] = data.alert;
2228
- tooltip['knowledgeSource'] = getKnowledgeSource(this.mapImp);
2465
+ if (
2466
+ (results && results[0]) ||
2467
+ (data.feature.hyperlinks && data.feature.hyperlinks.length > 0)
2468
+ ) {
2469
+ tooltip['featuresAlert'] = data.alert
2470
+ tooltip['knowledgeSource'] = getKnowledgeSource(this.mapImp)
2229
2471
  // Map id and uuid to load connectivity information from the map
2230
- tooltip['mapId'] = this.mapImp.mapMetadata.id;
2231
- tooltip['mapuuid'] = this.mapImp.mapMetadata.uuid;
2232
- // } else {
2233
- // tooltip = {
2234
- // ...tooltip,
2235
- // origins: [data.label],
2236
- // originsWithDatasets: [{ id: data.resource[0], name: data.label }],
2237
- // components: [],
2238
- // componentsWithDatasets: [],
2239
- // destinations: [],
2240
- // destinationsWithDatasets: [],
2241
- // }
2242
- // let featureIds = []
2243
- // const pathsOfEntities = await this.mapImp.queryPathsForFeatures(data.resource)
2244
- // if (pathsOfEntities.length) {
2245
- // pathsOfEntities.forEach((path) => {
2246
- // featureIds.push(...this.mapImp.pathModelNodes(path))
2247
- // const searchResults = this.mapImp.search(path)
2248
- // let featureId = undefined;
2249
- // for (let i = 0; i < searchResults.results.length; i++) {
2250
- // featureId = searchResults.results[i].featureId
2251
- // const annotation = this.mapImp.annotation(featureId)
2252
- // if (featureId && annotation?.label) break;
2253
- // }
2254
- // if (featureId) {
2255
- // const feature = this.mapImp.featureProperties(featureId)
2256
- // if (feature.label && !tooltip.components.includes(feature.label)) {
2257
- // tooltip.components.push(feature.label)
2258
- // tooltip.componentsWithDatasets.push({ id: feature.models, name: feature.label })
2259
- // }
2260
- // }
2261
- // })
2262
- // featureIds = [...new Set(featureIds)].filter(id => id !== data.feature.featureId)
2263
- // featureIds.forEach((id) => {
2264
- // const feature = this.mapImp.featureProperties(id)
2265
- // if (feature.label && !tooltip.destinations.includes(feature.label)) {
2266
- // tooltip.destinations.push(feature.label)
2267
- // tooltip.destinationsWithDatasets.push({ id: feature.models, name: feature.label })
2268
- // }
2269
- // })
2270
- // }
2271
- }
2272
- tooltip['ready'] = true;
2273
- return tooltip;
2472
+ tooltip['mapId'] = this.mapImp.mapMetadata.id
2473
+ tooltip['mapuuid'] = this.mapImp.mapMetadata.uuid
2474
+ // } else {
2475
+ // tooltip = {
2476
+ // ...tooltip,
2477
+ // origins: [data.label],
2478
+ // originsWithDatasets: [{ id: data.resource[0], name: data.label }],
2479
+ // components: [],
2480
+ // componentsWithDatasets: [],
2481
+ // destinations: [],
2482
+ // destinationsWithDatasets: [],
2483
+ // }
2484
+ // let featureIds = []
2485
+ // const pathsOfEntities = await this.mapImp.queryPathsForFeatures(data.resource)
2486
+ // if (pathsOfEntities.length) {
2487
+ // pathsOfEntities.forEach((path) => {
2488
+ // featureIds.push(...this.mapImp.pathModelNodes(path))
2489
+ // const searchResults = this.mapImp.search(path)
2490
+ // let featureId = undefined;
2491
+ // for (let i = 0; i < searchResults.results.length; i++) {
2492
+ // featureId = searchResults.results[i].featureId
2493
+ // const annotation = this.mapImp.annotation(featureId)
2494
+ // if (featureId && annotation?.label) break;
2495
+ // }
2496
+ // if (featureId) {
2497
+ // const feature = this.mapImp.featureProperties(featureId)
2498
+ // if (feature.label && !tooltip.components.includes(feature.label)) {
2499
+ // tooltip.components.push(feature.label)
2500
+ // tooltip.componentsWithDatasets.push({ id: feature.models, name: feature.label })
2501
+ // }
2502
+ // }
2503
+ // })
2504
+ // featureIds = [...new Set(featureIds)].filter(id => id !== data.feature.featureId)
2505
+ // featureIds.forEach((id) => {
2506
+ // const feature = this.mapImp.featureProperties(id)
2507
+ // if (feature.label && !tooltip.destinations.includes(feature.label)) {
2508
+ // tooltip.destinations.push(feature.label)
2509
+ // tooltip.destinationsWithDatasets.push({ id: feature.models, name: feature.label })
2510
+ // }
2511
+ // })
2512
+ // }
2513
+ }
2514
+ tooltip['ready'] = true
2515
+ return tooltip
2274
2516
  },
2275
2517
  /**
2276
2518
  * A hack to remove flatmap tooltips while popup is open
@@ -2278,7 +2520,9 @@ export default {
2278
2520
  popUpCssHacks: function () {
2279
2521
  // Below is a hack to remove flatmap tooltips while popup is open
2280
2522
  const ftooltip = document.querySelector('.flatmap-tooltip-popup')
2281
- const popupCloseButton = document.querySelector('.maplibregl-popup-close-button')
2523
+ const popupCloseButton = document.querySelector(
2524
+ '.maplibregl-popup-close-button'
2525
+ )
2282
2526
  if (ftooltip) ftooltip.style.display = 'none'
2283
2527
  popupCloseButton.style.display = 'block'
2284
2528
  this.$refs.tooltip.$el.style.display = 'flex'
@@ -2287,7 +2531,7 @@ export default {
2287
2531
  * This event is emitted
2288
2532
  * when a connectivity info (provenance popup) is closed.
2289
2533
  */
2290
- this.$emit('connectivity-info-close');
2534
+ this.$emit('connectivity-info-close')
2291
2535
  if (ftooltip) ftooltip.style.display = 'block'
2292
2536
  }
2293
2537
  },
@@ -2360,10 +2604,13 @@ export default {
2360
2604
  '.maplibregl-ctrl-minimap'
2361
2605
  )
2362
2606
  if (minimapEl) {
2363
- if (this.$refs.minimapResize &&
2364
- this.$refs.minimapResize.$el.parentNode) {
2607
+ if (
2608
+ this.$refs.minimapResize &&
2609
+ this.$refs.minimapResize.$el.parentNode
2610
+ ) {
2365
2611
  this.$refs.minimapResize.$el.parentNode.removeChild(
2366
- this.$refs.minimapResize.$el)
2612
+ this.$refs.minimapResize.$el
2613
+ )
2367
2614
  }
2368
2615
  minimapEl.appendChild(this.$refs.minimapResize.$el)
2369
2616
  this.minimapResizeShow = true
@@ -2376,52 +2623,58 @@ export default {
2376
2623
  * @arg {Boolean} `helpMode`
2377
2624
  */
2378
2625
  setHelpMode: function (helpMode) {
2379
- const toolTipsLength = this.hoverVisibilities.length;
2380
- const lastIndex = toolTipsLength - 1;
2381
- const activePopoverObj = this.hoverVisibilities[this.helpModeActiveIndex];
2626
+ const toolTipsLength = this.hoverVisibilities.length
2627
+ const lastIndex = toolTipsLength - 1
2628
+ const activePopoverObj = this.hoverVisibilities[this.helpModeActiveIndex]
2382
2629
 
2383
2630
  if (activePopoverObj) {
2384
- const popoverRefsId = activePopoverObj?.refs;
2385
- const popoverRefId = activePopoverObj?.ref;
2386
- const popoverRef = this.$refs[popoverRefsId ? popoverRefsId : popoverRefId];
2631
+ const popoverRefsId = activePopoverObj?.refs
2632
+ const popoverRefId = activePopoverObj?.ref
2633
+ const popoverRef =
2634
+ this.$refs[popoverRefsId ? popoverRefsId : popoverRefId]
2387
2635
 
2388
2636
  if (popoverRef) {
2389
2637
  // Open pathway drawer if the tooltip is inside or beside
2390
- const { parentElement, nextElementSibling } = popoverRef.$el;
2638
+ const { parentElement, nextElementSibling } = popoverRef.$el
2391
2639
  const isPathwayContainer = (element) => {
2392
- return element && (
2393
- element.classList.contains('pathway-container') ||
2394
- element.classList.contains('pathway-location')
2395
- );
2396
- };
2640
+ return (
2641
+ element &&
2642
+ (element.classList.contains('pathway-container') ||
2643
+ element.classList.contains('pathway-location'))
2644
+ )
2645
+ }
2397
2646
 
2398
2647
  if (
2399
2648
  isPathwayContainer(parentElement) ||
2400
2649
  isPathwayContainer(nextElementSibling)
2401
2650
  ) {
2402
2651
  if (this.requiresDrawer) {
2403
- this.drawerOpen = true;
2652
+ this.drawerOpen = true
2404
2653
  } else {
2405
- this.helpModeActiveIndex += 1;
2654
+ this.helpModeActiveIndex += 1
2406
2655
  }
2407
2656
  }
2408
2657
  } else {
2409
2658
  // skip the unavailable tooltips
2410
- this.helpModeActiveIndex += 1;
2411
- this.setHelpMode(helpMode);
2659
+ this.helpModeActiveIndex += 1
2660
+ this.setHelpMode(helpMode)
2412
2661
  }
2413
2662
  }
2414
2663
 
2415
2664
  // Skip checkbox tooltip if pathway filter is not shown
2416
- const activePopoverObjAfter = this.hoverVisibilities[this.helpModeActiveIndex];
2417
- if (activePopoverObjAfter?.ref === 'checkBoxPopover' && !this.showPathwayFilter) {
2418
- this.helpModeActiveIndex += 1;
2419
- this.setHelpMode(helpMode);
2665
+ const activePopoverObjAfter =
2666
+ this.hoverVisibilities[this.helpModeActiveIndex]
2667
+ if (
2668
+ activePopoverObjAfter?.ref === 'checkBoxPopover' &&
2669
+ !this.showPathwayFilter
2670
+ ) {
2671
+ this.helpModeActiveIndex += 1
2672
+ this.setHelpMode(helpMode)
2420
2673
  }
2421
2674
 
2422
2675
  if (!helpMode) {
2423
2676
  // reset to iniital state
2424
- this.helpModeActiveIndex = this.helpModeInitialIndex;
2677
+ this.helpModeActiveIndex = this.helpModeInitialIndex
2425
2678
  }
2426
2679
 
2427
2680
  if (this.viewingMode !== 'Annotation' && this.helpModeActiveIndex > 9) {
@@ -2432,31 +2685,34 @@ export default {
2432
2685
  /**
2433
2686
  * This event is emitted when the tooltips in help mode reach the last item.
2434
2687
  */
2435
- this.$emit('help-mode-last-item', true);
2688
+ this.$emit('help-mode-last-item', true)
2436
2689
  }
2437
2690
 
2438
2691
  if (helpMode && !this.helpModeDialog) {
2439
- this.inHelp = true;
2692
+ this.inHelp = true
2440
2693
  this.hoverVisibilities.forEach((item) => {
2441
- item.value = true;
2442
- });
2443
- } else if (helpMode && this.helpModeDialog && toolTipsLength > this.helpModeActiveIndex) {
2444
-
2694
+ item.value = true
2695
+ })
2696
+ } else if (
2697
+ helpMode &&
2698
+ this.helpModeDialog &&
2699
+ toolTipsLength > this.helpModeActiveIndex
2700
+ ) {
2445
2701
  // Show the map tooltip as first item
2446
2702
  if (this.helpModeActiveIndex > -1) {
2447
- this.closeFlatmapHelpPopup();
2703
+ this.closeFlatmapHelpPopup()
2448
2704
 
2449
2705
  // wait for CSS transition
2450
2706
  setTimeout(() => {
2451
- this.inHelp = false;
2707
+ this.inHelp = false
2452
2708
  this.hoverVisibilities.forEach((item) => {
2453
- item.value = false;
2454
- });
2709
+ item.value = false
2710
+ })
2455
2711
 
2456
- this.showTooltip(this.helpModeActiveIndex, 200);
2457
- }, 300);
2712
+ this.showTooltip(this.helpModeActiveIndex, 200)
2713
+ }, 300)
2458
2714
  } else if (this.helpModeActiveIndex === -1) {
2459
- this.openFlatmapHelpPopup();
2715
+ this.openFlatmapHelpPopup()
2460
2716
  }
2461
2717
  } else {
2462
2718
  this.inHelp = false
@@ -2481,7 +2737,7 @@ export default {
2481
2737
  /**
2482
2738
  * This event is emitted after a tooltip in Flatmap is shown.
2483
2739
  */
2484
- this.$emit('shown-tooltip');
2740
+ this.$emit('shown-tooltip')
2485
2741
  }, timeout)
2486
2742
  }
2487
2743
  },
@@ -2510,6 +2766,7 @@ export default {
2510
2766
  */
2511
2767
  displayTooltip: function (feature, geometry = undefined) {
2512
2768
  let featureId = undefined
2769
+ console.log('Displaying tooltip for feature:', feature)
2513
2770
  let options = { className: 'flatmapvuer-popover' }
2514
2771
  if (geometry) {
2515
2772
  featureId = feature
@@ -2517,7 +2774,7 @@ export default {
2517
2774
  if (this.annotationEntry.length) {
2518
2775
  options['annotationEvent'] = {
2519
2776
  type: this.annotationEntry[0].type,
2520
- feature: this.annotationEntry[0].feature
2777
+ feature: this.annotationEntry[0].feature,
2521
2778
  }
2522
2779
  }
2523
2780
  } else {
@@ -2532,15 +2789,19 @@ export default {
2532
2789
  // If connectivityInfoSidebar is set to `true`
2533
2790
  // Connectivity info will show in sidebar
2534
2791
  if (
2535
- (this.connectivityInfoSidebar && this.tooltipEntry.length) &&
2792
+ this.connectivityInfoSidebar &&
2793
+ this.tooltipEntry.length &&
2536
2794
  this.viewingMode !== 'Annotation'
2537
2795
  ) {
2538
2796
  if (this.checkConnectivityTooltipEntry(this.tooltipEntry)) {
2539
- this.$emit('connectivity-info-open', this.tooltipEntry);
2797
+ this.$emit('connectivity-info-open', this.tooltipEntry)
2540
2798
  }
2541
2799
  }
2542
2800
  if (this.annotationSidebar && this.viewingMode === 'Annotation') {
2543
- this.$emit('annotation-open', {annotationEntry: this.annotationEntry, commitCallback: this.commitAnnotationEvent});
2801
+ this.$emit('annotation-open', {
2802
+ annotationEntry: this.annotationEntry,
2803
+ commitCallback: this.commitAnnotationEvent,
2804
+ })
2544
2805
  }
2545
2806
  // If UI is not disabled,
2546
2807
  // And connectivityInfoSidebar is not set (default) or set to `false`
@@ -2549,16 +2810,14 @@ export default {
2549
2810
  if (
2550
2811
  featureId &&
2551
2812
  !this.disableUI &&
2552
- (
2553
- (this.viewingMode === 'Annotation' && !this.annotationSidebar) ||
2554
- (this.viewingMode === 'Exploration' && !this.connectivityInfoSidebar)
2555
- )
2813
+ ((this.viewingMode === 'Annotation' && !this.annotationSidebar) ||
2814
+ (this.viewingMode === 'Exploration' && !this.connectivityInfoSidebar))
2556
2815
  ) {
2557
- this.tooltipDisplay = true;
2816
+ this.tooltipDisplay = true
2558
2817
  this.$nextTick(() => {
2559
- this.mapImp.showPopup(featureId, this.$refs.tooltip.$el, options);
2560
- this.popUpCssHacks();
2561
- });
2818
+ this.mapImp.showPopup(featureId, this.$refs.tooltip.$el, options)
2819
+ this.popUpCssHacks()
2820
+ })
2562
2821
  }
2563
2822
  },
2564
2823
  /**
@@ -2567,18 +2826,18 @@ export default {
2567
2826
  * because the sidebar is opened
2568
2827
  * @arg featureIds
2569
2828
  */
2570
- moveMap: function (featureIds, options = {}) {
2829
+ moveMap: function (featureIds, options = {}) {
2571
2830
  if (this.mapImp) {
2572
- const { offsetX = 0, offsetY = 0, zoom = 4 } = options;
2573
- const Map = this.mapImp.map;
2574
- const bbox = this.mapImp.bounds.toArray();
2831
+ const { offsetX = 0, offsetY = 0, zoom = 4 } = options
2832
+ const Map = this.mapImp.map
2833
+ const bbox = this.mapImp.bounds.toArray()
2575
2834
 
2576
2835
  // Zoom the map to features first
2577
- this.mapImp.zoomToFeatures(featureIds, { noZoomIn: true });
2836
+ this.mapImp.zoomToFeatures(featureIds, { noZoomIn: true })
2578
2837
 
2579
2838
  // Hide the left pathway drawer
2580
2839
  // to get more space for the map
2581
- this.showPathwaysDrawer(false);
2840
+ this.showPathwaysDrawer(false)
2582
2841
 
2583
2842
  // Move the map to left side
2584
2843
  // since the sidebar is taking space on the right
@@ -2587,9 +2846,9 @@ export default {
2587
2846
  Map.fitBounds(bbox, {
2588
2847
  offset: [offsetX, offsetY],
2589
2848
  zoom: zoom,
2590
- animate: true
2591
- });
2592
- });
2849
+ animate: true,
2850
+ })
2851
+ })
2593
2852
  }
2594
2853
  }
2595
2854
  },
@@ -2609,7 +2868,7 @@ export default {
2609
2868
  /**
2610
2869
  * This event is emitted after a tooltip on Flatmap's map is shown.
2611
2870
  */
2612
- this.$emit('shown-map-tooltip');
2871
+ this.$emit('shown-map-tooltip')
2613
2872
  }
2614
2873
  }
2615
2874
  },
@@ -2644,16 +2903,19 @@ export default {
2644
2903
  */
2645
2904
  getVisibilityState: function (state) {
2646
2905
  const refs = ['alertSelection', 'pathwaysSelection', 'taxonSelection']
2647
- refs.forEach(ref => {
2906
+ refs.forEach((ref) => {
2648
2907
  let comp = this.$refs[ref]
2649
2908
  if (comp) {
2650
2909
  state[ref] = comp.getState()
2651
2910
  }
2652
2911
  })
2653
2912
  if (this.$refs.treeControls) {
2654
- const checkedKeys = this.$refs.treeControls.$refs.regionTree.getCheckedKeys();
2913
+ const checkedKeys =
2914
+ this.$refs.treeControls.$refs.regionTree.getCheckedKeys()
2655
2915
  //Only store first level systems (terms without .)
2656
- state['systemsSelection'] = checkedKeys.filter(term => !term.includes('.'))
2916
+ state['systemsSelection'] = checkedKeys.filter(
2917
+ (term) => !term.includes('.')
2918
+ )
2657
2919
  }
2658
2920
  },
2659
2921
  /**
@@ -2662,7 +2924,7 @@ export default {
2662
2924
  */
2663
2925
  setVisibilityState: function (state) {
2664
2926
  const refs = ['alertSelection', 'pathwaysSelection', 'taxonSelection']
2665
- refs.forEach(ref => {
2927
+ refs.forEach((ref) => {
2666
2928
  const settings = state[ref]
2667
2929
  if (settings) {
2668
2930
  const comp = this.$refs[ref]
@@ -2673,9 +2935,14 @@ export default {
2673
2935
  })
2674
2936
  if ('systemsSelection' in state) {
2675
2937
  if (this.$refs.treeControls) {
2676
- this.$refs.treeControls.$refs.regionTree.setCheckedKeys(state['systemsSelection']);
2938
+ this.$refs.treeControls.$refs.regionTree.setCheckedKeys(
2939
+ state['systemsSelection']
2940
+ )
2677
2941
  this.systems[0].children.forEach((item) => {
2678
- this.mapImp.enableSystem(item.key, state['systemsSelection'].includes(item.key))
2942
+ this.mapImp.enableSystem(
2943
+ item.key,
2944
+ state['systemsSelection'].includes(item.key)
2945
+ )
2679
2946
  })
2680
2947
  }
2681
2948
  }
@@ -2702,7 +2969,9 @@ export default {
2702
2969
  state['outlines'] = this.outlinesRadio
2703
2970
  state['background'] = this.currentBackground
2704
2971
  if (this.offlineAnnotationEnabled) {
2705
- state['offlineAnnotations'] = sessionStorage.getItem('anonymous-annotation')
2972
+ state['offlineAnnotations'] = sessionStorage.getItem(
2973
+ 'anonymous-annotation'
2974
+ )
2706
2975
  }
2707
2976
  this.getVisibilityState(state)
2708
2977
  return state
@@ -2739,7 +3008,10 @@ export default {
2739
3008
  if (state) {
2740
3009
  if (state.viewport) this.mapImp.setState(state.viewport)
2741
3010
  if (state.offlineAnnotations) {
2742
- sessionStorage.setItem('anonymous-annotation', state.offlineAnnotations)
3011
+ sessionStorage.setItem(
3012
+ 'anonymous-annotation',
3013
+ state.offlineAnnotations
3014
+ )
2743
3015
  }
2744
3016
  if (state.viewingMode) this.changeViewingMode(state.viewingMode)
2745
3017
  //The following three are boolean
@@ -2763,7 +3035,10 @@ export default {
2763
3035
  */
2764
3036
  setFlightPathInfo: function (mapVersion) {
2765
3037
  const mapVersionForFlightPath = 1.6
2766
- if (mapVersion === mapVersionForFlightPath || mapVersion > mapVersionForFlightPath) {
3038
+ if (
3039
+ mapVersion === mapVersionForFlightPath ||
3040
+ mapVersion > mapVersionForFlightPath
3041
+ ) {
2767
3042
  // Show flight path option UI
2768
3043
  this.displayFlightPathOption = true
2769
3044
  // Show 2D as default on FC type
@@ -2809,10 +3084,10 @@ export default {
2809
3084
  identifier.taxon = state.entry
2810
3085
  }
2811
3086
  if (state.biologicalSex) {
2812
- identifier['biologicalSex'] = state.biologicalSex;
3087
+ identifier['biologicalSex'] = state.biologicalSex
2813
3088
  } else if (identifier.taxon === 'NCBITaxon:9606') {
2814
3089
  //For backward compatibility
2815
- identifier['biologicalSex'] = 'PATO:0000384';
3090
+ identifier['biologicalSex'] = 'PATO:0000384'
2816
3091
  }
2817
3092
  } else {
2818
3093
  // Set the bioloicalSex now if map is not resumed from
@@ -2822,6 +3097,8 @@ export default {
2822
3097
  }
2823
3098
  }
2824
3099
 
3100
+ console.log("tooltip delay")
3101
+
2825
3102
  let promise1 = this.mapManagerRef.loadMap(
2826
3103
  identifier,
2827
3104
  this.eventCallback(),
@@ -2833,51 +3110,55 @@ export default {
2833
3110
  tooltips: this.tooltips,
2834
3111
  minimap: false,
2835
3112
  container: this.$refs.display,
2836
- // tooltipDelay: 15, // new feature to delay tooltips showing
3113
+ tooltipDelay: 15, // new feature to delay tooltips showing
2837
3114
  }
2838
3115
  )
2839
- promise1.then((returnedObject) => {
2840
- this.mapImp = returnedObject
2841
- this.serverURL = this.mapImp.makeServerUrl('').slice(0, -1)
2842
- let mapVersion = this.mapImp.details.version
2843
- this.setFlightPathInfo(mapVersion)
2844
- const stateToSet = this._stateToBeSet ? this._stateToBeSet : state
2845
- this.onFlatmapReady(stateToSet)
2846
- this.$nextTick(() => this.restoreMapState(stateToSet))
2847
- }).catch((error) => {
2848
- console.error('Flatmap loading error:', error)
2849
- // prepare error object
2850
- this.flatmapError = {};
2851
- if (error.message && error.message.indexOf('Unknown map') !== -1) {
2852
- this.flatmapError['title'] = 'Unknown Map!';
2853
- this.flatmapError['messages'] = Object.keys(identifier).map(key => {
2854
- const keyName = key === 'uuid' ? 'UUID' : capitalise(key);
2855
- return `${keyName}: ${identifier[key]}`
2856
- });
2857
- } else {
2858
- this.flatmapError['title'] = 'Error Loading Map!';
2859
- this.flatmapError['messages'] = [
2860
- error.message ? error.message : error.toString(),
2861
- 'Please try again later or contact support if the problem persists.'
2862
- ];
2863
- }
2864
- if (this.$parent?.$refs?.multiContainer) {
2865
- // if the flatmap is in a multiflatmapvuer
2866
- // show a button to load default map
2867
- const multiFlatmapVuer = this.$parent;
2868
- this.flatmapError['button'] = {
2869
- text: 'Load Default Map',
2870
- callback: () => {
2871
- const defaultSpecies = multiFlatmapVuer.initial;
2872
- multiFlatmapVuer.setSpecies(defaultSpecies, undefined, 3);
3116
+ promise1
3117
+ .then((returnedObject) => {
3118
+ this.mapImp = returnedObject
3119
+ this.serverURL = this.mapImp.makeServerUrl('').slice(0, -1)
3120
+ let mapVersion = this.mapImp.details.version
3121
+ this.setFlightPathInfo(mapVersion)
3122
+ const stateToSet = this._stateToBeSet ? this._stateToBeSet : state
3123
+ this.onFlatmapReady(stateToSet)
3124
+ this.$nextTick(() => this.restoreMapState(stateToSet))
3125
+ })
3126
+ .catch((error) => {
3127
+ console.error('Flatmap loading error:', error)
3128
+ // prepare error object
3129
+ this.flatmapError = {}
3130
+ if (error.message && error.message.indexOf('Unknown map') !== -1) {
3131
+ this.flatmapError['title'] = 'Unknown Map!'
3132
+ this.flatmapError['messages'] = Object.keys(identifier).map(
3133
+ (key) => {
3134
+ const keyName = key === 'uuid' ? 'UUID' : capitalise(key)
3135
+ return `${keyName}: ${identifier[key]}`
3136
+ }
3137
+ )
3138
+ } else {
3139
+ this.flatmapError['title'] = 'Error Loading Map!'
3140
+ this.flatmapError['messages'] = [
3141
+ error.message ? error.message : error.toString(),
3142
+ 'Please try again later or contact support if the problem persists.',
3143
+ ]
3144
+ }
3145
+ if (this.$parent?.$refs?.multiContainer) {
3146
+ // if the flatmap is in a multiflatmapvuer
3147
+ // show a button to load default map
3148
+ const multiFlatmapVuer = this.$parent
3149
+ this.flatmapError['button'] = {
3150
+ text: 'Load Default Map',
3151
+ callback: () => {
3152
+ const defaultSpecies = multiFlatmapVuer.initial
3153
+ multiFlatmapVuer.setSpecies(defaultSpecies, undefined, 3)
3154
+ },
2873
3155
  }
2874
- };
2875
- }
2876
- this.loading = false;
2877
- })
3156
+ }
3157
+ this.loading = false
3158
+ })
2878
3159
  } else if (state) {
2879
3160
  this._stateToBeSet = {
2880
- ...state
3161
+ ...state,
2881
3162
  }
2882
3163
  if (this.mapImp && !this.loading) {
2883
3164
  this.restoreMapState(this._stateToBeSet)
@@ -2919,7 +3200,7 @@ export default {
2919
3200
  let filterSourcesMap = new Map()
2920
3201
  for (const annotation of this.mapImp.annotations.values()) {
2921
3202
  if (annotation.source) {
2922
- if ("alert" in annotation) {
3203
+ if ('alert' in annotation) {
2923
3204
  withAlert.add(annotation.source)
2924
3205
  } else {
2925
3206
  withoutAlert.add(annotation.source)
@@ -2936,7 +3217,7 @@ export default {
2936
3217
  sourceMap.set(setKey, new Set())
2937
3218
  }
2938
3219
  sourceMap.get(setKey).add(`${annotation.source}`)
2939
- };
3220
+ }
2940
3221
  if (Array.isArray(value)) {
2941
3222
  value.forEach(addToSourceMap)
2942
3223
  } else {
@@ -2947,10 +3228,10 @@ export default {
2947
3228
  }
2948
3229
  }
2949
3230
  let filterSources = {
2950
- 'alert': {
2951
- 'with': [...withAlert],
2952
- 'without': [...withoutAlert]
2953
- }
3231
+ alert: {
3232
+ with: [...withAlert],
3233
+ without: [...withoutAlert],
3234
+ },
2954
3235
  }
2955
3236
  for (const [key, value] of filterSourcesMap.entries()) {
2956
3237
  filterSources[key] = {}
@@ -2961,10 +3242,15 @@ export default {
2961
3242
  return filterSources
2962
3243
  },
2963
3244
  getFilterOptions: async function (mapImp, _providedKnowledge) {
2964
- const providedKnowledge = _providedKnowledge || this.getFlatmapKnowledge();
2965
- const providedPathways = this.pathways;
2966
- const flatmapFilterOptions = await getFlatmapFilterOptions(this.flatmapAPI, mapImp, providedKnowledge, providedPathways);
2967
- return flatmapFilterOptions;
3245
+ const providedKnowledge = _providedKnowledge || this.getFlatmapKnowledge()
3246
+ const providedPathways = this.pathways
3247
+ const flatmapFilterOptions = await getFlatmapFilterOptions(
3248
+ this.flatmapAPI,
3249
+ mapImp,
3250
+ providedKnowledge,
3251
+ providedPathways
3252
+ )
3253
+ return flatmapFilterOptions
2968
3254
  },
2969
3255
  /**
2970
3256
  * @public
@@ -2972,33 +3258,40 @@ export default {
2972
3258
  */
2973
3259
  onFlatmapReady: function (state) {
2974
3260
  // onFlatmapReady is used for functions that need to run immediately after the flatmap is loaded
2975
- this.sensor = markRaw(new ResizeSensor(this.$refs.display, this.mapResize))
3261
+ this.sensor = markRaw(
3262
+ new ResizeSensor(this.$refs.display, this.mapResize)
3263
+ )
2976
3264
  if (this.mapImp.options?.style === 'functional') {
2977
3265
  this.isFC = true
2978
3266
  }
2979
3267
  this.mapImp.setBackgroundOpacity(1)
2980
3268
  this.backgroundChangeCallback(this.currentBackground)
2981
3269
  this.pathways = this.mapImp.pathTypes()
2982
- this.pathways = this.pathways.filter(path => {
3270
+ this.pathways = this.pathways.filter((path) => {
2983
3271
  return path.enabled && path.type !== 'other'
2984
3272
  })
2985
3273
  //Disable layers for now
2986
3274
  //this.layers = this.mapImp.getLayers();
2987
3275
  this.processSystems(this.mapImp.getSystems())
2988
3276
  //Async, pass the state for checking
2989
- this.processTaxon(this.mapImp.taxonIdentifiers, state ? state['taxonSelection'] : undefined)
2990
- this.containsAlert = "alert" in this.mapImp.featureFilterRanges()
3277
+ this.processTaxon(
3278
+ this.mapImp.taxonIdentifiers,
3279
+ state ? state['taxonSelection'] : undefined
3280
+ )
3281
+
3282
+ this.containsAlert = 'alert' in this.mapImp.featureFilterRanges()
2991
3283
  this.flatmapLegends = this.mapImp.flatmapLegend
2992
3284
  this.loading = false
2993
3285
  this.computePathControlsMaximumHeight()
2994
3286
  this.mapResize()
2995
- this.handleMapClick();
2996
- this.setInitMapState();
3287
+ this.handleMapClick()
3288
+ this.setInitMapState()
2997
3289
  if (this.displayMinimap) {
2998
- const minimapOptions = { position: 'top-right' };
2999
- this.mapImp.createMinimap(minimapOptions);
3290
+ const minimapOptions = { position: 'top-right' }
3291
+ this.mapImp.createMinimap(minimapOptions)
3000
3292
  this.addResizeButtonToMinimap()
3001
3293
  }
3294
+ this.currentFlatmapUuid = this.mapImp?.mapMetadata?.uuid
3002
3295
  /**
3003
3296
  * This is ``onFlatmapReady`` event.
3004
3297
  * @arg ``this`` (Component Vue Instance)
@@ -3011,33 +3304,35 @@ export default {
3011
3304
  * after the map is loaded.
3012
3305
  */
3013
3306
  handleMapClick: function () {
3014
- const _map = this.mapImp.map;
3307
+ const _map = this.mapImp.map
3015
3308
  if (_map) {
3016
3309
  _map.on('click', (e) => {
3017
3310
  if (!this.connectivityDataSource) {
3018
- this.$emit('connectivity-info-close');
3311
+ this.$emit('connectivity-info-close')
3019
3312
  }
3020
- this.connectivityDataSource = ''; // reset
3021
- });
3313
+ this.connectivityDataSource = '' // reset
3314
+ })
3022
3315
  }
3023
3316
  },
3024
- onContextLost: function() {
3317
+ onContextLost: function () {
3025
3318
  this.lastViewport = markRaw(this.mapImp.getState())
3026
- this.flatmapError = {};
3319
+ this.flatmapError = {}
3027
3320
  this.flatmapError['title'] = 'GL context lost!'
3028
- this.flatmapError['messages'] = [`A display issue has occurred due
3321
+ this.flatmapError['messages'] = [
3322
+ `A display issue has occurred due
3029
3323
  to a limit on available WebGL contexts. You can restore the display
3030
3324
  using the Restore Context button. Please see the
3031
3325
  <a href="https://docs.sparc.science/docs/integrated-maps-viewer-overview#limit-on-available-webgl-contexts" target='_blank'>documentation</a>
3032
- for more details.`]
3326
+ for more details.`,
3327
+ ]
3033
3328
  this.flatmapError['button'] = {
3034
3329
  text: 'Restore Context',
3035
3330
  callback: () => {
3036
3331
  this.forceContextRestore()
3037
- }
3038
- };
3332
+ },
3333
+ }
3039
3334
  },
3040
- onContextRestored: function() {
3335
+ onContextRestored: function () {
3041
3336
  if (this.mapImp) {
3042
3337
  this.handleMapClick()
3043
3338
  this.setInitMapState()
@@ -3047,8 +3342,8 @@ export default {
3047
3342
  }
3048
3343
  this.restoreMapState(lostState)
3049
3344
  if (this.displayMinimap) {
3050
- const minimapOptions = { position: 'top-right' };
3051
- this.mapImp.createMinimap(minimapOptions);
3345
+ const minimapOptions = { position: 'top-right' }
3346
+ this.mapImp.createMinimap(minimapOptions)
3052
3347
  this.addResizeButtonToMinimap()
3053
3348
  }
3054
3349
  if (this.filterToRestore) {
@@ -3079,23 +3374,23 @@ export default {
3079
3374
  if (this.mapImp) {
3080
3375
  if (term === undefined || term === '') {
3081
3376
  this.mapImp.clearSearchResults()
3082
- if (this.viewingMode === "Exploration") {
3083
- this.$emit('connectivity-info-close');
3084
- } else if (this.viewingMode === "Annotation") {
3377
+ if (this.viewingMode === 'Exploration') {
3378
+ this.$emit('connectivity-info-close')
3379
+ } else if (this.viewingMode === 'Annotation') {
3085
3380
  this.manualAbortedOnClose()
3086
3381
  }
3087
- this.searchTerm = ""
3382
+ this.searchTerm = ''
3088
3383
  return true
3089
3384
  } else {
3090
3385
  const searchResults = this.mapImp.search(term)
3091
3386
  if (searchResults?.results?.length) {
3092
3387
  this.mapImp.showSearchResults(searchResults)
3093
3388
  if (displayInfo) {
3094
- let featureId = undefined;
3389
+ let featureId = undefined
3095
3390
  for (let i = 0; i < searchResults.results.length; i++) {
3096
3391
  featureId = searchResults.results[i].featureId
3097
3392
  const annotation = this.mapImp.annotation(featureId)
3098
- if (featureId && annotation?.label) break;
3393
+ if (featureId && annotation?.label) break
3099
3394
  }
3100
3395
  if (featureId) {
3101
3396
  const feature = this.mapImp.featureProperties(featureId)
@@ -3131,10 +3426,13 @@ export default {
3131
3426
  highlightConnectedPaths: function (paths) {
3132
3427
  if (paths.length) {
3133
3428
  // filter paths for this map
3134
- const filteredPaths = paths.filter(path => (path in this.mapImp.pathways.paths))
3429
+ const filteredPaths = paths.filter(
3430
+ (path) => path in this.mapImp.pathways.paths
3431
+ )
3135
3432
  // this.zoomToFeatures is replaced with selectGeoJSONFeatures to highlight paths
3136
- const featureIdsToHighlight = this.mapImp.modelFeatureIdList(filteredPaths);
3137
- this.mapImp.selectGeoJSONFeatures(featureIdsToHighlight);
3433
+ const featureIdsToHighlight =
3434
+ this.mapImp.modelFeatureIdList(filteredPaths)
3435
+ this.mapImp.selectGeoJSONFeatures(featureIdsToHighlight)
3138
3436
  }
3139
3437
  },
3140
3438
  /**
@@ -3151,7 +3449,144 @@ export default {
3151
3449
  EventBus.emit('onActionClick', data)
3152
3450
  },
3153
3451
  setConnectionType: function (type) {
3154
- this.connectionType = type;
3452
+ this.connectionType = type
3453
+ },
3454
+ /**
3455
+ * Main function to coordinate fetching dataset info and processing files.
3456
+ */
3457
+ async fetchFlatmapProtocols(uuid) {
3458
+ const cacheKey = `flatmap_dataset_${uuid}`
3459
+
3460
+ // Try to get from cache first
3461
+ // console.log('------- caching temporary disabled for debugging -------')
3462
+ // const cachedData = null
3463
+ const cachedData = this.getSessionCache(cacheKey)
3464
+ if (cachedData) {
3465
+ this.datasetInfo = cachedData
3466
+ this.processDatasetFiles(cachedData)
3467
+ return
3468
+ }
3469
+
3470
+ // If not in cache, call the API
3471
+ const apiLocation = import.meta.env.VITE_API_LOCATION
3472
+ if (!apiLocation) {
3473
+ console.warn('VITE_API_LOCATION is not defined.')
3474
+ return
3475
+ }
3476
+
3477
+ try {
3478
+ console.log('Fetching dataset info from API...')
3479
+ // Ensure the URL matches your backend route structure
3480
+ const response = await fetch(`${apiLocation}flatmap/uuid?uuid=${uuid}`)
3481
+
3482
+ if (!response.ok)
3483
+ throw new Error(`API call failed: ${response.statusText}`)
3484
+
3485
+ const data = await response.json()
3486
+
3487
+ // Save to cache and process
3488
+ this.setSessionCache(cacheKey, data)
3489
+ this.datasetInfo = data
3490
+ this.processDatasetFiles(data)
3491
+ } catch (error) {
3492
+ console.error('Error fetching flatmap protocols:', error)
3493
+ }
3494
+ },
3495
+
3496
+ /**
3497
+ * Extract the bucket name from an S3 URI.
3498
+ *
3499
+ * @param s3Uri
3500
+ */
3501
+ extractBucketNameFromS3Uri(s3Uri) {
3502
+ try {
3503
+ // Use the native URL API to parse the s3:// URI
3504
+ // s3://bucket-name/path/to/key -> hostname is bucket-name
3505
+ const url = new URL(s3Uri)
3506
+ return url.hostname
3507
+ } catch (e) {
3508
+ console.error('Error converting S3 URI:', e)
3509
+ return null
3510
+ }
3511
+ },
3512
+ /**
3513
+ * Iterates through the file list, constructs full URLs, and checks for simulation content.
3514
+ */
3515
+ async processDatasetFiles(data) {
3516
+ if (!data || data.length === 0) return
3517
+
3518
+ this.simulationInfo = [] // Reset list
3519
+
3520
+ //FIXME: Currently only process the first dataset entry
3521
+ const firstData = data[0]
3522
+ const apiLocation = import.meta.env.VITE_API_LOCATION
3523
+ // Base URL for Pennsieve public assets
3524
+ const baseUrl = `${apiLocation}/s3-resource/${firstData.dataset_id}/files`
3525
+ const bucketName = this.extractBucketNameFromS3Uri(firstData.s3uri)
3526
+
3527
+ firstData.urls.map(async (filePath) => {
3528
+ const fullUrl = `${baseUrl}/${filePath}?s3BucketName=${bucketName}`
3529
+ // Add to our list of valid files
3530
+ this.simulationInfo.push({
3531
+ label: firstData.title,
3532
+ s3uri: firstData.s3uri,
3533
+ dataset_id: firstData.dataset_id,
3534
+ version: firstData.version,
3535
+ path: filePath,
3536
+ type: 'Simulation',
3537
+ resource: fullUrl,
3538
+ })
3539
+ })
3540
+ },
3541
+ /**
3542
+ * Retrieve data from session storage if it hasn't expired.
3543
+ */
3544
+ getSessionCache(key) {
3545
+ const itemStr = sessionStorage.getItem(key)
3546
+ if (!itemStr) return null
3547
+
3548
+ try {
3549
+ const item = JSON.parse(itemStr)
3550
+ const now = new Date()
3551
+
3552
+ // Check if expired (compare current time to expiry time)
3553
+ if (now.getTime() > item.expiry) {
3554
+ sessionStorage.removeItem(key)
3555
+ return null
3556
+ }
3557
+ return item.value
3558
+ } catch (e) {
3559
+ return null
3560
+ }
3561
+ },
3562
+
3563
+ /**
3564
+ * Save data to session storage with a 24-hour expiry.
3565
+ */
3566
+ setSessionCache(key, value) {
3567
+ const now = new Date()
3568
+ // 24 hours in milliseconds: 24 * 60 * 60 * 1000 = 86400000
3569
+ const ttl = 86400000
3570
+
3571
+ const item = {
3572
+ value: value,
3573
+ expiry: now.getTime() + ttl,
3574
+ }
3575
+
3576
+ try {
3577
+ sessionStorage.setItem(key, JSON.stringify(item))
3578
+ } catch (e) {
3579
+ console.warn('Session storage full or disabled', e)
3580
+ }
3581
+ },
3582
+ getSimulationLabel(info) {
3583
+ console.log(info.path)
3584
+ return info.path.split('/').pop()
3585
+ },
3586
+ openSimulation() {
3587
+ if (this.selectedSimulation) {
3588
+ this.$emit('open-simulation', this.selectedSimulation)
3589
+ }
3155
3590
  },
3156
3591
  },
3157
3592
  props: {
@@ -3210,7 +3645,7 @@ export default {
3210
3645
  * On default, `false`, clicking help will show all tooltips.
3211
3646
  * If `true`, clicking help will show the help-mode-dialog.
3212
3647
  */
3213
- helpModeDialog: {
3648
+ helpModeDialog: {
3214
3649
  type: Boolean,
3215
3650
  default: false,
3216
3651
  },
@@ -3344,7 +3779,7 @@ export default {
3344
3779
  /**
3345
3780
  * Flag to disable UIs on Map
3346
3781
  */
3347
- disableUI: {
3782
+ disableUI: {
3348
3783
  type: Boolean,
3349
3784
  default: false,
3350
3785
  },
@@ -3407,12 +3842,14 @@ export default {
3407
3842
  flatmapError: null,
3408
3843
  sensor: null,
3409
3844
  mapManagerRef: undefined,
3845
+ currentFlatmapUuid: undefined,
3410
3846
  flatmapQueries: undefined,
3411
3847
  annotationEntry: [],
3412
3848
  //tooltip display has to be set to false until it is rendered
3413
- //for the first time, otherwise it may display an arrow at a
3849
+ //for the first time, otherwise it may display an arrow at an
3414
3850
  //undesired location.
3415
3851
  tooltipDisplay: false,
3852
+ tooltipTimer: null,
3416
3853
  serverURL: undefined,
3417
3854
  layers: [],
3418
3855
  pathways: [],
@@ -3438,12 +3875,13 @@ export default {
3438
3875
  { value: false, ref: 'warningPopover' }, // 7
3439
3876
  { value: false, ref: 'whatsNewPopover' }, // 8
3440
3877
  { value: false, ref: 'featuredMarkerPopover' }, // 9
3441
- { value: false, refs: "toolbarPopover", ref: "editPopover" }, // 10
3442
- { value: false, refs: "toolbarPopover", ref: "deletePopover" }, // 11
3443
- { value: false, refs: "toolbarPopover", ref: "pointPopover" }, // 12
3444
- { value: false, refs: "toolbarPopover", ref: "lineStringPopover" }, // 13
3445
- { value: false, refs: "toolbarPopover", ref: "polygonPopover" }, // 14
3446
- { value: false, refs: "toolbarPopover", ref: "connectionPopover" }, // 15
3878
+ { value: false, refs: 'toolbarPopover', ref: 'editPopover' }, // 10
3879
+ { value: false, refs: 'toolbarPopover', ref: 'deletePopover' }, // 11
3880
+ { value: false, refs: 'toolbarPopover', ref: 'pointPopover' }, // 12
3881
+ { value: false, refs: 'toolbarPopover', ref: 'lineStringPopover' }, // 13
3882
+ { value: false, refs: 'toolbarPopover', ref: 'polygonPopover' }, // 14
3883
+ { value: false, refs: 'toolbarPopover', ref: 'connectionPopover' }, // 15
3884
+ { value: false, ref: 'simulationPopover' }, // 16
3447
3885
  ],
3448
3886
  helpModeActiveIndex: this.helpModeInitialIndex,
3449
3887
  yellowstar: yellowstar,
@@ -3468,9 +3906,14 @@ export default {
3468
3906
  currentHover: '',
3469
3907
  viewingMode: 'Exploration',
3470
3908
  viewingModes: {
3471
- 'Exploration': 'Find relevant research and view detail of neural pathways by selecting a pathway to view its connections and data sources',
3472
- 'Neuron Connection': 'Discover Neuron connections by selecting a neuron and viewing its associated network connections',
3473
- 'Annotation': ['View feature annotations', 'Add, comment on and view feature annotations']
3909
+ Exploration:
3910
+ 'Find relevant research and view detail of neural pathways by selecting a pathway to view its connections and data sources',
3911
+ 'Neuron Connection':
3912
+ 'Discover Neuron connections by selecting a neuron and viewing its associated network connections',
3913
+ Annotation: [
3914
+ 'View feature annotations',
3915
+ 'Add, comment on and view feature annotations',
3916
+ ],
3474
3917
  },
3475
3918
  connectionType: 'All',
3476
3919
  offlineAnnotationEnabled: false,
@@ -3480,12 +3923,12 @@ export default {
3480
3923
  openMapRef: undefined,
3481
3924
  backgroundIconRef: undefined,
3482
3925
  toolbarOptions: [
3483
- "Edit",
3484
- "Delete",
3485
- "Point",
3486
- "LineString",
3487
- "Polygon",
3488
- "Connection",
3926
+ 'Edit',
3927
+ 'Delete',
3928
+ 'Point',
3929
+ 'LineString',
3930
+ 'Polygon',
3931
+ 'Connection',
3489
3932
  ],
3490
3933
  annotator: undefined,
3491
3934
  authorisedUser: undefined,
@@ -3515,13 +3958,17 @@ export default {
3515
3958
  alert: {
3516
3959
  with: true,
3517
3960
  without: true,
3518
- }
3961
+ },
3519
3962
  }),
3520
- searchTerm: "",
3963
+ searchTerm: '',
3521
3964
  taxonLeaveDelay: undefined,
3522
3965
  connectivityFilters: [],
3523
3966
  flatmapLegends: [],
3524
3967
  lastViewport: undefined,
3968
+ simulationInfo: [],
3969
+ datasetInfo: null,
3970
+ simulationDrawerOpen: false,
3971
+ selectedSimulation: null,
3525
3972
  }
3526
3973
  },
3527
3974
  computed: {
@@ -3529,16 +3976,17 @@ export default {
3529
3976
  isValidDrawnCreated: function () {
3530
3977
  return Object.keys(this.drawnCreatedEvent).length > 0
3531
3978
  },
3532
- requiresDrawer: function() {
3979
+ requiresDrawer: function () {
3533
3980
  if (this.loading) {
3534
3981
  this.drawerOpen = false
3535
3982
  return false
3536
3983
  }
3537
- if ((this.systems?.length > 0) ||
3984
+ if (
3985
+ this.systems?.length > 0 ||
3538
3986
  (this.containsAlert && this.alertOptions) ||
3539
- (this.pathways?.length > 0) ||
3540
- (this.taxonConnectivity?.length > 0) ||
3541
- (this.legendEntry?.length > 0)
3987
+ this.pathways?.length > 0 ||
3988
+ this.taxonConnectivity?.length > 0 ||
3989
+ this.legendEntry?.length > 0
3542
3990
  ) {
3543
3991
  this.drawerOpen = true
3544
3992
  return true
@@ -3560,7 +4008,7 @@ export default {
3560
4008
  return [...this.flatmapLegends, ...this.externalLegends]
3561
4009
  },
3562
4010
  showDatasetMarkerTooltip: function () {
3563
- return this.hoverVisibilities[9].value;
4011
+ return this.hoverVisibilities[9].value
3564
4012
  },
3565
4013
  },
3566
4014
  watch: {
@@ -3576,11 +4024,11 @@ export default {
3576
4024
  // just take the action from helpModeActiveItem
3577
4025
  // work with local value since the indexing is different
3578
4026
  if (this.helpMode) {
3579
- this.helpModeActiveIndex += 1;
3580
- this.setHelpMode(this.helpMode);
4027
+ this.helpModeActiveIndex += 1
4028
+ this.setHelpMode(this.helpMode)
3581
4029
  }
3582
4030
  },
3583
- render: function(val) {
4031
+ render: function (val) {
3584
4032
  if (val) {
3585
4033
  if (this.mapImp && this.mapImp.contextLost && !this.loading) {
3586
4034
  this.$nextTick(() => {
@@ -3615,7 +4063,7 @@ export default {
3615
4063
  this.authorisedUser = undefined
3616
4064
  this.offlineAnnotationEnabled = true
3617
4065
  }
3618
- this.emitOfflineAnnotationUpdate();
4066
+ this.emitOfflineAnnotationUpdate()
3619
4067
  this.setFeatureAnnotated()
3620
4068
  this.addAnnotationFeature()
3621
4069
  this.loading = false
@@ -3628,54 +4076,67 @@ export default {
3628
4076
  }
3629
4077
  },
3630
4078
  activeDrawTool: function (tool) {
3631
- let coordinates = [];
3632
- let lastClick = { x: null, y: null };
3633
- const canvas = this.$el.querySelector('.maplibregl-canvas');
4079
+ let coordinates = []
4080
+ let lastClick = { x: null, y: null }
4081
+ const canvas = this.$el.querySelector('.maplibregl-canvas')
3634
4082
  const removeListeners = () => {
3635
- canvas.removeEventListener('keydown', handleKeyboardEvent);
3636
- canvas.removeEventListener('click', handleMouseEvent);
3637
- };
4083
+ canvas.removeEventListener('keydown', handleKeyboardEvent)
4084
+ canvas.removeEventListener('click', handleMouseEvent)
4085
+ }
3638
4086
  const handleKeyboardEvent = (event) => {
3639
- if (!['Escape', 'Enter'].includes(event.key)) return;
4087
+ if (!['Escape', 'Enter'].includes(event.key)) return
3640
4088
  const isValidDraw =
3641
4089
  (tool === 'Point' && coordinates.length === 1) ||
3642
4090
  (tool === 'LineString' && coordinates.length >= 2) ||
3643
- (tool === 'Polygon' && coordinates.length >= 3);
4091
+ (tool === 'Polygon' && coordinates.length >= 3)
3644
4092
  if (event.key === 'Escape' || (event.key === 'Enter' && !isValidDraw)) {
3645
- this.activeDrawTool = undefined;
4093
+ this.activeDrawTool = undefined
3646
4094
  }
3647
- removeListeners();
3648
- };
4095
+ removeListeners()
4096
+ }
3649
4097
  const handleMouseEvent = (event) => {
3650
- const rect = canvas.getBoundingClientRect();
3651
- const x = event.clientX - rect.left;
3652
- const y = event.clientY - rect.top;
3653
- const distance = Math.sqrt((x - lastClick.x) ** 2 + (y - lastClick.y) ** 2);
4098
+ const rect = canvas.getBoundingClientRect()
4099
+ const x = event.clientX - rect.left
4100
+ const y = event.clientY - rect.top
4101
+ const distance = Math.sqrt(
4102
+ (x - lastClick.x) ** 2 + (y - lastClick.y) ** 2
4103
+ )
3654
4104
  if (distance < 8) {
3655
- if (!this.isValidDrawnCreated) this.activeDrawTool = undefined;
3656
- removeListeners();
3657
- return;
4105
+ if (!this.isValidDrawnCreated) this.activeDrawTool = undefined
4106
+ removeListeners()
4107
+ return
3658
4108
  }
3659
- lastClick = { x, y };
3660
- coordinates.push(lastClick);
3661
- };
4109
+ lastClick = { x, y }
4110
+ coordinates.push(lastClick)
4111
+ }
3662
4112
  if (tool) {
3663
- removeListeners();
3664
- canvas.addEventListener('keydown', handleKeyboardEvent);
3665
- canvas.addEventListener('click', handleMouseEvent);
4113
+ removeListeners()
4114
+ canvas.addEventListener('keydown', handleKeyboardEvent)
4115
+ canvas.addEventListener('click', handleMouseEvent)
3666
4116
  }
3667
- }
4117
+ },
4118
+ currentFlatmapUuid: {
4119
+ handler(newUuid) {
4120
+ if (newUuid) {
4121
+ // console.log('New map loaded with uuid:', newUuid)
4122
+ this.fetchFlatmapProtocols(newUuid)
4123
+ }
4124
+ },
4125
+ // immediate: true,
4126
+ },
3668
4127
  },
3669
4128
  created: function () {
3670
4129
  if (this.mapManager) {
3671
- this.mapManagerRef = this.mapManager;
4130
+ this.mapManagerRef = this.mapManager
3672
4131
  } else {
3673
- this.mapManagerRef = markRaw(new flatmap.MapViewer(this.flatmapAPI, { container: undefined }));
4132
+ this.mapManagerRef = markRaw(
4133
+ new flatmap.MapViewer(this.flatmapAPI, { container: undefined })
4134
+ )
3674
4135
  /**
3675
4136
  * The event emitted after a new mapManager is loaded.
3676
4137
  * This mapManager can be used to create new flatmaps.
3677
4138
  */
3678
- this.$emit('mapmanager-loaded', this.mapManagerRef);
4139
+ this.$emit('mapmanager-loaded', this.mapManagerRef)
3679
4140
  }
3680
4141
  },
3681
4142
  mounted: function () {
@@ -3692,17 +4153,16 @@ export default {
3692
4153
  } else if (this.renderAtMounted) {
3693
4154
  this.createFlatmap()
3694
4155
  }
3695
- refreshFlatmapKnowledgeCache();
4156
+ refreshFlatmapKnowledgeCache()
3696
4157
  },
3697
4158
  }
3698
4159
  </script>
3699
4160
 
3700
4161
  <style lang="scss" scoped>
3701
-
3702
4162
  .beta-popovers {
3703
4163
  position: absolute;
3704
- top: 90px;
3705
- left: 16px;
4164
+ top: 0px;
4165
+ left: 50%;
3706
4166
  text-align: left;
3707
4167
  font-size: 25px;
3708
4168
  }
@@ -3758,6 +4218,32 @@ export default {
3758
4218
  width: 100%;
3759
4219
  }
3760
4220
 
4221
+ .popover-location {
4222
+ position: absolute;
4223
+ left: 0px;
4224
+ transform: translateX(0);
4225
+ transition: all var(--el-transition-duration);
4226
+ z-index: 99;
4227
+ display: flex;
4228
+ flex-direction: row;
4229
+ align-items: center;
4230
+
4231
+ &.open {
4232
+ transform: translateX(0);
4233
+ }
4234
+ &.close {
4235
+ transform: translateX(-100%);
4236
+ }
4237
+ }
4238
+
4239
+ .popover-location.top {
4240
+ top: 5px;
4241
+ }
4242
+
4243
+ .popover-location.bottom {
4244
+ bottom: 0px;
4245
+ }
4246
+
3761
4247
  .pathway-location {
3762
4248
  position: absolute;
3763
4249
  bottom: 0px;
@@ -4004,7 +4490,7 @@ export default {
4004
4490
  }
4005
4491
  }
4006
4492
 
4007
- :deep(.flatmap-marker-popup){
4493
+ :deep(.flatmap-marker-popup) {
4008
4494
  .maplibregl-popup-content {
4009
4495
  padding: 0px;
4010
4496
  }
@@ -4029,7 +4515,9 @@ export default {
4029
4515
  }
4030
4516
  }
4031
4517
 
4032
- .zoomIn, .zoomOut, .fitWindow {
4518
+ .zoomIn,
4519
+ .zoomOut,
4520
+ .fitWindow {
4033
4521
  padding: 4px;
4034
4522
  }
4035
4523
 
@@ -4144,7 +4632,7 @@ export default {
4144
4632
  color: $app-primary-color;
4145
4633
 
4146
4634
  &.open-map-button {
4147
- margin-bottom:4px;
4635
+ margin-bottom: 4px;
4148
4636
  }
4149
4637
 
4150
4638
  &:hover {
@@ -4268,7 +4756,7 @@ export default {
4268
4756
  position: relative;
4269
4757
 
4270
4758
  &::before {
4271
- content: "";
4759
+ content: '';
4272
4760
  display: block;
4273
4761
  width: 0;
4274
4762
  height: 0;
@@ -4397,7 +4885,7 @@ export default {
4397
4885
  background-color: var(--white);
4398
4886
  font-weight: 500;
4399
4887
  color: rgb(48, 49, 51);
4400
- width: 150px!important;
4888
+ width: 150px !important;
4401
4889
  }
4402
4890
 
4403
4891
  :deep(.flatmap_dropdown) {
@@ -4421,11 +4909,10 @@ export default {
4421
4909
  </style>
4422
4910
 
4423
4911
  <style lang="scss">
4424
-
4425
4912
  .flatmap-container {
4426
- --el-color-primary: #8300BF;
4427
- --el-color-primary-light-5: #CD99E5;
4428
- --el-color-primary-light-9: #F3E6F9;
4913
+ --el-color-primary: #8300bf;
4914
+ --el-color-primary-light-5: #cd99e5;
4915
+ --el-color-primary-light-9: #f3e6f9;
4429
4916
  --el-color-primary-dark-2: var(--el-color-primary);
4430
4917
  }
4431
4918
 
@@ -4448,5 +4935,4 @@ export default {
4448
4935
  }
4449
4936
  }
4450
4937
  }
4451
-
4452
4938
  </style>