Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 28 additions & 17 deletions core/frontend/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,25 @@ hotkeys('space', (e) => {
const elts = {};
const imageFileValidExtnames = new Set(['jpg', 'jpeg', 'png']);

// Precompute bidirectional edges
const edgeSet = new Set(data.edges.map((e) => `${e.source.key}--${e.target.key}`));
const bidirectionalEdges = new Set(
data.edges
.filter((e) => edgeSet.has(`${e.target.key}--${e.source.key}`))
.map((e) => e.key)
);

simulation.on('tick', () => {
elts.links
.attr('x1', (d) => d.source.x)
.attr('y1', (d) => d.source.y)
.attr('x2', (d) => d.target.x)
.attr('y2', (d) => d.target.y);
.attr('d', (d) => {
const dx = d.target.x - d.source.x;
const dy = d.target.y - d.source.y;
const dr = Math.sqrt(dx * dx + dy * dy);
if (bidirectionalEdges.has(d.key)) {
return `M ${d.source.x},${d.source.y} A ${dr},${dr} 0 0,1 ${d.target.x},${d.target.y}`;
}
return `M ${d.source.x},${d.source.y} L ${d.target.x},${d.target.y}`;
});

elts.nodes.attr('transform', (d) => 'translate(' + d.x + ',' + d.y + ')');

Expand All @@ -105,10 +118,11 @@ simulation.on('tick', () => {
/** @type {d3.Selection<SVGLineElement, Link, SVGElement, any>} */
elts.links = svgSub
.append('g')
.selectAll('line')
.selectAll('path')
.data(data.edges)
.enter()
.append('line')
.append('path')
.attr('fill', 'none')
.attr('stroke', (d) => `var(--l_${d.attributes.type})`)
.attr('title', (d) => d.attributes.title)
.attr('data-link', (d) => d.key)
Expand All @@ -128,9 +142,14 @@ elts.links = svgSub
});

if (graphProperties.graph_arrows === true) {
elts.links.attr('marker-end', 'url(#arrow)');
if (graphProperties.graph_arrows_reversed === true) {
elts.links.attr('marker-start', 'url(#arrow-reversed)');
} else {
elts.links.attr('marker-end', 'url(#arrow)');
}
}


const strokeWidth = 2;

/** @type {d3.Selection<SVGGElement, Node, SVGElement, any>} */
Expand Down Expand Up @@ -484,9 +503,8 @@ function highlightNodes(nodeIds) {
nodeIds
.filter((nodeId) => graph.hasNode(nodeId))
.forEach((nodeId) => {
const { links, node } = getNodeNetwork(nodeId);
const { node } = getNodeNetwork(nodeId);
node.node().classList.add('highlight');
links.nodes().forEach((elt) => elt.classList.add('highlight'));
});

highlightedNodes = highlightedNodes.concat(nodeIds);
Expand All @@ -501,14 +519,7 @@ function unlightNodes() {
return;
}

highlightedNodes
.filter((nodeId) => graph.hasNode(nodeId))
.forEach((nodeId) => {
const { links, node } = getNodeNetwork(nodeId);
node.node().classList.remove('highlight');
links.nodes().forEach((elt) => elt.classList.remove('highlight'));
});

elts.nodes.nodes().forEach((elt) => elt.classList.remove('highlight'));
highlightedNodes = [];
}

Expand Down
4 changes: 2 additions & 2 deletions core/frontend/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,8 @@ text {
/* arrows */
marker {
/* set into config.yml file by 'undefined' link type */
stroke: var(--l_undefined);
fill: var(--l_undefined);
stroke: context-stroke;
fill: context-stroke;
}

/* ---
Expand Down
3 changes: 3 additions & 0 deletions core/i18n.yml
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ config:
graph_arrows:
fr: La commande de fléchage des liens est invalide
en: Invalid link arrow command
graph_arrows_reversed:
fr: La commande d'inversion des flèches est invalide
en: Invalid reverse arrow command
devtools:
fr: La commande d'activation des outils de développement est invalide
en: Invalid devtools activation command
Expand Down
3 changes: 3 additions & 0 deletions core/models/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import Joi from 'joi';
* @property {boolean} graph_highlight_on_hover
* @property {number} graph_text_size
* @property {boolean} graph_arrows
* @property {boolean} graph_arrows_reversed
* @property {'unique'|'degree'} node_size_method
* @property {number} node_size
* @property {number} [node_size_max]
Expand Down Expand Up @@ -183,6 +184,7 @@ const optionsSchema = Joi.object({
graph_highlight_on_hover: Joi.boolean(),
graph_text_size: Joi.number(),
graph_arrows: Joi.boolean(),
graph_arrows_reversed: Joi.boolean(),
node_size_method: Joi.string().valid('unique', 'degree'),
node_size: Joi.number().integer().min(0),
node_size_max: Joi.number().integer().min(0).optional(),
Expand Down Expand Up @@ -254,6 +256,7 @@ class Config {
graph_highlight_on_hover: true,
graph_text_size: 10,
graph_arrows: true,
graph_arrows_reversed: false,
node_size_method: 'degree',
node_size: 10,
node_size_max: 20,
Expand Down
9 changes: 6 additions & 3 deletions static/template/cosmoscope.njk
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,11 @@
<svg id="graph-canvas">
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="22" refY="5" markerUnits="strokeWidth" markerWidth="5" markerHeight="5" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z"></path>
</marker>
<path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"></path>
</marker>
<marker id="arrow-reversed" viewBox="0 0 10 10" refX="22" refY="5" markerUnits="strokeWidth" markerWidth="5" markerHeight="5" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"></path>
</marker>
<filter id="double">
<feMorphology in="SourceGraphic" result="a" operator="dilate" radius="0.2"></feMorphology>
<feComposite in="SourceGraphic" in2="a" result="xx" operator="xor"></feComposite>
Expand Down Expand Up @@ -612,4 +615,4 @@

</body>

</html>
</html>