From db445d5cac4a9851c509fa54bb8786451b9ed59e Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Fri, 29 Jul 2022 11:39:23 -0700 Subject: Use internal links in job graph display Since we're using the graphviz library to render an svg, we can't just pass in a react router Link object for the node links we create for jobs. But we can manipulate the DOM after the SVG is produced and add onClick handlers that do the same thing. This avoids refreshing the page/app when clicking on links in the graph. Change-Id: Ie173e3d2e31efd47dbe4a44fda8b743250729339 --- web/src/containers/jobgraph/JobGraphDisplay.jsx | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/web/src/containers/jobgraph/JobGraphDisplay.jsx b/web/src/containers/jobgraph/JobGraphDisplay.jsx index 8d55c8f54..9bd67e7d2 100644 --- a/web/src/containers/jobgraph/JobGraphDisplay.jsx +++ b/web/src/containers/jobgraph/JobGraphDisplay.jsx @@ -16,12 +16,11 @@ import React, { useState, useEffect} from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import * as d3 from 'd3' +import { useHistory } from 'react-router-dom' import { makeJobGraphKey, fetchJobGraphIfNeeded } from '../../actions/jobgraph' import { graphviz } from 'd3-graphviz' -import { getHomepageUrl } from '../../api' - function makeDot(tenant, pipeline, project, branch, jobGraph) { let ret = 'digraph job_graph {\n' ret += ' rankdir=LR;\n' @@ -32,8 +31,11 @@ function makeDot(tenant, pipeline, project, branch, jobGraph) { searchParams.append('project', project.name) searchParams.append('job', job.name) searchParams.append('branch', branch) - const url = (getHomepageUrl() + tenant.linkPrefix + - 'freeze-job?' + searchParams.toString()) + // This will appear in the DOM as an "a href=" but we will + // manipulate the DOM later to add an onClick callback to make + // this an internal link. + const url = (tenant.linkPrefix + + '/freeze-job?' + searchParams.toString()) // Escape ampersands to get it through graphviz and d3; these will // appear unescaped in the DOM. const escaped_url = url.replace(/&/g, '&') @@ -53,6 +55,8 @@ function makeDot(tenant, pipeline, project, branch, jobGraph) { } function GraphViz(props) { + const history = useHistory() + useEffect(() => { const gv = graphviz('#graphviz') .options({ @@ -72,7 +76,13 @@ function GraphViz(props) { gv._translation.y = val gv._originalTransform.y = val } - }, [props.dot]) + + // Mutate the links to be internal links + d3.select('.zuul-job-graph').selectAll('.node a').on('click', event => { + d3.event.preventDefault() + history.push(event.attributes['xlink:href']) + }) + }, [props.dot, history]) return (
-- cgit v1.2.1