Browse Source

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

tags/3.4.0
Zuul 5 months ago
parent
commit
92ccf5f642
4 changed files with 142 additions and 34 deletions
  1. 60
    0
      web/src/actions/labels.js
  2. 33
    34
      web/src/pages/Labels.jsx
  3. 2
    0
      web/src/reducers/index.js
  4. 47
    0
      web/src/reducers/labels.js

+ 60
- 0
web/src/actions/labels.js View File

@@ -0,0 +1,60 @@
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 * as API from '../api'
16
+
17
+export const LABELS_FETCH_REQUEST = 'LABELS_FETCH_REQUEST'
18
+export const LABELS_FETCH_SUCCESS = 'LABELS_FETCH_SUCCESS'
19
+export const LABELS_FETCH_FAIL = 'LABELS_FETCH_FAIL'
20
+
21
+export const requestLabels = () => ({
22
+  type: LABELS_FETCH_REQUEST
23
+})
24
+
25
+export const receiveLabels = (tenant, json) => ({
26
+  type: LABELS_FETCH_SUCCESS,
27
+  tenant: tenant,
28
+  labels: json,
29
+  receivedAt: Date.now()
30
+})
31
+
32
+const failedLabels = error => ({
33
+  type: LABELS_FETCH_FAIL,
34
+  error
35
+})
36
+
37
+const fetchLabels = (tenant) => dispatch => {
38
+  dispatch(requestLabels())
39
+  return API.fetchLabels(tenant.apiPrefix)
40
+    .then(response => dispatch(receiveLabels(tenant.name, response.data)))
41
+    .catch(error => dispatch(failedLabels(error)))
42
+}
43
+
44
+const shouldFetchLabels = (tenant, state) => {
45
+  const labels = state.labels.labels[tenant.name]
46
+  if (!labels || labels.length === 0) {
47
+    return true
48
+  }
49
+  if (labels.isFetching) {
50
+    return false
51
+  }
52
+  return false
53
+}
54
+
55
+export const fetchLabelsIfNeeded = (tenant, force) => (
56
+  dispatch, getState) => {
57
+    if (force || shouldFetchLabels(tenant, getState())) {
58
+      return dispatch(fetchLabels(tenant))
59
+    }
60
+}

+ 33
- 34
web/src/pages/Labels.jsx View File

@@ -17,39 +17,30 @@ import PropTypes from 'prop-types'
17 17
 import { connect } from 'react-redux'
18 18
 import { Table } from 'patternfly-react'
19 19
 
20
-import { fetchLabels } from '../api'
20
+import { fetchLabelsIfNeeded } from '../actions/labels'
21
+import Refreshable from '../containers/Refreshable'
21 22
 
22 23
 
23
-class LabelsPage extends React.Component {
24
+class LabelsPage extends Refreshable {
24 25
   static propTypes = {
25
-    tenant: PropTypes.object
26
+    tenant: PropTypes.object,
27
+    remoteData: PropTypes.object,
28
+    dispatch: PropTypes.func
26 29
   }
27 30
 
28
-  state = {
29
-    labels: null
30
-  }
31
-
32
-  updateData () {
33
-    fetchLabels(this.props.tenant.apiPrefix).then(response => {
34
-      this.setState({labels: response.data})
35
-    })
31
+  updateData (force) {
32
+    this.props.dispatch(fetchLabelsIfNeeded(this.props.tenant, force))
36 33
   }
37 34
 
38 35
   componentDidMount () {
39 36
     document.title = 'Zuul Labels'
40
-    if (this.props.tenant.name) {
41
-      this.updateData()
42
-    }
43
-  }
44
-
45
-  componentDidUpdate (prevProps) {
46
-    if (this.props.tenant.name !== prevProps.tenant.name) {
47
-      this.updateData()
48
-    }
37
+    super.componentDidMount()
49 38
   }
50 39
 
51 40
   render () {
52
-    const { labels } = this.state
41
+    const { remoteData } = this.props
42
+    const labels = remoteData.labels[this.props.tenant.name]
43
+
53 44
     if (!labels) {
54 45
       return (<p>Loading...</p>)
55 46
     }
@@ -68,19 +59,27 @@ class LabelsPage extends React.Component {
68 59
       })
69 60
     })
70 61
     return (
71
-      <Table.PfProvider
72
-        striped
73
-        bordered
74
-        hover
75
-        columns={columns}
76
-      >
77
-        <Table.Header/>
78
-        <Table.Body
79
-          rows={labels}
80
-          rowKey="name"
81
-        />
82
-      </Table.PfProvider>)
62
+      <React.Fragment>
63
+        <div style={{float: 'right'}}>
64
+          {this.renderSpinner()}
65
+        </div>
66
+        <Table.PfProvider
67
+          striped
68
+          bordered
69
+          hover
70
+          columns={columns}
71
+        >
72
+          <Table.Header/>
73
+          <Table.Body
74
+            rows={labels}
75
+            rowKey="name"
76
+          />
77
+        </Table.PfProvider>
78
+      </React.Fragment>)
83 79
   }
84 80
 }
85 81
 
86
-export default connect(state => ({tenant: state.tenant}))(LabelsPage)
82
+export default connect(state => ({
83
+  tenant: state.tenant,
84
+  remoteData: state.labels,
85
+}))(LabelsPage)

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

@@ -20,6 +20,7 @@ import errors from './errors'
20 20
 import info from './info'
21 21
 import job from './job'
22 22
 import jobs from './jobs'
23
+import labels from './labels'
23 24
 import project from './project'
24 25
 import projects from './projects'
25 26
 import status from './status'
@@ -31,6 +32,7 @@ const reducers = {
31 32
   info,
32 33
   job,
33 34
   jobs,
35
+  labels,
34 36
   project,
35 37
   projects,
36 38
   configErrors,

+ 47
- 0
web/src/reducers/labels.js View File

@@ -0,0 +1,47 @@
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
+  LABELS_FETCH_FAIL,
17
+  LABELS_FETCH_REQUEST,
18
+  LABELS_FETCH_SUCCESS
19
+} from '../actions/labels'
20
+
21
+import update from 'immutability-helper'
22
+
23
+export default (state = {
24
+  isFetching: false,
25
+  labels: {},
26
+}, action) => {
27
+  switch (action.type) {
28
+    case LABELS_FETCH_REQUEST:
29
+      return {
30
+        isFetching: true,
31
+        labels: state.labels,
32
+      }
33
+    case LABELS_FETCH_SUCCESS:
34
+      return {
35
+        isFetching: false,
36
+        labels: update(
37
+          state.labels, {$merge: {[action.tenant]: action.labels}}),
38
+      }
39
+    case LABELS_FETCH_FAIL:
40
+      return {
41
+        isFetching: false,
42
+        labels: state.labels,
43
+      }
44
+    default:
45
+      return state
46
+  }
47
+}

Loading…
Cancel
Save