web: add buildsets page

This change adds a new page to display a buildsets table
similar to the builds page.

Change-Id: I795dc47149bfc3e4104183fd1838d5f0b05852c2
This commit is contained in:
Tristan Cacqueray 2019-01-11 07:11:29 +00:00
parent d60346181b
commit 84fefd146d
4 changed files with 168 additions and 1 deletions

View File

@ -128,6 +128,13 @@ function fetchBuilds (apiPrefix, queryString) {
}
return Axios.get(apiUrl + apiPrefix + path)
}
function fetchBuildsets (apiPrefix, queryString) {
let path = 'buildsets'
if (queryString) {
path += '?' + queryString.slice(1)
}
return Axios.get(apiUrl + apiPrefix + path)
}
function fetchProject (apiPrefix, projectName) {
return Axios.get(apiUrl + apiPrefix + 'project/' + projectName)
}
@ -155,6 +162,7 @@ export {
fetchStatus,
fetchBuild,
fetchBuilds,
fetchBuildsets,
fetchProject,
fetchProjects,
fetchJob,

150
web/src/pages/Buildsets.jsx Normal file
View File

@ -0,0 +1,150 @@
// Copyright 2019 Red Hat, Inc
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
import * as React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Table } from 'patternfly-react'
import { fetchBuildsets } from '../api'
import TableFilters from '../containers/TableFilters'
class BuildsetsPage extends TableFilters {
static propTypes = {
tenant: PropTypes.object
}
constructor () {
super()
this.prepareTableHeaders()
this.state = {
buildsets: null,
currentFilterType: this.filterTypes[0],
activeFilters: [],
currentValue: ''
}
}
updateData = (filters) => {
let queryString = ''
if (filters) {
filters.forEach(item => queryString += '&' + item.key + '=' + item.value)
}
this.setState({buildsets: null})
fetchBuildsets(this.props.tenant.apiPrefix, queryString).then(response => {
this.setState({buildsets: response.data})
})
}
componentDidMount () {
document.title = 'Zuul Buildsets'
if (this.props.tenant.name) {
this.updateData(this.getFilterFromUrl())
}
}
componentDidUpdate (prevProps) {
if (this.props.tenant.name !== prevProps.tenant.name) {
this.updateData(this.getFilterFromUrl())
}
}
prepareTableHeaders() {
const headerFormat = value => <Table.Heading>{value}</Table.Heading>
const cellFormat = (value) => <Table.Cell>{value}</Table.Cell>
const linkChangeFormat = (value, rowdata) => (
<Table.Cell>
<a href={rowdata.rowData.ref_url}>
{value ?
rowdata.rowData.change + ',' + rowdata.rowData.patchset :
rowdata.rowData.newrev ?
rowdata.rowData.newrev.substr(0, 7) :
rowdata.rowData.branch}
</a>
</Table.Cell>
)
this.columns = []
this.filterTypes = []
const myColumns = [
'project',
'branch',
'pipeline',
'change',
'result']
myColumns.forEach(column => {
let prop = column
let formatter = cellFormat
if (column === 'change') {
formatter = linkChangeFormat
}
const label = column.charAt(0).toUpperCase() + column.slice(1)
this.columns.push({
header: {label: label, formatters: [headerFormat]},
property: prop,
cell: {formatters: [formatter]}
})
if (column !== 'builds') {
this.filterTypes.push({
id: prop,
title: label,
placeholder: 'Filter by ' + label,
filterType: 'text',
})
}
})
// Add buildset filter at the end
this.filterTypes.push({
id: 'uuid',
title: 'Buildset',
palceholder: 'Filter by Buildset UUID',
fileterType: 'text',
})
}
renderTable (buildsets) {
return (
<Table.PfProvider
striped
bordered
columns={this.columns}
>
<Table.Header/>
<Table.Body
rows={buildsets}
rowKey='uuid'
onRow={(row) => {
switch (row.result) {
case 'SUCCESS':
return { className: 'success' }
default:
return { className: 'warning' }
}
}} />
</Table.PfProvider>)
}
render() {
const { buildsets } = this.state
return (
<React.Fragment>
{this.renderFilter()}
{buildsets ? this.renderTable(buildsets) : <p>Loading...</p>}
</React.Fragment>
)
}
}
export default connect(state => ({tenant: state.tenant}))(BuildsetsPage)

View File

@ -48,7 +48,8 @@ class TenantsPage extends Refreshable {
<Table.Cell>{value}</Table.Cell>)
const columns = []
const myColumns = [
'name', 'status', 'projects', 'jobs', 'builds', 'projects count', 'queue']
'name', 'status', 'projects', 'jobs', 'builds', 'buildsets',
'projects count', 'queue']
myColumns.forEach(column => {
let prop = column
if (column === 'projects count') {
@ -72,6 +73,8 @@ class TenantsPage extends Refreshable {
<Link to={'/t/' + tenant.name + '/jobs'}>Jobs</Link>)
tenant.builds = (
<Link to={'/t/' + tenant.name + '/builds'}>Builds</Link>)
tenant.buildsets = (
<Link to={'/t/' + tenant.name + '/buildsets'}>Buildsets</Link>)
})
return (
<React.Fragment>

View File

@ -22,6 +22,7 @@ import LabelsPage from './pages/Labels'
import NodesPage from './pages/Nodes'
import BuildPage from './pages/Build'
import BuildsPage from './pages/Builds'
import BuildsetsPage from './pages/Buildsets'
import ConfigErrorsPage from './pages/ConfigErrors'
import TenantsPage from './pages/Tenants'
import StreamPage from './pages/Stream'
@ -61,6 +62,11 @@ const routes = () => [
to: '/builds',
component: BuildsPage
},
{
title: 'Buildsets',
to: '/buildsets',
component: BuildsetsPage
},
{
to: '/status/change/:changeId',
component: ChangeStatusPage