summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-12-31 05:21:27 +0000
committerGerrit Code Review <review@openstack.org>2018-12-31 05:21:27 +0000
commit29fe7892a12c518864813e506214684394f6d3b5 (patch)
treecb218636b4548e6f412f92d24703c9ec1b4e1785
parente46cfe63e04bba058defb00f4b18fec0eb342b1f (diff)
parentf61e19900f1c57cb9e773fa5d85bec91b620e0ef (diff)
Merge "web: add change status page"
-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 28c1b39..75efe68 100644
--- a/web/src/api.js
+++ b/web/src/api.js
@@ -52,6 +52,7 @@ function getHomepageUrl (url) {
52 '/job/', 52 '/job/',
53 '/project/', 53 '/project/',
54 '/stream/', 54 '/stream/',
55 '/status/',
55 ] 56 ]
56 subDir.forEach(path => { 57 subDir.forEach(path => {
57 if (baseUrl.includes(path)) { 58 if (baseUrl.includes(path)) {
@@ -114,6 +115,9 @@ function fetchConfigErrors (apiPrefix) {
114function fetchStatus (apiPrefix) { 115function fetchStatus (apiPrefix) {
115 return Axios.get(apiUrl + apiPrefix + 'status') 116 return Axios.get(apiUrl + apiPrefix + 'status')
116} 117}
118function fetchChangeStatus (apiPrefix, changeId) {
119 return Axios.get(apiUrl + apiPrefix + 'status/change/' + changeId)
120}
117function fetchBuild (apiPrefix, buildId) { 121function fetchBuild (apiPrefix, buildId) {
118 return Axios.get(apiUrl + apiPrefix + 'build/' + buildId) 122 return Axios.get(apiUrl + apiPrefix + 'build/' + buildId)
119} 123}
@@ -134,6 +138,7 @@ function fetchJobs (apiPrefix) {
134export { 138export {
135 getHomepageUrl, 139 getHomepageUrl,
136 getStreamUrl, 140 getStreamUrl,
141 fetchChangeStatus,
137 fetchConfigErrors, 142 fetchConfigErrors,
138 fetchStatus, 143 fetchStatus,
139 fetchBuild, 144 fetchBuild,
diff --git a/web/src/containers/status/Change.jsx b/web/src/containers/status/Change.jsx
index ddd82a9..b4d9be3 100644
--- a/web/src/containers/status/Change.jsx
+++ b/web/src/containers/status/Change.jsx
@@ -14,6 +14,8 @@
14 14
15import * as React from 'react' 15import * as React from 'react'
16import PropTypes from 'prop-types' 16import PropTypes from 'prop-types'
17import { connect } from 'react-redux'
18import { Link } from 'react-router-dom'
17 19
18import LineAngleImage from '../../images/line-angle.png' 20import LineAngleImage from '../../images/line-angle.png'
19import LineTImage from '../../images/line-t.png' 21import LineTImage from '../../images/line-t.png'
@@ -24,7 +26,8 @@ class Change extends React.Component {
24 static propTypes = { 26 static propTypes = {
25 change: PropTypes.object.isRequired, 27 change: PropTypes.object.isRequired,
26 queue: PropTypes.object.isRequired, 28 queue: PropTypes.object.isRequired,
27 expanded: PropTypes.bool.isRequired 29 expanded: PropTypes.bool.isRequired,
30 tenant: PropTypes.object
28 } 31 }
29 32
30 renderStatusIcon (change) { 33 renderStatusIcon (change) {
@@ -47,10 +50,20 @@ class Change extends React.Component {
47 iconGlyph = 'pficon pficon-error-circle-o' 50 iconGlyph = 'pficon pficon-error-circle-o'
48 } 51 }
49 } 52 }
50 return ( 53 const icon = (
51 <span className={'zuul-build-status ' + iconGlyph} 54 <span
52 title={iconTitle} /> 55 className={'zuul-build-status ' + iconGlyph}
56 title={iconTitle} />
53 ) 57 )
58 if (change.live) {
59 return (
60 <Link to={this.props.tenant.linkPrefix + '/status/change/' + change.id}>
61 {icon}
62 </Link>
63 )
64 } else {
65 return icon
66 }
54 } 67 }
55 68
56 renderLineImg (change, i) { 69 renderLineImg (change, i) {
@@ -96,4 +109,4 @@ class Change extends React.Component {
96 } 109 }
97} 110}
98 111
99export default Change 112export 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 0000000..3ffb88e
--- /dev/null
+++ b/web/src/pages/ChangeStatus.jsx
@@ -0,0 +1,94 @@
1/* global setTimeout, clearTimeout */
2// Copyright 2018 Red Hat, Inc
3//
4// Licensed under the Apache License, Version 2.0 (the "License"); you may
5// not use this file except in compliance with the License. You may obtain
6// a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13// License for the specific language governing permissions and limitations
14// under the License.
15
16import * as React from 'react'
17import PropTypes from 'prop-types'
18import { connect } from 'react-redux'
19import {
20 Alert,
21} from 'patternfly-react'
22
23import { fetchChangeStatus } from '../api'
24import ChangePanel from '../containers/status/ChangePanel'
25
26
27class ChangeStatusPage extends React.Component {
28 static propTypes = {
29 match: PropTypes.object.isRequired,
30 tenant: PropTypes.object
31 }
32
33 state = {
34 change: null,
35 error: null,
36 }
37
38 updateData = () => {
39 // Clear any running timer
40 if (this.timer) {
41 clearTimeout(this.timer)
42 this.timer = null
43 }
44 this.setState({error: null})
45 fetchChangeStatus(
46 this.props.tenant.apiPrefix, this.props.match.params.changeId)
47 .then(response => {
48 this.setState({change: response.data})
49 }).catch(error => {
50 this.setState({error: error.message, change: null})
51 })
52 this.timer = setTimeout(this.updateData, 5000)
53 }
54
55 componentDidMount () {
56 document.title = this.props.match.params.changeId + ' | Zuul Status'
57 if (this.props.tenant.name) {
58 this.updateData()
59 }
60 }
61
62 componentDidUpdate (prevProps) {
63 if (this.props.tenant.name !== prevProps.tenant.name) {
64 this.updateData()
65 }
66 }
67
68 componentWillUnmount () {
69 if (this.timer) {
70 clearTimeout(this.timer)
71 this.timer = null
72 }
73 }
74
75 render () {
76 const { error, change } = this.state
77 if (error) {
78 return (<Alert>{this.state.error}</Alert>)
79 }
80 return (
81 <React.Fragment>
82 {change && change.map((item, idx) => (
83 <div className='row' key={idx}>
84 <ChangePanel
85 globalExpanded={true}
86 change={item}
87 />
88 </div>
89 ))}
90 </React.Fragment>)
91 }
92}
93
94export default connect(state => ({tenant: state.tenant}))(ChangeStatusPage)
diff --git a/web/src/routes.js b/web/src/routes.js
index 34da870..db6d001 100644
--- a/web/src/routes.js
+++ b/web/src/routes.js
@@ -13,6 +13,7 @@
13// under the License. 13// under the License.
14 14
15import StatusPage from './pages/Status' 15import StatusPage from './pages/Status'
16import ChangeStatusPage from './pages/ChangeStatus'
16import JobPage from './pages/Job' 17import JobPage from './pages/Job'
17import JobsPage from './pages/Jobs' 18import JobsPage from './pages/Jobs'
18import BuildPage from './pages/Build' 19import BuildPage from './pages/Build'
@@ -42,6 +43,10 @@ const routes = () => [
42 component: BuildsPage 43 component: BuildsPage
43 }, 44 },
44 { 45 {
46 to: '/status/change/:changeId',
47 component: ChangeStatusPage
48 },
49 {
45 to: '/stream/:buildId', 50 to: '/stream/:buildId',
46 component: StreamPage 51 component: StreamPage
47 }, 52 },