@abi-software/map-utilities 1.4.3-isan.1 → 1.5.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/map-utilities",
3
- "version": "1.4.3-isan.1",
3
+ "version": "1.5.0-beta.1",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
@@ -32,6 +32,7 @@
32
32
  "@abi-software/svg-sprite": "^1.0.1",
33
33
  "@element-plus/icons-vue": "^2.3.1",
34
34
  "cytoscape": "^3.30.2",
35
+ "cytoscape-dagre": "^2.5.0",
35
36
  "element-plus": "2.8.4",
36
37
  "mitt": "^3.0.1",
37
38
  "vue": "^3.4.21"
package/src/App.vue CHANGED
@@ -39,8 +39,16 @@ const drawnTypes = [
39
39
  { value: "None", label: "None" },
40
40
  ];
41
41
  const showConnectivityGraph = ref(false);
42
- const connectivityGraphEntry = "ilxtr:neuron-type-aacar-13";
43
- // const connectivityGraphEntry = "ilxtr:sparc-nlp/kidney/134";
42
+ const connectivityGraphEntry = ref("ilxtr:neuron-type-aacar-13");
43
+ const connectivityGraphEntries = [
44
+ "ilxtr:neuron-type-aacar-13",
45
+ "ilxtr:sparc-nlp/kidney/134",
46
+ "ilxtr:neuron-type-aacar-11",
47
+ "ilxtr:neuron-type-sstom-14",
48
+ "ilxtr:neuron-type-keast-6",
49
+ "ilxtr:neuron-type-aacar-4",
50
+ "ilxtr:neuron-type-aacar-12",
51
+ ];
44
52
  const mapServer = "https://mapcore-demo.org/curation/flatmap/";
45
53
  const sckanVersion = "sckan-2024-09-21-npo";
46
54
 
@@ -533,6 +541,28 @@ function confirmCreate(value) {
533
541
  <el-button @click="showConnectivityGraph = false" size="small">
534
542
  Hide connectivity graph
535
543
  </el-button>
544
+ <el-select
545
+ v-model="connectivityGraphEntry"
546
+ placeholder="Select featureId"
547
+ style="width: 180px"
548
+ size="small"
549
+ >
550
+ <el-option
551
+ v-for="item in connectivityGraphEntries"
552
+ :key="item"
553
+ :label="item"
554
+ :value="item"
555
+ />
556
+ </el-select>
557
+ </el-col>
558
+ <el-col>
559
+ <ConnectivityGraph
560
+ v-if="showConnectivityGraph"
561
+ :key="connectivityGraphEntry"
562
+ :entry="connectivityGraphEntry"
563
+ :map-server="mapServer"
564
+ :sckanVersion="sckanVersion"
565
+ />
536
566
  </el-col>
537
567
  </el-row>
538
568
 
@@ -604,12 +634,6 @@ function confirmCreate(value) {
604
634
  @setColour="setColour"
605
635
  @checkChanged="checkChanged"
606
636
  />
607
- <ConnectivityGraph
608
- v-if="showConnectivityGraph"
609
- :entry="connectivityGraphEntry"
610
- :map-server="mapServer"
611
- :sckanVersion="sckanVersion"
612
- />
613
637
  </div>
614
638
  </template>
615
639
 
@@ -643,4 +667,7 @@ function confirmCreate(value) {
643
667
  height: 600px;
644
668
  margin-top: 1rem;
645
669
  }
670
+ .el-button + .el-select {
671
+ margin-left: 12px;
672
+ }
646
673
  </style>
@@ -19,6 +19,8 @@ limitations under the License.
19
19
  ==============================================================================*/
20
20
 
21
21
  import cytoscape from 'cytoscape'
22
+ import dagre from 'cytoscape-dagre'
23
+ cytoscape.use( dagre );
22
24
 
23
25
  //==============================================================================
24
26
 
@@ -264,7 +266,7 @@ export class ConnectivityGraph extends EventTarget
264
266
  }
265
267
  } else if (this.dendrites.includes(id) || this.somas.includes(id)) {
266
268
  result['dendrite'] = true
267
-
269
+
268
270
  }
