@abi-software/flatmapvuer 0.5.7 → 0.5.8

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +399 -399
  2. package/LICENSE +201 -201
  3. package/README.md +105 -105
  4. package/babel.config.js +14 -14
  5. package/dist/flatmapvuer.common.js +139 -98
  6. package/dist/flatmapvuer.common.js.map +1 -1
  7. package/dist/flatmapvuer.css +1 -1
  8. package/dist/flatmapvuer.umd.js +139 -98
  9. package/dist/flatmapvuer.umd.js.map +1 -1
  10. package/dist/flatmapvuer.umd.min.js +2 -2
  11. package/dist/flatmapvuer.umd.min.js.map +1 -1
  12. package/package-lock.json +14399 -14399
  13. package/package.json +78 -78
  14. package/public/index.html +17 -17
  15. package/src/App.vue +226 -226
  16. package/src/assets/_variables.scss +43 -43
  17. package/src/assets/styles.scss +7 -7
  18. package/src/components/EventBus.js +2 -2
  19. package/src/components/ExternalResourceCard.vue +98 -98
  20. package/src/components/FlatmapVuer.vue +1841 -1841
  21. package/src/components/MultiFlatmapVuer.vue +529 -529
  22. package/src/components/SelectionsGroup.vue +249 -249
  23. package/src/components/Tooltip.vue +447 -417
  24. package/src/components/TreeControls.vue +231 -231
  25. package/src/components/index.js +9 -9
  26. package/src/components/legends/DynamicLegends.vue +112 -112
  27. package/src/components/legends/SvgLegends.vue +66 -66
  28. package/src/icons/fonts/mapicon-species.eot +0 -0
  29. package/src/icons/fonts/mapicon-species.svg +14 -14
  30. package/src/icons/fonts/mapicon-species.ttf +0 -0
  31. package/src/icons/fonts/mapicon-species.woff +0 -0
  32. package/src/icons/mapicon-species-style.css +42 -42
  33. package/src/legends/legend.svg +25 -25
  34. package/src/main.js +8 -8
  35. package/src/nerve-map.js +99 -0
  36. package/src/services/flatmapQueries.js +415 -415
  37. package/vue.config.js +31 -31
