@abi-software/flatmapvuer 0.6.1-annotator.0 → 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.
@@ -137,8 +137,8 @@
137
137
  </el-icon>
138
138
 
139
139
  <div class="bottom-draw-control"
140
- v-if="viewingMode === 'Annotation' && userInformation"
141
- v-show="!disableUI">
140
+ v-show="viewingMode === 'Annotation' && userInformation && !disableUI"
141
+ >
142
142
  <el-popover
143
143
  content="Relevance"
144
144
  placement="top"
@@ -151,11 +151,10 @@
151
151
  <template #reference>
152
152
  <map-svg-icon
153
153
  icon="connection"
154
- class="icon-button connection"
155
- @click="displayRelevanceDialog(true)"
154
+ class="icon-button drawRelevance inactive"
155
+ @click="relevanceDialogPopup"
156
156
  @mouseover="showToolitip(10)"
157
157
  @mouseout="hideToolitip(10)"
158
- v-show="hasRelevance && !inDrawing"
159
158
  />
160
159
  </template>
161
160
  </el-popover>
@@ -167,13 +166,13 @@
167
166
  width="80"
168
167
  popper-class="flatmap-popper"
169
168
  :visible="hoverVisibilities[11].value"
170
- v-if="drawingType !== 'LineString' && drawingType !== 'Polygon'"
169
+ v-if="drawnType !== 'LineString' && drawnType !== 'Polygon'"
171
170
  >
172
171
  <template #reference>
173
172
  <map-svg-icon
174
173
  icon="drawPoint"
175
174
  class="icon-button drawPoint"
176
- @click="drawnEvent('Point')"
175
+ @click="drawingEvent('Point')"
177
176
  @mouseover="showToolitip(11)"
178
177
  @mouseout="hideToolitip(11)"
179
178
  />
@@ -187,13 +186,13 @@
187
186
  width="80"
188
187
  popper-class="flatmap-popper"
189
188
  :visible="hoverVisibilities[12].value"
190
- v-if="drawingType !== 'Point' && drawingType !== 'Polygon'"
189
+ v-if="drawnType !== 'Point' && drawnType !== 'Polygon'"
191
190
  >
192
191
  <template #reference>
193
192
  <map-svg-icon
194
193
  icon="drawLine"
195
194
  class="icon-button drawLineString"
196
- @click="drawnEvent('LineString')"
195
+ @click="drawingEvent('LineString')"
197
196
  @mouseover="showToolitip(12)"
198
197
  @mouseout="hideToolitip(12)"
199
198
  />
@@ -207,13 +206,13 @@
207
206
  width="80"
208
207
  popper-class="flatmap-popper"
209
208
  :visible="hoverVisibilities[13].value"
210
- v-if="drawingType !== 'Point' && drawingType !== 'LineString'"
209
+ v-if="drawnType !== 'Point' && drawnType !== 'LineString'"
211
210
  >
212
211
  <template #reference>
213
212
  <map-svg-icon
214
213
  icon="drawPolygon"
215
214
  class="icon-button drawPolygon"
216
- @click="drawnEvent('Polygon')"
215
+ @click="drawingEvent('Polygon')"
217
216
  @mouseover="showToolitip(13)"
218
217
  @mouseout="hideToolitip(13)"
219
218
  />
@@ -231,8 +230,8 @@
231
230
  <template #reference>
232
231
  <map-svg-icon
233
232
  icon="drawTrash"
234
- class="icon-button drawTrash"
235
- @click="drawnEvent('Delete')"
233
+ class="icon-button drawDelete"
234
+ @click="drawingEvent('Delete')"
236
235
  @mouseover="showToolitip(14)"
237
236
  @mouseout="hideToolitip(14)"
238
237
  />
@@ -250,8 +249,8 @@
250
249
  <template #reference>
251
250
  <map-svg-icon
252
251
  icon="comment"
253
- class="icon-button comment"
254
- @click="drawnEvent('Edit')"
252
+ class="icon-button drawEdit"
253
+ @click="drawingEvent('Edit')"
255
254
  @mouseover="showToolitip(15)"
256
255
  @mouseout="hideToolitip(15)"
257
256
  />
@@ -342,7 +341,6 @@
342
341
  class="pathway-container"
343
342
  :class="{ open: drawerOpen, close: !drawerOpen }"
344
343
  :style="{ 'max-height': pathwaysMaxHeight + 'px' }"
345
- v-if="pathControls"
346
344
  v-popover:checkBoxPopover
347
345
  >
348
346
  <svg-legends v-if="!isFC" class="svg-legends-container" />
@@ -473,7 +471,14 @@
473
471
  virtual-triggering
474
472
  >
475
473
  <el-row v-for="item in openMapOptions" :key="item.key">
476
- <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
+ >
477
482
  {{ item.display }}
478
483
  </el-button>
479
484
  </el-row>
@@ -485,7 +490,7 @@
485
490
  width="200"
486
491
  :teleported="false"
487
492
  trigger="click"
488
- popper-class="background-popper"
493
+ popper-class="background-popper h-auto"
489
494
  virtual-triggering
490
495
  >
491
496
  <div>
@@ -499,8 +504,8 @@
499
504
  popper-class="flatmap_dropdown"
500
505
  >
501
506
  <el-option
502
- v-for="item in viewingModes"
503
- :key="item"
507
+ v-for="(item, i) in viewingModes"
508
+ :key="item + i"
504
509
  :label="item"
505
510
  :value="item"
506
511
  >
@@ -511,18 +516,18 @@
511
516
  </el-select>
512
517
  </el-row>
513
518
  <template v-if="viewingMode === 'Annotation' && userInformation">
514
- <el-row class="backgroundText">Drawing Type*</el-row>
519
+ <el-row class="backgroundText">Drawn By*</el-row>
515
520
  <el-row class="backgroundControl">
516
521
  <el-select
517
522
  :teleported="false"
518
- v-model="drawingType"
523
+ v-model="drawnType"
519
524
  placeholder="Select"
520
525
  class="select-box"
521
526
  popper-class="flatmap_dropdown"
522
- @change="setDrawingType"
527
+ @change="setDrawnType"
523
528
  >
524
529
  <el-option
525
- v-for="item in drawingTypes"
530
+ v-for="item in drawnTypes"
526
531
  :key="item"
527
532
  :label="item"
528
533
  :value="item"
@@ -533,18 +538,18 @@
533
538
  </el-option>
534
539
  </el-select>
535
540
  </el-row>
536
- <el-row class="backgroundText">Participation Type*</el-row>
541
+ <el-row class="backgroundText">Annotated By*</el-row>
537
542
  <el-row class="backgroundControl">
538
543
  <el-select
539
544
  :teleported="false"
540
- v-model="participationType"
545
+ v-model="annotatedType"
541
546
  placeholder="Select"
542
547
  class="select-box"
543
548
  popper-class="flatmap_dropdown"
544
- @change="setParticipationType"
549
+ @change="setAnnotatedType"
545
550
  >
546
551
  <el-option
547
- v-for="item in participationTypes"
552
+ v-for="item in annotatedTypes"
548
553
  :key="item"
549
554
  :label="item"
550
555
  :value="item"
@@ -556,13 +561,13 @@
556
561
  </el-select>
557
562
  </el-row>
558
563
  </template>
559
- <el-row class="backgroundSpacer"></el-row>
560
- <el-row class="backgroundText">Dimension display</el-row>
561
- <el-row class="backgroundControl">
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">
562
567
  <el-radio-group
563
- v-model="dimensionRadio"
568
+ v-model="flightPath3DRadio"
564
569
  class="flatmap-radio"
565
- @change="setDimension"
570
+ @change="setFlightPath3D"
566
571
  >
567
572
  <el-radio :label="false">2D</el-radio>
568
573
  <el-radio :label="true">3D</el-radio>
@@ -663,53 +668,18 @@
663
668
  :annotationDisplay="viewingMode === 'Annotation'"
