diff --git a/releasenotes/notes/web-page-build-93eeb53418f8a3f0.yaml b/releasenotes/notes/web-page-build-93eeb53418f8a3f0.yaml new file mode 100644 index 0000000000..562d3378c6 --- /dev/null +++ b/releasenotes/notes/web-page-build-93eeb53418f8a3f0.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + A new Build page in the web interface enable displaying a single Build + information. diff --git a/web/src/api.js b/web/src/api.js index 9af4adb8e8..40fc3ee173 100644 --- a/web/src/api.js +++ b/web/src/api.js @@ -111,6 +111,9 @@ function fetchTenants () { function fetchStatus (apiPrefix) { return Axios.get(apiUrl + apiPrefix + 'status') } +function fetchBuild (apiPrefix, buildId) { + return Axios.get(apiUrl + apiPrefix + 'build/' + buildId) +} function fetchBuilds (apiPrefix, queryString) { let path = 'builds' if (queryString) { @@ -126,6 +129,7 @@ export { getHomepageUrl, getStreamUrl, fetchStatus, + fetchBuild, fetchBuilds, fetchJobs, fetchTenants, diff --git a/web/src/pages/Build.jsx b/web/src/pages/Build.jsx new file mode 100644 index 0000000000..20dae9449e --- /dev/null +++ b/web/src/pages/Build.jsx @@ -0,0 +1,111 @@ +// Copyright 2018 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 { connect } from 'react-redux' +import PropTypes from 'prop-types' +import { Link } from 'react-router-dom' +import { Panel } from 'react-bootstrap' + +import { fetchBuild } from '../api' + + +class BuildPage extends React.Component { + static propTypes = { + match: PropTypes.object.isRequired, + tenant: PropTypes.object + } + + state = { + build: null + } + + updateData = () => { + fetchBuild(this.props.tenant.apiPrefix, this.props.match.params.buildId) + .then(response => { + this.setState({build: response.data}) + }) + } + + componentDidMount () { + document.title = 'Zuul Build' + if (this.props.tenant.name) { + this.updateData() + } + } + + componentDidUpdate (prevProps) { + if (this.props.tenant.name !== prevProps.tenant.name) { + this.updateData() + } + } + + render () { + const { build } = this.state + if (!build) { + return (

Loading...

) + } + const rows = [] + const myColumns = [ + 'job_name', 'result', 'voting', + 'pipeline', 'start_time', 'end_time', 'duration', + 'project', 'branch', 'ref', 'new_rev', 'ref_url', + 'log_url'] + + myColumns.forEach(column => { + let label = column + let value = build[column] + if (column === 'job_name') { + label = 'Job' + value = ( + + {value} + + ) + } + if (column === 'voting') { + if (value) { + value = 'Yes' + } else { + value = 'No' + } + } + if (value && (column === 'log_url' || column === 'ref_url')) { + value = {value} + } + if (value) { + rows.push({key: label, value: value}) + } + }) + return ( + + Build result {build.uuid} + + + + {rows.map(item => ( + + + + + ))} + +
{item.key}{item.value}
+
+
+ ) + } +} + +export default connect(state => ({tenant: state.tenant}))(BuildPage) diff --git a/web/src/pages/Builds.jsx b/web/src/pages/Builds.jsx index 8f902ee83d..b3b4497e25 100644 --- a/web/src/pages/Builds.jsx +++ b/web/src/pages/Builds.jsx @@ -15,6 +15,7 @@ import * as React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' +import { Link } from 'react-router-dom' import { Table } from 'patternfly-react' import { fetchBuilds } from '../api' @@ -71,9 +72,15 @@ class BuildsPage extends TableFilters { link ) + const linkBuildFormat = (value) => ( + + link + + ) this.columns = [] this.filterTypes = [] const myColumns = [ + 'build', 'job', 'project', 'branch', @@ -87,6 +94,10 @@ class BuildsPage extends TableFilters { let prop = column let formatter = cellFormat // Adapt column name and property name + if (column === 'build') { + prop = 'uuid' + formatter = linkBuildFormat + } if (column === 'job') { prop = 'job_name' } else if (column === 'start time') { diff --git a/web/src/routes.js b/web/src/routes.js index 408599eaf6..ff2ca7c926 100644 --- a/web/src/routes.js +++ b/web/src/routes.js @@ -14,6 +14,7 @@ import StatusPage from './pages/Status' import JobsPage from './pages/Jobs' +import BuildPage from './pages/Build' import BuildsPage from './pages/Builds' import TenantsPage from './pages/Tenants' import StreamPage from './pages/Stream' @@ -42,6 +43,10 @@ const routes = () => [ to: '/stream/:buildId', component: StreamPage }, + { + to: '/build/:buildId', + component: BuildPage + }, { to: '/tenants', component: TenantsPage,