269
271
  }
270
272
  return result
@@ -406,11 +408,13 @@ class CytoscapeGraph extends EventTarget
406
408
  container: graphCanvas,
407
409
  elements: connectivityGraph.elements,
408
410
  layout: {
409
- name: 'breadthfirst',
410
- circle: false,
411
- roots: connectivityGraph.roots
411
+ name: 'dagre',
412
+ nodeSep: 150,
413
+ edgeSep: 50,
414
+ rankSep: 100,
415
+ rankDir: 'TB',
416
+ roots: connectivityGraph.roots.length ? connectivityGraph.roots : undefined,
412
417
  },
413
- directed: true,
414
418
  style: GRAPH_STYLE,
415
419
  minZoom: 0.1,
416
420
  maxZoom: 10,
@@ -23,8 +23,8 @@
23
23
  class="attribute-content"
24
24
  :origin-item-label="origin"
25
25
  :key="origin"
26
- @mouseenter="toggleConnectivityTooltip(origin, {show: true})"
27
- @mouseleave="toggleConnectivityTooltip(origin, {show: false})"
26
+ @mouseenter="onConnectivityHovered(origin)"
27
+ @mouseleave="onConnectivityHovered()"
28
28
  >
29
29
  {{ capitalise(origin) }}
30
30
  </div>
@@ -52,10 +52,10 @@
52
52
  class="attribute-content"
53
53
  :component-item-label="component"
54
54
  :key="component"
55
- @mouseenter="toggleConnectivityTooltip(component, {show: true})"
56
- @mouseleave="toggleConnectivityTooltip(component, {show: false})"
55
+ @mouseenter="onConnectivityHovered(component)"
56
+ @mouseleave="onConnectivityHovered()"
57
57
  >
58
- {{ capitalise(component) }}
58
+ {{ capitalise(component) }}
59
59
  </div>
60
60
  </div>
61
61
  <div
@@ -83,8 +83,8 @@
83
83
  class="attribute-content"
84
84
  :destination-item-label="destination"
85
85
  :key="destination"
86
- @mouseenter="toggleConnectivityTooltip(destination, {show: true})"
87
- @mouseleave="toggleConnectivityTooltip(destination, {show: false})"
86
+ @mouseenter="onConnectivityHovered(destination)"
87
+ @mouseleave="onConnectivityHovered()"
88
88
  >
89
89
  {{ capitalise(destination) }}
90
90
  </div>