664
669
  @annotation="commitAnnotationEvent"
665
670
  />
666
- <el-dialog
667
- v-model="relevanceDisplay"
668
- width="200"
669
- :modal="false"
670
- :show-close="false"
671
- :lock-scroll="false"
672
- :close-on-click-modal="false"
673
- :close-on-press-escape="false"
674
- draggable
675
- >
676
- <template #header v-if="inDrawing">
677
- <span class="dialog-title">Finalise drawing</span>
678
- </template>
679
- <template #header v-else>
680
- <el-button type="primary" plain @click="displayRelevanceDialog(false)">
681
- Close
682
- </el-button>
683
- </template>
684
- <el-row v-if="inDrawing">
685
- <el-col :span="13">
686
- <el-button type="primary" plain @click="confirmDrawnFeature">
687
- Confirm
688
- </el-button>
689
- </el-col>
690
- <el-col :span="11">
691
- <el-button type="primary" plain @click="cancelDrawnFeature">
692
- Cancel
693
- </el-button>
694
- </el-col>
695
- </el-row>
696
- <el-row v-if="hasRelevance">
697
- <el-col :span="20">
698
- <b><span>Related Features</span></b>
699
- </el-col>
700
- <el-col :span="4">
701
- <el-icon><el-icon-circle-close @click="closePopup()"/></el-icon>
702
- </el-col>
703
- <el-card
704
- shadow="hover"
705
- v-for="(value, key) in relevanceEntry"
706
- :key="key"
707
- @click="displayRelevanceTooltip(value)"
708
- >
709
- <span>{{ key }}</span>
710
- </el-card>
711
- </el-row>
712
- </el-dialog>
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"
682
+ />
713
683
  </div>
714
684
  </div>
715
685
  </template>
@@ -721,7 +691,6 @@ import {
721
691
  WarningFilled as ElIconWarningFilled,
722
692
  ArrowDown as ElIconArrowDown,
723
693
  ArrowLeft as ElIconArrowLeft,
724
- CircleClose as ElIconCircleClose,
725
694
  } from '@element-plus/icons-vue'
726
695
  import Tooltip from './Tooltip.vue'
727
696
  import SelectionsGroup from './SelectionsGroup.vue'
@@ -746,14 +715,64 @@ import {
746
715
  } from '../services/flatmapQueries.js'
747
716
  import yellowstar from '../icons/yellowstar'
748
717
  import ResizeSensor from 'css-element-queries/src/ResizeSensor'
749
- import * as flatmap from 'customised-viewer'
718
+ import * as flatmap from '@abi-software/flatmap-viewer'
750
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
+ }
751
773
 
