@abi-software/map-utilities 1.1.3-beta.2 → 1.1.3-beta.4
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 +1979 -1944
- package/dist/map-utilities.umd.cjs +23 -23
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/App.vue +4 -0
- package/src/components/ConnectivityGraph/ConnectivityGraph.vue +126 -23
- package/src/components/ConnectivityGraph/graph.js +11 -12
package/package.json
CHANGED
package/src/App.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="connectivity-graph">
|
|
2
|
+
<div class="connectivity-graph" v-loading="loading">
|
|
3
3
|
<div ref="graphCanvas" class="graph-canvas"></div>
|
|
4
4
|
<div class="control-panel">
|
|
5
5
|
<div class="node-key">
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
import { ConnectivityGraph } from './graph';
|
|
61
61
|
|
|
62
62
|
const MIN_SCHEMA_VERSION = 1.3;
|
|
63
|
+
const CACHE_LIFETIME = 24 * 60 * 60 * 1000; // One day
|
|
63
64
|
const RESET_LABEL = 'Reset position';
|
|
64
65
|
const ZOOM_LOCK_LABEL = 'Lock zoom (to scroll)';
|
|
65
66
|
const ZOOM_UNLOCK_LABEL = 'Unlock zoom';
|
|
@@ -82,8 +83,11 @@ export default {
|
|
|
82
83
|
},
|
|
83
84
|
data: function () {
|
|
84
85
|
return {
|
|
85
|
-
|
|
86
|
+
loading: true,
|
|
86
87
|
connectivityGraph: null,
|
|
88
|
+
selectedSource: '',
|
|
89
|
+
pathList: [],
|
|
90
|
+
schemaVersion: '',
|
|
87
91
|
knowledgeByPath: new Map(),
|
|
88
92
|
labelledTerms: new Set(),
|
|
89
93
|
labelCache: new Map(),
|
|
@@ -94,34 +98,94 @@ export default {
|
|
|
94
98
|
};
|
|
95
99
|
},
|
|
96
100
|
mounted() {
|
|
101
|
+
this.refreshCache();
|
|
102
|
+
this.loadCacheData();
|
|
97
103
|
this.run().then((res) => {
|
|
98
104
|
this.showGraph(this.entry);
|
|
99
105
|
});
|
|
100
106
|
},
|
|
101
107
|
methods: {
|
|
108
|
+
loadCacheData: function () {
|
|
109
|
+
const selectedSource = sessionStorage.getItem('connectivity-graph-source');
|
|
110
|
+
const labelCache = sessionStorage.getItem('connectivity-graph-labels');
|
|
111
|
+
const pathList = sessionStorage.getItem('connectivity-graph-pathlist');
|
|
112
|
+
const schemaVersion = sessionStorage.getItem('connectivity-graph-schema-version');
|
|
113
|
+
|
|
114
|
+
if (selectedSource) {
|
|
115
|
+
this.selectedSource = selectedSource;
|
|
116
|
+
}
|
|
117
|
+
if (pathList) {
|
|
118
|
+
this.pathList = JSON.parse(pathList);
|
|
119
|
+
}
|
|
120
|
+
if (labelCache) {
|
|
121
|
+
const labelCacheObj = JSON.parse(labelCache);
|
|
122
|
+
this.labelCache = new Map(Object.entries(labelCacheObj));
|
|
123
|
+
}
|
|
124
|
+
if (schemaVersion) {
|
|
125
|
+
this.schemaVersion = schemaVersion;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
removeAllCacheData: function () {
|
|
129
|
+
const keys = [
|
|
130
|
+
'connectivity-graph-expiry',
|
|
131
|
+
'connectivity-graph-source',
|
|
132
|
+
'connectivity-graph-labels',
|
|
133
|
+
'connectivity-graph-pathlist',
|
|
134
|
+
'connectivity-graph-schema-version',
|
|
135
|
+
];
|
|
136
|
+
keys.forEach((key) => {
|
|
137
|
+
sessionStorage.removeItem(key);
|
|
138
|
+
});
|
|
139
|
+
},
|
|
140
|
+
refreshCache: function () {
|
|
141
|
+
const expiry = sessionStorage.getItem('connectivity-graph-expiry');
|
|
142
|
+
const now = new Date();
|
|
143
|
+
|
|
144
|
+
if (now.getTime() > expiry) {
|
|
145
|
+
this.removeAllCacheData();
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
updateCacheExpiry: function () {
|
|
149
|
+
const now = new Date();
|
|
150
|
+
const expiry = now.getTime() + CACHE_LIFETIME;
|
|
151
|
+
|
|
152
|
+
sessionStorage.setItem('connectivity-graph-expiry', expiry);
|
|
153
|
+
},
|
|
102
154
|
run: async function () {
|
|
103
|
-
|
|
104
|
-
|
|
155
|
+
if (!this.schemaVersion) {
|
|
156
|
+
this.schemaVersion = await this.getSchemaVersion();
|
|
157
|
+
sessionStorage.setItem('connectivity-graph-schema-version', this.schemaVersion);
|
|
158
|
+
this.updateCacheExpiry();
|
|
159
|
+
}
|
|
160
|
+
if (this.schemaVersion < MIN_SCHEMA_VERSION) {
|
|
105
161
|
console.warn('No Server!');
|
|
106
162
|
return;
|
|
107
163
|
}
|
|
108
164
|
this.showSpinner();
|
|
109
|
-
|
|
110
|
-
|
|
165
|
+
if (!this.selectedSource) {
|
|
166
|
+
this.selectedSource = await this.setSourceList();
|
|
167
|
+
sessionStorage.setItem('connectivity-graph-source', this.selectedSource);
|
|
168
|
+
this.updateCacheExpiry();
|
|
169
|
+
}
|
|
170
|
+
await this.setPathList(this.selectedSource);
|
|
111
171
|
this.hideSpinner();
|
|
112
172
|
},
|
|
113
173
|
showGraph: async function (neuronPath) {
|
|
114
174
|
const graphCanvas = this.$refs.graphCanvas;
|
|
175
|
+
|
|
115
176
|
this.showSpinner();
|
|
177
|
+
|
|
116
178
|
this.connectivityGraph = new ConnectivityGraph(this.labelCache, graphCanvas);
|
|
117
179
|
await this.connectivityGraph.addConnectivity(this.knowledgeByPath.get(neuronPath));
|
|
180
|
+
|
|
118
181
|
this.hideSpinner();
|
|
182
|
+
|
|
119
183
|
this.connectivityGraph.showConnectivity(graphCanvas);
|
|
120
|
-
this.currentPath = neuronPath
|
|
121
184
|
},
|
|
122
185
|
query: async function (sql, params) {
|
|
123
186
|
const url = `${this.mapServer}knowledge/query/`;
|
|
124
|
-
const query = { sql, params }
|
|
187
|
+
const query = { sql, params };
|
|
188
|
+
|
|
125
189
|
try {
|
|
126
190
|
const response = await fetch(url, {
|
|
127
191
|
method: 'POST',
|
|
@@ -132,9 +196,11 @@ export default {
|
|
|
132
196
|
},
|
|
133
197
|
body: JSON.stringify(query)
|
|
134
198
|
});
|
|
199
|
+
|
|
135
200
|
if (!response.ok) {
|
|
136
201
|
throw new Error(`Cannot access ${url}`);
|
|
137
202
|
}
|
|
203
|
+
|
|
138
204
|
return await response.json();
|
|
139
205
|
} catch {
|
|
140
206
|
return {
|
|
@@ -149,38 +215,50 @@ export default {
|
|
|
149
215
|
// Order with most recent first...
|
|
150
216
|
let firstSource = '';
|
|
151
217
|
const sourceList = [];
|
|
218
|
+
|
|
152
219
|
for (const source of sources) {
|
|
153
220
|
if (source) {
|
|
154
221
|
sourceList.push(source);
|
|
222
|
+
|
|
155
223
|
if (firstSource === '') {
|
|
156
224
|
firstSource = source;
|
|
157
225
|
}
|
|
158
226
|
}
|
|
159
227
|
}
|
|
228
|
+
|
|
160
229
|
return firstSource;
|
|
161
230
|
},
|
|
162
|
-
|
|
231
|
+
loadPathData: async function (source) {
|
|
163
232
|
const data = await this.query(
|
|
164
233
|
`select entity, knowledge from knowledge
|
|
165
234
|
where entity like 'ilxtr:%' and source=?
|
|
166
235
|
order by entity`,
|
|
167
236
|
[source]);
|
|
168
|
-
const pathList = [];
|
|
237
|
+
const pathList = data ? data.values : [];
|
|
238
|
+
return pathList;
|
|
239
|
+
},
|
|
240
|
+
setPathList: async function (source) {
|
|
241
|
+
if (!this.pathList.length) {
|
|
242
|
+
this.pathList = await this.loadPathData(source);
|
|
243
|
+
sessionStorage.setItem('connectivity-graph-pathlist', JSON.stringify(this.pathList));
|
|
244
|
+
this.updateCacheExpiry();
|
|
245
|
+
}
|
|
246
|
+
|
|
169
247
|
this.knowledgeByPath.clear();
|
|
170
248
|
this.labelledTerms = new Set();
|
|
171
|
-
|
|
249
|
+
|
|
250
|
+
for (const [key, jsonKnowledge] of this.pathList) {
|
|
172
251
|
const knowledge = JSON.parse(jsonKnowledge);
|
|
173
252
|
if ('connectivity' in knowledge) {
|
|
174
|
-
const label = knowledge.label || key;
|
|
175
|
-
const shortLabel = (label === key.slice(6).replace('-prime', "'").replaceAll('-', ' '))
|
|
176
|
-
? ''
|
|
177
|
-
: (label.length < 50) ? label : `${label.slice(0, 50)}...`;
|
|
178
|
-
pathList.push(key);
|
|
179
253
|
this.knowledgeByPath.set(key, knowledge);
|
|
180
254
|
this.cacheLabels(knowledge);
|
|
181
255
|
}
|
|
182
256
|
}
|
|
183
|
-
|
|
257
|
+
|
|
258
|
+
if (!this.labelCache.size) {
|
|
259
|
+
await this.getCachedTermLabels();
|
|
260
|
+
}
|
|
261
|
+
|
|
184
262
|
return '';
|
|
185
263
|
},
|
|
186
264
|
getSchemaVersion: async function () {
|
|
@@ -197,9 +275,11 @@ export default {
|
|
|
197
275
|
"Content-Type": "application/json"
|
|
198
276
|
}
|
|
199
277
|
});
|
|
278
|
+
|
|
200
279
|
if (!response.ok) {
|
|
201
280
|
console.error(`Cannot access ${url}`);
|
|
202
281
|
}
|
|
282
|
+
|
|
203
283
|
return await response.json();
|
|
204
284
|
} catch {
|
|
205
285
|
return null;
|
|
@@ -207,14 +287,19 @@ export default {
|
|
|
207
287
|
},
|
|
208
288
|
getCachedTermLabels: async function () {
|
|
209
289
|
if (this.labelledTerms.size) {
|
|
210
|
-
const
|
|
290
|
+
const data = await this.query(`
|
|
211
291
|
select entity, label from labels
|
|
212
292
|
where entity in (?${', ?'.repeat(this.labelledTerms.size-1)})`,
|
|
213
293
|
[...this.labelledTerms.values()]
|
|
214
294
|
);
|
|
215
|
-
|
|
295
|
+
|
|
296
|
+
for (const termLabel of data.values) {
|
|
216
297
|
this.labelCache.set(termLabel[0], termLabel[1]);
|
|
217
298
|
}
|
|
299
|
+
|
|
300
|
+
const labelCacheObj = Object.fromEntries(this.labelCache);
|
|
301
|
+
sessionStorage.setItem('connectivity-graph-labels', JSON.stringify(labelCacheObj));
|
|
302
|
+
this.updateCacheExpiry();
|
|
218
303
|
}
|
|
219
304
|
},
|
|
220
305
|
cacheNodeLabels: function (node) {
|
|
@@ -229,10 +314,10 @@ export default {
|
|
|
229
314
|
}
|
|
230
315
|
},
|
|
231
316
|
showSpinner: function () {
|
|
232
|
-
|
|
317
|
+
this.loading = true;
|
|
233
318
|
},
|
|
234
319
|
hideSpinner: function () {
|
|
235
|
-
|
|
320
|
+
this.loading = false;
|
|
236
321
|
},
|
|
237
322
|
reset: function () {
|
|
238
323
|
this.connectivityGraph.reset();
|
|
@@ -272,7 +357,7 @@ export default {
|
|
|
272
357
|
.node-key {
|
|
273
358
|
border: 1px solid $app-primary-color;
|
|
274
359
|
padding: 4px;
|
|
275
|
-
background-color: rgba(
|
|
360
|
+
background-color: rgba(#f7faff, 0.85);
|
|
276
361
|
|
|
277
362
|
div div {
|
|
278
363
|
width: 90px;
|
|
@@ -294,7 +379,7 @@ export default {
|
|
|
294
379
|
}
|
|
295
380
|
|
|
296
381
|
.tools {
|
|
297
|
-
margin-top:
|
|
382
|
+
margin-top: 0.5rem;
|
|
298
383
|
display: flex;
|
|
299
384
|
flex-direction: row;
|
|
300
385
|
gap: 0.5rem;
|
|
@@ -310,6 +395,10 @@ export default {
|
|
|
310
395
|
background: $app-primary-color !important;
|
|
311
396
|
transition: all 0.25s ease;
|
|
312
397
|
|
|
398
|
+
svg {
|
|
399
|
+
margin: 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
313
402
|
&,
|
|
314
403
|
&:focus,
|
|
315
404
|
&:active {
|
|
@@ -321,6 +410,20 @@ export default {
|
|
|
321
410
|
}
|
|
322
411
|
}
|
|
323
412
|
|
|
413
|
+
:deep(.cy-graph-tooltip) {
|
|
414
|
+
padding: 4px 10px;
|
|
415
|
+
font-family: Asap;
|
|
416
|
+
font-size: 12px;
|
|
417
|
+
background: #f3ecf6 !important;
|
|
418
|
+
border: 1px solid $app-primary-color;
|
|
419
|
+
border-radius: var(--el-border-radius-base);
|
|
420
|
+
position: relative;
|
|
421
|
+
top: 0;
|
|
422
|
+
left: 0;
|
|
423
|
+
width: fit-content;
|
|
424
|
+
z-index: 1;
|
|
425
|
+
}
|
|
426
|
+
|
|
324
427
|
.visually-hidden {
|
|
325
428
|
clip: rect(0 0 0 0);
|
|
326
429
|
clip-path: inset(50%);
|
|
@@ -27,7 +27,7 @@ import cytoscape from 'cytoscape'
|
|
|
27
27
|
|
|
28
28
|
export class ConnectivityGraph
|
|
29
29
|
{
|
|
30
|
-
|
|
30
|
+
cyg = null
|
|
31
31
|
nodes = []
|
|
32
32
|
edges = []
|
|
33
33
|
axons = []
|
|
@@ -69,31 +69,31 @@ export class ConnectivityGraph
|
|
|
69
69
|
showConnectivity(graphCanvas)
|
|
70
70
|
//================
|
|
71
71
|
{
|
|
72
|
-
this.
|
|
72
|
+
this.cyg = new CytoscapeGraph(this, graphCanvas)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
clearConnectivity()
|
|
76
76
|
//=================
|
|
77
77
|
{
|
|
78
|
-
if (this.cy) {
|
|
79
|
-
this.cy.remove()
|
|
80
|
-
this.cy = null
|
|
78
|
+
if (this.cyg?.cy) {
|
|
79
|
+
this.cyg.cy.remove()
|
|
80
|
+
this.cyg.cy = null
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
reset()
|
|
85
85
|
//=================
|
|
86
86
|
{
|
|
87
|
-
if (this.
|
|
88
|
-
this.
|
|
87
|
+
if (this.cyg?.cy) {
|
|
88
|
+
this.cyg.cy.reset()
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
enableZoom(option)
|
|
93
93
|
//=================
|
|
94
94
|
{
|
|
95
|
-
if (this.
|
|
96
|
-
this.
|
|
95
|
+
if (this.cyg?.cy) {
|
|
96
|
+
this.cyg.cy.userZoomingEnabled(option)
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -195,7 +195,6 @@ class CytoscapeGraph
|
|
|
195
195
|
|
|
196
196
|
constructor(connectivityGraph, graphCanvas)
|
|
197
197
|
{
|
|
198
|
-
// const graphCanvas = document.getElementById('graph-canvas')
|
|
199
198
|
this.cy = cytoscape({
|
|
200
199
|
container: graphCanvas,
|
|
201
200
|
elements: connectivityGraph.elements,
|
|
@@ -214,9 +213,9 @@ class CytoscapeGraph
|
|
|
214
213
|
.on('position', 'node', this.moveNode.bind(this))
|
|
215
214
|
|
|
216
215
|
this.tooltip = document.createElement('div')
|
|
217
|
-
this.tooltip.
|
|
216
|
+
this.tooltip.className = 'cy-graph-tooltip'
|
|
218
217
|
this.tooltip.hidden = true
|
|
219
|
-
|
|
218
|
+
graphCanvas?.lastChild?.appendChild(this.tooltip)
|
|
220
219
|
}
|
|
221
220
|
|
|
222
221
|
remove()
|