-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvisualization-pagination.js
91 lines (87 loc) · 5.29 KB
/
visualization-pagination.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/**
* Splits a large Graph into multiple smaller ones with query pagination to be able visualize them.
* Uses {@link https://github.com/neo4j-contrib/neovis.js|neovis.js}
* on top of {@link https://visjs.github.io/vis-network/docs/network/|vis-network.js}.
*
* @param {Object} parameters - The parameters for the paginated visualization using neovis.js on top of vis-network.js.
* @param {string} parameters.containerElementId - The id of the main container element (typically a div) where all visualizations will be drawn into.
* @param {Object} parameters.neoVizConfiguration - {@link https://neo4j-contrib.github.io/neovis.js/interfaces/NeovisConfig.html|NeovisConfig} object. The containerId will be overwritten so it can be left out or filled with an empty string.
* @param {string} [parameters.maxVisualizations=100] - Maximal number of visualizations (pages)
* @param {string} [parameters.recordsPerVisualization=160] - Maximal numbers of records per visualization (page/block size)
* @param {string} [parameters.idPrefixOfIndexedVisualizationElement="vis"] - Element id prefix for every indexed visualization element. It is then followed by the index number.
* @param {string} [parameters.classOfIndexedVisualizationElement="indexedVisualization"] - CSS class name for every indexed visualization element
* @param {string} [parameters.classOfFinishedVisualization="visualization-finished"] - CSS class name for finished visualizations (might be successful or failed)
* @param {string} [parameters.classOfFailedVisualization="visualization-failed"] - CSS class name for failed visualizations containing an error message
*/
function paginatedGraphVisualization({
containerElementId,
neoVizConfiguration,
maxVisualizations = 100,
recordsPerVisualization = 160,
idPrefixOfIndexedVisualizationElement = "vis",
classOfIndexedVisualizationElement = "indexedVisualization",
classOfFinishedVisualization = "visualization-finished",
classOfFailedVisualization = "visualization-failed",
}) {
/**
* Marks the given element as finished when the visualization is completed.
* @param {Element} indexedVisualizationElement
* @param {string} logDescription
*/
function markVisualizationAsFinished(indexedVisualizationElement, logDescription) {
indexedVisualizationElement.classList.add(classOfFinishedVisualization);
const unfinishedVisualizations = document.querySelectorAll(`.${classOfIndexedVisualizationElement}:not(.${classOfFinishedVisualization})`);
if (unfinishedVisualizations.length === 0) {
console.debug(`${logDescription}: Last visualization finished on element ${JSON.stringify(indexedVisualizationElement)}.`);
if (indexedVisualizationElement.parentElement) {
console.debug(`${logDescription}: Mark whole visualization as finished on parent element ${JSON.stringify( indexedVisualizationElement.parentElement)}`);
indexedVisualizationElement.parentElement.classList.add(classOfFinishedVisualization);
}
}
}
const containerElement = document.getElementById(containerElementId);
for (let index = 0; index < maxVisualizations; index++) {
const indexedVisualizationContainer = document.createElement("div");
indexedVisualizationContainer.id = `${idPrefixOfIndexedVisualizationElement}-${index}`;
indexedVisualizationContainer.classList.add(classOfIndexedVisualizationElement);
containerElement.appendChild(indexedVisualizationContainer);
const config = { ...neoVizConfiguration, containerId: indexedVisualizationContainer.id };
const neoViz = new NeoVis.default(config);
neoViz.registerOnEvent(NeoVis.NeoVisEvents.CompletionEvent, (event) => {
if (event.recordCount == 0) {
if (index === 0) {
const message = 'No query results. Nothing to visualize. Check the query and if the nodes and properties have been written.';
console.warn(message)
indexedVisualizationContainer.classList.add(classOfFailedVisualization);
indexedVisualizationContainer.textContent = message;
} else {
indexedVisualizationContainer.remove(); // remove an empty canvas
}
markVisualizationAsFinished(indexedVisualizationContainer, 'No query results (anymore)');
} else {
setTimeout(() => {
neoViz.stabilize();
markVisualizationAsFinished(indexedVisualizationContainer, 'Visualization stabilized');
}, 5000);
}
});
neoViz.registerOnEvent(NeoVis.NeoVisEvents.ErrorEvent, (event) => {
indexedVisualizationContainer.classList.add(classOfFailedVisualization);
indexedVisualizationContainer.textContent = event.error.message;
console.error(`Visualization Error: ${JSON.stringify(event.error)}`)
markVisualizationAsFinished(indexedVisualizationContainer, 'Error event');
});
neoViz.registerOnEvent(NeoVis.NeoVisEvents.ClickNodeEvent, (event) => {
console.debug(`Clicked on node: ${JSON.stringify(event.node, undefined, 2)}`)
});
neoViz.registerOnEvent(NeoVis.NeoVisEvents.ClickEdgeEvent, (event) => {
console.debug(`Clicked on edge: ${JSON.stringify(event.edge, undefined, 2)}`)
});
const parameters = {
blockSize: recordsPerVisualization,
startIndex: index * recordsPerVisualization,
endIndex: (index + 1) * recordsPerVisualization,
};
neoViz.render(undefined, parameters);
}
}