summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-12-31 05:21:28 +0000
committerGerrit Code Review <review@openstack.org>2018-12-31 05:21:28 +0000
commit566bc2173f15bdf96bb4f78a417db4284ff77739 (patch)
treeb5cf3c3f9eddebad2c8f1c877cec890cacf43439
parent29fe7892a12c518864813e506214684394f6d3b5 (diff)
parente5da1e11491e429c6427c8f46f2c2db2bf620682 (diff)
Merge "web: refactor change page to use a reducer"
-rw-r--r--web/src/actions/change.js61
-rw-r--r--web/src/pages/ChangeStatus.jsx55
-rw-r--r--web/src/reducers/change.js44
-rw-r--r--web/src/reducers/index.js2
4 files changed, 127 insertions, 35 deletions
diff --git a/web/src/actions/change.js b/web/src/actions/change.js
new file mode 100644
index 0000000..9029828
--- /dev/null
+++ b/web/src/actions/change.js
@@ -0,0 +1,61 @@
1/* global Promise */
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 API from '../api'
17
18export const CHANGE_FETCH_REQUEST = 'CHANGE_FETCH_REQUEST'
19export const CHANGE_FETCH_SUCCESS = 'CHANGE_FETCH_SUCCESS'
20export const CHANGE_FETCH_FAIL = 'CHANGE_FETCH_FAIL'
21
22export const requestChange = () => ({
23 type: CHANGE_FETCH_REQUEST
24})
25
26export const receiveChange = json => ({
27 type: CHANGE_FETCH_SUCCESS,
28 change: json,
29 receivedAt: Date.now()
30})
31
32const failedChange = error => ({
33 type: CHANGE_FETCH_FAIL,
34 error
35})
36
37const fetchChange = (tenant, changeId) => dispatch => {
38 dispatch(requestChange())
39 return API.fetchChangeStatus(tenant.apiPrefix, changeId)
40 .then(response => dispatch(receiveChange(response.data)))
41 .catch(error => dispatch(failedChange(error)))
42}
43
44const shouldFetchChange = state => {
45 const change = state.change
46 if (!change) {
47 return true
48 }
49 if (change.isFetching) {
50 return false
51 }
52 return true
53}
54
55export const fetchChangeIfNeeded = (tenant, change, force) => (
56 dispatch, getState) => {
57 if (force || shouldFetchChange(getState())) {
58 return dispatch(fetchChange(tenant, change))
59 }
60 return Promise.resolve()
61}
diff --git a/web/src/pages/ChangeStatus.jsx b/web/src/pages/ChangeStatus.jsx
index 3ffb88e..0abbf6d 100644
--- a/web/src/pages/ChangeStatus.jsx
+++ b/web/src/pages/ChangeStatus.jsx
@@ -16,53 +16,34 @@
16import * as React from 'react' 16import * as React from 'react'
17import PropTypes from 'prop-types' 17import PropTypes from 'prop-types'
18import { connect } from 'react-redux' 18import { connect } from 'react-redux'
19import {
20 Alert,
21} from 'patternfly-react'
22 19
23import { fetchChangeStatus } from '../api' 20import { fetchChangeIfNeeded } from '../actions/change'
24import ChangePanel from '../containers/status/ChangePanel' 21import ChangePanel from '../containers/status/ChangePanel'
22import Refreshable from '../containers/Refreshable'
25 23
26 24
27class ChangeStatusPage extends React.Component { 25class ChangeStatusPage extends Refreshable {
28 static propTypes = { 26 static propTypes = {
29 match: PropTypes.object.isRequired, 27 match: PropTypes.object.isRequired,
30 tenant: PropTypes.object 28 tenant: PropTypes.object,
29 remoteData: PropTypes.object,
30 dispatch: PropTypes.func
31 } 31 }
32 32
33 state = { 33 updateData = (force) => {
34 change: null, 34 this.props.dispatch(fetchChangeIfNeeded(
35 error: null, 35 this.props.tenant, this.props.match.params.changeId, force))
36 } 36 .then(() => {this.timer = setTimeout(this.updateData, 5000)})
37
38 updateData = () => {
39 // Clear any running timer 37 // Clear any running timer
40 if (this.timer) { 38 if (this.timer) {
41 clearTimeout(this.timer) 39 clearTimeout(this.timer)
42 this.timer = null 40 this.timer = null
43 } 41 }
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 } 42 }
54 43
55 componentDidMount () { 44 componentDidMount () {
56 document.title = this.props.match.params.changeId + ' | Zuul Status' 45 document.title = this.props.match.params.changeId + ' | Zuul Status'
57 if (this.props.tenant.name) { 46 super.componentDidMount()
58 this.updateData()
59 }
60 }
61
62 componentDidUpdate (prevProps) {
63 if (this.props.tenant.name !== prevProps.tenant.name) {
64 this.updateData()
65 }
66 } 47 }
67 48
68 componentWillUnmount () { 49 componentWillUnmount () {
@@ -73,12 +54,13 @@ class ChangeStatusPage extends React.Component {
73 } 54 }
74 55
75 render () { 56 render () {
76 const { error, change } = this.state 57 const { remoteData } = this.props
77 if (error) { 58 const change = remoteData.change
78 return (<Alert>{this.state.error}</Alert>)
79 }
80 return ( 59 return (
81 <React.Fragment> 60 <React.Fragment>
61 <div style={{float: 'right'}}>
62 {this.renderSpinner()}
63 </div><br />
82 {change && change.map((item, idx) => ( 64 {change && change.map((item, idx) => (
83 <div className='row' key={idx}> 65 <div className='row' key={idx}>
84 <ChangePanel 66 <ChangePanel
@@ -91,4 +73,7 @@ class ChangeStatusPage extends React.Component {
91 } 73 }
92} 74}
93 75
94export default connect(state => ({tenant: state.tenant}))(ChangeStatusPage) 76export default connect(state => ({
77 tenant: state.tenant,
78 remoteData: state.change
79}))(ChangeStatusPage)
diff --git a/web/src/reducers/change.js b/web/src/reducers/change.js
new file mode 100644
index 0000000..73bb545
--- /dev/null
+++ b/web/src/reducers/change.js
@@ -0,0 +1,44 @@
1// Copyright 2018 Red Hat, Inc
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations
13// under the License.
14
15import {
16 CHANGE_FETCH_FAIL,
17 CHANGE_FETCH_REQUEST,
18 CHANGE_FETCH_SUCCESS
19} from '../actions/change'
20
21export default (state = {
22 isFetching: false,
23 change: null
24}, action) => {
25 switch (action.type) {
26 case CHANGE_FETCH_REQUEST:
27 return {
28 isFetching: true,
29 change: state.change
30 }
31 case CHANGE_FETCH_SUCCESS:
32 return {
33 isFetching: false,
34 change: action.change,
35 }
36 case CHANGE_FETCH_FAIL:
37 return {
38 isFetching: false,
39 change: state.change,
40 }
41 default:
42 return state
43 }
44}
diff --git a/web/src/reducers/index.js b/web/src/reducers/index.js
index fd70148..1b59fb8 100644
--- a/web/src/reducers/index.js
+++ b/web/src/reducers/index.js
@@ -15,6 +15,7 @@
15import { combineReducers } from 'redux' 15import { combineReducers } from 'redux'
16 16
17import configErrors from './configErrors' 17import configErrors from './configErrors'
18import change from './change'
18import errors from './errors' 19import errors from './errors'
19import info from './info' 20import info from './info'
20import job from './job' 21import job from './job'
@@ -24,6 +25,7 @@ import tenant from './tenant'
24import tenants from './tenants' 25import tenants from './tenants'
25 26
26const reducers = { 27const reducers = {
28 change,
27 info, 29 info,
28 job, 30 job,
29 jobs, 31 jobs,