diff --git a/awx/ui/src/screens/TopologyView/MeshGraph.js b/awx/ui/src/screens/TopologyView/MeshGraph.js
index c1ac487532..52747d0a81 100644
--- a/awx/ui/src/screens/TopologyView/MeshGraph.js
+++ b/awx/ui/src/screens/TopologyView/MeshGraph.js
@@ -2,8 +2,102 @@ import React, { useEffect, useCallback } from 'react';
import { t } from '@lingui/macro';
import * as d3 from 'd3';
-function MeshGraph({ data }) {
- console.log('data', data);
+// function MeshGraph({ data }) {
+function MeshGraph() {
+ const data = {
+ nodes: [
+ {
+ hostname: "aapc1.local",
+ node_state: "healthy",
+ node_type: "control",
+ id: 1
+ },
+ {
+ hostname: "aapc2.local",
+ node_type: "control",
+ node_state: "disabled",
+ id: 2
+ },
+ {
+ hostname: "aapc3.local",
+ node_type: "control",
+ node_state: "healthy",
+ id: 3
+ },
+ {
+ hostname: "aape1.local",
+ node_type: "execution",
+ node_state: "error",
+ id: 4
+ },
+ {
+ hostname: "aape2.local",
+ node_type: "execution",
+ node_state: "error",
+ id: 5
+ },
+ {
+ hostname: "aape3.local",
+ node_type: "execution",
+ node_state: "healthy",
+ id: 6
+ },
+ {
+ hostname: "aape4.local",
+ node_type: "execution",
+ node_state: "healthy",
+ id: 7
+ },
+ {
+ hostname: "aaph1.local",
+ node_type: "hop",
+ node_state: "disabled",
+ id: 8
+ },
+ {
+ hostname: "aaph2.local",
+ node_type: "hop",
+ node_state: "healthy",
+ id: 9
+ },
+ {
+ hostname: "aaph3.local",
+ node_type: "hop",
+ node_state: "error",
+ id: 10
+ }
+ ],
+ links: [
+ { source: "aapc1.local", target: "aapc2.local" },
+ { source: "aapc1.local", target: "aapc3.local" },
+ { source: "aapc1.local", target: "aape1.local" },
+ { source: "aapc1.local", target: "aape2.local" },
+
+ { source: "aapc2.local", target: "aapc3.local" },
+ { source: "aapc2.local", target: "aape1.local" },
+ { source: "aapc2.local", target: "aape2.local" },
+
+ { source: "aapc3.local", target: "aape1.local" },
+ { source: "aapc3.local", target: "aape2.local" },
+
+ { source: "aape3.local", target: "aaph1.local" },
+ { source: "aape3.local", target: "aaph2.local" },
+
+ { source: "aape4.local", target: "aaph3.local" },
+
+ { source: "aaph1.local", target: "aapc1.local" },
+ { source: "aaph1.local", target: "aapc2.local" },
+ { source: "aaph1.local", target: "aapc3.local" },
+
+ { source: "aaph2.local", target: "aapc1.local" },
+ { source: "aaph2.local", target: "aapc2.local" },
+ { source: "aaph2.local", target: "aapc3.local" },
+
+ { source: "aaph3.local", target: "aaph1.local" },
+ { source: "aaph3.local", target: "aaph2.local" }
+ ]
+ };
+
const draw = useCallback(() => {
const margin = 80;
const getWidth = () => {
@@ -22,6 +116,15 @@ function MeshGraph({ data }) {
};
const width = getWidth();
const height = 600;
+ const defaultRadius = 6;
+ const highlightRadius = 9;
+
+ const zoom = d3
+ .zoom()
+ .scaleExtent([1, 8])
+ .on('zoom', function (event) {
+ svg.selectAll('.links, .nodes').attr('transform', event.transform);
+ });
/* Add SVG */
d3.selectAll(`#chart > *`).remove();
@@ -32,9 +135,11 @@ function MeshGraph({ data }) {
.attr('width', `${width + margin}px`)
.attr('height', `${height + margin}px`)
.append('g')
- .attr('transform', `translate(${margin}, ${margin})`);
+ .attr('transform', `translate(${margin}, ${margin})`)
+ .call(zoom);
const color = d3.scaleOrdinal(d3.schemeCategory10);
+ const graph = data;
const simulation = d3
.forceSimulation()
@@ -55,32 +160,31 @@ function MeshGraph({ data }) {
)
.force('center', d3.forceCenter(width / 2, height / 2));
- const graph = data;
-
const link = svg
.append('g')
- .attr('class', 'links')
+ .attr('class', `links`)
.selectAll('path')
.data(graph.links)
.enter()
.append('path')
+ .attr('class', (d, i) => `link-${i}`)
.style('fill', 'none')
.style('stroke', '#ccc')
.style('stroke-width', '2px')
- .attr('pointer-events', 'visibleStroke')
+ .attr('pointer-events', 'none')
.on('mouseover', function (event, d) {
- tooltip
- .html(`source: ${d.source.hostname}
target: ${d.target.hostname}`)
- .style('visibility', 'visible');
+ // tooltip
+ // .html(`source: ${d.source.hostname}
target: ${d.target.hostname}`)
+ // .style('visibility', 'visible');
d3.select(this).transition().style('cursor', 'pointer');
})
.on('mousemove', function () {
- tooltip
- .style('top', event.pageY - 10 + 'px')
- .style('left', event.pageX + 10 + 'px');
+ // tooltip
+ // .style('top', event.pageY - 10 + 'px')
+ // .style('left', event.pageX + 10 + 'px');
})
.on('mouseout', function () {
- tooltip.html(``).style('visibility', 'hidden');
+ // tooltip.html(``).style('visibility', 'hidden');
});
const node = svg
@@ -90,52 +194,64 @@ function MeshGraph({ data }) {
.data(graph.nodes)
.enter()
.append('g')
- .on('mouseover', function (event, d) {
+ .on('mouseenter', function (event, d) {
+ d3.select(this).transition().style('cursor', 'pointer');
+ highlightSiblings(d)
tooltip
.html(
- `name: ${d.hostname}
type: ${d.node_type}
status: ${d.node_state}`
+ `