@abi-software/flatmapvuer 0.3.0 → 0.3.1

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