store: Use redux to store composes
This commit is contained in:
parent
b17be18dfd
commit
3e797b92b0
9 changed files with 144 additions and 75 deletions
|
|
@ -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);
|
||||
|
|
|
|||
70
src/SmartComponents/LandingPage/ImagesCard.js
Normal file
70
src/SmartComponents/LandingPage/ImagesCard.js
Normal 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);
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
12
src/SmartComponents/redux/actions.js
Normal file
12
src/SmartComponents/redux/actions.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import types from './types';
|
||||
|
||||
function updateCompose(compose) {
|
||||
return {
|
||||
type: types.UPDATE_COMPOSE,
|
||||
compose
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
updateCompose,
|
||||
};
|
||||
1
src/SmartComponents/redux/index.js
Normal file
1
src/SmartComponents/redux/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as actions } from './actions';
|
||||
22
src/SmartComponents/redux/reducers.js
Normal file
22
src/SmartComponents/redux/reducers.js
Normal 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
|
||||
};
|
||||
}
|
||||
}
|
||||
6
src/SmartComponents/redux/types.js
Normal file
6
src/SmartComponents/redux/types.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
const UPDATE_COMPOSE = 'UPDATE_COMPOSE';
|
||||
|
||||
export default {
|
||||
UPDATE_COMPOSE,
|
||||
};
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue