@abi-software/flatmapvuer 1.10.3-beta.8 → 1.11.0-beta.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/flatmapvuer",
3
- "version": "1.10.3-beta.8",
3
+ "version": "1.11.0-beta.1",
4
4
  "license": "Apache-2.0",
5
5
  "files": [
6
6
  "dist/*",
@@ -44,7 +44,7 @@
44
44
  "./src/*": "./src/*"
45
45
  },
46
46
  "dependencies": {
47
- "@abi-software/map-utilities": "^1.6.1-beta.5",
47
+ "@abi-software/map-utilities": "^1.6.1-beta.6",
48
48
  "@abi-software/sparc-annotation": "0.3.2",
49
49
  "@abi-software/svg-sprite": "^1.0.1",
50
50
  "@element-plus/icons-vue": "^2.3.1",
@@ -643,9 +643,6 @@ import {
643
643
  refreshFlatmapKnowledgeCache,
644
644
  getKnowledgeSource,
645
645
  getReferenceConnectivitiesByAPI,
646
- filterPathsByOriginFromKnowledge,
647
- filterPathsByDestinationFromKnowledge,
648
- filterPathsByViaFromKnowledge,
649
646
  } from '../services/flatmapKnowledge.js'
650
647
  import { capitalise } from './utilities.js'
651
648
  import yellowstar from '../icons/yellowstar'
@@ -655,14 +652,10 @@ import { AnnotationService } from '@abi-software/sparc-annotation'
655
652
  import { mapState } from 'pinia'
656
653
  import { useMainStore } from '@/store/index'
657
654
  import {
658
- queryPathsByOrigin,
659
- queryPathsByViaLocation,
660
- queryPathsByDestination,
661
655
  extractOriginItems,
662
656
  extractDestinationItems,
663
657
  extractViaItems,
664
658
  fetchLabels,
665
- queryAllConnectedPaths,
666
659
  DrawToolbar,
667
660
  Tooltip,
668
661
  TreeControls
@@ -833,7 +826,7 @@ export default {
833
826
  ? this.mapImp.featureProperties(numericId)
834
827
  : { feature: this.existDrawnFeatures.find(feature => feature.id === value.trim()) };
835
828
  let payload = { feature: featureObject }
836
- this.checkAndCreatePopups([payload])
829
+ this.checkAndCreatePopups([payload], false)
837
830
  } else {
838
831
  this.closeTooltip()
839
832
  }
@@ -845,7 +838,7 @@ export default {
845
838
  */
846
839
  confirmDrawnFeature: function () {
847
840
  if (this.isValidDrawnCreated) {
848
- this.checkAndCreatePopups([this.drawnCreatedEvent])
841
+ this.checkAndCreatePopups([this.drawnCreatedEvent], false)
849
842
  // Add connection if exist to annotationEntry
850
843
  // Connection will only be added in creating new drawn feature annotation
851
844
  // And will not be updated if move drawn features
@@ -1343,12 +1336,6 @@ export default {
1343
1336
  * @arg {string} `pathId` or `anatomicalId`
1344
1337
  */
1345
1338
  retrieveConnectedPaths: async function (payload, options = {}) {
1346
- // query all connected paths CQ
1347
- if (this.viewingMode === 'Neuron Connection' && this.connectionType.toLowerCase() === 'all') {
1348
- const sourceId = this.mapImp.uuid;
1349
- const connectedPaths = await queryAllConnectedPaths(this.flatmapAPI, sourceId, payload);
1350
- return connectedPaths;
1351
- }
1352
1339
  // query all connected paths from flatmap
1353
1340
  if (this.mapImp) {
1354
1341
  let connectedPaths = [];
@@ -1522,7 +1509,7 @@ export default {
1522
1509
  * @arg {String} `models`
1523
1510
  */
1524
1511
  ftuSelected: function (models) {
1525
- this.searchAndShowResult(models, true)
1512
+ this.searchAndShowResult(models, true, true)
1526
1513
  },
1527
1514
  /**
1528
1515
  * @public
@@ -2027,7 +2014,7 @@ export default {
2027
2014
  * _checkNeuronClicked shows a neuron path pop up if a path was recently clicked._
2028
2015
  * @arg {Object} `data`
2029
2016
  */
2030
- checkAndCreatePopups: async function (data, connectivityExplorerClicked) {
2017
+ checkAndCreatePopups: async function (data, mapclick = true) {
2031
2018
  // Call flatmap database to get the connection data
2032
2019
  if (this.viewingMode === 'Annotation') {
2033
2020
  const features = data.filter(d => d.feature).map(d => d.feature)
@@ -2077,7 +2064,7 @@ export default {
2077
2064
  }
2078
2065
  // clicking on a connectivity explorer card will be the same as exploration mode
2079
2066
  // the card should be opened without doing other functions
2080
- else if (this.viewingMode === 'Neuron Connection' && !connectivityExplorerClicked) {
2067
+ else if (this.viewingMode === 'Neuron Connection' && mapclick) {
2081
2068
  const resources = data.map(tooltip => tooltip.resource[0]);
2082
2069
 
2083
2070
  // filter out paths
@@ -2092,11 +2079,16 @@ export default {
2092
2079
  const featureId = data[0].feature?.featureId;
2093
2080
  const annotation = this.mapImp.annotations.get(featureId);
2094
2081
  const anatomicalNodes = annotation?.['anatomical-nodes'];
2082
+ const annotationModels = annotation?.['models'];
2095
2083
  let anatomicalNode;
2096
2084
  let uniqueResource = transformResources;
2097
2085
  const models = annotation?.['models'];
2098
2086
  if (anatomicalNodes?.length) {
2099
- anatomicalNode = anatomicalNodes[anatomicalNodes.length - 1];
2087
+ // get the node which match the feature in a location
2088
+ // [feature, location]
2089
+ anatomicalNode = anatomicalNodes.find((node) =>
2090
+ JSON.parse(node)[0] === annotationModels
2091
+ );
2100
2092
  }
2101
2093
  if (anatomicalNode) {
2102
2094
  uniqueResource = JSON.parse(anatomicalNode);
@@ -2139,18 +2131,10 @@ export default {
2139
2131
  this.connectivityFilters.push(newConnectivityfilter);
2140
2132
  }
2141
2133
 
2142
- if (this.connectionType.toLowerCase() === 'all') {
2143
- const searchTerms = uniqueTerms.join();
2144
- this.$emit('neuron-connection-feature-click', {
2145
- filters: [],
2146
- search: searchTerms,
2147
- });
2148
- } else {
2149
- this.$emit('neuron-connection-feature-click', {
2150
- filters: this.connectivityFilters,
2151
- search: '',
2152
- });
2153
- }
2134
+ this.$emit('neuron-connection-feature-click', {
2135
+ filters: this.connectivityFilters,
2136
+ search: '',
2137
+ });
2154
2138
  } else {
2155
2139
  // clicking on paths
2156
2140
  // do nothing for origin, destination, via
@@ -2733,7 +2717,7 @@ export default {
2733
2717
  if (state.background) this.backgroundChangeCallback(state.background)
2734
2718
  if (state.searchTerm) {
2735
2719
  const searchTerm = state.searchTerm
2736
- this.searchAndShowResult(searchTerm, true)
2720
+ this.searchAndShowResult(searchTerm, true, true)
2737
2721
  }
2738
2722
  this.setVisibilityState(state)
2739
2723
  }
@@ -2980,7 +2964,7 @@ export default {
2980
2964
  const id = knowledge.id;
2981
2965
  if (id) {
2982
2966
  const mapKnowledgeObj = mapKnowledge[id];
2983
- if (mapKnowledgeObj) {
2967
+ if (mapKnowledgeObj && mapKnowledgeObj.connectivity && mapKnowledgeObj['node-phenotypes']) {
2984
2968
  const mapConnectivity = mapKnowledgeObj.connectivity;
2985
2969
  const mapNodePhenotypes = mapKnowledgeObj['node-phenotypes'];
2986
2970
  // take only map connectivity
@@ -3010,7 +2994,7 @@ export default {
3010
2994
  };
3011
2995
  }
3012
2996
 
3013
- for (const facet of ["origin", "via", "destination"]) {
2997
+ for (const facet of ["origin", "via", "destination", "all"]) {
3014
2998
  let childrenList = []
3015
2999
  if (facet === 'origin') {
3016
3000
  childrenList = originItems.map((item) => transformItem(facet, item));
@@ -3018,6 +3002,20 @@ export default {
3018
3002
  childrenList = viaItems.map((item) => transformItem(facet, item));
3019
3003
  } else if (facet === 'destination') {
3020
3004
  childrenList = destinationItems.map((item) => transformItem(facet, item));
3005
+ } else {
3006
+ // All is the combination of origin, via, destination
3007
+ const allList = [
3008
+ ...originItems.map((item) => transformItem(facet, item)),
3009
+ ...viaItems.map((item) => transformItem(facet, item)),
3010
+ ...destinationItems.map((item) => transformItem(facet, item))
3011
+ ];
3012
+ // Generate unique list since the same feature can be in origin, via, and destination
3013
+ const seenKeys = new Set();
3014
+ childrenList = allList.filter(item => {
3015
+ if (seenKeys.has(item.key)) return false;
3016
+ seenKeys.add(item.key);
3017
+ return true;
3018
+ });
3021
3019
  }
3022
3020
 
3023
3021
  // Those without label but key should be below
@@ -3032,14 +3030,18 @@ export default {
3032
3030
  return a.label.localeCompare(b.label);
3033
3031
  });
3034
3032
 
3035
- connectionFilters.push({
3036
- key: `flatmap.connectivity.source.${facet}`,
3037
- label: facet,
3038
- children: childrenList,
3039
- })
3033
+ if (childrenList.length) {
3034
+ connectionFilters.push({
3035
+ key: `flatmap.connectivity.source.${facet}`,
3036
+ label: facet,
3037
+ children: childrenList,
3038
+ })
3039
+ }
3040
3040
  }
3041
3041
 
3042
- filterOptions.push(...connectionFilters)
3042
+ if (connectionFilters.length) {
3043
+ filterOptions.push(...connectionFilters)
3044
+ }
3043
3045
  }
3044
3046
  return filterOptions;
3045
3047
  },
@@ -3118,8 +3120,9 @@ export default {
3118
3120
  * with the option to display the label/connectivity information using displayInfo flag.
3119
3121
  * @arg {String} `term`,
3120
3122
  * @arg {String} `displayInfo`
3123
+ * @arg {String} `mapclick` Similate the event as it is triggered by an user click
3121
3124
  */
3122
- searchAndShowResult: function (term, displayInfo, connectivityExplorerClicked) {
3125
+ searchAndShowResult: function (term, displayInfo, mapclick = true) {
3123
3126
  if (this.mapImp) {
3124
3127
  if (term === undefined || term === '') {
3125
3128
  this.mapImp.clearSearchResults()
@@ -3151,7 +3154,7 @@ export default {
3151
3154
  alert: feature.alert,
3152
3155
  }
3153
3156
  // Show popup for all modes
3154
- this.checkAndCreatePopups([data], connectivityExplorerClicked)
3157
+ this.checkAndCreatePopups([data], mapclick)
3155
3158
  this.mapImp.showPopup(featureId, capitalise(feature.label), {
3156
3159
  className: 'custom-popup',
3157
3160
  positionAtLastClick: false,
@@ -6,12 +6,7 @@
6
6
  :key="item[identifierKey]"
7
7
  :label="item[identifierKey]"
8
8
  >
9
- <div
10
- v-if="legendStyle(item) === 'yellow-star'"
11
- :class="legendStyle(item)"
12
- v-html="showStarInLegend ? yellowstar : ''"
13
- ></div>
14
- <div v-else class="legend-item">
9
+ <div class="legend-item" v-if="legendStyle(item)">
15
10
  <div
16
11
  :class="legendStyle(item)"
17
12
  :style="{ 'background-color': item[colourKey] }"
@@ -23,7 +18,6 @@
23
18
  </template>
24
19
 
25
20
  <script>
26
- import yellowstar from "../../icons/yellowstar";
27
21
  /* eslint-disable no-alert, no-console */
28
22
  export default {
29
23
  name: "DynamicLegends",
@@ -55,11 +49,6 @@ export default {
55
49
  default: false,
56
50
  },
57
51
  },
58
- data: function () {
59
- return {
60
- yellowstar: yellowstar,
61
- };
62
- },
63
52
  methods: {
64
53
  capitalise: function (label) {
65
54
  return label.charAt(0).toUpperCase() + label.slice(1).toLowerCase();
@@ -67,6 +56,9 @@ export default {
67
56
  legendStyle: function (item) {
68
57
  if (item[this.styleKey] === "star") {
69
58
  if (item[this.identifierKey] === "Featured dataset marker") {
59
+ if (!this.showStarInLegend) {
60
+ return;
61
+ }
70
62
  return "yellow-star";
71
63
  } else if (item[this.identifierKey] === "Gaglionated nerve plexus") {
72
64
  return "hexagon-star";
@@ -101,20 +93,31 @@ export default {
101
93
  display: inline-block;
102
94
  }
103
95
 
104
- // hexagon
105
96
  .hexagon-star {
106
- width: 21px;
97
+ width: 20px;
107
98
  height: 25px;
108
99
  background-color: #ffffff;
109
100
  opacity: 0.64;
110
101
  clip-path: path(
111
- "M10.48 0.76 c-2.12 3.72 -6.12 6.04 -10.44 6.04 l-0.16 0.24 c2.04 3.6 2.04 8 0 11.6 l0.16 0.24 c4.28 0 8.32 2.32 10.44 6.04 c2.12 -3.72 6.12 -6.04 10.44 -6.04 c-2.12 -3.72 -2.12 -8.36 0 -12.16 C16.64 6.84 12.68 4.52 10.48 0.76z"
102
+ "M9.96 0.72 c-2.01 3.53 -5.81 5.74 -9.92 5.74 l-0.15 0.23 c1.94 3.42 1.94 7.6 0 11.02 l0.15 0.23 c4.07 0 7.9 2.2 9.92 5.74 c2.01 -3.53 5.81 -5.74 9.92 -5.74 c-2.01 -3.53 -2.01 -7.94 0 -11.55 C15.81 6.5 12.04 4.29 9.96 0.72z"
112
103
  );
113
104
  -webkit-clip-path: path(
114
- "M10.48 0.76 c-2.12 3.72 -6.12 6.04 -10.44 6.04 l-0.16 0.24 c2.04 3.6 2.04 8 0 11.6 l0.16 0.24 c4.28 0 8.32 2.32 10.44 6.04 c2.12 -3.72 6.12 -6.04 10.44 -6.04 c-2.12 -3.72 -2.12 -8.36 0 -12.16 C16.64 6.84 12.68 4.52 10.48 0.76z"
105
+ "M9.96 0.72 c-2.01 3.53 -5.81 5.74 -9.92 5.74 l-0.15 0.23 c1.94 3.42 1.94 7.6 0 11.02 l0.15 0.23 c4.07 0 7.9 2.2 9.92 5.74 c2.01 -3.53 5.81 -5.74 9.92 -5.74 c-2.01 -3.53 -2.01 -7.94 0 -11.55 C15.81 6.5 12.04 4.29 9.96 0.72z"
115
106
  );
116
107
  }
117
108
 
109
+ .yellow-star {
110
+ width: 25px;
111
+ height: 25px;
112
+ background-color: #ffffff !important;
113
+ background-image: url("data:image/svg+xml,%3Csvg%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Cpath%20fill%3D%22yellow%22%20stroke%3D%22%23000%22%20stroke-width%3D%222%22%20d%3D%22M11.0748%203.25583C11.4141%202.42845%2012.5859%202.42845%2012.9252%203.25583L14.6493%207.45955C14.793%207.80979%2015.1221%208.04889%2015.4995%208.07727L20.0303%208.41798C20.922%208.48504%2021.2841%209.59942%2020.6021%2010.1778L17.1369%2013.1166C16.8482%2013.3614%2016.7225%2013.7483%2016.8122%2014.1161L17.8882%2018.5304C18.1%2019.3992%2017.152%2020.0879%2016.3912%2019.618L12.5255%2017.2305C12.2034%2017.0316%2011.7966%2017.0316%2011.4745%2017.2305L7.60881%2019.618C6.84796%2020.0879%205.90001%2019.3992%206.1118%2018.5304L7.18785%2014.1161C7.2775%2013.7483%207.1518%2013.3614%206.86309%2013.1166L3.3979%2010.1778C2.71588%209.59942%203.07796%208.48504%203.96971%208.41798L8.50046%208.07727C8.87794%208.04889%209.20704%207.80979%209.35068%207.45955L11.0748%203.25583Z%22/%3E%3C/svg%3E");
114
+ background-repeat: no-repeat;
115
+ background-size: contain;
116
+ display: inline-block;
117
+ margin: -3px;
118
+ padding-right: 2px;
119
+ }
120
+
118
121
  .label {
119
122
  margin-left: 14px;
120
123
  font-size: 12px;
@@ -25,9 +25,8 @@ async function getReferenceConnectivitiesByAPI(mapImp, resource, flatmapQueries)
25
25
  const sql = `select knowledge from knowledge
26
26
  where source="${knowledgeSource}" and
27
27
  knowledge like "%${resource}%" order by source desc`;
28
- const response = await flatmapQueries.flatmapQuery(sql);
29
- const mappedData = response.values.map((x) => x[0]);
30
- const parsedData = mappedData.map((x) => JSON.parse(x));
28
+ const response = await flatmapQueries.queryKnowledge(sql);
29
+ const parsedData = response.map((x) => JSON.parse(x));
31
30
  const featureIds = parsedData.map((x) => x.id);
32
31
  return featureIds;
33
32
  }
@@ -97,9 +96,8 @@ async function loadAndStoreKnowledge(mapImp, flatmapQueries) {
97
96
  const flatmapKnowledgeSource = sessionStorage.getItem('flatmap-knowledge-source');
98
97
 
99
98
  if (!flatmapKnowledge || flatmapKnowledgeSource !== knowledgeSource) {
100
- const response = await flatmapQueries.flatmapQuery(sql);
101
- const mappedData = response.values.map(x => x[0]);
102
- const parsedData = mappedData.map(x => JSON.parse(x));
99
+ const response = await flatmapQueries.queryKnowledge(sql);
100
+ const parsedData = response.map(x => JSON.parse(x));
103
101
 
104
102
  sessionStorage.setItem('flatmap-knowledge', JSON.stringify(parsedData));
105
103
  sessionStorage.setItem('flatmap-knowledge-source', knowledgeSource);
@@ -104,6 +104,7 @@ let FlatmapQueries = function () {
104
104
  this.uberons = []
105
105
  this.lookUp = []
106
106
  this.connectivitySource = 'map' // 'sckan'
107
+ this.noMapConnectivity = false
107
108
  }
108
109
 
109
110
  this.createTooltipData = async function (mapImp, eventData) {
@@ -144,7 +145,8 @@ let FlatmapQueries = function () {
144
145
  hyperlinks: hyperlinks,
145
146
  provenanceTaxonomy: eventData.provenanceTaxonomy,
146
147
  provenanceTaxonomyLabel: taxonomyLabel,
147
- connectivitySource: this.connectivitySource
148
+ connectivitySource: this.connectivitySource,
149
+ noMapConnectivity: this.noMapConnectivity,
148
150
  }
149
151
  return tooltipData
150
152
  }
@@ -158,7 +160,8 @@ let FlatmapQueries = function () {
158
160
  componentsWithDatasets: this.componentsWithDatasets,
159
161
  destinations: this.destinations,
160
162
  destinationsWithDatasets: this.destinationsWithDatasets,
161
- connectivitySource: this.connectivitySource
163
+ connectivitySource: this.connectivitySource,
164
+ noMapConnectivity: this.noMapConnectivity,
162
165
  };
163
166
  }
164
167
 
@@ -300,6 +303,9 @@ let FlatmapQueries = function () {
300
303
  queryAPI
301
304
  .then((response) => {
302
305
  if (this.checkConnectivityExists(response)) {
306
+ if (connectivitySource === 'map') {
307
+ this.noMapConnectivity = false;
308
+ }
303
309
  let connectivity = response;
304
310
  if (processConnectivity) {
305
311
  this.processConnectivity(mapImp, connectivity).then((processedConnectivity) => {
@@ -312,6 +318,32 @@ let FlatmapQueries = function () {
312
318
  })
313
319
  }
314
320
  else resolve(connectivity)
321
+ } else if (connectivitySource === 'map') {
322
+ // switch to SCKAN
323
+ // when there has no connectivity data from Map
324
+ // and add the noMapConnectivity flag to disable the option
325
+ this.connectivitySource = 'sckan';
326
+ this.noMapConnectivity = true;
327
+ mapImp.queryKnowledge(keastId)
328
+ .then((fallbackResponse) => {
329
+ if (this.checkConnectivityExists(fallbackResponse)) {
330
+ let connectivity = fallbackResponse;
331
+ if (processConnectivity) {
332
+ this.processConnectivity(mapImp, connectivity).then((processedConnectivity) => {
333
+ // response.references is publication urls
334
+ if (fallbackResponse.references) {
335
+ // with publications from both PubMed and Others
336
+ this.rawURLs = [...fallbackResponse.references];
337
+ }
338
+ resolve(processedConnectivity)
339
+ })
340
+ }
341
+ else resolve(connectivity)
342
+ } else {
343
+ resolve(false)
344
+ }
345
+ })
346
+ .catch(() => resolve(false));
315
347
  } else {
316
348
  resolve(false)
317
349
  }
@@ -536,19 +568,24 @@ let FlatmapQueries = function () {
536
568
  return `select distinct publication from publications where entity = '${model}'`
537
569
  }
538
570
 
539
- this.flatmapQuery = function (sql) {
540
- const data = { sql: sql }
541
- return fetch(`${this.flatmapAPI}knowledge/query/`, {
542
- method: 'POST',
543
- headers: {
544
- 'Content-Type': 'application/json',
545
- },
546
- body: JSON.stringify(data),
571
+ this.queryKnowledge = async (sql, params) => {
572
+ const url = `${this.flatmapAPI}/knowledge/query/`;
573
+ const query = { sql, params };
574
+ const response = await fetch(url, {
575
+ method: 'POST',
576
+ headers: {
577
+ "Accept": "application/json"
578
+ },
579
+ body: JSON.stringify(query),
547
580
  })
548
- .then((response) => response.json())
549
- .catch((error) => {
550
- console.error('Error:', error)
551
- })
581
+ if (!response.ok) {
582
+ throw new Error(`Cannot access ${url}`);
583
+ }
584
+ const data = await response.json();
585
+ if ('error' in data) {
586
+ throw new TypeError(data.error);
587
+ }
588
+ return data.values
552
589
  }
553
590
  }
554
591