@abi-software/map-utilities 1.4.3-isan.1 → 1.5.0-beta.0

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.
@@ -1,37 +1,11 @@
1
1
  <template>
2
- <div v-if="entry" class="main" v-loading="loading">
3
- <div v-if="tooltipEntry.length > 1" class="toggle-button">
4
- <el-popover width="auto" trigger="hover" :teleported="false">
5
- <template #reference>
6
- <el-button
7
- class="button"
8
- @click="previous"
9
- :disabled="this.entryIndex === 0"
10
- >
11
- Previous
12
- </el-button>
13
- </template>
14
- <span>{{ previousLabel }}</span>
15
- </el-popover>
16
- <el-popover width="auto" trigger="hover" :teleported="false">
17
- <template #reference>
18
- <el-button
19
- class="button"
20
- @click="next"
21
- :disabled="this.entryIndex === this.tooltipEntry.length - 1"
22
- >
23
- Next
24
- </el-button>
25
- </template>
26
- <span>{{ nextLabel }}</span>
27
- </el-popover>
28
- </div>
29
- <div class="block" v-if="entry.title">
30
- <div class="title">{{ capitalise(entry.title) }}</div>
2
+ <div v-if="tooltipEntry" class="main" v-loading="loading">
3
+ <div class="block" v-if="tooltipEntry.title">
4
+ <div class="title">{{ capitalise(tooltipEntry.title) }}</div>
31
5
  <div
32
6
  v-if="
33
- entry.provenanceTaxonomyLabel &&
34
- entry.provenanceTaxonomyLabel.length > 0
7
+ tooltipEntry.provenanceTaxonomyLabel &&
8
+ tooltipEntry.provenanceTaxonomyLabel.length > 0
35
9
  "
36
10
  class="subtitle"
37
11
  >
@@ -39,9 +13,9 @@
39
13
  </div>
40
14
  </div>
41
15
  <div class="block" v-else>
42
- <div class="title">{{ entry.featureId }}</div>
16
+ <div class="title">{{ tooltipEntry.featureId }}</div>
43
17
  </div>
44
- <div v-if="entry.featuresAlert" class="attribute-title-container">
18
+ <div v-if="featuresAlert" class="attribute-title-container">
45
19
  <span class="attribute-title">Alert</span>
46
20
  <el-popover
47
21
  width="250"
@@ -53,7 +27,7 @@
53
27
  <el-icon class="info"><el-icon-warning /></el-icon>
54
28
  </template>
55
29
  <span style="word-break: keep-all">
56
- {{ entry.featuresAlert }}
30
+ {{ featuresAlert }}
57
31
  </span>
58
32
  </el-popover>
59
33
  </div>
@@ -77,159 +51,243 @@
77
51
  </div>
78
52
  <transition name="slide-fade">
79
53
  <div v-show="showDetails" class="content-container scrollbar">
