@abi-software/map-utilities 1.1.3-beta.1 → 1.1.3-beta.10
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.
- package/dist/map-utilities.js +5892 -5532
- package/dist/map-utilities.umd.cjs +37 -32
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.vue +9 -2
- package/src/components/ConnectivityGraph/ConnectivityGraph.vue +441 -43
- package/src/components/ConnectivityGraph/graph.js +119 -22
- package/src/components/TreeControls/TreeControls.vue +38 -1
- package/src/components.d.ts +5 -0
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -39,6 +39,9 @@ const drawnTypes = [
|
|
|
39
39
|
{ value: "None", label: "None" },
|
|
40
40
|
];
|
|
41
41
|
const showConnectivityGraph = ref(false);
|
|
42
|
+
const connectivityGraphEntry = "ilxtr:neuron-type-aacar-13";
|
|
43
|
+
// const connectivityGraphEntry = "ilxtr:sparc-nlp/kidney/134";
|
|
44
|
+
const mapServer = "https://mapcore-demo.org/curation/flatmap/";
|
|
42
45
|
|
|
43
46
|
onMounted(() => {
|
|
44
47
|
console.log("🚀 ~ onMounted ~ appRef:", appRef.value);
|
|
@@ -513,8 +516,8 @@ function changeHover(value) {
|
|
|
513
516
|
/>
|
|
514
517
|
<ConnectivityGraph
|
|
515
518
|
v-if="showConnectivityGraph"
|
|
516
|
-
entry="
|
|
517
|
-
map-server="
|
|
519
|
+
:entry="connectivityGraphEntry"
|
|
520
|
+
:map-server="mapServer"
|
|
518
521
|
/>
|
|
519
522
|
</div>
|
|
520
523
|
</template>
|
|
@@ -533,6 +536,10 @@ function changeHover(value) {
|
|
|
533
536
|
top: calc(50% - 100px);
|
|
534
537
|
left: calc(50% - 200px);
|
|
535
538
|
}
|
|
539
|
+
.toolbar-container {
|
|
540
|
+
height: 80px;
|
|
541
|
+
position: relative;
|
|
542
|
+
}
|
|
536
543
|
.connectivity-graph {
|
|
537
544
|
width: 600px;
|
|
538
545
|
height: 600px;
|
|
@@ -1,15 +1,113 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="connectivity-graph">
|
|
2
|
+
<div class="connectivity-graph" v-loading="loading">
|
|
3
|
+
|
|
3
4
|
<div ref="graphCanvas" class="graph-canvas"></div>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<div>
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
|
|
6
|
+
<div class="control-panel control-panel-tools">
|
|
7
|
+
<div class="tools" :class="{'zoom-locked': zoomEnabled}">
|
|
8
|
+
<el-tooltip
|
|
9
|
+
:content="resetLabel"
|
|
10
|
+
placement="bottom"
|
|
11
|
+
effect="control-tooltip"
|
|
12
|
+
>
|
|
13
|
+
<el-button
|
|
14
|
+
class="control-button"
|
|
15
|
+
:class="theme"
|
|
16
|
+
size="small"
|
|
17
|
+
@click="reset"
|
|
18
|
+
>
|
|
19
|
+
<el-icon color="white">
|
|
20
|
+
<el-icon-aim />
|
|
21
|
+
</el-icon>
|
|
22
|
+
<span class="visually-hidden">{{ resetLabel }}</span>
|
|
23
|
+
</el-button>
|
|
24
|
+
</el-tooltip>
|
|
25
|
+
|
|
26
|
+
<el-tooltip
|
|
27
|
+
:content="zoomLockLabel"
|
|
28
|
+
placement="bottom"
|
|
29
|
+
effect="control-tooltip"
|
|
30
|
+
>
|
|
31
|
+
<el-button
|
|
32
|
+
class="control-button"
|
|
33
|
+
:class="theme"
|
|
34
|
+
size="small"
|
|
35
|
+
@click="toggleZoom"
|
|
36
|
+
>
|
|
37
|
+
<el-icon color="white">
|
|
38
|
+
<template v-if="zoomEnabled">
|
|
39
|
+
<el-icon-lock />
|
|
40
|
+
</template>
|
|
41
|
+
<template v-else>
|
|
42
|
+
<el-icon-unlock />
|
|
43
|
+
</template>
|
|
44
|
+
</el-icon>
|
|
45
|
+
<span class="visually-hidden">{{ zoomLockLabel }}</span>
|
|
46
|
+
</el-button>
|
|
47
|
+
</el-tooltip>
|
|
48
|
+
|
|
49
|
+
<el-tooltip
|
|
50
|
+
:content="zoomInLabel"
|
|
51
|
+
placement="left"
|
|
52
|
+
effect="control-tooltip"
|
|
53
|
+
>
|
|
54
|
+
<el-button
|
|
55
|
+
class="control-button"
|
|
56
|
+
:class="theme"
|
|
57
|
+
size="small"
|
|
58
|
+
@click="zoomIn"
|
|
59
|
+
>
|
|
60
|
+
<el-icon color="white">
|
|
61
|
+
<el-icon-zoom-in />
|
|
62
|
+
</el-icon>
|
|
63
|
+
<span class="visually-hidden">{{ zoomInLabel }}</span>
|
|
64
|
+
</el-button>
|
|
65
|
+
</el-tooltip>
|
|
66
|
+
|
|
67
|
+
<el-tooltip
|
|
68
|
+
:content="zoomOutLabel"
|
|
69
|
+
placement="left"
|
|
70
|
+
effect="control-tooltip"
|
|
71
|
+
>
|
|
72
|
+
<el-button
|
|
73
|
+
class="control-button"
|
|
74
|
+
:class="theme"
|
|
75
|
+
size="small"
|
|
76
|
+
@click="zoomOut"
|
|
77
|
+
>
|
|
78
|
+
<el-icon color="white">
|
|
79
|
+
<el-icon-zoom-out />
|
|
80
|
+
</el-icon>
|
|
81
|
+
<span class="visually-hidden">{{ zoomOutLabel }}</span>
|
|
82
|
+
</el-button>
|
|
83
|
+
</el-tooltip>
|
|
84
|
+
</div>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<div class="control-panel control-panel-nodes">
|
|
88
|
+
<div class="node-key">
|
|
89
|
+
<!-- <div class="key-head">Node type:</div> -->
|
|
90
|
+
<div class="key-box-container">
|
|
91
|
+
<div class="key-box key-box-dendrite">
|
|
92
|
+
Dendrite
|
|
93
|
+
</div>
|
|
94
|
+
<div class="key-box key-box-node">
|
|
95
|
+
Node
|
|
96
|
+
</div>
|
|
97
|
+
<div class="key-box key-box-axon">
|
|
98
|
+
Axon
|
|
99
|
+
</div>
|
|
100
|
+
<div class="key-box key-box-both">
|
|
101
|
+
Both
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
11
104
|
</div>
|
|
12
105
|
</div>
|
|
106
|
+
|
|
107
|
+
<div class="connectivity-graph-error" v-if="errorMessage">
|
|
108
|
+
{{ errorMessage }}
|
|
109
|
+
</div>
|
|
110
|
+
|
|
13
111
|
</div>
|
|
14
112
|
</template>
|
|
15
113
|
|
|
@@ -17,6 +115,14 @@
|
|
|
17
115
|
import { ConnectivityGraph } from './graph';
|
|
18
116
|
|
|
19
117
|
const MIN_SCHEMA_VERSION = 1.3;
|
|
118
|
+
const CACHE_LIFETIME = 24 * 60 * 60 * 1000; // One day
|
|
119
|
+
const RESET_LABEL = 'Reset position';
|
|
120
|
+
const ZOOM_LOCK_LABEL = 'Lock zoom (to scroll)';
|
|
121
|
+
const ZOOM_UNLOCK_LABEL = 'Unlock zoom';
|
|
122
|
+
const ZOOM_IN_LABEL = 'Zoom in';
|
|
123
|
+
const ZOOM_OUT_LABEL = 'Zoom out';
|
|
124
|
+
const ZOOM_INCREMENT = 0.25;
|
|
125
|
+
const APP_PRIMARY_COLOR = '#8300bf';
|
|
20
126
|
|
|
21
127
|
export default {
|
|
22
128
|
name: 'ConnectivityGraph',
|
|
@@ -35,42 +141,121 @@ export default {
|
|
|
35
141
|
},
|
|
36
142
|
data: function () {
|
|
37
143
|
return {
|
|
38
|
-
|
|
144
|
+
loading: true,
|
|
39
145
|
connectivityGraph: null,
|
|
146
|
+
selectedSource: '',
|
|
147
|
+
pathList: [],
|
|
148
|
+
schemaVersion: '',
|
|
40
149
|
knowledgeByPath: new Map(),
|
|
41
150
|
labelledTerms: new Set(),
|
|
42
151
|
labelCache: new Map(),
|
|
152
|
+
resetLabel: RESET_LABEL,
|
|
153
|
+
zoomLockLabel: ZOOM_LOCK_LABEL,
|
|
154
|
+
zoomInLabel: ZOOM_IN_LABEL,
|
|
155
|
+
zoomOutLabel: ZOOM_OUT_LABEL,
|
|
156
|
+
iconColor: APP_PRIMARY_COLOR,
|
|
157
|
+
zoomEnabled: false,
|
|
158
|
+
errorMessage: '',
|
|
43
159
|
};
|
|
44
160
|
},
|
|
45
161
|
mounted() {
|
|
162
|
+
this.refreshCache();
|
|
163
|
+
this.loadCacheData();
|
|
46
164
|
this.run().then((res) => {
|
|
47
165
|
this.showGraph(this.entry);
|
|
48
166
|
});
|
|
49
167
|
},
|
|
50
168
|
methods: {
|
|
169
|
+
loadCacheData: function () {
|
|
170
|
+
const selectedSource = sessionStorage.getItem('connectivity-graph-source');
|
|
171
|
+
const labelCache = sessionStorage.getItem('connectivity-graph-labels');
|
|
172
|
+
const pathList = sessionStorage.getItem('connectivity-graph-pathlist');
|
|
173
|
+
const schemaVersion = sessionStorage.getItem('connectivity-graph-schema-version');
|
|
174
|
+
|
|
175
|
+
if (selectedSource) {
|
|
176
|
+
this.selectedSource = selectedSource;
|
|
177
|
+
}
|
|
178
|
+
if (pathList) {
|
|
179
|
+
this.pathList = JSON.parse(pathList);
|
|
180
|
+
}
|
|
181
|
+
if (labelCache) {
|
|
182
|
+
const labelCacheObj = JSON.parse(labelCache);
|
|
183
|
+
this.labelCache = new Map(Object.entries(labelCacheObj));
|
|
184
|
+
}
|
|
185
|
+
if (schemaVersion) {
|
|
186
|
+
this.schemaVersion = schemaVersion;
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
removeAllCacheData: function () {
|
|
190
|
+
const keys = [
|
|
191
|
+
'connectivity-graph-expiry',
|
|
192
|
+
'connectivity-graph-source',
|
|
193
|
+
'connectivity-graph-labels',
|
|
194
|
+
'connectivity-graph-pathlist',
|
|
195
|
+
'connectivity-graph-schema-version',
|
|
196
|
+
];
|
|
197
|
+
keys.forEach((key) => {
|
|
198
|
+
sessionStorage.removeItem(key);
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
refreshCache: function () {
|
|
202
|
+
const expiry = sessionStorage.getItem('connectivity-graph-expiry');
|
|
203
|
+
const now = new Date();
|
|
204
|
+
|
|
205
|
+
if (now.getTime() > expiry) {
|
|
206
|
+
this.removeAllCacheData();
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
updateCacheExpiry: function () {
|
|
210
|
+
const now = new Date();
|
|
211
|
+
const expiry = now.getTime() + CACHE_LIFETIME;
|
|
212
|
+
|
|
213
|
+
sessionStorage.setItem('connectivity-graph-expiry', expiry);
|
|
214
|
+
},
|
|
51
215
|
run: async function () {
|
|
52
|
-
|
|
53
|
-
|
|
216
|
+
if (!this.schemaVersion) {
|
|
217
|
+
this.schemaVersion = await this.getSchemaVersion();
|
|
218
|
+
sessionStorage.setItem('connectivity-graph-schema-version', this.schemaVersion);
|
|
219
|
+
this.updateCacheExpiry();
|
|
220
|
+
}
|
|
221
|
+
if (this.schemaVersion < MIN_SCHEMA_VERSION) {
|
|
54
222
|
console.warn('No Server!');
|
|
55
223
|
return;
|
|
56
224
|
}
|
|
57
225
|
this.showSpinner();
|
|
58
|
-
|
|
59
|
-
|
|
226
|
+
if (!this.selectedSource) {
|
|
227
|
+
this.selectedSource = await this.setSourceList();
|
|
228
|
+
sessionStorage.setItem('connectivity-graph-source', this.selectedSource);
|
|
229
|
+
this.updateCacheExpiry();
|
|
230
|
+
}
|
|
231
|
+
await this.setPathList(this.selectedSource);
|
|
60
232
|
this.hideSpinner();
|
|
61
233
|
},
|
|
62
234
|
showGraph: async function (neuronPath) {
|
|
63
235
|
const graphCanvas = this.$refs.graphCanvas;
|
|
236
|
+
|
|
64
237
|
this.showSpinner();
|
|
238
|
+
|
|
65
239
|
this.connectivityGraph = new ConnectivityGraph(this.labelCache, graphCanvas);
|
|
66
240
|
await this.connectivityGraph.addConnectivity(this.knowledgeByPath.get(neuronPath));
|
|
241
|
+
|
|
67
242
|
this.hideSpinner();
|
|
243
|
+
|
|
68
244
|
this.connectivityGraph.showConnectivity(graphCanvas);
|
|
69
|
-
|
|
245
|
+
|
|
246
|
+
this.connectivityGraph.on('tap-node', (event) => {
|
|
247
|
+
const { label } = event.detail;
|
|
248
|
+
const labels = label ? label.split(`\n`) : [];
|
|
249
|
+
/**
|
|
250
|
+
* This event is triggered after a node on the connectivity graph is clicked.
|
|
251
|
+
*/
|
|
252
|
+
this.$emit('tap-node', labels);
|
|
253
|
+
});
|
|
70
254
|
},
|
|
71
255
|
query: async function (sql, params) {
|
|
72
256
|
const url = `${this.mapServer}knowledge/query/`;
|
|
73
|
-
const query = { sql, params }
|
|
257
|
+
const query = { sql, params };
|
|
258
|
+
|
|
74
259
|
try {
|
|
75
260
|
const response = await fetch(url, {
|
|
76
261
|
method: 'POST',
|
|
@@ -81,9 +266,11 @@ export default {
|
|
|
81
266
|
},
|
|
82
267
|
body: JSON.stringify(query)
|
|
83
268
|
});
|
|
269
|
+
|
|
84
270
|
if (!response.ok) {
|
|
85
271
|
throw new Error(`Cannot access ${url}`);
|
|
86
272
|
}
|
|
273
|
+
|
|
87
274
|
return await response.json();
|
|
88
275
|
} catch {
|
|
89
276
|
return {
|
|
@@ -98,38 +285,50 @@ export default {
|
|
|
98
285
|
// Order with most recent first...
|
|
99
286
|
let firstSource = '';
|
|
100
287
|
const sourceList = [];
|
|
288
|
+
|
|
101
289
|
for (const source of sources) {
|
|
102
290
|
if (source) {
|
|
103
291
|
sourceList.push(source);
|
|
292
|
+
|
|
104
293
|
if (firstSource === '') {
|
|
105
294
|
firstSource = source;
|
|
106
295
|
}
|
|
107
296
|
}
|
|
108
297
|
}
|
|
298
|
+
|
|
109
299
|
return firstSource;
|
|
110
300
|
},
|
|
111
|
-
|
|
301
|
+
loadPathData: async function (source) {
|
|
112
302
|
const data = await this.query(
|
|
113
303
|
`select entity, knowledge from knowledge
|
|
114
304
|
where entity like 'ilxtr:%' and source=?
|
|
115
305
|
order by entity`,
|
|
116
306
|
[source]);
|
|
117
|
-
const pathList = [];
|
|
307
|
+
const pathList = data ? data.values : [];
|
|
308
|
+
return pathList;
|
|
309
|
+
},
|
|
310
|
+
setPathList: async function (source) {
|
|
311
|
+
if (!this.pathList.length) {
|
|
312
|
+
this.pathList = await this.loadPathData(source);
|
|
313
|
+
sessionStorage.setItem('connectivity-graph-pathlist', JSON.stringify(this.pathList));
|
|
314
|
+
this.updateCacheExpiry();
|
|
315
|
+
}
|
|
316
|
+
|
|
118
317
|
this.knowledgeByPath.clear();
|
|
119
318
|
this.labelledTerms = new Set();
|
|
120
|
-
|
|
319
|
+
|
|
320
|
+
for (const [key, jsonKnowledge] of this.pathList) {
|
|
121
321
|
const knowledge = JSON.parse(jsonKnowledge);
|
|
122
322
|
if ('connectivity' in knowledge) {
|
|
123
|
-
const label = knowledge.label || key;
|
|
124
|
-
const shortLabel = (label === key.slice(6).replace('-prime', "'").replaceAll('-', ' '))
|
|
125
|
-
? ''
|
|
126
|
-
: (label.length < 50) ? label : `${label.slice(0, 50)}...`;
|
|
127
|
-
pathList.push(key);
|
|
128
323
|
this.knowledgeByPath.set(key, knowledge);
|
|
129
324
|
this.cacheLabels(knowledge);
|
|
130
325
|
}
|
|
131
326
|
}
|
|
132
|
-
|
|
327
|
+
|
|
328
|
+
if (!this.labelCache.size) {
|
|
329
|
+
await this.getCachedTermLabels();
|
|
330
|
+
}
|
|
331
|
+
|
|
133
332
|
return '';
|
|
134
333
|
},
|
|
135
334
|
getSchemaVersion: async function () {
|
|
@@ -146,9 +345,11 @@ export default {
|
|
|
146
345
|
"Content-Type": "application/json"
|
|
147
346
|
}
|
|
148
347
|
});
|
|
348
|
+
|
|
149
349
|
if (!response.ok) {
|
|
150
350
|
console.error(`Cannot access ${url}`);
|
|
151
351
|
}
|
|
352
|
+
|
|
152
353
|
return await response.json();
|
|
153
354
|
} catch {
|
|
154
355
|
return null;
|
|
@@ -156,14 +357,25 @@ export default {
|
|
|
156
357
|
},
|
|
157
358
|
getCachedTermLabels: async function () {
|
|
158
359
|
if (this.labelledTerms.size) {
|
|
159
|
-
const
|
|
160
|
-
select entity,
|
|
161
|
-
|
|
360
|
+
const data = await this.query(
|
|
361
|
+
`select entity, knowledge from knowledge
|
|
362
|
+
where entity in (?${', ?'.repeat(this.labelledTerms.size-1)})
|
|
363
|
+
order by source desc`,
|
|
162
364
|
[...this.labelledTerms.values()]
|
|
163
365
|
);
|
|
164
|
-
|
|
165
|
-
|
|
366
|
+
|
|
367
|
+
let last_entity = null;
|
|
368
|
+
for (const [key, jsonKnowledge] of data.values) {
|
|
369
|
+
if (key !== last_entity) {
|
|
370
|
+
const knowledge = JSON.parse(jsonKnowledge);
|
|
371
|
+
this.labelCache.set(key, knowledge['label'] || key);
|
|
372
|
+
last_entity = key;
|
|
373
|
+
}
|
|
166
374
|
}
|
|
375
|
+
|
|
376
|
+
const labelCacheObj = Object.fromEntries(this.labelCache);
|
|
377
|
+
sessionStorage.setItem('connectivity-graph-labels', JSON.stringify(labelCacheObj));
|
|
378
|
+
this.updateCacheExpiry();
|
|
167
379
|
}
|
|
168
380
|
},
|
|
169
381
|
cacheNodeLabels: function (node) {
|
|
@@ -178,10 +390,34 @@ export default {
|
|
|
178
390
|
}
|
|
179
391
|
},
|
|
180
392
|
showSpinner: function () {
|
|
181
|
-
|
|
393
|
+
this.loading = true;
|
|
182
394
|
},
|
|
183
395
|
hideSpinner: function () {
|
|
184
|
-
|
|
396
|
+
this.loading = false;
|
|
397
|
+
},
|
|
398
|
+
reset: function () {
|
|
399
|
+
this.connectivityGraph.reset();
|
|
400
|
+
},
|
|
401
|
+
zoomIn: function () {
|
|
402
|
+
this.connectivityGraph.zoom(ZOOM_INCREMENT);
|
|
403
|
+
},
|
|
404
|
+
zoomOut: function () {
|
|
405
|
+
this.connectivityGraph.zoom(-ZOOM_INCREMENT);
|
|
406
|
+
},
|
|
407
|
+
/**
|
|
408
|
+
* Enable/disable user zoom for scrolling
|
|
409
|
+
*/
|
|
410
|
+
toggleZoom: function () {
|
|
411
|
+
this.zoomEnabled = !this.zoomEnabled;
|
|
412
|
+
this.zoomLockLabel = this.zoomEnabled ? ZOOM_UNLOCK_LABEL : ZOOM_LOCK_LABEL;
|
|
413
|
+
this.connectivityGraph.enableZoom(!this.zoomEnabled);
|
|
414
|
+
},
|
|
415
|
+
showErrorMessage: function (errorMessage) {
|
|
416
|
+
this.errorMessage = errorMessage;
|
|
417
|
+
// Show error for 3 seconds
|
|
418
|
+
setTimeout(() => {
|
|
419
|
+
this.errorMessage = '';
|
|
420
|
+
}, 3000);
|
|
185
421
|
},
|
|
186
422
|
},
|
|
187
423
|
};
|
|
@@ -201,30 +437,192 @@ export default {
|
|
|
201
437
|
border: solid 1px #e4e7ed;
|
|
202
438
|
}
|
|
203
439
|
|
|
204
|
-
.
|
|
440
|
+
.control-panel {
|
|
205
441
|
position: absolute;
|
|
206
|
-
top: 1rem;
|
|
207
442
|
right: 1rem;
|
|
208
|
-
border: 1px solid $app-primary-color;
|
|
209
|
-
padding: 4px;
|
|
210
|
-
background-color: rgba(240, 240, 240, 0.8);
|
|
211
443
|
|
|
212
|
-
|
|
213
|
-
|
|
444
|
+
&-tools {
|
|
445
|
+
top: 1rem;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
&-nodes {
|
|
449
|
+
bottom: 1rem;
|
|
214
450
|
}
|
|
215
451
|
}
|
|
216
452
|
|
|
453
|
+
.node-key {
|
|
454
|
+
padding: 0.5rem;
|
|
455
|
+
font-size: 12px;
|
|
456
|
+
border: 1px solid var(--el-border-color);
|
|
457
|
+
background-color: rgba(#f7faff, 0.85);
|
|
458
|
+
}
|
|
459
|
+
|
|
217
460
|
.key-head {
|
|
218
461
|
text-align: center;
|
|
219
462
|
font-weight: bold;
|
|
220
|
-
border-bottom: 1px solid
|
|
463
|
+
border-bottom: 1px solid var(--el-border-color);
|
|
221
464
|
padding-bottom: 4px;
|
|
222
|
-
margin-bottom:
|
|
465
|
+
margin-bottom: 0.5rem;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.key-box-container {
|
|
469
|
+
display: flex;
|
|
470
|
+
flex-direction: row;
|
|
471
|
+
gap: 1rem;
|
|
223
472
|
}
|
|
224
473
|
|
|
225
474
|
.key-box {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
475
|
+
display: flex;
|
|
476
|
+
align-items: center;
|
|
477
|
+
gap: 0.35rem;
|
|
478
|
+
position: relative;
|
|
479
|
+
|
|
480
|
+
&::before {
|
|
481
|
+
content: "";
|
|
482
|
+
display: block;
|
|
483
|
+
width: 14px;
|
|
484
|
+
height: 14px;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
&-node::before,
|
|
488
|
+
&-both::before {
|
|
489
|
+
border: 1px solid gray;
|
|
490
|
+
border-radius: var(--el-border-radius-small);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// &-node {
|
|
494
|
+
// background: #80F0F0;
|
|
495
|
+
// }
|
|
496
|
+
|
|
497
|
+
// &-both {
|
|
498
|
+
// background: gray;
|
|
499
|
+
// }
|
|
500
|
+
|
|
501
|
+
&-axon::before {
|
|
502
|
+
border: 1px solid gray;
|
|
503
|
+
border-radius: var(--el-border-radius-small);
|
|
504
|
+
transform: rotate(45deg);
|
|
505
|
+
// background: green;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
&-dendrite::before {
|
|
509
|
+
border: 1px solid gray;
|
|
510
|
+
border-radius: 50%;
|
|
511
|
+
// background: red;
|
|
512
|
+
}
|
|
229
513
|
}
|
|
514
|
+
|
|
515
|
+
.tools {
|
|
516
|
+
display: grid;
|
|
517
|
+
grid-template-columns: repeat(2, 1fr);
|
|
518
|
+
grid-template-rows: repeat(3, 1fr);
|
|
519
|
+
gap: 0.5rem;
|
|
520
|
+
|
|
521
|
+
:deep(.el-button:nth-child(3)) {
|
|
522
|
+
grid-column: 2;
|
|
523
|
+
grid-row: 2;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
:deep(.el-button:nth-child(4)) {
|
|
527
|
+
grid-column: 2;
|
|
528
|
+
grid-row: 3;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
:deep(.el-button:nth-child(3)),
|
|
532
|
+
:deep(.el-button:nth-child(4)) {
|
|
533
|
+
opacity: 0;
|
|
534
|
+
visibility: hidden;
|
|
535
|
+
pointer-events: none;
|
|
536
|
+
transform: translateY(-100%);
|
|
537
|
+
transition: all 0.25s ease;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
&.zoom-locked {
|
|
541
|
+
:deep(.el-button:nth-child(3)),
|
|
542
|
+
:deep(.el-button:nth-child(4)) {
|
|
543
|
+
opacity: 1;
|
|
544
|
+
visibility: visible;
|
|
545
|
+
pointer-events: initial;
|
|
546
|
+
transform: translateY(0%);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
:deep(.el-button:nth-child(4)) {
|
|
550
|
+
transition-delay: 0.125s;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.control-button {
|
|
556
|
+
width: 24px;
|
|
557
|
+
height: 24px;
|
|
558
|
+
margin: 0 !important;
|
|
559
|
+
padding: 0 !important;
|
|
560
|
+
font-size: 16px !important;
|
|
561
|
+
border-color: $app-primary-color !important;
|
|
562
|
+
border-radius: 50%;
|
|
563
|
+
background: $app-primary-color !important;
|
|
564
|
+
transition: all 0.25s ease;
|
|
565
|
+
|
|
566
|
+
svg {
|
|
567
|
+
margin: 0;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
&,
|
|
571
|
+
&:focus,
|
|
572
|
+
&:active {
|
|
573
|
+
box-shadow: none !important;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
:deep(.cy-graph-tooltip) {
|
|
578
|
+
padding: 4px 10px;
|
|
579
|
+
font-family: Asap;
|
|
580
|
+
font-size: 12px;
|
|
581
|
+
background: #f3ecf6 !important;
|
|
582
|
+
border: 1px solid $app-primary-color;
|
|
583
|
+
border-radius: var(--el-border-radius-base);
|
|
584
|
+
position: relative;
|
|
585
|
+
top: 0;
|
|
586
|
+
left: 0;
|
|
587
|
+
width: fit-content;
|
|
588
|
+
z-index: 1;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.connectivity-graph-error {
|
|
592
|
+
position: absolute;
|
|
593
|
+
top: 1rem;
|
|
594
|
+
left: 50%;
|
|
595
|
+
transform: translateX(-50%);
|
|
596
|
+
width: fit-content;
|
|
597
|
+
font-size: 12px;
|
|
598
|
+
padding: 0.25rem 0.5rem;
|
|
599
|
+
background-color: var(--el-color-error-light-9);
|
|
600
|
+
border-radius: var(--el-border-radius-small);
|
|
601
|
+
border: 1px solid var(--el-color-error);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.visually-hidden {
|
|
605
|
+
clip: rect(0 0 0 0);
|
|
606
|
+
clip-path: inset(50%);
|
|
607
|
+
height: 1px;
|
|
608
|
+
overflow: hidden;
|
|
609
|
+
position: absolute;
|
|
610
|
+
white-space: nowrap;
|
|
611
|
+
width: 1px;
|
|
612
|
+
}
|
|
613
|
+
</style>
|
|
614
|
+
|
|
615
|
+
<style lang="scss">
|
|
616
|
+
.el-popper.is-control-tooltip {
|
|
617
|
+
padding: 4px 10px;
|
|
618
|
+
font-family: Asap;
|
|
619
|
+
background: #f3ecf6 !important;
|
|
620
|
+
border: 1px solid $app-primary-color;
|
|
621
|
+
|
|
622
|
+
& .el-popper__arrow::before {
|
|
623
|
+
border: 1px solid;
|
|
624
|
+
border-color: $app-primary-color;
|
|
625
|
+
background: #f3ecf6;
|
|
626
|
+
}
|
|
627
|
+
}
|
|
230
628
|
</style>
|