Browse Source

Merge "web: refactor change page to use a reducer"

tags/3.4.0
Zuul 5 months ago
parent
commit
566bc2173f
4 changed files with 127 additions and 35 deletions
  1. 61
    0
      web/src/actions/change.js
  2. 20
    35
      web/src/pages/ChangeStatus.jsx
  3. 44
    0
      web/src/reducers/change.js
  4. 2
    0
      web/src/reducers/index.js

+ 61
- 0
web/src/actions/change.js View File

@@ -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
+
16
+import * as API from '../api'
17
+
18
+export const CHANGE_FETCH_REQUEST = 'CHANGE_FETCH_REQUEST'
19
+export const CHANGE_FETCH_SUCCESS = 'CHANGE_FETCH_SUCCESS'
20
+export const CHANGE_FETCH_FAIL = 'CHANGE_FETCH_FAIL'
21
+
22
+export const requestChange = () => ({
23
+  type: CHANGE_FETCH_REQUEST
24
+})
25
+
26
+export const receiveChange = json => ({
27
+  type: CHANGE_FETCH_SUCCESS,
28
+  change: json,
29
+  receivedAt: Date.now()
30
+})
31
+
32
+const failedChange = error => ({
33
+  type: CHANGE_FETCH_FAIL,
34
+  error
35
+})
36
+
37
+const 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
+
44
+const 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
+
55
+export 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
+}

+ 20
- 35
web/src/pages/ChangeStatus.jsx View File

@@ -16,53 +16,34 @@
16 16
 import * as React from 'react'
17 17
 import PropTypes from 'prop-types'
18 18
 import { connect } from 'react-redux'
19
-import {
20
-  Alert,
21
-} from 'patternfly-react'
22 19
 
23
-import { fetchChangeStatus } from '../api'
20
+import { fetchChangeIfNeeded } from '../actions/change'
24 21
 import ChangePanel from '../containers/status/ChangePanel'
22
+import Refreshable from '../containers/Refreshable'
25 23
 
26 24
 
27
-class ChangeStatusPage extends React.Component {
25
+class ChangeStatusPage extends Refreshable {
28 26
   static propTypes = {
29 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 = {
34
-    change: null,
35
-    error: null,
36
-  }
37
-
38
-  updateData = () => {
33
+  updateData = (force) => {
34
+    this.props.dispatch(fetchChangeIfNeeded(
35
+      this.props.tenant, this.props.match.params.changeId, force))
36
+      .then(() => {this.timer = setTimeout(this.updateData, 5000)})
39 37
     // Clear any running timer
40 38
     if (this.timer) {
41 39
       clearTimeout(this.timer)
42 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 44
   componentDidMount () {
56 45
     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
-    }
46
+    super.componentDidMount()
66 47
   }
67 48
 
68 49
   componentWillUnmount () {
@@ -73,12 +54,13 @@ class ChangeStatusPage extends React.Component {
73 54
   }
74 55
 
75 56
   render () {
76
-    const { error, change } = this.state
77
-    if (error) {
78
-      return (<Alert>{this.state.error}</Alert>)
79
-    }
57
+    const { remoteData } = this.props
58
+    const change = remoteData.change
80 59
     return (
81 60
       <React.Fragment>
61
+        <div style={{float: 'right'}}>
62
+          {this.renderSpinner()}
63
+        </div><br />
82 64
         {change && change.map((item, idx) => (
83 65
           <div className='row' key={idx}>
84 66
             <ChangePanel
@@ -91,4 +73,7 @@ class ChangeStatusPage extends React.Component {
91 73
   }
92 74
 }
93 75
 
94
-export default connect(state => ({tenant: state.tenant}))(ChangeStatusPage)
76
+export default connect(state => ({
77
+  tenant: state.tenant,
78
+  remoteData: state.change
79
+}))(ChangeStatusPage)

+ 44
- 0
web/src/reducers/change.js View File

@@ -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
+
15
+import {
16
+  CHANGE_FETCH_FAIL,
17
+  CHANGE_FETCH_REQUEST,
18
+  CHANGE_FETCH_SUCCESS
19
+} from '../actions/change'
20
+
21
+export 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
+}

+ 2
- 0
web/src/reducers/index.js View File

@@ -15,6 +15,7 @@
15 15
 import { combineReducers } from 'redux'
16 16
 
17 17
 import configErrors from './configErrors'
18
+import change from './change'
18 19
 import errors from './errors'
19 20
 import info from './info'
20 21
 import job from './job'
@@ -24,6 +25,7 @@ import tenant from './tenant'
24 25
 import tenants from './tenants'
25 26
 
26 27
 const reducers = {
28
+  change,
27 29
   info,
28 30
   job,
29 31
   jobs,

Loading…
Cancel
Save