80
- <connectivity-list
81
- :key="entry.featureId[0]"
82
- :entry="entry"
83
- :origins="origins"
84
- :components="components"
85
- :destinations="destinations"
86
- :originsWithDatasets="originsWithDatasets"
87
- :componentsWithDatasets="componentsWithDatasets"
88
- :destinationsWithDatasets="destinationsWithDatasets"
89
- :availableAnatomyFacets="availableAnatomyFacets"
90
- @connectivity-action-click="onConnectivityActionClick"
91
- />
92
- <external-resource-card
93
- v-if="resources.length"
94
- :resources="resources"
95
- />
54
+ {{ tooltipEntry.paths }}
55
+ <div v-if="tooltipEntry.origins && tooltipEntry.origins.length > 0" class="block">
56
+ <div class="attribute-title-container">
57
+ <span class="attribute-title">Origin</span>
58
+ <el-popover
59
+ width="250"
60
+ trigger="hover"
61
+ :teleported="false"
62
+ popper-class="popover-origin-help"
63
+ >
64
+ <template #reference>
65
+ <el-icon class="info"><el-icon-warning /></el-icon>
66
+ </template>
67
+ <span style="word-break: keep-all">
68
+ <i>Origin</i> {{ originDescription }}
69
+ </span>
70
+ </el-popover>
71
+ </div>
72
+ <div
73
+ v-for="(origin, i) in tooltipEntry.origins"
74
+ class="attribute-content"
75
+ :origin-item-label="origin"
76
+ :key="origin"
77
+ >
78
+ {{ capitalise(origin) }}
79
+ <div v-if="i != tooltipEntry.origins.length - 1" class="separator"></div>
80
+ </div>
81
+ <el-button
82
+ v-show="
83
+ tooltipEntry.originsWithDatasets && tooltipEntry.originsWithDatasets.length > 0
84
+ "
85
+ class="button"
86
+ id="open-dendrites-button"
87
+ @click="openDendrites"
88
+ >
89
+ Explore origin data
90
+ </el-button>
91
+ </div>
92
+ <div
93
+ v-if="tooltipEntry.components && tooltipEntry.components.length > 0"
94
+ class="block"
95
+ >
96
+ <div class="attribute-title-container">
97
+ <div class="attribute-title">Components</div>
98
+ </div>
99
+ <div
100
+ v-for="(component, i) in tooltipEntry.components"
101
+ class="attribute-content"
102
+ :component-item-label="component"
103
+ :key="component"
104
+ >
105
+ {{ capitalise(component) }}
106
+ <div
107
+ v-if="i != tooltipEntry.components.length - 1"
108
+ class="separator"
109
+ ></div>
110
+ </div>
111
+ </div>
112
+ <div
113
+ v-if="tooltipEntry.destinations && tooltipEntry.destinations.length > 0"
114
+ class="block"
115
+ >
116
+ <div class="attribute-title-container">
117
+ <span class="attribute-title">Destination</span>
118
+ <el-popover
119
+ width="250"
120
+ trigger="hover"
121
+ :teleported="false"
122
+ popper-class="popover-origin-help"
123
+ >
124
+ <template #reference>
125
+ <el-icon class="info"><el-icon-warning /></el-icon>
126
+ </template>
127
+ <span style="word-break: keep-all">
128
+ <i>Destination</i> is where the axons terminate
129
+ </span>
130
+ </el-popover>
131
+ </div>
132
+ <div
133
+ v-for="(destination, i) in tooltipEntry.destinations"
134
+ class="attribute-content"
135
+ :destination-item-label="destination"
136
+ :key="destination"
137
+ >
138
+ {{ capitalise(destination) }}
139
+ <div
140
+ v-if="i != tooltipEntry.destinations.length - 1"
141
+ class="separator"
142
+ ></div>
143
+ </div>
144
+ <el-button
145
+ v-show="
146
+ tooltipEntry.destinationsWithDatasets &&
147
+ tooltipEntry.destinationsWithDatasets.length > 0
148
+ "
149
+ class="button"
150
+ @click="openAxons"
151
+ >
152
+ Explore destination data
153
+ </el-button>
154
+ </div>
155
+
156
+ <el-button
157
+ v-show="
158
+ tooltipEntry.componentsWithDatasets &&
159
+ tooltipEntry.componentsWithDatasets.length > 0
160
+ "
161
+ class="button"
162
+ @click="openAll"
163
+ >
164
+ Search for data on components
165
+ </el-button>
166
+
167
+ <external-resource-card :resources="resources" v-if="resources.length"></external-resource-card>
96
168
  </div>
97
169
  </transition>
98
170
  </div>
99
171
  </template>
100
172
 
101
173
  <script>
102
- import {
103
- ArrowUp as ElIconArrowUp,
104
- ArrowDown as ElIconArrowDown,
105
- Warning as ElIconWarning,
106
- } from "@element-plus/icons-vue";
107
174
  import EventBus from "../EventBus.js";
