import * as d3 from 'd3' import {Neo4JAdapter} from '../neo4j/neo' import {Graph} from '../graph/graph' import {GraphCreator} from '../graph/graphCreator' import {v1 as neo4j} from 'neo4j-driver' import {elements} from '../discussionElements' import {getIssueTooltipOf, getStatementTooltipOf, getArgumentTooltipOf, getEdgeTooltipOf} from './tooltip/tooltip' export class Network { async showNetwork(query) { const graph = await new GraphCreator().fill(new Graph(), query); var tooltip = d3.select("body") .append("div") .attr("class", "tooltip") .style("opacity", 0); const svg = d3.select('svg'), width = +svg.attr('width'), height = +svg.attr('height'); const simulation = d3.forceSimulation() .nodes(graph.nodes) .force('link', d3.forceLink().id(d => d.id).distance(100)) .force('charge', d3.forceManyBody()) .force('center', d3.forceCenter(width / 2, height / 2)) .velocityDecay(0.3) .alphaTarget(1) .on('tick', ticked); simulation.force('link') .links(graph.edges); const R = 10; let link = svg.selectAll('line') .data(graph.edges) .enter().append('line'); link .attr('class', 'link') .attr('stroke', function (l) { if (l.type.includes(elements.REGARDING)) { return "#A9A9A9"; } else if (l.type.includes(elements.CONCLUDES)) { return "#ce34ff"; } else if (l.type.includes(elements.PREMISEOF)) { return "#7b6fcc"; } }) .on('mouseover.tooltip', function (d) { tooltip.transition() .duration(300) .style("opacity", 0.8); tooltip.html(getEdgeTooltipOf(d)) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY + 10) + "px"); }) .on("mouseout.tooltip", function () { tooltip.transition() .duration(100) .style("opacity", 0); }) .on('mouseout.fade', fade(1)) .on("mousemove", function () { tooltip.style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY + 10) + "px"); }); ; let node = svg.selectAll('.node') .data(graph.nodes) .enter().append('g') .attr('class', 'node') .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); ; node.append('circle') .attr('r', R) .attr("fill", function (d) { if (d.labels.includes(elements.ATTACK)) { return "#ff0000"; } else if (d.labels.includes(elements.SUPPORT)) { return "#00ff00"; } else if (d.labels.includes(elements.STATEMENT)) { return "#ffff00"; } else if (d.labels.includes(elements.ISSUE)) { return "#0000ff" } }) .on('mouseover.tooltip', function (d) { tooltip.transition() .duration(300) .style("opacity", .8); let info = ""; if (d.labels.includes("Issue")) { info = getIssueTooltipOf(d); } else if (d.labels.includes(elements.STATEMENT)) { info = getStatementTooltipOf(d); } else if (d.labels.includes(elements.ARGUMENT)) { info = getArgumentTooltipOf(d); } tooltip.html(info) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY + 10) + "px"); }) .on('mouseover.fade', fade(0.1)) .on("mouseout.tooltip", function () { tooltip.transition() .duration(100) .style("opacity", 0); }) .on('mouseout.fade', fade(1)) .on("mousemove", function () { tooltip.style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY + 10) + "px"); }) .on('dblclick', releasenode); function ticked() { link .attr('x1', d => d.source.x) .attr('y1', d => d.source.y) .attr('x2', d => d.target.x) .attr('y2', d => d.target.y); node .attr('transform', d => `translate(${d.x},${d.y})`) .attr("cx", function (d) { return d.x = Math.max(R, Math.min(width - R, d.x)); }) .attr("cy", function (d) { return d.y = Math.max(R, Math.min(height - R, d.y)); }); } function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; graph.nodes[0].x = width / 2; graph.nodes[0].y = height / 2; } function releasenode(d) { d.fx = null; d.fy = null; } const linkedByIndex = {}; graph.edges.forEach(d => { linkedByIndex[`${d.source.index},${d.target.index}`] = 1; }); function isConnected(a, b) { return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index; } function fade(opacity) { return d => { node.style('stroke-opacity', function (o) { const thisOpacity = isConnected(d, o) ? 1 : opacity; this.setAttribute('fill-opacity', thisOpacity); return thisOpacity; }); link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity)); }; } svg.append("g") .attr("class", "legendSequential") .attr("transform", "translate(" + (width - 100) + "," + (height - 300) + ")"); } }