summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
authorTristan Cacqueray <tdecacqu@redhat.com>2018-09-04 01:37:09 +0000
committerTristan Cacqueray <tdecacqu@redhat.com>2018-12-14 05:36:11 +0000
commitf61e19900f1c57cb9e773fa5d85bec91b620e0ef (patch)
tree60bf5b9ba38089be6744becfe7c55fb21d657fef /web
parentc933eac2ed1cf08ee86a968275348f558917fc6a (diff)
downloadzuul-f61e19900f1c57cb9e773fa5d85bec91b620e0ef.tar.gz
web: add change status page
This change adds a ChangeStatus page to display the status of a single change and updates the Change component to link the icon to the new page. Change-Id: I265f7a390fde33721624a0da7fe5bd1cde32dc37
Diffstat (limited to 'web')
-rw-r--r--web/src/api.js5
-rw-r--r--web/src/containers/status/Change.jsx23
-rw-r--r--web/src/pages/ChangeStatus.jsx94
-rw-r--r--web/src/routes.js5
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
},