752
774
  const centroid = (geometry) => {
753
- let featureGeometry = {
754
- lng: 0,
755
- lat: 0,
756
- }
775
+ let featureGeometry = { lng: 0, lat: 0, }
757
776
  let coordinates
758
777
  if (geometry.type === "Polygon") {
759
778
  coordinates = geometry.coordinates[0]
@@ -834,6 +853,9 @@ const createUnfilledTooltipData = function () {
834
853
  }
835
854
  }
836
855
 
856
+ /**
857
+ * A vue component of the flatmap viewer.
858
+ */
837
859
  export default {
838
860
  name: 'FlatmapVuer',
839
861
  components: {
@@ -868,125 +890,96 @@ export default {
868
890
  return { annotator }
869
891
  },
870
892
  methods: {
871
- displayRelevanceTooltip: function (value) {
872
- if (this.mapImp) {
873
- this.checkAndCreatePopups(value)
874
- }
875
- },
876
893
  // This should be called when create is confirmed or cancelled
877
- initialiseDraw: function () {
894
+ initialiseDrawing: function () {
878
895
  this.inDrawing = false
879
- this.relevanceDisplay = false
880
- this.relevanceEntry = {}
896
+ this.initialiseDialog()
881
897
  this.activeDrawTool = undefined
882
898
  this.createdEvent = undefined
883
- this.setActiveDrawIcon()
884
899
  },
885
900
  cancelDrawnFeature: function () {
886
901
  if (this.createdEvent) {
887
- // For 'created' callback
888
902
  this.closePopup()
889
903
  this.annotationEntry = {
890
904
  ...this.createdEvent.feature,
891
- resourceId: this.serverUUID,
905
+ resourceId: this.serverURL,
892
906
  }
893
907
  this.rollbackAnnotationEvent()
894
- this.initialiseDraw()
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 })
895
915
  }
896
916
  },
897
917
  confirmDrawnFeature: function () {
898
918
  if (this.createdEvent) {
899
919
  this.checkAndCreatePopups(this.createdEvent)
900
920
  // Add relevance if exist to annotationEntry
901
- // Relevance will only be added in creating draw annotation
902
- // And will not be updated if move drawn annotation
921
+ // Relevance will only be added in creating new drawn feature annotation
922
+ // And will not be updated if move drawn features
903
923
  if (Object.keys(this.relevanceEntry).length > 0) {
904
924
  this.annotationEntry.feature.relevance = this.relevanceEntry
905
925
  }
906
- this.initialiseDraw()
926
+ this.initialiseDrawing()
907
927
  }
908
928
  },
909
- displayRelevanceDialog: function (display) {
910
- // Change back to the initial window size
911
- // For a better view of the relevance popup
912
- if (display) this.resetView()
913
- this.closePopup()
914
- // Used when check exist drawn annotation relevance
915
- if (
916
- !this.createdEvent && !this.currentDrawnFeature &&
917
- Object.keys(this.relevanceEntry).length === 0
918
- ) {
919
- // Reset drawn event
920
- this.drawnEvent()
921
- } else if (this.createdEvent || Object.keys(this.relevanceEntry).length > 0) {
922
- this.relevanceDisplay = display
923
- if (!display && this.activeDrawMode === 'Delete') this.relevanceEntry = {}
924
- }
925
- },
926
- setActiveDrawIcon: function () {
927
- let mclass
928
- if (document.querySelector('.toolSelected')) {
929
- this.drawingTypes.map((t) => {
930
- if (t !== 'All' && t !== 'None') {
931
- document.querySelector(`.draw${t}`).classList.remove('toolSelected');
932
- }
933
- })
934
- this.drawModes.map((m) => {
935
- if (m === 'Delete') mclass = '.drawTrash'
936
- else if (m === 'Edit') mclass = '.comment'
937
- document.querySelector(mclass).classList.remove('toolSelected');
938
- })
939
- }
940
- if (this.activeDrawTool) {
941
- document.querySelector(`.draw${this.activeDrawTool}`).classList.add('toolSelected');
942
- } else if (this.activeDrawMode) {
943
- if (this.activeDrawMode === 'Delete') mclass = '.drawTrash'
944
- else if (this.activeDrawMode === 'Edit') mclass = '.comment'
945
- document.querySelector(mclass).classList.add('toolSelected');
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
946
939
  }
947
940
  },
948
- drawnEvent: function (type = undefined) {
941
+ drawingEvent: function (type) {
949
942
  this.closePopup()
950
- if (!type) {
951
- this.activeDrawTool = undefined
952
- this.activeDrawMode = undefined
953
- this.inDrawing = false
954
- } else if (this.drawingTypes.includes(type)) {
955
- if (this.activeDrawMode) {
956
- document.querySelector('.mapbox-gl-draw_trash').click()
957
- this.activeDrawMode = undefined
958
- }
943
+ // disable mode icon click if any tool is active
944
+ if (this.drawnTypes.includes(type) && !this.activeDrawMode && !this.relevanceDisplay) {
959
945
  if (type === 'Point') {
960
- document.querySelector('.mapbox-gl-draw_point').click()
961
- this.activeDrawTool = this.activeDrawTool === 'Point' ? undefined : '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
962
949
  } else if (type === 'LineString') {
963
- document.querySelector('.mapbox-gl-draw_line').click()
964
- this.activeDrawTool = this.activeDrawTool === 'LineString' ? undefined : '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
965
953
  } else if (type === 'Polygon') {
966
- document.querySelector('.mapbox-gl-draw_polygon').click()
967
- this.activeDrawTool = this.activeDrawTool === 'Polygon' ? undefined : 'Polygon'
968
- }
969
- } else if (this.drawModes.includes(type)) {
970
- if (this.activeDrawTool) {
971
- document.querySelector('.mapbox-gl-draw_trash').click()
972
- this.activeDrawTool = undefined
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
973
957
  }
958
+ // disable tool icon click if any mode is on
959
+ } else if (this.drawModes.includes(type) && !this.activeDrawTool) {
974
960
  if (type === 'Delete') {
975
- if (this.currentDrawnFeature && !this.activeDrawMode) {
961
+ if (
962
+ this.currentDrawnFeature &&
963
+ // For either no mode is on or edit is on
964
+ (!this.activeDrawMode || this.activeDrawMode === 'Edit')
965
+ ) {
976
966
  // Force simple_select a feature for delete event
977
967
  this.doubleClickedFeature = false
978
968
  this.changeAnnotationDrawMode({
979
969
  mode: 'simple_select',
980
970
  options: { featureIds: [this.currentDrawnFeature.id] }
981
971
  })
982
- this.trashAnnotationFeature()
972
+ this.deleteOrEditAnnotationFeature()
983
973
  }
984
974
  this.activeDrawMode = this.activeDrawMode === 'Delete' ? undefined : 'Delete'
975
+ // clear currentDrawnFeature when quit delete mode
976
+ if (!this.activeDrawMode) {
977
+ this.currentDrawnFeature = undefined
978
+ }
985
979
  } else if (type === 'Edit') {
986
980
  this.activeDrawMode = this.activeDrawMode === 'Edit' ? undefined : 'Edit'
987
981
  }
988
982
  }
989
- this.setActiveDrawIcon()
990
983
  },
991
984
  changeAnnotationDrawMode: function (mode) {
992
985
  if (this.mapImp) {
@@ -1003,17 +996,21 @@ export default {
1003
996
  this.mapImp.clearAnnotationFeature()
1004
997
  }
1005
998
  },
1006
- trashAnnotationFeature: function () {
999
+ deleteOrEditAnnotationFeature: function () {
1007
1000
  if (this.mapImp) {
1008
- this.mapImp.trashAnnotationFeature()
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()
1009
1005
  }
1010
1006
  },
1011
1007
  rollbackAnnotationEvent: function () {
1012
- if (this.mapImp) {
1013
- // For 'updated' and 'deleted' callback
1014
- if (this.drawnAnnotationEvent.includes(this.annotationEntry.type)) {
1015
- this.mapImp.rollbackAnnotationEvent(this.annotationEntry)
1016
- }
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)
1017
1014
  }
1018
1015
  },
1019
1016
  commitAnnotationEvent: function (annotation) {
@@ -1024,13 +1021,18 @@ export default {
1024
1021
  annotation
1025
1022
  ) {
1026
1023
  this.annotationSubmitted = true
1027
- if (this.annotationEntry.type === 'deleted') this.closePopup()
1028
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
+ }
1029
1031
  }
1030
1032
  },
1031
1033
  setFeatureAnnotated: function () {
1032
1034
  if (this.mapImp) {
1033
- this.annotator.annotatedItemIds(this.serverUUID)
1035
+ this.annotator.annotatedItemIds(this.userToken, this.serverURL)
1034
1036
  .then((annotatedItemIds) => {
1035
1037
  for (const id of annotatedItemIds) {
1036
1038
  this.mapImp.setFeatureAnnotated(id)
@@ -1043,39 +1045,44 @@ export default {
1043
1045
  },
1044
1046
  addAnnotationFeature: function () {
1045
1047
  if (this.mapImp) {
1046
- this.clearAnnotationFeature()
1047
- if (this.drawingType !== 'None') {
1048
- this.annotator.drawnFeatures(this.serverUUID)
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)
1049
1052
  .then((drawnFeatures) => {
1050
1053
  // Use to switch the displayed feature type
1051
- if (this.drawingType !== 'All') {
1054
+ if (this.drawnType !== 'All tools') {
1052
1055
  drawnFeatures = drawnFeatures.filter((feature) => {
1053
- return feature.geometry.type === this.drawingType
1056
+ return feature.geometry.type === this.drawnType
1054
1057
  })
1055
1058
  }
1056
1059
  this.drawnAnnotationFeatures = drawnFeatures
1057
- for (const feature of drawnFeatures) {
1058
- if (this.participationType !== 'All') {
1059
- this.annotator
1060
- .itemAnnotations(this.serverUUID, feature.id)
1061
- .then((value) => {
1062
- let participated = value.filter((v) => {
1063
- return (
1064
- v.creator.name === this.userInformation.name &&
1065
- v.creator.email === this.userInformation.email
1066
- )
1067
- }).length > 0
1068
- if (
1069
- (this.participationType === 'Participated' && participated) ||
1070
- (this.participationType === 'Not participated' && !participated)
1071
- ) {
1072
- this.mapImp.addAnnotationFeature(feature)
1073
- }
1074
- })
1075
- .catch((reason) => {
1076
- console.log(reason) // Error!
1077
- })
1078
- } else this.mapImp.addAnnotationFeature(feature)
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
+ }
1079
1086
  }
1080
1087
  })
1081
1088
  .catch((reason) => {
@@ -1089,27 +1096,36 @@ export default {
1089
1096
  // Control the show/hide of the drawn annotations
1090
1097
  this.mapImp.showAnnotator(flag)
1091
1098
  // Hide default toolbar, we will use customised SVG icons instead
1092
- document.querySelector('.maplibregl-ctrl-group').style.display = 'none'
1099
+ this.$el.querySelector('.maplibregl-ctrl-group').style.display = 'none'
1093
1100
  }
1094
1101
  },
1095
- setDrawingType: function (flag) {
1096
- this.drawingType = flag
1102
+ setDrawnType: function (flag) {
1103
+ this.drawnType = flag
1097
1104
  if (this.mapImp) {
1098
1105
  this.addAnnotationFeature()
1099
1106
  }
1100
1107
  },
1101
- setParticipationType: function (flag) {
1102
- this.participationType = flag
1108
+ setAnnotatedType: function (flag) {
1109
+ this.annotatedType = flag
1103
1110
  if (this.mapImp) {
1104
1111
  this.addAnnotationFeature()
1105
1112
  }
1106
1113
  },
1107
- setDimension: function (flag) {
1108
- this.dimensionRadio = flag
1114
+ /**
1115
+ * @vuese
1116
+ * Function to switch from 2D to 3D
1117
+ * @arg flag
1118
+ */
1119
+ setFlightPath3D: function (flag) {
1120
+ this.flightPath3DRadio = flag
1109
1121
  if (this.mapImp) {
1110
- this.mapImp.enable3dPaths(flag)
1122
+ this.mapImp.enableFlightPaths(flag)
1111
1123
  }
1112
1124
  },
1125
+ /**
1126
+ * @vuese
1127
+ * Function to view the latest map (example when you are on legacy map).
1128
+ */
1113
1129
  viewLatestMap: function () {
1114
1130
  let biologicalSex = this.biologicalSex ? this.biologicalSex : undefined
1115
1131
  //Human requires special handling
@@ -1121,14 +1137,28 @@ export default {
1121
1137
  biologicalSex,
1122
1138
  viewport: this.mapImp.getState(),
1123
1139
  }
1140
+ /**
1141
+ * The event emitted by ``viewLatestMap`` method.
1142
+ */
1124
1143
  this.$emit('view-latest-map', state)
1125
1144
  },
1145
+ /**
1146
+ * @vuese
1147
+ * Function to change the background colour of the map
1148
+ * by providing the ``colour``.
1149
+ * @arg colour
1150
+ */
1126
1151
  backgroundChangeCallback: function (colour) {
1127
1152
  this.currentBackground = colour
1128
1153
  if (this.mapImp) {
1129
1154
  this.mapImp.setBackgroundColour(this.currentBackground, 1)
1130
1155
  }
1131
1156
  },
1157
+ /**
1158
+ * @vuese
1159
+ * Function to process a list of a FC flatmap's systems.
1160
+ * @arg systems
1161
+ */
1132
1162
  processSystems: function (systems) {
1133
1163
  this.systems.length = 0
1134
1164
  if (systems && systems.length > 0) {
@@ -1148,6 +1178,13 @@ export default {
1148
1178
  this.systems.push(data)
1149
1179
  }
1150
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
+ */
1151
1188
  processTaxon: function (flatmapAPI, taxonIdentifiers) {
1152
1189
  this.taxonConnectivity.length = 0
1153
1190
  taxonIdentifiers.forEach((taxon) => {
@@ -1157,11 +1194,18 @@ export default {
1157
1194
  })
1158
1195
  })
1159
1196
  },
1197
+ /**
1198
+ * @vuese
1199
+ * Function to show or hide the display of the bottom-left drawer container.
1200
+ */
1160
1201
  toggleDrawer: function () {
1161
1202
  this.drawerOpen = !this.drawerOpen
1162
1203
  },
1163
1204
  /**
1205
+ * @vuese
1164
1206
  * Function to toggle colour/greyscale of organs.
1207
+ * The parameter ``flag`` is a boolean, ``true`` (colour) and ``false`` (greyscale).
1208
+ * @arg flag
1165
1209
  */
1166
1210
  setColour: function (flag) {
1167
1211
  this.colourRadio = flag
@@ -1170,7 +1214,10 @@ export default {
1170
1214
  }
1171
1215
  },
1172
1216
  /**
1217
+ * @vuese
1173
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
1174
1221
  */
1175
1222
  setOutlines: function (flag) {
1176
1223
  this.outlineRadio = flag
@@ -1179,6 +1226,7 @@ export default {
1179
1226
  }
1180
1227
  },
1181
1228
  /**
1229
+ * @vuese
1182
1230
  * Function to toggle paths to default.
1183
1231
  * Also called when the associated button is pressed.
1184
1232
  */
@@ -1203,6 +1251,7 @@ export default {
1203
1251
  }
1204
1252
  },
1205
1253
  /**
1254
+ * @vuese
1206
1255
  * Function to zoom in.
1207
1256
  * Also called when the associated button is pressed.
1208
1257
  */
@@ -1212,6 +1261,7 @@ export default {
1212
1261
  }
1213
1262
  },
1214
1263
  /**
1264
+ * @vuese
1215
1265
  * Function to zoom out.
1216
1266
  * Also called when the associated button is pressed.
1217
1267
  */
@@ -1220,16 +1270,34 @@ export default {
1220
1270
  this.mapImp.zoomOut()
1221
1271
  }
1222
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
+ */
1223
1280
  centreLinesSelected: function (payload) {
1224
1281
  if (this.mapImp) {
1225
1282
  this.mapImp.enableCentrelines(payload.value)
1226
1283
  }
1227
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
+ */
1228
1291
  sckanSelected: function (payload) {
1229
1292
  if (this.mapImp) {
1230
1293
  this.mapImp.enableSckanPath(payload.key, payload.value)
1231
1294
  }
1232
1295
  },
1296
+ /**
1297
+ * // Currently not in use
1298
+ * Function to show or hide all paths valid in SCKAN.
1299
+ * @arg payload
1300
+ */
1233
1301
  checkAllSCKAN: function (payload) {
1234
1302
  if (this.mapImp) {
1235
1303
  payload.keys.forEach((key) =>
@@ -1237,6 +1305,12 @@ export default {
1237
1305
  )
1238
1306
  }
1239
1307
  },
1308
+ /**
1309
+ * @vuese
1310
+ * Function to highlight the connected paths
1311
+ * by providing path model identifier, ``pathId``.
1312
+ * @arg pathId
1313
+ */
1240
1314
  highlightConnectedPaths: function (payload) {
1241
1315
  if (this.mapImp) {
1242
1316
  let paths = [...this.mapImp.pathModelNodes(payload)]
@@ -1253,11 +1327,23 @@ export default {
1253
1327
  this.mapImp.zoomToFeatures(toHighlight, { noZoomIn: true })
1254
1328
  }
1255
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
+ */
1256
1336
  systemSelected: function (payload) {
1257
1337
  if (this.mapImp) {
1258
1338
  this.mapImp.enableSystem(payload.key, payload.value)
1259
1339
  }
1260
1340
  },
1341
+ /**
1342
+ * @vuese
1343
+ * Function to enable/disable (show/hide) all systems
1344
+ * by providing ``flag`` (true/false).
1345
+ * @arg flag
1346
+ */
1261
1347
  checkAllSystems: function (flag) {
1262
1348
  if (this.mapImp) {
1263
1349
  this.systems[0].children.forEach((key) =>
@@ -1265,14 +1351,31 @@ export default {
1265
1351
  )
1266
1352
  }
1267
1353
  },
1354
+ /**
1355
+ * @vuese
1356
+ * Function to display features with annotation matching the provided term.
1357
+ * @arg models
1358
+ */
1268
1359
  ftuSelected: function (models) {
1269
1360
  this.searchAndShowResult(models, true)
1270
1361
  },
1362
+ /**
1363
+ * @vuese
1364
+ * Function to show or hide the layer
1365
+ * by providing ``{layerId, true/false}`` in ``payload``.
1366
+ * @arg payload
1367
+ */
1271
1368
  layersSelected: function (payload) {
1272
1369
  if (this.mapImp) {
1273
1370
  this.mapImp.enableLayer(payload.key, payload.value)
1274
1371
  }
1275
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
+ */
1276
1379
  checkAllLayers: function (payload) {
1277
1380
  if (this.mapImp) {
1278
1381
  payload.keys.forEach((key) =>
@@ -1280,11 +1383,23 @@ export default {
1280
1383
  )
1281
1384
  }
1282
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
+ */
1283
1392
  taxonsSelected: function (payload) {
1284
1393
  if (this.mapImp) {
1285
1394
  this.mapImp.enableConnectivityByTaxonIds(payload.key, payload.value)
1286
1395
  }
1287
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
+ */
1288
1403
  checkAllTaxons: function (payload) {
1289
1404
  if (this.mapImp) {
1290
1405
  payload.keys.forEach((key) =>
@@ -1292,11 +1407,23 @@ export default {
1292
1407
  )
1293
1408
  }
1294
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
+ */
1295
1416
  pathwaysSelected: function (payload) {
1296
1417
  if (this.mapImp) {
1297
1418
  this.mapImp.enablePath(payload.key, payload.value)
1298
1419
  }
1299
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
+ */
1300
1427
  checkAllPathways: function (payload) {
1301
1428
  if (this.mapImp) {
1302
1429
  payload.keys.forEach((key) =>
@@ -1304,9 +1431,21 @@ export default {
1304
1431
  )
1305
1432
  }
1306
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
+ */
1307
1440
  enablePanZoomEvents: function (flag) {
1308
1441
  this.mapImp.enablePanZoomEvents(flag)
1309
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
+ */
1310
1449
  eventCallback: function () {
1311
1450
  return (eventType, data, ...args) => {
1312
1451
  if (eventType === 'annotation') {
@@ -1318,17 +1457,21 @@ export default {
1318
1457
  // Popup closed will trigger aborted event
1319
1458
  if (data.type === 'aborted') {
1320
1459
  // Rollback drawing when no new annotation submitted
1321
- if (!this.annotationSubmitted) {
1322
- this.rollbackAnnotationEvent()
1323
- }
1460
+ if (!this.annotationSubmitted) this.rollbackAnnotationEvent()
1461
+ else this.annotationSubmitted = false
1324
1462
  } else if (data.type === 'modeChanged') {
1325
1463
  // 'modeChanged' event is before 'created' event
1326
1464
  if (data.feature.mode.startsWith('draw_')) {
1327
1465
  // Reset data entry for every draw
1328
- this.relevanceEntry = {}
1466
+ this.initialiseDialog()
1329
1467
  this.inDrawing = true
1330
1468
  } else if (data.feature.mode === 'simple_select' && this.inDrawing) {
1331
- this.displayRelevanceDialog(true)
1469
+ if (this.createdEvent) {
1470
+ this.relevanceDisplay = true
1471
+ } else {
1472
+ // Reset if a invalid draw
1473
+ this.initialiseDrawing()
1474
+ }
1332
1475
  } else if (data.feature.mode === 'direct_select') {
1333
1476
  this.doubleClickedFeature = true
1334
1477
  }
@@ -1338,8 +1481,18 @@ export default {
1338
1481
  undefined :
1339
1482
  data.feature.features[0]
1340
1483
  payload.feature.feature = this.currentDrawnFeature
1341
- // For exist drawn annotation features
1342
- this.checkAndCreateDrawnFeaturePopups(payload)
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
+ }
1343
1496
  } else {
1344
1497
  if (data.type === 'created' || data.type === 'updated') {
1345
1498
  if (data.type === 'updated' && data.feature.action) {
@@ -1364,6 +1517,15 @@ export default {
1364
1517
  const resource = [data.models]
1365
1518
  const taxonomy = this.entry
1366
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
+ }
1367
1529
  const payload = {
1368
1530
  dataset: data.dataset,
1369
1531
  biologicalSex: biologicalSex,
@@ -1373,16 +1535,22 @@ export default {
1373
1535
  feature: data,
1374
1536
  userData: args,
1375
1537
  eventType: eventType,
1376
- provenanceTaxonomy: data.taxons
1377
- ? JSON.parse(data.taxons)
1378
- : undefined,
1538
+ provenanceTaxonomy: taxons,
1379
1539
  }
1380
1540
  if (eventType === 'click') {
1381
1541
  if (this.viewingMode === 'Network Discovery') {
1382
1542
  this.highlightConnectedPaths([data.models])
1383
1543
  } else {
1384
1544
  this.currentActive = data.models ? data.models : ''
1385
- this.allocateRelevance(payload)
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
+ }
1386
1554
  }
1387
1555
  } else if (
1388
1556
  eventType === 'mouseenter' &&
@@ -1407,67 +1575,117 @@ export default {
1407
1575
  }
1408
1576
  }
1409
1577
  },
1410
- allocateRelevance: function (data = undefined) {
1411
- if (data && data.feature) {
1412
- // Only clicked relevance data will be added
1413
- let relevance = data.feature.models ?
1414
- data.feature.models :
1415
- data.feature.featureId
1416
- if (
1417
- relevance &&
1418
- this.inDrawing &&
1419
- // Currently only draw line will show relevance
1420
- this.activeDrawTool === 'LineString' &&
1421
- !(relevance in this.relevanceEntry)
1422
- ) {
1423
- this.relevanceEntry[relevance] = data
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
1424
1592
  }
1425
- } else if (this.currentDrawnFeature && this.drawnAnnotationFeatures) {
1426
- let relevance = this.drawnAnnotationFeatures
1427
- .filter((feature) => {
1428
- return feature.id === this.currentDrawnFeature.id
1429
- })[0].relevance
1430
- if (relevance) this.relevanceEntry = relevance
1431
- }
1432
- },
1433
- checkAndCreateDrawnFeaturePopups: function (data) {
1434
- if (!this.inDrawing) {
1435
- this.relevanceEntry = {}
1436
- if (this.currentDrawnFeature) {
1437
- this.allocateRelevance()
1438
- if (this.activeDrawMode) {
1439
- // double click fires 'updated' callback
1440
- if (this.doubleClickedFeature) {
1441
- if (data.feature.feature.geometry.type !== 'Point') {
1442
- // show tooltip and enter edit mode
1443
- this.changeAnnotationDrawMode({
1444
- mode: 'direct_select',
1445
- options: { featureId: data.feature.feature.id }
1446
- })
1447
- this.trashAnnotationFeature()
1448
- }
1449
- this.doubleClickedFeature = false
1450
- } else { // single click
1451
- if (this.activeDrawMode === 'Delete') {
1452
- this.changeAnnotationDrawMode({
1453
- mode: 'simple_select',
1454
- options: { featureIds: [data.feature.feature.id] }
1455
- })
1456
- this.trashAnnotationFeature()
1457
- }
1458
- }
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()
1644
+ }
1645
+ this.doubleClickedFeature = false
1646
+ } else {
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()
1459
1654
  }
1460
1655
  }
1461
1656
  }
1462
1657
  },
1463
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
+ */
1464
1682
  checkAndCreatePopups: async function (data) {
1465
1683
  // Call flatmap database to get the connection data
1466
1684
  if (this.viewingMode === 'Annotation') {
1467
1685
  if (data.feature) {
1468
1686
  this.annotationEntry = {
1469
1687
  ...data.feature,
1470
- resourceId: this.serverUUID,
1688
+ resourceId: this.serverURL,
1471
1689
  }
1472
1690
  if (data.feature.featureId && data.feature.models) {
1473
1691
  this.displayTooltip(data.feature.models)
@@ -1475,14 +1693,21 @@ export default {
1475
1693
  if (this.inDrawing || this.activeDrawMode) {
1476
1694
  this.annotationSubmitted = false
1477
1695
  this.annotationEntry.featureId = data.feature.feature.id
1478
- let featureGeometry = centroid(data.feature.feature.geometry)
1479
- this.displayTooltip(data.feature.feature.id, featureGeometry)
1696
+ this.createConnectivityBody()
1697
+ this.displayTooltip(
1698
+ data.feature.feature.id,
1699
+ centroid(data.feature.feature.geometry)
1700
+ )
1480
1701
  } else {
1481
- // Not allowed to update feature if edit mode not on
1702
+ // Not allowed to update feature if not on edit mode
1482
1703
  if (data.feature.type === 'updated') {
1483
1704
  this.rollbackAnnotationEvent()
1484
1705
  }
1485
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
+ }
1486
1711
  }
1487
1712
  } else {
1488
1713
  this.annotation = {}
@@ -1503,6 +1728,9 @@ export default {
1503
1728
  }
1504
1729
  }
1505
1730
  },
1731
+ /**
1732
+ * A hack to remove flatmap tooltips while popup is open
1733
+ */
1506
1734
  popUpCssHacks: function () {
1507
1735
  // Below is a hack to remove flatmap tooltips while popup is open
1508
1736
  let ftooltip = document.querySelector('.flatmap-tooltip-popup')
@@ -1518,18 +1746,34 @@ export default {
1518
1746
  let cbutton = document.querySelector('.maplibregl-popup-close-button')
1519
1747
  if (cbutton) cbutton.click()
1520
1748
  },
1749
+ /**
1750
+ * @vuese
1751
+ * Function to close tooltip.
1752
+ */
1521
1753
  closeTooltip: function () {
1522
1754
  this.$refs.tooltip.$el.style.display = 'none'
1523
1755
  document.querySelectorAll('.maplibregl-popup').forEach((item) => {
1524
1756
  item.style.display = 'none'
1525
1757
  })
1526
1758
  },
1759
+ /**
1760
+ * @vuese
1761
+ * Function to create tooltip from Neuron Curation ``data``.
1762
+ * @arg data
1763
+ */
1527
1764
  createTooltipFromNeuronCuration: async function (data) {
1528
1765
  this.tooltipEntry = await this.flatmapQueries.createTooltipData(data)
1529
1766
  this.displayTooltip(data.resource[0])
1530
1767
  },
1531
- // 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
+ */
1532
1775
  showPopup: function (featureId, node, options) {
1776
+ // Keeping this as an API
1533
1777
  let myOptions = options
1534
1778
  if (this.mapImp) {
1535
1779
  if (myOptions) {
@@ -1540,11 +1784,22 @@ export default {
1540
1784
  this.mapImp.showPopup(featureId, node, myOptions)
1541
1785
  }
1542
1786
  },
1787
+ /**
1788
+ * @vuese
1789
+ * Function to show marker popup.
1790
+ * @arg featureId,
1791
+ * @arg node,
1792
+ * @arg options
1793
+ */
1543
1794
  showMarkerPopup: function (featureId, node, options) {
1544
1795
  if (this.mapImp) {
1545
1796
  this.mapImp.showMarkerPopup(featureId, node, options)
1546
1797
  }
1547
1798
  },
1799
+ /**
1800
+ * @vuese
1801
+ * Function to close minimap.
1802
+ */
1548
1803
  closeMinimap: function () {
1549
1804
  let minimapEl = this.$refs.flatmapContainer.querySelector(
1550
1805
  '.maplibregl-ctrl-minimap'
@@ -1559,6 +1814,9 @@ export default {
1559
1814
  }
1560
1815
  this.minimapSmall = !this.minimapSmall
1561
1816
  },
1817
+ /**
1818
+ * Function to add resize button to minimap.
1819
+ */
1562
1820
  addResizeButtonToMinimap: function () {
1563
1821
  let minimapEl = this.$refs.flatmapContainer.querySelector(
1564
1822
  '.maplibregl-ctrl-minimap'
@@ -1573,6 +1831,12 @@ export default {
1573
1831
  this.minimapResizeShow = true
1574
1832
  }
1575
1833
  },
1834
+ /**
1835
+ * @vuese
1836
+ * Function to set help mode
1837
+ * by providing flag ``helpMode`` (true/false).
1838
+ * @arg helpMode
1839
+ */
1576
1840
  setHelpMode: function (helpMode) {
1577
1841
  if (helpMode) {
1578
1842
  this.inHelp = true
@@ -1588,6 +1852,12 @@ export default {
1588
1852
  this.closeFlatmapHelpPopup()
1589
1853
  }
1590
1854
  },
1855
+ /**
1856
+ * @vuese
1857
+ * Function to show tooltip
1858
+ * by providing ``tooltipNumber``.
1859
+ * @arg tooltipNumber
1860
+ */
1591
1861
  showToolitip: function (tooltipNumber) {
1592
1862
  if (!this.inHelp) {
1593
1863
  clearTimeout(this.tooltipWait[tooltipNumber])
@@ -1596,6 +1866,12 @@ export default {
1596
1866
  }, 500)
1597
1867
  }
1598
1868
  },
1869
+ /**
1870
+ * @vuese
1871
+ * Function to hide tooltip
1872
+ * by providing ``tooltipNumber``.
1873
+ * @arg tooltipNumber
1874
+ */
1599
1875
  hideToolitip: function (tooltipNumber) {
1600
1876
  if (!this.inHelp) {
1601
1877
  clearTimeout(this.tooltipWait[tooltipNumber])
@@ -1604,6 +1880,12 @@ export default {
1604
1880
  }, 500)
1605
1881
  }
1606
1882
  },
1883
+ /**
1884
+ * @vuese
1885
+ * Function to display tooltip
1886
+ * by providing featureId (``feature``).
1887
+ * @arg feature
1888
+ */
1607
1889
  displayTooltip: function (feature, geometry = undefined) {
1608
1890
  this.tooltipDisplay = true
1609
1891
  let featureId = undefined
@@ -1618,10 +1900,16 @@ export default {
1618
1900
  }
1619
1901
  }
1620
1902
  if (!this.disableUI) {
1621
- this.mapImp.showPopup(featureId, this.$refs.tooltip.$el, options)
1903
+ this.$nextTick(() => {
1904
+ this.mapImp.showPopup(featureId, this.$refs.tooltip.$el, options)
1905
+ this.popUpCssHacks()
1906
+ })
1622
1907
  }
1623
- this.popUpCssHacks()
1624
1908
  },
1909
+ /**
1910
+ * @vuese
1911
+ * Function to open Flatmap Help Popup.
1912
+ */
1625
1913
  openFlatmapHelpPopup: function () {
1626
1914
  if (this.mapImp) {
1627
1915
  let heartId = this.mapImp.modelFeatureIds('UBERON:0000948')
@@ -1634,6 +1922,10 @@ export default {
1634
1922
  }
1635
1923
  }
1636
1924
  },
1925
+ /**
1926
+ * @vuese
1927
+ * Function to close Flatmap Help Popup.
1928
+ */
1637
1929
  closeFlatmapHelpPopup: function () {
1638
1930
  this.$el
1639
1931
  .querySelectorAll('.maplibregl-popup-close-button')
@@ -1641,6 +1933,10 @@ export default {
1641
1933
  item.click()
1642
1934
  })
1643
1935
  },
1936
+ /**
1937
+ * @vuese
1938
+ * Function to get annotation labels.
1939
+ */
1644
1940
  getLabels: function () {
1645
1941
  let labels = []
1646
1942
  if (this.mapImp) {
@@ -1651,6 +1947,10 @@ export default {
1651
1947
  return Array.from(new Set(labels))
1652
1948
  }
1653
1949
  },
1950
+ /**
1951
+ * @vuese
1952
+ * Function to get the state (object) of the map.
1953
+ */
1654
1954
  getState: function () {
1655
1955
  if (this.mapImp) {
1656
1956
  let state = {
@@ -1666,6 +1966,11 @@ export default {
1666
1966
  }
1667
1967
  return undefined
1668
1968
  },
1969
+ /**
1970
+ * @vuese
1971
+ * Function to set state (object) for the map.
1972
+ * @arg state
1973
+ */
1669
1974
  setState: function (state) {
1670
1975
  if (state) {
1671
1976
  if (
@@ -1683,12 +1988,40 @@ export default {
1683
1988
  this.setStateRequired = false
1684
1989
  }
1685
1990
  },
1991
+ /**
1992
+ * @vuese
1993
+ * Function to restore map's state
1994
+ * from the ``state`` provided.
1995
+ * @arg state
1996
+ */
1686
1997
  restoreMapState: function (state) {
1687
1998
  if (state) {
1688
1999
  if (state.viewport) this.mapImp.setState(state.viewport)
1689
2000
  if (state.searchTerm) this.searchAndShowResult(state.searchTerm, true)
1690
2001
  }
1691
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
+ */
1692
2025
  createFlatmap: function (state) {
1693
2026
  if (!this.mapImp && !this.loading) {
1694
2027
  this.loading = true
@@ -1746,18 +2079,16 @@ export default {
1746
2079
  //fullscreenControl: false,
1747
2080
  //annotatable: false,
1748
2081
  //debug: true,
1749
- featureInfo: this.featureInfo,
1750
- 'min-zoom': this.minZoom,
1751
- layerControl: true,
1752
- pathControls: true,
1753
- searchable: this.searchable,
2082
+ minZoom: this.minZoom,
1754
2083
  tooltips: this.tooltips,
1755
2084
  minimap: minimap,
1756
2085
  }
1757
2086
  )
1758
2087
  promise1.then((returnedObject) => {
1759
2088
  this.mapImp = returnedObject
1760
- 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)
1761
2092
  this.onFlatmapReady()
1762
2093
  if (this._stateToBeSet) this.restoreMapState(this._stateToBeSet)
1763
2094
  else {
@@ -1773,6 +2104,10 @@ export default {
1773
2104
  this.restoreMapState(this._stateToBeSet)
1774
2105
  }
1775
2106
  },
2107
+ /**
2108
+ * @vuese
2109
+ * Function to compute path controls maximum height.
2110
+ */
1776
2111
  computePathControlsMaximumHeight() {
1777
2112
  const elem = this.$refs.display
1778
2113
  if (elem) {
@@ -1783,6 +2118,10 @@ export default {
1783
2118
  this.pathwaysMaxHeight = height - 170
1784
2119
  }
1785
2120
  },
2121
+ /**
2122
+ * @vuese
2123
+ * Function to resize the map.
2124
+ */
1786
2125
  mapResize: function () {
1787
2126
  try {
1788
2127
  this.computePathControlsMaximumHeight()
@@ -1797,6 +2136,10 @@ export default {
1797
2136
  console.error('Map resize error')
1798
2137
  }
1799
2138
  },
2139
+ /**
2140
+ * @vuese
2141
+ * This function is used for functions that need to run immediately after the flatmap is loaded.
2142
+ */
1800
2143
  onFlatmapReady: function () {
1801
2144
  // onFlatmapReady is used for functions that need to run immediately after the flatmap is loaded
1802
2145
  this.sensor = new ResizeSensor(this.$refs.display, this.mapResize)
@@ -1816,17 +2159,36 @@ export default {
1816
2159
  this.computePathControlsMaximumHeight()
1817
2160
  this.drawerOpen = true
1818
2161
  this.mapResize()
2162
+ /**
2163
+ * This is ``onFlatmapReady`` event.
2164
+ * @arg ``this`` (Component Vue Instance)
2165
+ */
1819
2166
  this.$emit('ready', this)
1820
2167
  },
2168
+ /**
2169
+ * @vuese
2170
+ * Function to show or hide the minimap
2171
+ * by providing ``flag`` (boolean) value.
2172
+ * @arg flag
2173
+ */
1821
2174
  showMinimap: function (flag) {
1822
2175
  if (this.mapImp) this.mapImp.showMinimap(flag)
1823
2176
  },
2177
+ /**
2178
+ * @vuese
2179
+ * Function to show or hide the pathways drawer
2180
+ * by providing ``flag`` (boolean) value.
2181
+ * @arg flag
2182
+ */
1824
2183
  showPathwaysDrawer: function (flag) {
1825
2184
  this.drawerOpen = flag
1826
2185
  },
1827
2186
  /**
2187
+ * @vuese
1828
2188
  * Function to display features with annotation matching the provided term,
1829
2189
  * with the option to display the label using displayLabel flag.
2190
+ * @arg term,
2191
+ * @arg displayLabel
1830
2192
  */
1831
2193
  searchAndShowResult: function (term, displayLabel) {
1832
2194
  if (this.mapImp) {
@@ -1866,7 +2228,10 @@ export default {
1866
2228
  return false
1867
2229
  },
1868
2230
  /**
1869
- * Get the list of suggested terms
2231
+ * @vuese
2232
+ * Function to show search suggestions
2233
+ * from the ``term`` provided.
2234
+ * @arg term
1870
2235
  */
1871
2236
  searchSuggestions: function (term) {
1872
2237
  if (this.mapImp) return this.mapImp.search(term)
@@ -1874,48 +2239,66 @@ export default {
1874
2239
  },
1875
2240
  },
1876
2241
  props: {
1877
- 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
+ */
1878
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
+ */
1879
2259
  biologicalSex: {
1880
2260
  type: String,
1881
2261
  default: '',
1882
2262
  },
1883
- featureInfo: {
1884
- type: Boolean,
1885
- default: false,
1886
- },
2263
+ /**
2264
+ * The minimum zoom level of the map.
2265
+ */
1887
2266
  minZoom: {
1888
2267
  type: Number,
1889
2268
  default: 4,
1890
2269
  },
1891
- pathControls: {
1892
- type: Boolean,
1893
- default: false,
1894
- },
1895
- searchable: {
1896
- type: Boolean,
1897
- default: false,
1898
- },
1899
- layerControl: {
1900
- type: Boolean,
1901
- default: false,
1902
- },
2270
+ /**
2271
+ * The option to add another feature label _(`FeatureSmallSymbolLayer`)_
2272
+ * when this `tooltips` is set to `false`.
2273
+ */
1903
2274
  tooltips: {
1904
2275
  type: Boolean,
1905
2276
  default: true,
1906
2277
  },
2278
+ /**
2279
+ * The option to show tooltips for help mode.
2280
+ */
1907
2281
  helpMode: {
1908
2282
  type: Boolean,
1909
2283
  default: false,
1910
2284
  },
2285
+ /**
2286
+ * The option to create map on component mounted.
2287
+ */
1911
2288
  renderAtMounted: {
1912
2289
  type: Boolean,
1913
2290
  default: true,
1914
2291
  },
2292
+ /**
2293
+ * The option to display minimap at the top-right corner of the map.
2294
+ */
1915
2295
  displayMinimap: {
1916
2296
  type: Boolean,
1917
2297
  default: false,
1918
2298
  },
2299
+ /**
2300
+ * The option to show warning. Example for legacy or beta maps.
2301
+ */
1919
2302
  displayWarning: {
1920
2303
  type: Boolean,
1921
2304
  default: false,
@@ -1928,8 +2311,28 @@ export default {
1928
2311
  type: Boolean,
1929
2312
  default: false,
1930
2313
  },
2314
+ /**
2315
+ * The data to show different map options.
2316
+ * Available at the bottom-left corner ("Open new map" tooltip).
2317
+ */
1931
2318
  openMapOptions: {
1932
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
+ */
1933
2336
  default: function () {
1934
2337
  return [
1935
2338
  {
@@ -1947,14 +2350,24 @@ export default {
1947
2350
  ]
1948
2351
  },
1949
2352
  },
2353
+ /**
2354
+ * The option to show star in legend area.
2355
+ */
1950
2356
  showStarInLegend: {
1951
2357
  type: Boolean,
1952
2358
  default: false,
1953
2359
  },
2360
+ /**
2361
+ * Flag to determine whether this is legacy map or not.
2362
+ * ``displayWarning`` should be shown for legacy map.
2363
+ */
1954
2364
  isLegacy: {
1955
2365
  type: Boolean,
1956
2366
  default: false,
1957
2367
  },
2368
+ /**
2369
+ * The option to show the latest changes.
2370
+ */
1958
2371
  displayLatestChanges: {
1959
2372
  type: Boolean,
1960
2373
  default: false,
@@ -1973,6 +2386,9 @@ export default {
1973
2386
  type: String,
1974
2387
  default: 'https://mapcore-demo.org/current/flatmap/v3/',
1975
2388
  },
2389
+ /**
2390
+ * Specify the endpoint of the SPARC API.
2391
+ */
1976
2392
  sparcAPI: {
1977
2393
  type: String,
1978
2394
  default: 'https://api.sparc.science/',
@@ -1989,7 +2405,8 @@ export default {
1989
2405
  return {
1990
2406
  flatmapAPI: this.flatmapAPI,
1991
2407
  sparcAPI: this.sparcAPI,
1992
- $annotator: this.annotator
2408
+ $annotator: this.annotator,
2409
+ userApiKey: this.userToken
1993
2410
  }
1994
2411
  },
1995
2412
  data: function () {
@@ -1998,8 +2415,8 @@ export default {
1998
2415
  //tooltip display has to be set to false until it is rendered
1999
2416
  //for the first time, otherwise it may display an arrow at a
2000
2417
  //undesired location.
2001
- tooltipDisplay: true,
2002
- serverUUID: undefined,
2418
+ tooltipDisplay: false,
2419
+ serverURL: undefined,
2003
2420
  layers: [],
2004
2421
  pathways: [],
2005
2422
  sckanDisplay: [
@@ -2046,7 +2463,8 @@ export default {
2046
2463
  tooltipEntry: createUnfilledTooltipData(),
2047
2464
  connectivityTooltipVisible: false,
2048
2465
  drawerOpen: false,
2049
- dimensionRadio: false,
2466
+ flightPath3DRadio: false,
2467
+ displayFlightPathOption: false,
2050
2468
  colourRadio: true,
2051
2469
  outlinesRadio: true,
2052
2470
  minimapResizeShow: false,
@@ -2056,10 +2474,10 @@ export default {
2056
2474
  currentHover: '',
2057
2475
  viewingMode: 'Exploration',
2058
2476
  viewingModes: ['Annotation', 'Exploration', 'Network Discovery'],
2059
- drawingType: 'All',
2060
- drawingTypes: ['All', 'Point', 'LineString', 'Polygon', 'None'],
2061
- participationType: 'All',
2062
- participationTypes: ['All', 'Participated', 'Not participated'],
2477
+ drawnType: 'All tools',
2478
+ drawnTypes: ['All tools', 'Point', 'LineString', 'Polygon', 'None'],
2479
+ annotatedType: 'Anyone',
2480
+ annotatedTypes: ['Anyone', 'Me', 'Others'],
2063
2481
  openMapRef: undefined,
2064
2482
  backgroundIconRef: undefined,
2065
2483
  annotator: undefined,
@@ -2071,14 +2489,21 @@ export default {
2071
2489
  inDrawing: false,
2072
2490
  relevanceDisplay: false,
2073
2491
  relevanceEntry: {},
2074
- drawnAnnotationFeatures: undefined, // Store all exist drawn annotations
2492
+ drawnAnnotationFeatures: undefined, // Store all exist drawn features
2075
2493
  doubleClickedFeature: false,
2076
2494
  activeDrawMode: undefined,
2077
2495
  drawModes: ['Delete', 'Edit'],
2496
+ dialogPosition: {
2497
+ offsetX: 0,
2498
+ offsetY: 0,
2499
+ x: undefined,
2500
+ y: undefined
2501
+ }
2078
2502
  }
2079
2503
  },
2080
2504
  computed: {
2081
- hasRelevance: function () {
2505
+ ...mapState(useMainStore, ['userToken']),
2506
+ relevance: function () {
2082
2507
  return Object.keys(this.relevanceEntry).length > 0
2083
2508
  }
2084
2509
  },
@@ -2086,32 +2511,90 @@ export default {
2086
2511
  entry: function () {
2087
2512
  if (!this.state) this.createFlatmap()
2088
2513
  },
2089
- helpMode: function (val) {
2090
- this.setHelpMode(val)
2514
+ helpMode: function (newVal, oldVal) {
2515
+ if (newVal !== oldVal) {
2516
+ this.setHelpMode(val)
2517
+ }
2091
2518
  },
2092
2519
  state: {
2093
- handler: function (state) {
2094
- if (this.mapManager) {
2095
- this.setState(state)
2096
- } else {
2097
- //this component has not been mounted yet
2098
- 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
+ }
2099
2528
  }
2100
2529
  },
2101
2530
  immediate: true,
2102
2531
  deep: true,
2103
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
+ },
2104
2576
  viewingMode: function (mode) {
2105
2577
  if (mode === 'Annotation') {
2106
- this.showAnnotator(true)
2107
- this.annotator.authenticate().then((userData) => {
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) => {
2108
2589
  if (userData.name && userData.email) {
2590
+ this.showAnnotator(true)
2109
2591
  this.userInformation = userData
2110
2592
  this.setFeatureAnnotated()
2111
2593
  if (!this.drawnAnnotationFeatures) {
2112
2594
  this.addAnnotationFeature()
2113
2595
  }
2114
2596
  }
2597
+ this.loading = false
2115
2598
  })
2116
2599
  } else this.showAnnotator(false)
2117
2600
  },
@@ -2197,6 +2680,7 @@ export default {
2197
2680
  position: absolute;
2198
2681
  bottom: 0px;
2199
2682
  transition: all 1s ease;
2683
+ z-index: 8;
2200
2684
  &.open {
2201
2685
  left: 0px;
2202
2686
  }
@@ -2227,6 +2711,8 @@ export default {
2227
2711
  transition: all 1s ease;
2228
2712
  &.open {
2229
2713
  opacity: 1;
2714
+ position: relative;
2715
+ z-index: 2;
2230
2716
  }
2231
2717
  &.close {
2232
2718
  opacity: 0;
@@ -2269,7 +2755,8 @@ export default {
2269
2755
  }
2270
2756
 
2271
2757
  :deep(.maplibregl-popup) {
2272
- max-width: 300px !important;
2758
+ z-index: 10;
2759
+ max-width: 330px !important;
2273
2760
  }
2274
2761
 
2275
2762
  :deep(.flatmap-tooltip-popup) {
@@ -2383,15 +2870,21 @@ export default {
2383
2870
  }
2384
2871
  }
2385
2872
 
2386
- .drawPoint, .drawLineString, .drawPolygon, .drawTrash,
2387
- .connection, .comment, .zoomIn, .zoomOut, .fitWindow {
2388
- padding-left: 8px;
2873
+ .drawPoint, .drawLineString, .drawPolygon,
2874
+ .drawDelete, .drawEdit, .drawRelevance,
2875
+ .zoomIn, .zoomOut, .fitWindow {
2876
+ padding: 4px;
2389
2877
  }
2390
2878
 
2391
- .toolSelected {
2879
+ .iconSelected {
2392
2880
  color: var(--el-color-primary-light-5) !important;
2393
2881
  }
2394
2882
 
2883
+ .inactive {
2884
+ color: #DDDDDD !important;
2885
+ cursor: not-allowed !important;
2886
+ }
2887
+
2395
2888
  .yellow-star-legend {
2396
2889
  width: 130px;
2397
2890
  cursor: pointer;
@@ -2401,6 +2894,7 @@ export default {
2401
2894
  bottom: 16px;
2402
2895
  position: absolute;
2403
2896
  transition: all 1s ease;
2897
+ z-index: 10;
2404
2898
  &.open {
2405
2899
  left: 322px;
2406
2900
  }
@@ -2423,6 +2917,10 @@ export default {
2423
2917
  }
2424
2918
  }
2425
2919
 
2920
+ :deep(.background-popper.el-popover.el-popper.h-auto) {
2921
+ height: auto !important;
2922
+ }
2923
+
2426
2924
  :deep(.open-map-popper.el-popover.el-popper) {
2427
2925
  padding-top: 5px;
2428
2926
  padding-bottom: 5px;
@@ -2598,15 +3096,22 @@ export default {
2598
3096
  }
2599
3097
 
2600
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;
2601
3104
  position: absolute;
2602
- right: 40%;
3105
+ right: calc(50vw - 100px);;
2603
3106
  bottom: 16px;
3107
+ z-index: 10;
2604
3108
  }
2605
3109
 
2606
3110
  .bottom-right-control {
2607
3111
  position: absolute;
2608
3112
  right: 16px;
2609
3113
  bottom: 16px;
3114
+ z-index: 10;
2610
3115
  }
2611
3116
 
2612
3117
  :deep(.my-drawer) {
@@ -2793,34 +3298,10 @@ export default {
2793
3298
  }
2794
3299
  }
2795
3300
 
2796
- :deep(.el-dialog) {
2797
- text-align: justify;
2798
- border-radius: 4px;
2799
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
2800
- pointer-events: auto;
2801
- background: #fff;
2802
- border: 1px solid $app-primary-color;
2803
- display: flex;
2804
- flex-direction: column;
3301
+ .relevance-dialog {
2805
3302
  position: absolute;
2806
- left: 100px;
2807
- bottom: 0px;
2808
- }
2809
-
2810
- :deep(.el-dialog__body, .el-dialog__header) {
2811
- padding-top: 10px;
2812
- padding-bottom: 10px;
2813
- }
2814
-
2815
- .dialog-title {
2816
- font-size: 18px;
2817
- font-weight: bold;
2818
- color: rgb(131, 0, 191);
2819
- }
2820
-
2821
- :deep(.el-card) {
2822
- --el-card-padding: 12px;
2823
- border: 0;
3303
+ z-index: 10;
3304
+ cursor: move;
2824
3305
  }
2825
3306
  </style>
2826
3307