@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/dist/flatmapvuer.js +3339 -3239
- package/dist/flatmapvuer.umd.cjs +13 -10
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/FlatmapError.vue +84 -0
- package/src/components/FlatmapVuer.vue +176 -119
- package/src/components/MultiFlatmapVuer.vue +35 -3
- package/src/components.d.ts +2 -0
- package/src/services/flatmapKnowledge.js +8 -8
- package/src/services/flatmapQueries.js +1 -1
package/package.json
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
-
*
|
|
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
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
if (
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
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
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
)
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
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
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
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
|
-
|
|
1793
|
-
|
|
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
|
-
//
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
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
|
-
|
|
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.
|
|
2207
|
-
tooltip['mapuuid'] = this.mapImp.
|
|
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.
|
|
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: {
|
package/src/components.d.ts
CHANGED
|
@@ -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.
|
|
72
|
+
return getKnowledgeSourceFromProvenance(mapImp.mapMetadata);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function getKnowledgeSourceFromProvenance(
|
|
75
|
+
function getKnowledgeSourceFromProvenance(mapMetadata) {
|
|
76
76
|
let mapKnowledgeSource = '';
|
|
77
|
-
if (
|
|
78
|
-
const
|
|
79
|
-
if ('knowledge-source' in
|
|
80
|
-
mapKnowledgeSource =
|
|
81
|
-
} else if ('npo' in
|
|
82
|
-
mapKnowledgeSource = `${
|
|
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.
|
|
300
|
+
? this.queryMapConnectivity(mapImp.mapMetadata.uuid, keastId)
|
|
301
301
|
: mapImp.queryKnowledge(keastId);
|
|
302
302
|
|
|
303
303
|
queryAPI
|