108
- import ConnectivityList from "../ConnectivityList/ConnectivityList.vue";
109
- import ExternalResourceCard from "./ExternalResourceCard.vue";
110
- import { capitalise, titleCase } from "../utilities.js";
175
+
176
+ const titleCase = (str) => {
177
+ return str.replace(/\w\S*/g, (t) => {
178
+ return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase();
179
+ });
180
+ };
181
+
182
+ const capitalise = function (str) {
183
+ if (str) return str.charAt(0).toUpperCase() + str.slice(1);
184
+ return "";
185
+ };
111
186
 
112
187
  export default {
113
188
  name: "ProvenancePopup",
114
- components: {
115
- ElIconArrowUp,
116
- ElIconArrowDown,
117
- ElIconWarning,
118
- ConnectivityList,
119
- ExternalResourceCard,
120
- },
121
189
  props: {
122
190
  tooltipEntry: {
123
- type: Array,
124
- default: [],
191
+ type: Object,
192
+ default: () => ({
193
+ destinations: [],
194
+ origins: [],
195
+ components: [],
196
+ destinationsWithDatasets: [],
197
+ originsWithDatasets: [],
198
+ componentsWithDatasets: [],
199
+ resource: undefined,
200
+ }),
125
201
  },
126
202
  },
203
+ inject: ["getFeaturesAlert"],
127
204
  data: function () {
128
205
  return {
206
+ controller: undefined,
207
+ activeSpecies: undefined,
208
+ pubmedSearchUrl: "",
129
209
  loading: false,
210
+ showToolip: false,
130
211
  showDetails: false,
131
212
  originDescriptions: {
132
213
  motor: "is the location of the initial cell body of the circuit",
133
214
  sensory: "is the location of the initial cell body in the PNS circuit",
134
215
  },
135
- entryIndex: 0,
136
- availableAnatomyFacets: [],
216
+ componentsWithDatasets: [],
217
+ uberons: [{ id: undefined, name: undefined }],
137
218
  };
138
219
  },
139
220
  computed: {
140
- entry: function () {
141
- return this.tooltipEntry[this.entryIndex];
221
+ featuresAlert() {
222
+ return this.getFeaturesAlert();
142
223
  },
143
- previousLabel: function () {
144
- if (this.entryIndex === 0) {
145
- return "This is the first item. Click 'Next' to see more information.";
224
+ resources: function () {
225
+ let resources = [];
226
+ if (this.tooltipEntry && this.tooltipEntry.hyperlinks) {
227
+ resources = this.tooltipEntry.hyperlinks;
146
228
  }
147
- return this.tooltipEntry[this.entryIndex - 1]?.title;
229
+ return resources;
148
230
  },
149
- nextLabel: function () {
150
- if (this.entryIndex === this.tooltipEntry.length - 1) {
151
- return "This is the last item. Click 'Previous' to see more information.";
231
+ originDescription: function () {
232
+ if (
233
+ this.tooltipEntry &&
234
+ this.tooltipEntry.title &&
235
+ this.tooltipEntry.title.toLowerCase().includes("motor")
236
+ ) {
237
+ return this.originDescriptions.motor;
238
+ } else {
239
+ return this.originDescriptions.sensory;
152
240
  }
153
- return this.tooltipEntry[this.entryIndex + 1]?.title;
154
241
  },
155
242
  provSpeciesDescription: function () {
156
243
  let text = "Studied in";
157
- this.entry.provenanceTaxonomyLabel.forEach((label) => {
244
+ this.tooltipEntry.provenanceTaxonomyLabel.forEach((label) => {
158
245
  text += ` ${label},`;
159
246
  });
160
247
  text = text.slice(0, -1); // remove last comma
161
248
  text += " species";
162
249
  return text;
163
250
  },
164
- origins: function () {
165
- return this.entry.origins;
166
- },
167
- components: function () {
168
- return this.entry.components;
169
- },
170
- destinations: function () {
171
- return this.entry.destinations;
172
- },
173
- originsWithDatasets: function () {
174
- return this.entry.originsWithDatasets;
175
- },
176
- componentsWithDatasets: function () {
177
- return this.entry.componentsWithDatasets;
178
- },
179
- destinationsWithDatasets: function () {
180
- return this.entry.destinationsWithDatasets;
181
- },
182
- resources: function () {
183
- return this.entry.hyperlinks;
184
- },
185
- },
186
- mounted: function () {
187
- this.loadAvailableAnatomyFacets();
188
251
  },
189
252
  methods: {
190
- previous: function () {
191
- if (this.entryIndex !== 0) {
192
- this.entryIndex = this.entryIndex - 1;
193
- }
194
- },
195
- next: function () {
196
- if (this.entryIndex !== this.tooltipEntry.length - 1) {
197
- this.entryIndex = this.entryIndex + 1;
198
- }
199
- },
200
253
  titleCase: function (title) {
201
254
  return titleCase(title);
202
255
  },
203
256
  capitalise: function (text) {
204
257
  return capitalise(text);
205
258
  },
206
- onConnectivityActionClick: function (data) {
207
- EventBus.emit("onActionClick", data);
259
+ openUrl: function (url) {
260
+ window.open(url, "_blank");
208
261
  },
209
- // Load available anatomy facets from the local storage if available.
210
- // The data is from Algolia in Sidebar.
211
- loadAvailableAnatomyFacets: function () {
212
- const availableAnatomyFacets = localStorage.getItem(
213
- "available-anatomy-facets"
214
- );
215
- if (availableAnatomyFacets) {
216
- this.availableAnatomyFacets = JSON.parse(availableAnatomyFacets);
217
- }
262
+ openAll: function () {
263
+ EventBus.emit("onActionClick", {
264
+ type: "Facets",
265
+ labels: this.tooltipEntry.componentsWithDatasets.map((a) => a.name),
266
+ });
267
+ },
268
+ openAxons: function () {
269
+ EventBus.emit("onActionClick", {
270
+ type: "Facets",
271
+ labels: this.tooltipEntry.destinationsWithDatasets.map((a) => a.name),
272
+ });
273
+ },
274
+ openDendrites: function () {
275
+ EventBus.emit("onActionClick", {
276
+ type: "Facets",
277
+ labels: this.tooltipEntry.originsWithDatasets.map((a) => a.name),
278
+ });
279
+ },
280
+ pubmedSearchUrlUpdate: function (val) {
281
+ this.pubmedSearchUrl = val;
218
282
  },
219
283
  },
220
284
  };
221
285
  </script>
222
286
 
223
287
  <style lang="scss" scoped>
224
- .toggle-button {
225
- display: flex;
226
- justify-content: space-between;
227
-
228
- .is-disabled {
229
- color: #fff !important;
230
- background-color: #ac76c5 !important;
231
- border: 1px solid #ac76c5 !important;
232
- }
288
+ .display {
289
+ width: 44px;
290
+ word-break: normal;
233
291
  }
234
292
 
235
293
  .title {
@@ -251,12 +309,43 @@ export default {
251
309
  }
252
310
  }
253
311
 
312
+ .pub {
313
+ width: 16rem;
314
+ }
315
+
316
+ .icon {
317
+ right: 0px;
318
+ position: absolute;
319
+ top: 10px;
320
+ }
321
+
322
+ .icon:hover {
323
+ cursor: pointer;
324
+ }
325
+
326
+ :deep(.popover-origin-help.el-popover) {
327
+ text-transform: none !important; // need to overide the tooltip text transform
328
+ border: 1px solid $app-primary-color;
329
+ .el-popper__arrow {
330
+ &:before {
331
+ border-color: $app-primary-color;
332
+ background-color: #ffffff;
333
+ }
334
+ }
335
+ }
336
+
254
337
  .info {
255
338
  transform: rotate(180deg);
256
339
  color: #8300bf;
257
340
  margin-left: 8px;
258
341
  }
259
342
 
343
+ .separator {
344
+ width: 90%;
345
+ height: 1px;
346
+ background-color: #bfbec2;
347
+ }
348
+
260
349
  .hide {
261
350
  color: $app-primary-color;
262
351
  cursor: pointer;
@@ -264,6 +353,17 @@ export default {
264
353
  margin-top: 3px;
265
354
  }
266
355
 
356
+ .slide-fade-enter-active {
357
+ transition: opacity 0.5s, transform 0.5s;
358
+ }
359
+ .slide-fade-leave-active {
360
+ transition: opacity 0.2s, transform 0.2s;
361
+ }
362
+ .slide-fade-enter, .slide-fade-leave-to /* .slide-fade-leave-active in <2.1.8 */ {
363
+ opacity: 0;
364
+ transform: translateY(-8px);
365
+ }
366
+
267
367
  .main {
268
368
  font-size: 14px;
269
369
  text-align: left;
@@ -296,6 +396,11 @@ export default {
296
396
  }
297
397
  }
298
398
 
399
+ .popover-container {
400
+ height: 100%;
401
+ width: 100%;
402
+ }
403
+
299
404
  .main {
300
405
  .el-button.is-round {
301
406
  border-radius: 4px;
@@ -311,11 +416,9 @@ export default {
311
416
  font-size: 14px !important;
312
417
  background-color: $app-primary-color;
313
418
  color: #fff;
314
-
315
419
  & + .button {
316
420
  margin-top: 10px !important;
317
421
  }
318
-
319
422
  &:hover {
320
423
  color: #fff !important;
321
424
  background: #ac76c5 !important;
@@ -323,6 +426,27 @@ export default {
323
426
  }
324
427
  }
325
428
 
429
+ .tooltip-container {
430
+ &::after,
431
+ &::before {
432
+ content: "";
433
+ display: block;
434
+ position: absolute;
435
+ width: 0;
436
+ height: 0;
437
+ border-style: solid;
438
+ flex-shrink: 0;
439
+ }
440
+ .tooltip {
441
+ &::after {
442
+ display: none;
443
+ }
444
+ &::before {
445
+ display: none;
446
+ }
447
+ }
448
+ }
449
+
326
450
  .maplibregl-popup-anchor-bottom {
327
451
  .tooltip-container {
328
452
  &::after,
@@ -330,12 +454,10 @@ export default {
330
454
  top: 100%;
331
455
  border-width: 12px;
332
456
  }
333
-
334
457
  &::after {
335
458
  margin-top: -1px;
336
459
  border-color: rgb(255, 255, 255) transparent transparent transparent;
337
460
  }
338
-
339
461
  &::before {
340
462
  margin: 0 auto;
341
463
  border-color: $app-primary-color transparent transparent transparent;
@@ -350,12 +472,10 @@ export default {
350
472
  top: -24px;
351
473
  border-width: 12px;
352
474
  }
353
-
354
475
  &::after {
355
476
  margin-top: 1px;
356
477
  border-color: transparent transparent rgb(255, 255, 255) transparent;
357
478
  }
358
-
359
479
  &::before {
360
480
  margin: 0 auto;
361
481
  border-color: transparent transparent $app-primary-color transparent;
@@ -371,10 +491,6 @@ export default {
371
491
  .block {
372
492
  padding-top: 0.5em;
373
493
  }
374
-
375
- .connectivity-list {
376
- padding-top: 1rem;
377
- }
378
494
  }
379
495
 
380
496
  .scrollbar::-webkit-scrollbar-track {
@@ -393,4 +509,10 @@ export default {
393
509
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.06);
394
510
  background-color: #979797;
395
511
  }
512
+
513
+ /* Fix for chrome bug where under triangle pops up above one on top of it */
514
+ .selector:not(*:root),
515
+ .tooltip-container::after {
516
+ top: 99.4%;
517
+ }
396
518
  </style>
@@ -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>
@@ -19,14 +19,14 @@ export default {
19
19
  name: "Tooltip",
20
20
  props: {
21
21
  tooltipEntry: {
22
- type: Array,
22
+ type: Object,
23
23
  },
24
24
  annotationDisplay: {
25
25
  type: Boolean,
26
26
  default: false,
27
27
  },
28
28
  annotationEntry: {
29
- type: Array,
29
+ type: Object,
30
30
  },
31
31
  },
32
32
  mounted: function() {
@@ -1,7 +1,6 @@
1
1
  import AnnotationPopup from "./Tooltip/AnnotationPopup.vue";
2
2
  import CreateTooltipContent from "./Tooltip/CreateTooltipContent.vue";
3
3
  import ConnectivityGraph from "./ConnectivityGraph/ConnectivityGraph.vue";
4
- import ConnectivityList from "./ConnectivityList/ConnectivityList.vue";
5
4
  import CopyToClipboard from "./CopyToClipboard/CopyToClipboard.vue";
6
5
  import DrawToolbar from "./DrawToolbar/DrawToolbar.vue";
7
6
  import HelpModeDialog from "./HelpModeDialog/HelpModeDialog.vue";
@@ -13,7 +12,6 @@ export {
13
12
  AnnotationPopup,
14
13
  CreateTooltipContent,
15
14
  ConnectivityGraph,
16
- ConnectivityList,
17
15
  CopyToClipboard,
18
16
  DrawToolbar,
19
17
  HelpModeDialog,
@@ -4,12 +4,6 @@ const capitalise = term => {
4
4
  return term;
5
5
  };
6
6
 
7
- const titleCase = (str) => {
8
- return str.replace(/\w\S*/g, (t) => {
9
- return t.charAt(0).toUpperCase() + t.substr(1).toLowerCase();
10
- });
11
- };
12
-
13
7
  const convertNodeToObject = (node) => {
14
8
  const obj = {};
15
9
 
@@ -56,7 +50,6 @@ const delay = (ms) => {
56
50
 
57
51
  export {
58
52
  capitalise,
59
- titleCase,
60
53
  xmlToJSON,
61
54
  delay,
62
55
  };
@@ -10,7 +10,6 @@ declare module 'vue' {
10
10
  AnnotationPopup: typeof import('./components/Tooltip/AnnotationPopup.vue')['default']
11
11
  ConnectionDialog: typeof import('./components/DrawToolbar/ConnectionDialog.vue')['default']
12
12
  ConnectivityGraph: typeof import('./components/ConnectivityGraph/ConnectivityGraph.vue')['default']
13
- ConnectivityList: typeof import('./components/ConnectivityList/ConnectivityList.vue')['default']
14
13
  CopyToClipboard: typeof import('./components/CopyToClipboard/CopyToClipboard.vue')['default']
15
14
  CreateTooltipContent: typeof import('./components/Tooltip/CreateTooltipContent.vue')['default']
16
15
  DrawToolbar: typeof import('./components/DrawToolbar/DrawToolbar.vue')['default']
@@ -45,6 +44,7 @@ declare module 'vue' {
45
44
  ExternalResourceCard: typeof import('./components/Tooltip/ExternalResourceCard.vue')['default']
46
45
  HelpModeDialog: typeof import('./components/HelpModeDialog/HelpModeDialog.vue')['default']
47
46
  ProvenancePopup: typeof import('./components/Tooltip/ProvenancePopup.vue')['default']
47
+ RelatedConnectivitiesButton: typeof import('./components/Tooltip/RelatedConnectivitiesButton.vue')['default']
48
48
  Tooltip: typeof import('./components/Tooltip/Tooltip.vue')['default']
49
49
  TreeControls: typeof import('./components/TreeControls/TreeControls.vue')['default']
50
50
  }