@@ -1,529 +1,529 @@
1
- <template>
2
- <div class="multi-container" ref="multiContainer">
3
- <div style="position:absolute;z-index:10;">
4
- <div class="species-display-text">
5
- Species
6
- </div>
7
- <el-popover content="Select a species" placement="right"
8
- :appendToBody=false trigger="manual" popper-class="flatmap-popper right-popper" v-model="helpMode" ref="selectPopover">
9
- </el-popover>
10
- <el-select
11
- id="flatmap-select"
12
- :popper-append-to-body="appendToBody"
13
- v-model="activeSpecies"
14
- placeholder="Select"
15
- class="select-box"
16
- popper-class="flatmap_dropdown"
17
- @change="setSpecies"
18
- v-popover:selectPopover
19
- >
20
- <el-option v-for="(item, key) in speciesList" :key="key" :label="key" :value="key">
21
- <el-row>
22
- <el-col :span="8"><i :class="item.iconClass"></i></el-col>
23
- <el-col :span="12">{{ key }}</el-col>
24
- </el-row>
25
- </el-option>
26
- </el-select>
27
- </div>
28
- <FlatmapVuer
29
- v-for="(item, key) in speciesList"
30
- :key="key"
31
- :showLayer="showLayer"
32
- v-show="activeSpecies==key"
33
- :entry="item.taxo"
34
- :uuid="item.uuid"
35
- :biologicalSex="item.biologicalSex"
36
- :displayWarning="item.displayWarning"
37
- :displayLatestChanges="item.displayLatestChanges"
38
- :latestChangesMessage="item.latestChangesMessage"
39
- :isLegacy="item.isLegacy"
40
- :ref="key"
41
- :enableOpenMapUI="enableOpenMapUI"
42
- :openMapOptions="openMapOptions"
43
- @view-latest-map="viewLatestMap"
44
- @resource-selected="FlatmapSelected"
45
- @ready="FlatmapReady"
46
- @pan-zoom-callback="panZoomCallback"
47
- @open-map="$emit('open-map', $event)"
48
- :featureInfo="featureInfo"
49
- :minZoom="minZoom"
50
- :pathControls="pathControls"
51
- :searchable="searchable"
52
- :layerControl="layerControl"
53
- :helpMode="helpMode"
54
- :renderAtMounted="renderAtMounted"
55
- :displayMinimap="displayMinimap"
56
- style="height:100%"
57
- :flatmapAPI="flatmapAPI"
58
- :sparcAPI="sparcAPI"
59
- />
60
- </div>
61
- </template>
62
-
63
-
64
- <script>
65
- /* eslint-disable no-alert, no-console */
66
- import EventBus from './EventBus'
67
- import Vue from "vue";
68
- import FlatmapVuer from "./FlatmapVuer.vue";
69
- import { Col, Option, Select, Row, Popover } from "element-ui";
70
- import lang from "element-ui/lib/locale/lang/en";
71
- import locale from "element-ui/lib/locale";
72
- locale.use(lang);
73
- Vue.use(Col);
74
- Vue.use(Row);
75
- Vue.use(Option);
76
- Vue.use(Select);
77
- Vue.use(Popover)
78
-
79
- const TAXON_UUID = {
80
- "NCBITaxon:10114": "01fedbf9-d783-509c-a10c-827941ab13da",
81
- "NCBITaxon:9823": "a336ac04-24db-561f-a25f-1c994fe17410",
82
- "NCBITaxon:9606": "42ed6323-f645-5fbe-bada-9581819cf689",
83
- "NCBITaxon:10090": "25285fab-48a0-5620-a6a0-f9a0374837d5",
84
- "NCBITaxon:9685": "73060497-46a6-52bf-b975-cac511c127cb"
85
- }
86
-
87
- export default {
88
- name: "MultiFlatmapVuer",
89
- components: {
90
- FlatmapVuer
91
- },
92
- beforeMount() {
93
- //List for resolving the promise in initialise
94
- //if initialise is called multiple times
95
- this._resolveList = [];
96
- this._initialised = false;
97
- },
98
- mounted: function() {
99
- this.initialise();
100
- EventBus.$on('onActionClick', (action) =>{
101
- this.FlatmapSelected(action)
102
- })
103
- },
104
- methods: {
105
- initialise: function() {
106
- return new Promise(resolve => {
107
- if (this.requireInitialisation) {
108
- //It has not been initialised yet
109
- this.requireInitialisation = false;
110
- fetch(this.flatmapAPI)
111
- .then(response => response.json())
112
- .then(data => {
113
- //Check each key in the provided availableSpecies against the one
114
- Object.keys(this.availableSpecies).forEach(key => {
115
- // FIrst look through the uuid
116
- const uuid = this.availableSpecies[key].uuid;
117
- if (uuid && data.map(e => e.uuid).indexOf(uuid) > 0) {
118
- this.$set(this.speciesList, key, this.availableSpecies[key]);
119
- } else {
120
- for (let i = 0; i < data.length; i++) {
121
- if (this.availableSpecies[key].taxo === data[i].taxon) {
122
- if (this.availableSpecies[key].biologicalSex) {
123
- if (data[i].biologicalSex &&
124
- data[i].biologicalSex === this.availableSpecies[key].biologicalSex) {
125
- this.$set(this.speciesList, key, this.availableSpecies[key]);
126
- break;
127
- }
128
- } else {
129
- this.$set(this.speciesList, key, this.availableSpecies[key]);
130
- break;
131
- }
132
- }
133
- }
134
- }
135
- });
136
- //Use the state species if it does not have any other species information
137
- let species = this.initial;
138
- if (this.state) {
139
- const mapState = this.state.state;
140
- if ((!mapState || ( !mapState.uuid && !mapState.entry )) && this.state.species)
141
- species = this.state.species;
142
- else
143
- species = undefined;
144
- }
145
- if (species) {
146
- //No state resuming, set the current flatmap to {this.initial}
147
- if (species && this.speciesList[species] !== undefined) {
148
- this.activeSpecies = species;
149
- } else {
150
- this.activeSpecies = Object.keys(this.speciesList)[0];
151
- }
152
- this.setSpecies(this.activeSpecies, this.state ? this.state.state : undefined, 5);
153
- }
154
- this._initialised = true;
155
- resolve();
156
- //Resolve all other promises resolve in the list
157
- this._resolveList.forEach(other => { other(); });
158
- });
159
- } else if (this._initialised) {
160
- //resolve as it has been initialised
161
- resolve();
162
- } else {
163
- //resolve when the async initialisation is finished
164
- this._resolveList.push(resolve);
165
- }
166
- })
167
- },
168
- FlatmapSelected: function(resource) {
169
- this.$emit("resource-selected", resource);
170
- },
171
- FlatmapReady: function(component) {
172
- this.$emit("ready", component);
173
- },
174
- getCoordinatesOfLastClick: function() {
175
- const flatmap = this.$refs[this.activeSpecies];
176
- if (flatmap && flatmap[0]) {
177
- return flatmap[0].getCoordinatesOfLastClick();
178
- }
179
- return undefined;
180
- },
181
- getCurrentFlatmap: function() {
182
- return this.$refs[this.activeSpecies][0];
183
- },
184
- panZoomCallback: function(payload) {
185
- this.$emit("pan-zoom-callback", payload);
186
- },
187
- showPopup: function(featureId, node, options) {
188
- let map = this.getCurrentFlatmap();
189
- map.showPopup(featureId, node, options);
190
- },
191
- showMarkerPopup: function(featureId, node, options) {
192
- let map = this.getCurrentFlatmap();
193
- map.showMarkerPopup(featureId, node, options);
194
- },
195
- setSpecies: function(species, state, numberOfRetry) {
196
- if (this.$refs && species in this.$refs) {
197
- this.activeSpecies = species;
198
- this.$refs[this.activeSpecies][0].createFlatmap(state);
199
- this.$emit('flatmapChanged', this.activeSpecies);
200
- } else if (numberOfRetry) {
201
- const retry = numberOfRetry - 1;
202
- if (retry >= 0) {
203
- Vue.nextTick(() => {
204
- this.setSpecies(species, state, retry);
205
- });
206
- }
207
- }
208
- },
209
- /**
210
- * Function to switch to the latest existing map from
211
- * a legacy map of the same species.
212
- *
213
- * @private
214
- */
215
- viewLatestMap: function(state) {
216
- const keys = Object.keys(this.speciesList);
217
- for (let i = 0; i < keys.length; i++) {
218
- const species = this.speciesList[keys[i]];
219
- if (!species.isLegacy &&
220
- (species.taxo === state.entry) &&
221
- (species.biologicalSex === state.biologicalSex)) {
222
- this.setSpecies(keys[i], state, 0);
223
- return;
224
- }
225
- }
226
- },
227
- /**
228
- * Create a legacy entry with the provided information
229
- *
230
- * @private
231
- */
232
- createLegacyEntry: function(state, taxo, uuid) {
233
- if (uuid && taxo) {
234
- let name = "Legacy";
235
- if (state.species) {
236
- if (state.species.slice(0, 6) === "Legacy")
237
- name = state.species;
238
- else
239
- name = name + ` ${state.species}`;
240
- }
241
- this.$set(
242
- this.speciesList,
243
- name,
244
- {
245
- taxo: taxo,
246
- isLegacy: true,
247
- displayWarning: true
248
- }
249
- );
250
- return {
251
- species: name,
252
- state: {
253
- entry: taxo,
254
- uuid: uuid,
255
- viewport: state.state.viewport,
256
- searchTerm: state.state.searchTerm
257
- },
258
- }
259
- }
260
- },
261
- /**
262
- * Function used to translate the legacy map state to one that can be used in current
263
- * flatmap if required. If it is a legacy, an Select entry will be added
264
- *
265
- * @private
266
- */
267
- updateState: function(state) {
268
- return new Promise((resolve) => {
269
- if (state && state.state) {
270
- const mapState = state.state;
271
- //uuid is not in the state, this is a legacy map
272
- if (!mapState.uuid) {
273
- if (mapState.entry) {
274
- const uuid = mapState.entry in TAXON_UUID ? TAXON_UUID[mapState.entry] : undefined;
275
- const newState = this.createLegacyEntry(state, mapState.entry, uuid);
276
- resolve(newState ? newState : state);
277
- }
278
- } else if (mapState.entry) {
279
- //uuid is in the state but should be checked if it is the latest map
280
- //for that taxon
281
- return new Promise(() => {
282
- const mapManager = new (require("@abi-software/flatmap-viewer")).MapManager(this.flatmapAPI);
283
- //mapManager.findMap_ is an async function so we need to wrap this with a promise
284
- const identifier = { taxon: mapState.entry };
285
- if (mapState.biologicalSex)
286
- identifier['biologicalSex'] = mapState.biologicalSex;
287
- mapManager.findMap_(identifier).then(map => {
288
- if (map.uuid !== mapState.uuid) {
289
- return this.createLegacyEntry(state, mapState.entry, mapState.uuid);
290
- }
291
- }).then(newState => {
292
- resolve(newState ? newState : state);
293
- })
294
- .catch(() => {
295
- resolve(state);
296
- });
297
- });
298
- }
299
- //Create a new state and add the legacy map to the select
300
- }
301
- resolve(state);
302
- });
303
- },
304
- /**
305
- * Function used for getting the current states of the scene. This exported states
306
- * can be imported using the importStates method.
307
- *
308
- * @public
309
- */
310
- getState: function() {
311
- let state = {
312
- species: this.activeSpecies,
313
- state: undefined,
314
- };
315
- let map = this.getCurrentFlatmap();
316
- state.state = map.getState();
317
- return state;
318
- },
319
- /**
320
- * Function used for importing the states of the scene. This exported states
321
- * can be imported using the read states method.
322
- *
323
- * @public
324
- */
325
- setState: function(state) {
326
- if (state) {
327
- //Update state if required
328
- this.updateState(state).then(currentState => {
329
- this.initialise().then(() => {
330
- if (currentState.species && (currentState.species !== this.activeSpecies)) {
331
- this.setSpecies(currentState.species, currentState.state, 5);
332
- } else if (currentState.state) {
333
- let map = this.getCurrentFlatmap();
334
- map.setState(currentState.state);
335
- }
336
- });
337
- });
338
- }
339
- },
340
- resourceSelected: function(action) {
341
- this.$emit("resource-selected", action);
342
- },
343
- },
344
- props: {
345
- showLayer: {
346
- type: Boolean,
347
- default: false
348
- },
349
- featureInfo: {
350
- type: Boolean,
351
- default: false
352
- },
353
- pathControls: {
354
- type: Boolean,
355
- default: true
356
- },
357
- searchable: {
358
- type: Boolean,
359
- default: false
360
- },
361
- layerControl: {
362
- type: Boolean,
363
- default: false
364
- },
365
- /**
366
- * Initial species for the flatmap.
367
- * This value will be ignored if a valid state object is provided.
368
- */
369
- initial: {
370
- type: String,
371
- default: ""
372
- },
373
- minZoom: {
374
- type: Number,
375
- default: 4
376
- },
377
- renderAtMounted: {
378
- type: Boolean,
379
- default: false
380
- },
381
- helpMode: {
382
- type: Boolean,
383
- default: false
384
- },
385
- displayMinimap: {
386
- type: Boolean,
387
- default: false
388
- },
389
- /**
390
- * Flag to determine rather open map UI should be
391
- * presented or not.
392
- */
393
- enableOpenMapUI: {
394
- type: Boolean,
395
- default: false,
396
- },
397
- openMapOptions: {
398
- type: Array
399
- },
400
- availableSpecies: {
401
- type: Object,
402
- default: function() {
403
- return {
404
- "Human Female":{taxo: "NCBITaxon:9606", biologicalSex: "PATO:0000383", iconClass:"mapicon-icon_human", displayWarning:true},
405
- "Human Male":{taxo: "NCBITaxon:9606", biologicalSex: "PATO:0000384", iconClass:"mapicon-icon_human", displayWarning:true},
406
- "Rat":{taxo: "NCBITaxon:10114", iconClass:"mapicon-icon_rat", displayLatestChanges: true},
407
- "Mouse":{taxo: "NCBITaxon:10090", iconClass:"mapicon-icon_mouse", displayWarning: true},
408
- "Pig":{taxo: "NCBITaxon:9823", iconClass:"mapicon-icon_pig", displayWarning: true},
409
- "Cat":{taxo: "NCBITaxon:9685", iconClass:"mapicon-icon_cat", displayWarning: true},
410
- }
411
- }
412
- },
413
- /**
414
- * State containing state of the flatmap.
415
- */
416
- state: {
417
- type: Object,
418
- default: undefined,
419
- },
420
- /**
421
- * Specify the endpoint of the flatmap server.
422
- */
423
- flatmapAPI: {
424
- type: String,
425
- default: "https://mapcore-demo.org/current/flatmap/v3/"
426
- },
427
- sparcAPI: {
428
- type: String,
429
- default: "https://api.sparc.science/"
430
- }
431
- },
432
- data: function() {
433
- return {
434
- activeSpecies: undefined,
435
- appendToBody: false,
436
- speciesList: {},
437
- requireInitialisation: true
438
- };
439
- },
440
- watch: {
441
- state: {
442
- handler: function(state) {
443
- this.setState(state);
444
- },
445
- immediate: true,
446
- deep: true,
447
- }
448
- }
449
- };
450
- </script>
451
-
452
- <style scoped lang="scss">
453
- @import "~element-ui/packages/theme-chalk/src/select";
454
- @import "~element-ui/packages/theme-chalk/src/option";
455
-
456
- .multi-container {
457
- height: 100%;
458
- width: 100%;
459
- }
460
-
461
- .species-display-text {
462
- width: 47px;
463
- height: 20px;
464
- color: rgb(48, 49, 51);
465
- font-size: 14px;
466
- font-weight: normal;
467
- line-height: 20px;
468
- left:24px;
469
- top:16px;
470
- position: absolute;
471
- }
472
-
473
- .select-box {
474
- width: 120px;
475
- border-radius: 4px;
476
- border: 1px solid rgb(144, 147, 153);
477
- background-color: var(--white);
478
- font-weight: 500;
479
- color:rgb(48, 49, 51);;
480
- left: 16px;
481
- top: 44px;
482
- position: absolute;
483
- ::v-deep .el-input__inner {
484
- color: rgb(48, 49, 51);
485
- padding-top: 0.25em;
486
- .is-focus {
487
- border: 1px solid $app-primary-color;
488
- }
489
- }
490
- }
491
-
492
-
493
- ::v-deep .flatmap_dropdown {
494
- min-width: 160px!important;
495
- .el-select-dropdown__item {
496
- white-space: nowrap;
497
- text-align: left;
498
- &.selected {
499
- color: $app-primary-color;
500
- font-weight: normal;
501
- }
502
- }
503
- }
504
-
505
- ::v-deep .flatmap-popper {
506
- padding: 6px 4px;
507
- font-size:12px;
508
- color: rgb(48, 49, 51);
509
- background-color: #f3ecf6;
510
- border: 1px solid $app-primary-color;
511
- white-space: nowrap;
512
- min-width: unset;
513
- &.right-popper {
514
- .popper__arrow {
515
- border-right-color: $app-primary-color !important;
516
- &:after {
517
- border-right-color: #f3ecf6 !important;
518
- }
519
- }
520
- }
521
- }
522
-
523
- ::v-deep .flatmap-marker-popup{
524
- background-color: #f0f0f000 !important;
525
- box-shadow: none !important;
526
- }
527
-
528
- </style>
529
-
1
+ <template>
2
+ <div class="multi-container" ref="multiContainer">
3
+ <div style="position:absolute;z-index:10;">
4
+ <div class="species-display-text">
5
+ Species
6
+ </div>
7
+ <el-popover content="Select a species" placement="right"
8
+ :appendToBody=false trigger="manual" popper-class="flatmap-popper right-popper" v-model="helpMode" ref="selectPopover">
9
+ </el-popover>
10
+ <el-select
11
+ id="flatmap-select"
12
+ :popper-append-to-body="appendToBody"
13
+ v-model="activeSpecies"
14
+ placeholder="Select"
15
+ class="select-box"
16
+ popper-class="flatmap_dropdown"
17
+ @change="setSpecies"
18
+ v-popover:selectPopover
19
+ >
20
+ <el-option v-for="(item, key) in speciesList" :key="key" :label="key" :value="key">
21
+ <el-row>
22
+ <el-col :span="8"><i :class="item.iconClass"></i></el-col>
23
+ <el-col :span="12">{{ key }}</el-col>
24
+ </el-row>
25
+ </el-option>
26
+ </el-select>
27
+ </div>
28
+ <FlatmapVuer
29
+ v-for="(item, key) in speciesList"
30
+ :key="key"
31
+ :showLayer="showLayer"
32
+ v-show="activeSpecies==key"
33
+ :entry="item.taxo"
34
+ :uuid="item.uuid"
35
+ :biologicalSex="item.biologicalSex"
36
+ :displayWarning="item.displayWarning"
37
+ :displayLatestChanges="item.displayLatestChanges"
38
+ :latestChangesMessage="item.latestChangesMessage"
39
+ :isLegacy="item.isLegacy"
40
+ :ref="key"
41
+ :enableOpenMapUI="enableOpenMapUI"
42
+ :openMapOptions="openMapOptions"
43
+ @view-latest-map="viewLatestMap"
44
+ @resource-selected="FlatmapSelected"
45
+ @ready="FlatmapReady"
46
+ @pan-zoom-callback="panZoomCallback"
47
+ @open-map="$emit('open-map', $event)"
48
+ :featureInfo="featureInfo"
49
+ :minZoom="minZoom"
50
+ :pathControls="pathControls"
51
+ :searchable="searchable"
52
+ :layerControl="layerControl"
53
+ :helpMode="helpMode"
54
+ :renderAtMounted="renderAtMounted"
55
+ :displayMinimap="displayMinimap"
56
+ style="height:100%"
57
+ :flatmapAPI="flatmapAPI"
58
+ :sparcAPI="sparcAPI"
59
+ />
60
+ </div>
61
+ </template>
62
+
63
+
64
+ <script>
65
+ /* eslint-disable no-alert, no-console */
66
+ import EventBus from './EventBus'
67
+ import Vue from "vue";
68
+ import FlatmapVuer from "./FlatmapVuer.vue";
69
+ import { Col, Option, Select, Row, Popover } from "element-ui";
70
+ import lang from "element-ui/lib/locale/lang/en";
71
+ import locale from "element-ui/lib/locale";
72
+ locale.use(lang);
73
+ Vue.use(Col);
74
+ Vue.use(Row);
75
+ Vue.use(Option);
76
+ Vue.use(Select);
77
+ Vue.use(Popover)
78
+
79
+ const TAXON_UUID = {
80
+ "NCBITaxon:10114": "01fedbf9-d783-509c-a10c-827941ab13da",
81
+ "NCBITaxon:9823": "a336ac04-24db-561f-a25f-1c994fe17410",
82
+ "NCBITaxon:9606": "42ed6323-f645-5fbe-bada-9581819cf689",
83
+ "NCBITaxon:10090": "25285fab-48a0-5620-a6a0-f9a0374837d5",
84
+ "NCBITaxon:9685": "73060497-46a6-52bf-b975-cac511c127cb"
85
+ }
86
+
87
+ export default {
88
+ name: "MultiFlatmapVuer",
89
+ components: {
90
+ FlatmapVuer
91
+ },
92
+ beforeMount() {
93
+ //List for resolving the promise in initialise
94
+ //if initialise is called multiple times
95
+ this._resolveList = [];
96
+ this._initialised = false;
97
+ },
98
+ mounted: function() {
99
+ this.initialise();
100
+ EventBus.$on('onActionClick', (action) =>{
101
+ this.FlatmapSelected(action)
102
+ })
103
+ },
104
+ methods: {
105
+ initialise: function() {
106
+ return new Promise(resolve => {
107
+ if (this.requireInitialisation) {
108
+ //It has not been initialised yet
109
+ this.requireInitialisation = false;
110
+ fetch(this.flatmapAPI)
111
+ .then(response => response.json())
112
+ .then(data => {
113
+ //Check each key in the provided availableSpecies against the one
114
+ Object.keys(this.availableSpecies).forEach(key => {
115
+ // FIrst look through the uuid
116
+ const uuid = this.availableSpecies[key].uuid;
117
+ if (uuid && data.map(e => e.uuid).indexOf(uuid) > 0) {
118
+ this.$set(this.speciesList, key, this.availableSpecies[key]);
119
+ } else {
120
+ for (let i = 0; i < data.length; i++) {
121
+ if (this.availableSpecies[key].taxo === data[i].taxon) {
122
+ if (this.availableSpecies[key].biologicalSex) {
123
+ if (data[i].biologicalSex &&
124
+ data[i].biologicalSex === this.availableSpecies[key].biologicalSex) {
125
+ this.$set(this.speciesList, key, this.availableSpecies[key]);
126
+ break;
127
+ }
128
+ } else {
129
+ this.$set(this.speciesList, key, this.availableSpecies[key]);
130
+ break;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ });
136
+ //Use the state species if it does not have any other species information
137
+ let species = this.initial;
138
+ if (this.state) {
139
+ const mapState = this.state.state;
140
+ if ((!mapState || ( !mapState.uuid && !mapState.entry )) && this.state.species)
141
+ species = this.state.species;
142
+ else
143
+ species = undefined;
144
+ }
145
+ if (species) {
146
+ //No state resuming, set the current flatmap to {this.initial}
147
+ if (species && this.speciesList[species] !== undefined) {
148
+ this.activeSpecies = species;
149
+ } else {
150
+ this.activeSpecies = Object.keys(this.speciesList)[0];
151
+ }
152
+ this.setSpecies(this.activeSpecies, this.state ? this.state.state : undefined, 5);
153
+ }
154
+ this._initialised = true;
155
+ resolve();
156
+ //Resolve all other promises resolve in the list
157
+ this._resolveList.forEach(other => { other(); });
158
+ });
159
+ } else if (this._initialised) {
160
+ //resolve as it has been initialised
161
+ resolve();
162
+ } else {
163
+ //resolve when the async initialisation is finished
164
+ this._resolveList.push(resolve);
165
+ }
166
+ })
167
+ },
168
+ FlatmapSelected: function(resource) {
169
+ this.$emit("resource-selected", resource);
170
+ },
171
+ FlatmapReady: function(component) {
172
+ this.$emit("ready", component);
173
+ },
174
+ getCoordinatesOfLastClick: function() {
175
+ const flatmap = this.$refs[this.activeSpecies];
176
+ if (flatmap && flatmap[0]) {
177
+ return flatmap[0].getCoordinatesOfLastClick();
178
+ }
179
+ return undefined;
180
+ },
181
+ getCurrentFlatmap: function() {
182
+ return this.$refs[this.activeSpecies][0];
183
+ },
184
+ panZoomCallback: function(payload) {
185
+ this.$emit("pan-zoom-callback", payload);
186
+ },
187
+ showPopup: function(featureId, node, options) {
188
+ let map = this.getCurrentFlatmap();
189
+ map.showPopup(featureId, node, options);
190
+ },
191
+ showMarkerPopup: function(featureId, node, options) {
192
+ let map = this.getCurrentFlatmap();
193
+ map.showMarkerPopup(featureId, node, options);
194
+ },
195
+ setSpecies: function(species, state, numberOfRetry) {
196
+ if (this.$refs && species in this.$refs) {
197
+ this.activeSpecies = species;
198
+ this.$refs[this.activeSpecies][0].createFlatmap(state);
199
+ this.$emit('flatmapChanged', this.activeSpecies);
200
+ } else if (numberOfRetry) {
201
+ const retry = numberOfRetry - 1;
202
+ if (retry >= 0) {
203
+ Vue.nextTick(() => {
204
+ this.setSpecies(species, state, retry);
205
+ });
206
+ }
207
+ }
208
+ },
209
+ /**
210
+ * Function to switch to the latest existing map from
211
+ * a legacy map of the same species.
212
+ *
213
+ * @private
214
+ */
215
+ viewLatestMap: function(state) {
216
+ const keys = Object.keys(this.speciesList);
217
+ for (let i = 0; i < keys.length; i++) {
218
+ const species = this.speciesList[keys[i]];
219
+ if (!species.isLegacy &&
220
+ (species.taxo === state.entry) &&
221
+ (species.biologicalSex === state.biologicalSex)) {
222
+ this.setSpecies(keys[i], state, 0);
223
+ return;
224
+ }
225
+ }
226
+ },
227
+ /**
228
+ * Create a legacy entry with the provided information
229
+ *
230
+ * @private
231
+ */
232
+ createLegacyEntry: function(state, taxo, uuid) {
233
+ if (uuid && taxo) {
234
+ let name = "Legacy";
235
+ if (state.species) {
236
+ if (state.species.slice(0, 6) === "Legacy")
237
+ name = state.species;
238
+ else
239
+ name = name + ` ${state.species}`;
240
+ }
241
+ this.$set(
242
+ this.speciesList,
243
+ name,
244
+ {
245
+ taxo: taxo,
246
+ isLegacy: true,
247
+ displayWarning: true
248
+ }
249
+ );
250
+ return {
251
+ species: name,
252
+ state: {
253
+ entry: taxo,
254
+ uuid: uuid,
255
+ viewport: state.state.viewport,
256
+ searchTerm: state.state.searchTerm
257
+ },
258
+ }
259
+ }
260
+ },
261
+ /**
262
+ * Function used to translate the legacy map state to one that can be used in current
263
+ * flatmap if required. If it is a legacy, an Select entry will be added
264
+ *
265
+ * @private
266
+ */
267
+ updateState: function(state) {
268
+ return new Promise((resolve) => {
269
+ if (state && state.state) {
270
+ const mapState = state.state;
271
+ //uuid is not in the state, this is a legacy map
272
+ if (!mapState.uuid) {
273
+ if (mapState.entry) {
274
+ const uuid = mapState.entry in TAXON_UUID ? TAXON_UUID[mapState.entry] : undefined;
275
+ const newState = this.createLegacyEntry(state, mapState.entry, uuid);
276
+ resolve(newState ? newState : state);
277
+ }
278
+ } else if (mapState.entry) {
279
+ //uuid is in the state but should be checked if it is the latest map
280
+ //for that taxon
281
+ return new Promise(() => {
282
+ const mapManager = new (require("@abi-software/flatmap-viewer")).MapManager(this.flatmapAPI);
283
+ //mapManager.findMap_ is an async function so we need to wrap this with a promise
284
+ const identifier = { taxon: mapState.entry };
285
+ if (mapState.biologicalSex)
286
+ identifier['biologicalSex'] = mapState.biologicalSex;
287
+ mapManager.findMap_(identifier).then(map => {
288
+ if (map.uuid !== mapState.uuid) {
289
+ return this.createLegacyEntry(state, mapState.entry, mapState.uuid);
290
+ }
291
+ }).then(newState => {
292
+ resolve(newState ? newState : state);
293
+ })
294
+ .catch(() => {
295
+ resolve(state);
296
+ });
297
+ });
298
+ }
299
+ //Create a new state and add the legacy map to the select
300
+ }
301
+ resolve(state);
302
+ });
303
+ },
304
+ /**
305
+ * Function used for getting the current states of the scene. This exported states
306
+ * can be imported using the importStates method.
307
+ *
308
+ * @public
309
+ */
310
+ getState: function() {
311
+ let state = {
312
+ species: this.activeSpecies,
313
+ state: undefined,
314
+ };
315
+ let map = this.getCurrentFlatmap();
316
+ state.state = map.getState();
317
+ return state;
318
+ },
319
+ /**
320
+ * Function used for importing the states of the scene. This exported states
321
+ * can be imported using the read states method.
322
+ *
323
+ * @public
324
+ */
325
+ setState: function(state) {
326
+ if (state) {
327
+ //Update state if required
328
+ this.updateState(state).then(currentState => {
329
+ this.initialise().then(() => {
330
+ if (currentState.species && (currentState.species !== this.activeSpecies)) {
331
+ this.setSpecies(currentState.species, currentState.state, 5);
332
+ } else if (currentState.state) {
333
+ let map = this.getCurrentFlatmap();
334
+ map.setState(currentState.state);
335
+ }
336
+ });
337
+ });
338
+ }
339
+ },
340
+ resourceSelected: function(action) {
341
+ this.$emit("resource-selected", action);
342
+ },
343
+ },
344
+ props: {
345
+ showLayer: {
346
+ type: Boolean,
347
+ default: false
348
+ },
349
+ featureInfo: {
350
+ type: Boolean,
351
+ default: false
352
+ },
353
+ pathControls: {
354
+ type: Boolean,
355
+ default: true
356
+ },
357
+ searchable: {
358
+ type: Boolean,
359
+ default: false
360
+ },
361
+ layerControl: {
362
+ type: Boolean,
363
+ default: false
364
+ },
365
+ /**
366
+ * Initial species for the flatmap.
367
+ * This value will be ignored if a valid state object is provided.
368
+ */
369
+ initial: {
370
+ type: String,
371
+ default: ""
372
+ },
373
+ minZoom: {
374
+ type: Number,
375
+ default: 4
376
+ },
377
+ renderAtMounted: {
378
+ type: Boolean,
379
+ default: false
380
+ },
381
+ helpMode: {
382
+ type: Boolean,
383
+ default: false
384
+ },
385
+ displayMinimap: {
386
+ type: Boolean,
387
+ default: false
388
+ },
389
+ /**
390
+ * Flag to determine rather open map UI should be
391
+ * presented or not.
392
+ */
393
+ enableOpenMapUI: {
394
+ type: Boolean,
395
+ default: false,
396
+ },
397
+ openMapOptions: {
398
+ type: Array
399
+ },
400
+ availableSpecies: {
401
+ type: Object,
402
+ default: function() {
403
+ return {
404
+ "Human Female":{taxo: "NCBITaxon:9606", biologicalSex: "PATO:0000383", iconClass:"mapicon-icon_human", displayWarning:true},
405
+ "Human Male":{taxo: "NCBITaxon:9606", biologicalSex: "PATO:0000384", iconClass:"mapicon-icon_human", displayWarning:true},
406
+ "Rat":{taxo: "NCBITaxon:10114", iconClass:"mapicon-icon_rat", displayLatestChanges: true},
407
+ "Mouse":{taxo: "NCBITaxon:10090", iconClass:"mapicon-icon_mouse", displayWarning: true},
408
+ "Pig":{taxo: "NCBITaxon:9823", iconClass:"mapicon-icon_pig", displayWarning: true},
409
+ "Cat":{taxo: "NCBITaxon:9685", iconClass:"mapicon-icon_cat", displayWarning: true},
410
+ }
411
+ }
412
+ },
413
+ /**
414
+ * State containing state of the flatmap.
415
+ */
416
+ state: {
417
+ type: Object,
418
+ default: undefined,
419
+ },
420
+ /**
421
+ * Specify the endpoint of the flatmap server.
422
+ */
423
+ flatmapAPI: {
424
+ type: String,
425
+ default: "https://mapcore-demo.org/current/flatmap/v3/"
426
+ },
427
+ sparcAPI: {
428
+ type: String,
429
+ default: "https://api.sparc.science/"
430
+ }
431
+ },
432
+ data: function() {
433
+ return {
434
+ activeSpecies: undefined,
435
+ appendToBody: false,
436
+ speciesList: {},
437
+ requireInitialisation: true
438
+ };
439
+ },
440
+ watch: {
441
+ state: {
442
+ handler: function(state) {
443
+ this.setState(state);
444
+ },
445
+ immediate: true,
446
+ deep: true,
447
+ }
448
+ }
449
+ };
450
+ </script>
451
+
452
+ <style scoped lang="scss">
453
+ @import "~element-ui/packages/theme-chalk/src/select";
454
+ @import "~element-ui/packages/theme-chalk/src/option";
455
+
456
+ .multi-container {
457
+ height: 100%;
458
+ width: 100%;
459
+ }
460
+
461
+ .species-display-text {
462
+ width: 47px;
463
+ height: 20px;
464
+ color: rgb(48, 49, 51);
465
+ font-size: 14px;
466
+ font-weight: normal;
467
+ line-height: 20px;
468
+ left:24px;
469
+ top:16px;
470
+ position: absolute;
471
+ }
472
+
473
+ .select-box {
474
+ width: 120px;
475
+ border-radius: 4px;
476
+ border: 1px solid rgb(144, 147, 153);
477
+ background-color: var(--white);
478
+ font-weight: 500;
479
+ color:rgb(48, 49, 51);;
480
+ left: 16px;
481
+ top: 44px;
482
+ position: absolute;
483
+ ::v-deep .el-input__inner {
484
+ color: rgb(48, 49, 51);
485
+ padding-top: 0.25em;
486
+ .is-focus {
487
+ border: 1px solid $app-primary-color;
488
+ }
489
+ }
490
+ }
491
+
492
+
493
+ ::v-deep .flatmap_dropdown {
494
+ min-width: 160px!important;
495
+ .el-select-dropdown__item {
496
+ white-space: nowrap;
497
+ text-align: left;
498
+ &.selected {
499
+ color: $app-primary-color;
500
+ font-weight: normal;
501
+ }
502
+ }
503
+ }
504
+
505
+ ::v-deep .flatmap-popper {
506
+ padding: 6px 4px;
507
+ font-size:12px;
508
+ color: rgb(48, 49, 51);
509
+ background-color: #f3ecf6;
510
+ border: 1px solid $app-primary-color;
511
+ white-space: nowrap;
512
+ min-width: unset;
513
+ &.right-popper {
514
+ .popper__arrow {
515
+ border-right-color: $app-primary-color !important;
516
+ &:after {
517
+ border-right-color: #f3ecf6 !important;
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+ ::v-deep .flatmap-marker-popup{
524
+ background-color: #f0f0f000 !important;
525
+ box-shadow: none !important;
526
+ }
527
+
528
+ </style>
529
+