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

238 lines
6.5 KiB
JavaScript

import React, { Component, Fragment } from 'react';
import { If, Then } from 'react-if';
import ReduxForm from 'declarative-redux-form';
import { SubmissionError, destroy } from 'redux-form';
import { Margin, Padding } from 'styled-components-spacing';
import { compose, graphql } from 'react-apollo';
import { connect } from 'react-redux';
import { set, destroyAll } from 'react-redux-values';
import intercept from 'apr-intercept';
import get from 'lodash.get';
import {
ViewContainer,
Message,
MessageTitle,
MessageDescription,
Button
} from 'joyent-ui-toolkit';
import {
PostCreation,
PostCreationContent,
PostCreationTitle
} from 'joyent-ui-resource-widgets';
import { Provider as ResourceSteps } from 'joyent-ui-resource-step';
import parseError from '@state/parse-error';
import { Forms, Values } from '@root/constants';
import ListServiceGroups from '@graphql/list-service-groups.gql';
import CreateServiceGroup from '@graphql/create-service-group.gql';
import GetServiceGroup from '@graphql/get-service-group.gql';
import Template from './steps/template';
import Name from './steps/name';
const { SGC_F } = Forms;
const { SGC_N_V, SGC_T_V } = Values;
class CreateTemplate extends Component {
constructor(...args) {
super(...args);
this.isValids = {};
}
setIsValid = name => ref => {
if (!ref) {
return;
}
const { isValid } = ref;
if (!isValid) {
return;
}
this.isValids = Object.assign({}, this.isValids, {
[name]: isValid
});
};
isFormValid = () => {
const { steps } = this.props;
return Boolean(
Object.keys(this.isValids).filter(
name => !this.isValids[name](steps[name] || {})
).length
);
};
isStepValid = step => {
const { steps } = this.props;
const fn = this.isValids[step];
const values = steps[step];
if (!fn || !values) {
return true;
}
return fn(values);
};
render() {
const { match, steps, handleDefocus, handleSubmit } = this.props;
const { params } = match;
const { step } = params;
const { template, name } = steps;
const disabled = !(
template &&
template.id &&
name &&
name.name &&
name.capacity
);
return (
<ViewContainer main>
<Padding top="5">
<ResourceSteps namespace="service-groups/~create">
<Margin bottom="4">
<Template
ref={this.setIsValid('template')}
expanded={step === 'template'}
next="name"
saved={get(steps, 'template.id', false)}
onDefocus={handleDefocus(SGC_T_V)}
preview={template}
isValid={this.isStepValid('template')}
/>
</Margin>
<Margin bottom="4">
<Name
ref={this.setIsValid('name')}
expanded={step === 'name'}
saved={get(steps, 'name.name', false)}
onDefocus={handleDefocus(SGC_N_V)}
preview={name}
isValid={this.isStepValid('name')}
/>
</Margin>
</ResourceSteps>
<Margin top="5" bottom="3">
<ReduxForm form={SGC_F} onSubmit={handleSubmit}>
{({ handleSubmit, submitting, error }) => (
<Fragment>
<If condition={error}>
<Then>
<Margin bottom="4">
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{error}</MessageDescription>
</Message>
</Margin>
</Then>
</If>
<form onSubmit={handleSubmit}>
<Button loading={submitting} disabled={disabled}>
Deploy
</Button>
</form>
</Fragment>
)}
</ReduxForm>
</Margin>
</Padding>
</ViewContainer>
);
}
}
export const Success = ({ match }) => {
const id = match.params.sg;
return (
<ViewContainer main>
<Margin top="5">
<PostCreation id={id} object="service group">
<PostCreationTitle>
You have successfully created a service group
</PostCreationTitle>
<PostCreationContent>
Your service group has been created and is currently being
processed. It should only take a few minutes and will then appear in
your console.
</PostCreationContent>
</PostCreation>
</Margin>
</ViewContainer>
);
};
export default compose(
graphql(CreateServiceGroup, { name: 'createServiceGroup' }),
connect(({ form, values = {} }) => ({
forms: Object.keys(form),
steps: {
name: get(values, SGC_N_V),
template: get(values, SGC_T_V)
}
})),
connect(null, (dispatch, { forms, steps, history, createServiceGroup }) => ({
handleDefocus: name => value => {
return dispatch(set({ name, value }));
},
handleSubmit: async () => {
const [err, res] = await intercept(
createServiceGroup({
variables: {
name: steps.name.name,
template: steps.template.id,
capacity: steps.name.capacity
},
update: (proxy, { data: { createGroup: group } }) => {
try {
proxy.writeQuery({
query: ListServiceGroups,
data: {
groups: proxy
.readQuery({ query: ListServiceGroups })
.groups.concat([group])
}
});
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
}
try {
proxy.writeQuery({
query: GetServiceGroup,
variables: { id: group.id },
data: { group }
});
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);
}
}
})
);
if (err) {
throw new SubmissionError({
_error: parseError(err)
});
}
const { data } = res;
const { createGroup: cg } = data;
const { id } = cg;
dispatch([destroyAll(), forms.map(name => destroy(name))]);
history.push(`/service-groups/~create/${id}/success`);
}
}))
)(CreateTemplate);