@abi-software/map-utilities 1.1.3-beta.3 → 1.1.3-beta.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abi-software/map-utilities",
3
- "version": "1.1.3-beta.3",
3
+ "version": "1.1.3-beta.5",
4
4
  "files": [
5
5
  "dist/*",
6
6
  "src/*",
package/src/App.vue CHANGED
@@ -533,6 +533,10 @@ function changeHover(value) {
533
533
  top: calc(50% - 100px);
534
534
  left: calc(50% - 200px);
535
535
  }
536
+ .toolbar-container {
537
+ height: 80px;
538
+ position: relative;
539
+ }
536
540
  .connectivity-graph {
537
541
  width: 600px;
538
542
  height: 600px;
@@ -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';
@@ -97,6 +98,7 @@ export default {
97
98
  };
98
99
  },
99
100
  mounted() {
101
+ this.refreshCache();
100
102
  this.loadCacheData();
101
103
  this.run().then((res) => {
102
104
  this.showGraph(this.entry);
@@ -123,10 +125,37 @@ export default {
123
125
  this.schemaVersion = schemaVersion;
124
126
  }
125
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
+ },
126
154
  run: async function () {
127
155
  if (!this.schemaVersion) {
128
156
  this.schemaVersion = await this.getSchemaVersion();
129
157
  sessionStorage.setItem('connectivity-graph-schema-version', this.schemaVersion);
158
+ this.updateCacheExpiry();
130
159
  }
131
160
  if (this.schemaVersion < MIN_SCHEMA_VERSION) {
132
161
  console.warn('No Server!');
@@ -136,22 +165,36 @@ export default {
136
165
  if (!this.selectedSource) {
137
166
  this.selectedSource = await this.setSourceList();
138
167
  sessionStorage.setItem('connectivity-graph-source', this.selectedSource);
168
+ this.updateCacheExpiry();
139
169
  }
140
- await this.setPathList(this.selectedSource)
170
+ await this.setPathList(this.selectedSource);
141
171
  this.hideSpinner();
142
172
  },
143
173
  showGraph: async function (neuronPath) {
144
174
  const graphCanvas = this.$refs.graphCanvas;
175
+
145
176
  this.showSpinner();
177
+
146
178
  this.connectivityGraph = new ConnectivityGraph(this.labelCache, graphCanvas);
147
179
  await this.connectivityGraph.addConnectivity(this.knowledgeByPath.get(neuronPath));
180
+
148
181
  this.hideSpinner();
182
+
149
183
  this.connectivityGraph.showConnectivity(graphCanvas);
150
- this.currentPath = neuronPath
184
+
185
+ this.connectivityGraph.on('tap-node', (event) => {
186
+ const { label } = event.detail;
187
+ const labels = label.split(`\n`);
188
+ /**
189
+ * This event is triggered after a node on the connectivity graph is clicked.
190
+ */
191
+ this.$emit('tap-node', labels);
192
+ });
151
193
  },
152
194
  query: async function (sql, params) {
153
195
  const url = `${this.mapServer}knowledge/query/`;
154
- const query = { sql, params }
196
+ const query = { sql, params };
197
+
155
198
  try {
156
199
  const response = await fetch(url, {
157
200
  method: 'POST',
@@ -162,9 +205,11 @@ export default {
162
205
  },
163
206
  body: JSON.stringify(query)
164
207
  });
208
+
165
209
  if (!response.ok) {
166
210
  throw new Error(`Cannot access ${url}`);
167
211
  }
212
+
168
213
  return await response.json();
169
214
  } catch {
170
215
  return {
@@ -179,14 +224,17 @@ export default {
179
224
  // Order with most recent first...
180
225
  let firstSource = '';
181
226
  const sourceList = [];
227
+
182
228
  for (const source of sources) {
183
229
  if (source) {
184
230
  sourceList.push(source);
231
+
185
232
  if (firstSource === '') {
186
233
  firstSource = source;
187
234
  }
188
235
  }
189
236
  }
237
+
190
238
  return firstSource;
191
239
  },
192
240
  loadPathData: async function (source) {
@@ -202,9 +250,12 @@ export default {
202
250
  if (!this.pathList.length) {
203
251
  this.pathList = await this.loadPathData(source);
204
252
  sessionStorage.setItem('connectivity-graph-pathlist', JSON.stringify(this.pathList));
253
+ this.updateCacheExpiry();
205
254
  }
255
+
206
256
  this.knowledgeByPath.clear();
207
257
  this.labelledTerms = new Set();
258
+
208
259
  for (const [key, jsonKnowledge] of this.pathList) {
209
260
  const knowledge = JSON.parse(jsonKnowledge);
210
261
  if ('connectivity' in knowledge) {
@@ -216,6 +267,7 @@ export default {
216
267
  if (!this.labelCache.size) {
217
268
  await this.getCachedTermLabels();
218
269
  }
270
+
219
271
  return '';
220
272
  },
221
273
  getSchemaVersion: async function () {
@@ -232,9 +284,11 @@ export default {
232
284
  "Content-Type": "application/json"
233
285
  }
234
286
  });
287
+
235
288
  if (!response.ok) {
236
289
  console.error(`Cannot access ${url}`);
237
290
  }
291
+
238
292
  return await response.json();
239
293
  } catch {
240
294
  return null;
@@ -247,11 +301,14 @@ export default {
247
301
  where entity in (?${', ?'.repeat(this.labelledTerms.size-1)})`,
248
302
  [...this.labelledTerms.values()]
249
303
  );
304
+
250
305
  for (const termLabel of data.values) {
251
306
  this.labelCache.set(termLabel[0], termLabel[1]);
252
307
  }
308
+
253
309
  const labelCacheObj = Object.fromEntries(this.labelCache);
254
310
  sessionStorage.setItem('connectivity-graph-labels', JSON.stringify(labelCacheObj));
311
+ this.updateCacheExpiry();
255
312
  }
256
313
  },
257
314
  cacheNodeLabels: function (node) {
@@ -309,7 +366,7 @@ export default {
309
366
  .node-key {
310
367
  border: 1px solid $app-primary-color;
311
368
  padding: 4px;
312
- background-color: rgba(240, 240, 240, 0.8);
369
+ background-color: rgba(#f7faff, 0.85);
313
370
 
314
371
  div div {
315
372
  width: 90px;
@@ -362,6 +419,20 @@ export default {
362
419
  }
363
420
  }
364
421
 
422
+ :deep(.cy-graph-tooltip) {
423
+ padding: 4px 10px;
424
+ font-family: Asap;
425
+ font-size: 12px;
426
+ background: #f3ecf6 !important;
427
+ border: 1px solid $app-primary-color;
428
+ border-radius: var(--el-border-radius-base);
429
+ position: relative;
430
+ top: 0;
431
+ left: 0;
432
+ width: fit-content;
433
+ z-index: 1;
434
+ }
435
+
365
436
  .visually-hidden {
366
437
  clip: rect(0 0 0 0);
367
438
  clip-path: inset(50%);
@@ -25,7 +25,7 @@ import cytoscape from 'cytoscape'
25
25
 
26
26
  //==============================================================================
27
27
 
28
- export class ConnectivityGraph
28
+ export class ConnectivityGraph extends EventTarget
29
29
  {
30
30
  cyg = null
31
31
  nodes = []
@@ -37,8 +37,9 @@ export class ConnectivityGraph
37
37
 
38
38
  constructor(labelCache, graphCanvas)
39
39
  {
40
- this.labelCache = labelCache;
41
- this.graphCanvas = graphCanvas;
40
+ super()
41
+ this.labelCache = labelCache;
42
+ this.graphCanvas = graphCanvas;
42
43
  }
43
44
 
44
45
  async addConnectivity(knowledge)
@@ -70,6 +71,13 @@ export class ConnectivityGraph
70
71
  //================
71
72
  {
72
73
  this.cyg = new CytoscapeGraph(this, graphCanvas)
74
+
75
+ this.cyg.on('tap-node', (event) => {
76
+ const tapEvent = new CustomEvent('tap-node', {
77
+ detail: event.detail
78
+ })
79
+ this.dispatchEvent(tapEvent);
80
+ });
73
81
  }
74
82
 
75
83
  clearConnectivity()
@@ -140,6 +148,12 @@ export class ConnectivityGraph
140
148
  }
141
149
  return result
142
150
  }
151
+
152
+ on(eventName, callback)
153
+ //=====================
154
+ {
155
+ this.addEventListener(eventName, callback)
156
+ }
143
157
  }
144
158
 
145
159
  //==============================================================================
@@ -188,13 +202,14 @@ const GRAPH_STYLE = [
188
202
 
189
203
  //==============================================================================
190
204
 
191
- class CytoscapeGraph
205
+ class CytoscapeGraph extends EventTarget
192
206
  {
193
207
  cy
194
208
  tooltip
195
209
 
196
210
  constructor(connectivityGraph, graphCanvas)
197
211
  {
212
+ super()
198
213
  this.cy = cytoscape({
199
214
  container: graphCanvas,
200
215
  elements: connectivityGraph.elements,
@@ -211,11 +226,12 @@ class CytoscapeGraph
211
226
  }).on('mouseover', 'node', this.overNode.bind(this))
212
227
  .on('mouseout', 'node', this.exitNode.bind(this))
213
228
  .on('position', 'node', this.moveNode.bind(this))
229
+ .on('tap', 'node', this.tapNode.bind(this))
214
230
 
215
231
  this.tooltip = document.createElement('div')
216
- this.tooltip.id = 'tooltip'
232
+ this.tooltip.className = 'cy-graph-tooltip'
217
233
  this.tooltip.hidden = true
218
- this.graphCanvas?.lastChild?.appendChild(this.tooltip)
234
+ graphCanvas?.lastChild?.appendChild(this.tooltip)
219
235
  }
220
236
 
221
237
  remove()
@@ -259,6 +275,23 @@ class CytoscapeGraph
259
275
  {
260
276
  this.tooltip.hidden = true
261
277
  }
278
+
279
+ tapNode(event)
280
+ //============
281
+ {
282
+ const node = event.target
283
+ const data = node.data()
284
+ const tapEvent = new CustomEvent('tap-node', {
285
+ detail: data
286
+ })
287
+ this.dispatchEvent(tapEvent);
288
+ }
289
+
290
+ on(eventName, callback)
291
+ //=====================
292
+ {
293
+ this.addEventListener(eventName, callback)
294
+ }
262
295
  }
263
296
 
264
297
  //==============================================================================