added files

This commit is contained in:
Tobias Weise 2024-08-09 21:56:32 +02:00
parent fdcb949f19
commit 670432e96e
5 changed files with 386 additions and 0 deletions

46
dynamic_usage_example.html Executable file
View File

@ -0,0 +1,46 @@
<!doctype html>
<html>
<head>
<title>JsNetworkx Custom Element</title>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.js"></script>
<script src="jsnetworkx.js"></script>
<script src="widget.js"></script>
</head>
<body>
<net-graph id="graph2" weighted="true" style="border-style: dotted; width:800px; height:600px;">
{
"nodes": [
[ 1, { "radius": 5, "color": "yellow"} ],
[ 2, { "radius": 15, "color": "green"} ],
[ 3, { "radius": 25, "color": "red"} ]
],
"edges": [
[1, 2, {"color": "red"}]
]
}
</net-graph>
<net-graph id="graph" weighted="true" style="border-style: dotted; width:800px; height:600px;" />
<script>
let ele = document.getElementById("graph");
let i = 10;
setInterval(()=>{
ele.G.addNode(i, { "radius": Math.floor(Math.random() * 30), "color": "red"} );
ele.G.addEdge(i - 1, i);
if(i > 20) i = -10;
i += 1;
},1000);
</script>
</body>
</html>

216
jira_graph.twig Normal file
View File

@ -0,0 +1,216 @@
<!doctype html>
<html>
<head>
<title>Jira Graph</title>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.js"></script>
<script src="jsnetworkx.js"></script>
<script>
function simulateClick(control) {
if (document.all) {
control.click();
} else {
var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window, 1, 12, 345, 7, 220, false, false, true, false, 0, null );
control.dispatchEvent(evObj);
}
}
</script>
</head>
<body style="font-family: Arial; background-color: black; color: white; height: 890px;">
{% for k, v in issues.items() %}
<div id="{{ k }}_state" style="display: none;">{{ v['state'] }}</div>
{% endfor %}
{% for k, v in issues.items() %}
<div id="{{ k }}_summary" style="display: none;">{{ v['summary'] }}</div>
{% endfor %}
{% for k, v in issues.items() %}
<div id="{{ k }}_description" style="display: none;">{{ v['description'] }}</div>
{% endfor %}
{% for k, v in issues.items() %}
<div id="{{ k }}_type" style="display: none;">{{ v['type'] }}</div>
{% endfor %}
<div style="width: 450px; float: right;">
<div>
<input type="text" id="search">
<button onclick="simulateClick(document.getElementById('node-' + document.getElementById('search').value));">Search</button>
</div>
<br>
<div style="display: flex;">
<table style="table-layout: fixed">
<thead>
<tr>
<th>Issue type(Nodes)</th>
</tr>
</thead>
<tbody>
{% for k, v in issue_colors.items() %}
<tr>
<td>{{ k }}</td>
<td style="width: 20px; background-color:{{ v }};" title="{{ v }}">
<!--<input type="color" value="{{ v }}">-->
</td>
</tr>
{% endfor %}
</tbody>
</table>
<table style="table-layout: fixed; float: right;">
<thead>
<tr>
<th>Link type(Edges)</th>
</tr>
</thead>
<tbody>
{% for k, v in link_colors.items() %}
<tr>
<td>{{ k }}</td>
<td style="width: 20px; background-color:{{ v }};" title="{{ v }}"></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<br>
<div style="width:300px; height: 350px;">
<b><span id="issue_type"></span>:<span id="issue_nr"></span>(<span style="font-size: 11pt;" id="issue_state"></span>)</b>
<br>
<br>
<b>Summary</b>
<br>
<br>
<div id="summary"></div>
<br>
<b>Description</b>
<br>
<br>
<div id="description"></div>
</div>
</div>
<div id="graph" style="background-color: darkblue; height: 100%; width: 1400px;"></div>
<script>
let G = new jsnx.MultiDiGraph();
G.addNodesFrom([
{% for k, v in issues.items() %}
[ {{ k }}, { radius: {{ v['radius'] }}, color: "{{ v['color'] }}"} ],
{% endfor %}
], {color: 'black'} );
G.addEdgesFrom([
{% for d in connections %}
[{{ d['start'] }}, {{ d['end'] }}, {color: "{{d['color']}}"}],
{% endfor %}
], {color: 'black'} );
jsnx.draw(G, {
element: '#graph',
//weighted: true,
withLabels: true,
labelStyle: {fill: 'white'},
edgeStyle: {
'stroke-width': 5,
fill: function(d) {
//stroke: function(d) {
//console.log(d.data.color);
//console.log(d.data[0]);
return d.data[0].color;// || 'red';
//return d.data.color
//return "red";
}
},
nodeStyle: {
fill: function(d) {
//hsl({link_hue_values[link.type.name]},100%,50%)
return d.data.color;
}
},
nodeAttr: {
r: function(d) {
// `d` has the properties `node`, `data` and `G`
return d.data.radius | 10;
}
}
});
//add ids
d3.selectAll('.node').each(function(d, i){
d3.select(this).attr('id', "node-" + d.node);
});
d3.selectAll('.edge').each(function(d, i){
d3.select(this).attr('id', "edge-" + d.edge[0] + "-" + d.edge[1]);
});
function highlight_nodes(d, on, active_color="#f00", ignore_color="#000") {
let node = d.node;
let neighbours = d.G.neighbors(d.node);
let n = d3.select('#node-' + node);
let circle_ele = n[0][0].children[0];
circle_ele.style["fill"] = on ? active_color : d.data.color;
d.G.nodes(true).forEach(function(t) {
let[node2, data] = t;
if(node !== node2){
let n = d3.select('#node-' + node2);
let circle_ele = n[0][0].children[0];
circle_ele.style["fill"] = on ? ignore_color : data.color;
}
});
d.G.edges(true).forEach(function(t) {
let[a, b, data] = t;
let n = d3.select('#edge-' + a + "-" + b);
let circle_ele = n[0][0].children[0];
circle_ele.style["fill"] = on ? ignore_color : data.color;
});
}
// bind event handlers
//d3.selectAll('.node').on('mouseover', function(d) {
//highlight_nodes(d.G.neighbors(d.node).concat(d.node), true);
//console.log("("+d.node+")");
//});
//d3.selectAll('.node').on('mouseout', function(d) {
//highlight_nodes(d.G.neighbors(d.node).concat(d.node), false);
//});
let focus_node = null;
d3.selectAll('.node').on('click', function(d) {
if(focus_node === d.node){
highlight_nodes(d, false);
focus_node = null;
}
else{
highlight_nodes(d, true);
focus_node = d.node;
}
document.getElementById("issue_nr").innerHTML = `<a style="color:lightblue;" target="_blank" rel="noopener noreferrer" href="https://team.breuer-gmbh.de/browse/DW-${d.node}">${d.node}</a>`;
document.getElementById("issue_type").innerHTML = document.getElementById(d.node+"_type").innerHTML;
document.getElementById("issue_state").innerHTML = document.getElementById(d.node+"_state").innerHTML;
document.getElementById("summary").innerHTML = document.getElementById(d.node+"_summary").innerHTML;
document.getElementById("description").innerHTML = document.getElementById(d.node+"_description").innerHTML;
});
</script>
</body>
</html>

