@abi-software/flatmapvuer 0.6.0-vue3.8 → 0.6.1-annotator.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -136,6 +136,128 @@
136
136
  <el-icon-arrow-down />
137
137
  </el-icon>
138
138
 
139
+ <div class="bottom-draw-control"
140
+ v-show="viewingMode === 'Annotation' && userInformation && !disableUI"
141
+ >
142
+ <el-popover
143
+ content="Relevance"
144
+ placement="top"
145
+ :teleported="false"
146
+ trigger="manual"
147
+ width="80"
148
+ popper-class="flatmap-popper"
149
+ :visible="hoverVisibilities[10].value"
150
+ >
151
+ <template #reference>
152
+ <map-svg-icon
153
+ icon="connection"
154
+ class="icon-button drawRelevance inactive"
155
+ @click="relevanceDialogPopup"
156
+ @mouseover="showToolitip(10)"
157
+ @mouseout="hideToolitip(10)"
158
+ />
159
+ </template>
160
+ </el-popover>
161
+ <el-popover
162
+ content="Draw Point"
163
+ placement="top"
164
+ :teleported="false"
165
+ trigger="manual"
166
+ width="80"
167
+ popper-class="flatmap-popper"
168
+ :visible="hoverVisibilities[11].value"
169
+ v-if="drawnType !== 'LineString' && drawnType !== 'Polygon'"
170
+ >
171
+ <template #reference>
172
+ <map-svg-icon
173
+ icon="drawPoint"
174
+ class="icon-button drawPoint"
175
+ @click="drawingEvent('Point')"
176
+ @mouseover="showToolitip(11)"
177
+ @mouseout="hideToolitip(11)"
178
+ />
179
+ </template>
180
+ </el-popover>
181
+ <el-popover
182
+ content="Draw Line"
183
+ placement="top"
184
+ :teleported="false"
185
+ trigger="manual"
186
+ width="80"
187
+ popper-class="flatmap-popper"
188
+ :visible="hoverVisibilities[12].value"
189
+ v-if="drawnType !== 'Point' && drawnType !== 'Polygon'"
190
+ >
191
+ <template #reference>
192
+ <map-svg-icon
193
+ icon="drawLine"
194
+ class="icon-button drawLineString"
195
+ @click="drawingEvent('LineString')"
196
+ @mouseover="showToolitip(12)"
197
+ @mouseout="hideToolitip(12)"
198
+ />
199
+ </template>
200
+ </el-popover>
201
+ <el-popover
202
+ content="Draw Polygon"
203
+ placement="top"
204
+ :teleported="false"
205
+ trigger="manual"
206
+ width="80"
207
+ popper-class="flatmap-popper"
208
+ :visible="hoverVisibilities[13].value"
209
+ v-if="drawnType !== 'Point' && drawnType !== 'LineString'"
210
+ >
211
+ <template #reference>
212
+ <map-svg-icon
213
+ icon="drawPolygon"
214
+ class="icon-button drawPolygon"
215
+ @click="drawingEvent('Polygon')"
216
+ @mouseover="showToolitip(13)"
217
+ @mouseout="hideToolitip(13)"
218
+ />
219
+ </template>
220
+ </el-popover>
221
+ <el-popover
222
+ content="Delete"
223
+ placement="top"
224
+ :teleported="false"
225
+ trigger="manual"
226
+ width="80"
227
+ popper-class="flatmap-popper"
228
+ :visible="hoverVisibilities[14].value"
229
+ >
230
+ <template #reference>
231
+ <map-svg-icon
232
+ icon="drawTrash"
233
+ class="icon-button drawDelete"
234
+ @click="drawingEvent('Delete')"
235
+ @mouseover="showToolitip(14)"
236
+ @mouseout="hideToolitip(14)"
237
+ />
238
+ </template>
239
+ </el-popover>
240
+ <el-popover
241
+ content="Edit"
242
+ placement="top"
243
+ :teleported="false"
244
+ trigger="manual"
245
+ width="80"
246
+ popper-class="flatmap-popper"
247
+ :visible="hoverVisibilities[15].value"
248
+ >
249
+ <template #reference>
250
+ <map-svg-icon
251
+ icon="comment"
252
+ class="icon-button drawEdit"
253
+ @click="drawingEvent('Edit')"
254
+ @mouseover="showToolitip(15)"
255
+ @mouseout="hideToolitip(15)"
256
+ />
257
+ </template>
258
+ </el-popover>
259
+ </div>
260
+
139
261
  <div class="bottom-right-control" v-show="!disableUI">
140
262
  <el-popover
141
263
  content="Zoom in"
@@ -162,7 +284,7 @@
162
284
  :teleported="false"
163
285
  trigger="manual"
164
286
  width="70"
165
- popper-class="flatmap-popper popper-zoomout"
287
+ popper-class="flatmap-popper"
166
288
  :visible="hoverVisibilities[1].value"
167
289
  >
168
290
  <template #reference>
@@ -219,7 +341,6 @@
219
341
  class="pathway-container"
220
342
  :class="{ open: drawerOpen, close: !drawerOpen }"
221
343
  :style="{ 'max-height': pathwaysMaxHeight + 'px' }"
222
- v-if="pathControls"
223
344
  v-popover:checkBoxPopover
224
345
  >
225
346
  <svg-legends v-if="!isFC" class="svg-legends-container" />
@@ -350,7 +471,14 @@
350
471
  virtual-triggering
351
472
  >
352
473
  <el-row v-for="item in openMapOptions" :key="item.key">
353
- <el-button type="primary" plain @click="$emit('open-map', item.key)">
474
+ <el-button type="primary" plain
475
+ @click="/**
476
+ * This event is emitted when the user chooses a different map option
477
+ * from ``openMapOptions`` props.
478
+ * @arg mapOption.key
479
+ * */
480
+ $emit('open-map', item.key)"
481
+ >
354
482
  {{ item.display }}
355
483
  </el-button>
356
484
  </el-row>
@@ -362,7 +490,7 @@
362
490
  width="200"
363
491
  :teleported="false"
364
492
  trigger="click"
365
- popper-class="background-popper"
493
+ popper-class="background-popper h-auto"
366
494
  virtual-triggering
367
495
  >
368
496
  <div>
@@ -376,8 +504,8 @@
376
504
  popper-class="flatmap_dropdown"
377
505
  >
378
506
  <el-option
379
- v-for="item in viewingModes"
380
- :key="item"
507
+ v-for="(item, i) in viewingModes"
508
+ :key="item + i"
381
509
  :label="item"
382
510
  :value="item"
383
511
  >
@@ -387,6 +515,64 @@
387
515
  </el-option>
388
516
  </el-select>
389
517
  </el-row>
518
+ <template v-if="viewingMode === 'Annotation' && userInformation">
519
+ <el-row class="backgroundText">Drawn By*</el-row>
520
+ <el-row class="backgroundControl">
521
+ <el-select
522
+ :teleported="false"
523
+ v-model="drawnType"
524
+ placeholder="Select"
525
+ class="select-box"
526
+ popper-class="flatmap_dropdown"
527
+ @change="setDrawnType"
528
+ >
529
+ <el-option
530
+ v-for="item in drawnTypes"
531
+ :key="item"
532
+ :label="item"
533
+ :value="item"
534
+ >
535
+ <el-row>
536
+ <el-col :span="12">{{ item }}</el-col>
537
+ </el-row>
538
+ </el-option>
539
+ </el-select>
540
+ </el-row>
541
+ <el-row class="backgroundText">Annotated By*</el-row>
542
+ <el-row class="backgroundControl">
543
+ <el-select
544
+ :teleported="false"
545
+ v-model="annotatedType"
546
+ placeholder="Select"
547
+ class="select-box"
548
+ popper-class="flatmap_dropdown"
549
+ @change="setAnnotatedType"
550
+ >
551
+ <el-option
552
+ v-for="item in annotatedTypes"
553
+ :key="item"
554
+ :label="item"
555
+ :value="item"
556
+ >
557
+ <el-row>
558
+ <el-col :span="12">{{ item }}</el-col>
559
+ </el-row>
560
+ </el-option>
561
+ </el-select>
562
+ </el-row>
563
+ </template>
564
+ <el-row class="backgroundSpacer" v-if="displayFlightPathOption"></el-row>
565
+ <el-row class="backgroundText" v-if="displayFlightPathOption">Flight path display</el-row>
566
+ <el-row class="backgroundControl" v-if="displayFlightPathOption">
567
+ <el-radio-group
568
+ v-model="flightPath3DRadio"
569
+ class="flatmap-radio"
570
+ @change="setFlightPath3D"
571
+ >
572
+ <el-radio :label="false">2D</el-radio>
573
+ <el-radio :label="true">3D</el-radio>
574
+ </el-radio-group>
575
+ </el-row>
390
576
  <el-row class="backgroundSpacer"></el-row>
391
577
  <el-row class="backgroundText">Organs display</el-row>
392
578
  <el-row class="backgroundControl">
@@ -480,23 +666,37 @@
480
666
  :annotationEntry="annotationEntry"
481
667
  :entry="tooltipEntry"
482
668
  :annotationDisplay="viewingMode === 'Annotation'"
669
+ @annotation="commitAnnotationEvent"
670
+ />
671
+ <RelevanceDialog
672
+ class="relevance-dialog"
673
+ v-show="relevanceDisplay"
674
+ :entry="relevanceEntry"
675
+ :drawing="inDrawing"
676
+ :relevance="relevance"
677
+ @display="relevanceDialogPopup"
678
+ @confirm="confirmDrawnFeature"
679
+ @cancel="cancelDrawnFeature"
680
+ @popup="closePopup"
681
+ @tooltip="displayRelevantFeatureTooltip"
483
682
  />
484
683
  </div>
485
684
  </div>
486
685
  </template>
487
686
 
488
687
  <script>
489
- import { shallowRef } from 'vue'
688
+ /* eslint-disable no-alert, no-console */
689
+ import { shallowRef, markRaw } from 'vue'
490
690
  import {
491
691
  WarningFilled as ElIconWarningFilled,
492
692
  ArrowDown as ElIconArrowDown,
493
693
  ArrowLeft as ElIconArrowLeft,
494
694
  } from '@element-plus/icons-vue'
