Merge "web: switch jobs list to a tree view"

This commit is contained in:
Zuul 2019-03-12 10:03:50 +00:00 committed by Gerrit Code Review
commit 52877b3b26
2 changed files with 75 additions and 45 deletions

View File

@ -16,7 +16,7 @@ import * as React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { Table } from 'patternfly-react' import { TreeView } from 'patternfly-react'
class JobsList extends React.Component { class JobsList extends React.Component {
@ -28,53 +28,78 @@ class JobsList extends React.Component {
render () { render () {
const { jobs } = this.props const { jobs } = this.props
const headerFormat = value => <Table.Heading>{value}</Table.Heading> const linkPrefix = this.props.tenant.linkPrefix + '/job/'
const cellFormat = (value) => (
<Table.Cell>{value}</Table.Cell>) // job index map
const cellJobFormat = (value) => ( const jobMap = {}
<Table.Cell> // nodes contains the tree data
<Link to={this.props.tenant.linkPrefix + '/job/' + value}> const nodes = []
{value} // visited contains individual node
</Link> const visited = {}
</Table.Cell>) // getNode returns the tree node and visit each parents
const cellBuildFormat = (value) => ( const getNode = function (job) {
<Table.Cell> if (!visited[job.name]) {
<Link to={this.props.tenant.linkPrefix + '/builds?job_name=' + value}> // Collect parents
builds let parents = []
</Link> if (job.variants) {
</Table.Cell>) for (let jobVariant of job.variants) {
const columns = [] if (jobVariant.parent &&
const myColumns = ['name', 'description', 'Last builds'] parents.indexOf(jobVariant.parent) === -1) {
myColumns.forEach(column => { parents.push(jobVariant.parent)
let formatter = cellFormat }
let prop = column }
if (column === 'name') { }
formatter = cellJobFormat visited[job.name] = {
text: (
<React.Fragment>
<Link to={linkPrefix + job.name}>{job.name}</Link>
{job.description && (
<span style={{marginLeft: '10px'}}>{job.description}</span>
)}
</React.Fragment>),
icon: 'fa fa-cube',
state: {
expanded: true,
},
parents: parents,
}
// Visit parent recursively
for (let parent of parents) {
getNode(jobMap[parent])
}
} }
if (column === 'Last builds') { return visited[job.name]
prop = 'name' }
formatter = cellBuildFormat // index job list
for (let job of jobs) {
jobMap[job.name] = job
}
// process job list
for (let job of jobs) {
const jobNode = getNode(job)
let attached = false
// add tree node to each parent and expand the parent
for (let parent of jobNode.parents) {
const parentNode = visited[parent]
if (!parentNode) {
console.log('Job ', job.name, ' parent ', parent, ' does not exist!')
continue
}
if (!parentNode.nodes) {
parentNode.nodes = []
}
parentNode.nodes.push(jobNode)
attached = true
} }
columns.push({ // else add node at the tree root
header: {label: column, if (!attached || jobNode.parents.length === 0) {
formatters: [headerFormat]}, nodes.push(jobNode)
property: prop, }
cell: {formatters: [formatter]} }
})
})
return ( return (
<Table.PfProvider <div className='tree-view-container'>
striped <TreeView nodes={nodes} />
bordered </div>
hover
columns={columns}
>
<Table.Header/>
<Table.Body
rows={jobs}
rowKey="name"
/>
</Table.PfProvider>
) )
} }
} }

View File

@ -130,3 +130,8 @@ p.zuulstreamline {
margin: 0px 0px; margin: 0px 0px;
line-height: 1.4; line-height: 1.4;
} }
/* Job Tree View group gap */
div.tree-view-container ul.list-group {
margin: 0px 0px;
}