summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.openstack.org>2018-12-31 10:14:35 +0000
committerGerrit Code Review <review@openstack.org>2018-12-31 10:14:35 +0000
commit92ccf5f642d3a407ead7687f93e3d15d40d5f95f (patch)
tree1b8bbf4ca637043d1fe4b040e8157f57e24f9de2
parent98b1fc77d2248bbdeb9ad102a6ae000d8d09a30e (diff)
parent4b32dda7074d5769c4b63dac5578f6cad52beee1 (diff)
Merge "web: refactor labels page to use a reducer"
-rw-r--r--web/src/actions/labels.js60
-rw-r--r--web/src/pages/Labels.jsx67
-rw-r--r--web/src/reducers/index.js2
-rw-r--r--web/src/reducers/labels.js47
4 files changed, 142 insertions, 34 deletions
diff --git a/web/src/actions/labels.js b/web/src/actions/labels.js
new file mode 100644
index 0000000..0235500
--- /dev/null
+++ b/web/src/actions/labels.js
@@ -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
15import * as API from '../api'
16
17export const LABELS_FETCH_REQUEST = 'LABELS_FETCH_REQUEST'
18export const LABELS_FETCH_SUCCESS = 'LABELS_FETCH_SUCCESS'
19export const LABELS_FETCH_FAIL = 'LABELS_FETCH_FAIL'
20
21export const requestLabels = () => ({
22 type: LABELS_FETCH_REQUEST
23})
24
25export const receiveLabels = (tenant, json) => ({
26 type: LABELS_FETCH_SUCCESS,
27 tenant: tenant,
28 labels: json,
29 receivedAt: Date.now()
30})
31
32const failedLabels = error => ({
33 type: LABELS_FETCH_FAIL,
34 error
35})
36
37const 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
44const 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
55export const fetchLabelsIfNeeded = (tenant, force) => (
56 dispatch, getState) => {
57 if (force || shouldFetchLabels(tenant, getState())) {
58 return dispatch(fetchLabels(tenant))
59 }
60}
diff --git a/web/src/pages/Labels.jsx b/web/src/pages/Labels.jsx
index d262c14..e4145d2 100644
--- a/web/src/pages/Labels.jsx
+++ b/web/src/pages/Labels.jsx
@@ -17,39 +17,30 @@ import PropTypes from 'prop-types'
17import { connect } from 'react-redux' 17import { connect } from 'react-redux'
18import { Table } from 'patternfly-react' 18import { Table } from 'patternfly-react'
19 19
20import { fetchLabels } from '../api' 20import { fetchLabelsIfNeeded } from '../actions/labels'
21import Refreshable from '../containers/Refreshable'
21 22
22 23
23class LabelsPage extends React.Component { 24class LabelsPage extends Refreshable {
24 static propTypes = { 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 = { 31 updateData (force) {
29 labels: null 32 this.props.dispatch(fetchLabelsIfNeeded(this.props.tenant, force))
30 }
31
32 updateData () {
33 fetchLabels(this.props.tenant.apiPrefix).then(response => {
34 this.setState({labels: response.data})
35 })
36 } 33 }
37 34
38 componentDidMount () { 35 componentDidMount () {
39 document.title = 'Zuul Labels' 36 document.title = 'Zuul Labels'
40 if (this.props.tenant.name) { 37 super.componentDidMount()
41 this.updateData()
42 }
43 }
44
45 componentDidUpdate (prevProps) {
46 if (this.props.tenant.name !== prevProps.tenant.name) {
47 this.updateData()
48 }
49 } 38 }
50 39
51 render () { 40 render () {
52 const { labels } = this.state 41 const { remoteData } = this.props
42 const labels = remoteData.labels[this.props.tenant.name]
43
53 if (!labels) { 44 if (!labels) {
54 return (<p>Loading...</p>) 45 return (<p>Loading...</p>)
55 } 46 }
@@ -68,19 +59,27 @@ class LabelsPage extends React.Component {
68 }) 59 })
69 }) 60 })
70 return ( 61 return (
71 <Table.PfProvider 62 <React.Fragment>
72 striped 63 <div style={{float: 'right'}}>
73 bordered 64 {this.renderSpinner()}
74 hover 65 </div>
75 columns={columns} 66 <Table.PfProvider
76 > 67 striped
77 <Table.Header/> 68 bordered
78 <Table.Body 69 hover
79 rows={labels} 70 columns={columns}
80 rowKey="name" 71 >
81 /> 72 <Table.Header/>
82 </Table.PfProvider>) 73 <Table.Body
74 rows={labels}
75 rowKey="name"
76 />
77 </Table.PfProvider>
78 </React.Fragment>)
83 } 79 }
84} 80}
85 81
86export default connect(state => ({tenant: state.tenant}))(LabelsPage) 82export default connect(state => ({
83 tenant: state.tenant,
84 remoteData: state.labels,
85}))(LabelsPage)
diff --git a/web/src/reducers/index.js b/web/src/reducers/index.js
index 69b24d6..b4e3a8b 100644
--- a/web/src/reducers/index.js
+++ b/web/src/reducers/index.js
@@ -20,6 +20,7 @@ import errors from './errors'
20import info from './info' 20import info from './info'
21import job from './job' 21import job from './job'
22import jobs from './jobs' 22import jobs from './jobs'
23import labels from './labels'
23import project from './project' 24import project from './project'
24import projects from './projects' 25import projects from './projects'
25import status from './status' 26import status from './status'
@@ -31,6 +32,7 @@ const reducers = {
31 info, 32 info,
32 job, 33 job,
33 jobs, 34 jobs,
35 labels,
34 project, 36 project,
35 projects, 37 projects,
36 configErrors, 38 configErrors,
diff --git a/web/src/reducers/labels.js b/web/src/reducers/labels.js
new file mode 100644
index 0000000..8a04f20
--- /dev/null
+++ b/web/src/reducers/labels.js
@@ -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
15import {
16 LABELS_FETCH_FAIL,
17 LABELS_FETCH_REQUEST,
18 LABELS_FETCH_SUCCESS
19} from '../actions/labels'
20
21import update from 'immutability-helper'
22
23export 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}