From 3e797b92b04ceb3955c3da91458149d258fcb2f3 Mon Sep 17 00:00:00 2001 From: sanne raymaekers Date: Tue, 28 Apr 2020 15:10:43 +0200 Subject: [PATCH] store: Use redux to store composes --- .../LandingPage/CreateImageCard.js | 27 ++++++- src/SmartComponents/LandingPage/ImagesCard.js | 70 +++++++++++++++++++ .../LandingPage/LandingPage.js | 19 +---- .../LandingPage/PendingImagesCard.js | 56 --------------- src/SmartComponents/redux/actions.js | 12 ++++ src/SmartComponents/redux/index.js | 1 + src/SmartComponents/redux/reducers.js | 22 ++++++ src/SmartComponents/redux/types.js | 6 ++ src/store/index.js | 6 ++ 9 files changed, 144 insertions(+), 75 deletions(-) create mode 100644 src/SmartComponents/LandingPage/ImagesCard.js delete mode 100644 src/SmartComponents/LandingPage/PendingImagesCard.js create mode 100644 src/SmartComponents/redux/actions.js create mode 100644 src/SmartComponents/redux/index.js create mode 100644 src/SmartComponents/redux/reducers.js create mode 100644 src/SmartComponents/redux/types.js diff --git a/src/SmartComponents/LandingPage/CreateImageCard.js b/src/SmartComponents/LandingPage/CreateImageCard.js index 68f2aa47..6065b2ab 100644 --- a/src/SmartComponents/LandingPage/CreateImageCard.js +++ b/src/SmartComponents/LandingPage/CreateImageCard.js @@ -1,5 +1,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { actions } from '../redux'; import { Button, @@ -32,8 +34,21 @@ class CreateImageCard extends Component { }] }; let api = new DefaultApi(); + let { updateCompose } = this.props; api.composeImage(request).then(response => { - this.props.onCompose(response.data.compose_id); + /* request failed? */ + if (response.data.compose_id === undefined) { + return; + } + + let compose = {}; + compose[response.data.compose_id] = { + status: 'request sent', + distribution: request.image_builds[0].distribution, + architecture: request.image_builds[0].architecture, + image_type: request.image_builds[0].image_type, + }; + updateCompose(compose); }); } @@ -54,8 +69,14 @@ class CreateImageCard extends Component { } } +function mapDispatchToProps(dispatch) { + return { + updateCompose: (compose) => dispatch(actions.updateCompose(compose)), + }; +} + CreateImageCard.propTypes = { - onCompose: PropTypes.func, + updateCompose: PropTypes.func, }; -export default CreateImageCard; +export default connect(() => {}, mapDispatchToProps)(CreateImageCard); diff --git a/src/SmartComponents/LandingPage/ImagesCard.js b/src/SmartComponents/LandingPage/ImagesCard.js new file mode 100644 index 00000000..7c538a99 --- /dev/null +++ b/src/SmartComponents/LandingPage/ImagesCard.js @@ -0,0 +1,70 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { connect } from 'react-redux'; +import { actions } from '../redux'; + +import { + Card, + CardHeader, + CardBody, +} from '@patternfly/react-core'; + +import { DefaultApi } from '@redhat-cloud-services/osbuild-installer'; + +class ImagesCard extends Component { + constructor(props) { + super(props); + this.pollComposeStatuses = this.pollComposeStatuses.bind(this); + } + + componentDidMount() { + this.interval = setInterval(() => this.pollComposeStatuses(), 8000); + } + + pollComposeStatuses() { + let api = new DefaultApi(); + let { updateCompose, composes } = this.props; + Object.entries(composes).map(([ id, compose ]) => { + api.getComposeStatus(id).then(response => { + let newCompose = {}; + newCompose[id] = Object.assign({}, compose, { status: response.data.status }); + updateCompose(newCompose); + }); + }); + } + + render() { + let { composes } = this.props; + return ( + + Pending composes + { Object.entries(composes).map(([ id, compose ]) => { + return + +

{ compose.architecture }, { compose.distribution }, { compose.image_type }

+

{ compose.status }

+
; + }) + } +
); + } +} + +function mapStateToProps(state) { + return { + composes: state.composes, + }; +} + +function mapDispatchToProps(dispatch) { + return { + updateCompose: (compose) => dispatch(actions.updateCompose(compose)), + }; +} + +ImagesCard.propTypes = { + composes: PropTypes.object, + updateCompose: PropTypes.func, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(ImagesCard); diff --git a/src/SmartComponents/LandingPage/LandingPage.js b/src/SmartComponents/LandingPage/LandingPage.js index 42d098aa..39eefdf4 100644 --- a/src/SmartComponents/LandingPage/LandingPage.js +++ b/src/SmartComponents/LandingPage/LandingPage.js @@ -9,7 +9,7 @@ import { } from '@redhat-cloud-services/frontend-components'; import CreateImageCard from './CreateImageCard'; -import PendingImagesCard from './PendingImagesCard.js'; +import ImagesCard from './ImagesCard.js'; /** * A smart component that handles all the api calls and data needed by the dumb components. @@ -21,20 +21,7 @@ import PendingImagesCard from './PendingImagesCard.js'; class LandingPage extends Component { constructor(props) { super(props); - - this.state = { - pendingComposeIds: [], - }; - - this.onPendingCompose = this.onPendingCompose.bind(this); } - - onPendingCompose(composeId) { - this.setState(oldState => { - return { pendingComposeIds: oldState.pendingComposeIds.concat(composeId) }; - }); - } - render() { return ( @@ -44,10 +31,10 @@ class LandingPage extends Component {
- + - +
diff --git a/src/SmartComponents/LandingPage/PendingImagesCard.js b/src/SmartComponents/LandingPage/PendingImagesCard.js deleted file mode 100644 index 1d420a1d..00000000 --- a/src/SmartComponents/LandingPage/PendingImagesCard.js +++ /dev/null @@ -1,56 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; - -import { - Card, - CardHeader, - CardBody, -} from '@patternfly/react-core'; - -import { DefaultApi } from '@redhat-cloud-services/osbuild-installer'; - -class PendingImagesCard extends Component { - constructor(props) { - super(props); - - this.state = { - composeStatuses: {}, - }; - - this.pollComposeIds = this.pollComposeIds.bind(this); - } - - componentDidMount() { - this.interval = setInterval(() => this.pollComposeIds(), 8000); - } - - pollComposeIds() { - let api = new DefaultApi(); - for (let id of this.props.pendingComposeIds) { - api.getComposeStatus(id).then(response => { - this.setState(oldState => { - let composeStatuses = Object.assign({}, oldState.composeStatuses); - composeStatuses[id] = response.data.status; - return { composeStatuses }; - }); - }); - } - } - - render() { - return ( - - Pending composes - { Object.entries(this.state.composeStatuses).map(([ id, status ]) => { - return

{ status }

; - }) - } -
); - } -} - -PendingImagesCard.propTypes = { - pendingComposeIds: PropTypes.array, -}; - -export default PendingImagesCard; diff --git a/src/SmartComponents/redux/actions.js b/src/SmartComponents/redux/actions.js new file mode 100644 index 00000000..f89235e8 --- /dev/null +++ b/src/SmartComponents/redux/actions.js @@ -0,0 +1,12 @@ +import types from './types'; + +function updateCompose(compose) { + return { + type: types.UPDATE_COMPOSE, + compose + }; +} + +export default { + updateCompose, +}; diff --git a/src/SmartComponents/redux/index.js b/src/SmartComponents/redux/index.js new file mode 100644 index 00000000..792ac234 --- /dev/null +++ b/src/SmartComponents/redux/index.js @@ -0,0 +1 @@ +export { default as actions } from './actions'; diff --git a/src/SmartComponents/redux/reducers.js b/src/SmartComponents/redux/reducers.js new file mode 100644 index 00000000..758f1f8e --- /dev/null +++ b/src/SmartComponents/redux/reducers.js @@ -0,0 +1,22 @@ +import types from './types'; + +// Example of action.compose +// { +// "xxxx-xxxx-xxxx-xxxx": { +// state: "uploading", +// distribution: "fedora-31", +// architecture: "x86_64", +// image_type: "qcow2" +// } +// }; + +export function composeReducer(state = { }, action) { + switch (action.type) { + case types.UPDATE_COMPOSE: + return Object.assign({}, state, action.compose); + default: + return { + ...state + }; + } +} diff --git a/src/SmartComponents/redux/types.js b/src/SmartComponents/redux/types.js new file mode 100644 index 00000000..382ce47a --- /dev/null +++ b/src/SmartComponents/redux/types.js @@ -0,0 +1,6 @@ +const UPDATE_COMPOSE = 'UPDATE_COMPOSE'; + +export default { + UPDATE_COMPOSE, +}; + diff --git a/src/store/index.js b/src/store/index.js index 432e9359..cdf8cca1 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,6 +1,8 @@ import ReducerRegistry from '@redhat-cloud-services/frontend-components-utilities/files/ReducerRegistry'; import promiseMiddleware from 'redux-promise-middleware'; +import { composeReducer } from '../SmartComponents/redux/reducers'; + let registry; export function init (...middleware) { @@ -13,6 +15,10 @@ export function init (...middleware) { ...middleware ]); + registry.register({ + composes: composeReducer, + }); + return registry; }