@@ -229,14 +229,18 @@ export default {
229
229
  capitalise: function (text) {
230
230
  return capitalise(text)
231
231
  },
232
- toggleConnectivityTooltip: function (name, option) {
233
- this.$emit('toggle-connectivity-tooltip', {
234
- name,
235
- option
236
- });
232
+ onConnectivityHovered: function (name) {
233
+ this.$emit('connectivity-hovered', name);
234
+ },
235
+ onConnectivityClicked: function (id, type, label) {
236
+ this.$emit('connectivity-clicked', { id, type, label });
237
237
  },
238
238
  // shouldShowExploreButton: Checks if the feature is in the list of available anatomy facets
239
239
  shouldShowExploreButton: function (features) {
240
+ // facetList will not be available when there has no Sidebar's data
241
+ if (!this.facetList.length) {
242
+ return true
243
+ }
240
244
  for (let i = 0; i < features.length; i++) {
241
245
  if (this.facetList.includes(features[i].name.toLowerCase())) {
242
246
  return true
@@ -573,8 +573,8 @@ export default {
573
573
  border-color: var(--el-color-primary-light-5);
574
574
  border-radius: 1rem;
575
575
  position: absolute;
576
- right: calc(50vw - 100px);
577
- bottom: 16px;
576
+ right: 40%;
577
+ bottom: 1rem;
578
578
  z-index: 10;
579
579
  }
580
580
 
@@ -67,7 +67,7 @@
67
67
  <strong class="sub-title">Previous submissions:</strong>
68
68
  </el-row>
69
69
  <div class="entry" v-for="(sub, index) in prevSubs" :key="index">
70
- <el-row class="dialog-text">
70
+ <el-row class="dialog-text" v-if="sub.creator">
71
71
  <strong>{{ formatTime(sub.created) }}</strong>
72
72
  {{ sub.creator.name }}
73
73
  </el-row>
@@ -91,7 +91,7 @@
91
91
  </div>
92
92
  </template>
93
93
  </template>
94
- <template v-if="authenticated">
94
+ <template v-if="authenticated || offlineAnnotationEnabled">
95
95
  <template v-if="isEditable">
96
96
  <el-row class="dialog-spacer"></el-row>
97
97
  <el-row v-if="!editing">
@@ -259,6 +259,12 @@ export default {
259
259
  updatedCopyContent: function () {
260
260
  return this.getUpdateCopyContent();
261
261
  },
262
+ offlineAnnotationEnabled: function () {
263
+ if (this.entry) {
264
+ return this.entry["offline"];
265
+ }
266
+ return false;
267
+ },
262
268
  },
263
269
  methods: {
264
270
  previous: function () {
@@ -314,7 +320,15 @@ export default {
314
320
  return new Date(dateString).toLocaleDateString(undefined, options);
315
321
  },
316
322
  updatePrevSubmissions: function () {
317
- if (this.$annotator && this.authenticated) {
323
+ if (this.offlineAnnotationEnabled) {
324
+ const offlineAnnotations = JSON.parse(sessionStorage.getItem('anonymous-annotation')) || [];
325
+ this.prevSubs = offlineAnnotations.filter((offline) => {
326
+ return (
327
+ offline.resource === this.entry.resourceId &&
328
+ offline.item.id === this.entry.featureId
329
+ )
330
+ });
331
+ } else if (this.$annotator && this.authenticated) {
318
332
  if (
319
333
  this.entry["resourceId"] &&
320
334
  this.entry["featureId"]
@@ -394,7 +408,6 @@ export default {
394
408
  this.$annotator
395
409
  ?.addAnnotation(this.userApiKey, userAnnotation)
396
410
  .then(() => {
397
- this.$emit("annotation", userAnnotation);
398
411
  this.errorMessage = "";
399
412
  this.resetSubmission();
400
413
  this.updatePrevSubmissions();
@@ -403,6 +416,7 @@ export default {
403
416
  this.errorMessage =
404
417
  "There is a problem with the submission, please try again later";
405
418
  });
419
+ this.$emit("annotation", userAnnotation);
406
420
  }
407
421
  }
408
422
  },
@@ -448,9 +462,11 @@ export default {
448
462
  if (this.prevSubs.length) {
449
463
  let annotationContent = '<div><strong>Annotations:</strong></div>\n<br>';
450
464
  this.prevSubs.map((sub, index) => {
451
- annotationContent += `<div><strong>Created:</strong>${this.formatTime(sub.created)}</div>\n<br>`;
452
- annotationContent += `<div><strong>Creator:</strong>${sub.creator.name}</div>\n<br>`;
453
- annotationContent += `<div><strong>Email:</strong>${sub.creator.email}</div>\n<br>`;
465
+ if (sub.creator) {
466
+ annotationContent += `<div><strong>Created:</strong>${this.formatTime(sub.created)}</div>\n<br>`;
467
+ annotationContent += `<div><strong>Creator:</strong>${sub.creator.name}</div>\n<br>`;
468
+ annotationContent += `<div><strong>Email:</strong>${sub.creator.email}</div>\n<br>`;
469
+ }
454
470
  if (sub.body.evidence.length) {
455
471
  let evidenceContent = '';
456
472
  sub.body.evidence.forEach((evi, index) => {
@@ -468,11 +484,20 @@ export default {
468
484
  },
469
485
  },
470
486
  watch: {
471
- entry: {
487
+ annotationEntry: {
472
488
  deep: true,
473
489
  immediate: true,
474
490
  handler: function (newVal, oldVal) {
475
491
  if (newVal !== oldVal) {
492
+ this.entryIndex = 0;
493
+ }
494
+ },
495
+ },
496
+ entry: {
497
+ deep: true,
498
+ immediate: true,
499
+ handler: function (newVal, oldVal) {
500
+ if (newVal && newVal !== oldVal) {
476
501
  this.resetSubmission();
477
502
  this.updatePrevSubmissions();
478
503
  }
@@ -485,10 +510,10 @@ export default {
485
510
  this.creator = userData;
486
511
  if (!userData.orcid) this.creator.orcid = "0000-0000-0000-0000";
487
512
  this.authenticated = true;
488
- this.updatePrevSubmissions();
489
513
  } else {
490
514
  this.errorMessage = "";
491
515
  }
516
+ this.updatePrevSubmissions();
492
517
  });
493
518
  },
494
519
  };
@@ -498,7 +523,6 @@ export default {
498
523
  .toggle-button {
499
524
  display: flex;
500
525
  justify-content: space-between;
501
- margin-bottom: 30px;
502
526
 
503
527
  .is-disabled {
504
528
  color: #fff !important;
@@ -22,8 +22,8 @@
22
22
  v-for="reference of pubMedReferences"
23
23
  :key="reference.id"
24
24
  :class="{
25
- 'loading': reference.citation && !reference.citation.error && reference.citation[citationType] === '',
26
- 'error': reference.citation && reference.citation.error
25
+ 'loading': isCitationLoading(reference.citation),
26
+ 'error': isCitationError(reference.citation),
27
27
  }"
28
28
  >
29
29
  <template v-if="reference.citation">
@@ -50,49 +50,34 @@
50
50
  <template v-else>
51
51
  <span v-html="reference.citation[citationType]"></span>
52
52
 
53
- <div class="reference-button-container">
54
- <el-button
55
- class="reference-icon-button"
56
- size="small"
57
- @click="showRelatedConnectivities(reference.resource)"
58
- >
59
- Show related connectivities
60
- </el-button>
61
- </div>
53
+ <RelatedConnectivitiesButton
54
+ :resource="reference.resource"
55
+ @show-related-connectivities="showRelatedConnectivities"
56
+ />
62
57
 
63
58
  <CopyToClipboard :content="reference.citation[citationType]" />
64
59
  </template>
65
60
  </template>
66
61
  </li>
67
62
 
68
- <li v-for="reference of openLibReferences">
63
+ <li v-for="reference of openLibReferences" :key="reference.id">
69
64
  <div v-html="formatCopyReference(reference)"></div>
70
65
 
71
- <div class="reference-button-container">
72
- <el-button
73
- class="reference-icon-button"
74
- size="small"
75
- @click="showRelatedConnectivities(reference.resource)"
76
- >
77
- Show related connectivities
78
- </el-button>
79
- </div>
66
+ <RelatedConnectivitiesButton
67
+ :resource="reference.resource"
68
+ @show-related-connectivities="showRelatedConnectivities"
69
+ />
80
70
 
81
71
  <CopyToClipboard :content="formatCopyReference(reference)" />
82
72
  </li>
83
73
 
84
- <li v-for="reference of isbnDBReferences">
74
+ <li v-for="reference of isbnDBReferences" :key="reference.id">
85
75
  <a :href="reference.url" target="_blank">{{ reference.url }}</a>
86
76
 
87
- <div class="reference-button-container">
88
- <el-button
89
- class="reference-icon-button"
90
- size="small"
91
- @click="showRelatedConnectivities(reference.resource)"
92
- >
93
- Show related connectivities
94
- </el-button>
95
- </div>
77
+ <RelatedConnectivitiesButton
78
+ :resource="reference.resource"
79
+ @show-related-connectivities="showRelatedConnectivities"
80
+ />
96
81
 
97
82
  <CopyToClipboard :content="reference.url" />
98
83
  </li>
@@ -103,6 +88,7 @@
103
88
  <script>
104
89
  import CopyToClipboard from '../CopyToClipboard/CopyToClipboard.vue';
105
90
  import { delay } from '../utilities';
91
+ import RelatedConnectivitiesButton from './RelatedConnectivitiesButton.vue';
106
92
 
107
93
  const CROSSCITE_API_HOST = 'https://citation.doi.org';
108
94
  const CITATION_OPTIONS = [
@@ -128,6 +114,10 @@ const LOADING_DELAY = 600;
128
114
 
129
115
  export default {
130
116
  name: "ExternalResourceCard",
117
+ components: {
118
+ CopyToClipboard,
119
+ RelatedConnectivitiesButton,
120
+ },
131
121
  props: {
132
122
  resources: {
133
123
  type: Array,
@@ -411,6 +401,12 @@ export default {
411
401
  reloadCitation: function (reference) {
412
402
  this.generateCitationText(reference, this.citationType);
413
403
  },
404
+ isCitationLoading: function (citation) {
405
+ return citation && !citation[this.citationType] && !citation.error;
406
+ },
407
+ isCitationError: function (citation) {
408
+ return citation && citation.error;
409
+ },
414
410
  updateCopyContents: function () {
415
411
  const citationTypeObj = this.citationOptions.find((item) => item.value === this.citationType);
416
412
  let citationFormatStyle = '';
@@ -611,7 +607,7 @@ export default {
611
607
  &.loading {
612
608
  padding: 1rem;
613
609
 
614
- &::before {
610
+ &::after {
615
611
  content: "";
616
612
  display: block;
617
613
  width: 100%;
@@ -691,20 +687,6 @@ export default {
691
687
  cursor: pointer;
692
688
  }
693
689
 
694
- .reference-button-container {
695
- margin-top: 0.5rem;
696
- }
697
-
698
- .reference-icon-button {
699
- color: $app-primary-color !important;
700
- background-color: #f9f2fc !important;
701
- border-color: $app-primary-color !important;
702
-
703
- &:hover {
704
- background-color: transparent !important;
705
- }
706
- }
707
-
708
690
  @keyframes loadingAnimation {
709
691
  0% {
710
692
  background-position: -30vw 0;
@@ -183,6 +183,17 @@ export default {
183
183
  return this.entry.hyperlinks;
184
184
  },
185
185
  },
186
+ watch: {
187
+ tooltipEntry: {
188
+ deep: true,
189
+ immediate: true,
190
+ handler: function (newVal, oldVal) {
191
+ if (newVal !== oldVal) {
192
+ this.entryIndex = 0;
193
+ }
194
+ },
195
+ },
196
+ },
186
197
  mounted: function () {
187
198
  this.loadAvailableAnatomyFacets();
188
199
  },
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <div class="reference-button-container">
3
+ <el-button
4
+ class="reference-icon-button"
5
+ size="small"
6
+ @click="$emit('show-related-connectivities', resource)"
7
+ >
8
+ Show related connectivities
9
+ </el-button>
10
+ </div>
11
+ </template>
12
+
13
+ <script>
14
+ export default {
15
+ name: "RelatedConnectivitiesButton",
16
+ props: {
17
+ resource: {
18
+ type: String,
19
+ required: true,
20
+ },
21
+ },
22
+ };
23
+ </script>
24
+
25
+ <style lang="scss" scoped>
26
+ .reference-button-container {
27
+ margin-top: 0.5rem;
28
+ }
29
+
30
+ .reference-icon-button {
31
+ color: $app-primary-color !important;
32
+ background-color: #f9f2fc !important;
33
+ border-color: $app-primary-color !important;
34
+
35
+ &:hover {
36
+ background-color: transparent !important;
37
+ }
38
+ }
39
+ </style>
@@ -45,6 +45,7 @@ declare module 'vue' {
45
45
  ExternalResourceCard: typeof import('./components/Tooltip/ExternalResourceCard.vue')['default']
46
46
  HelpModeDialog: typeof import('./components/HelpModeDialog/HelpModeDialog.vue')['default']
47
47
  ProvenancePopup: typeof import('./components/Tooltip/ProvenancePopup.vue')['default']
48
+ RelatedConnectivitiesButton: typeof import('./components/Tooltip/RelatedConnectivitiesButton.vue')['default']
48
49
  Tooltip: typeof import('./components/Tooltip/Tooltip.vue')['default']
49
50
  TreeControls: typeof import('./components/TreeControls/TreeControls.vue')['default']
50
51
  }