mirror of
https://github.com/ansible/awx.git
synced 2026-03-09 13:39:27 -02:30
Hook up zoom in, zoom out buttons.
This commit is contained in:
@@ -17,9 +17,14 @@ import {
|
|||||||
ExpandArrowsAltIcon,
|
ExpandArrowsAltIcon,
|
||||||
} from '@patternfly/react-icons';
|
} from '@patternfly/react-icons';
|
||||||
|
|
||||||
const Header = ({ title, handleSwitchToggle, toggleState }) => {
|
const Header = ({
|
||||||
|
title,
|
||||||
|
handleSwitchToggle,
|
||||||
|
toggleState,
|
||||||
|
zoomIn,
|
||||||
|
zoomOut,
|
||||||
|
}) => {
|
||||||
const { light } = PageSectionVariants;
|
const { light } = PageSectionVariants;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageSection variant={light}>
|
<PageSection variant={light}>
|
||||||
<div
|
<div
|
||||||
@@ -45,6 +50,7 @@ const Header = ({ title, handleSwitchToggle, toggleState }) => {
|
|||||||
aria-label={t`Zoom in`}
|
aria-label={t`Zoom in`}
|
||||||
variant="plain"
|
variant="plain"
|
||||||
icon={<SearchPlusIcon />}
|
icon={<SearchPlusIcon />}
|
||||||
|
onClick={zoomIn}
|
||||||
>
|
>
|
||||||
<SearchPlusIcon />
|
<SearchPlusIcon />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -55,6 +61,7 @@ const Header = ({ title, handleSwitchToggle, toggleState }) => {
|
|||||||
aria-label={t`Zoom out`}
|
aria-label={t`Zoom out`}
|
||||||
variant="plain"
|
variant="plain"
|
||||||
icon={<SearchMinusIcon />}
|
icon={<SearchMinusIcon />}
|
||||||
|
onClick={zoomOut}
|
||||||
>
|
>
|
||||||
<SearchMinusIcon />
|
<SearchMinusIcon />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Legend from './Legend';
|
|||||||
import Tooltip from './Tooltip';
|
import Tooltip from './Tooltip';
|
||||||
|
|
||||||
// function MeshGraph({ data }) {
|
// function MeshGraph({ data }) {
|
||||||
function MeshGraph({ showLegend }) {
|
function MeshGraph({ showLegend, zoom }) {
|
||||||
const [isNodeSelected, setIsNodeSelected] = useState(false);
|
const [isNodeSelected, setIsNodeSelected] = useState(false);
|
||||||
const [selectedNode, setSelectedNode] = useState(null);
|
const [selectedNode, setSelectedNode] = useState(null);
|
||||||
const [nodeDetail, setNodeDetail] = useState(null);
|
const [nodeDetail, setNodeDetail] = useState(null);
|
||||||
@@ -83,7 +83,6 @@ function MeshGraph({ showLegend }) {
|
|||||||
return width;
|
return width;
|
||||||
};
|
};
|
||||||
const width = getWidth();
|
const width = getWidth();
|
||||||
const zoom = d3.zoom().scaleExtent([-40, 40]).on('zoom', zoomed);
|
|
||||||
|
|
||||||
/* Add SVG */
|
/* Add SVG */
|
||||||
d3.selectAll(`#chart > svg`).remove();
|
d3.selectAll(`#chart > svg`).remove();
|
||||||
@@ -91,11 +90,13 @@ function MeshGraph({ showLegend }) {
|
|||||||
const svg = d3
|
const svg = d3
|
||||||
.select('#chart')
|
.select('#chart')
|
||||||
.append('svg')
|
.append('svg')
|
||||||
|
.attr('class', 'mesh-svg')
|
||||||
.attr('width', `${width + margin}px`)
|
.attr('width', `${width + margin}px`)
|
||||||
.attr('height', `${height + margin}px`)
|
.attr('height', `${height + margin}px`)
|
||||||
.attr('viewBox', [0, 0, width, height]);
|
.attr('viewBox', [0, 0, width, height]);
|
||||||
const mesh = svg
|
const mesh = svg
|
||||||
.append('g')
|
.append('g')
|
||||||
|
.attr('class', 'mesh')
|
||||||
.attr('transform', `translate(${margin}, ${margin})`);
|
.attr('transform', `translate(${margin}, ${margin})`);
|
||||||
|
|
||||||
const graph = data;
|
const graph = data;
|
||||||
@@ -295,10 +296,6 @@ function MeshGraph({ showLegend }) {
|
|||||||
setIsNodeSelected(true);
|
setIsNodeSelected(true);
|
||||||
setSelectedNode(n);
|
setSelectedNode(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
function zoomed({ transform }) {
|
|
||||||
mesh.attr('transform', transform);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function redirectToDetailsPage() {
|
async function redirectToDetailsPage() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { useEffect, useCallback, useState } from 'react';
|
import React, { useEffect, useCallback, useState } from 'react';
|
||||||
|
import * as d3 from 'd3';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { PageSection, Card, CardBody } from '@patternfly/react-core';
|
import { PageSection, Card, CardBody } from '@patternfly/react-core';
|
||||||
import useRequest from 'hooks/useRequest';
|
import useRequest from 'hooks/useRequest';
|
||||||
@@ -25,18 +26,31 @@ function TopologyView() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchMeshVisualizer();
|
fetchMeshVisualizer();
|
||||||
}, [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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header
|
<Header
|
||||||
title={t`Topology View`}
|
title={t`Topology View`}
|
||||||
handleSwitchToggle={setShowLegend}
|
handleSwitchToggle={setShowLegend}
|
||||||
toggleState={showLegend}
|
toggleState={showLegend}
|
||||||
|
zoomIn={zoomIn}
|
||||||
|
zoomOut={zoomOut}
|
||||||
/>
|
/>
|
||||||
<PageSection>
|
<PageSection>
|
||||||
<Card>
|
<Card>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<MeshGraph data={meshData} showLegend={showLegend} />
|
<MeshGraph data={meshData} showLegend={showLegend} zoom={zoom} />
|
||||||
)}
|
)}
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Reference in New Issue
Block a user