@abi-software/flatmapvuer 1.11.3 → 1.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/flatmapvuer",
3
- "version": "1.11.3",
3
+ "version": "1.11.4",
4
4
  "license": "Apache-2.0",
5
5
  "files": [
6
6
  "dist/*",
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <!-- flatmap-error -->
3
+ <div class="flatmap-error">
4
+ <div class="flatmap-error-title">
5
+ <el-icon size="24">
6
+ <el-icon-document-delete />
7
+ </el-icon>
8
+ <div v-if="flatmapError.title">
9
+ {{ flatmapError.title }}
10
+ </div>
11
+ </div>
12
+ <div class="flatmap-error-message" v-if="flatmapError.messages">
13
+ <div v-for="(message, index) in flatmapError.messages" :key="index">
14
+ {{ message }}
15
+ </div>
16
+ </div>
17
+ <div v-if="flatmapError.button">
18
+ <el-button class="button" type="primary" @click="flatmapError.button.callback">
19
+ {{ flatmapError.button.text }}
20
+ </el-button>
21
+ </div>
22
+ </div>
23
+ </template>
24
+
25
+ <script>
26
+ export default {
27
+ name: 'FlatmapError',
28
+ // The flatmapError prop is an object that may have the following properties:
29
+ // 1. title: string
30
+ // 2. messages: string[]
31
+ // 3. button: { text: string, callback: Function }
32
+ props: {
33
+ flatmapError: {
34
+ type: Object,
35
+ default: () => ({}),
36
+ },
37
+ },
38
+ }
39
+ </script>
40
+
41
+ <style lang="scss" scoped>
42
+ .flatmap-error {
43
+ width: 100%;
44
+ height: 100%;
45
+ position: absolute;
46
+ top: 0;
47
+ left: 0;
48
+ display: flex;
49
+ justify-content: center;
50
+ align-items: center;
51
+ flex-direction: column;
52
+ gap: 1rem;;
53
+ }
54
+
55
+ .flatmap-error-title {
56
+ font-size: 18px;
57
+ text-align: center;
58
+ }
59
+
60
+ .flatmap-error-message {
61
+ text-align: left;
62
+ display: flex;
63
+ flex-direction: column;
64
+ gap: 0.5rem;
65
+ padding: 1rem;
66
+ line-height: 20px;
67
+ border: 1px solid var(--el-border-color);
68
+ border-radius: var(--el-border-radius-base);
69
+ max-width: 500px;
70
+ }
71
+
72
+ .el-button--primary.button {
73
+ font-family: inherit;
74
+
75
+ &:hover,
76
+ &:active,
77
+ &:focus {
78
+ background: $app-primary-color;
79
+ border-color: $app-primary-color;
80
+ box-shadow: 0px 0px 2px 0px rgba(131, 0, 191, 0.5);
81
+ color: #fff;
82
+ }
83
+ }
84
+ </style>
@@ -10,7 +10,11 @@
10
10
  <div
11
11
  style="height: 100%; width: 100%; position: relative; overflow-y: none"
12
12
  >
13
- <div style="height: 100%; width: 100%" ref="display"></div>
13
+ <!-- flatmap-display -->
14
+ <div style="height: 100%; width: 100%" ref="display" class="flatmap-display"></div>
15
+ <!-- flatmap-error -->
16
+ <FlatmapError v-if="flatmapError" :flatmapError="flatmapError" />
17
+
14
18
  <div class="beta-popovers" v-show="!disableUI">
15
19
  <div>
16
20
  <el-popover
@@ -643,7 +647,7 @@ import {
643
647
  import { capitalise } from './utilities.js'
644
648
  import yellowstar from '../icons/yellowstar'
645
649
  import ResizeSensor from 'css-element-queries/src/ResizeSensor'
646
- import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.3.0/+esm'
650
+ import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.3.5/+esm'
647
651
  import { AnnotationService } from '@abi-software/sparc-annotation'
648
652
  import { mapState } from 'pinia'
649
653
  import { useMainStore } from '@/store/index'
@@ -656,6 +660,7 @@ import {
656
660
  } from '@abi-software/map-utilities'
657
661
  import '@abi-software/map-utilities/dist/style.css'
658
662
  import EventBus from './EventBus.js'
663
+ import FlatmapError from './FlatmapError.vue'
659
664
 
660
665
  const ERROR_MESSAGE = 'cannot be found on the map.';
661
666
 
@@ -735,7 +740,8 @@ export default {
735
740
  ElIconWarningFilled,
736
741
  ElIconArrowDown,
737
742
  ElIconArrowLeft,
738
- DrawToolbar
743
+ DrawToolbar,
744
+ FlatmapError,
739
745
  },
740
746
  beforeCreate: function () {
741
747
  //The state watcher may triggered before
@@ -758,8 +764,13 @@ export default {
758
764
  }
759
765
  },
760
766
  /**
761
- *
762
- * @param filter format should follow #makeStyleFilter (flatmap-viewer)
767
+ * @public
768
+ * Function to set visibility filter for features and paths on the map.
769
+ * The param `filter` format should follow `#makeStyleFilter` (flatmap-viewer).
770
+ * If the param is `null` or `undefined`, the visibility filter will be cleared.
771
+ * Refer to [`setVisibilityFilter` in flatmap-viewer](https://anatomicmaps.github.io/flatmap-viewer/classes/index.FlatMap.html#setvisibilityfilter)
772
+ * for more details.
773
+ * @param {Object} `filter`
763
774
  */
764
775
  setVisibilityFilter: function (filter) {
765
776
  // More filter options -> this.mapImp.featureFilterRanges()
@@ -1629,6 +1640,8 @@ export default {
1629
1640
  this.connectionEntry = {}
1630
1641
  // For exist drawn annotation features
1631
1642
  if (this.selectedDrawnFeature) {
1643
+ // The `id` here is GeoJSONId from AnnotatedFeature
1644
+ // Ref: flatmap-viewer/src/flatmap-types.ts
1632
1645
  const drawnFeature = this.existDrawnFeatures.find(
1633
1646
  (feature) => feature.id === this.selectedDrawnFeature.id
1634
1647
  )
@@ -1666,6 +1679,18 @@ export default {
1666
1679
  if (data.type === 'deleted') this.previousDeletedEvent = data
1667
1680
  else this.previousDeletedEvent = {}
1668
1681
  },
1682
+ getTaxons: function (data) {
1683
+ let taxons = undefined
1684
+ if (data.taxons) {
1685
+ // check if data.taxons is string or array
1686
+ if (typeof data.taxons !== 'object') {
1687
+ taxons = JSON.parse(data.taxons)
1688
+ } else {
1689
+ taxons = data.taxons
1690
+ }
1691
+ }
1692
+ return taxons
1693
+ },
1669
1694
  /**
1670
1695
  * @public
1671
1696
  * A callback function, invoked when events occur with the map.
@@ -1681,118 +1706,98 @@ export default {
1681
1706
  eventType: eventType,
1682
1707
  }
1683
1708
  this.annotationEventCallback(payload, data)
1709
+ } else if (eventType === 'pan-zoom') {
1710
+ this.$emit('pan-zoom-callback', data)
1684
1711
  } else {
1685
- if (eventType !== 'pan-zoom') {
1686
- const label = data.label
1687
- const resource = [data.models]
1688
- const taxonomy = this.entry
1689
- const biologicalSex = this.biologicalSex
1690
- const featuresAlert = data.alert
1691
- let taxons = undefined
1692
- if (data.taxons) {
1693
- // check if data.taxons is string or array
1694
- if (typeof data.taxons !== 'object') {
1695
- taxons = JSON.parse(data.taxons)
1696
- } else {
1697
- taxons = data.taxons
1698
- }
1699
- }
1700
- let payload = [{
1701
- dataset: data.dataset,
1702
- biologicalSex: biologicalSex,
1703
- taxonomy: taxonomy,
1704
- resource: resource,
1705
- label: label,
1706
- feature: data,
1707
- userData: args,
1708
- eventType: eventType,
1709
- provenanceTaxonomy: taxons,
1710
- alert: featuresAlert
1711
- }]
1712
- if (eventType === 'click') {
1713
- const singleSelection = Object.keys(data).includes('id')
1714
- if (!singleSelection) {
1715
- payload = []
1716
- const mapuuid = data.mapUUID
1717
- const seenIds = new Set();
1718
- for (let [key, value] of Object.entries(data)) {
1719
- if (key !== 'mapUUID') {
1720
- const id = value.id
1721
- const label = value.label
1722
- const resource = [value.models]
1723
- let taxons = undefined
1724
- if (value.taxons) {
1725
- // check if data.taxons is string or array
1726
- if (typeof value.taxons !== 'object') {
1727
- taxons = JSON.parse(value.taxons)
1728
- } else {
1729
- taxons = value.taxons
1730
- }
1731
- }
1732
- if (seenIds.has(id)) continue;
1733
- seenIds.add(id);
1734
- payload.push({
1735
- dataset: value.dataset,
1736
- biologicalSex: biologicalSex,
1737
- taxonomy: taxonomy,
1738
- resource: resource,
1739
- label: label,
1740
- feature: value,
1741
- userData: args,
1742
- eventType: eventType,
1743
- provenanceTaxonomy: taxons,
1744
- alert: value.alert,
1745
- mapUUID: mapuuid
1746
- })
1747
- }
1712
+ const label = data.label
1713
+ const resource = [data.models]
1714
+ const taxonomy = this.entry
1715
+ const biologicalSex = this.biologicalSex
1716
+ const featuresAlert = data.alert
1717
+ const taxons = this.getTaxons(data)
1718
+ let payload = [{
1719
+ dataset: data.dataset,
1720
+ biologicalSex: biologicalSex,
1721
+ taxonomy: taxonomy,
1722
+ resource: resource,
1723
+ label: label,
1724
+ feature: data,
1725
+ userData: args,
1726
+ eventType: eventType,
1727
+ provenanceTaxonomy: taxons,
1728
+ alert: featuresAlert
1729
+ }]
1730
+ if (eventType === 'click') {
1731
+ // If multiple paths overlap at the click location,
1732
+ // `data` is an object with numeric keys for each feature (e.g., {0: {...}, 1: {...}, ..., mapUUID: '...'}).
1733
+ // If only one feature or path is clicked,
1734
+ // `data` is a single object (e.g., {featureId: '...', mapUUID: '...'}).
1735
+ const singleSelection = !data[0];
1736
+ if (!singleSelection) {
1737
+ payload = []
1738
+ const mapuuid = data.mapUUID
1739
+ const seenIds = new Set();
1740
+ for (let [key, value] of Object.entries(data)) {
1741
+ if (key !== 'mapUUID') {
1742
+ const id = value.featureId
1743
+ const label = value.label
1744
+ const resource = [value.models]
1745
+ const taxons = this.getTaxons(value)
1746
+ if (seenIds.has(id)) continue;
1747
+ seenIds.add(id);
1748
+ payload.push({
1749
+ dataset: value.dataset,
1750
+ biologicalSex: biologicalSex,
1751
+ taxonomy: taxonomy,
1752
+ resource: resource,
1753
+ label: label,
1754
+ feature: value,
1755
+ userData: args,
1756
+ eventType: eventType,
1757
+ provenanceTaxonomy: taxons,
1758
+ alert: value.alert,
1759
+ mapUUID: mapuuid
1760
+ })
1748
1761
  }
1749
1762
  }
1750
- const clickedItem = singleSelection ? data : data[0]
1751
- this.setConnectivityDataSource(this.viewingMode, clickedItem);
1752
- if (this.viewingMode === 'Neuron Connection') {
1753
- // do nothing here
1754
- // the method to highlight paths is moved to checkAndCreatePopups function
1755
- } else {
1756
- this.currentActive = clickedItem.models ? clickedItem.models : '' // This is for FC map
1757
- // This is for annotation mode - draw connectivity between features/paths
1758
- if (this.activeDrawTool && !this.isValidDrawnCreated) {
1759
- // Check if flatmap features or existing drawn features
1760
- const validDrawnFeature = clickedItem.featureId || this.existDrawnFeatures.find(
1761
- (feature) => feature.id === clickedItem.id
1762
- )
1763
- // Only the linestring will have connection
1764
- if (this.activeDrawTool === 'LineString' && validDrawnFeature) {
1765
- const key = clickedItem.featureId ? clickedItem.featureId : clickedItem.id
1766
- const nodeLabel = clickedItem.label ? clickedItem.label : `Feature ${clickedItem.id}`
1767
- // Add space before key to make sure properties follows adding order
1768
- this.connectionEntry[` ${key}`] = Object.assign(
1769
- { label: nodeLabel },
1770
- Object.fromEntries(
1771
- Object.entries(clickedItem)
1772
- .filter(([key]) => ['featureId', 'models'].includes(key))
1773
- .map(([key, value]) => [(key === 'featureId') ? 'id' : key, value])))
1774
- }
1763
+ }
1764
+ const clickedItem = singleSelection ? data : data[0]
1765
+ this.setConnectivityDataSource(this.viewingMode, clickedItem);
1766
+ if (this.viewingMode === 'Neuron Connection') {
1767
+ // do nothing here
1768
+ // the method to highlight paths is moved to checkAndCreatePopups function
1769
+ } else {
1770
+ this.currentActive = clickedItem.models ? clickedItem.models : '' // This is for FC map
1771
+ // This is for annotation mode - draw connectivity between features/paths
1772
+ if (this.activeDrawTool && !this.isValidDrawnCreated) {
1773
+ // Check if flatmap features or existing drawn features
1774
+ const validDrawnFeature = clickedItem.featureId || this.existDrawnFeatures.find(
1775
+ (feature) => feature.id === clickedItem.id
1776
+ )
1777
+ // Only the linestring will have connection
1778
+ if (this.activeDrawTool === 'LineString' && validDrawnFeature) {
1779
+ const key = clickedItem.featureId ? clickedItem.featureId : clickedItem.id
1780
+ const nodeLabel = clickedItem.label ? clickedItem.label : `Feature ${clickedItem.id}`
1781
+ // Add space before key to make sure properties follows adding order
1782
+ this.connectionEntry[` ${key}`] = Object.assign(
1783
+ { label: nodeLabel },
1784
+ Object.fromEntries(
1785
+ Object.entries(clickedItem)
1786
+ .filter(([key]) => ['featureId', 'models'].includes(key))
1787
+ .map(([key, value]) => [(key === 'featureId') ? 'id' : key, value])))
1775
1788
  }
1776
1789
  }
1777
- } else if (
1778
- eventType === 'mouseenter' &&
1779
- !(this.viewingMode === 'Neuron Connection')
1780
- ) {
1781
- this.currentHover = data.models ? data.models : ''
1782
1790
  }
1783
- if (
1784
- data &&
1785
- data.type !== 'marker' &&
1786
- eventType === 'click' &&
1787
- // Disable popup when drawing
1788
- !this.activeDrawTool
1789
- ) {
1791
+
1792
+ // Disable popup when drawing
1793
+ if (data && data.type !== 'marker' && !this.activeDrawTool) {
1790
1794
  this.checkAndCreatePopups(payload)
1791
1795
  }
1792
- this.$emit('resource-selected', payload)
1793
- } else {
1794
- this.$emit('pan-zoom-callback', data)
1796
+ } else if (eventType === 'mouseenter' && this.viewingMode !== 'Neuron Connection') {
1797
+ this.currentHover = data.models ? data.models : ''
1795
1798
  }
1799
+
1800
+ this.$emit('resource-selected', payload)
1796
1801
  }
1797
1802
  }
1798
1803
  },
@@ -1806,11 +1811,13 @@ export default {
1806
1811
  * @param data
1807
1812
  */
1808
1813
  setConnectivityDataSource: function (viewingMode, data) {
1809
- // for Exploration mode, only path click will be used as data source
1810
- this.connectivityDataSource = data.source;
1811
- // for other modes, it can be feature or path
1812
- if (viewingMode === 'Neuron Connection' || viewingMode === 'Annotation') {
1813
- this.connectivityDataSource = data.featureId;
1814
+ // Exploration mode, only path click will be used as data source
1815
+ if (viewingMode === 'Exploration') {
1816
+ this.connectivityDataSource = data.models.startsWith('ilxtr:') ? data.models : '';
1817
+ } else {
1818
+ // Other modes, it can be anything
1819
+ // (annotation drawing doesn't have featureId or models)
1820
+ this.connectivityDataSource = data.featureId || data.id;
1814
1821
  }
1815
1822
  },
1816
1823
  /**
@@ -2090,17 +2097,27 @@ export default {
2090
2097
  uniqueResource = [models, []];
2091
2098
  }
2092
2099
 
2100
+ const knowledgeSource = this.mapImp.knowledgeSource;
2093
2101
  const terms = uniqueResource.flat(Infinity);
2094
2102
  const uniqueTerms = [...new Set(terms)];
2095
2103
  const fetchResults = await fetchLabels(this.flatmapAPI, uniqueTerms);
2096
2104
  const objectResults = fetchResults.reduce((arr, item) => {
2097
2105
  const id = item[0];
2098
2106
  const valObj = JSON.parse(item[1]);
2099
- if (valObj.source === this.mapImp.knowledgeSource) {
2100
- arr.push({ id, label: valObj.label });
2101
- }
2107
+ arr.push({ id, label: valObj.label, source: valObj.source });
2102
2108
  return arr;
2103
2109
  }, []);
2110
+
2111
+ // sort matched knowledgeSource items for same id
2112
+ objectResults.sort((a, b) => {
2113
+ if (a.id === b.id) {
2114
+ if (a.source === knowledgeSource && b.source !== knowledgeSource) return -1;
2115
+ if (a.source !== knowledgeSource && b.source === knowledgeSource) return 1;
2116
+ return 0;
2117
+ }
2118
+ return a.id.localeCompare(b.id);
2119
+ });
2120
+
2104
2121
  const labels = [];
2105
2122
  for (let i = 0; i < uniqueTerms.length; i++) {
2106
2123
  const foundObj = objectResults.find((obj) => obj.id === uniqueTerms[i])
@@ -2203,8 +2220,8 @@ export default {
2203
2220
  tooltip['featuresAlert'] = data.alert;
2204
2221
  tooltip['knowledgeSource'] = getKnowledgeSource(this.mapImp);
2205
2222
  // Map id and uuid to load connectivity information from the map
2206
- tooltip['mapId'] = this.mapImp.provenance.id;
2207
- tooltip['mapuuid'] = this.mapImp.provenance.uuid;
2223
+ tooltip['mapId'] = this.mapImp.mapMetadata.id;
2224
+ tooltip['mapuuid'] = this.mapImp.mapMetadata.uuid;
2208
2225
  // } else {
2209
2226
  // tooltip = {
2210
2227
  // ...tooltip,
@@ -2482,6 +2499,12 @@ export default {
2482
2499
  if (geometry) {
2483
2500
  featureId = feature
2484
2501
  options.annotationFeatureGeometry = geometry
2502
+ if (this.annotationEntry.length) {
2503
+ options['annotationEvent'] = {
2504
+ type: this.annotationEntry[0].type,
2505
+ feature: this.annotationEntry[0].feature
2506
+ }
2507
+ }
2485
2508
  } else {
2486
2509
  const entry = Array.isArray(feature) ? feature[0] : feature
2487
2510
  if (entry) {
@@ -2741,6 +2764,7 @@ export default {
2741
2764
  createFlatmap: function (state) {
2742
2765
  if (!this.mapImp && !this.loading) {
2743
2766
  this.loading = true
2767
+ this.flatmapError = null
2744
2768
  let minimap = false
2745
2769
  if (this.displayMinimap) {
2746
2770
  minimap = { position: 'top-right' }
@@ -2809,6 +2833,36 @@ export default {
2809
2833
  const stateToSet = this._stateToBeSet ? this._stateToBeSet : state
2810
2834
  this.onFlatmapReady(stateToSet)
2811
2835
  this.$nextTick(() => this.restoreMapState(stateToSet))
2836
+ }).catch((error) => {
2837
+ console.error('Flatmap loading error:', error)
2838
+ // prepare error object
2839
+ this.flatmapError = {};
2840
+ if (error.message && error.message.indexOf('Unknown map') !== -1) {
2841
+ this.flatmapError['title'] = 'Unknown Map!';
2842
+ this.flatmapError['messages'] = Object.keys(identifier).map(key => {
2843
+ const keyName = key === 'uuid' ? 'UUID' : capitalise(key);
2844
+ return `${keyName}: ${identifier[key]}`
2845
+ });
2846
+ } else {
2847
+ this.flatmapError['title'] = 'Error Loading Map!';
2848
+ this.flatmapError['messages'] = [
2849
+ error.message ? error.message : error.toString(),
2850
+ 'Please try again later or contact support if the problem persists.'
2851
+ ];
2852
+ }
2853
+ if (this.$parent?.$refs?.multiContainer) {
2854
+ // if the flatmap is in a multiflatmapvuer
2855
+ // show a button to load default map
2856
+ const multiFlatmapVuer = this.$parent;
2857
+ this.flatmapError['button'] = {
2858
+ text: 'Load Default Map',
2859
+ callback: () => {
2860
+ const defaultSpecies = multiFlatmapVuer.initial;
2861
+ multiFlatmapVuer.setSpecies(defaultSpecies, undefined, 3);
2862
+ }
2863
+ };
2864
+ }
2865
+ this.loading = false;
2812
2866
  })
2813
2867
  } else if (state) {
2814
2868
  this._stateToBeSet = {
@@ -3284,7 +3338,9 @@ export default {
3284
3338
  */
3285
3339
  externalLegends: {
3286
3340
  type: Array,
3287
- default: [],
3341
+ default: function () {
3342
+ return []
3343
+ },
3288
3344
  },
3289
3345
  },
3290
3346
  provide() {
@@ -3296,6 +3352,7 @@ export default {
3296
3352
  },
3297
3353
  data: function () {
3298
3354
  return {
3355
+ flatmapError: null,
3299
3356
  sensor: null,
3300
3357
  mapManagerRef: undefined,
3301
3358
  flatmapQueries: undefined,
@@ -93,6 +93,9 @@
93
93
  :showPathwayFilter="showPathwayFilter"
94
94
  :externalLegends="externalLegends"
95
95
  />
96
+
97
+ <!-- multiflatmap-error -->
98
+ <FlatmapError v-if="multiflatmapError" :flatmapError="multiflatmapError" />
96
99
  </div>
97
100
  </template>
98
101
 
@@ -101,7 +104,7 @@
101
104
  import { markRaw } from 'vue'
102
105
  import EventBus from './EventBus'
103
106
  import FlatmapVuer from './FlatmapVuer.vue'
104
- import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.3.0/+esm'
107
+ import * as flatmap from 'https://cdn.jsdelivr.net/npm/@abi-software/flatmap-viewer@4.3.5/+esm'
105
108
  import {
106
109
  ElCol as Col,
107
110
  ElOption as Option,
@@ -156,6 +159,7 @@ export default {
156
159
  * It returns a promise.
157
160
  */
158
161
  initialise: function () {
162
+ this.multiflatmapError = null;
159
163
  return new Promise((resolve) => {
160
164
  if (this.requireInitialisation) {
161
165
  //It has not been initialised yet
@@ -163,11 +167,21 @@ export default {
163
167
  fetch(this.flatmapAPI)
164
168
  .then((response) => response.json())
165
169
  .then((data) => {
170
+ if (data.status_code === 404) {
171
+ console.error('Flatmap API endpoint is incorrect', data);
172
+ this.multiflatmapError = {};
173
+ this.multiflatmapError['title'] = 'MultiFlatmap Error!';
174
+ this.multiflatmapError['messages'] = [
175
+ `Sorry, the component could not be loaded because the specified
176
+ flatmap API endpoint is incorrect. Please check the endpoint URL
177
+ or contact support if the problem persists.`
178
+ ];
179
+ }
166
180
  //Check each key in the provided availableSpecies against the one
167
181
  Object.keys(this.availableSpecies).forEach((key) => {
168
182
  // FIrst look through the uuid
169
183
  const uuid = this.availableSpecies[key].uuid
170
- if (uuid && data.map((e) => e.uuid).indexOf(uuid) > 0) {
184
+ if (uuid && data.length && data.map((e) => e.uuid).indexOf(uuid) > 0) {
171
185
  this.speciesList[key] = this.availableSpecies[key]
172
186
  } else {
173
187
  for (let i = 0; i < data.length; i++) {
@@ -220,6 +234,21 @@ export default {
220
234
  other()
221
235
  })
222
236
  })
237
+ .catch((error) => {
238
+ console.error('Error fetching flatmap:', error)
239
+ this.initialised = true;
240
+ this.multiflatmapError = {};
241
+ this.multiflatmapError['title'] = 'MultiFlatmap Error!';
242
+ this.multiflatmapError['messages'] = [
243
+ `Sorry, the component could not be loaded due to an unexpected error.
244
+ Please try again later or contact support if the problem persists.`
245
+ ];
246
+ resolve()
247
+ //Resolve all other promises resolve in the list
248
+ this.resolveList.forEach((other) => {
249
+ other()
250
+ })
251
+ })
223
252
  } else if (this.initialised) {
224
253
  //resolve as it has been initialised
225
254
  resolve()
@@ -805,7 +834,9 @@ export default {
805
834
  */
806
835
  externalLegends: {
807
836
  type: Array,
808
- default: [],
837
+ default: function () {
838
+ return []
839
+ },
809
840
  },
810
841
  },
811
842
  data: function () {
@@ -816,6 +847,7 @@ export default {
816
847
  resolveList: markRaw([]),
817
848
  initialised: false,
818
849
  mapManagerRef: undefined,
850
+ multiflatmapError: null,
819
851
  }
820
852
  },
821
853
  watch: {
@@ -15,6 +15,7 @@ declare module 'vue' {
15
15
  ElIcon: typeof import('element-plus/es')['ElIcon']
16
16
  ElIconArrowDown: typeof import('@element-plus/icons-vue')['ArrowDown']
17
17
  ElIconArrowLeft: typeof import('@element-plus/icons-vue')['ArrowLeft']
18
+ ElIconDocumentDelete: typeof import('@element-plus/icons-vue')['DocumentDelete']
18
19
  ElIconWarning: typeof import('@element-plus/icons-vue')['Warning']
19
20
  ElIconWarningFilled: typeof import('@element-plus/icons-vue')['WarningFilled']
20
21
  ElOption: typeof import('element-plus/es')['ElOption']
@@ -23,6 +24,7 @@ declare module 'vue' {
23
24
  ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
24
25
  ElRow: typeof import('element-plus/es')['ElRow']
25
26
  ElSelect: typeof import('element-plus/es')['ElSelect']
27
+ FlatmapError: typeof import('./components/FlatmapError.vue')['default']
26
28
  FlatmapVuer: typeof import('./components/FlatmapVuer.vue')['default']
27
29
  MultiFlatmapVuer: typeof import('./components/MultiFlatmapVuer.vue')['default']
28
30
  SelectionsGroup: typeof import('./components/SelectionsGroup.vue')['default']
@@ -69,17 +69,17 @@ async function filterPathsByViaFromKnowledge(resource) {
69
69
  }
70
70
 
71
71
  function getKnowledgeSource(mapImp) {
72
- return getKnowledgeSourceFromProvenance(mapImp.provenance);
72
+ return getKnowledgeSourceFromProvenance(mapImp.mapMetadata);
73
73
  }
74
74
 
75
- function getKnowledgeSourceFromProvenance(provenance) {
75
+ function getKnowledgeSourceFromProvenance(mapMetadata) {
76
76
  let mapKnowledgeSource = '';
77
- if (provenance?.connectivity) {
78
- const sckanProvenance = provenance.connectivity;
79
- if ('knowledge-source' in sckanProvenance) {
80
- mapKnowledgeSource = sckanProvenance['knowledge-source'];
81
- } else if ('npo' in sckanProvenance) {
82
- mapKnowledgeSource = `${sckanProvenance.npo.release}-npo`;
77
+ if (mapMetadata?.connectivity) {
78
+ const mapMetadataConnectivity = mapMetadata.connectivity;
79
+ if ('knowledge-source' in mapMetadataConnectivity) {
80
+ mapKnowledgeSource = mapMetadataConnectivity['knowledge-source'];
81
+ } else if ('npo' in mapMetadataConnectivity) {
82
+ mapKnowledgeSource = `${mapMetadataConnectivity.npo.release}-npo`;
83
83
  }
84
84
  }
85
85
  return mapKnowledgeSource;
@@ -297,7 +297,7 @@ let FlatmapQueries = function () {
297
297
  this.connectivitySource = connectivitySource
298
298
  return new Promise((resolve) => {
299
299
  const queryAPI = connectivitySource === 'map'
300
- ? this.queryMapConnectivity(mapImp.provenance.uuid, keastId)
300
+ ? this.queryMapConnectivity(mapImp.mapMetadata.uuid, keastId)
301
301
  : mapImp.queryKnowledge(keastId);
302
302
 
303
303
  queryAPI