495
- /* eslint-disable no-alert, no-console */
496
695
  import Tooltip from './Tooltip.vue'
497
696
  import SelectionsGroup from './SelectionsGroup.vue'
498
697
  import TreeControls from './TreeControls.vue'
499
698
  import { MapSvgIcon, MapSvgSpriteColor } from '@abi-software/svg-sprite'
699
+ import '@abi-software/svg-sprite/dist/style.css'
500
700
  import SvgLegends from './legends/SvgLegends.vue'
501
701
  import {
502
702
  ElButton as Button,
@@ -506,6 +706,7 @@ import {
506
706
  ElRadioGroup as RadioGroup,
507
707
  ElRow as Row,
508
708
  ElSelect as Select,
709
+ ElDialog as Dialog,
509
710
  } from 'element-plus'
510
711
  import flatmapMarker from '../icons/flatmap-marker'
511
712
  import {
@@ -515,7 +716,82 @@ import {
515
716
  import yellowstar from '../icons/yellowstar'
516
717
  import ResizeSensor from 'css-element-queries/src/ResizeSensor'
517
718
  import * as flatmap from '@abi-software/flatmap-viewer'
719
+ import { AnnotationService } from '@abi-software/sparc-annotation'
720
+ import RelevanceDialog from './RelevanceDialog.vue'
721
+ import { mapState } from 'pinia'
722
+ import { useMainStore } from '@/store/index'
723
+
724
+ /**
725
+ * @param scopeElement Draggable scope area (Optional)
726
+ * @param dragElement Draggable element
727
+ */
728
+ const draggable = (scopeElement, dragElement) => {
729
+ let startX, startY, clickX, clickY, posX, posY
730
+ // reset position in case previous pupped up dialog is dragged
731
+ dragElement.style.left = ''
732
+ dragElement.style.top = ''
733
+ // const scopeRect = scopeElement.getBoundingClientRect()
734
+ // const dragRect = dragElement.getBoundingClientRect()
735
+
736
+ dragElement.addEventListener('mousedown', (e) => {
737
+ e.preventDefault();
738
+ startX = dragElement.offsetLeft
739
+ startY = dragElement.offsetTop
740
+ clickX = e.clientX
741
+ clickY = e.clientY
742
+
743
+ dragElement.addEventListener('mousemove', drag, false);
744
+ document.addEventListener('mouseup', () => {
745
+ dragElement.removeEventListener('mousemove', drag, false);
746
+ }, false);
747
+ }, false);
748
+
749
+ function drag(e) {
750
+ e.preventDefault();
751
+ posX = startX - (clickX - e.clientX)
752
+ posY = startY - (clickY - e.clientY)
753
+ // if (
754
+ // (posX > scopeRect.left && ((posX + dragRect.width) < scopeRect.right)) &&
755
+ // (posY > scopeRect.top && ((posY + dragRect.height) < scopeRect.bottom))
756
+ // ) {
757
+ dragElement.style.left = `${posX}px`;
758
+ dragElement.style.top = `${posY}px`;
759
+ // } else {
760
+ // if (posX <= scopeRect.left) {
761
+ // dragElement.style.left = '0px';
762
+ // } else if (posX + dragRect.width >= scopeRect.right) {
763
+ // dragElement.style.left = `${scopeRect.right - dragRect.width}px`;
764
+ // }
765
+ // if (posY <= scopeRect.top) {
766
+ // dragElement.style.top = '0px';
767
+ // } else if (posY + dragRect.height >= scopeRect.bottom) {
768
+ // dragElement.style.top = `${scopeRect.bottom - dragRect.height}px`;
769
+ // }
770
+ // }
771
+ }
772
+ }
518
773
 
774
+ const centroid = (geometry) => {
775
+ let featureGeometry = { lng: 0, lat: 0, }
776
+ let coordinates
777
+ if (geometry.type === "Polygon") {
778
+ coordinates = geometry.coordinates[0]
779
+ } else {
780
+ coordinates = geometry.coordinates
781
+ }
782
+ if (!(geometry.type === 'Point')) {
783
+ coordinates.map((coor) => {
784
+ featureGeometry.lng += parseFloat(coor[0])
785
+ featureGeometry.lat += parseFloat(coor[1])
786
+ })
787
+ featureGeometry.lng = featureGeometry.lng / coordinates.length
788
+ featureGeometry.lat = featureGeometry.lat / coordinates.length
789
+ } else {
790
+ featureGeometry.lng += parseFloat(coordinates[0])
791
+ featureGeometry.lat += parseFloat(coordinates[1])
792
+ }
793
+ return featureGeometry
794
+ }
519
795
 
520
796
  const processFTUs = (parent, key) => {
521
797
  const ftus = []
@@ -577,6 +853,9 @@ const createUnfilledTooltipData = function () {
577
853
  }
578
854
  }
579
855
 
856
+ /**
857
+ * A vue component of the flatmap viewer.
858
+ */
580
859
  export default {
581
860
  name: 'FlatmapVuer',
582
861
  components: {
@@ -587,6 +866,7 @@ export default {
587
866
  RadioGroup,
588
867
  Row,
589
868
  Select,
869
+ Dialog,
590
870
  MapSvgIcon,
591
871
  MapSvgSpriteColor,
592
872
  Tooltip,
@@ -605,7 +885,247 @@ export default {
605
885
  //resolve this issue.
606
886
  this.setStateRequired = false
607
887
  },
888
+ setup(props) {
889
+ const annotator = markRaw(new AnnotationService(`${props.flatmapAPI}annotator`));
890
+ return { annotator }
891
+ },
608
892
  methods: {
893
+ // This should be called when create is confirmed or cancelled
894
+ initialiseDrawing: function () {
895
+ this.inDrawing = false
896
+ this.initialiseDialog()
897
+ this.activeDrawTool = undefined
898
+ this.createdEvent = undefined
899
+ },
900
+ cancelDrawnFeature: function () {
901
+ if (this.createdEvent) {
902
+ this.closePopup()
903
+ this.annotationEntry = {
904
+ ...this.createdEvent.feature,
905
+ resourceId: this.serverURL,
906
+ }
907
+ this.rollbackAnnotationEvent()
908
+ this.initialiseDrawing()
909
+ }
910
+ },
911
+ displayRelevantFeatureTooltip: function (id) {
912
+ if (this.mapImp) {
913
+ const data = this.mapImp.featureProperties(id)
914
+ this.checkAndCreatePopups({ feature: data })
915
+ }
916
+ },
917
+ confirmDrawnFeature: function () {
918
+ if (this.createdEvent) {
919
+ this.checkAndCreatePopups(this.createdEvent)
920
+ // Add relevance if exist to annotationEntry
921
+ // Relevance will only be added in creating new drawn feature annotation
922
+ // And will not be updated if move drawn features
923
+ if (Object.keys(this.relevanceEntry).length > 0) {
924
+ this.annotationEntry.feature.relevance = this.relevanceEntry
925
+ }
926
+ this.initialiseDrawing()
927
+ }
928
+ },
929
+ initialiseDialog: function () {
930
+ this.relevanceDisplay = false
931
+ this.relevanceEntry = {}
932
+ },
933
+ relevanceDialogPopup: function () {
934
+ const inactive = this.$el.querySelector('.drawRelevance').classList.contains('inactive')
935
+ // disable click popup if icon inactive or in drawing
936
+ if (!inactive && !this.inDrawing) {
937
+ this.closePopup()
938
+ this.relevanceDisplay = !this.relevanceDisplay
939
+ }
940
+ },
941
+ drawingEvent: function (type) {
942
+ this.closePopup()
943
+ // disable mode icon click if any tool is active
944
+ if (this.drawnTypes.includes(type) && !this.activeDrawMode && !this.relevanceDisplay) {
945
+ if (type === 'Point') {
946
+ const point = this.$el.querySelector('.mapbox-gl-draw_point')
947
+ this.$el.querySelector('.mapbox-gl-draw_point').click()
948
+ this.activeDrawTool = point.classList.contains('active') ? 'Point' : undefined
949
+ } else if (type === 'LineString') {
950
+ const line = this.$el.querySelector('.mapbox-gl-draw_line')
951
+ this.$el.querySelector('.mapbox-gl-draw_line').click()
952
+ this.activeDrawTool = line.classList.contains('active') ? 'LineString' : undefined
953
+ } else if (type === 'Polygon') {
954
+ const polygon = this.$el.querySelector('.mapbox-gl-draw_polygon')
955
+ this.$el.querySelector('.mapbox-gl-draw_polygon').click()
956
+ this.activeDrawTool = polygon.classList.contains('active') ? 'Polygon' : undefined
957
+ }
958
+ // disable tool icon click if any mode is on
959
+ } else if (this.drawModes.includes(type) && !this.activeDrawTool) {
960
+ if (type === 'Delete') {
961
+ if (
962
+ this.currentDrawnFeature &&
963
+ // For either no mode is on or edit is on
964
+ (!this.activeDrawMode || this.activeDrawMode === 'Edit')
965
+ ) {
966
+ // Force simple_select a feature for delete event
967
+ this.doubleClickedFeature = false
968
+ this.changeAnnotationDrawMode({
969
+ mode: 'simple_select',
970
+ options: { featureIds: [this.currentDrawnFeature.id] }
971
+ })
972
+ this.deleteOrEditAnnotationFeature()
973
+ }
974
+ this.activeDrawMode = this.activeDrawMode === 'Delete' ? undefined : 'Delete'
975
+ // clear currentDrawnFeature when quit delete mode
976
+ if (!this.activeDrawMode) {
977
+ this.currentDrawnFeature = undefined
978
+ }
979
+ } else if (type === 'Edit') {
980
+ this.activeDrawMode = this.activeDrawMode === 'Edit' ? undefined : 'Edit'
981
+ }
982
+ }
983
+ },
984
+ changeAnnotationDrawMode: function (mode) {
985
+ if (this.mapImp) {
986
+ this.mapImp.changeAnnotationDrawMode(mode)
987
+ }
988
+ },
989
+ // Remove all drawn annotations from annotation layer
990
+ clearAnnotationFeature: function () {
991
+ if (
992
+ this.mapImp &&
993
+ this.drawnAnnotationFeatures &&
994
+ this.drawnAnnotationFeatures.length > 0
995
+ ) {
996
+ this.mapImp.clearAnnotationFeature()
997
+ }
998
+ },
999
+ deleteOrEditAnnotationFeature: function () {
1000
+ if (this.mapImp) {
1001
+ // Fire the 'trash' button
1002
+ // Not only use to remove features
1003
+ // 'simple_select' for DELETE and 'direct_select' for EDIT
1004
+ this.mapImp.removeAnnotationFeature()
1005
+ }
1006
+ },
1007
+ rollbackAnnotationEvent: function () {
1008
+ // For 'updated' and 'deleted' callback
1009
+ if (
1010
+ this.mapImp &&
1011
+ this.drawnAnnotationEvent.includes(this.annotationEntry.type)
1012
+ ) {
1013
+ this.mapImp.rollbackAnnotationEvent(this.annotationEntry)
1014
+ }
1015
+ },
1016
+ commitAnnotationEvent: function (annotation) {
1017
+ if (
1018
+ this.mapImp &&
1019
+ this.drawnAnnotationEvent.includes(this.annotationEntry.type) &&
1020
+ // Only when annotation comments stored successfully
1021
+ annotation
1022
+ ) {
1023
+ this.annotationSubmitted = true
1024
+ this.mapImp.commitAnnotationEvent(this.annotationEntry)
1025
+ if (this.annotationEntry.type === 'deleted') {
1026
+ this.closePopup()
1027
+ } else {
1028
+ // Use to update 'this.drawnAnnotationFeatures' when created or updated
1029
+ this.addAnnotationFeature()
1030
+ }
1031
+ }
1032
+ },
1033
+ setFeatureAnnotated: function () {
1034
+ if (this.mapImp) {
1035
+ this.annotator.annotatedItemIds(this.userToken, this.serverURL)
1036
+ .then((annotatedItemIds) => {
1037
+ for (const id of annotatedItemIds) {
1038
+ this.mapImp.setFeatureAnnotated(id)
1039
+ }
1040
+ })
1041
+ .catch((reason) => {
1042
+ console.log(reason) // Error!
1043
+ })
1044
+ }
1045
+ },
1046
+ addAnnotationFeature: function () {
1047
+ if (this.mapImp) {
1048
+ if (!this.annotationSubmitted) this.clearAnnotationFeature()
1049
+ if (this.drawnType !== 'None') {
1050
+ if (!this.annotationSubmitted) this.loading = true
1051
+ this.annotator.drawnFeatures(this.userToken, this.serverURL)
1052
+ .then((drawnFeatures) => {
1053
+ // Use to switch the displayed feature type
1054
+ if (this.drawnType !== 'All tools') {
1055
+ drawnFeatures = drawnFeatures.filter((feature) => {
1056
+ return feature.geometry.type === this.drawnType
1057
+ })
1058
+ }
1059
+ this.drawnAnnotationFeatures = drawnFeatures
1060
+ this.loading = false
1061
+ // No need to call 'addAnnotationFeature' when a new feature created
1062
+ if (!this.annotationSubmitted) {
1063
+ for (const feature of drawnFeatures) {
1064
+ if (this.annotatedType !== 'Anyone') {
1065
+ this.annotator
1066
+ .itemAnnotations(this.userToken, this.serverURL, feature.id)
1067
+ .then((value) => {
1068
+ let participated = value.filter((v) => {
1069
+ return (
1070
+ v.creator.name === this.userInformation.name &&
1071
+ v.creator.email === this.userInformation.email
1072
+ )
1073
+ }).length > 0
1074
+ if (
1075
+ (this.annotatedType === 'Me' && participated) ||
1076
+ (this.annotatedType === 'Others' && !participated)
1077
+ ) {
1078
+ this.mapImp.addAnnotationFeature(feature)
1079
+ }
1080
+ })
1081
+ .catch((reason) => {
1082
+ console.log(reason) // Error!
1083
+ })
1084
+ } else this.mapImp.addAnnotationFeature(feature)
1085
+ }
1086
+ }
1087
+ })
1088
+ .catch((reason) => {
1089
+ console.log(reason) // Error!
1090
+ })
1091
+ }
1092
+ }
1093
+ },
1094
+ showAnnotator: function (flag) {
1095
+ if (this.mapImp) {
1096
+ // Control the show/hide of the drawn annotations
1097
+ this.mapImp.showAnnotator(flag)
1098
+ // Hide default toolbar, we will use customised SVG icons instead
1099
+ this.$el.querySelector('.maplibregl-ctrl-group').style.display = 'none'
1100
+ }
1101
+ },
1102
+ setDrawnType: function (flag) {
1103
+ this.drawnType = flag
1104
+ if (this.mapImp) {
1105
+ this.addAnnotationFeature()
1106
+ }
1107
+ },
1108
+ setAnnotatedType: function (flag) {
1109
+ this.annotatedType = flag
1110
+ if (this.mapImp) {
1111
+ this.addAnnotationFeature()
1112
+ }
1113
+ },
1114
+ /**
1115
+ * @vuese
1116
+ * Function to switch from 2D to 3D
1117
+ * @arg flag
1118
+ */
1119
+ setFlightPath3D: function (flag) {
1120
+ this.flightPath3DRadio = flag
1121
+ if (this.mapImp) {
1122
+ this.mapImp.enableFlightPaths(flag)
1123
+ }
1124
+ },
1125
+ /**
1126
+ * @vuese
1127
+ * Function to view the latest map (example when you are on legacy map).
1128
+ */
609
1129
  viewLatestMap: function () {
610
1130
  let biologicalSex = this.biologicalSex ? this.biologicalSex : undefined
611
1131
  //Human requires special handling
@@ -617,14 +1137,28 @@ export default {
617
1137
  biologicalSex,
618
1138
  viewport: this.mapImp.getState(),
619
1139
  }
1140
+ /**
1141
+ * The event emitted by ``viewLatestMap`` method.
1142
+ */
620
1143
  this.$emit('view-latest-map', state)
621
1144
  },
1145
+ /**
1146
+ * @vuese
1147
+ * Function to change the background colour of the map
1148
+ * by providing the ``colour``.
1149
+ * @arg colour
1150
+ */
622
1151
  backgroundChangeCallback: function (colour) {
623
1152
  this.currentBackground = colour
624
1153
  if (this.mapImp) {
625
1154
  this.mapImp.setBackgroundColour(this.currentBackground, 1)
626
1155
  }
627
1156
  },
1157
+ /**
1158
+ * @vuese
1159
+ * Function to process a list of a FC flatmap's systems.
1160
+ * @arg systems
1161
+ */
628
1162
  processSystems: function (systems) {
629
1163
  this.systems.length = 0
630
1164
  if (systems && systems.length > 0) {
@@ -644,6 +1178,13 @@ export default {
644
1178
  this.systems.push(data)
645
1179
  }
646
1180
  },
1181
+ /**
1182
+ * @vuese
1183
+ * Function to add taxon identifiers into the taxon connectivity array,
1184
+ * by retrieving their corresponding labels using the flatmap API.
1185
+ * @arg flatmapAPI,
1186
+ * @arg taxonIdentifiers
1187
+ */
647
1188
  processTaxon: function (flatmapAPI, taxonIdentifiers) {
648
1189
  this.taxonConnectivity.length = 0
649
1190
  taxonIdentifiers.forEach((taxon) => {
@@ -653,11 +1194,18 @@ export default {
653
1194
  })
654
1195
  })
655
1196
  },
1197
+ /**
1198
+ * @vuese
1199
+ * Function to show or hide the display of the bottom-left drawer container.
1200
+ */
656
1201
  toggleDrawer: function () {
657
1202
  this.drawerOpen = !this.drawerOpen
658
1203
  },
659
1204
  /**
1205
+ * @vuese
660
1206
  * Function to toggle colour/greyscale of organs.
1207
+ * The parameter ``flag`` is a boolean, ``true`` (colour) and ``false`` (greyscale).
1208
+ * @arg flag
661
1209
  */
662
1210
  setColour: function (flag) {
663
1211
  this.colourRadio = flag
@@ -666,7 +1214,10 @@ export default {
666
1214
  }
667
1215
  },
668
1216
  /**
1217
+ * @vuese
669
1218
  * Function to toggle outlines f organs.
1219
+ * The parameter ``flag`` is a boolean, ``true`` to show outlines, ``false`` to hide outlines.
1220
+ * @arg flag
670
1221
  */
671
1222
  setOutlines: function (flag) {
672
1223
  this.outlineRadio = flag
@@ -675,6 +1226,7 @@ export default {
675
1226
  }
676
1227
  },
677
1228
  /**
1229
+ * @vuese
678
1230
  * Function to toggle paths to default.
679
1231
  * Also called when the associated button is pressed.
680
1232
  */
@@ -699,6 +1251,7 @@ export default {
699
1251
  }
700
1252
  },
701
1253
  /**
1254
+ * @vuese
702
1255
  * Function to zoom in.
703
1256
  * Also called when the associated button is pressed.
704
1257
  */
@@ -708,6 +1261,7 @@ export default {
708
1261
  }
709
1262
  },
710
1263
  /**
1264
+ * @vuese
711
1265
  * Function to zoom out.
712
1266
  * Also called when the associated button is pressed.
713
1267
  */
@@ -716,16 +1270,34 @@ export default {
716
1270
  this.mapImp.zoomOut()
717
1271
  }
718
1272
  },
1273
+ /**
1274
+ * @vuese
1275
+ * Function to show or hide centrelines and nodes.
1276
+ * The parameter ``payload`` is an object with a boolean property, ``value``,
1277
+ * ``payload.value = true/false``.
1278
+ * @arg payload
1279
+ */
719
1280
  centreLinesSelected: function (payload) {
720
1281
  if (this.mapImp) {
721
1282
  this.mapImp.enableCentrelines(payload.value)
722
1283
  }
723
1284
  },
1285
+ /**
1286
+ * // Currently not in use
1287
+ * Function to show or hide paths valid in SCKAN
1288
+ * by providing ``{key, value}`` pair in ``payload``.
1289
+ * @arg payload
1290
+ */
724
1291
  sckanSelected: function (payload) {
725
1292
  if (this.mapImp) {
726
1293
  this.mapImp.enableSckanPath(payload.key, payload.value)
727
1294
  }
728
1295
  },
1296
+ /**
1297
+ * // Currently not in use
1298
+ * Function to show or hide all paths valid in SCKAN.
1299
+ * @arg payload
1300
+ */
729
1301
  checkAllSCKAN: function (payload) {
730
1302
  if (this.mapImp) {
731
1303
  payload.keys.forEach((key) =>
@@ -733,6 +1305,12 @@ export default {
733
1305
  )
734
1306
  }
735
1307
  },
1308
+ /**
1309
+ * @vuese
1310
+ * Function to highlight the connected paths
1311
+ * by providing path model identifier, ``pathId``.
1312
+ * @arg pathId
1313
+ */
736
1314
  highlightConnectedPaths: function (payload) {
737
1315
  if (this.mapImp) {
738
1316
  let paths = [...this.mapImp.pathModelNodes(payload)]
@@ -749,11 +1327,23 @@ export default {
749
1327
  this.mapImp.zoomToFeatures(toHighlight, { noZoomIn: true })
750
1328
  }
751
1329
  },
1330
+ /**
1331
+ * @vuese
1332
+ * Function to enable/disable (show/hide) the system
1333
+ * by providing ``kay, value`` ``payload`` object ``{systemId, true/false}``.
1334
+ * @arg payload
1335
+ */
752
1336
  systemSelected: function (payload) {
753
1337
  if (this.mapImp) {
754
1338
  this.mapImp.enableSystem(payload.key, payload.value)
755
1339
  }
756
1340
  },
1341
+ /**
1342
+ * @vuese
1343
+ * Function to enable/disable (show/hide) all systems
1344
+ * by providing ``flag`` (true/false).
1345
+ * @arg flag
1346
+ */
757
1347
  checkAllSystems: function (flag) {
758
1348
  if (this.mapImp) {
759
1349
  this.systems[0].children.forEach((key) =>
@@ -761,14 +1351,31 @@ export default {
761
1351
  )
762
1352
  }
763
1353
  },
1354
+ /**
1355
+ * @vuese
1356
+ * Function to display features with annotation matching the provided term.
1357
+ * @arg models
1358
+ */
764
1359
  ftuSelected: function (models) {
765
1360
  this.searchAndShowResult(models, true)
766
1361
  },
1362
+ /**
1363
+ * @vuese
1364
+ * Function to show or hide the layer
1365
+ * by providing ``{layerId, true/false}`` in ``payload``.
1366
+ * @arg payload
1367
+ */
767
1368
  layersSelected: function (payload) {
768
1369
  if (this.mapImp) {
769
1370
  this.mapImp.enableLayer(payload.key, payload.value)
770
1371
  }
771
1372
  },
1373
+ /**
1374
+ * @vuese
1375
+ * Function to show or hide all layers
1376
+ * by providing ``payload`` with ``payload.keys`` array and ``payload.value`` flag.
1377
+ * @arg payload
1378
+ */
772
1379
  checkAllLayers: function (payload) {
773
1380
  if (this.mapImp) {
774
1381
  payload.keys.forEach((key) =>
@@ -776,11 +1383,23 @@ export default {
776
1383
  )
777
1384
  }
778
1385
  },
1386
+ /**
1387
+ * @vuese
1388
+ * Function to show or hide connectivity features observed in particular species
1389
+ * by providing ``{taxonId, true/false}`` in ``payload.key, payload.value``.
1390
+ * @arg payload
1391
+ */
779
1392
  taxonsSelected: function (payload) {
780
1393
  if (this.mapImp) {
781
1394
  this.mapImp.enableConnectivityByTaxonIds(payload.key, payload.value)
782
1395
  }
783
1396
  },
1397
+ /**
1398
+ * @vuese
1399
+ * Function to show or hide connectivity features observed in particular species
1400
+ * by providing ``payload`` with ``payload.keys`` array and ``payload.value`` flag.
1401
+ * @arg payload
1402
+ */
784
1403
  checkAllTaxons: function (payload) {
785
1404
  if (this.mapImp) {
786
1405
  payload.keys.forEach((key) =>
@@ -788,11 +1407,23 @@ export default {
788
1407
  )
789
1408
  }
790
1409
  },
1410
+ /**
1411
+ * @vuese
1412
+ * Function to hide or show paths of a given type
1413
+ * by providing ``{pathType, true/false}`` in ``payload.key, payload.value``.
1414
+ * @arg payload
1415
+ */
791
1416
  pathwaysSelected: function (payload) {
792
1417
  if (this.mapImp) {
793
1418
  this.mapImp.enablePath(payload.key, payload.value)
794
1419
  }
795
1420
  },
1421
+ /**
1422
+ * @vuese
1423
+ * Function to hide or show paths of a given type
1424
+ * by providing ``payload`` with ``payload.keys`` array and ``payload.value`` flag.
1425
+ * @arg payload
1426
+ */
796
1427
  checkAllPathways: function (payload) {
797
1428
  if (this.mapImp) {
798
1429
  payload.keys.forEach((key) =>
@@ -800,65 +1431,284 @@ export default {
800
1431
  )
801
1432
  }
802
1433
  },
1434
+ /**
1435
+ * @vuese
1436
+ * Function to generate callbacks as a result of panning/zooming the map.
1437
+ * ``flag`` (boolean) - generate callbacks when ``true``, otherwise disable them.
1438
+ * @arg flag
1439
+ */
803
1440
  enablePanZoomEvents: function (flag) {
804
1441
  this.mapImp.enablePanZoomEvents(flag)
805
1442
  },
1443
+ /**
1444
+ * @vuese
1445
+ * A callback function, invoked when events occur with the map.
1446
+ * The first parameter gives the type of event, the second provides details about the event.
1447
+ * _(This is the ``callback`` function from ``MapManager.loadMap()``)_.
1448
+ */
806
1449
  eventCallback: function () {
807
1450
  return (eventType, data, ...args) => {
808
- if (eventType !== 'pan-zoom') {
809
- const label = data.label
810
- const resource = [data.models]
811
- const taxonomy = this.entry
812
- const biologicalSex = this.biologicalSex
1451
+ if (eventType === 'annotation') {
813
1452
  const payload = {
814
- dataset: data.dataset,
815
- biologicalSex: biologicalSex,
816
- taxonomy: taxonomy,
817
- resource: resource,
818
- label: label,
819
1453
  feature: data,
820
1454
  userData: args,
821
1455
  eventType: eventType,
822
- provenanceTaxonomy: data.taxons
823
- ? JSON.parse(data.taxons)
824
- : undefined,
825
1456
  }
826
- if (eventType === 'click') {
827
- if (this.viewingMode === 'Network Discovery') {
828
- this.highlightConnectedPaths([data.models])
1457
+ // Popup closed will trigger aborted event
1458
+ if (data.type === 'aborted') {
1459
+ // Rollback drawing when no new annotation submitted
1460
+ if (!this.annotationSubmitted) this.rollbackAnnotationEvent()
1461
+ else this.annotationSubmitted = false
1462
+ } else if (data.type === 'modeChanged') {
1463
+ // 'modeChanged' event is before 'created' event
1464
+ if (data.feature.mode.startsWith('draw_')) {
1465
+ // Reset data entry for every draw
1466
+ this.initialiseDialog()
1467
+ this.inDrawing = true
1468
+ } else if (data.feature.mode === 'simple_select' && this.inDrawing) {
1469
+ if (this.createdEvent) {
1470
+ this.relevanceDisplay = true
1471
+ } else {
1472
+ // Reset if a invalid draw
1473
+ this.initialiseDrawing()
1474
+ }
1475
+ } else if (data.feature.mode === 'direct_select') {
1476
+ this.doubleClickedFeature = true
1477
+ }
1478
+ } else if (data.type === 'selectionChanged') {
1479
+ this.currentDrawnFeature =
1480
+ data.feature.features.length === 0 ?
1481
+ undefined :
1482
+ data.feature.features[0]
1483
+ payload.feature.feature = this.currentDrawnFeature
1484
+ if (!this.inDrawing) {
1485
+ this.initialiseDialog()
1486
+ // For exist drawn annotation features
1487
+ if (this.currentDrawnFeature) {
1488
+ let feature = this.drawnAnnotationFeatures
1489
+ .filter((feature) => feature.id === this.currentDrawnFeature.id)[0]
1490
+ if (feature && feature.relevance) {
1491
+ this.relevanceEntry = feature.relevance
1492
+ }
1493
+ this.drawModeEvent(payload)
1494
+ }
1495
+ }
1496
+ } else {
1497
+ if (data.type === 'created' || data.type === 'updated') {
1498
+ if (data.type === 'updated' && data.feature.action) {
1499
+ data.positionUpdated = data.feature.action === 'move'
1500
+ }
1501
+ const feature = this.mapImp.refreshAnnotationFeatureGeometry(data.feature)
1502
+ payload.feature.feature = feature
1503
+ // NB. this might now be `null` if user has deleted it (before OK/Submit)
1504
+ // so maybe then no `service.addAnnotation` ??
1505
+ }
1506
+ // Once double click mouse to confirm drawing, 'aborted' event will be triggered.
1507
+ // Hence disable direct popup when 'created' event, dialog will be used instead.
1508
+ if (data.type === 'created') {
1509
+ this.createdEvent = payload
829
1510
  } else {
830
- this.currentActive = data.models ? data.models : ''
1511
+ this.checkAndCreatePopups(payload)
831
1512
  }
832
- } else if (
833
- eventType === 'mouseenter' &&
834
- !(this.viewingMode === 'Network Discovery')
835
- ) {
836
- this.currentHover = data.models ? data.models : ''
837
1513
  }
838
- if (
839
- data &&
840
- data.type !== 'marker' &&
841
- eventType === 'click' &&
842
- !(this.viewingMode === 'Network Discovery')
843
- ) {
844
- this.checkAndCreatePopups(payload)
1514
+ } else {
1515
+ if (eventType !== 'pan-zoom') {
1516
+ const label = data.label
1517
+ const resource = [data.models]
1518
+ const taxonomy = this.entry
1519
+ const biologicalSex = this.biologicalSex
1520
+ let taxons = undefined
1521
+ if (data.taxons) {
1522
+ // check if data.taxons is string or array
1523
+ if (typeof data.taxons !== 'object') {
1524
+ taxons = JSON.parse(data.taxons)
1525
+ } else {
1526
+ taxons = data.taxons
1527
+ }
1528
+ }
1529
+ const payload = {
1530
+ dataset: data.dataset,
1531
+ biologicalSex: biologicalSex,
1532
+ taxonomy: taxonomy,
1533
+ resource: resource,
1534
+ label: label,
1535
+ feature: data,
1536
+ userData: args,
1537
+ eventType: eventType,
1538
+ provenanceTaxonomy: taxons,
1539
+ }
1540
+ if (eventType === 'click') {
1541
+ if (this.viewingMode === 'Network Discovery') {
1542
+ this.highlightConnectedPaths([data.models])
1543
+ } else {
1544
+ this.currentActive = data.models ? data.models : ''
1545
+ // Stop adding features if dialog displayed
1546
+ if (this.inDrawing && !this.relevanceDisplay) {
1547
+ // Only clicked relevance data will be added
1548
+ let relevant = data.label ? data.label : `*${data.id}`
1549
+ // only the linestring will have relevance at the current stage
1550
+ if (relevant && this.activeDrawTool === 'LineString') {
1551
+ this.relevanceEntry[relevant] = data.featureId
1552
+ }
1553
+ }
1554
+ }
1555
+ } else if (
1556
+ eventType === 'mouseenter' &&
1557
+ !(this.viewingMode === 'Network Discovery')
1558
+ ) {
1559
+ this.currentHover = data.models ? data.models : ''
1560
+ }
1561
+ if (
1562
+ data &&
1563
+ data.type !== 'marker' &&
1564
+ eventType === 'click' &&
1565
+ !(this.viewingMode === 'Network Discovery') &&
1566
+ // Disable popup when drawing
1567
+ !this.inDrawing
1568
+ ) {
1569
+ this.checkAndCreatePopups(payload)
1570
+ }
1571
+ this.$emit('resource-selected', payload)
1572
+ } else {
1573
+ this.$emit('pan-zoom-callback', data)
1574
+ }
1575
+ }
1576
+ }
1577
+ },
1578
+ // for dialog popup
1579
+ dialogCssHacks: function () {
1580
+ this.$nextTick(() => {
1581
+ const dialog = this.$el.querySelector('.relevance-dialog')
1582
+ draggable(this.$el, dialog)
1583
+ // dialog popup at the click position
1584
+ // slightly change x or y if close to boundary
1585
+ let posX, posY
1586
+ const containerRect = this.$el.getBoundingClientRect()
1587
+ const dialogRect = dialog.getBoundingClientRect()
1588
+ if (this.dialogPosition.x > containerRect.width / 2) {
1589
+ posX = this.dialogPosition.x - dialogRect.width
1590
+ } else {
1591
+ posX = this.dialogPosition.x
1592
+ }
1593
+ if (this.dialogPosition.y > containerRect.height / 2) {
1594
+ posY = this.dialogPosition.y - dialogRect.height
1595
+ } else {
1596
+ posY = this.dialogPosition.y
1597
+ }
1598
+ dialog.style.transform =
1599
+ `translate(${posX - this.dialogPosition.offsetX}px, ${posY - this.dialogPosition.offsetY}px)`
1600
+ })
1601
+ },
1602
+ drawIconCssHacks: function () {
1603
+ // set tool/mode icon status
1604
+ if (this.$el.querySelector('.iconSelected') || !this.relevanceDisplay) {
1605
+ this.drawnTypes.map((t) => {
1606
+ const dtype = this.$el.querySelector(`.draw${t}`)
1607
+ if (dtype) {
1608
+ dtype.classList.remove('iconSelected');
1609
+ dtype.classList.remove('inactive');
1610
+ }
1611
+ })
1612
+ this.drawModes.map((m) => {
1613
+ this.$el.querySelector(`.draw${m}`).classList.remove('iconSelected');
1614
+ this.$el.querySelector(`.draw${m}`).classList.remove('inactive');
1615
+ })
1616
+ }
1617
+ if (this.activeDrawTool) {
1618
+ this.$el.querySelector(`.draw${this.activeDrawTool}`).classList.add('iconSelected');
1619
+ this.drawModes.map((m) => {
1620
+ this.$el.querySelector(`.draw${m}`).classList.add('inactive');
1621
+ })
1622
+ } else if (this.activeDrawMode || this.relevanceDisplay) {
1623
+ if (this.activeDrawMode) {
1624
+ this.$el.querySelector(`.draw${this.activeDrawMode}`).classList.add('iconSelected');
1625
+ }
1626
+ this.drawnTypes.map((t) => {
1627
+ const dtype = this.$el.querySelector(`.draw${t}`)
1628
+ if (dtype) dtype.classList.add('inactive');
1629
+ })
1630
+ }
1631
+ },
1632
+ // Fire either update or delete event
1633
+ drawModeEvent: function (data) {
1634
+ if (this.activeDrawMode) {
1635
+ // double click fires 'updated' callback
1636
+ if (this.doubleClickedFeature) {
1637
+ if (data.feature.feature.geometry.type !== 'Point') {
1638
+ // show tooltip and enter edit mode
1639
+ this.changeAnnotationDrawMode({
1640
+ mode: 'direct_select',
1641
+ options: { featureId: data.feature.feature.id }
1642
+ })
1643
+ this.deleteOrEditAnnotationFeature()
845
1644
  }
846
- this.$emit('resource-selected', payload)
1645
+ this.doubleClickedFeature = false
847
1646
  } else {
848
- this.$emit('pan-zoom-callback', data)
1647
+ // single click fires delete
1648
+ if (this.activeDrawMode === 'Delete') {
1649
+ this.changeAnnotationDrawMode({
1650
+ mode: 'simple_select',
1651
+ options: { featureIds: [data.feature.feature.id] }
1652
+ })
1653
+ this.deleteOrEditAnnotationFeature()
1654
+ }
849
1655
  }
850
1656
  }
851
1657
  },
852
1658
  // checkNeuronClicked shows a neuron path pop up if a path was recently clicked
1659
+ createConnectivityBody: function () {
1660
+ if (Object.keys(this.relevanceEntry).length > 0) {
1661
+ const featureIds = Object.values(this.relevanceEntry)
1662
+ const body = {
1663
+ type: 'connectivity',
1664
+ sourceId: featureIds[0],
1665
+ targetId: featureIds[featureIds.length - 1],
1666
+ intermediateIds: [],
1667
+ }
1668
+ if (featureIds.length > 2) {
1669
+ featureIds.slice(1, -1).forEach((id) => {
1670
+ body.intermediateIds.push(id)
1671
+ });
1672
+ }
1673
+ this.annotationEntry.body = body
1674
+ }
1675
+ },
1676
+ /**
1677
+ * @vuese
1678
+ * Function to create/display tooltips from the provided ``data``.
1679
+ * _checkNeuronClicked shows a neuron path pop up if a path was recently clicked._
1680
+ * @arg data
1681
+ */
853
1682
  checkAndCreatePopups: async function (data) {
854
1683
  // Call flatmap database to get the connection data
855
1684
  if (this.viewingMode === 'Annotation') {
856
- if (data.feature && data.feature.featureId && data.feature.models) {
1685
+ if (data.feature) {
857
1686
  this.annotationEntry = {
858
1687
  ...data.feature,
859
- resourceId: this.serverUUID,
1688
+ resourceId: this.serverURL,
1689
+ }
1690
+ if (data.feature.featureId && data.feature.models) {
1691
+ this.displayTooltip(data.feature.models)
1692
+ } else if (data.feature.feature) {
1693
+ if (this.inDrawing || this.activeDrawMode) {
1694
+ this.annotationSubmitted = false
1695
+ this.annotationEntry.featureId = data.feature.feature.id
1696
+ this.createConnectivityBody()
1697
+ this.displayTooltip(
1698
+ data.feature.feature.id,
1699
+ centroid(data.feature.feature.geometry)
1700
+ )
1701
+ } else {
1702
+ // Not allowed to update feature if not on edit mode
1703
+ if (data.feature.type === 'updated') {
1704
+ this.rollbackAnnotationEvent()
1705
+ }
1706
+ }
1707
+ // Hide dialog when updated or deleted event is fired and tooltip is displayed
1708
+ if (data.feature.type === 'updated' || data.feature.type === 'deleted') {
1709
+ this.initialiseDialog()
1710
+ }
860
1711
  }
861
- this.displayTooltip(data.feature.models)
862
1712
  } else {
863
1713
  this.annotation = {}
864
1714
  }
@@ -878,6 +1728,9 @@ export default {
878
1728
  }
879
1729
  }
880
1730
  },
1731
+ /**
1732
+ * A hack to remove flatmap tooltips while popup is open
1733
+ */
881
1734
  popUpCssHacks: function () {
882
1735
  // Below is a hack to remove flatmap tooltips while popup is open
883
1736
  let ftooltip = document.querySelector('.flatmap-tooltip-popup')
@@ -886,21 +1739,41 @@ export default {
886
1739
  'block'
887
1740
  this.$refs.tooltip.$el.style.display = 'flex'
888
1741
  document.querySelector('.maplibregl-popup-close-button').onclick = () => {
889
- document.querySelector('.flatmap-tooltip-popup').style.display = 'block'
1742
+ if (ftooltip) ftooltip.style.display = 'block'
890
1743
  }
891
1744
  },
1745
+ closePopup: function () {
1746
+ let cbutton = document.querySelector('.maplibregl-popup-close-button')
1747
+ if (cbutton) cbutton.click()
1748
+ },
1749
+ /**
1750
+ * @vuese
1751
+ * Function to close tooltip.
1752
+ */
892
1753
  closeTooltip: function () {
893
1754
  this.$refs.tooltip.$el.style.display = 'none'
894
1755
  document.querySelectorAll('.maplibregl-popup').forEach((item) => {
895
1756
  item.style.display = 'none'
896
1757
  })
897
1758
  },
1759
+ /**
1760
+ * @vuese
1761
+ * Function to create tooltip from Neuron Curation ``data``.
1762
+ * @arg data
1763
+ */
898
1764
  createTooltipFromNeuronCuration: async function (data) {
899
1765
  this.tooltipEntry = await this.flatmapQueries.createTooltipData(data)
900
1766
  this.displayTooltip(data.resource[0])
901
1767
  },
902
- // Keeping this as an API
1768
+ /**
1769
+ * @vuese
1770
+ * Function to show popup on map.
1771
+ * @arg featureId,
1772
+ * @arg node,
1773
+ * @arg options
1774
+ */
903
1775
  showPopup: function (featureId, node, options) {
1776
+ // Keeping this as an API
904
1777
  let myOptions = options
905
1778
  if (this.mapImp) {
906
1779
  if (myOptions) {
@@ -911,11 +1784,22 @@ export default {
911
1784
  this.mapImp.showPopup(featureId, node, myOptions)
912
1785
  }
913
1786
  },
1787
+ /**
1788
+ * @vuese
1789
+ * Function to show marker popup.
1790
+ * @arg featureId,
1791
+ * @arg node,
1792
+ * @arg options
1793
+ */
914
1794
  showMarkerPopup: function (featureId, node, options) {
915
1795
  if (this.mapImp) {
916
1796
  this.mapImp.showMarkerPopup(featureId, node, options)
917
1797
  }
918
1798
  },
1799
+ /**
1800
+ * @vuese
1801
+ * Function to close minimap.
1802
+ */
919
1803
  closeMinimap: function () {
920
1804
  let minimapEl = this.$refs.flatmapContainer.querySelector(
921
1805
  '.maplibregl-ctrl-minimap'
@@ -930,6 +1814,9 @@ export default {
930
1814
  }
931
1815
  this.minimapSmall = !this.minimapSmall
932
1816
  },
1817
+ /**
1818
+ * Function to add resize button to minimap.
1819
+ */
933
1820
  addResizeButtonToMinimap: function () {
934
1821
  let minimapEl = this.$refs.flatmapContainer.querySelector(
935
1822
  '.maplibregl-ctrl-minimap'
@@ -944,6 +1831,12 @@ export default {
944
1831
  this.minimapResizeShow = true
945
1832
  }
946
1833
  },
1834
+ /**
1835
+ * @vuese
1836
+ * Function to set help mode
1837
+ * by providing flag ``helpMode`` (true/false).
1838
+ * @arg helpMode
1839
+ */
947
1840
  setHelpMode: function (helpMode) {
948
1841
  if (helpMode) {
949
1842
  this.inHelp = true
@@ -959,6 +1852,12 @@ export default {
959
1852
  this.closeFlatmapHelpPopup()
960
1853
  }
961
1854
  },
1855
+ /**
1856
+ * @vuese
1857
+ * Function to show tooltip
1858
+ * by providing ``tooltipNumber``.
1859
+ * @arg tooltipNumber
1860
+ */
962
1861
  showToolitip: function (tooltipNumber) {
963
1862
  if (!this.inHelp) {
964
1863
  clearTimeout(this.tooltipWait[tooltipNumber])
@@ -967,6 +1866,12 @@ export default {
967
1866
  }, 500)
968
1867
  }
969
1868
  },
1869
+ /**
1870
+ * @vuese
1871
+ * Function to hide tooltip
1872
+ * by providing ``tooltipNumber``.
1873
+ * @arg tooltipNumber
1874
+ */
970
1875
  hideToolitip: function (tooltipNumber) {
971
1876
  if (!this.inHelp) {
972
1877
  clearTimeout(this.tooltipWait[tooltipNumber])
@@ -975,20 +1880,36 @@ export default {
975
1880
  }, 500)
976
1881
  }
977
1882
  },
978
- displayTooltip: function (feature) {
1883
+ /**
1884
+ * @vuese
1885
+ * Function to display tooltip
1886
+ * by providing featureId (``feature``).
1887
+ * @arg feature
1888
+ */
1889
+ displayTooltip: function (feature, geometry = undefined) {
979
1890
  this.tooltipDisplay = true
1891
+ let featureId = undefined
1892
+ let options = { className: 'flatmapvuer-popover' }
1893
+ if (geometry) {
1894
+ featureId = feature
1895
+ options.annotationFeatureGeometry = geometry
1896
+ } else {
1897
+ featureId = this.mapImp.modelFeatureIds(feature)[0]
1898
+ if (!this.inDrawing) {
1899
+ options.positionAtLastClick = true
1900
+ }
1901
+ }
980
1902
  if (!this.disableUI) {
981
- this.displayPopup(feature)
1903
+ this.$nextTick(() => {
1904
+ this.mapImp.showPopup(featureId, this.$refs.tooltip.$el, options)
1905
+ this.popUpCssHacks()
1906
+ })
982
1907
  }
983
1908
  },
984
- displayPopup: function (feature) {
985
- this.mapImp.showPopup(
986
- this.mapImp.modelFeatureIds(feature)[0],
987
- this.$refs.tooltip.$el,
988
- { className: 'flatmapvuer-popover', positionAtLastClick: true }
989
- )
990
- this.popUpCssHacks()
991
- },
1909
+ /**
1910
+ * @vuese
1911
+ * Function to open Flatmap Help Popup.
1912
+ */
992
1913
  openFlatmapHelpPopup: function () {
993
1914
  if (this.mapImp) {
994
1915
  let heartId = this.mapImp.modelFeatureIds('UBERON:0000948')
@@ -1001,6 +1922,10 @@ export default {
1001
1922
  }
1002
1923
  }
1003
1924
  },
1925
+ /**
1926
+ * @vuese
1927
+ * Function to close Flatmap Help Popup.
1928
+ */
1004
1929
  closeFlatmapHelpPopup: function () {
1005
1930
  this.$el
1006
1931
  .querySelectorAll('.maplibregl-popup-close-button')
@@ -1008,6 +1933,10 @@ export default {
1008
1933
  item.click()
1009
1934
  })
1010
1935
  },
1936
+ /**
1937
+ * @vuese
1938
+ * Function to get annotation labels.
1939
+ */
1011
1940
  getLabels: function () {
1012
1941
  let labels = []
1013
1942
  if (this.mapImp) {
@@ -1018,6 +1947,10 @@ export default {
1018
1947
  return Array.from(new Set(labels))
1019
1948
  }
1020
1949
  },
1950
+ /**
1951
+ * @vuese
1952
+ * Function to get the state (object) of the map.
1953
+ */
1021
1954
  getState: function () {
1022
1955
  if (this.mapImp) {
1023
1956
  let state = {
@@ -1033,6 +1966,11 @@ export default {
1033
1966
  }
1034
1967
  return undefined
1035
1968
  },
1969
+ /**
1970
+ * @vuese
1971
+ * Function to set state (object) for the map.
1972
+ * @arg state
1973
+ */
1036
1974
  setState: function (state) {
1037
1975
  if (state) {
1038
1976
  if (
@@ -1050,12 +1988,40 @@ export default {
1050
1988
  this.setStateRequired = false
1051
1989
  }
1052
1990
  },
1991
+ /**
1992
+ * @vuese
1993
+ * Function to restore map's state
1994
+ * from the ``state`` provided.
1995
+ * @arg state
1996
+ */
1053
1997
  restoreMapState: function (state) {
1054
1998
  if (state) {
1055
1999
  if (state.viewport) this.mapImp.setState(state.viewport)
1056
2000
  if (state.searchTerm) this.searchAndShowResult(state.searchTerm, true)
1057
2001
  }
1058
2002
  },
2003
+ /**
2004
+ * @vuese
2005
+ * Function to show flight path option
2006
+ * (3D option)
2007
+ * based on the map version (currently 1.6 and above).
2008
+ * @arg mapVersion
2009
+ */
2010
+ setFlightPathInfo: function (mapVersion) {
2011
+ const mapVersionForFlightPath = 1.6
2012
+ if (mapVersion === mapVersionForFlightPath || mapVersion > mapVersionForFlightPath) {
2013
+ // Show flight path option UI
2014
+ this.displayFlightPathOption = true
2015
+ // Show 2D as default on FC type
2016
+ this.setFlightPath3D(false)
2017
+ }
2018
+ },
2019
+ /**
2020
+ * @vuese
2021
+ * Function to create Flatmap
2022
+ * by providing the ``state``.
2023
+ * @arg state
2024
+ */
1059
2025
  createFlatmap: function (state) {
1060
2026
  if (!this.mapImp && !this.loading) {
1061
2027
  this.loading = true
@@ -1113,18 +2079,16 @@ export default {
1113
2079
  //fullscreenControl: false,
1114
2080
  //annotatable: false,
1115
2081
  //debug: true,
1116
- featureInfo: this.featureInfo,
1117
- 'min-zoom': this.minZoom,
1118
- layerControl: true,
1119
- pathControls: true,
1120
- searchable: this.searchable,
2082
+ minZoom: this.minZoom,
1121
2083
  tooltips: this.tooltips,
1122
2084
  minimap: minimap,
1123
2085
  }
1124
2086
  )
1125
2087
  promise1.then((returnedObject) => {
1126
2088
  this.mapImp = returnedObject
1127
- this.serverUUID = this.mapImp.getIdentifier().uuid
2089
+ this.serverURL = this.mapImp.makeServerUrl('').slice(0, -1)
2090
+ let mapVersion = this.mapImp.details.version
2091
+ this.setFlightPathInfo(mapVersion)
1128
2092
  this.onFlatmapReady()
1129
2093
  if (this._stateToBeSet) this.restoreMapState(this._stateToBeSet)
1130
2094
  else {
@@ -1140,6 +2104,10 @@ export default {
1140
2104
  this.restoreMapState(this._stateToBeSet)
1141
2105
  }
1142
2106
  },
2107
+ /**
2108
+ * @vuese
2109
+ * Function to compute path controls maximum height.
2110
+ */
1143
2111
  computePathControlsMaximumHeight() {
1144
2112
  const elem = this.$refs.display
1145
2113
  if (elem) {
@@ -1150,6 +2118,10 @@ export default {
1150
2118
  this.pathwaysMaxHeight = height - 170
1151
2119
  }
1152
2120
  },
2121
+ /**
2122
+ * @vuese
2123
+ * Function to resize the map.
2124
+ */
1153
2125
  mapResize: function () {
1154
2126
  try {
1155
2127
  this.computePathControlsMaximumHeight()
@@ -1164,6 +2136,10 @@ export default {
1164
2136
  console.error('Map resize error')
1165
2137
  }
1166
2138
  },
2139
+ /**
2140
+ * @vuese
2141
+ * This function is used for functions that need to run immediately after the flatmap is loaded.
2142
+ */
1167
2143
  onFlatmapReady: function () {
1168
2144
  // onFlatmapReady is used for functions that need to run immediately after the flatmap is loaded
1169
2145
  this.sensor = new ResizeSensor(this.$refs.display, this.mapResize)
@@ -1183,17 +2159,36 @@ export default {
1183
2159
  this.computePathControlsMaximumHeight()
1184
2160
  this.drawerOpen = true
1185
2161
  this.mapResize()
2162
+ /**
2163
+ * This is ``onFlatmapReady`` event.
2164
+ * @arg ``this`` (Component Vue Instance)
2165
+ */
1186
2166
  this.$emit('ready', this)
1187
2167
  },
2168
+ /**
2169
+ * @vuese
2170
+ * Function to show or hide the minimap
2171
+ * by providing ``flag`` (boolean) value.
2172
+ * @arg flag
2173
+ */
1188
2174
  showMinimap: function (flag) {
1189
2175
  if (this.mapImp) this.mapImp.showMinimap(flag)
1190
2176
  },
2177
+ /**
2178
+ * @vuese
2179
+ * Function to show or hide the pathways drawer
2180
+ * by providing ``flag`` (boolean) value.
2181
+ * @arg flag
2182
+ */
1191
2183
  showPathwaysDrawer: function (flag) {
1192
2184
  this.drawerOpen = flag
1193
2185
  },
1194
2186
  /**
2187
+ * @vuese
1195
2188
  * Function to display features with annotation matching the provided term,
1196
2189
  * with the option to display the label using displayLabel flag.
2190
+ * @arg term,
2191
+ * @arg displayLabel
1197
2192
  */
1198
2193
  searchAndShowResult: function (term, displayLabel) {
1199
2194
  if (this.mapImp) {
@@ -1233,7 +2228,10 @@ export default {
1233
2228
  return false
1234
2229
  },
1235
2230
  /**
1236
- * Get the list of suggested terms
2231
+ * @vuese
2232
+ * Function to show search suggestions
2233
+ * from the ``term`` provided.
2234
+ * @arg term
1237
2235
  */
1238
2236
  searchSuggestions: function (term) {
1239
2237
  if (this.mapImp) return this.mapImp.search(term)
@@ -1241,48 +2239,66 @@ export default {
1241
2239
  },
1242
2240
  },
1243
2241
  props: {
1244
- entry: String,
2242
+ /**
2243
+ * The taxon identifier of the species represented by the map.
2244
+ */
2245
+ entry: {
2246
+ type: String,
2247
+ required: true,
2248
+ },
2249
+ /**
2250
+ * The unique ``uuid`` of the flatmap.
2251
+ * If given then this exact map will be loaded,
2252
+ * overriding ``taxon`` and ``biologicalSex``.
2253
+ */
1245
2254
  uuid: String,
2255
+ /**
2256
+ * The biological sex of the species represented by the map.
2257
+ * This is specified as metadata in the map's source file.
2258
+ */
1246
2259
  biologicalSex: {
1247
2260
  type: String,
1248
2261
  default: '',
1249
2262
  },
1250
- featureInfo: {
1251
- type: Boolean,
1252
- default: false,
1253
- },
2263
+ /**
2264
+ * The minimum zoom level of the map.
2265
+ */
1254
2266
  minZoom: {
1255
2267
  type: Number,
1256
2268
  default: 4,
1257
2269
  },
1258
- pathControls: {
1259
- type: Boolean,
1260
- default: false,
1261
- },
1262
- searchable: {
1263
- type: Boolean,
1264
- default: false,
1265
- },
1266
- layerControl: {
1267
- type: Boolean,
1268
- default: false,
1269
- },
2270
+ /**
2271
+ * The option to add another feature label _(`FeatureSmallSymbolLayer`)_
2272
+ * when this `tooltips` is set to `false`.
2273
+ */
1270
2274
  tooltips: {
1271
2275
  type: Boolean,
1272
2276
  default: true,
1273
2277
  },
2278
+ /**
2279
+ * The option to show tooltips for help mode.
2280
+ */
1274
2281
  helpMode: {
1275
2282
  type: Boolean,
1276
2283
  default: false,
1277
2284
  },
2285
+ /**
2286
+ * The option to create map on component mounted.
2287
+ */
1278
2288
  renderAtMounted: {
1279
2289
  type: Boolean,
1280
2290
  default: true,
1281
2291
  },
2292
+ /**
2293
+ * The option to display minimap at the top-right corner of the map.
2294
+ */
1282
2295
  displayMinimap: {
1283
2296
  type: Boolean,
1284
2297
  default: false,
1285
2298
  },
2299
+ /**
2300
+ * The option to show warning. Example for legacy or beta maps.
2301
+ */
1286
2302
  displayWarning: {
1287
2303
  type: Boolean,
1288
2304
  default: false,
@@ -1295,8 +2311,28 @@ export default {
1295
2311
  type: Boolean,
1296
2312
  default: false,
1297
2313
  },
2314
+ /**
2315
+ * The data to show different map options.
2316
+ * Available at the bottom-left corner ("Open new map" tooltip).
2317
+ */
1298
2318
  openMapOptions: {
1299
2319
  type: Array,
2320
+ /**
2321
+ * ```[
2322
+ {
2323
+ display: 'Open AC Map',
2324
+ key: 'AC',
2325
+ },
2326
+ {
2327
+ display: 'Open FC Map',
2328
+ key: 'FC',
2329
+ },
2330
+ {
2331
+ display: 'Open 3D Human Map',
2332
+ key: '3D',
2333
+ },
2334
+ ]```
2335
+ */
1300
2336
  default: function () {
1301
2337
  return [
1302
2338
  {
@@ -1314,14 +2350,24 @@ export default {
1314
2350
  ]
1315
2351
  },
1316
2352
  },
2353
+ /**
2354
+ * The option to show star in legend area.
2355
+ */
1317
2356
  showStarInLegend: {
1318
2357
  type: Boolean,
1319
2358
  default: false,
1320
2359
  },
2360
+ /**
2361
+ * Flag to determine whether this is legacy map or not.
2362
+ * ``displayWarning`` should be shown for legacy map.
2363
+ */
1321
2364
  isLegacy: {
1322
2365
  type: Boolean,
1323
2366
  default: false,
1324
2367
  },
2368
+ /**
2369
+ * The option to show the latest changes.
2370
+ */
1325
2371
  displayLatestChanges: {
1326
2372
  type: Boolean,
1327
2373
  default: false,
@@ -1340,6 +2386,9 @@ export default {
1340
2386
  type: String,
1341
2387
  default: 'https://mapcore-demo.org/current/flatmap/v3/',
1342
2388
  },
2389
+ /**
2390
+ * Specify the endpoint of the SPARC API.
2391
+ */
1343
2392
  sparcAPI: {
1344
2393
  type: String,
1345
2394
  default: 'https://api.sparc.science/',
@@ -1356,6 +2405,8 @@ export default {
1356
2405
  return {
1357
2406
  flatmapAPI: this.flatmapAPI,
1358
2407
  sparcAPI: this.sparcAPI,
2408
+ $annotator: this.annotator,
2409
+ userApiKey: this.userToken
1359
2410
  }
1360
2411
  },
1361
2412
  data: function () {
@@ -1365,7 +2416,7 @@ export default {
1365
2416
  //for the first time, otherwise it may display an arrow at a
1366
2417
  //undesired location.
1367
2418
  tooltipDisplay: false,
1368
- serverUUID: undefined,
2419
+ serverURL: undefined,
1369
2420
  layers: [],
1370
2421
  pathways: [],
1371
2422
  sckanDisplay: [
@@ -1395,6 +2446,12 @@ export default {
1395
2446
  { value: false },
1396
2447
  { value: false },
1397
2448
  { value: false },
2449
+ { value: false },
2450
+ { value: false },
2451
+ { value: false },
2452
+ { value: false },
2453
+ { value: false },
2454
+ { value: false },
1398
2455
  ],
1399
2456
  yellowstar: yellowstar,
1400
2457
  isFC: false,
@@ -1406,38 +2463,141 @@ export default {
1406
2463
  tooltipEntry: createUnfilledTooltipData(),
1407
2464
  connectivityTooltipVisible: false,
1408
2465
  drawerOpen: false,
1409
- annotationRadio: false,
2466
+ flightPath3DRadio: false,
2467
+ displayFlightPathOption: false,
1410
2468
  colourRadio: true,
1411
2469
  outlinesRadio: true,
1412
2470
  minimapResizeShow: false,
1413
2471
  minimapSmall: false,
1414
2472
  currentActive: '',
2473
+ currentDrawnFeature: undefined, // Clicked drawn annotation
1415
2474
  currentHover: '',
1416
2475
  viewingMode: 'Exploration',
1417
2476
  viewingModes: ['Annotation', 'Exploration', 'Network Discovery'],
2477
+ drawnType: 'All tools',
2478
+ drawnTypes: ['All tools', 'Point', 'LineString', 'Polygon', 'None'],
2479
+ annotatedType: 'Anyone',
2480
+ annotatedTypes: ['Anyone', 'Me', 'Others'],
1418
2481
  openMapRef: undefined,
1419
2482
  backgroundIconRef: undefined,
2483
+ annotator: undefined,
2484
+ userInformation: undefined,
2485
+ activeDrawTool: undefined,
2486
+ drawnAnnotationEvent: ['created', 'updated', 'deleted'],
2487
+ createdEvent: undefined,
2488
+ annotationSubmitted: false,
2489
+ inDrawing: false,
2490
+ relevanceDisplay: false,
2491
+ relevanceEntry: {},
2492
+ drawnAnnotationFeatures: undefined, // Store all exist drawn features
2493
+ doubleClickedFeature: false,
2494
+ activeDrawMode: undefined,
2495
+ drawModes: ['Delete', 'Edit'],
2496
+ dialogPosition: {
2497
+ offsetX: 0,
2498
+ offsetY: 0,
2499
+ x: undefined,
2500
+ y: undefined
2501
+ }
2502
+ }
2503
+ },
2504
+ computed: {
2505
+ ...mapState(useMainStore, ['userToken']),
2506
+ relevance: function () {
2507
+ return Object.keys(this.relevanceEntry).length > 0
1420
2508
  }
1421
2509
  },
1422
2510
  watch: {
1423
2511
  entry: function () {
1424
2512
  if (!this.state) this.createFlatmap()
1425
2513
  },
1426
- helpMode: function (val) {
1427
- this.setHelpMode(val)
2514
+ helpMode: function (newVal, oldVal) {
2515
+ if (newVal !== oldVal) {
2516
+ this.setHelpMode(val)
2517
+ }
1428
2518
  },
1429
2519
  state: {
1430
- handler: function (state) {
1431
- if (this.mapManager) {
1432
- this.setState(state)
1433
- } else {
1434
- //this component has not been mounted yet
1435
- this.setStateRequired = true
2520
+ handler: function (state, oldVal) {
2521
+ if (state !== oldVal) {
2522
+ if (this.mapManager) {
2523
+ this.setState(state)
2524
+ } else {
2525
+ //this component has not been mounted yet
2526
+ this.setStateRequired = true
2527
+ }
1436
2528
  }
1437
2529
  },
1438
2530
  immediate: true,
1439
2531
  deep: true,
1440
2532
  },
2533
+ activeDrawTool: function () {
2534
+ this.drawIconCssHacks()
2535
+ },
2536
+ activeDrawMode: function () {
2537
+ this.drawIconCssHacks()
2538
+ },
2539
+ /**
2540
+ * hide dialog when relevanceEntry is empty
2541
+ */
2542
+ relevance: function (value) {
2543
+ const relevanceIcon = this.$el.querySelector('.drawRelevance')
2544
+ if (!value) {
2545
+ this.relevanceDisplay = false
2546
+ relevanceIcon.classList.add('inactive')
2547
+ } else {
2548
+ relevanceIcon.classList.remove('inactive')
2549
+ }
2550
+ },
2551
+ /**
2552
+ * popup dialog via click icon
2553
+ */
2554
+ relevanceDisplay: function (display) {
2555
+ const relevanceIcon = this.$el.querySelector('.drawRelevance')
2556
+ if (display) {
2557
+ relevanceIcon.classList.add('iconSelected')
2558
+ this.dialogCssHacks()
2559
+ } else {
2560
+ relevanceIcon.classList.remove('iconSelected')
2561
+ }
2562
+ this.drawIconCssHacks()
2563
+ },
2564
+ /**
2565
+ * Set dialog offset when flatmap annotator used
2566
+ */
2567
+ dialogPosition: {
2568
+ handler: function () {
2569
+ const containerRect = this.$el.getBoundingClientRect()
2570
+ this.dialogPosition.offsetX = containerRect.x
2571
+ this.dialogPosition.offsetY = containerRect.y
2572
+ },
2573
+ deep: true,
2574
+ once: true,
2575
+ },
2576
+ viewingMode: function (mode) {
2577
+ if (mode === 'Annotation') {
2578
+ this.$el.querySelector('.maplibregl-canvas').addEventListener('click', (e) => {
2579
+ e.preventDefault();
2580
+ this.dialogPosition.x = e.clientX
2581
+ this.dialogPosition.y = e.clientY
2582
+ // use to fix the draw point pop up position issue
2583
+ if (this.activeDrawTool === 'Point') {
2584
+ this.dialogCssHacks()
2585
+ }
2586
+ }, false)
2587
+ this.loading = true
2588
+ this.annotator.authenticate(this.userToken).then((userData) => {
2589
+ if (userData.name && userData.email) {
2590
+ this.showAnnotator(true)
2591
+ this.userInformation = userData
2592
+ this.setFeatureAnnotated()
2593
+ if (!this.drawnAnnotationFeatures) {
2594
+ this.addAnnotationFeature()
2595
+ }
2596
+ }
2597
+ this.loading = false
2598
+ })
2599
+ } else this.showAnnotator(false)
2600
+ },
1441
2601
  disableUI: function (isUIDisabled) {
1442
2602
  if (isUIDisabled) {
1443
2603
  this.closeTooltip()
@@ -1520,6 +2680,7 @@ export default {
1520
2680
  position: absolute;
1521
2681
  bottom: 0px;
1522
2682
  transition: all 1s ease;
2683
+ z-index: 8;
1523
2684
  &.open {
1524
2685
  left: 0px;
1525
2686
  }
@@ -1550,6 +2711,8 @@ export default {
1550
2711
  transition: all 1s ease;
1551
2712
  &.open {
1552
2713
  opacity: 1;
2714
+ position: relative;
2715
+ z-index: 2;
1553
2716
  }
1554
2717
  &.close {
1555
2718
  opacity: 0;
@@ -1592,7 +2755,8 @@ export default {
1592
2755
  }
1593
2756
 
1594
2757
  :deep(.maplibregl-popup) {
1595
- max-width: 300px !important;
2758
+ z-index: 10;
2759
+ max-width: 330px !important;
1596
2760
  }
1597
2761
 
1598
2762
  :deep(.flatmap-tooltip-popup) {
@@ -1706,12 +2870,19 @@ export default {
1706
2870
  }
1707
2871
  }
1708
2872
 
1709
- .zoomOut {
1710
- padding-left: 8px;
2873
+ .drawPoint, .drawLineString, .drawPolygon,
2874
+ .drawDelete, .drawEdit, .drawRelevance,
2875
+ .zoomIn, .zoomOut, .fitWindow {
2876
+ padding: 4px;
2877
+ }
2878
+
2879
+ .iconSelected {
2880
+ color: var(--el-color-primary-light-5) !important;
1711
2881
  }
1712
2882
 
1713
- .fitWindow {
1714
- padding-left: 8px;
2883
+ .inactive {
2884
+ color: #DDDDDD !important;
2885
+ cursor: not-allowed !important;
1715
2886
  }
1716
2887
 
1717
2888
  .yellow-star-legend {
@@ -1723,6 +2894,7 @@ export default {
1723
2894
  bottom: 16px;
1724
2895
  position: absolute;
1725
2896
  transition: all 1s ease;
2897
+ z-index: 10;
1726
2898
  &.open {
1727
2899
  left: 322px;
1728
2900
  }
@@ -1736,7 +2908,7 @@ export default {
1736
2908
  background-color: #ffffff;
1737
2909
  border: 1px solid $app-primary-color;
1738
2910
  box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
1739
- height: 290px;
2911
+ height: fit-content;
1740
2912
  min-width: 200px;
1741
2913
  .el-popper__arrow {
1742
2914
  &:before {
@@ -1745,6 +2917,10 @@ export default {
1745
2917
  }
1746
2918
  }
1747
2919
 
2920
+ :deep(.background-popper.el-popover.el-popper.h-auto) {
2921
+ height: auto !important;
2922
+ }
2923
+
1748
2924
  :deep(.open-map-popper.el-popover.el-popper) {
1749
2925
  padding-top: 5px;
1750
2926
  padding-bottom: 5px;
@@ -1915,25 +3091,27 @@ export default {
1915
3091
  }
1916
3092
  }
1917
3093
 
1918
- :deep(.popper-zoomout) {
1919
- padding-right: 13px !important;
1920
- left: -21px !important;
1921
- }
1922
-
1923
- :deep(.popper-zoomout) {
1924
- .popper__arrow {
1925
- left: 53px !important;
1926
- }
1927
- }
1928
-
1929
3094
  :deep(.maplibregl-popup-content) {
1930
3095
  padding: 0px;
1931
3096
  }
1932
3097
 
3098
+ .bottom-draw-control {
3099
+ background-color: var(--el-color-primary-light-9);
3100
+ padding: 4px 4px 2px 4px;
3101
+ border-style: solid;
3102
+ border-color: var(--el-color-primary-light-5);
3103
+ border-radius: 1rem;
3104
+ position: absolute;
3105
+ right: calc(50vw - 100px);;
3106
+ bottom: 16px;
3107
+ z-index: 10;
3108
+ }
3109
+
1933
3110
  .bottom-right-control {
1934
3111
  position: absolute;
1935
3112
  right: 16px;
1936
3113
  bottom: 16px;
3114
+ z-index: 10;
1937
3115
  }
1938
3116
 
1939
3117
  :deep(.my-drawer) {
@@ -2119,12 +3297,21 @@ export default {
2119
3297
  }
2120
3298
  }
2121
3299
  }
3300
+
3301
+ .relevance-dialog {
3302
+ position: absolute;
3303
+ z-index: 10;
3304
+ cursor: move;
3305
+ }
2122
3306
  </style>
2123
3307
 
2124
3308
  <style lang="scss">
2125
3309
 
2126
3310
  .flatmap-container {
2127
3311
  --el-color-primary: #8300BF;
3312
+ --el-color-primary-light-5: #CD99E5;
3313
+ --el-color-primary-light-9: #F3E6F9;
3314
+ --el-color-primary-dark-2: var(--el-color-primary);
2128
3315
  }
2129
3316
 
2130
3317
  </style>