diff options
-rw-r--r-- | web/src/api.js | 5 | ||||
-rw-r--r-- | web/src/containers/status/Change.jsx | 23 | ||||
-rw-r--r-- | web/src/pages/ChangeStatus.jsx | 94 | ||||
-rw-r--r-- | web/src/routes.js | 5 |
4 files changed, 122 insertions, 5 deletions
diff --git a/web/src/api.js b/web/src/api.js index 28c1b39ab..75efe686b 100644 --- a/web/src/api.js +++ b/web/src/api.js @@ -52,6 +52,7 @@ function getHomepageUrl (url) { '/job/', '/project/', '/stream/', + '/status/', ] subDir.forEach(path => { if (baseUrl.includes(path)) { @@ -114,6 +115,9 @@ function fetchConfigErrors (apiPrefix) { function fetchStatus (apiPrefix) { return Axios.get(apiUrl + apiPrefix + 'status') } +function fetchChangeStatus (apiPrefix, changeId) { + return Axios.get(apiUrl + apiPrefix + 'status/change/' + changeId) +} function fetchBuild (apiPrefix, buildId) { return Axios.get(apiUrl + apiPrefix + 'build/' + buildId) } @@ -134,6 +138,7 @@ function fetchJobs (apiPrefix) { export { getHomepageUrl, getStreamUrl, + fetchChangeStatus, fetchConfigErrors, fetchStatus, fetchBuild, diff --git a/web/src/containers/status/Change.jsx b/web/src/containers/status/Change.jsx index ddd82a9ae..b4d9be31d 100644 --- a/web/src/containers/status/Change.jsx +++ b/web/src/containers/status/Change.jsx @@ -14,6 +14,8 @@ import * as React from 'react' import PropTypes from 'prop-types' +import { connect } from 'react-redux' +import { Link } from 'react-router-dom' import LineAngleImage from '../../images/line-angle.png' import LineTImage from '../../images/line-t.png' @@ -24,7 +26,8 @@ class Change extends React.Component { static propTypes = { change: PropTypes.object.isRequired, queue: PropTypes.object.isRequired, - expanded: PropTypes.bool.isRequired + expanded: PropTypes.bool.isRequired, + tenant: PropTypes.object } renderStatusIcon (change) { @@ -47,10 +50,20 @@ class Change extends React.Component { iconGlyph = 'pficon pficon-error-circle-o' } } - return ( - <span className={'zuul-build-status ' + iconGlyph} - title={iconTitle} /> + const icon = ( + <span + className={'zuul-build-status ' + iconGlyph} + title={iconTitle} /> ) + if (change.live) { + return ( + <Link to={this.props.tenant.linkPrefix + '/status/change/' + change.id}> + {icon} + </Link> + ) + } else { + return icon + } } renderLineImg (change, i) { @@ -96,4 +109,4 @@ class Change extends React.Component { } } -export default Change +export default connect(state => ({tenant: state.tenant}))(Change) diff --git a/web/src/pages/ChangeStatus.jsx b/web/src/pages/ChangeStatus.jsx new file mode 100644 index 000000000..3ffb88e81 --- /dev/null +++ b/web/src/pages/ChangeStatus.jsx @@ -0,0 +1,94 @@ +/* global setTimeout, clearTimeout */ +// 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 PropTypes from 'prop-types' +import { connect } from 'react-redux' +import { + Alert, +} from 'patternfly-react' + +import { fetchChangeStatus } from '../api' +import ChangePanel from '../containers/status/ChangePanel' + + +class ChangeStatusPage extends React.Component { + static propTypes = { + match: PropTypes.object.isRequired, + tenant: PropTypes.object + } + + state = { + change: null, + error: null, + } + + updateData = () => { + // Clear any running timer + if (this.timer) { + clearTimeout(this.timer) + this.timer = null + } + this.setState({error: null}) + fetchChangeStatus( + this.props.tenant.apiPrefix, this.props.match.params.changeId) + .then(response => { + this.setState({change: response.data}) + }).catch(error => { + this.setState({error: error.message, change: null}) + }) + this.timer = setTimeout(this.updateData, 5000) + } + + componentDidMount () { + document.title = this.props.match.params.changeId + ' | Zuul Status' + if (this.props.tenant.name) { + this.updateData() + } + } + + componentDidUpdate (prevProps) { + if (this.props.tenant.name !== prevProps.tenant.name) { + this.updateData() + } + } + + componentWillUnmount () { + if (this.timer) { + clearTimeout(this.timer) + this.timer = null + } + } + + render () { + const { error, change } = this.state + if (error) { + return (<Alert>{this.state.error}</Alert>) + } + return ( + <React.Fragment> + {change && change.map((item, idx) => ( + <div className='row' key={idx}> + <ChangePanel + globalExpanded={true} + change={item} + /> + </div> + ))} + </React.Fragment>) + } +} + +export default connect(state => ({tenant: state.tenant}))(ChangeStatusPage) diff --git a/web/src/routes.js b/web/src/routes.js index 34da870ef..db6d0012c 100644 --- a/web/src/routes.js +++ b/web/src/routes.js @@ -13,6 +13,7 @@ // under the License. import StatusPage from './pages/Status' +import ChangeStatusPage from './pages/ChangeStatus' import JobPage from './pages/Job' import JobsPage from './pages/Jobs' import BuildPage from './pages/Build' @@ -42,6 +43,10 @@ const routes = () => [ component: BuildsPage }, { + to: '/status/change/:changeId', + component: ChangeStatusPage + }, + { to: '/stream/:buildId', component: StreamPage }, |