joyent-portal/consoles/my-joy-images/src/containers/create.js

190 lines
4.6 KiB
JavaScript

import React from 'react';
import { Margin } from 'styled-components-spacing';
import ReduxForm from 'declarative-redux-form';
import { destroyAll } from 'react-redux-values';
import { destroy, stopSubmit } from 'redux-form';
import { connect } from 'react-redux';
import { compose, graphql } from 'react-apollo';
import intercept from 'apr-intercept';
import get from 'lodash.get';
import uniqBy from 'lodash.uniqby';
import omit from 'lodash.omit';
import {
ViewContainer,
H2,
Button,
StatusLoader,
Message,
MessageTitle,
MessageDescription
} from 'joyent-ui-toolkit';
import CreateImage from '@graphql/create-image.gql';
import GetInstance from '@graphql/get-instance.gql';
import Details from '@containers/create-image/details';
import Tags from '@containers/create-image/tags';
import { Forms } from '@root/constants';
import parseError from '@state/parse-error';
const Create = ({
step,
history,
location,
match,
disabled,
loading,
loadingError,
handleSubmit
}) => (
<ViewContainer>
{loading ? (
<Margin top="4">
<StatusLoader />
</Margin>
) : null}
{loadingError ? (
<Margin top="4">
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{loadingError}</MessageDescription>
</Message>
</Margin>
) : null}
{!loading && !loadingError ? (
<Margin top="4" bottom="5">
<H2>Create Image</H2>
</Margin>
) : null}
{!loading && !loadingError ? (
<Details
history={history}
match={match}
step="name"
expanded={step === 'name'}
/>
) : null}
{!loading && !loadingError ? (
<Tags
history={history}
match={match}
step="tag"
expanded={step === 'tag'}
/>
) : null}
<ReduxForm form={Forms.CREATE_FORM} onSubmit={handleSubmit}>
{({ handleSubmit, submitting }) =>
!loading && !loadingError ? (
<form onSubmit={handleSubmit}>
<Margin top={step === 'tag' ? '7' : '4'}>
<Button disabled={disabled} loading={submitting}>
Create Image
</Button>
</Margin>
</form>
) : null
}
</ReduxForm>
</ViewContainer>
);
export default compose(
graphql(CreateImage, { name: 'createImage' }),
graphql(GetInstance, {
options: ({ match }) => ({
ssr: false,
variables: {
id: get(match, 'params.instance')
}
}),
props: ({ data: { loading, error, machine, variables, ...rest } }) => {
const notFoundMsg = `Instance "${variables.name}" not found!`;
const notFound = !loading && !machine ? notFoundMsg : false;
return {
instance: machine,
loadingError: error ? parseError(error) : notFound,
loading
};
}
}),
connect(({ form, values }, { match }) => {
const step = get(match, 'params.step', 'name');
const name = get(form, `${Forms.FORM_DETAILS}.values.name`, '');
const version = get(form, `${Forms.FORM_DETAILS}.values.version`, '');
const disabled = !(name.length && version.length);
if (disabled) {
return { disabled, step };
}
const description = get(
form,
`${Forms.FORM_DETAILS}.values.description`,
'<instance-description>'
);
const tags = get(values, Forms.CREATE_TAGS, []);
return {
forms: Object.keys(form), // improve this
name,
description,
version,
tags,
disabled,
step
};
}),
connect(null, (dispatch, ownProps) => {
const {
name,
description,
version,
tags,
instance,
forms,
createImage,
history
} = ownProps;
return {
handleSubmit: async () => {
const _name = name.toLowerCase();
const _description = description.toLowerCase();
const _version = version.toLowerCase();
const _tags = uniqBy(tags, 'name').map(a => omit(a, 'expanded'));
const [err, res] = await intercept(
createImage({
variables: {
machine: instance.id,
name: _name,
version: _version,
description: _description,
tags: _tags
}
})
);
if (err) {
return dispatch(
stopSubmit(Forms.CREATE_FORM, {
_error: parseError(err)
})
);
}
dispatch([destroyAll(), forms.map(name => destroy(name))]);
const { data } = res;
const { createImageFromMachine } = data;
history.push(`/images/${createImageFromMachine.id}`);
}
};
})
)(Create);