diff --git a/awx/ui/src/screens/TopologyView/Header.js b/awx/ui/src/screens/TopologyView/Header.js index ed94f2d295..4dacc7b598 100644 --- a/awx/ui/src/screens/TopologyView/Header.js +++ b/awx/ui/src/screens/TopologyView/Header.js @@ -17,9 +17,14 @@ import { ExpandArrowsAltIcon, } from '@patternfly/react-icons'; -const Header = ({ title, handleSwitchToggle, toggleState }) => { +const Header = ({ + title, + handleSwitchToggle, + toggleState, + zoomIn, + zoomOut, +}) => { const { light } = PageSectionVariants; - return (
{ aria-label={t`Zoom in`} variant="plain" icon={} + onClick={zoomIn} > @@ -55,6 +61,7 @@ const Header = ({ title, handleSwitchToggle, toggleState }) => { aria-label={t`Zoom out`} variant="plain" icon={} + onClick={zoomOut} > diff --git a/awx/ui/src/screens/TopologyView/MeshGraph.js b/awx/ui/src/screens/TopologyView/MeshGraph.js index f971807121..ab808f2a50 100644 --- a/awx/ui/src/screens/TopologyView/MeshGraph.js +++ b/awx/ui/src/screens/TopologyView/MeshGraph.js @@ -8,7 +8,7 @@ import Legend from './Legend'; import Tooltip from './Tooltip'; // function MeshGraph({ data }) { -function MeshGraph({ showLegend }) { +function MeshGraph({ showLegend, zoom }) { const [isNodeSelected, setIsNodeSelected] = useState(false); const [selectedNode, setSelectedNode] = useState(null); const [nodeDetail, setNodeDetail] = useState(null); @@ -83,7 +83,6 @@ function MeshGraph({ showLegend }) { return width; }; const width = getWidth(); - const zoom = d3.zoom().scaleExtent([-40, 40]).on('zoom', zoomed); /* Add SVG */ d3.selectAll(`#chart > svg`).remove(); @@ -91,11 +90,13 @@ function MeshGraph({ showLegend }) { const svg = d3 .select('#chart') .append('svg') + .attr('class', 'mesh-svg') .attr('width', `${width + margin}px`) .attr('height', `${height + margin}px`) .attr('viewBox', [0, 0, width, height]); const mesh = svg .append('g') + .attr('class', 'mesh') .attr('transform', `translate(${margin}, ${margin})`); const graph = data; @@ -295,10 +296,6 @@ function MeshGraph({ showLegend }) { setIsNodeSelected(true); setSelectedNode(n); } - - function zoomed({ transform }) { - mesh.attr('transform', transform); - } }; async function redirectToDetailsPage() { diff --git a/awx/ui/src/screens/TopologyView/TopologyView.js b/awx/ui/src/screens/TopologyView/TopologyView.js index 1fde272709..ac36360669 100644 --- a/awx/ui/src/screens/TopologyView/TopologyView.js +++ b/awx/ui/src/screens/TopologyView/TopologyView.js @@ -1,4 +1,5 @@ import React, { useEffect, useCallback, useState } from 'react'; +import * as d3 from 'd3'; import { t } from '@lingui/macro'; import { PageSection, Card, CardBody } from '@patternfly/react-core'; import useRequest from 'hooks/useRequest'; @@ -25,18 +26,31 @@ function TopologyView() { useEffect(() => { fetchMeshVisualizer(); }, [fetchMeshVisualizer]); + + const zoom = d3.zoom().on('zoom', ({ transform }) => { + d3.select('.mesh').attr('transform', transform); + }); + const zoomIn = () => { + d3.select('.mesh-svg').transition().call(zoom.scaleBy, 2); + }; + const zoomOut = () => { + d3.select('.mesh-svg').transition().call(zoom.scaleBy, 0.5); + }; + return ( <>
{!isLoading && ( - + )}