8
jsnetworkx.js Normal file

File diff suppressed because one or more lines are too long

27
usage_example.html Executable file
View File

@ -0,0 +1,27 @@
<!doctype html>
<html>
<head>
<title>My Custom Element</title>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.js"></script>
<script src="jsnetworkx.js"></script>
<script src="widget.js"></script>
</head>
<body>
<net-graph style="border-style: dotted; width:800px; height:600px;">
{
"nodes": [
[ 1, { "radius": 5, "color": "yellow"} ],
[ 2, { "radius": 15, "color": "green"} ],
[ 3, { "radius": 25, "color": "red"} ]
],
"edges": [
[1, 2, {"color": "red"}]
]
}
</net-graph>
</body>
</html>

89
widget.js Executable file
View File

@ -0,0 +1,89 @@
class NetGraphElement extends HTMLElement {
static get observedAttributes() {
return ['G'];
}
constructor() {
super();
this.attachShadow({mode: 'open'});
this.content_div = document.createElement('div');
this.shadowRoot.appendChild(this.content_div);
this.slot_ele = document.createElement('slot');
this.shadowRoot.appendChild(this.slot_ele);
this.G = new jsnx.MultiDiGraph();
}
connectedCallback(){
let style = this.hasAttribute('style') ? this.getAttribute('style') : "";
let weighted = this.hasAttribute('weighted') ? JSON.parse(this.getAttribute('weighted')) : false;
let withLabels = this.hasAttribute('withLabels') ? JSON.parse(this.getAttribute('withLabels')) : true;
this.content_div.style = style;
let that = this;
jsnx.draw(that.G, {
element: that.content_div,
weighted,
withLabels,
labelStyle: {fill: 'white'},
edgeStyle: {
'stroke-width': 5,
fill: d => d.data[0].color
},
nodeStyle: {
fill: d => d.data.color
},
nodeAttr: {
r: d => d.data.radius | 10
}
}, true); //true ensures redrawing
this.slot_ele.addEventListener('slotchange', e => {
try{
let text = that.innerText.trim();
let{nodes, edges} = JSON.parse(text);
that.G.addNodesFrom(nodes, {color: 'black'} );
that.G.addEdgesFrom(edges, {color: 'black'} );
}
catch(e){
}
jsnx.draw(that.G, {
element: that.content_div,
weighted,
withLabels,
labelStyle: {fill: 'white'},
edgeStyle: {
'stroke-width': 5,
fill: d => d.data[0].color
},
nodeStyle: {
fill: d => d.data.color
},
nodeAttr: {
r: d => d.data.radius | 10
}
}, true); //true ensures redrawing
that.slot_ele.style.display = "none";
that.content_div.children[0].setAttribute("width", that.content_div.style.width);
that.content_div.children[0].setAttribute("height", that.content_div.style.height);
});
}
disconnectedCallback() {
}
}
customElements.define('net-graph', NetGraphElement);