store: Use redux to store composes

This commit is contained in:
sanne raymaekers 2020-04-28 15:10:43 +02:00
parent b17be18dfd
commit 3e797b92b0
9 changed files with 144 additions and 75 deletions

View file

@ -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);

View file

@ -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 (
<Card>
<CardHeader>Pending composes</CardHeader>
{ Object.entries(composes).map(([ id, compose ]) => {
return <CardBody key={ id }>
<label>{ id }</label>
<p>{ compose.architecture }, { compose.distribution }, { compose.image_type }</p>
<p>{ compose.status }</p>
</CardBody>;
})
}
</Card>);
}
}
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);

View file

@ -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 (
<React.Fragment>
@ -44,10 +31,10 @@ class LandingPage extends Component {
<Main>
<Flex>
<FlexItem breakpointMods={ [{ modifier: FlexModifiers.column }, { modifier: FlexModifiers['flex-1'] }] }>
<CreateImageCard onCompose={ this.onPendingCompose } />
<CreateImageCard />
</FlexItem>
<FlexItem breakpointMods={ [{ modifier: FlexModifiers.column }, { modifier: FlexModifiers['flex-1'] }] }>
<PendingImagesCard pendingComposeIds={ this.state.pendingComposeIds } />
<ImagesCard />
</FlexItem>
</Flex>
</Main>

View file

@ -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 (
<Card>
<CardHeader>Pending composes</CardHeader>
{ Object.entries(this.state.composeStatuses).map(([ id, status ]) => {
return <CardBody key={ id }><label>{ id }</label><p>{ status }</p></CardBody>;
})
}
</Card>);
}
}
PendingImagesCard.propTypes = {
pendingComposeIds: PropTypes.array,
};
export default PendingImagesCard;

View file

@ -0,0 +1,12 @@
import types from './types';
function updateCompose(compose) {
return {
type: types.UPDATE_COMPOSE,
compose
};
}
export default {
updateCompose,
};

View file

@ -0,0 +1 @@
export { default as actions } from './actions';

View file

@ -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
};
}
}

View file

@ -0,0 +1,6 @@
const UPDATE_COMPOSE = 'UPDATE_COMPOSE';
export default {
UPDATE_COMPOSE,
};

View file

@ -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;
}