@abi-software/flatmapvuer 0.3.8 → 0.3.10-beta

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,1388 +1,1442 @@
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
- <svg-legends class= "svg-legends-container"/>
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 SvgLegends from "./legends/Legends";
255
- import {
256
- Checkbox,
257
- CheckboxGroup,
258
- Col,
259
- Loading,
260
- Radio,
261
- RadioGroup,
262
- Row
263
- } from "element-ui";
264
- import lang from "element-ui/lib/locale/lang/en";
265
- import locale from "element-ui/lib/locale";
266
- import flatmapMarker from "../icons/flatmap-marker";
267
-
268
- locale.use(lang);
269
- Vue.use(Checkbox);
270
- Vue.use(CheckboxGroup);
271
- Vue.use(Col);
272
- Vue.use(Loading.directive);
273
- Vue.use(Radio);
274
- Vue.use(RadioGroup);
275
- Vue.use(Row);
276
- const ResizeSensor = require("css-element-queries/src/ResizeSensor");
277
-
278
- const mapResize = map => {
279
- return () => {
280
- if (map) map.resize();
281
- };
282
- };
283
-
284
- export default {
285
- name: "FlatmapVuer",
286
- components: {
287
- MapSvgIcon,
288
- MapSvgSpriteColor,
289
- Tooltip,
290
- SvgLegends
291
- },
292
- beforeCreate: function() {
293
- this.mapManager = undefined;
294
- this.mapImp = undefined;
295
- },
296
- methods: {
297
- backgroundChangeCallback: function(colour) {
298
- this.currentBackground = colour;
299
- if (this.mapImp) {
300
- this.mapImp.setBackgroundColour(this.currentBackground, 1);
301
- }
302
- },
303
- toggleDrawer: function() {
304
- this.drawerOpen = !this.drawerOpen;
305
- },
306
- /**
307
- * Function to toggle colour/greyscale of organs.
308
- */
309
- setColour: function(flag) {
310
- this.colourRadio = flag;
311
- if (this.mapImp) {
312
- this.mapImp.setColour({ colour: flag, outline: this.outlinesRadio });
313
- }
314
- },
315
- /**
316
- * Function to toggle outlines f organs.
317
- */
318
- setOutlines: function(flag) {
319
- this.outlineRadio = flag;
320
- if (this.mapImp) {
321
- this.mapImp.setColour({ colour: this.colourRadio, outline: flag });
322
- }
323
- },
324
- /**
325
- * Function to toggle paths to default.
326
- * Also called when the associated button is pressed.
327
- */
328
- resetView: function() {
329
- if (this.mapImp) {
330
- this.mapImp.resetMap();
331
- this.checkedItems = this.mapImp.pathTypes().map(item => item.type);
332
- this.isIndeterminate = false;
333
- this.checkAll = true;
334
- }
335
- },
336
- /**
337
- * Function to zoom in.
338
- * Also called when the associated button is pressed.
339
- */
340
- zoomIn: function() {
341
- if (this.mapImp) {
342
- this.mapImp.zoomIn();
343
- }
344
- },
345
- /**
346
- * Function to zoom out.
347
- * Also called when the associated button is pressed.
348
- */
349
- zoomOut: function() {
350
- if (this.mapImp) {
351
- this.mapImp.zoomOut();
352
- }
353
- },
354
- visibilityToggle: function() {
355
- if (this.mapImp) {
356
- this.mapImp.showPaths(this.checkedItems);
357
- }
358
- },
359
- handleCheckedItemsChange: function(value) {
360
- let checkedCount = value.length;
361
- this.checkAll = checkedCount === this.pathways.length;
362
- this.isIndeterminate =
363
- checkedCount > 0 && checkedCount < this.pathways.length;
364
- },
365
- handleCheckAllChange(val) {
366
- this.checkedItems = val ? this.pathways.map(a => a.type) : [];
367
- this.isIndeterminate = false;
368
- if (this.mapImp) {
369
- this.mapImp.showPaths(this.checkedItems);
370
- }
371
- },
372
- enablePanZoomEvents: function(flag) {
373
- this.mapImp.enablePanZoomEvents(flag);
374
- },
375
- eventCallback: function() {
376
- return (eventType, data, ...args) => {
377
- if (eventType !== "pan-zoom") {
378
- const label = data.label;
379
- const resource = [data.models];
380
- const taxonomy = this.entry;
381
- const flatmapId = this.flatmapId;
382
- const payload = {
383
- dataset: data.dataset,
384
- flatmapId: flatmapId,
385
- taxonomy: taxonomy,
386
- resource: resource,
387
- label: label,
388
- feature: data,
389
- userData: args,
390
- eventType: eventType
391
- };
392
- // Disable the nueron pop up for now.
393
- if (data && data.type !== "marker")
394
- this.checkAndCreatePopups(payload);
395
- this.$emit("resource-selected", payload);
396
- } else {
397
- this.$emit("pan-zoom-callback", data);
398
- }
399
- };
400
- },
401
- // checkNeuronClicked shows a neuron path pop up if a path was recently clicked
402
- checkAndCreatePopups: function(data) {
403
- if (
404
- data.eventType == "click" &&
405
- this.hasNeuronTooltip(data)
406
- ) {
407
- this.createTooltipFromNeuronCuration(data);
408
- this.mapImp.showPopup(
409
- this.mapImp.modelFeatureIds(data.resource[0])[0],
410
- this.$refs.tooltip.$el,
411
- { className: "flatmapvuer-popover", positionAtLastClick: true }
412
- );
413
- this.popUpCssHacks();
414
- }
415
- },
416
- popUpCssHacks: function() {
417
- // Below is a hack to remove flatmap tooltips while popup is open
418
- let ftooltip = document.querySelector(".flatmap-tooltip-popup");
419
- if (ftooltip) ftooltip.style.display = "none";
420
- document.querySelector(".mapboxgl-popup-close-button").style.display =
421
- "block";
422
- this.$refs.tooltip.$el.style.display = "flex";
423
- document.querySelector(".mapboxgl-popup-close-button").onclick = () => {
424
- document.querySelector(".flatmap-tooltip-popup").style.display =
425
- "block";
426
- };
427
- },
428
- resourceSelected: function(action) {
429
- this.$emit("resource-selected", action);
430
- },
431
- hasNeuronTooltip: function(data) {
432
-
433
- // neural data check
434
- if (data.resource[0]){
435
- if (data.resource[0].includes('ilxtr:neuron')){
436
- return true
437
- }
438
- }
439
- // annotated with datset check
440
- if (data.dataset) {
441
- return true
442
- }
443
-
444
- // if there is no cuff, neural data, or dataset we do not display neuron tooltip
445
- return false
446
-
447
- },
448
- createTooltipFromNeuronCuration: function(data) {
449
- const feature = data.resource[0];
450
- let content = {
451
- title: undefined,
452
- components: undefined,
453
- start: undefined,
454
- distribution: undefined,
455
- actions: []
456
- };
457
-
458
- this.tooltipVisible = false;
459
-
460
- // neural data check
461
- if (feature){
462
- if (feature.includes('ilxtr:neuron')){
463
- this.tooltipVisible = true;
464
- this.tooltipContent = content;
465
- this.tooltipContent.uberon = feature;
466
- this.tooltipContent.title = data.label;
467
- this.tooltipContent.featureIds = [feature];
468
- this.tooltipContent.actions.push({
469
- title: "Search for datasets",
470
- label: "Neuron Datasets",
471
- resource: feature.split(":")[1],
472
- type: "Neuron Search",
473
- feature: feature,
474
- nervePath: true
475
- });
476
- }
477
- }
478
- // annotated with datset check
479
- if (data.dataset) {
480
- this.tooltipVisible = true;
481
- this.tooltipContent = content;
482
- this.tooltipContent.uberon = feature;
483
- this.tooltipContent.title = data.label;
484
- this.tooltipContent.actions.push({
485
- title: "View dataset",
486
- resource: data.dataset,
487
- type: "URL",
488
- feature: feature,
489
- nervePath: false
490
- });
491
- }
492
- },
493
- // Keeping this as an API
494
- showPopup: function(featureId, node, options) {
495
- let myOptions = options;
496
- if (this.mapImp) {
497
- if (myOptions) {
498
- if (!myOptions.className) myOptions.className = "flatmapvuer-popover";
499
- } else {
500
- myOptions = { className: "flatmapvuer-popover", positionAtLastClick: true };
501
- }
502
- this.mapImp.showPopup(featureId, node, myOptions);
503
- }
504
- },
505
- showMarkerPopup: function(featureId, node, options) {
506
- if (this.mapImp) {
507
- this.mapImp.showMarkerPopup(featureId, node, options);
508
- }
509
- },
510
- setHelpMode: function(helpMode) {
511
- if (helpMode) {
512
- this.inHelp = true;
513
- this.hoverVisibilities.forEach(item => {
514
- item.value = true;
515
- });
516
- this.openFlatmapHelpPopup();
517
- } else {
518
- this.inHelp = false;
519
- this.hoverVisibilities.forEach(item => {
520
- item.value = false;
521
- });
522
- this.closeFlatmapHelpPopup();
523
- }
524
- },
525
- showToolitip: function(tooltipNumber) {
526
- if (!this.inHelp) {
527
- this.tooltipWait = setTimeout(() => {
528
- this.hoverVisibilities[tooltipNumber].value = true;
529
- }, 500);
530
- }
531
- },
532
- hideToolitip: function(tooltipNumber) {
533
- if (!this.inHelp) {
534
- this.hoverVisibilities[tooltipNumber].value = false;
535
- clearTimeout(this.tooltipWait);
536
- }
537
- },
538
- openFlatmapHelpPopup: function() {
539
- if (this.mapImp) {
540
- let heartId = this.mapImp.featureIdsForModel("UBERON:0000948")[0];
541
- const elm = "Click for more information";
542
- this.mapImp.showPopup(heartId, elm, {
543
- anchor: "top",
544
- className: "flatmap-popup-popper"
545
- });
546
- }
547
- },
548
- closeFlatmapHelpPopup: function() {
549
- this.$el
550
- .querySelectorAll(".mapboxgl-popup-close-button")
551
- .forEach(item => {
552
- item.click();
553
- });
554
- },
555
- getLabels: function() {
556
- let labels = [];
557
- if (this.mapImp) {
558
- let annotations = this.mapImp.annotations;
559
- for (let value of annotations.values()) {
560
- if (value.label) labels.push(value.label);
561
- }
562
- return Array.from(new Set(labels));
563
- }
564
- },
565
- getState: function() {
566
- if (this.mapImp) {
567
- let state = {
568
- entry: this.entry,
569
- flatmapId: this.flatmapId,
570
- viewport: this.mapImp.getState()
571
- };
572
- return state;
573
- }
574
- return undefined;
575
- },
576
- setState: function(state) {
577
- if (state) {
578
- if (this.mapImp && (state.entry || state.flatmapId)) {
579
- if ((this.flatmapId && (this.flatmapId == state.flatmapId)) || (this.entry == state.entry))
580
- if (state.viewport) {
581
- this.mapImp.setState(state.viewport);
582
- }
583
- } else {
584
- this.createFlatmap(state);
585
- }
586
- }
587
- },
588
- createFlatmap: function(state) {
589
- if (!this.mapImp && !this.loading) {
590
- this.loading = true;
591
- let minimap = false;
592
- if (this.displayMinimap) {
593
- minimap = { position: "top-right" };
594
- }
595
-
596
- let entry = this.flatmapId;
597
- if (state && state.flatmapId) entry = state.flatmapId;
598
- if (!entry) {
599
- entry = this.entry;
600
- if (state && state.entry) entry = state.entry;
601
- }
602
-
603
- let promise1 = this.mapManager.loadMap(
604
- entry,
605
- this.$refs.display,
606
- this.eventCallback(),
607
- {
608
- //fullscreenControl: false,
609
- //annotatable: false,
610
- //debug: true,
611
- featureInfo: this.featureInfo,
612
- "min-zoom": this.minZoom,
613
- pathControls: false,
614
- searchable: this.searchable,
615
- tooltips: this.tooltips,
616
- minimap: minimap
617
- }
618
- );
619
- promise1.then(returnedObject => {
620
- this.mapImp = returnedObject;
621
- this.sensor = new ResizeSensor(
622
- this.$refs.display,
623
- mapResize(this.mapImp)
624
- );
625
- this.mapImp.setBackgroundOpacity(1);
626
- this.backgroundChangeCallback(this.currentBackground);
627
- this.pathways = this.mapImp.pathTypes();
628
- this.$emit("ready", this);
629
- this.loading = false;
630
- if (this._viewportToBeSet)
631
- this.mapImp.setState(this._viewportToBeSet);
632
- else if (state && state.viewport)
633
- this.mapImp.setState(state.viewport);
634
- });
635
- } else if (state) {
636
- if ((this.flatmapId == state.flatmapId) || this.entry == state.entry)
637
- this._viewportToBeSet = state.viewport;
638
- }
639
- },
640
- showMinimap: function(flag) {
641
- if (this.mapImp)
642
- this.mapImp.showMinimap(flag);
643
- },
644
- showPathwaysDrawer: function(flag) {
645
- this.drawerOpen = flag;
646
- },
647
- /**
648
- * Function to display features with annotation matching the provided term.
649
- */
650
- searchAndShowResult: function(term) {
651
- if (this.mapImp) {
652
- if (term === undefined || term === "") {
653
- this.mapImp.clearSearchResults();
654
- return true;
655
- } else {
656
- let searchResults = this.mapImp.search(term);
657
- if (searchResults && searchResults.__featureIds.length > 0) {
658
- this.mapImp.showSearchResults(searchResults);
659
- return true;
660
- }
661
- else
662
- this.mapImp.clearSearchResults();
663
- }
664
- }
665
- return false;
666
- },
667
- /**
668
- * Get the list of suggested terms
669
- */
670
- searchSuggestions: function(term) {
671
- if (this.mapImp)
672
- return this.mapImp.search(term);
673
- return [];
674
- },
675
- },
676
- props: {
677
- entry: String,
678
- flatmapId: String,
679
- featureInfo: {
680
- type: Boolean,
681
- default: false
682
- },
683
- minZoom: {
684
- type: Number,
685
- default: 4
686
- },
687
- pathControls: {
688
- type: Boolean,
689
- default: true
690
- },
691
- searchable: {
692
- type: Boolean,
693
- default: false
694
- },
695
- tooltips: {
696
- type: Boolean,
697
- default: true
698
- },
699
- helpMode: {
700
- type: Boolean,
701
- default: false
702
- },
703
- renderAtMounted: {
704
- type: Boolean,
705
- default: true
706
- },
707
- displayMinimap: {
708
- type: Boolean,
709
- default: false
710
- },
711
- displayWarning: {
712
- type: Boolean,
713
- default: false
714
- },
715
- warningMessage: {
716
- type: String,
717
- 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."
718
- },
719
- displayLatestChanges: {
720
- type: Boolean,
721
- default: false,
722
- },
723
- latestChangesMessage: {
724
- type: String,
725
- default: "Search now provide suggested terms. Add new legends. New tilesets. New female map. Improve upstream downstream information",
726
- },
727
- /**
728
- * State containing state of the flatmap.
729
- */
730
- state: {
731
- type: Object,
732
- default: undefined
733
- },
734
- /**
735
- * Specify the endpoint of the flatmap server.
736
- */
737
- flatmapAPI: {
738
- type: String,
739
- default: "https://mapcore-demo.org/current/flatmap/v3/"
740
- },
741
- sparcAPI: {
742
- type: String,
743
- default: "https://api.sparc.science/"
744
- },
745
- },
746
- provide() {
747
- return {
748
- sparcAPI: this.sparcAPI,
749
- flatmapAPI: this.flatmapAPI
750
- }
751
- },
752
- data: function() {
753
- return {
754
- checkedItems: [],
755
- pathways: [],
756
- isIndeterminate: false,
757
- checkAll: true,
758
- hoverVisibilities: [
759
- { value: false },
760
- { value: false },
761
- { value: false },
762
- { value: false },
763
- { value: false },
764
- { value: false },
765
- { value: false },
766
- { value: false }
767
- ],
768
- inHelp: false,
769
- currentBackground: "white",
770
- availableBackground: ["white", "lightskyblue", "black"],
771
- loading: false,
772
- flatmapMarker: flatmapMarker,
773
- drawerOpen: true,
774
- tooltipContent: { featureIds: []},
775
- colourRadio: true,
776
- outlinesRadio: true
777
- };
778
- },
779
- watch: {
780
- entry: function() {
781
- if (!this.state) this.createFlatmap();
782
- },
783
- flatmapId: function() {
784
- if (!this.state) this.createFlatmap();
785
- },
786
- helpMode: function(val) {
787
- this.setHelpMode(val);
788
- },
789
- state: {
790
- handler: function(state) {
791
- this.setState(state);
792
- },
793
- immediate: true,
794
- deep: true
795
- }
796
- },
797
- mounted: function() {
798
- const flatmap = require("@abi-software/flatmap-viewer");
799
- this.mapManager = new flatmap.MapManager(this.flatmapAPI);
800
- if (this.renderAtMounted) this.createFlatmap();
801
- }
802
- };
803
- </script>
804
-
805
- <!-- Add "scoped" attribute to limit CSS to this component only -->
806
- <style scoped lang="scss">
807
- @import "~element-ui/packages/theme-chalk/src/button";
808
- @import "~element-ui/packages/theme-chalk/src/checkbox";
809
- @import "~element-ui/packages/theme-chalk/src/checkbox-group";
810
- @import "~element-ui/packages/theme-chalk/src/loading";
811
- @import "~element-ui/packages/theme-chalk/src/row";
812
-
813
- .beta-popovers {
814
- position: absolute;
815
- top: 90px;
816
- left: 16px;
817
- text-align: left;
818
- font-size: 25px;
819
- }
820
-
821
- .warning-icon {
822
- color: $warning;
823
-
824
- &:hover {
825
- cursor: pointer;
826
- }
827
- }
828
-
829
- .warning-text {
830
- font-family: Asap, sans-serif;
831
- font-size: 15px;
832
- vertical-align: 5px;
833
- }
834
-
835
- .latest-changesicon {
836
- color: $success;
837
-
838
- &:hover {
839
- cursor: pointer;
840
- }
841
- }
842
-
843
- .latest-changestext {
844
- font-family: Asap, sans-serif;
845
- font-size: 15px;
846
- vertical-align: 5px;
847
- }
848
-
849
- .path-visual {
850
- margin: 3px 0;
851
- height: 3px;
852
- width: 25px;
853
- margin-right: 5px;
854
- display: inline-block;
855
- &.cns {
856
- background: #9b1fc1;
857
- }
858
- &.lcn {
859
- background: #f19e38;
860
- }
861
- &.para-pre {
862
- background: #3f8f4a;
863
- }
864
- &.para-post {
865
- background: repeating-linear-gradient(
866
- 90deg,
867
- #3f8f4a,
868
- #3f8f4a 6px,
869
- transparent 0,
870
- transparent 9px
871
- );
872
- }
873
- &.sensory {
874
- background: #2a62f6;
875
- }
876
- &.somatic {
877
- background: #98561d;
878
- }
879
- &.symp-pre {
880
- background: #ea3423;
881
- }
882
- &.symp-post {
883
- background: repeating-linear-gradient(
884
- 90deg,
885
- #ea3423,
886
- #ea3423 6px,
887
- transparent 0,
888
- transparent 9px
889
- );
890
- }
891
- }
892
-
893
- .flatmap-container {
894
- height: 100%;
895
- width: 100%;
896
- }
897
-
898
- .pathway-location {
899
- position: absolute;
900
- bottom: 0px;
901
- transition: all 1s ease;
902
- &.open {
903
- left: 0px;
904
- }
905
- &.close {
906
- left: -298px;
907
- }
908
- }
909
-
910
- .svg-legends-container {
911
- width:70%;
912
- height:auto;
913
- }
914
-
915
- .pathway-container {
916
- float: left;
917
- padding-left: 16px;
918
- padding-right: 18px;
919
- max-height: calc(100% - 184px);
920
- text-align: left;
921
- overflow: auto;
922
- border: 1px solid rgb(220, 223, 230);
923
- padding-bottom: 16px;
924
- background: #ffffff;
925
- }
926
-
927
- .pathways-display-text {
928
- width: 59px;
929
- height: 20px;
930
- color: rgb(48, 49, 51);
931
- font-size: 14px;
932
- font-weight: normal;
933
- line-height: 20px;
934
- margin-left: 8px;
935
- }
936
-
937
- .all-checkbox {
938
- float: right;
939
- }
940
-
941
- .checkbox-container {
942
- display: flex;
943
- cursor: pointer;
944
- }
945
-
946
- .checkbox-group {
947
- width: 260px;
948
- border: 1px solid rgb(144, 147, 153);
949
- border-radius: 4px;
950
- background: #ffffff;
951
- }
952
-
953
- .my-checkbox {
954
- background-color: #fff;
955
- width: 100%;
956
- }
957
-
958
- .checkbox-group-inner {
959
- padding: 18px;
960
- }
961
-
962
- .flatmap-marker-help {
963
- display: inline-block;
964
- }
965
-
966
- ::v-deep .popper-bump-right {
967
- left: 30px;
968
- }
969
-
970
- ::v-deep .el-checkbox__label {
971
- padding-left: 5px;
972
- color: $app-primary-color;
973
- font-size: 12px;
974
- font-weight: 500;
975
- letter-spacing: 0px;
976
- line-height: 14px;
977
- }
978
-
979
- ::v-deep .el-checkbox__input {
980
- &.is-indeterminate,
981
- &.is-checked {
982
- .el-checkbox__inner {
983
- background-color: $app-primary-color;
984
- border-color: $app-primary-color;
985
- }
986
- }
987
- }
988
-
989
- ::v-deep .el-checkbox__label {
990
- color: $app-primary-color !important;
991
- }
992
-
993
- .el-dropdown-link {
994
- cursor: pointer;
995
- color: #409eff;
996
- }
997
- .el-icon-arrow-down {
998
- font-size: 12px;
999
- }
1000
- .demonstration {
1001
- display: block;
1002
- color: #8492a6;
1003
- font-size: 14px;
1004
- margin-bottom: 20px;
1005
- }
1006
-
1007
- .tooltip {
1008
- display: none;
1009
- }
1010
-
1011
- ::v-deep .mapboxgl-popup {
1012
- max-width: 300px !important;
1013
- }
1014
-
1015
- ::v-deep .flatmap-tooltip-popup {
1016
- &.mapboxgl-popup-anchor-bottom {
1017
- .mapboxgl-popup-content {
1018
- margin-bottom: 12px;
1019
- &::after,
1020
- &::before {
1021
- top: 100%;
1022
- border-width: 12px;
1023
- }
1024
- /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1025
- &::after {
1026
- margin-top: -1px;
1027
- border-color: rgb(255, 255, 255) transparent transparent transparent;
1028
- }
1029
- /* this border color controlls the outside, thin border */
1030
- &::before {
1031
- margin: 0 auto;
1032
- border-color: $app-primary-color transparent transparent transparent;
1033
- }
1034
- }
1035
- }
1036
- &.mapboxgl-popup-anchor-top {
1037
- .mapboxgl-popup-content {
1038
- margin-top: 18px;
1039
- &::after,
1040
- &::before {
1041
- top: calc(-100% + 6px);
1042
- border-width: 12px;
1043
- }
1044
- /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1045
- &::after {
1046
- margin-top: 1px;
1047
- border-color: transparent transparent rgb(255, 255, 255) transparent;
1048
- }
1049
- &::before {
1050
- margin: 0 auto;
1051
- border-color: transparent transparent $app-primary-color transparent;
1052
- }
1053
- }
1054
- }
1055
- .mapboxgl-popup-content {
1056
- border-radius: 4px;
1057
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
1058
- pointer-events: none;
1059
- display: none;
1060
- background: #fff;
1061
- border: 1px solid $app-primary-color;
1062
- padding-left: 6px;
1063
- padding-right: 6px;
1064
- display: flex;
1065
- justify-content: center;
1066
- align-items: center;
1067
- &::after,
1068
- &::before {
1069
- content: "";
1070
- display: block;
1071
- position: absolute;
1072
- width: 0;
1073
- height: 0;
1074
- border-style: solid;
1075
- flex-shrink: 0;
1076
- }
1077
- }
1078
- .mapboxgl-popup-tip {
1079
- display: none;
1080
- }
1081
- }
1082
-
1083
- ::v-deep .mapboxgl-popup {
1084
- &.flatmap-marker-popup {
1085
- box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
1086
- pointer-events: auto;
1087
- background: #fff;
1088
- }
1089
- }
1090
-
1091
- /* Fix for chrome bug where under triangle pops up above one on top of it */
1092
- .selector:not(*:root),
1093
- ::v-deep.flatmap-tooltip-popup {
1094
- .mapboxgl-popup-content::after {
1095
- top: 99.9%;
1096
- }
1097
- }
1098
-
1099
- ::v-deep .flatmap-tooltip-dialog {
1100
- .mapboxgl-popup-tip {
1101
- display: none;
1102
- }
1103
- }
1104
-
1105
- ::v-deep .flatmap-marker-popup {
1106
- .mapboxgl-popup-content {
1107
- padding: 0px;
1108
- }
1109
- }
1110
-
1111
- ::v-deep .flatmapvuer-popover {
1112
- .mapboxgl-popup-close-button {
1113
- position: absolute;
1114
- right: 0.5em;
1115
- top: 0;
1116
- border: 0;
1117
- border-radius: 0 3px 0 0;
1118
- cursor: pointer;
1119
- background-color: transparent;
1120
- font-size: 2.5em;
1121
- color: grey;
1122
- top: 0.95em;
1123
- }
1124
- }
1125
-
1126
- .zoomOut {
1127
- padding-left: 8px;
1128
- }
1129
-
1130
- .fitWindow {
1131
- padding-left: 8px;
1132
- }
1133
-
1134
- .background-colour {
1135
- bottom: 16px;
1136
- position: absolute;
1137
- transition: all 1s ease;
1138
- }
1139
- .background-colour.open {
1140
- left: 322px;
1141
- }
1142
- .background-colour.close {
1143
- left: 24px;
1144
- }
1145
-
1146
- ::v-deep .background-popper {
1147
- padding: 5px 12px;
1148
- background-color: #ffffff;
1149
- border: 1px solid $app-primary-color;
1150
- box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
1151
- height: 200px;
1152
- width: 175px;
1153
- min-width: 175px;
1154
- &.el-popper[x-placement^="top"] {
1155
- .popper__arrow {
1156
- border-top-color: $app-primary-color !important;
1157
- &::after {
1158
- border-top-color: #fff !important;
1159
- }
1160
- }
1161
- }
1162
- }
1163
-
1164
- .backgroundText {
1165
- color: rgb(48, 49, 51);
1166
- font-size: 14px;
1167
- font-weight: normal;
1168
- line-height: 20px;
1169
- }
1170
-
1171
- .backgroundControl {
1172
- display: flex;
1173
- margin-top: 16px;
1174
- }
1175
-
1176
- .backgroundChoice {
1177
- width: 20px;
1178
- height: 20px;
1179
- border: 1px solid rgb(144, 147, 153);
1180
- margin-left: 20px;
1181
- &.active {
1182
- border: 2px solid $app-primary-color;
1183
- }
1184
- &:hover {
1185
- cursor: pointer;
1186
- }
1187
- &.white {
1188
- background-color: white;
1189
- margin-left: 10px;
1190
- }
1191
- &.black {
1192
- background-color: black;
1193
- }
1194
- &.lightskyblue {
1195
- background-color: lightskyblue;
1196
- }
1197
- }
1198
-
1199
- .togglePaths {
1200
- top: 201px;
1201
- right: 20px;
1202
- position: absolute;
1203
- }
1204
-
1205
- .icon-button {
1206
- height: 24px !important;
1207
- width: 24px !important;
1208
- color: $app-primary-color;
1209
- &:hover {
1210
- cursor: pointer;
1211
- }
1212
- }
1213
-
1214
- ::v-deep .flatmap-popper {
1215
- padding: 6px 4px;
1216
- font-size: 12px;
1217
- color: rgb(48, 49, 51);
1218
- background-color: #f3ecf6;
1219
- border: 1px solid $app-primary-color;
1220
- white-space: nowrap;
1221
- min-width: unset;
1222
- &.warning-popper {
1223
- min-width: 150px;
1224
- max-width: 400px;
1225
- word-break: keep-all;
1226
- white-space: unset;
1227
- }
1228
- &.left-popper {
1229
- .popper__arrow {
1230
- border-left-color: $app-primary-color !important;
1231
- &::after {
1232
- border-left-color: #f3ecf6 !important;
1233
- }
1234
- }
1235
- }
1236
- &.right-popper {
1237
- .popper__arrow {
1238
- border-right-color: $app-primary-color !important;
1239
- &:after {
1240
- border-right-color: #f3ecf6 !important;
1241
- }
1242
- }
1243
- }
1244
- &.el-popper[x-placement^="top"] {
1245
- .popper__arrow {
1246
- border-top-color: $app-primary-color !important;
1247
- &:after {
1248
- border-top-color: #f3ecf6 !important;
1249
- }
1250
- }
1251
- }
1252
- }
1253
-
1254
- ::v-deep .el-loading-spinner {
1255
- i,
1256
- .el-loading-text {
1257
- color: $app-primary-color;
1258
- }
1259
- }
1260
-
1261
- ::v-deep .flatmap-popup-popper {
1262
- .mapboxgl-popup-tip {
1263
- border-bottom-color: $app-primary-color;
1264
- }
1265
- .mapboxgl-popup-content {
1266
- padding: 6px 4px;
1267
- font-size: 12px;
1268
- color: rgb(48, 49, 51);
1269
- background-color: #f3ecf6;
1270
- border: 1px solid $app-primary-color;
1271
- white-space: nowrap;
1272
- min-width: unset;
1273
- .mapboxgl-popup-close-button {
1274
- display: none;
1275
- }
1276
- }
1277
- }
1278
-
1279
- ::v-deep .flatmap-popper {
1280
-
1281
- }
1282
-
1283
- ::v-deep .popper-zoomout {
1284
- padding-right: 13px !important;
1285
- left: -21px !important;
1286
- }
1287
-
1288
- ::v-deep .popper-zoomout {
1289
- .popper__arrow {
1290
- left: 53px !important;
1291
- }
1292
- }
1293
-
1294
- ::v-deep .mapboxgl-popup-content {
1295
- padding: 0px;
1296
- }
1297
-
1298
- .bottom-right-control {
1299
- position: absolute;
1300
- right: 16px;
1301
- bottom: 16px;
1302
- }
1303
-
1304
- ::v-deep .my-drawer {
1305
- background: rgba(0, 0, 0, 0);
1306
- box-shadow: none;
1307
- }
1308
-
1309
- .drawer {
1310
- ::v-deep .el-drawer:focus {
1311
- outline: none;
1312
- }
1313
- }
1314
-
1315
- .open-drawer,
1316
- .drawer-button {
1317
- z-index: 8;
1318
- width: 20px;
1319
- height: 40px;
1320
- border: solid 1px $app-primary-color;
1321
- text-align: center;
1322
- vertical-align: middle;
1323
- cursor: pointer;
1324
- pointer-events: auto;
1325
- }
1326
-
1327
- .open-drawer {
1328
- position: absolute;
1329
- left: 0px;
1330
- background-color: #f7faff;
1331
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
1332
- }
1333
-
1334
- .drawer-button {
1335
- float: left;
1336
- margin-top: calc(50% - 36px);
1337
- background-color: #F9F2FC;
1338
-
1339
- i {
1340
- font-weight: 600;
1341
- margin-top: 12px;
1342
- color: $app-primary-color;
1343
- transition-delay: 0.9s;
1344
- }
1345
- &.open {
1346
- i {
1347
- transform: rotate(0deg) scaleY(2);
1348
- }
1349
- }
1350
- &.close {
1351
- i {
1352
- transform: rotate(180deg) scaleY(2);
1353
- }
1354
- }
1355
- }
1356
-
1357
- ::v-deep .mapboxgl-canvas-container {
1358
- canvas {
1359
- outline: none;
1360
- }
1361
- }
1362
-
1363
- .backgroundSpacer {
1364
- border-bottom: 1px solid #e4e7ed;
1365
- margin-bottom: 10px;
1366
- }
1367
-
1368
- .flatmap-radio {
1369
- ::v-deep label {
1370
- margin-right: 20px;
1371
- &:last-child {
1372
- margin-right: 0px;
1373
- }
1374
- }
1375
- .el-radio__input {
1376
- &.is-checked {
1377
- & + .el-radio__label {
1378
- color: $app-primary-color;
1379
- }
1380
- .el-radio__inner {
1381
- border-color: $app-primary-color;
1382
- background: $app-primary-color;
1383
- }
1384
- }
1385
- }
1386
- }
1387
- </style>
1388
-
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" @click="setLastClickAndCheckPopups">
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
+ <svg-legends class= "svg-legends-container"/>
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 SvgLegends from "./legends/Legends";
255
+ import {
256
+ Checkbox,
257
+ CheckboxGroup,
258
+ Col,
259
+ Loading,
260
+ Radio,
261
+ RadioGroup,
262
+ Row
263
+ } from "element-ui";
264
+ import lang from "element-ui/lib/locale/lang/en";
265
+ import locale from "element-ui/lib/locale";
266
+ import flatmapMarker from "../icons/flatmap-marker";
267
+
268
+ locale.use(lang);
269
+ Vue.use(Checkbox);
270
+ Vue.use(CheckboxGroup);
271
+ Vue.use(Col);
272
+ Vue.use(Loading.directive);
273
+ Vue.use(Radio);
274
+ Vue.use(RadioGroup);
275
+ Vue.use(Row);
276
+ const ResizeSensor = require("css-element-queries/src/ResizeSensor");
277
+
278
+ const mapResize = map => {
279
+ return () => {
280
+ if (map) map.resize();
281
+ };
282
+ };
283
+
284
+ export default {
285
+ name: "FlatmapVuer",
286
+ components: {
287
+ MapSvgIcon,
288
+ MapSvgSpriteColor,
289
+ Tooltip,
290
+ SvgLegends
291
+ },
292
+ beforeCreate: function() {
293
+ this.mapManager = undefined;
294
+ this.mapImp = undefined;
295
+ },
296
+ methods: {
297
+ backgroundChangeCallback: function(colour) {
298
+ this.currentBackground = colour;
299
+ if (this.mapImp) {
300
+ this.mapImp.setBackgroundColour(this.currentBackground, 1);
301
+ }
302
+ },
303
+ toggleDrawer: function() {
304
+ this.drawerOpen = !this.drawerOpen;
305
+ },
306
+ /**
307
+ * Function to toggle colour/greyscale of organs.
308
+ */
309
+ setColour: function(flag) {
310
+ this.colourRadio = flag;
311
+ if (this.mapImp) {
312
+ this.mapImp.setColour({ colour: flag, outline: this.outlinesRadio });
313
+ }
314
+ },
315
+ /**
316
+ * Function to toggle outlines f organs.
317
+ */
318
+ setOutlines: function(flag) {
319
+ this.outlineRadio = flag;
320
+ if (this.mapImp) {
321
+ this.mapImp.setColour({ colour: this.colourRadio, outline: flag });
322
+ }
323
+ },
324
+ /**
325
+ * Function to toggle paths to default.
326
+ * Also called when the associated button is pressed.
327
+ */
328
+ resetView: function() {
329
+ if (this.mapImp) {
330
+ this.mapImp.resetMap();
331
+ this.checkedItems = this.mapImp.pathTypes().map(item => item.type);
332
+ this.isIndeterminate = false;
333
+ this.checkAll = true;
334
+ }
335
+ },
336
+ /**
337
+ * Function to zoom in.
338
+ * Also called when the associated button is pressed.
339
+ */
340
+ zoomIn: function() {
341
+ if (this.mapImp) {
342
+ this.mapImp.zoomIn();
343
+ }
344
+ },
345
+ /**
346
+ * Function to zoom out.
347
+ * Also called when the associated button is pressed.
348
+ */
349
+ zoomOut: function() {
350
+ if (this.mapImp) {
351
+ this.mapImp.zoomOut();
352
+ }
353
+ },
354
+ visibilityToggle: function() {
355
+ if (this.mapImp) {
356
+ this.mapImp.showPaths(this.checkedItems);
357
+ }
358
+ },
359
+ handleCheckedItemsChange: function(value) {
360
+ let checkedCount = value.length;
361
+ this.checkAll = checkedCount === this.pathways.length;
362
+ this.isIndeterminate =
363
+ checkedCount > 0 && checkedCount < this.pathways.length;
364
+ },
365
+ handleCheckAllChange(val) {
366
+ this.checkedItems = val ? this.pathways.map(a => a.type) : [];
367
+ this.isIndeterminate = false;
368
+ if (this.mapImp) {
369
+ this.mapImp.showPaths(this.checkedItems);
370
+ }
371
+ },
372
+ enablePanZoomEvents: function(flag) {
373
+ this.mapImp.enablePanZoomEvents(flag);
374
+ },
375
+ eventCallback: function() {
376
+ return (eventType, data, ...args) => {
377
+ if (eventType !== "pan-zoom") {
378
+ const label = data.label;
379
+ const resource = [data.models];
380
+ const taxonomy = this.entry;
381
+ const biologicalSex = this.biologicalSex;
382
+ const payload = {
383
+ dataset: data.dataset,
384
+ biologicalSex: biologicalSex,
385
+ taxonomy: taxonomy,
386
+ resource: resource,
387
+ label: label,
388
+ feature: data,
389
+ userData: args,
390
+ eventType: eventType
391
+ };
392
+ this.lastPayload = payload
393
+ this.lastData = data
394
+ this.$emit("resource-selected", payload);
395
+ } else {
396
+ this.$emit("pan-zoom-callback", data);
397
+ }
398
+ };
399
+ },
400
+ // checkNeuronClicked shows a neuron path pop up if a path was recently clicked
401
+ checkAndCreatePopups: function(data) {
402
+ if (
403
+ data.eventType == "click" &&
404
+ this.hasNeuronTooltip(data)
405
+ ) {
406
+ this.createTooltipFromNeuronCuration(data);
407
+ this.mapImp.showPopup(
408
+ this.mapImp.modelFeatureIds(data.resource[0])[0],
409
+ this.$refs.tooltip.$el,
410
+ { className: "flatmapvuer-popover", positionAtLastClick: true, anchor: this.setAnchor()}
411
+ );
412
+ this.popUpCssHacks();
413
+ }
414
+ },
415
+ setAnchor: function(){
416
+ // note that we are setting the anchor. So anchor on the *right* means tooltip is on the *left*
417
+
418
+ let width = this.$refs.display.clientWidth
419
+ if (this.lastClick.x > width/2){
420
+ return 'left'
421
+ } else {
422
+ return 'right'
423
+ }
424
+ },
425
+ popUpCssHacks: function() {
426
+ // Below is a hack to remove flatmap tooltips while popup is open
427
+ let ftooltip = document.querySelector(".flatmap-tooltip-popup");
428
+ if (ftooltip) ftooltip.style.display = "none";
429
+ document.querySelector(".mapboxgl-popup-close-button").style.display =
430
+ "block";
431
+ this.$refs.tooltip.$el.style.display = "flex";
432
+ document.querySelector(".mapboxgl-popup-close-button").onclick = () => {
433
+ document.querySelector(".flatmap-tooltip-popup").style.display =
434
+ "block";
435
+ };
436
+ },
437
+ resourceSelected: function(action) {
438
+ this.$emit("resource-selected", action);
439
+ },
440
+ hasNeuronTooltip: function(data) {
441
+
442
+ // neural data check
443
+ if (data.resource[0]){
444
+ if (data.resource[0].includes('ilxtr:neuron')){
445
+ return true
446
+ }
447
+ }
448
+ // annotated with datset check
449
+ if (data.dataset) {
450
+ return true
451
+ }
452
+
453
+ // if there is no cuff, neural data, or dataset we do not display neuron tooltip
454
+ return false
455
+
456
+ },
457
+ createTooltipFromNeuronCuration: function(data) {
458
+ const feature = data.resource[0];
459
+ let content = {
460
+ title: undefined,
461
+ components: undefined,
462
+ start: undefined,
463
+ distribution: undefined,
464
+ actions: []
465
+ };
466
+
467
+ this.tooltipVisible = false;
468
+
469
+ // neural data check
470
+ if (feature){
471
+ if (feature.includes('ilxtr:neuron')){
472
+ this.tooltipVisible = true;
473
+ this.tooltipContent = content;
474
+ this.tooltipContent.uberon = feature;
475
+ this.tooltipContent.source = data.feature.source;
476
+ this.tooltipContent.title = data.label;
477
+ this.tooltipContent.featureIds = [feature];
478
+ this.tooltipContent.actions.push({
479
+ title: "Search for datasets",
480
+ label: "Neuron Datasets",
481
+ resource: feature.split(":")[1],
482
+ type: "Neuron Search",
483
+ feature: feature,
484
+ nervePath: true
485
+ });
486
+ }
487
+ }
488
+ // annotated with datset check
489
+ if (data.dataset) {
490
+ this.tooltipVisible = true;
491
+ this.tooltipContent = content;
492
+ this.tooltipContent.uberon = feature;
493
+ this.tooltipContent.source = data.feature.source;
494
+ this.tooltipContent.title = data.label;
495
+ this.tooltipContent.actions.push({
496
+ title: "View dataset",
497
+ resource: data.dataset,
498
+ type: "URL",
499
+ feature: feature,
500
+ nervePath: false
501
+ });
502
+ }
503
+ },
504
+ // Keeping this as an API
505
+ showPopup: function(featureId, node, options) {
506
+ let myOptions = options;
507
+ if (this.mapImp) {
508
+ if (myOptions) {
509
+ if (!myOptions.className) myOptions.className = "flatmapvuer-popover";
510
+ } else {
511
+ myOptions = { className: "flatmapvuer-popover", positionAtLastClick: true };
512
+ }
513
+ this.mapImp.showPopup(featureId, node, myOptions);
514
+ }
515
+ },
516
+ showMarkerPopup: function(featureId, node, options) {
517
+ if (this.mapImp) {
518
+ this.mapImp.showMarkerPopup(featureId, node, options);
519
+ }
520
+ },
521
+ setHelpMode: function(helpMode) {
522
+ if (helpMode) {
523
+ this.inHelp = true;
524
+ this.hoverVisibilities.forEach(item => {
525
+ item.value = true;
526
+ });
527
+ this.openFlatmapHelpPopup();
528
+ } else {
529
+ this.inHelp = false;
530
+ this.hoverVisibilities.forEach(item => {
531
+ item.value = false;
532
+ });
533
+ this.closeFlatmapHelpPopup();
534
+ }
535
+ },
536
+ showToolitip: function(tooltipNumber) {
537
+ if (!this.inHelp) {
538
+ this.tooltipWait = setTimeout(() => {
539
+ this.hoverVisibilities[tooltipNumber].value = true;
540
+ }, 500);
541
+ }
542
+ },
543
+ hideToolitip: function(tooltipNumber) {
544
+ if (!this.inHelp) {
545
+ this.hoverVisibilities[tooltipNumber].value = false;
546
+ clearTimeout(this.tooltipWait);
547
+ }
548
+ },
549
+ openFlatmapHelpPopup: function() {
550
+ if (this.mapImp) {
551
+ let heartId = this.mapImp.featureIdsForModel("UBERON:0000948")[0];
552
+ const elm = "Click for more information";
553
+ this.mapImp.showPopup(heartId, elm, {
554
+ anchor: "top",
555
+ className: "flatmap-popup-popper"
556
+ });
557
+ }
558
+ },
559
+ closeFlatmapHelpPopup: function() {
560
+ this.$el
561
+ .querySelectorAll(".mapboxgl-popup-close-button")
562
+ .forEach(item => {
563
+ item.click();
564
+ });
565
+ },
566
+ getLabels: function() {
567
+ let labels = [];
568
+ if (this.mapImp) {
569
+ let annotations = this.mapImp.annotations;
570
+ for (let value of annotations.values()) {
571
+ if (value.label) labels.push(value.label);
572
+ }
573
+ return Array.from(new Set(labels));
574
+ }
575
+ },
576
+ getState: function() {
577
+ if (this.mapImp) {
578
+ let state = {
579
+ entry: this.entry,
580
+ viewport: this.mapImp.getState()
581
+ };
582
+ const identifier = this.mapImp.getIdentifier();
583
+ if (this.biologicalSex)
584
+ state['biologicalSex'] = this.biologicalSex;
585
+ else if (identifier && identifier.biologicalSex)
586
+ state['biologicalSex'] = identifier.biologicalSex;
587
+ if (identifier && identifier.uuid)
588
+ state['uuid'] = identifier.uuid;
589
+ return state;
590
+ }
591
+ return undefined;
592
+ },
593
+ setState: function(state) {
594
+ if (state) {
595
+ if (this.mapImp &&
596
+ (state.entry && (this.entry == state.entry)) &&
597
+ (!state.biologicalSex || (state.biologicalSex === this.biologicalSex)))
598
+ {
599
+ if (state.viewport) {
600
+ this.mapImp.setState(state.viewport);
601
+ }
602
+ } else {
603
+ this.createFlatmap(state);
604
+ }
605
+ }
606
+ },
607
+ createFlatmap: function(state) {
608
+ if (!this.mapImp && !this.loading) {
609
+ this.loading = true;
610
+ let minimap = false;
611
+ if (this.displayMinimap) {
612
+ minimap = { position: "top-right" };
613
+ }
614
+
615
+ //As for flatmap-viewer@2.2.7, see below for the documentation
616
+ //for the identifier:
617
+
618
+ //@arg identifier {string|Object}
619
+ // A string or object identifying the map to load. If a string its
620
+ // value can be either the map's ``uuid``, assigned at generation time,
621
+ // or taxon and biological sex identifiers of the species that the map
622
+ // represents. The latest version of a map is loaded unless it has been
623
+ // identified using a ``uuid`` (see below).
624
+ // @arg identifier.taxon {string} The taxon identifier of the species
625
+ // represented by the map. This is specified as metadata in the map's source file.
626
+ // @arg identifier.biologicalSex {string} The biological sex of the species
627
+ // represented by the map. This is specified as metadatain the map's source file.
628
+ // @arg identifier.uuid {string} The unique uuid the flatmap. If given then this exact map will
629
+ // be loaded, overriding ``taxon`` and ``biologicalSex``.
630
+
631
+ let identifier = { taxon: this.entry };
632
+ if (state && state.entry) {
633
+ identifier.taxon = state.entry;
634
+ if (state.biologicalSex) {
635
+ identifier["biologicalSex"] = state.biologicalSex;
636
+ } else if (identifier.taxon === "NCBITaxon:9606") {
637
+ //For backward compatibility
638
+ identifier["biologicalSex"] ="PATO:0000384";
639
+ }
640
+ } else {
641
+ // Set the bioloicalSex now if map is not resumed from
642
+ // a saved state
643
+ if (this.biologicalSex) {
644
+ identifier["biologicalSex"] = this.biologicalSex;
645
+ }
646
+ }
647
+
648
+ let promise1 = this.mapManager.loadMap(
649
+ identifier,
650
+ this.$refs.display,
651
+ this.eventCallback(),
652
+ {
653
+ //fullscreenControl: false,
654
+ //annotatable: false,
655
+ //debug: true,
656
+ featureInfo: this.featureInfo,
657
+ "min-zoom": this.minZoom,
658
+ pathControls: false,
659
+ searchable: this.searchable,
660
+ tooltips: this.tooltips,
661
+ minimap: minimap
662
+ }
663
+ );
664
+ promise1.then(returnedObject => {
665
+ this.mapImp = returnedObject;
666
+ this.sensor = new ResizeSensor(
667
+ this.$refs.display,
668
+ mapResize(this.mapImp)
669
+ );
670
+ this.mapImp.setBackgroundOpacity(1);
671
+ this.backgroundChangeCallback(this.currentBackground);
672
+ this.pathways = this.mapImp.pathTypes();
673
+ this.$emit("ready", this);
674
+ this.loading = false;
675
+ if (this._viewportToBeSet)
676
+ this.mapImp.setState(this._viewportToBeSet);
677
+ else if (state && state.viewport)
678
+ this.mapImp.setState(state.viewport);
679
+ });
680
+ } else if (state) {
681
+ if (this.entry == state.entry)
682
+ this._viewportToBeSet = state.viewport;
683
+ }
684
+ },
685
+ showMinimap: function(flag) {
686
+ if (this.mapImp)
687
+ this.mapImp.showMinimap(flag);
688
+ },
689
+ showPathwaysDrawer: function(flag) {
690
+ this.drawerOpen = flag;
691
+ },
692
+ /**
693
+ * Function to display features with annotation matching the provided term.
694
+ */
695
+ searchAndShowResult: function(term) {
696
+ if (this.mapImp) {
697
+ if (term === undefined || term === "") {
698
+ this.mapImp.clearSearchResults();
699
+ return true;
700
+ } else {
701
+ let searchResults = this.mapImp.search(term);
702
+ if (searchResults && searchResults.__featureIds.length > 0) {
703
+ this.mapImp.showSearchResults(searchResults);
704
+ return true;
705
+ }
706
+ else
707
+ this.mapImp.clearSearchResults();
708
+ }
709
+ }
710
+ return false;
711
+ },
712
+ /**
713
+ * Get the list of suggested terms
714
+ */
715
+ searchSuggestions: function(term) {
716
+ if (this.mapImp)
717
+ return this.mapImp.search(term);
718
+ return [];
719
+ },
720
+ setLastClickAndCheckPopups: function(ev){
721
+ this.lastClick = {
722
+ x: ev.x,
723
+ y: ev.y
724
+ }
725
+ if (this.lastData && this.lastData.type !== "marker")
726
+ this.checkAndCreatePopups(this.lastPayload)
727
+ this.lastData = undefined // reset incase events object doesn't reset
728
+ }
729
+ },
730
+ props: {
731
+ entry: String,
732
+ biologicalSex: {
733
+ type: String,
734
+ default: ""
735
+ },
736
+ featureInfo: {
737
+ type: Boolean,
738
+ default: false
739
+ },
740
+ minZoom: {
741
+ type: Number,
742
+ default: 4
743
+ },
744
+ pathControls: {
745
+ type: Boolean,
746
+ default: true
747
+ },
748
+ searchable: {
749
+ type: Boolean,
750
+ default: false
751
+ },
752
+ tooltips: {
753
+ type: Boolean,
754
+ default: true
755
+ },
756
+ helpMode: {
757
+ type: Boolean,
758
+ default: false
759
+ },
760
+ renderAtMounted: {
761
+ type: Boolean,
762
+ default: true
763
+ },
764
+ displayMinimap: {
765
+ type: Boolean,
766
+ default: false
767
+ },
768
+ displayWarning: {
769
+ type: Boolean,
770
+ default: false
771
+ },
772
+ warningMessage: {
773
+ type: String,
774
+ 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."
775
+ },
776
+ displayLatestChanges: {
777
+ type: Boolean,
778
+ default: false,
779
+ },
780
+ latestChangesMessage: {
781
+ type: String,
782
+ default: "Search now provide suggested terms. Add new legends. New tilesets. New female map. Improve upstream downstream information",
783
+ },
784
+ /**
785
+ * State containing state of the flatmap.
786
+ */
787
+ state: {
788
+ type: Object,
789
+ default: undefined
790
+ },
791
+ /**
792
+ * Specify the endpoint of the flatmap server.
793
+ */
794
+ flatmapAPI: {
795
+ type: String,
796
+ default: "https://mapcore-demo.org/current/flatmap/v3/"
797
+ },
798
+ sparcAPI: {
799
+ type: String,
800
+ default: "https://api.sparc.science/"
801
+ },
802
+ },
803
+ provide() {
804
+ return {
805
+ sparcAPI: this.sparcAPI,
806
+ flatmapAPI: this.flatmapAPI
807
+ }
808
+ },
809
+ data: function() {
810
+ return {
811
+ checkedItems: [],
812
+ pathways: [],
813
+ isIndeterminate: false,
814
+ checkAll: true,
815
+ hoverVisibilities: [
816
+ { value: false },
817
+ { value: false },
818
+ { value: false },
819
+ { value: false },
820
+ { value: false },
821
+ { value: false },
822
+ { value: false },
823
+ { value: false }
824
+ ],
825
+ inHelp: false,
826
+ currentBackground: "white",
827
+ availableBackground: ["white", "lightskyblue", "black"],
828
+ loading: false,
829
+ flatmapMarker: flatmapMarker,
830
+ drawerOpen: true,
831
+ tooltipContent: { featureIds: []},
832
+ colourRadio: true,
833
+ outlinesRadio: true,
834
+ lastClick: {x: 0, y: 0}
835
+ };
836
+ },
837
+ watch: {
838
+ entry: function() {
839
+ if (!this.state) this.createFlatmap();
840
+ },
841
+ helpMode: function(val) {
842
+ this.setHelpMode(val);
843
+ },
844
+ state: {
845
+ handler: function(state) {
846
+ this.setState(state);
847
+ },
848
+ immediate: true,
849
+ deep: true
850
+ }
851
+ },
852
+ mounted: function() {
853
+ const flatmap = require("@abi-software/flatmap-viewer");
854
+ this.mapManager = new flatmap.MapManager(this.flatmapAPI);
855
+ if (this.renderAtMounted) this.createFlatmap();
856
+ }
857
+ };
858
+ </script>
859
+
860
+ <!-- Add "scoped" attribute to limit CSS to this component only -->
861
+ <style scoped lang="scss">
862
+ @import "~element-ui/packages/theme-chalk/src/button";
863
+ @import "~element-ui/packages/theme-chalk/src/checkbox";
864
+ @import "~element-ui/packages/theme-chalk/src/checkbox-group";
865
+ @import "~element-ui/packages/theme-chalk/src/loading";
866
+ @import "~element-ui/packages/theme-chalk/src/row";
867
+
868
+ .beta-popovers {
869
+ position: absolute;
870
+ top: 90px;
871
+ left: 16px;
872
+ text-align: left;
873
+ font-size: 25px;
874
+ }
875
+
876
+ .warning-icon {
877
+ color: $warning;
878
+
879
+ &:hover {
880
+ cursor: pointer;
881
+ }
882
+ }
883
+
884
+ .warning-text {
885
+ font-family: Asap, sans-serif;
886
+ font-size: 15px;
887
+ vertical-align: 5px;
888
+ }
889
+
890
+ .latest-changesicon {
891
+ color: $success;
892
+
893
+ &:hover {
894
+ cursor: pointer;
895
+ }
896
+ }
897
+
898
+ .latest-changestext {
899
+ font-family: Asap, sans-serif;
900
+ font-size: 15px;
901
+ vertical-align: 5px;
902
+ }
903
+
904
+ .path-visual {
905
+ margin: 3px 0;
906
+ height: 3px;
907
+ width: 25px;
908
+ margin-right: 5px;
909
+ display: inline-block;
910
+ &.cns {
911
+ background: #9b1fc1;
912
+ }
913
+ &.lcn {
914
+ background: #f19e38;
915
+ }
916
+ &.para-pre {
917
+ background: #3f8f4a;
918
+ }
919
+ &.para-post {
920
+ background: repeating-linear-gradient(
921
+ 90deg,
922
+ #3f8f4a,
923
+ #3f8f4a 6px,
924
+ transparent 0,
925
+ transparent 9px
926
+ );
927
+ }
928
+ &.sensory {
929
+ background: #2a62f6;
930
+ }
931
+ &.somatic {
932
+ background: #98561d;
933
+ }
934
+ &.symp-pre {
935
+ background: #ea3423;
936
+ }
937
+ &.symp-post {
938
+ background: repeating-linear-gradient(
939
+ 90deg,
940
+ #ea3423,
941
+ #ea3423 6px,
942
+ transparent 0,
943
+ transparent 9px
944
+ );
945
+ }
946
+ &.other {
947
+ background: #888;
948
+ }
949
+ }
950
+
951
+ .flatmap-container {
952
+ height: 100%;
953
+ width: 100%;
954
+ }
955
+
956
+ .pathway-location {
957
+ position: absolute;
958
+ bottom: 0px;
959
+ transition: all 1s ease;
960
+ &.open {
961
+ left: 0px;
962
+ }
963
+ &.close {
964
+ left: -298px;
965
+ }
966
+ }
967
+
968
+ .svg-legends-container {
969
+ width:70%;
970
+ height:auto;
971
+ }
972
+
973
+ .pathway-container {
974
+ float: left;
975
+ padding-left: 16px;
976
+ padding-right: 18px;
977
+ max-height: calc(100% - 184px);
978
+ text-align: left;
979
+ overflow: auto;
980
+ border: 1px solid rgb(220, 223, 230);
981
+ padding-bottom: 16px;
982
+ background: #ffffff;
983
+ }
984
+
985
+ .pathways-display-text {
986
+ width: 59px;
987
+ height: 20px;
988
+ color: rgb(48, 49, 51);
989
+ font-size: 14px;
990
+ font-weight: normal;
991
+ line-height: 20px;
992
+ margin-left: 8px;
993
+ }
994
+
995
+ .all-checkbox {
996
+ float: right;
997
+ }
998
+
999
+ .checkbox-container {
1000
+ display: flex;
1001
+ cursor: pointer;
1002
+ }
1003
+
1004
+ .checkbox-group {
1005
+ width: 260px;
1006
+ border: 1px solid rgb(144, 147, 153);
1007
+ border-radius: 4px;
1008
+ background: #ffffff;
1009
+ }
1010
+
1011
+ .my-checkbox {
1012
+ background-color: #fff;
1013
+ width: 100%;
1014
+ }
1015
+
1016
+ .checkbox-group-inner {
1017
+ padding: 18px;
1018
+ }
1019
+
1020
+ .flatmap-marker-help {
1021
+ display: inline-block;
1022
+ }
1023
+
1024
+ ::v-deep .popper-bump-right {
1025
+ left: 30px;
1026
+ }
1027
+
1028
+ ::v-deep .el-checkbox__label {
1029
+ padding-left: 5px;
1030
+ color: $app-primary-color;
1031
+ font-size: 12px;
1032
+ font-weight: 500;
1033
+ letter-spacing: 0px;
1034
+ line-height: 14px;
1035
+ }
1036
+
1037
+ ::v-deep .el-checkbox__input {
1038
+ &.is-indeterminate,
1039
+ &.is-checked {
1040
+ .el-checkbox__inner {
1041
+ background-color: $app-primary-color;
1042
+ border-color: $app-primary-color;
1043
+ }
1044
+ }
1045
+ }
1046
+
1047
+ ::v-deep .el-checkbox__label {
1048
+ color: $app-primary-color !important;
1049
+ }
1050
+
1051
+ .el-dropdown-link {
1052
+ cursor: pointer;
1053
+ color: #409eff;
1054
+ }
1055
+ .el-icon-arrow-down {
1056
+ font-size: 12px;
1057
+ }
1058
+ .demonstration {
1059
+ display: block;
1060
+ color: #8492a6;
1061
+ font-size: 14px;
1062
+ margin-bottom: 20px;
1063
+ }
1064
+
1065
+ .tooltip {
1066
+ display: none;
1067
+ }
1068
+
1069
+ ::v-deep .mapboxgl-popup {
1070
+ max-width: 300px !important;
1071
+ }
1072
+
1073
+ ::v-deep .flatmap-tooltip-popup {
1074
+ &.mapboxgl-popup-anchor-bottom {
1075
+ .mapboxgl-popup-content {
1076
+ margin-bottom: 12px;
1077
+ &::after,
1078
+ &::before {
1079
+ top: 100%;
1080
+ border-width: 12px;
1081
+ }
1082
+ /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1083
+ &::after {
1084
+ margin-top: -1px;
1085
+ border-color: rgb(255, 255, 255) transparent transparent transparent;
1086
+ }
1087
+ /* this border color controlls the outside, thin border */
1088
+ &::before {
1089
+ margin: 0 auto;
1090
+ border-color: $app-primary-color transparent transparent transparent;
1091
+ }
1092
+ }
1093
+ }
1094
+ &.mapboxgl-popup-anchor-top {
1095
+ .mapboxgl-popup-content {
1096
+ margin-top: 18px;
1097
+ &::after,
1098
+ &::before {
1099
+ top: calc(-100% + 6px);
1100
+ border-width: 12px;
1101
+ }
1102
+ /* this border color controlls the color of the triangle (what looks like the fill of the triangle) */
1103
+ &::after {
1104
+ margin-top: 1px;
1105
+ border-color: transparent transparent rgb(255, 255, 255) transparent;
1106
+ }
1107
+ &::before {
1108
+ margin: 0 auto;
1109
+ border-color: transparent transparent $app-primary-color transparent;
1110
+ }
1111
+ }
1112
+ }
1113
+ .mapboxgl-popup-content {
1114
+ border-radius: 4px;
1115
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
1116
+ pointer-events: none;
1117
+ display: none;
1118
+ background: #fff;
1119
+ border: 1px solid $app-primary-color;
1120
+ padding-left: 6px;
1121
+ padding-right: 6px;
1122
+ display: flex;
1123
+ justify-content: center;
1124
+ align-items: center;
1125
+ &::after,
1126
+ &::before {
1127
+ content: "";
1128
+ display: block;
1129
+ position: absolute;
1130
+ width: 0;
1131
+ height: 0;
1132
+ border-style: solid;
1133
+ flex-shrink: 0;
1134
+ }
1135
+ }
1136
+ .mapboxgl-popup-tip {
1137
+ display: none;
1138
+ }
1139
+ }
1140
+
1141
+ ::v-deep .mapboxgl-popup {
1142
+ &.flatmap-marker-popup {
1143
+ box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
1144
+ pointer-events: auto;
1145
+ background: #fff;
1146
+ }
1147
+ }
1148
+
1149
+ /* Fix for chrome bug where under triangle pops up above one on top of it */
1150
+ .selector:not(*:root),
1151
+ ::v-deep.flatmap-tooltip-popup {
1152
+ .mapboxgl-popup-content::after {
1153
+ top: 99.9%;
1154
+ }
1155
+ }
1156
+
1157
+ ::v-deep .flatmap-tooltip-dialog {
1158
+ .mapboxgl-popup-tip {
1159
+ display: none;
1160
+ }
1161
+ }
1162
+
1163
+ ::v-deep .flatmap-marker-popup {
1164
+ .mapboxgl-popup-content {
1165
+ padding: 0px;
1166
+ }
1167
+ }
1168
+
1169
+ ::v-deep .flatmapvuer-popover {
1170
+ .mapboxgl-popup-close-button {
1171
+ position: absolute;
1172
+ right: 0.5em;
1173
+ top: 0;
1174
+ border: 0;
1175
+ border-radius: 0 3px 0 0;
1176
+ cursor: pointer;
1177
+ background-color: transparent;
1178
+ font-size: 2.5em;
1179
+ color: grey;
1180
+ top: 0.95em;
1181
+ }
1182
+ }
1183
+
1184
+ .zoomOut {
1185
+ padding-left: 8px;
1186
+ }
1187
+
1188
+ .fitWindow {
1189
+ padding-left: 8px;
1190
+ }
1191
+
1192
+ .background-colour {
1193
+ bottom: 16px;
1194
+ position: absolute;
1195
+ transition: all 1s ease;
1196
+ }
1197
+ .background-colour.open {
1198
+ left: 322px;
1199
+ }
1200
+ .background-colour.close {
1201
+ left: 24px;
1202
+ }
1203
+
1204
+ ::v-deep .background-popper {
1205
+ padding: 5px 12px;
1206
+ background-color: #ffffff;
1207
+ border: 1px solid $app-primary-color;
1208
+ box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
1209
+ height: 200px;
1210
+ width: 175px;
1211
+ min-width: 175px;
1212
+ &.el-popper[x-placement^="top"] {
1213
+ .popper__arrow {
1214
+ border-top-color: $app-primary-color !important;
1215
+ &::after {
1216
+ border-top-color: #fff !important;
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+
1222
+ .backgroundText {
1223
+ color: rgb(48, 49, 51);
1224
+ font-size: 14px;
1225
+ font-weight: normal;
1226
+ line-height: 20px;
1227
+ }
1228
+
1229
+ .backgroundControl {
1230
+ display: flex;
1231
+ margin-top: 16px;
1232
+ }
1233
+
1234
+ .backgroundChoice {
1235
+ width: 20px;
1236
+ height: 20px;
1237
+ border: 1px solid rgb(144, 147, 153);
1238
+ margin-left: 20px;
1239
+ &.active {
1240
+ border: 2px solid $app-primary-color;
1241
+ }
1242
+ &:hover {
1243
+ cursor: pointer;
1244
+ }
1245
+ &.white {
1246
+ background-color: white;
1247
+ margin-left: 10px;
1248
+ }
1249
+ &.black {
1250
+ background-color: black;
1251
+ }
1252
+ &.lightskyblue {
1253
+ background-color: lightskyblue;
1254
+ }
1255
+ }
1256
+
1257
+ .togglePaths {
1258
+ top: 201px;
1259
+ right: 20px;
1260
+ position: absolute;
1261
+ }
1262
+
1263
+ .icon-button {
1264
+ height: 24px !important;
1265
+ width: 24px !important;
1266
+ color: $app-primary-color;
1267
+ &:hover {
1268
+ cursor: pointer;
1269
+ }
1270
+ }
1271
+
1272
+ ::v-deep .flatmap-popper {
1273
+ padding: 6px 4px;
1274
+ font-size: 12px;
1275
+ color: rgb(48, 49, 51);
1276
+ background-color: #f3ecf6;
1277
+ border: 1px solid $app-primary-color;
1278
+ white-space: nowrap;
1279
+ min-width: unset;
1280
+ &.warning-popper {
1281
+ min-width: 150px;
1282
+ max-width: 400px;
1283
+ word-break: keep-all;
1284
+ white-space: unset;
1285
+ }
1286
+ &.left-popper {
1287
+ .popper__arrow {
1288
+ border-left-color: $app-primary-color !important;
1289
+ &::after {
1290
+ border-left-color: #f3ecf6 !important;
1291
+ }
1292
+ }
1293
+ }
1294
+ &.right-popper {
1295
+ .popper__arrow {
1296
+ border-right-color: $app-primary-color !important;
1297
+ &:after {
1298
+ border-right-color: #f3ecf6 !important;
1299
+ }
1300
+ }
1301
+ }
1302
+ &.el-popper[x-placement^="top"] {
1303
+ .popper__arrow {
1304
+ border-top-color: $app-primary-color !important;
1305
+ &:after {
1306
+ border-top-color: #f3ecf6 !important;
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+
1312
+ ::v-deep .el-loading-spinner {
1313
+ i,
1314
+ .el-loading-text {
1315
+ color: $app-primary-color;
1316
+ }
1317
+ }
1318
+
1319
+ ::v-deep .flatmap-popup-popper {
1320
+ .mapboxgl-popup-tip {
1321
+ border-bottom-color: $app-primary-color;
1322
+ }
1323
+ .mapboxgl-popup-content {
1324
+ padding: 6px 4px;
1325
+ font-size: 12px;
1326
+ color: rgb(48, 49, 51);
1327
+ background-color: #f3ecf6;
1328
+ border: 1px solid $app-primary-color;
1329
+ white-space: nowrap;
1330
+ min-width: unset;
1331
+ .mapboxgl-popup-close-button {
1332
+ display: none;
1333
+ }
1334
+ }
1335
+ }
1336
+
1337
+ ::v-deep .popper-zoomout {
1338
+ padding-right: 13px !important;
1339
+ left: -21px !important;
1340
+ }
1341
+
1342
+ ::v-deep .popper-zoomout {
1343
+ .popper__arrow {
1344
+ left: 53px !important;
1345
+ }
1346
+ }
1347
+
1348
+ ::v-deep .mapboxgl-popup-content {
1349
+ padding: 0px;
1350
+ }
1351
+
1352
+ .bottom-right-control {
1353
+ position: absolute;
1354
+ right: 16px;
1355
+ bottom: 16px;
1356
+ }
1357
+
1358
+ ::v-deep .my-drawer {
1359
+ background: rgba(0, 0, 0, 0);
1360
+ box-shadow: none;
1361
+ }
1362
+
1363
+ .drawer {
1364
+ ::v-deep .el-drawer:focus {
1365
+ outline: none;
1366
+ }
1367
+ }
1368
+
1369
+ .open-drawer,
1370
+ .drawer-button {
1371
+ z-index: 8;
1372
+ width: 20px;
1373
+ height: 40px;
1374
+ border: solid 1px $app-primary-color;
1375
+ text-align: center;
1376
+ vertical-align: middle;
1377
+ cursor: pointer;
1378
+ pointer-events: auto;
1379
+ }
1380
+
1381
+ .open-drawer {
1382
+ position: absolute;
1383
+ left: 0px;
1384
+ background-color: #f7faff;
1385
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.06);
1386
+ }
1387
+
1388
+ .drawer-button {
1389
+ float: left;
1390
+ margin-top: calc(50% - 36px);
1391
+ background-color: #F9F2FC;
1392
+
1393
+ i {
1394
+ font-weight: 600;
1395
+ margin-top: 12px;
1396
+ color: $app-primary-color;
1397
+ transition-delay: 0.9s;
1398
+ }
1399
+ &.open {
1400
+ i {
1401
+ transform: rotate(0deg) scaleY(2);
1402
+ }
1403
+ }
1404
+ &.close {
1405
+ i {
1406
+ transform: rotate(180deg) scaleY(2);
1407
+ }
1408
+ }
1409
+ }
1410
+
1411
+ ::v-deep .mapboxgl-canvas-container {
1412
+ canvas {
1413
+ outline: none;
1414
+ }
1415
+ }
1416
+
1417
+ .backgroundSpacer {
1418
+ border-bottom: 1px solid #e4e7ed;
1419
+ margin-bottom: 10px;
1420
+ }
1421
+
1422
+ .flatmap-radio {
1423
+ ::v-deep label {
1424
+ margin-right: 20px;
1425
+ &:last-child {
1426
+ margin-right: 0px;
1427
+ }
1428
+ }
1429
+ .el-radio__input {
1430
+ &.is-checked {
1431
+ & + .el-radio__label {
1432
+ color: $app-primary-color;
1433
+ }
1434
+ .el-radio__inner {
1435
+ border-color: $app-primary-color;
1436
+ background: $app-primary-color;
1437
+ }
1438
+ }
1439
+ }
1440
+ }
1441
+ </style>
1442
+