@abi-software/flatmapvuer 0.3.2 → 0.3.3

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,1353 +1,1358 @@
1
- <template>
2
- <div
3
- class="flatmap-container"
4
- v-loading="loading"
5
- element-loading-text="Loading..."
6
- element-loading-spinner="el-icon-loading"
7
- element-loading-background="rgba(0, 0, 0, 0.3)"
8
- >
9
- <map-svg-sprite-color />
10
- <div style="height:100%;width:100%;position:relative;overflow-y:none">
11
- <div style="height:100%;width:100%;" ref="display"></div>
12
- <div class="beta-popovers">
13
- <div>
14
- <el-popover
15
- :content="warningMessage"
16
- placement="right"
17
- v-if="displayWarning"
18
- :appendToBody="false"
19
- trigger="manual"
20
- popper-class="warning-popper flatmap-popper right-popper"
21
- v-model="hoverVisibilities[6].value"
22
- ref="warningPopover"
23
- ></el-popover>
24
- <i
25
- class="el-icon-warning warning-icon"
26
- v-if="displayWarning"
27
- @mouseover="showToolitip(6)"
28
- @mouseout="hideToolitip(6)"
29
- v-popover:warningPopover
30
- >
31
- <span class="warning-text">Beta</span>
32
- </i>
33
- </div>
34
- <el-popover
35
- :content="latestChangesMessage"
36
- placement="right"
37
- v-if="displayLatestChanges"
38
- :appendToBody="false"
39
- trigger="manual"
40
- popper-class="warning-popper flatmap-popper right-popper"
41
- v-model="hoverVisibilities[7].value"
42
- ref="latestChangesPopover"
43
- ></el-popover>
44
- <i
45
- class="el-icon-warning latest-changesicon"
46
- v-if="displayLatestChanges"
47
- @mouseover="showToolitip(7)"
48
- @mouseout="hideToolitip(7)"
49
- v-popover:latestChangesPopover
50
- >
51
- <span class="warning-text">What's new?</span>
52
- </i>
53
- </div>
54
-
55
- <div class="bottom-right-control">
56
- <el-popover
57
- content="Zoom in"
58
- placement="left"
59
- :appendToBody="false"
60
- trigger="manual"
61
- popper-class="flatmap-popper left-popper"
62
- v-model="hoverVisibilities[0].value"
63
- >
64
- <map-svg-icon
65
- icon="zoomIn"
66
- class="icon-button zoomIn"
67
- slot="reference"
68
- @click.native="zoomIn()"
69
- @mouseover.native="showToolitip(0)"
70
- @mouseout.native="hideToolitip(0)"
71
- />
72
- </el-popover>
73
- <el-popover
74
- content="Zoom out"
75
- placement="top-end"
76
- :appendToBody="false"
77
- trigger="manual"
78
- popper-class="flatmap-popper popper-zoomout"
79
- v-model="hoverVisibilities[1].value"
80
- >
81
- <map-svg-icon
82
- icon="zoomOut"
83
- class="icon-button zoomOut"
84
- slot="reference"
85
- @click.native="zoomOut()"
86
- @mouseover.native="showToolitip(1)"
87
- @mouseout.native="hideToolitip(1)"
88
- />
89
- </el-popover>
90
- <el-popover
91
- content="Reset"
92
- placement="top"
93
- :appendToBody="false"
94
- trigger="manual"
95
- popper-class="flatmap-popper"
96
- v-model="hoverVisibilities[2].value"
97
- >
98
- <div>
99
- Fit to
100
- <br>
101
- window
102
- </div>
103
- <map-svg-icon
104
- slot="reference"
105
- icon="fitWindow"
106
- class="icon-button fitWindow"
107
- @click.native="resetView()"
108
- @mouseover.native="showToolitip(2)"
109
- @mouseout.native="hideToolitip(2)"
110
- />
111
- </el-popover>
112
- </div>
113
- <el-popover
114
- content="Change pathway visibility"
115
- placement="right"
116
- :appendToBody="false"
117
- trigger="manual"
118
- popper-class="flatmap-popper right-popper"
119
- v-model="hoverVisibilities[4].value"
120
- ref="checkBoxPopover"
121
- />
122
- <div class="pathway-location" :class="{ open: drawerOpen, close: !drawerOpen }">
123
- <div
124
- class="pathway-container"
125
- v-if="pathways.length > 0 && pathControls"
126
- v-popover:checkBoxPopover
127
- >
128
- <el-popover
129
- content="Find these markers for data"
130
- placement="right"
131
- :appendToBody="false"
132
- trigger="manual"
133
- popper-class="flatmap-popper popper-bump-right right-popper"
134
- v-model="hoverVisibilities[5].value"
135
- ref="markerPopover"
136
- ></el-popover>
137
- <div
138
- v-show="hoverVisibilities[5].value"
139
- class="flatmap-marker-help"
140
- v-html="flatmapMarker"
141
- v-popover:markerPopover
142
- ></div>
143
- <el-row>
144
- <el-col :span="12">
145
- <div class="pathways-display-text">Pathways</div>
146
- </el-col>
147
- <el-col :span="12">
148
- <el-checkbox
149
- class="all-checkbox"
150
- :indeterminate="isIndeterminate"
151
- v-model="checkAll"
152
- @change="handleCheckAllChange"
153
- >Display all</el-checkbox>
154
- </el-col>
155
- </el-row>
156
- <el-checkbox-group
157
- v-model="checkedItems"
158
- size="small"
159
- class="checkbox-group"
160
- @change="handleCheckedItemsChange"
161
- >
162
- <div class="checkbox-group-inner">
163
- <el-row v-for="item in pathways" :key="item.type" :label="item.type">
164
- <div class="checkbox-container">
165
- <el-checkbox
166
- class="my-checkbox"
167
- :label="item.type"
168
- @change="visibilityToggle()"
169
- :checked="true"
170
- >
171
- <div class="path-visual" :class="item.type"></div>
172
- {{item.label}}
173
- </el-checkbox>
174
- </div>
175
- </el-row>
176
- </div>
177
- </el-checkbox-group>
178
- </div>
179
- <div
180
- @click="toggleDrawer"
181
- class="drawer-button"
182
- :class="{ open: drawerOpen, close: !drawerOpen }"
183
- >
184
- <i class="el-icon-arrow-left"></i>
185
- </div>
186
- </div>
187
- <el-popover
188
- ref="backgroundPopover"
189
- placement="top-start"
190
- width="175"
191
- :appendToBody="false"
192
- trigger="click"
193
- popper-class="background-popper"
194
- >
195
- <el-row class="backgroundText">Organs display</el-row>
196
- <el-row class="backgroundControl">
197
- <el-radio-group v-model="colourRadio" class="flatmap-radio" @change="setColour">
198
- <el-radio :label="true">Colour</el-radio>
199
- <el-radio :label="false">Greyscale</el-radio>
200
- </el-radio-group>
201
- </el-row>
202
- <el-row class="backgroundSpacer"></el-row>
203
- <el-row class="backgroundText">Outlines display</el-row>
204
- <el-row class="backgroundControl">
205
- <el-radio-group v-model="outlinesRadio" class="flatmap-radio" @change="setOutlines">
206
- <el-radio :label="true">Show</el-radio>
207
- <el-radio :label="false">Hide</el-radio>
208
- </el-radio-group>
209
- </el-row>
210
- <el-row class="backgroundSpacer"></el-row>
211
- <el-row class="backgroundText">Change background</el-row>
212
- <el-row class="backgroundControl">
213
- <div
214
- v-for="item in availableBackground"
215
- :key="item"
216
- :class="['backgroundChoice', item, item == currentBackground ? 'active' :'']"
217
- @click="backgroundChangeCallback(item)"
218
- />
219
- </el-row>
220
- </el-popover>
221
- <el-popover
222
- content="Change background color"
223
- placement="right"
224
- v-model="hoverVisibilities[3].value"
225
- :appendToBody="false"
226
- trigger="manual"
227
- popper-class="flatmap-popper right-popper"
228
- >
229
- <map-svg-icon
230
- v-popover:backgroundPopover
231
- icon="changeBckgd"
232
- class="icon-button background-colour"
233
- :class="{ open: drawerOpen, close: !drawerOpen }"
234
- slot="reference"
235
- @mouseover.native="showToolitip(3)"
236
- @mouseout.native="hideToolitip(3)"
237
- />
238
- </el-popover>
239
- <Tooltip
240
- ref="tooltip"
241
- class="tooltip"
242
- :content="tooltipContent"
243
- @resource-selected="resourceSelected"
244
- />
245
- </div>
246
- </div>
247
- </template>
248
-
249
- <script>
250
- /* eslint-disable no-alert, no-console */
251
- import Vue from "vue";
252
- import Tooltip from "./Tooltip";
253
- import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
254
- import {
255
- Checkbox,
256
- CheckboxGroup,
257
- Col,
258
- Loading,
259
- Radio,
260
- RadioGroup,
261
- Row
262
- } from "element-ui";
263
- import lang from "element-ui/lib/locale/lang/en";
264
- import locale from "element-ui/lib/locale";
265
- import flatmapMarker from "../icons/flatmap-marker";
266
-
267
- locale.use(lang);
268
- Vue.use(Checkbox);
269
- Vue.use(CheckboxGroup);
270
- Vue.use(Col);
271
- Vue.use(Loading.directive);
272
- Vue.use(Radio);
273
- Vue.use(RadioGroup);
274
- Vue.use(Row);
275
- const ResizeSensor = require("css-element-queries/src/ResizeSensor");
276
-
277
- const mapResize = map => {
278
- return () => {
279
- if (map) map.resize();
280
- };
281
- };
282
-
283
- export default {
284
- name: "FlatmapVuer",
285
- components: {
286
- MapSvgIcon,
287
- MapSvgSpriteColor,
288
- Tooltip
289
- },
290
- beforeCreate: function() {
291
- this.mapManager = undefined;
292
- this.mapImp = undefined;
293
- },
294
- methods: {
295
- backgroundChangeCallback: function(colour) {
296
- this.currentBackground = colour;
297
- if (this.mapImp) {
298
- this.mapImp.setBackgroundColour(this.currentBackground, 1);
299
- }
300
- },
301
- toggleDrawer: function() {
302
- this.drawerOpen = !this.drawerOpen;
303
- },
304
- /**
305
- * Function to toggle colour/greyscale of organs.
306
- */
307
- setColour: function(flag) {
308
- this.colourRadio = flag;
309
- if (this.mapImp) {
310
- this.mapImp.setColour({ colour: flag, outline: this.outlinesRadio });
311
- }
312
- },
313
- /**
314
- * Function to toggle outlines f organs.
315
- */
316
- setOutlines: function(flag) {
317
- this.outlineRadio = flag;
318
- if (this.mapImp) {
319
- this.mapImp.setColour({ colour: this.colourRadio, outline: flag });
320
- }
321
- },
322
- /**
323
- * Function to toggle paths to default.
324
- * Also called when the associated button is pressed.
325
- */
326
- resetView: function() {
327
- if (this.mapImp) {
328
- this.mapImp.resetMap();
329
- this.checkedItems = this.mapImp.pathTypes().map(item => item.type);
330
- this.isIndeterminate = false;
331
- this.checkAll = true;
332
- }
333
- },
334
- /**
335
- * Function to zoom in.
336
- * Also called when the associated button is pressed.
337
- */
338
- zoomIn: function() {
339
- if (this.mapImp) {
340
- this.mapImp.zoomIn();
341
- }
342
- },
343
- /**
344
- * Function to zoom out.
345
- * Also called when the associated button is pressed.
346
- */
347
- zoomOut: function() {
348
- if (this.mapImp) {
349
- this.mapImp.zoomOut();
350
- }
351
- },
352
- visibilityToggle: function() {
353
- if (this.mapImp) {
354
- this.mapImp.showPaths(this.checkedItems);
355
- }
356
- },
357
- handleCheckedItemsChange: function(value) {
358
- let checkedCount = value.length;
359
- this.checkAll = checkedCount === this.pathways.length;
360
- this.isIndeterminate =
361
- checkedCount > 0 && checkedCount < this.pathways.length;
362
- },
363
- handleCheckAllChange(val) {
364
- this.checkedItems = val ? this.pathways.map(a => a.type) : [];
365
- this.isIndeterminate = false;
366
- if (this.mapImp) {
367
- this.mapImp.showPaths(this.checkedItems);
368
- }
369
- },
370
- enablePanZoomEvents: function(flag) {
371
- this.mapImp.enablePanZoomEvents(flag);
372
- },
373
- eventCallback: function() {
374
- return (eventType, data, ...args) => {
375
- if (eventType !== "pan-zoom") {
376
- const label = data.label;
377
- const resource = [data.models];
378
- const taxonomy = this.entry;
379
- const payload = {
380
- dataset: data.dataset,
381
- taxonomy: taxonomy,
382
- resource: resource,
383
- label: label,
384
- feature: data,
385
- userData: args,
386
- eventType: eventType
387
- };
388
- // Disable the nueron pop up for now.
389
- if (data && data.type !== "marker")
390
- this.checkAndCreatePopups(payload);
391
- this.$emit("resource-selected", payload);
392
- } else {
393
- this.$emit("pan-zoom-callback", data);
394
- }
395
- };
396
- },
397
- // checkNeuronClicked shows a neuron path pop up if a path was recently clicked
398
- checkAndCreatePopups: function(data) {
399
- if (
400
- data.eventType == "click" &&
401
- this.hasNeuronTooltip(data)
402
- ) {
403
- this.createTooltipFromNeuronCuration(data);
404
- this.mapImp.showPopup(
405
- this.mapImp.modelFeatureIds(data.resource[0])[0],
406
- this.$refs.tooltip.$el,
407
- { className: "flatmapvuer-popover", positionAtLastClick: true }
408
- );
409
- this.popUpCssHacks();
410
- }
411
- },
412
- popUpCssHacks: function() {
413
- // Below is a hack to remove flatmap tooltips while popup is open
414
- let ftooltip = document.querySelector(".flatmap-tooltip-popup");
415
- if (ftooltip) ftooltip.style.display = "none";
416
- document.querySelector(".mapboxgl-popup-close-button").style.display =
417
- "block";
418
- this.$refs.tooltip.$el.style.display = "flex";
419
- document.querySelector(".mapboxgl-popup-close-button").onclick = () => {
420
- document.querySelector(".flatmap-tooltip-popup").style.display =
421
- "block";
422
- };
423
- },
424
- resourceSelected: function(action) {
425
- this.$emit("resource-selected", action);
426
- },
427
- hasNeuronTooltip: function(data) {
428
-
429
- // neural data check
430
- if (data.resource[0]){
431
- if (data.resource[0].includes('ilxtr:neuron')){
432
- return true
433
- }
434
- }
435
- // annotated with datset check
436
- if (data.dataset) {
437
- return true
438
- }
439
-
440
- // if there is no cuff, neural data, or dataset we do not display neuron tooltip
441
- return false
442
-
443
- },
444
- createTooltipFromNeuronCuration: function(data) {
445
- const feature = data.resource[0];
446
- let content = {
447
- title: undefined,
448
- components: undefined,
449
- start: undefined,
450
- distribution: undefined,
451
- actions: []
452
- };
453
-
454
- this.tooltipVisible = false;
455
-
456
- // neural data check
457
- if (feature){
458
- if (feature.includes('ilxtr:neuron')){
459
- this.tooltipVisible = true;
460
- this.tooltipContent = content;
461
- this.tooltipContent.uberon = feature;
462
- this.tooltipContent.title = data.label;
463
- this.tooltipContent.featureIds = [feature];
464
- this.tooltipContent.actions.push({
465
- title: "Search for datasets",
466
- label: "Neuron Datasets",
467
- resource: feature.split(":")[1],
468
- type: "Neuron Search",
469
- feature: feature,
470
- nervePath: true
471
- });
472
- }
473
- }
474
- // annotated with datset check
475
- if (data.dataset) {
476
- this.tooltipVisible = true;
477
- this.tooltipContent = content;
478
- this.tooltipContent.uberon = feature;
479
- this.tooltipContent.title = data.label;
480
- this.tooltipContent.actions.push({
481
- title: "View dataset",
482
- resource: data.dataset,
483
- type: "URL",
484
- feature: feature,
485
- nervePath: false
486
- });
487
- }
488
- },
489
- // Keeping this as an API
490
- showPopup: function(featureId, node, options) {
491
- let myOptions = options;
492
- if (this.mapImp) {
493
- if (myOptions) {
494
- if (!myOptions.className) myOptions.className = "flatmapvuer-popover";
495
- } else {
496
- myOptions = { className: "flatmapvuer-popover", positionAtLastClick: true };
497
- }
498
- this.mapImp.showPopup(featureId, node, myOptions);
499
- }
500
- },
501
- showMarkerPopup: function(featureId, node, options) {
502
- if (this.mapImp) {
503
- this.mapImp.showMarkerPopup(featureId, node, options);
504
- }
505
- },
506
- setHelpMode: function(helpMode) {
507
- if (helpMode) {
508
- this.inHelp = true;
509
- this.hoverVisibilities.forEach(item => {
510
- item.value = true;
511
- });
512
- this.openFlatmapHelpPopup();
513
- } else {
514
- this.inHelp = false;
515
- this.hoverVisibilities.forEach(item => {
516
- item.value = false;
517
- });
518
- this.closeFlatmapHelpPopup();
519
- }
520
- },
521
- showToolitip: function(tooltipNumber) {
522
- if (!this.inHelp) {
523
- this.tooltipWait = setTimeout(() => {
524
- this.hoverVisibilities[tooltipNumber].value = true;
525
- }, 500);
526
- }
527
- },
528
- hideToolitip: function(tooltipNumber) {
529
- if (!this.inHelp) {
530
- this.hoverVisibilities[tooltipNumber].value = false;
531
- clearTimeout(this.tooltipWait);
532
- }
533
- },
534
- openFlatmapHelpPopup: function() {
535
- if (this.mapImp) {
536
- let heartId = this.mapImp.featureIdsForModel("UBERON:0000948")[0];
537
- const elm = "Click for more information";
538
- this.mapImp.showPopup(heartId, elm, {
539
- anchor: "top",
540
- className: "flatmap-popup-popper"
541
- });
542
- }
543
- },
544
- closeFlatmapHelpPopup: function() {
545
- this.$el
546
- .querySelectorAll(".mapboxgl-popup-close-button")
547
- .forEach(item => {
548
- item.click();
549
- });
550
- },
551
- getLabels: function() {
552
- let labels = [];
553
- if (this.mapImp) {
554
- let annotations = this.mapImp.annotations;
555
- for (let value of annotations.values()) {
556
- if (value.label) labels.push(value.label);
557
- }
558
- return Array.from(new Set(labels));
559
- }
560
- },
561
- getState: function() {
562
- if (this.mapImp) {
563
- let state = {
564
- entry: this.entry,
565
- viewport: this.mapImp.getState()
566
- };
567
- return state;
568
- }
569
- return undefined;
570
- },
571
- setState: function(state) {
572
- if (state) {
573
- if (this.mapImp && state.entry) {
574
- if (this.entry == state.entry)
575
- if (state.viewport) {
576
- this.mapImp.setState(state.viewport);
577
- }
578
- } else {
579
- this.createFlatmap(state);
580
- }
581
- }
582
- },
583
- createFlatmap: function(state) {
584
- if (!this.mapImp && !this.loading) {
585
- this.loading = true;
586
- let minimap = false;
587
- if (this.displayMinimap) {
588
- minimap = { position: "top-right" };
589
- }
590
- let entry = this.entry;
591
- if (state && state.entry) entry = state.entry;
592
- let promise1 = this.mapManager.loadMap(
593
- entry,
594
- this.$refs.display,
595
- this.eventCallback(),
596
- {
597
- //fullscreenControl: false,
598
- //annotatable: false,
599
- //debug: true,
600
- featureInfo: this.featureInfo,
601
- "min-zoom": this.minZoom,
602
- pathControls: false,
603
- searchable: this.searchable,
604
- tooltips: this.tooltips,
605
- minimap: minimap
606
- }
607
- );
608
- promise1.then(returnedObject => {
609
- this.mapImp = returnedObject;
610
- this.sensor = new ResizeSensor(
611
- this.$refs.display,
612
- mapResize(this.mapImp)
613
- );
614
- this.mapImp.setBackgroundOpacity(1);
615
- this.backgroundChangeCallback(this.currentBackground);
616
- this.pathways = this.mapImp.pathTypes();
617
- this.$emit("ready", this);
618
- this.loading = false;
619
- if (this._viewportToBeSet)
620
- this.mapImp.setState(this._viewportToBeSet);
621
- else if (state && state.viewport)
622
- this.mapImp.setState(state.viewport);
623
- });
624
- } else if (state) {
625
- if (this.entry == state.entry) this._viewportToBeSet = state.viewport;
626
- }
627
- },
628
- showMinimap: function(flag) {
629
- if (this.mapImp)
630
- this.mapImp.showMinimap(flag);
631
- },
632
- showPathwaysDrawer: function(flag) {
633
- this.drawerOpen = flag;
634
- },
635
- /**
636
- * Function to display features with annotation matching the provided term.
637
- */
638
- searchAndShowResult: function(term) {
639
- if (this.mapImp) {
640
- if (term === undefined || term === "") {
641
- this.mapImp.clearSearchResults();
642
- return true;
643
- } else {
644
- let searchResults = this.mapImp.search(term);
645
- if (searchResults && searchResults.__featureIds.length > 0) {
646
- this.mapImp.showSearchResults(searchResults);
647
- return true;
648
- }
649
- else
650
- this.mapImp.clearSearchResults();
651
- }
652
- }
653
- return false;
654
- }
655
- },
656
- props: {
657
- entry: String,
658
- featureInfo: {
659
- type: Boolean,
660
- default: false
661
- },
662
- minZoom: {
663
- type: Number,
664
- default: 4
665
- },
666
- pathControls: {
667
- type: Boolean,
668
- default: true
669
- },
670
- searchable: {
671
- type: Boolean,
672
- default: false
673
- },
674
- tooltips: {
675
- type: Boolean,
676
- default: true
677
- },
678
- helpMode: {
679
- type: Boolean,
680
- default: false
681
- },
682
- renderAtMounted: {
683
- type: Boolean,
684
- default: true
685
- },
686
- displayWarning: {
687
- type: Boolean,
688
- default: true
689
- },
690
- displayMinimap: {
691
- type: Boolean,
692
- default: false
693
- },
694
- warningMessage: {
695
- type: String,
696
- default: "Beta feature - This map is based on the connectivity of a rat. New connectivity and species specificity will be added as the SPARC program progress."
697
- },
698
- /**
699
- * State containing state of the flatmap.
700
- */
701
- state: {
702
- type: Object,
703
- default: undefined
704
- },
705
- /**
706
- * Specify the endpoint of the flatmap server.
707
- */
708
- flatmapAPI: {
709
- type: String,
710
- default: "https://mapcore-demo.org/flatmaps/"
711
- },
712
- sparcAPI: {
713
- type: String,
714
- default: "https://api.sparc.science/"
715
- }
716
- },
717
- provide() {
718
- return {
719
- sparcAPI: this.sparcAPI,
720
- flatmapAPI: this.flatmapAPI
721
- }
722
- },
723
- data: function() {
724
- return {
725
- checkedItems: [],
726
- pathways: [],
727
- isIndeterminate: false,
728
- checkAll: true,
729
- hoverVisibilities: [
730
- { value: false },
731
- { value: false },
732
- { value: false },
733
- { value: false },
734
- { value: false },
735
- { value: false },
736
- { value: false },
737
- { value: false }
738
- ],
739
- inHelp: false,
740
- displayLatestChanges: true,
741
- latestChangesMessage: "Bladder connectivity can now be explored and searched on when selected! To see it, click on any of the paths coming from the bladder. Other pathways will be searchable soon.",
742
- currentBackground: "white",
743
- availableBackground: ["white", "lightskyblue", "black"],
744
- loading: false,
745
- flatmapMarker: flatmapMarker,
746
- drawerOpen: true,
747
- tooltipContent: { featureIds: []},
748
- colourRadio: true,
749
- outlinesRadio: true
750
- };
751
- },
752
- watch: {
753
- entry: function() {
754
- if (!this.state) this.createFlatmap();
755
- },
756
- helpMode: function(val) {
757
- this.setHelpMode(val);
758
- },
759
- state: {
760
- handler: function(state) {
761
- this.setState(state);
762
- },
763
- immediate: true,
764
- deep: true
765
- }
766
- },
767
- mounted: function() {
768
- const flatmap = require("@abi-software/flatmap-viewer");
769
- this.mapManager = new flatmap.MapManager(this.flatmapAPI);
770
- if (this.renderAtMounted) this.createFlatmap();
771
- }
772
- };
773
- </script>
774
-
775
- <!-- Add "scoped" attribute to limit CSS to this component only -->
776
- <style scoped lang="scss">
777
- @import "~element-ui/packages/theme-chalk/src/button";
778
- @import "~element-ui/packages/theme-chalk/src/checkbox";
779
- @import "~element-ui/packages/theme-chalk/src/checkbox-group";
780
- @import "~element-ui/packages/theme-chalk/src/loading";
781
- @import "~element-ui/packages/theme-chalk/src/row";
782
-
783
- .beta-popovers{
784
- position: absolute;
785
- top: 90px;
786
- left: 16px;
787
- text-align: left;
788
- font-size: 25px;
789
- }
790
-
791
- .warning-icon {
792
- color: $warning;
793
-
794
- &:hover {
795
- cursor: pointer;
796
- }
797
- }
798
-
799
- .warning-text {
800
- font-family: Asap, sans-serif;
801
- font-size: 15px;
802
- vertical-align: 5px;
803
- }
804
-
805
- .latest-changesicon {
806
- color: $success;
807
-
808
- &:hover {
809
- cursor: pointer;
810
- }
811
- }
812
-
813
- .latest-changestext {
814
- font-family: Asap, sans-serif;
815
- font-size: 15px;
816
- vertical-align: 5px;
817
- }
818
-
819
- .path-visual {
820
- margin: 3px 0;
821
- height: 3px;
822
- width: 25px;
823
- margin-right: 5px;
824
- display: inline-block;
825
- &.cns {
826
- background: #9b1fc1;
827
- }
828
- &.lcn {
829
- background: #f19e38;
830
- }
831
- &.para-pre {
832
- background: #3f8f4a;
833
- }
834
- &.para-post {
835
- background: repeating-linear-gradient(
836
- 90deg,
837
- #3f8f4a,
838
- #3f8f4a 6px,
839
- transparent 0,
840
- transparent 9px
841
- );
842
- }
843
- &.sensory {
844
- background: #2a62f6;
845
- }
846
- &.somatic {
847
- background: #98561d;
848
- }
849
- &.symp-pre {
850
- background: #ea3423;
851
- }
852
- &.symp-post {
853
- background: repeating-linear-gradient(
854
- 90deg,
855
- #ea3423,
856
- #ea3423 6px,
857
- transparent 0,
858
- transparent 9px
859
- );
860
- }
861
- }
862
-
863
- .flatmap-container {
864
- height: 100%;
865
- width: 100%;
866
- }
867
-
868
- .pathway-location {
869
- position: absolute;
870
- bottom: 0px;
871
- transition: all 1s ease;
872
- &.open {
873
- left: 0px;
874
- }
875
- &.close {
876
- left: -298px;
877
- }
878
- }
879
-
880
- .pathway-container {
881
- float: left;
882
- padding-left: 16px;
883
- padding-right: 18px;
884
- max-height: calc(100% - 184px);
885
- text-align: left;
886
- overflow: auto;
887
- border: 1px solid rgb(220, 223, 230);
888
- padding-top: 7px;
889
- padding-bottom: 16px;
890
- background: #ffffff;
891
- }
892
-
893
- .pathways-display-text {
894
- width: 59px;
895
- height: 20px;
896
- color: rgb(48, 49, 51);
897
- font-size: 14px;
898
- font-weight: normal;
899
- line-height: 20px;
900
- margin-left: 8px;
901
- }
902
-
903
- .all-checkbox {
904
- float: right;
905
- }
906
-
907
- .checkbox-container {
908
- display: flex;
909
- cursor: pointer;
910
- }
911
-
912
- .checkbox-group {
913
- width: 260px;
914
- border: 1px solid rgb(144, 147, 153);
915
- border-radius: 4px;
916
- background: #ffffff;
917
- }
918
-
919
- .my-checkbox {
920
- background-color: #fff;
921
- width: 100%;
922
- }
923
-
924
- .checkbox-group-inner {
925
- padding: 18px;
926
- }
927
-
928
- .flatmap-marker-help {
929
- display: inline-block;
930
- }
931
-
932
- ::v-deep .popper-bump-right {
933
- left: 30px;
934
- }
935
-
936
- ::v-deep .el-checkbox__label {
937
- padding-left: 5px;
938
- color: $app-primary-color;
939
- font-size: 12px;
940
- font-weight: 500;
941
- letter-spacing: 0px;
942
- line-height: 14px;
943
- }
944
-
945
- ::v-deep .el-checkbox__input {
946
- &.is-indeterminate,
947
- &.is-checked {
948
- .el-checkbox__inner {
949
- background-color: $app-primary-color;
950
- border-color: $app-primary-color;
951
- }
952
- }
953
- }
954
-
955
- ::v-deep .el-checkbox__label {
956
- color: $app-primary-color !important;
957
- }
958
-
959
- .el-dropdown-link {
960
- cursor: pointer;
961
- color: #409eff;
962
- }
963
- .el-icon-arrow-down {
964
- font-size: 12px;
965
- }
966
- .demonstration {
967
- display: block;
968
- color: #8492a6;
969
- font-size: 14px;
970
- margin-bottom: 20px;
971
- }
972
-
973
- .tooltip {
974
- display: none;
975
- }
976
-
977
- ::v-deep .mapboxgl-popup {
978
- max-width: 300px !important;
979
- }
980
-
981
- ::v-deep .flatmap-tooltip-popup {
982
- &.mapboxgl-popup-anchor-bottom {
983
- .mapboxgl-popup-content {
984
- margin-bottom: 12px;
985
- &::after,
986
- &::before {
987
- top: 100%;
988
- border-width: 12px;
989
- }
990
- /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
991
- &::after {
992
- margin-top: -1px;
993
- border-color: rgb(255, 255, 255) transparent transparent transparent;
994
- }
995
- /* this border color controlls the outside, thin border */
996
- &::before {
997
- margin: 0 auto;
998
- border-color: $app-primary-color transparent transparent transparent;
999
- }
1000
- }
1001
- }
1002
- &.mapboxgl-popup-anchor-top {
1003
- .mapboxgl-popup-content {
1004
- margin-top: 18px;
1005
- &::after,
1006
- &::before {
1007
- top: calc(-100% + 6px);
1008
- border-width: 12px;
1009
- }
1010
- /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1011
- &::after {
1012
- margin-top: 1px;
1013
- border-color: transparent transparent rgb(255, 255, 255) transparent;
1014
- }
1015
- &::before {
1016
- margin: 0 auto;
1017
- border-color: transparent transparent $app-primary-color transparent;
1018
- }
1019
- }
1020
- }
1021
- .mapboxgl-popup-content {
1022
- border-radius: 4px;
1023
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
1024
- pointer-events: none;
1025
- display: none;
1026
- background: #fff;
1027
- border: 1px solid $app-primary-color;
1028
- padding-left: 6px;
1029
- padding-right: 6px;
1030
- display: flex;
1031
- justify-content: center;
1032
- align-items: center;
1033
- &::after,
1034
- &::before {
1035
- content: "";
1036
- display: block;
1037
- position: absolute;
1038
- width: 0;
1039
- height: 0;
1040
- border-style: solid;
1041
- flex-shrink: 0;
1042
- }
1043
- }
1044
- .mapboxgl-popup-tip {
1045
- display: none;
1046
- }
1047
- }
1048
-
1049
- ::v-deep .mapboxgl-popup {
1050
- &.flatmap-marker-popup {
1051
- box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
1052
- pointer-events: auto;
1053
- background: #fff;
1054
- }
1055
- }
1056
-
1057
- /* Fix for chrome bug where under triangle pops up above one on top of it */
1058
- .selector:not(*:root),
1059
- ::v-deep.flatmap-tooltip-popup {
1060
- .mapboxgl-popup-content::after {
1061
- top: 99.9%;
1062
- }
1063
- }
1064
-
1065
- ::v-deep .flatmap-tooltip-dialog {
1066
- .mapboxgl-popup-tip {
1067
- display: none;
1068
- }
1069
- }
1070
-
1071
- ::v-deep .flatmap-marker-popup {
1072
- .mapboxgl-popup-content {
1073
- padding: 0px;
1074
- }
1075
- }
1076
-
1077
- ::v-deep .flatmapvuer-popover {
1078
- .mapboxgl-popup-close-button {
1079
- position: absolute;
1080
- right: 0.5em;
1081
- top: 0;
1082
- border: 0;
1083
- border-radius: 0 3px 0 0;
1084
- cursor: pointer;
1085
- background-color: transparent;
1086
- font-size: 2.5em;
1087
- color: grey;
1088
- top: 0.95em;
1089
- }
1090
- }
1091
-
1092
- .zoomOut {
1093
- padding-left: 8px;
1094
- }
1095
-
1096
- .fitWindow {
1097
- padding-left: 8px;
1098
- }
1099
-
1100
- .background-colour {
1101
- bottom: 16px;
1102
- position: absolute;
1103
- transition: all 1s ease;
1104
- }
1105
- .background-colour.open {
1106
- left: 322px;
1107
- }
1108
- .background-colour.close {
1109
- left: 24px;
1110
- }
1111
-
1112
- ::v-deep .background-popper {
1113
- padding: 5px 12px;
1114
- background-color: #ffffff;
1115
- border: 1px solid $app-primary-color;
1116
- box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
1117
- height: 200px;
1118
- width: 175px;
1119
- min-width: 175px;
1120
- &.el-popper[x-placement^="top"] {
1121
- .popper__arrow {
1122
- border-top-color: $app-primary-color !important;
1123
- &::after {
1124
- border-top-color: #fff !important;
1125
- }
1126
- }
1127
- }
1128
- }
1129
-
1130
- .backgroundText {
1131
- color: rgb(48, 49, 51);
1132
- font-size: 14px;
1133
- font-weight: normal;
1134
- line-height: 20px;
1135
- }
1136
-
1137
- .backgroundControl {
1138
- display: flex;
1139
- margin-top: 16px;
1140
- }
1141
-
1142
- .backgroundChoice {
1143
- width: 20px;
1144
- height: 20px;
1145
- border: 1px solid rgb(144, 147, 153);
1146
- margin-left: 20px;
1147
- &.active {
1148
- border: 2px solid $app-primary-color;
1149
- }
1150
- &:hover {
1151
- cursor: pointer;
1152
- }
1153
- &.white {
1154
- background-color: white;
1155
- margin-left: 10px;
1156
- }
1157
- &.black {
1158
- background-color: black;
1159
- }
1160
- &.lightskyblue {
1161
- background-color: white;
1162
- }
1163
- }
1164
-
1165
- .togglePaths {
1166
- top: 201px;
1167
- right: 20px;
1168
- position: absolute;
1169
- }
1170
-
1171
- .icon-button {
1172
- height: 24px !important;
1173
- width: 24px !important;
1174
- color: $app-primary-color;
1175
- &:hover {
1176
- cursor: pointer;
1177
- }
1178
- }
1179
-
1180
- ::v-deep .flatmap-popper {
1181
- padding: 6px 4px;
1182
- font-size: 12px;
1183
- color: rgb(48, 49, 51);
1184
- background-color: #f3ecf6;
1185
- border: 1px solid $app-primary-color;
1186
- white-space: nowrap;
1187
- min-width: unset;
1188
- &.warning-popper {
1189
- min-width: 150px;
1190
- max-width: 400px;
1191
- word-break: keep-all;
1192
- white-space: unset;
1193
- }
1194
- &.left-popper {
1195
- .popper__arrow {
1196
- border-left-color: $app-primary-color !important;
1197
- &::after {
1198
- border-left-color: #f3ecf6 !important;
1199
- }
1200
- }
1201
- }
1202
- &.right-popper {
1203
- .popper__arrow {
1204
- border-right-color: $app-primary-color !important;
1205
- &:after {
1206
- border-right-color: #f3ecf6 !important;
1207
- }
1208
- }
1209
- }
1210
- &.el-popper[x-placement^="top"] {
1211
- .popper__arrow {
1212
- border-top-color: $app-primary-color !important;
1213
- &:after {
1214
- border-top-color: #f3ecf6 !important;
1215
- }
1216
- }
1217
- }
1218
- }
1219
-
1220
- ::v-deep .el-loading-spinner {
1221
- i,
1222
- .el-loading-text {
1223
- color: $app-primary-color;
1224
- }
1225
- }
1226
-
1227
- ::v-deep .flatmap-popup-popper {
1228
- .mapboxgl-popup-tip {
1229
- border-bottom-color: $app-primary-color;
1230
- }
1231
- .mapboxgl-popup-content {
1232
- padding: 6px 4px;
1233
- font-size: 12px;
1234
- color: rgb(48, 49, 51);
1235
- background-color: #f3ecf6;
1236
- border: 1px solid $app-primary-color;
1237
- white-space: nowrap;
1238
- min-width: unset;
1239
- .mapboxgl-popup-close-button {
1240
- display: none;
1241
- }
1242
- }
1243
- }
1244
-
1245
- ::v-deep .flatmap-popper {
1246
-
1247
- }
1248
-
1249
- ::v-deep .popper-zoomout {
1250
- padding-right: 13px !important;
1251
- left: -21px !important;
1252
- }
1253
-
1254
- ::v-deep .popper-zoomout {
1255
- .popper__arrow {
1256
- left: 53px !important;
1257
- }
1258
- }
1259
-
1260
- ::v-deep .mapboxgl-popup-content {
1261
- padding: 0px;
1262
- }
1263
-
1264
- .bottom-right-control {
1265
- position: absolute;
1266
- right: 16px;
1267
- bottom: 16px;
1268
- }
1269
-
1270
- ::v-deep .my-drawer {
1271
- background: rgba(0, 0, 0, 0);
1272
- box-shadow: none;
1273
- }
1274
-
1275
- .drawer {
1276
- ::v-deep .el-drawer:focus {
1277
- outline: none;
1278
- }
1279
- }
1280
-
1281
- .open-drawer,
1282
- .drawer-button {
1283
- z-index: 8;
1284
- width: 20px;
1285
- height: 40px;
1286
- border: solid 1px #e4e7ed;
1287
- text-align: center;
1288
- vertical-align: middle;
1289
- cursor: pointer;
1290
- pointer-events: auto;
1291
- }
1292
-
1293
- .open-drawer {
1294
- position: absolute;
1295
- left: 0px;
1296
- background-color: #f7faff;
1297
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
1298
- }
1299
-
1300
- .drawer-button {
1301
- float: left;
1302
- margin-top: calc(50% - 36px);
1303
- border-left: 0;
1304
- background-color: #ffffff;
1305
- i {
1306
- margin-top: 12px;
1307
- color: $app-primary-color;
1308
- transition-delay: 0.9s;
1309
- }
1310
- &.open {
1311
- i {
1312
- transform: rotate(0deg) scaleY(2.5);
1313
- }
1314
- }
1315
- &.close {
1316
- i {
1317
- transform: rotate(180deg) scaleY(2.5);
1318
- }
1319
- }
1320
- }
1321
-
1322
- ::v-deep .mapboxgl-canvas-container {
1323
- canvas {
1324
- outline: none;
1325
- }
1326
- }
1327
-
1328
- .backgroundSpacer {
1329
- border-bottom: 1px solid #e4e7ed;
1330
- margin-bottom: 10px;
1331
- }
1332
-
1333
- .flatmap-radio {
1334
- ::v-deep label {
1335
- margin-right: 20px;
1336
- &:last-child {
1337
- margin-right: 0px;
1338
- }
1339
- }
1340
- .el-radio__input {
1341
- &.is-checked {
1342
- & + .el-radio__label {
1343
- color: $app-primary-color;
1344
- }
1345
- .el-radio__inner {
1346
- border-color: $app-primary-color;
1347
- background: $app-primary-color;
1348
- }
1349
- }
1350
- }
1351
- }
1352
- </style>
1353
-
1
+ <template>
2
+ <div
3
+ class="flatmap-container"
4
+ v-loading="loading"
5
+ element-loading-text="Loading..."
6
+ element-loading-spinner="el-icon-loading"
7
+ element-loading-background="rgba(0, 0, 0, 0.3)"
8
+ >
9
+ <map-svg-sprite-color />
10
+ <div style="height:100%;width:100%;position:relative;overflow-y:none">
11
+ <div style="height:100%;width:100%;" ref="display"></div>
12
+ <div class="beta-popovers">
13
+ <div>
14
+ <el-popover
15
+ :content="warningMessage"
16
+ placement="right"
17
+ :appendToBody="false"
18
+ trigger="manual"
19
+ popper-class="warning-popper flatmap-popper right-popper"
20
+ v-model="hoverVisibilities[6].value"
21
+ ref="warningPopover"
22
+ ></el-popover>
23
+ <i
24
+ class="el-icon-warning warning-icon"
25
+ v-if="displayWarning && warningMessage"
26
+ @mouseover="showToolitip(6)"
27
+ @mouseout="hideToolitip(6)"
28
+ v-popover:warningPopover
29
+ >
30
+ <span class="warning-text">Beta</span>
31
+ </i>
32
+ </div>
33
+ <el-popover
34
+ :content="latestChangesMessage"
35
+ placement="right"
36
+ v-if="displayLatestChanges"
37
+ :appendToBody="false"
38
+ trigger="manual"
39
+ popper-class="warning-popper flatmap-popper right-popper"
40
+ v-model="hoverVisibilities[7].value"
41
+ ref="latestChangesPopover"
42
+ ></el-popover>
43
+ <i
44
+ class="el-icon-warning latest-changesicon"
45
+ v-if="displayLatestChanges && latestChangesMessage"
46
+ @mouseover="showToolitip(7)"
47
+ @mouseout="hideToolitip(7)"
48
+ v-popover:latestChangesPopover
49
+ >
50
+ <span class="warning-text">What's new?</span>
51
+ </i>
52
+ </div>
53
+
54
+ <div class="bottom-right-control">
55
+ <el-popover
56
+ content="Zoom in"
57
+ placement="left"
58
+ :appendToBody="false"
59
+ trigger="manual"
60
+ popper-class="flatmap-popper left-popper"
61
+ v-model="hoverVisibilities[0].value"
62
+ >
63
+ <map-svg-icon
64
+ icon="zoomIn"
65
+ class="icon-button zoomIn"
66
+ slot="reference"
67
+ @click.native="zoomIn()"
68
+ @mouseover.native="showToolitip(0)"
69
+ @mouseout.native="hideToolitip(0)"
70
+ />
71
+ </el-popover>
72
+ <el-popover
73
+ content="Zoom out"
74
+ placement="top-end"
75
+ :appendToBody="false"
76
+ trigger="manual"
77
+ popper-class="flatmap-popper popper-zoomout"
78
+ v-model="hoverVisibilities[1].value"
79
+ >
80
+ <map-svg-icon
81
+ icon="zoomOut"
82
+ class="icon-button zoomOut"
83
+ slot="reference"
84
+ @click.native="zoomOut()"
85
+ @mouseover.native="showToolitip(1)"
86
+ @mouseout.native="hideToolitip(1)"
87
+ />
88
+ </el-popover>
89
+ <el-popover
90
+ content="Reset"
91
+ placement="top"
92
+ :appendToBody="false"
93
+ trigger="manual"
94
+ popper-class="flatmap-popper"
95
+ v-model="hoverVisibilities[2].value"
96
+ >
97
+ <div>
98
+ Fit to
99
+ <br>
100
+ window
101
+ </div>
102
+ <map-svg-icon
103
+ slot="reference"
104
+ icon="fitWindow"
105
+ class="icon-button fitWindow"
106
+ @click.native="resetView()"
107
+ @mouseover.native="showToolitip(2)"
108
+ @mouseout.native="hideToolitip(2)"
109
+ />
110
+ </el-popover>
111
+ </div>
112
+ <el-popover
113
+ content="Change pathway visibility"
114
+ placement="right"
115
+ :appendToBody="false"
116
+ trigger="manual"
117
+ popper-class="flatmap-popper right-popper"
118
+ v-model="hoverVisibilities[4].value"
119
+ ref="checkBoxPopover"
120
+ />
121
+ <div class="pathway-location" :class="{ open: drawerOpen, close: !drawerOpen }">
122
+ <div
123
+ class="pathway-container"
124
+ v-if="pathways.length > 0 && pathControls"
125
+ v-popover:checkBoxPopover
126
+ >
127
+ <el-popover
128
+ content="Find these markers for data"
129
+ placement="right"
130
+ :appendToBody="false"
131
+ trigger="manual"
132
+ popper-class="flatmap-popper popper-bump-right right-popper"
133
+ v-model="hoverVisibilities[5].value"
134
+ ref="markerPopover"
135
+ ></el-popover>
136
+ <div
137
+ v-show="hoverVisibilities[5].value"
138
+ class="flatmap-marker-help"
139
+ v-html="flatmapMarker"
140
+ v-popover:markerPopover
141
+ ></div>
142
+ <el-row>
143
+ <el-col :span="12">
144
+ <div class="pathways-display-text">Pathways</div>
145
+ </el-col>
146
+ <el-col :span="12">
147
+ <el-checkbox
148
+ class="all-checkbox"
149
+ :indeterminate="isIndeterminate"
150
+ v-model="checkAll"
151
+ @change="handleCheckAllChange"
152
+ >Display all</el-checkbox>
153
+ </el-col>
154
+ </el-row>
155
+ <el-checkbox-group
156
+ v-model="checkedItems"
157
+ size="small"
158
+ class="checkbox-group"
159
+ @change="handleCheckedItemsChange"
160
+ >
161
+ <div class="checkbox-group-inner">
162
+ <el-row v-for="item in pathways" :key="item.type" :label="item.type">
163
+ <div class="checkbox-container">
164
+ <el-checkbox
165
+ class="my-checkbox"
166
+ :label="item.type"
167
+ @change="visibilityToggle()"
168
+ :checked="true"
169
+ >
170
+ <div class="path-visual" :class="item.type"></div>
171
+ {{item.label}}
172
+ </el-checkbox>
173
+ </div>
174
+ </el-row>
175
+ </div>
176
+ </el-checkbox-group>
177
+ </div>
178
+ <div
179
+ @click="toggleDrawer"
180
+ class="drawer-button"
181
+ :class="{ open: drawerOpen, close: !drawerOpen }"
182
+ >
183
+ <i class="el-icon-arrow-left"></i>
184
+ </div>
185
+ </div>
186
+ <el-popover
187
+ ref="backgroundPopover"
188
+ placement="top-start"
189
+ width="175"
190
+ :appendToBody="false"
191
+ trigger="click"
192
+ popper-class="background-popper"
193
+ >
194
+ <el-row class="backgroundText">Organs display</el-row>
195
+ <el-row class="backgroundControl">
196
+ <el-radio-group v-model="colourRadio" class="flatmap-radio" @change="setColour">
197
+ <el-radio :label="true">Colour</el-radio>
198
+ <el-radio :label="false">Greyscale</el-radio>
199
+ </el-radio-group>
200
+ </el-row>
201
+ <el-row class="backgroundSpacer"></el-row>
202
+ <el-row class="backgroundText">Outlines display</el-row>
203
+ <el-row class="backgroundControl">
204
+ <el-radio-group v-model="outlinesRadio" class="flatmap-radio" @change="setOutlines">
205
+ <el-radio :label="true">Show</el-radio>
206
+ <el-radio :label="false">Hide</el-radio>
207
+ </el-radio-group>
208
+ </el-row>
209
+ <el-row class="backgroundSpacer"></el-row>
210
+ <el-row class="backgroundText">Change background</el-row>
211
+ <el-row class="backgroundControl">
212
+ <div
213
+ v-for="item in availableBackground"
214
+ :key="item"
215
+ :class="['backgroundChoice', item, item == currentBackground ? 'active' :'']"
216
+ @click="backgroundChangeCallback(item)"
217
+ />
218
+ </el-row>
219
+ </el-popover>
220
+ <el-popover
221
+ content="Change background color"
222
+ placement="right"
223
+ v-model="hoverVisibilities[3].value"
224
+ :appendToBody="false"
225
+ trigger="manual"
226
+ popper-class="flatmap-popper right-popper"
227
+ >
228
+ <map-svg-icon
229
+ v-popover:backgroundPopover
230
+ icon="changeBckgd"
231
+ class="icon-button background-colour"
232
+ :class="{ open: drawerOpen, close: !drawerOpen }"
233
+ slot="reference"
234
+ @mouseover.native="showToolitip(3)"
235
+ @mouseout.native="hideToolitip(3)"
236
+ />
237
+ </el-popover>
238
+ <Tooltip
239
+ ref="tooltip"
240
+ class="tooltip"
241
+ :content="tooltipContent"
242
+ @resource-selected="resourceSelected"
243
+ />
244
+ </div>
245
+ </div>
246
+ </template>
247
+
248
+ <script>
249
+ /* eslint-disable no-alert, no-console */
250
+ import Vue from "vue";
251
+ import Tooltip from "./Tooltip";
252
+ import { MapSvgIcon, MapSvgSpriteColor } from "@abi-software/svg-sprite";
253
+ import {
254
+ Checkbox,
255
+ CheckboxGroup,
256
+ Col,
257
+ Loading,
258
+ Radio,
259
+ RadioGroup,
260
+ Row
261
+ } from "element-ui";
262
+ import lang from "element-ui/lib/locale/lang/en";
263
+ import locale from "element-ui/lib/locale";
264
+ import flatmapMarker from "../icons/flatmap-marker";
265
+
266
+ locale.use(lang);
267
+ Vue.use(Checkbox);
268
+ Vue.use(CheckboxGroup);
269
+ Vue.use(Col);
270
+ Vue.use(Loading.directive);
271
+ Vue.use(Radio);
272
+ Vue.use(RadioGroup);
273
+ Vue.use(Row);
274
+ const ResizeSensor = require("css-element-queries/src/ResizeSensor");
275
+
276
+ const mapResize = map => {
277
+ return () => {
278
+ if (map) map.resize();
279
+ };
280
+ };
281
+
282
+ export default {
283
+ name: "FlatmapVuer",
284
+ components: {
285
+ MapSvgIcon,
286
+ MapSvgSpriteColor,
287
+ Tooltip
288
+ },
289
+ beforeCreate: function() {
290
+ this.mapManager = undefined;
291
+ this.mapImp = undefined;
292
+ },
293
+ methods: {
294
+ backgroundChangeCallback: function(colour) {
295
+ this.currentBackground = colour;
296
+ if (this.mapImp) {
297
+ this.mapImp.setBackgroundColour(this.currentBackground, 1);
298
+ }
299
+ },
300
+ toggleDrawer: function() {
301
+ this.drawerOpen = !this.drawerOpen;
302
+ },
303
+ /**
304
+ * Function to toggle colour/greyscale of organs.
305
+ */
306
+ setColour: function(flag) {
307
+ this.colourRadio = flag;
308
+ if (this.mapImp) {
309
+ this.mapImp.setColour({ colour: flag, outline: this.outlinesRadio });
310
+ }
311
+ },
312
+ /**
313
+ * Function to toggle outlines f organs.
314
+ */
315
+ setOutlines: function(flag) {
316
+ this.outlineRadio = flag;
317
+ if (this.mapImp) {
318
+ this.mapImp.setColour({ colour: this.colourRadio, outline: flag });
319
+ }
320
+ },
321
+ /**
322
+ * Function to toggle paths to default.
323
+ * Also called when the associated button is pressed.
324
+ */
325
+ resetView: function() {
326
+ if (this.mapImp) {
327
+ this.mapImp.resetMap();
328
+ this.checkedItems = this.mapImp.pathTypes().map(item => item.type);
329
+ this.isIndeterminate = false;
330
+ this.checkAll = true;
331
+ }
332
+ },
333
+ /**
334
+ * Function to zoom in.
335
+ * Also called when the associated button is pressed.
336
+ */
337
+ zoomIn: function() {
338
+ if (this.mapImp) {
339
+ this.mapImp.zoomIn();
340
+ }
341
+ },
342
+ /**
343
+ * Function to zoom out.
344
+ * Also called when the associated button is pressed.
345
+ */
346
+ zoomOut: function() {
347
+ if (this.mapImp) {
348
+ this.mapImp.zoomOut();
349
+ }
350
+ },
351
+ visibilityToggle: function() {
352
+ if (this.mapImp) {
353
+ this.mapImp.showPaths(this.checkedItems);
354
+ }
355
+ },
356
+ handleCheckedItemsChange: function(value) {
357
+ let checkedCount = value.length;
358
+ this.checkAll = checkedCount === this.pathways.length;
359
+ this.isIndeterminate =
360
+ checkedCount > 0 && checkedCount < this.pathways.length;
361
+ },
362
+ handleCheckAllChange(val) {
363
+ this.checkedItems = val ? this.pathways.map(a => a.type) : [];
364
+ this.isIndeterminate = false;
365
+ if (this.mapImp) {
366
+ this.mapImp.showPaths(this.checkedItems);
367
+ }
368
+ },
369
+ enablePanZoomEvents: function(flag) {
370
+ this.mapImp.enablePanZoomEvents(flag);
371
+ },
372
+ eventCallback: function() {
373
+ return (eventType, data, ...args) => {
374
+ if (eventType !== "pan-zoom") {
375
+ const label = data.label;
376
+ const resource = [data.models];
377
+ const taxonomy = this.entry;
378
+ const payload = {
379
+ dataset: data.dataset,
380
+ taxonomy: taxonomy,
381
+ resource: resource,
382
+ label: label,
383
+ feature: data,
384
+ userData: args,
385
+ eventType: eventType
386
+ };
387
+ // Disable the nueron pop up for now.
388
+ if (data && data.type !== "marker")
389
+ this.checkAndCreatePopups(payload);
390
+ this.$emit("resource-selected", payload);
391
+ } else {
392
+ this.$emit("pan-zoom-callback", data);
393
+ }
394
+ };
395
+ },
396
+ // checkNeuronClicked shows a neuron path pop up if a path was recently clicked
397
+ checkAndCreatePopups: function(data) {
398
+ if (
399
+ data.eventType == "click" &&
400
+ this.hasNeuronTooltip(data)
401
+ ) {
402
+ this.createTooltipFromNeuronCuration(data);
403
+ this.mapImp.showPopup(
404
+ this.mapImp.modelFeatureIds(data.resource[0])[0],
405
+ this.$refs.tooltip.$el,
406
+ { className: "flatmapvuer-popover", positionAtLastClick: true }
407
+ );
408
+ this.popUpCssHacks();
409
+ }
410
+ },
411
+ popUpCssHacks: function() {
412
+ // Below is a hack to remove flatmap tooltips while popup is open
413
+ let ftooltip = document.querySelector(".flatmap-tooltip-popup");
414
+ if (ftooltip) ftooltip.style.display = "none";
415
+ document.querySelector(".mapboxgl-popup-close-button").style.display =
416
+ "block";
417
+ this.$refs.tooltip.$el.style.display = "flex";
418
+ document.querySelector(".mapboxgl-popup-close-button").onclick = () => {
419
+ document.querySelector(".flatmap-tooltip-popup").style.display =
420
+ "block";
421
+ };
422
+ },
423
+ resourceSelected: function(action) {
424
+ this.$emit("resource-selected", action);
425
+ },
426
+ hasNeuronTooltip: function(data) {
427
+
428
+ // neural data check
429
+ if (data.resource[0]){
430
+ if (data.resource[0].includes('ilxtr:neuron')){
431
+ return true
432
+ }
433
+ }
434
+ // annotated with datset check
435
+ if (data.dataset) {
436
+ return true
437
+ }
438
+
439
+ // if there is no cuff, neural data, or dataset we do not display neuron tooltip
440
+ return false
441
+
442
+ },
443
+ createTooltipFromNeuronCuration: function(data) {
444
+ const feature = data.resource[0];
445
+ let content = {
446
+ title: undefined,
447
+ components: undefined,
448
+ start: undefined,
449
+ distribution: undefined,
450
+ actions: []
451
+ };
452
+
453
+ this.tooltipVisible = false;
454
+
455
+ // neural data check
456
+ if (feature){
457
+ if (feature.includes('ilxtr:neuron')){
458
+ this.tooltipVisible = true;
459
+ this.tooltipContent = content;
460
+ this.tooltipContent.uberon = feature;
461
+ this.tooltipContent.title = data.label;
462
+ this.tooltipContent.featureIds = [feature];
463
+ this.tooltipContent.actions.push({
464
+ title: "Search for datasets",
465
+ label: "Neuron Datasets",
466
+ resource: feature.split(":")[1],
467
+ type: "Neuron Search",
468
+ feature: feature,
469
+ nervePath: true
470
+ });
471
+ }
472
+ }
473
+ // annotated with datset check
474
+ if (data.dataset) {
475
+ this.tooltipVisible = true;
476
+ this.tooltipContent = content;
477
+ this.tooltipContent.uberon = feature;
478
+ this.tooltipContent.title = data.label;
479
+ this.tooltipContent.actions.push({
480
+ title: "View dataset",
481
+ resource: data.dataset,
482
+ type: "URL",
483
+ feature: feature,
484
+ nervePath: false
485
+ });
486
+ }
487
+ },
488
+ // Keeping this as an API
489
+ showPopup: function(featureId, node, options) {
490
+ let myOptions = options;
491
+ if (this.mapImp) {
492
+ if (myOptions) {
493
+ if (!myOptions.className) myOptions.className = "flatmapvuer-popover";
494
+ } else {
495
+ myOptions = { className: "flatmapvuer-popover", positionAtLastClick: true };
496
+ }
497
+ this.mapImp.showPopup(featureId, node, myOptions);
498
+ }
499
+ },
500
+ showMarkerPopup: function(featureId, node, options) {
501
+ if (this.mapImp) {
502
+ this.mapImp.showMarkerPopup(featureId, node, options);
503
+ }
504
+ },
505
+ setHelpMode: function(helpMode) {
506
+ if (helpMode) {
507
+ this.inHelp = true;
508
+ this.hoverVisibilities.forEach(item => {
509
+ item.value = true;
510
+ });
511
+ this.openFlatmapHelpPopup();
512
+ } else {
513
+ this.inHelp = false;
514
+ this.hoverVisibilities.forEach(item => {
515
+ item.value = false;
516
+ });
517
+ this.closeFlatmapHelpPopup();
518
+ }
519
+ },
520
+ showToolitip: function(tooltipNumber) {
521
+ if (!this.inHelp) {
522
+ this.tooltipWait = setTimeout(() => {
523
+ this.hoverVisibilities[tooltipNumber].value = true;
524
+ }, 500);
525
+ }
526
+ },
527
+ hideToolitip: function(tooltipNumber) {
528
+ if (!this.inHelp) {
529
+ this.hoverVisibilities[tooltipNumber].value = false;
530
+ clearTimeout(this.tooltipWait);
531
+ }
532
+ },
533
+ openFlatmapHelpPopup: function() {
534
+ if (this.mapImp) {
535
+ let heartId = this.mapImp.featureIdsForModel("UBERON:0000948")[0];
536
+ const elm = "Click for more information";
537
+ this.mapImp.showPopup(heartId, elm, {
538
+ anchor: "top",
539
+ className: "flatmap-popup-popper"
540
+ });
541
+ }
542
+ },
543
+ closeFlatmapHelpPopup: function() {
544
+ this.$el
545
+ .querySelectorAll(".mapboxgl-popup-close-button")
546
+ .forEach(item => {
547
+ item.click();
548
+ });
549
+ },
550
+ getLabels: function() {
551
+ let labels = [];
552
+ if (this.mapImp) {
553
+ let annotations = this.mapImp.annotations;
554
+ for (let value of annotations.values()) {
555
+ if (value.label) labels.push(value.label);
556
+ }
557
+ return Array.from(new Set(labels));
558
+ }
559
+ },
560
+ getState: function() {
561
+ if (this.mapImp) {
562
+ let state = {
563
+ entry: this.entry,
564
+ viewport: this.mapImp.getState()
565
+ };
566
+ return state;
567
+ }
568
+ return undefined;
569
+ },
570
+ setState: function(state) {
571
+ if (state) {
572
+ if (this.mapImp && state.entry) {
573
+ if (this.entry == state.entry)
574
+ if (state.viewport) {
575
+ this.mapImp.setState(state.viewport);
576
+ }
577
+ } else {
578
+ this.createFlatmap(state);
579
+ }
580
+ }
581
+ },
582
+ createFlatmap: function(state) {
583
+ if (!this.mapImp && !this.loading) {
584
+ this.loading = true;
585
+ let minimap = false;
586
+ if (this.displayMinimap) {
587
+ minimap = { position: "top-right" };
588
+ }
589
+ let entry = this.entry;
590
+ if (state && state.entry) entry = state.entry;
591
+ let promise1 = this.mapManager.loadMap(
592
+ entry,
593
+ this.$refs.display,
594
+ this.eventCallback(),
595
+ {
596
+ //fullscreenControl: false,
597
+ //annotatable: false,
598
+ //debug: true,
599
+ featureInfo: this.featureInfo,
600
+ "min-zoom": this.minZoom,
601
+ pathControls: false,
602
+ searchable: this.searchable,
603
+ tooltips: this.tooltips,
604
+ minimap: minimap
605
+ }
606
+ );
607
+ promise1.then(returnedObject => {
608
+ this.mapImp = returnedObject;
609
+ this.sensor = new ResizeSensor(
610
+ this.$refs.display,
611
+ mapResize(this.mapImp)
612
+ );
613
+ this.mapImp.setBackgroundOpacity(1);
614
+ this.backgroundChangeCallback(this.currentBackground);
615
+ this.pathways = this.mapImp.pathTypes();
616
+ this.$emit("ready", this);
617
+ this.loading = false;
618
+ if (this._viewportToBeSet)
619
+ this.mapImp.setState(this._viewportToBeSet);
620
+ else if (state && state.viewport)
621
+ this.mapImp.setState(state.viewport);
622
+ });
623
+ } else if (state) {
624
+ if (this.entry == state.entry) this._viewportToBeSet = state.viewport;
625
+ }
626
+ },
627
+ showMinimap: function(flag) {
628
+ if (this.mapImp)
629
+ this.mapImp.showMinimap(flag);
630
+ },
631
+ showPathwaysDrawer: function(flag) {
632
+ this.drawerOpen = flag;
633
+ },
634
+ /**
635
+ * Function to display features with annotation matching the provided term.
636
+ */
637
+ searchAndShowResult: function(term) {
638
+ if (this.mapImp) {
639
+ if (term === undefined || term === "") {
640
+ this.mapImp.clearSearchResults();
641
+ return true;
642
+ } else {
643
+ let searchResults = this.mapImp.search(term);
644
+ if (searchResults && searchResults.__featureIds.length > 0) {
645
+ this.mapImp.showSearchResults(searchResults);
646
+ return true;
647
+ }
648
+ else
649
+ this.mapImp.clearSearchResults();
650
+ }
651
+ }
652
+ return false;
653
+ }
654
+ },
655
+ props: {
656
+ entry: String,
657
+ featureInfo: {
658
+ type: Boolean,
659
+ default: false
660
+ },
661
+ minZoom: {
662
+ type: Number,
663
+ default: 4
664
+ },
665
+ pathControls: {
666
+ type: Boolean,
667
+ default: true
668
+ },
669
+ searchable: {
670
+ type: Boolean,
671
+ default: false
672
+ },
673
+ tooltips: {
674
+ type: Boolean,
675
+ default: true
676
+ },
677
+ helpMode: {
678
+ type: Boolean,
679
+ default: false
680
+ },
681
+ renderAtMounted: {
682
+ type: Boolean,
683
+ default: true
684
+ },
685
+ displayMinimap: {
686
+ type: Boolean,
687
+ default: false
688
+ },
689
+ displayWarning: {
690
+ type: Boolean,
691
+ default: false
692
+ },
693
+ warningMessage: {
694
+ type: String,
695
+ default: "Beta feature - This map is based on the connectivity of a rat. New connectivity and species specificity will be added as the SPARC program progress."
696
+ },
697
+ displayLatestChanges: {
698
+ type: Boolean,
699
+ default: false,
700
+ },
701
+ latestChangesMessage: {
702
+ type: String,
703
+ default: "Bladder connectivity can now be explored and searched on when selected! To see it, click on any of the paths coming from the bladder. Other pathways will be searchable soon.",
704
+ },
705
+ /**
706
+ * State containing state of the flatmap.
707
+ */
708
+ state: {
709
+ type: Object,
710
+ default: undefined
711
+ },
712
+ /**
713
+ * Specify the endpoint of the flatmap server.
714
+ */
715
+ flatmapAPI: {
716
+ type: String,
717
+ default: "https://mapcore-demo.org/flatmaps/"
718
+ },
719
+ sparcAPI: {
720
+ type: String,
721
+ default: "https://api.sparc.science/"
722
+ },
723
+ },
724
+ provide() {
725
+ return {
726
+ sparcAPI: this.sparcAPI,
727
+ flatmapAPI: this.flatmapAPI
728
+ }
729
+ },
730
+ data: function() {
731
+ return {
732
+ checkedItems: [],
733
+ pathways: [],
734
+ isIndeterminate: false,
735
+ checkAll: true,
736
+ hoverVisibilities: [
737
+ { value: false },
738
+ { value: false },
739
+ { value: false },
740
+ { value: false },
741
+ { value: false },
742
+ { value: false },
743
+ { value: false },
744
+ { value: false }
745
+ ],
746
+ inHelp: false,
747
+ currentBackground: "white",
748
+ availableBackground: ["white", "lightskyblue", "black"],
749
+ loading: false,
750
+ flatmapMarker: flatmapMarker,
751
+ drawerOpen: true,
752
+ tooltipContent: { featureIds: []},
753
+ colourRadio: true,
754
+ outlinesRadio: true
755
+ };
756
+ },
757
+ watch: {
758
+ entry: function() {
759
+ if (!this.state) this.createFlatmap();
760
+ },
761
+ helpMode: function(val) {
762
+ this.setHelpMode(val);
763
+ },
764
+ state: {
765
+ handler: function(state) {
766
+ this.setState(state);
767
+ },
768
+ immediate: true,
769
+ deep: true
770
+ }
771
+ },
772
+ mounted: function() {
773
+ const flatmap = require("@abi-software/flatmap-viewer");
774
+ this.mapManager = new flatmap.MapManager(this.flatmapAPI);
775
+ if (this.renderAtMounted) this.createFlatmap();
776
+ }
777
+ };
778
+ </script>
779
+
780
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
781
+ <style scoped lang="scss">
782
+ @import "~element-ui/packages/theme-chalk/src/button";
783
+ @import "~element-ui/packages/theme-chalk/src/checkbox";
784
+ @import "~element-ui/packages/theme-chalk/src/checkbox-group";
785
+ @import "~element-ui/packages/theme-chalk/src/loading";
786
+ @import "~element-ui/packages/theme-chalk/src/row";
787
+
788
+ .beta-popovers{
789
+ position: absolute;
790
+ top: 90px;
791
+ left: 16px;
792
+ text-align: left;
793
+ font-size: 25px;
794
+ }
795
+
796
+ .warning-icon {
797
+ color: $warning;
798
+
799
+ &:hover {
800
+ cursor: pointer;
801
+ }
802
+ }
803
+
804
+ .warning-text {
805
+ font-family: Asap, sans-serif;
806
+ font-size: 15px;
807
+ vertical-align: 5px;
808
+ }
809
+
810
+ .latest-changesicon {
811
+ color: $success;
812
+
813
+ &:hover {
814
+ cursor: pointer;
815
+ }
816
+ }
817
+
818
+ .latest-changestext {
819
+ font-family: Asap, sans-serif;
820
+ font-size: 15px;
821
+ vertical-align: 5px;
822
+ }
823
+
824
+ .path-visual {
825
+ margin: 3px 0;
826
+ height: 3px;
827
+ width: 25px;
828
+ margin-right: 5px;
829
+ display: inline-block;
830
+ &.cns {
831
+ background: #9b1fc1;
832
+ }
833
+ &.lcn {
834
+ background: #f19e38;
835
+ }
836
+ &.para-pre {
837
+ background: #3f8f4a;
838
+ }
839
+ &.para-post {
840
+ background: repeating-linear-gradient(
841
+ 90deg,
842
+ #3f8f4a,
843
+ #3f8f4a 6px,
844
+ transparent 0,
845
+ transparent 9px
846
+ );
847
+ }
848
+ &.sensory {
849
+ background: #2a62f6;
850
+ }
851
+ &.somatic {
852
+ background: #98561d;
853
+ }
854
+ &.symp-pre {
855
+ background: #ea3423;
856
+ }
857
+ &.symp-post {
858
+ background: repeating-linear-gradient(
859
+ 90deg,
860
+ #ea3423,
861
+ #ea3423 6px,
862
+ transparent 0,
863
+ transparent 9px
864
+ );
865
+ }
866
+ }
867
+
868
+ .flatmap-container {
869
+ height: 100%;
870
+ width: 100%;
871
+ }
872
+
873
+ .pathway-location {
874
+ position: absolute;
875
+ bottom: 0px;
876
+ transition: all 1s ease;
877
+ &.open {
878
+ left: 0px;
879
+ }
880
+ &.close {
881
+ left: -298px;
882
+ }
883
+ }
884
+
885
+ .pathway-container {
886
+ float: left;
887
+ padding-left: 16px;
888
+ padding-right: 18px;
889
+ max-height: calc(100% - 184px);
890
+ text-align: left;
891
+ overflow: auto;
892
+ border: 1px solid rgb(220, 223, 230);
893
+ padding-top: 7px;
894
+ padding-bottom: 16px;
895
+ background: #ffffff;
896
+ }
897
+
898
+ .pathways-display-text {
899
+ width: 59px;
900
+ height: 20px;
901
+ color: rgb(48, 49, 51);
902
+ font-size: 14px;
903
+ font-weight: normal;
904
+ line-height: 20px;
905
+ margin-left: 8px;
906
+ }
907
+
908
+ .all-checkbox {
909
+ float: right;
910
+ }
911
+
912
+ .checkbox-container {
913
+ display: flex;
914
+ cursor: pointer;
915
+ }
916
+
917
+ .checkbox-group {
918
+ width: 260px;
919
+ border: 1px solid rgb(144, 147, 153);
920
+ border-radius: 4px;
921
+ background: #ffffff;
922
+ }
923
+
924
+ .my-checkbox {
925
+ background-color: #fff;
926
+ width: 100%;
927
+ }
928
+
929
+ .checkbox-group-inner {
930
+ padding: 18px;
931
+ }
932
+
933
+ .flatmap-marker-help {
934
+ display: inline-block;
935
+ }
936
+
937
+ ::v-deep .popper-bump-right {
938
+ left: 30px;
939
+ }
940
+
941
+ ::v-deep .el-checkbox__label {
942
+ padding-left: 5px;
943
+ color: $app-primary-color;
944
+ font-size: 12px;
945
+ font-weight: 500;
946
+ letter-spacing: 0px;
947
+ line-height: 14px;
948
+ }
949
+
950
+ ::v-deep .el-checkbox__input {
951
+ &.is-indeterminate,
952
+ &.is-checked {
953
+ .el-checkbox__inner {
954
+ background-color: $app-primary-color;
955
+ border-color: $app-primary-color;
956
+ }
957
+ }
958
+ }
959
+
960
+ ::v-deep .el-checkbox__label {
961
+ color: $app-primary-color !important;
962
+ }
963
+
964
+ .el-dropdown-link {
965
+ cursor: pointer;
966
+ color: #409eff;
967
+ }
968
+ .el-icon-arrow-down {
969
+ font-size: 12px;
970
+ }
971
+ .demonstration {
972
+ display: block;
973
+ color: #8492a6;
974
+ font-size: 14px;
975
+ margin-bottom: 20px;
976
+ }
977
+
978
+ .tooltip {
979
+ display: none;
980
+ }
981
+
982
+ ::v-deep .mapboxgl-popup {
983
+ max-width: 300px !important;
984
+ }
985
+
986
+ ::v-deep .flatmap-tooltip-popup {
987
+ &.mapboxgl-popup-anchor-bottom {
988
+ .mapboxgl-popup-content {
989
+ margin-bottom: 12px;
990
+ &::after,
991
+ &::before {
992
+ top: 100%;
993
+ border-width: 12px;
994
+ }
995
+ /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
996
+ &::after {
997
+ margin-top: -1px;
998
+ border-color: rgb(255, 255, 255) transparent transparent transparent;
999
+ }
1000
+ /* this border color controlls the outside, thin border */
1001
+ &::before {
1002
+ margin: 0 auto;
1003
+ border-color: $app-primary-color transparent transparent transparent;
1004
+ }
1005
+ }
1006
+ }
1007
+ &.mapboxgl-popup-anchor-top {
1008
+ .mapboxgl-popup-content {
1009
+ margin-top: 18px;
1010
+ &::after,
1011
+ &::before {
1012
+ top: calc(-100% + 6px);
1013
+ border-width: 12px;
1014
+ }
1015
+ /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1016
+ &::after {
1017
+ margin-top: 1px;
1018
+ border-color: transparent transparent rgb(255, 255, 255) transparent;
1019
+ }
1020
+ &::before {
1021
+ margin: 0 auto;
1022
+ border-color: transparent transparent $app-primary-color transparent;
1023
+ }
1024
+ }
1025
+ }
1026
+ .mapboxgl-popup-content {
1027
+ border-radius: 4px;
1028
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
1029
+ pointer-events: none;
1030
+ display: none;
1031
+ background: #fff;
1032
+ border: 1px solid $app-primary-color;
1033
+ padding-left: 6px;
1034
+ padding-right: 6px;
1035
+ display: flex;
1036
+ justify-content: center;
1037
+ align-items: center;
1038
+ &::after,
1039
+ &::before {
1040
+ content: "";
1041
+ display: block;
1042
+ position: absolute;
1043
+ width: 0;
1044
+ height: 0;
1045
+ border-style: solid;
1046
+ flex-shrink: 0;
1047
+ }
1048
+ }
1049
+ .mapboxgl-popup-tip {
1050
+ display: none;
1051
+ }
1052
+ }
1053
+
1054
+ ::v-deep .mapboxgl-popup {
1055
+ &.flatmap-marker-popup {
1056
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
1057
+ pointer-events: auto;
1058
+ background: #fff;
1059
+ }
1060
+ }
1061
+
1062
+ /* Fix for chrome bug where under triangle pops up above one on top of it */
1063
+ .selector:not(*:root),
1064
+ ::v-deep.flatmap-tooltip-popup {
1065
+ .mapboxgl-popup-content::after {
1066
+ top: 99.9%;
1067
+ }
1068
+ }
1069
+
1070
+ ::v-deep .flatmap-tooltip-dialog {
1071
+ .mapboxgl-popup-tip {
1072
+ display: none;
1073
+ }
1074
+ }
1075
+
1076
+ ::v-deep .flatmap-marker-popup {
1077
+ .mapboxgl-popup-content {
1078
+ padding: 0px;
1079
+ }
1080
+ }
1081
+
1082
+ ::v-deep .flatmapvuer-popover {
1083
+ .mapboxgl-popup-close-button {
1084
+ position: absolute;
1085
+ right: 0.5em;
1086
+ top: 0;
1087
+ border: 0;
1088
+ border-radius: 0 3px 0 0;
1089
+ cursor: pointer;
1090
+ background-color: transparent;
1091
+ font-size: 2.5em;
1092
+ color: grey;
1093
+ top: 0.95em;
1094
+ }
1095
+ }
1096
+
1097
+ .zoomOut {
1098
+ padding-left: 8px;
1099
+ }
1100
+
1101
+ .fitWindow {
1102
+ padding-left: 8px;
1103
+ }
1104
+
1105
+ .background-colour {
1106
+ bottom: 16px;
1107
+ position: absolute;
1108
+ transition: all 1s ease;
1109
+ }
1110
+ .background-colour.open {
1111
+ left: 322px;
1112
+ }
1113
+ .background-colour.close {
1114
+ left: 24px;
1115
+ }
1116
+
1117
+ ::v-deep .background-popper {
1118
+ padding: 5px 12px;
1119
+ background-color: #ffffff;
1120
+ border: 1px solid $app-primary-color;
1121
+ box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
1122
+ height: 200px;
1123
+ width: 175px;
1124
+ min-width: 175px;
1125
+ &.el-popper[x-placement^="top"] {
1126
+ .popper__arrow {
1127
+ border-top-color: $app-primary-color !important;
1128
+ &::after {
1129
+ border-top-color: #fff !important;
1130
+ }
1131
+ }
1132
+ }
1133
+ }
1134
+
1135
+ .backgroundText {
1136
+ color: rgb(48, 49, 51);
1137
+ font-size: 14px;
1138
+ font-weight: normal;
1139
+ line-height: 20px;
1140
+ }
1141
+
1142
+ .backgroundControl {
1143
+ display: flex;
1144
+ margin-top: 16px;
1145
+ }
1146
+
1147
+ .backgroundChoice {
1148
+ width: 20px;
1149
+ height: 20px;
1150
+ border: 1px solid rgb(144, 147, 153);
1151
+ margin-left: 20px;
1152
+ &.active {
1153
+ border: 2px solid $app-primary-color;
1154
+ }
1155
+ &:hover {
1156
+ cursor: pointer;
1157
+ }
1158
+ &.white {
1159
+ background-color: white;
1160
+ margin-left: 10px;
1161
+ }
1162
+ &.black {
1163
+ background-color: black;
1164
+ }
1165
+ &.lightskyblue {
1166
+ background-color: white;
1167
+ }
1168
+ }
1169
+
1170
+ .togglePaths {
1171
+ top: 201px;
1172
+ right: 20px;
1173
+ position: absolute;
1174
+ }
1175
+
1176
+ .icon-button {
1177
+ height: 24px !important;
1178
+ width: 24px !important;
1179
+ color: $app-primary-color;
1180
+ &:hover {
1181
+ cursor: pointer;
1182
+ }
1183
+ }
1184
+
1185
+ ::v-deep .flatmap-popper {
1186
+ padding: 6px 4px;
1187
+ font-size: 12px;
1188
+ color: rgb(48, 49, 51);
1189
+ background-color: #f3ecf6;
1190
+ border: 1px solid $app-primary-color;
1191
+ white-space: nowrap;
1192
+ min-width: unset;
1193
+ &.warning-popper {
1194
+ min-width: 150px;
1195
+ max-width: 400px;
1196
+ word-break: keep-all;
1197
+ white-space: unset;
1198
+ }
1199
+ &.left-popper {
1200
+ .popper__arrow {
1201
+ border-left-color: $app-primary-color !important;
1202
+ &::after {
1203
+ border-left-color: #f3ecf6 !important;
1204
+ }
1205
+ }
1206
+ }
1207
+ &.right-popper {
1208
+ .popper__arrow {
1209
+ border-right-color: $app-primary-color !important;
1210
+ &:after {
1211
+ border-right-color: #f3ecf6 !important;
1212
+ }
1213
+ }
1214
+ }
1215
+ &.el-popper[x-placement^="top"] {
1216
+ .popper__arrow {
1217
+ border-top-color: $app-primary-color !important;
1218
+ &:after {
1219
+ border-top-color: #f3ecf6 !important;
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+
1225
+ ::v-deep .el-loading-spinner {
1226
+ i,
1227
+ .el-loading-text {
1228
+ color: $app-primary-color;
1229
+ }
1230
+ }
1231
+
1232
+ ::v-deep .flatmap-popup-popper {
1233
+ .mapboxgl-popup-tip {
1234
+ border-bottom-color: $app-primary-color;
1235
+ }
1236
+ .mapboxgl-popup-content {
1237
+ padding: 6px 4px;
1238
+ font-size: 12px;
1239
+ color: rgb(48, 49, 51);
1240
+ background-color: #f3ecf6;
1241
+ border: 1px solid $app-primary-color;
1242
+ white-space: nowrap;
1243
+ min-width: unset;
1244
+ .mapboxgl-popup-close-button {
1245
+ display: none;
1246
+ }
1247
+ }
1248
+ }
1249
+
1250
+ ::v-deep .flatmap-popper {
1251
+
1252
+ }
1253
+
1254
+ ::v-deep .popper-zoomout {
1255
+ padding-right: 13px !important;
1256
+ left: -21px !important;
1257
+ }
1258
+
1259
+ ::v-deep .popper-zoomout {
1260
+ .popper__arrow {
1261
+ left: 53px !important;
1262
+ }
1263
+ }
1264
+
1265
+ ::v-deep .mapboxgl-popup-content {
1266
+ padding: 0px;
1267
+ }
1268
+
1269
+ .bottom-right-control {
1270
+ position: absolute;
1271
+ right: 16px;
1272
+ bottom: 16px;
1273
+ }
1274
+
1275
+ ::v-deep .my-drawer {
1276
+ background: rgba(0, 0, 0, 0);
1277
+ box-shadow: none;
1278
+ }
1279
+
1280
+ .drawer {
1281
+ ::v-deep .el-drawer:focus {
1282
+ outline: none;
1283
+ }
1284
+ }
1285
+
1286
+ .open-drawer,
1287
+ .drawer-button {
1288
+ z-index: 8;
1289
+ width: 20px;
1290
+ height: 40px;
1291
+ border: solid 1px #e4e7ed;
1292
+ text-align: center;
1293
+ vertical-align: middle;
1294
+ cursor: pointer;
1295
+ pointer-events: auto;
1296
+ }
1297
+
1298
+ .open-drawer {
1299
+ position: absolute;
1300
+ left: 0px;
1301
+ background-color: #f7faff;
1302
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
1303
+ }
1304
+
1305
+ .drawer-button {
1306
+ float: left;
1307
+ margin-top: calc(50% - 36px);
1308
+ border-left: 0;
1309
+ background-color: #ffffff;
1310
+ i {
1311
+ margin-top: 12px;
1312
+ color: $app-primary-color;
1313
+ transition-delay: 0.9s;
1314
+ }
1315
+ &.open {
1316
+ i {
1317
+ transform: rotate(0deg) scaleY(2.5);
1318
+ }
1319
+ }
1320
+ &.close {
1321
+ i {
1322
+ transform: rotate(180deg) scaleY(2.5);
1323
+ }
1324
+ }
1325
+ }
1326
+
1327
+ ::v-deep .mapboxgl-canvas-container {
1328
+ canvas {
1329
+ outline: none;
1330
+ }
1331
+ }
1332
+
1333
+ .backgroundSpacer {
1334
+ border-bottom: 1px solid #e4e7ed;
1335
+ margin-bottom: 10px;
1336
+ }
1337
+
1338
+ .flatmap-radio {
1339
+ ::v-deep label {
1340
+ margin-right: 20px;
1341
+ &:last-child {
1342
+ margin-right: 0px;
1343
+ }
1344
+ }
1345
+ .el-radio__input {
1346
+ &.is-checked {
1347
+ & + .el-radio__label {
1348
+ color: $app-primary-color;
1349
+ }
1350
+ .el-radio__inner {
1351
+ border-color: $app-primary-color;
1352
+ background: $app-primary-color;
1353
+ }
1354
+ }
1355
+ }
1356
+ }
1357
+ </style>
1358
+