summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Cacqueray <tdecacqu@redhat.com>2018-12-02 01:05:02 +0000
committerTristan Cacqueray <tdecacqu@redhat.com>2018-12-02 01:05:02 +0000
commit76867ca14aec3e7e6df8604e911826049b57946f (patch)
tree9ad76d6bee006fe76f194d37f986ef84e097d08d
parent300915538c04ebe782da31464fa937b204579d6a (diff)
web: break the reducers module into logical units
This change applies best practices to split the current reducers module in logical unit. Each reducer and its actions are moved into different modules to ease further refactor and follow-up tests. Change-Id: I75cc41ca3d31a61046868aafbc84505de661a99d
Notes
Notes (review): Code-Review+1: Artem Goncharov <artem.goncharov@gmail.com> Code-Review+2: Monty Taylor <mordred@inaugust.com> Code-Review+2: Tobias Henkel <tobias.henkel@bmw.de> Workflow+1: Monty Taylor <mordred@inaugust.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Thu, 06 Dec 2018 18:20:06 +0000 Reviewed-on: https://review.openstack.org/621385 Project: openstack-infra/zuul Branch: refs/heads/master
-rw-r--r--web/src/App.jsx3
-rw-r--r--web/src/App.test.jsx3
-rw-r--r--web/src/actions/configErrors.js28
-rw-r--r--web/src/actions/info.js27
-rw-r--r--web/src/actions/tenant.js37
-rw-r--r--web/src/containers/status/ChangePanel.test.jsx3
-rw-r--r--web/src/index.js7
-rw-r--r--web/src/pages/ConfigErrors.jsx2
-rw-r--r--web/src/reducers.js117
-rw-r--r--web/src/reducers/configErrors.js22
-rw-r--r--web/src/reducers/index.js27
-rw-r--r--web/src/reducers/info.js22
-rw-r--r--web/src/reducers/tenant.js22
-rw-r--r--web/src/store.js22
14 files changed, 218 insertions, 124 deletions
diff --git a/web/src/App.jsx b/web/src/App.jsx
index 5c22083..85d2009 100644
--- a/web/src/App.jsx
+++ b/web/src/App.jsx
@@ -29,7 +29,8 @@ import {
29 29
30import logo from './images/logo.png' 30import logo from './images/logo.png'
31import { routes } from './routes' 31import { routes } from './routes'
32import { fetchConfigErrorsAction, setTenantAction } from './reducers' 32import { fetchConfigErrorsAction } from './actions/configErrors'
33import { setTenantAction } from './actions/tenant'
33 34
34 35
35class App extends React.Component { 36class App extends React.Component {
diff --git a/web/src/App.test.jsx b/web/src/App.test.jsx
index 494e159..58a88f4 100644
--- a/web/src/App.test.jsx
+++ b/web/src/App.test.jsx
@@ -19,7 +19,8 @@ import ReactDOM from 'react-dom'
19import { Link, BrowserRouter as Router } from 'react-router-dom' 19import { Link, BrowserRouter as Router } from 'react-router-dom'
20import { Provider } from 'react-redux' 20import { Provider } from 'react-redux'
21 21
22import { createZuulStore, fetchInfoAction } from './reducers' 22import { fetchInfoAction } from './actions/info'
23import createZuulStore from './store'
23import App from './App' 24import App from './App'
24import TenantsPage from './pages/Tenants' 25import TenantsPage from './pages/Tenants'
25import StatusPage from './pages/Status' 26import StatusPage from './pages/Status'
diff --git a/web/src/actions/configErrors.js b/web/src/actions/configErrors.js
new file mode 100644
index 0000000..8f52f06
--- /dev/null
+++ b/web/src/actions/configErrors.js
@@ -0,0 +1,28 @@
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 { fetchConfigErrors } from '../api'
16
17export function fetchConfigErrorsAction (tenant) {
18 return (dispatch) => {
19 return fetchConfigErrors(tenant.apiPrefix)
20 .then(response => {
21 dispatch({type: 'FETCH_CONFIGERRORS_SUCCESS',
22 errors: response.data})
23 })
24 .catch(error => {
25 throw (error)
26 })
27 }
28}
diff --git a/web/src/actions/info.js b/web/src/actions/info.js
new file mode 100644
index 0000000..8894eef
--- /dev/null
+++ b/web/src/actions/info.js
@@ -0,0 +1,27 @@
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 { fetchInfo } from '../api'
16
17export function fetchInfoAction () {
18 return (dispatch) => {
19 return fetchInfo()
20 .then(response => {
21 dispatch({type: 'FETCH_INFO_SUCCESS', info: response.data.info})
22 })
23 .catch(error => {
24 throw (error)
25 })
26 }
27}
diff --git a/web/src/actions/tenant.js b/web/src/actions/tenant.js
new file mode 100644
index 0000000..992f4e9
--- /dev/null
+++ b/web/src/actions/tenant.js
@@ -0,0 +1,37 @@
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
15export function setTenantAction (name, whiteLabel) {
16 let apiPrefix = ''
17 let linkPrefix = ''
18 let routePrefix = ''
19 let defaultRoute = '/status'
20 if (!whiteLabel) {
21 apiPrefix = 'tenant/' + name + '/'
22 linkPrefix = '/t/' + name
23 routePrefix = '/t/:tenant'
24 defaultRoute = '/tenants'
25 }
26 return {
27 type: 'SET_TENANT',
28 tenant: {
29 name: name,
30 whiteLabel: whiteLabel,
31 defaultRoute: defaultRoute,
32 linkPrefix: linkPrefix,
33 apiPrefix: apiPrefix,
34 routePrefix: routePrefix
35 }
36 }
37}
diff --git a/web/src/containers/status/ChangePanel.test.jsx b/web/src/containers/status/ChangePanel.test.jsx
index f36c6a7..b4089fa 100644
--- a/web/src/containers/status/ChangePanel.test.jsx
+++ b/web/src/containers/status/ChangePanel.test.jsx
@@ -18,7 +18,8 @@ import ReactTestUtils from 'react-dom/test-utils'
18import { Link, BrowserRouter as Router } from 'react-router-dom' 18import { Link, BrowserRouter as Router } from 'react-router-dom'
19import { Provider } from 'react-redux' 19import { Provider } from 'react-redux'
20 20
21import { createZuulStore, setTenantAction } from '../../reducers' 21import { setTenantAction } from '../../actions/tenant'
22import createZuulStore from '../../store'
22import ChangePanel from './ChangePanel' 23import ChangePanel from './ChangePanel'
23 24
24 25
diff --git a/web/src/index.js b/web/src/index.js
index fb42857..933186e 100644
--- a/web/src/index.js
+++ b/web/src/index.js
@@ -25,12 +25,13 @@ import './index.css'
25 25
26import { getHomepageUrl } from './api' 26import { getHomepageUrl } from './api'
27import registerServiceWorker from './registerServiceWorker' 27import registerServiceWorker from './registerServiceWorker'
28import { createZuulStore, fetchInfoAction } from './reducers' 28import { fetchInfoAction } from './actions/info'
29import createZuulStore from './store'
29import App from './App' 30import App from './App'
30 31
31// This calls the /api/info endpoint asynchronously, the App is connected
32// with redux and it will update the info prop when fetch succeed.
33const store = createZuulStore() 32const store = createZuulStore()
33
34// Load info endpoint
34store.dispatch(fetchInfoAction()) 35store.dispatch(fetchInfoAction())
35 36
36ReactDOM.render( 37ReactDOM.render(
diff --git a/web/src/pages/ConfigErrors.jsx b/web/src/pages/ConfigErrors.jsx
index 04470c0..05aceec 100644
--- a/web/src/pages/ConfigErrors.jsx
+++ b/web/src/pages/ConfigErrors.jsx
@@ -19,7 +19,7 @@ import {
19 Icon 19 Icon
20} from 'patternfly-react' 20} from 'patternfly-react'
21 21
22import { fetchConfigErrorsAction } from '../reducers' 22import { fetchConfigErrorsAction } from '../actions/configErrors'
23 23
24class ConfigErrorsPage extends React.Component { 24class ConfigErrorsPage extends React.Component {
25 static propTypes = { 25 static propTypes = {
diff --git a/web/src/reducers.js b/web/src/reducers.js
deleted file mode 100644
index b02c9f6..0000000
--- a/web/src/reducers.js
+++ /dev/null
@@ -1,117 +0,0 @@
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// Redux store enable to share global variables through state
16// To update the store, use a reducer and dispatch method,
17// see the App.setTenant method
18//
19// The store contains:
20// info: the info object, tenant is set when white-label api
21// tenant: the current tenant name, only used with multi-tenant api
22
23import { applyMiddleware, createStore, combineReducers } from 'redux'
24import thunk from 'redux-thunk'
25
26import { fetchConfigErrors, fetchInfo } from './api'
27
28const infoReducer = (state = {}, action) => {
29 switch (action.type) {
30 case 'FETCH_INFO_SUCCESS':
31 return action.info
32 default:
33 return state
34 }
35}
36
37const configErrorsReducer = (state = [], action) => {
38 switch (action.type) {
39 case 'FETCH_CONFIGERRORS_SUCCESS':
40 return action.errors
41 default:
42 return state
43 }
44}
45
46const tenantReducer = (state = {}, action) => {
47 switch (action.type) {
48 case 'SET_TENANT':
49 return action.tenant
50 default:
51 return state
52 }
53}
54
55function createZuulStore() {
56 return createStore(combineReducers({
57 info: infoReducer,
58 tenant: tenantReducer,
59 configErrors: configErrorsReducer,
60 }), applyMiddleware(thunk))
61}
62
63// Reducer actions
64function fetchInfoAction () {
65 return (dispatch) => {
66 return fetchInfo()
67 .then(response => {
68 dispatch({type: 'FETCH_INFO_SUCCESS', info: response.data.info})
69 })
70 .catch(error => {
71 throw (error)
72 })
73 }
74}
75function fetchConfigErrorsAction (tenant) {
76 return (dispatch) => {
77 return fetchConfigErrors(tenant.apiPrefix)
78 .then(response => {
79 dispatch({type: 'FETCH_CONFIGERRORS_SUCCESS',
80 errors: response.data})
81 })
82 .catch(error => {
83 throw (error)
84 })
85 }
86}
87
88function setTenantAction (name, whiteLabel) {
89 let apiPrefix = ''
90 let linkPrefix = ''
91 let routePrefix = ''
92 let defaultRoute = '/status'
93 if (!whiteLabel) {
94 apiPrefix = 'tenant/' + name + '/'
95 linkPrefix = '/t/' + name
96 routePrefix = '/t/:tenant'
97 defaultRoute = '/tenants'
98 }
99 return {
100 type: 'SET_TENANT',
101 tenant: {
102 name: name,
103 whiteLabel: whiteLabel,
104 defaultRoute: defaultRoute,
105 linkPrefix: linkPrefix,
106 apiPrefix: apiPrefix,
107 routePrefix: routePrefix
108 }
109 }
110}
111
112export {
113 createZuulStore,
114 setTenantAction,
115 fetchConfigErrorsAction,
116 fetchInfoAction
117}
diff --git a/web/src/reducers/configErrors.js b/web/src/reducers/configErrors.js
new file mode 100644
index 0000000..dd0a284
--- /dev/null
+++ b/web/src/reducers/configErrors.js
@@ -0,0 +1,22 @@
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
15export default (state = [], action) => {
16 switch (action.type) {
17 case 'FETCH_CONFIGERRORS_SUCCESS':
18 return action.errors
19 default:
20 return state
21 }
22}
diff --git a/web/src/reducers/index.js b/web/src/reducers/index.js
new file mode 100644
index 0000000..6f287ae
--- /dev/null
+++ b/web/src/reducers/index.js
@@ -0,0 +1,27 @@
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 { combineReducers } from 'redux'
16
17import configErrors from './configErrors'
18import info from './info'
19import tenant from './tenant'
20
21const reducers = {
22 info,
23 configErrors,
24 tenant,
25}
26
27export default combineReducers(reducers)
diff --git a/web/src/reducers/info.js b/web/src/reducers/info.js
new file mode 100644
index 0000000..5386622
--- /dev/null
+++ b/web/src/reducers/info.js
@@ -0,0 +1,22 @@
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
15export default (state = {}, action) => {
16 switch (action.type) {
17 case 'FETCH_INFO_SUCCESS':
18 return action.info
19 default:
20 return state
21 }
22}
diff --git a/web/src/reducers/tenant.js b/web/src/reducers/tenant.js
new file mode 100644
index 0000000..b634b03
--- /dev/null
+++ b/web/src/reducers/tenant.js
@@ -0,0 +1,22 @@
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
15export default (state = {}, action) => {
16 switch (action.type) {
17 case 'SET_TENANT':
18 return action.tenant
19 default:
20 return state
21 }
22}
diff --git a/web/src/store.js b/web/src/store.js
new file mode 100644
index 0000000..bad6b19
--- /dev/null
+++ b/web/src/store.js
@@ -0,0 +1,22 @@
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 { applyMiddleware, createStore } from 'redux'
16import thunk from 'redux-thunk'
17
18import appReducers from './reducers'
19
20export default function createZuulStore() {
21 return createStore(appReducers, applyMiddleware(thunk))
22}