feat(cp-frontend): DeploymentGroup reprovision flow
This commit is contained in:
parent
3aa7ec54bb
commit
4e241191bf
@ -28,6 +28,7 @@
|
|||||||
"jest-cli": "^20.0.4",
|
"jest-cli": "^20.0.4",
|
||||||
"joyent-manifest-editor": "^1.0.0",
|
"joyent-manifest-editor": "^1.0.0",
|
||||||
"joyent-ui-toolkit": "^1.1.0",
|
"joyent-ui-toolkit": "^1.1.0",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.isstring": "^4.0.1",
|
"lodash.isstring": "^4.0.1",
|
||||||
"normalized-styled-components": "^1.0.8",
|
"normalized-styled-components": "^1.0.8",
|
||||||
"param-case": "^2.1.1",
|
"param-case": "^2.1.1",
|
||||||
|
@ -45,8 +45,8 @@ const ButtonsRow = Row.extend`
|
|||||||
margin-bottom: ${remcalc(60)};
|
margin-bottom: ${remcalc(60)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Editor = ManifestEditor => ({ input }) =>
|
const Editor = ManifestEditor => ({ input, defaultValue }) =>
|
||||||
<ManifestEditor mode="yaml" {...input} />;
|
<ManifestEditor mode="yaml" {...input} value={input.value || defaultValue} />;
|
||||||
|
|
||||||
export const Name = ({ handleSubmit, onCancel, dirty }) =>
|
export const Name = ({ handleSubmit, onCancel, dirty }) =>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
@ -64,12 +64,23 @@ export const Name = ({ handleSubmit, onCancel, dirty }) =>
|
|||||||
</ButtonsRow>
|
</ButtonsRow>
|
||||||
</form>;
|
</form>;
|
||||||
|
|
||||||
export const Manifest = ({ handleSubmit, onCancel, dirty, mode, loading }) =>
|
export const Manifest = ({
|
||||||
|
handleSubmit,
|
||||||
|
onCancel,
|
||||||
|
dirty,
|
||||||
|
defaultValue,
|
||||||
|
mode,
|
||||||
|
loading
|
||||||
|
}) =>
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<Bundle load={() => import('joyent-manifest-editor')}>
|
<Bundle load={() => import('joyent-manifest-editor')}>
|
||||||
{ManifestEditor =>
|
{ManifestEditor =>
|
||||||
ManifestEditor
|
ManifestEditor
|
||||||
? <Field name="manifest" component={Editor(ManifestEditor)} />
|
? <Field
|
||||||
|
name="manifest"
|
||||||
|
defaultValue={defaultValue}
|
||||||
|
component={Editor(ManifestEditor)}
|
||||||
|
/>
|
||||||
: <Dots2 />}
|
: <Dots2 />}
|
||||||
</Bundle>
|
</Bundle>
|
||||||
<ButtonsRow>
|
<ButtonsRow>
|
||||||
@ -82,7 +93,7 @@ export const Manifest = ({ handleSubmit, onCancel, dirty, mode, loading }) =>
|
|||||||
|
|
||||||
export const Review = ({ handleSubmit, onCancel, dirty, ...state }) => {
|
export const Review = ({ handleSubmit, onCancel, dirty, ...state }) => {
|
||||||
const serviceList = forceArray(state.services).map(({ name, image }) =>
|
const serviceList = forceArray(state.services).map(({ name, image }) =>
|
||||||
<ServiceCard>
|
<ServiceCard key={name}>
|
||||||
<Dl>
|
<Dl>
|
||||||
<dt><ServiceName>{name}</ServiceName></dt>
|
<dt><ServiceName>{name}</ServiceName></dt>
|
||||||
<dt><ImageTitle>Image:</ImageTitle> <Image>{image}</Image></dt>
|
<dt><ImageTitle>Image:</ImageTitle> <Image>{image}</Image></dt>
|
||||||
|
@ -18,11 +18,14 @@ import {
|
|||||||
const STATUSES = [
|
const STATUSES = [
|
||||||
'CREATED',
|
'CREATED',
|
||||||
'RESTARTING',
|
'RESTARTING',
|
||||||
|
'PROVISIONING',
|
||||||
|
'READY',
|
||||||
'RUNNING',
|
'RUNNING',
|
||||||
'PAUSED',
|
'PAUSED',
|
||||||
'EXITED',
|
'EXITED',
|
||||||
'DELETED',
|
'DELETED',
|
||||||
'STOPPED',
|
'STOPPED',
|
||||||
|
'STOPPING',
|
||||||
'FAILED'
|
'FAILED'
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -46,6 +49,14 @@ const Dot = styled.div`
|
|||||||
background-color: yellow;
|
background-color: yellow;
|
||||||
`};
|
`};
|
||||||
|
|
||||||
|
${is('provisioning')`
|
||||||
|
background-color: yellow;
|
||||||
|
`};
|
||||||
|
|
||||||
|
${is('ready')`
|
||||||
|
background-color: yellow;
|
||||||
|
`};
|
||||||
|
|
||||||
${is('running')`
|
${is('running')`
|
||||||
background-color: ${props => props.theme.green};
|
background-color: ${props => props.theme.green};
|
||||||
`};
|
`};
|
||||||
@ -62,6 +73,10 @@ const Dot = styled.div`
|
|||||||
background-color: ${props => props.theme.secondaryActive};
|
background-color: ${props => props.theme.secondaryActive};
|
||||||
`};
|
`};
|
||||||
|
|
||||||
|
${is('stopping')`
|
||||||
|
background-color: orange;
|
||||||
|
`};
|
||||||
|
|
||||||
${is('stopped')`
|
${is('stopped')`
|
||||||
background-color: ${props => props.theme.red};
|
background-color: ${props => props.theme.red};
|
||||||
`};
|
`};
|
||||||
|
@ -1,270 +1,18 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
import { reduxForm } from 'redux-form';
|
|
||||||
import { compose, graphql } from 'react-apollo';
|
|
||||||
import { Redirect } from 'react-router-dom';
|
|
||||||
import intercept from 'apr-intercept';
|
|
||||||
import paramCase from 'param-case';
|
|
||||||
|
|
||||||
import DeploymentGroupBySlug from '@graphql/DeploymentGroupBySlug.gql';
|
import DeploymentGroupEditOrCreate from './edit-or-create';
|
||||||
import DeploymentGroupCreateMutation from '@graphql/DeploymentGroupCreate.gql';
|
|
||||||
import DeploymentGroupProvisionMutation from '@graphql/DeploymentGroupProvision.gql';
|
|
||||||
import DeploymentGroupConfigQuery from '@graphql/DeploymentGroupConfig.gql';
|
|
||||||
|
|
||||||
import { client } from '@state/store';
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { Name, Manifest, Review } from '@components/deployment-groups/create';
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
import { H2 } from 'joyent-ui-toolkit';
|
import { H2 } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
const validateName = async ({ name = '' }) => {
|
export default ({ loading, error, manifest = '', deploymentGroup = null }) =>
|
||||||
const { data } = await client.query({
|
|
||||||
fetchPolicy: 'network-only',
|
|
||||||
query: DeploymentGroupBySlug,
|
|
||||||
variables: {
|
|
||||||
slug: paramCase(name.trim())
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (data.deploymentGroups.length) {
|
|
||||||
// eslint-disable-next-line no-throw-literal
|
|
||||||
throw { name: `"${name}" already exists!` };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const NameForm = reduxForm({
|
|
||||||
form: 'create-deployment-group',
|
|
||||||
destroyOnUnmount: true,
|
|
||||||
forceUnregisterOnUnmount: true,
|
|
||||||
asyncValidate: validateName
|
|
||||||
})(Name);
|
|
||||||
|
|
||||||
const ManifestForm = reduxForm({
|
|
||||||
form: 'create-deployment-group',
|
|
||||||
destroyOnUnmount: true,
|
|
||||||
forceUnregisterOnUnmount: true
|
|
||||||
})(Manifest);
|
|
||||||
|
|
||||||
const ReviewForm = reduxForm({
|
|
||||||
form: 'create-deployment-group',
|
|
||||||
destroyOnUnmount: true,
|
|
||||||
forceUnregisterOnUnmount: true
|
|
||||||
})(Review);
|
|
||||||
|
|
||||||
// TODO: move state to redux. why: because in redux we can cache transactional
|
|
||||||
// state between refreshes
|
|
||||||
class DeploymentGroupCreate extends Component {
|
|
||||||
state = {
|
|
||||||
name: '',
|
|
||||||
manifest: '',
|
|
||||||
services: [],
|
|
||||||
loading: false,
|
|
||||||
error: null
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.stages = {
|
|
||||||
name: this.renderNameForm.bind(this),
|
|
||||||
manifest: this.renderManifestEditor.bind(this),
|
|
||||||
review: this.renderReview.bind(this)
|
|
||||||
};
|
|
||||||
|
|
||||||
this.handleNameSubmit = this.handleNameSubmit.bind(this);
|
|
||||||
this.handleManifestSubmit = this.handleManifestSubmit.bind(this);
|
|
||||||
this.handleReviewSubmit = this.handleReviewSubmit.bind(this);
|
|
||||||
this.handleCancel = this.handleCancel.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNameSubmit({ name = '' }) {
|
|
||||||
this.setState({ name }, () =>
|
|
||||||
this.redirect({ stage: 'manifest', prog: true })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleManifestSubmit({ manifest = '' }) {
|
|
||||||
const { config } = this.props;
|
|
||||||
const { name } = this.state;
|
|
||||||
|
|
||||||
const getConfig = async () => {
|
|
||||||
const [err, conf] = await intercept(
|
|
||||||
config({
|
|
||||||
deploymentGroupName: name,
|
|
||||||
type: 'COMPOSE',
|
|
||||||
format: 'YAML',
|
|
||||||
raw: manifest
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
return this.setState({
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data } = conf;
|
|
||||||
const { config: services } = data;
|
|
||||||
|
|
||||||
this.setState({ loading: false, services }, () => {
|
|
||||||
this.redirect({ stage: 'review', prog: true });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setState({ manifest, loading: true }, getConfig);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleReviewSubmit() {
|
|
||||||
const { history } = this.props;
|
|
||||||
|
|
||||||
const submit = async () => {
|
|
||||||
const { id, slug } = await this.createDeploymentGroup();
|
|
||||||
|
|
||||||
if (!id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const manifest = await this.provision(id);
|
|
||||||
|
|
||||||
if (!manifest) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
history.push(`/deployment-groups/${slug}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setState({ loading: true }, submit);
|
|
||||||
}
|
|
||||||
|
|
||||||
createDeploymentGroup = async () => {
|
|
||||||
const { name } = this.state;
|
|
||||||
const { createDeploymentGroup } = this.props;
|
|
||||||
|
|
||||||
const [err, res] = await intercept(createDeploymentGroup({ name }));
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
this.setState({
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return err ? null : res.data.createDeploymentGroup;
|
|
||||||
};
|
|
||||||
|
|
||||||
provision = async deploymentGroupId => {
|
|
||||||
const { manifest } = this.state;
|
|
||||||
const { provisionManifest } = this.props;
|
|
||||||
|
|
||||||
const [err] = await intercept(
|
|
||||||
provisionManifest({
|
|
||||||
deploymentGroupId,
|
|
||||||
type: 'COMPOSE',
|
|
||||||
format: 'YAML',
|
|
||||||
raw: manifest
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
this.setState({
|
|
||||||
error: err.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return err ? null : true;
|
|
||||||
};
|
|
||||||
|
|
||||||
renderNameForm() {
|
|
||||||
return (
|
|
||||||
<NameForm onSubmit={this.handleNameSubmit} onCancel={this.handleCancel} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderManifestEditor() {
|
|
||||||
return (
|
|
||||||
<ManifestForm
|
|
||||||
onSubmit={this.handleManifestSubmit}
|
|
||||||
onCancel={this.handleCancel}
|
|
||||||
loading={this.state.loading}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderReview() {
|
|
||||||
return (
|
|
||||||
<ReviewForm
|
|
||||||
onSubmit={this.handleReviewSubmit}
|
|
||||||
onCancel={this.handleCancel}
|
|
||||||
{...this.state}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleCancel() {
|
|
||||||
const { history } = this.props;
|
|
||||||
|
|
||||||
history.push('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
redirect({ stage = 'name', prog = false }) {
|
|
||||||
const { match, history } = this.props;
|
|
||||||
|
|
||||||
const pathname = match.url.replace(/~create(.*)/, '~create');
|
|
||||||
const to = `${pathname}/${stage}`;
|
|
||||||
|
|
||||||
if (!prog) {
|
|
||||||
return <Redirect to={to} />;
|
|
||||||
}
|
|
||||||
|
|
||||||
history.push(to);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { err } = this.state;
|
|
||||||
const { match } = this.props;
|
|
||||||
const stage = match.params.stage;
|
|
||||||
|
|
||||||
if (!stage) {
|
|
||||||
return this.redirect({ stage: 'name' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.stages[stage]) {
|
|
||||||
return this.redirect({ stage: 'name' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stage !== 'name' && !this.state.name) {
|
|
||||||
return this.redirect({ stage: 'name' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stage === 'review' && !this.state.manifest) {
|
|
||||||
return this.redirect({ stage: 'manifest' });
|
|
||||||
}
|
|
||||||
|
|
||||||
const view = this.stages[stage]();
|
|
||||||
|
|
||||||
const error = err ? <span>{err}</span> : null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<LayoutContainer>
|
<LayoutContainer>
|
||||||
<H2>Creating deployment group</H2>
|
<H2>Creating deployment group</H2>
|
||||||
{error}
|
{loading && <DeploymentGroupsLoading />}
|
||||||
{view}
|
{error && <span>{error.toString()}</span>}
|
||||||
</LayoutContainer>
|
<DeploymentGroupEditOrCreate
|
||||||
);
|
create
|
||||||
}
|
manifest={manifest}
|
||||||
}
|
deploymentGroup={deploymentGroup}
|
||||||
|
/>
|
||||||
export default compose(
|
</LayoutContainer>;
|
||||||
graphql(DeploymentGroupCreateMutation, {
|
|
||||||
props: ({ mutate }) => ({
|
|
||||||
createDeploymentGroup: variables => mutate({ variables })
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
graphql(DeploymentGroupProvisionMutation, {
|
|
||||||
props: ({ mutate }) => ({
|
|
||||||
provisionManifest: variables => mutate({ variables })
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
graphql(DeploymentGroupConfigQuery, {
|
|
||||||
props: ({ mutate }) => ({
|
|
||||||
config: variables => mutate({ variables })
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)(DeploymentGroupCreate);
|
|
||||||
|
@ -0,0 +1,298 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { reduxForm } from 'redux-form';
|
||||||
|
import { compose, graphql } from 'react-apollo';
|
||||||
|
import { withRouter } from 'react-router';
|
||||||
|
import { Redirect } from 'react-router-dom';
|
||||||
|
import intercept from 'apr-intercept';
|
||||||
|
import paramCase from 'param-case';
|
||||||
|
|
||||||
|
import DeploymentGroupBySlugQuery from '@graphql/DeploymentGroupBySlug.gql';
|
||||||
|
import DeploymentGroupCreateMutation from '@graphql/DeploymentGroupCreate.gql';
|
||||||
|
import DeploymentGroupProvisionMutation from '@graphql/DeploymentGroupProvision.gql';
|
||||||
|
import DeploymentGroupConfigQuery from '@graphql/DeploymentGroupConfig.gql';
|
||||||
|
|
||||||
|
import { client } from '@state/store';
|
||||||
|
import { Name, Manifest, Review } from '@components/deployment-groups/create';
|
||||||
|
|
||||||
|
// TODO: move state to redux. why: because in redux we can cache transactional
|
||||||
|
// state between refreshes
|
||||||
|
class DeploymentGroupEditOrCreate extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
const { create, edit } = props;
|
||||||
|
const type = create ? 'create' : 'edit';
|
||||||
|
|
||||||
|
const NameForm =
|
||||||
|
create &&
|
||||||
|
reduxForm({
|
||||||
|
form: `${type}-deployment-group`,
|
||||||
|
destroyOnUnmount: true,
|
||||||
|
forceUnregisterOnUnmount: true,
|
||||||
|
asyncValidate: async ({ name = '' }) => {
|
||||||
|
const { data } = await client.query({
|
||||||
|
fetchPolicy: 'network-only',
|
||||||
|
query: DeploymentGroupBySlugQuery,
|
||||||
|
variables: {
|
||||||
|
slug: paramCase(name.trim())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.deploymentGroups.length) {
|
||||||
|
// eslint-disable-next-line no-throw-literal
|
||||||
|
throw { name: `"${name}" already exists!` };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})(Name);
|
||||||
|
|
||||||
|
const ManifestForm = reduxForm({
|
||||||
|
form: `${type}-deployment-group`,
|
||||||
|
destroyOnUnmount: true,
|
||||||
|
forceUnregisterOnUnmount: true
|
||||||
|
})(Manifest);
|
||||||
|
|
||||||
|
const ReviewForm = reduxForm({
|
||||||
|
form: `${type}-deployment-group`,
|
||||||
|
destroyOnUnmount: true,
|
||||||
|
forceUnregisterOnUnmount: true
|
||||||
|
})(Review);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
defaultStage: create ? 'name' : 'edit',
|
||||||
|
manifestStage: create ? 'manifest' : 'edit',
|
||||||
|
name: '',
|
||||||
|
manifest: '',
|
||||||
|
services: [],
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
NameForm,
|
||||||
|
ManifestForm,
|
||||||
|
ReviewForm
|
||||||
|
};
|
||||||
|
|
||||||
|
this.stages = {
|
||||||
|
name: create && this.renderNameForm.bind(this),
|
||||||
|
[create ? 'manifest' : 'edit']: this.renderManifestEditor.bind(this),
|
||||||
|
review: this.renderReview.bind(this)
|
||||||
|
};
|
||||||
|
|
||||||
|
this.handleNameSubmit =
|
||||||
|
type === 'create' && this.handleNameSubmit.bind(this);
|
||||||
|
|
||||||
|
this.handleManifestSubmit = this.handleManifestSubmit.bind(this);
|
||||||
|
this.handleReviewSubmit = this.handleReviewSubmit.bind(this);
|
||||||
|
this.handleCancel = this.handleCancel.bind(this);
|
||||||
|
|
||||||
|
if (edit) {
|
||||||
|
setTimeout(this.getDeploymentGroup, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
createDeploymentGroup = async () => {
|
||||||
|
const { createDeploymentGroup, deploymentGroup, edit } = this.props;
|
||||||
|
|
||||||
|
if (edit && (!deploymentGroup || !deploymentGroup.id)) {
|
||||||
|
this.setState({
|
||||||
|
error: 'Unexpected Error: Inexistent DeploymentGroup!'
|
||||||
|
});
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deploymentGroup && deploymentGroup.id) {
|
||||||
|
return deploymentGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { name } = this.state;
|
||||||
|
|
||||||
|
const [err, res] = await intercept(createDeploymentGroup({ name }));
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
this.setState({
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return err ? {} : res.data.createDeploymentGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
provision = async deploymentGroupId => {
|
||||||
|
const { manifest } = this.state;
|
||||||
|
const { provisionManifest } = this.props;
|
||||||
|
|
||||||
|
const [err] = await intercept(
|
||||||
|
provisionManifest({
|
||||||
|
deploymentGroupId,
|
||||||
|
type: 'COMPOSE',
|
||||||
|
format: 'YAML',
|
||||||
|
raw: manifest
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
this.setState({
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return err ? null : true;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleNameSubmit({ name = '' }) {
|
||||||
|
this.setState({ name }, () =>
|
||||||
|
this.redirect({ stage: 'manifest', prog: true })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleManifestSubmit({ manifest = '' }) {
|
||||||
|
const { name } = this.state;
|
||||||
|
|
||||||
|
const getConfig = async () => {
|
||||||
|
const [err, conf] = await intercept(
|
||||||
|
client.query({
|
||||||
|
query: DeploymentGroupConfigQuery,
|
||||||
|
variables: {
|
||||||
|
deploymentGroupName: name,
|
||||||
|
type: 'COMPOSE',
|
||||||
|
format: 'YAML',
|
||||||
|
raw: manifest
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return this.setState({
|
||||||
|
error: err.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = conf;
|
||||||
|
const { config: services } = data;
|
||||||
|
|
||||||
|
this.setState({ loading: false, services }, () => {
|
||||||
|
this.redirect({ stage: 'review', prog: true });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setState({ manifest, loading: true }, getConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleReviewSubmit() {
|
||||||
|
const { history } = this.props;
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
|
const { id, slug } = await this.createDeploymentGroup();
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const manifest = await this.provision(id);
|
||||||
|
|
||||||
|
if (!manifest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
history.push(`/deployment-groups/${slug}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setState({ loading: true }, submit);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel() {
|
||||||
|
const { history, create, deploymentGroup } = this.props;
|
||||||
|
|
||||||
|
history.push(create ? '/' : `/deployment-groups/${deploymentGroup.slug}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect({ stage = 'name', prog = false }) {
|
||||||
|
const { match, history, create } = this.props;
|
||||||
|
|
||||||
|
const regex = create ? /\/~create(.*)/ : /\/manifest(.*)/;
|
||||||
|
const to = match.url.replace(
|
||||||
|
regex,
|
||||||
|
create ? `/~create/${stage}` : `/manifest/${stage}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!prog) {
|
||||||
|
return <Redirect to={to} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
history.push(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNameForm() {
|
||||||
|
const { NameForm } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NameForm onSubmit={this.handleNameSubmit} onCancel={this.handleCancel} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderManifestEditor() {
|
||||||
|
const { ManifestForm } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ManifestForm
|
||||||
|
defaultValue={this.props.manifest}
|
||||||
|
onSubmit={this.handleManifestSubmit}
|
||||||
|
onCancel={this.handleCancel}
|
||||||
|
loading={this.state.loading}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderReview() {
|
||||||
|
const { ReviewForm } = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReviewForm
|
||||||
|
onSubmit={this.handleReviewSubmit}
|
||||||
|
onCancel={this.handleCancel}
|
||||||
|
{...this.state}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { error, defaultStage, manifestStage } = this.state;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <span>{error}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { match, create } = this.props;
|
||||||
|
const stage = match.params.stage;
|
||||||
|
|
||||||
|
if (!stage) {
|
||||||
|
return this.redirect({ stage: defaultStage });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.stages[stage]) {
|
||||||
|
return this.redirect({ stage: defaultStage });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (create && stage !== 'name' && !this.state.name) {
|
||||||
|
return this.redirect({ stage: defaultStage });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stage === 'review' && !this.state.manifest) {
|
||||||
|
return this.redirect({ stage: manifestStage });
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.stages[stage]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
graphql(DeploymentGroupCreateMutation, {
|
||||||
|
props: ({ mutate }) => ({
|
||||||
|
createDeploymentGroup: variables => mutate({ variables })
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
graphql(DeploymentGroupProvisionMutation, {
|
||||||
|
props: ({ mutate }) => ({
|
||||||
|
provisionManifest: variables => mutate({ variables })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)(withRouter(DeploymentGroupEditOrCreate));
|
@ -1,12 +1,11 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { graphql } from 'react-apollo';
|
||||||
import intercept from 'apr-intercept';
|
import intercept from 'apr-intercept';
|
||||||
|
|
||||||
import DeploymentGroupImportMutation from '@graphql/DeploymentGroupImport.gql';
|
import DeploymentGroupImportMutation from '@graphql/DeploymentGroupImport.gql';
|
||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
import { Dots2 } from 'styled-text-spinners';
|
|
||||||
import { H2 } from 'joyent-ui-toolkit';
|
import { H2 } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
class DeploymentGroupImport extends Component {
|
class DeploymentGroupImport extends Component {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export { default as DeploymentGroupList } from './list';
|
export { default as DeploymentGroupList } from './list';
|
||||||
export { default as DeploymentGroupCreate } from './create';
|
export { default as DeploymentGroupCreate } from './create';
|
||||||
export { default as DeploymentGroupImport } from './import';
|
export { default as DeploymentGroupImport } from './import';
|
||||||
|
export { default as DeploymentGroupManifest } from './manifest';
|
||||||
|
@ -8,11 +8,11 @@ import forceArray from 'force-array';
|
|||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { Loader, ErrorMessage } from '@components/messaging';
|
import { ErrorMessage } from '@components/messaging';
|
||||||
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
import DeploymentGroupsQuery from '@graphql/DeploymentGroups.gql';
|
import DeploymentGroupsQuery from '@graphql/DeploymentGroups.gql';
|
||||||
import DeploymentGroupsImportableQuery from '@graphql/DeploymentGroupsImportable.gql';
|
import DeploymentGroupsImportableQuery from '@graphql/DeploymentGroupsImportable.gql';
|
||||||
import { Button, H2, H3, Small } from 'joyent-ui-toolkit';
|
import { H2, H3, Small } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
const Title = H2.extend`
|
const Title = H2.extend`
|
||||||
margin-top: ${remcalc(2)};
|
margin-top: ${remcalc(2)};
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { compose, graphql } from 'react-apollo';
|
||||||
|
import get from 'lodash.get';
|
||||||
|
|
||||||
|
import ManifestQuery from '@graphql/Manifest.gql';
|
||||||
|
import DeploymentGroupBySlugQuery from '@graphql/DeploymentGroupBySlug.gql';
|
||||||
|
|
||||||
|
import DeploymentGroupEditOrCreate from './edit-or-create';
|
||||||
|
import { LayoutContainer } from '@components/layout';
|
||||||
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
|
import { H2 } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
|
const Manifest = ({
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
manifest = '',
|
||||||
|
deploymentGroup = null
|
||||||
|
}) => {
|
||||||
|
const _loading = !loading ? null : <DeploymentGroupsLoading />;
|
||||||
|
const _error = !error ? null : <span>{error.toString()}</span>;
|
||||||
|
|
||||||
|
const _view = (loading || !deploymentGroup)
|
||||||
|
? null
|
||||||
|
: <DeploymentGroupEditOrCreate
|
||||||
|
edit
|
||||||
|
manifest={manifest}
|
||||||
|
deploymentGroup={deploymentGroup}
|
||||||
|
/>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LayoutContainer>
|
||||||
|
<H2>Edit Manifest</H2>
|
||||||
|
{_error}
|
||||||
|
{_loading}
|
||||||
|
{_view}
|
||||||
|
</LayoutContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
graphql(ManifestQuery, {
|
||||||
|
options: props => ({
|
||||||
|
variables: {
|
||||||
|
deploymentGroupSlug: props.match.params.deploymentGroup
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
props: ({ data: { deploymentGroup, loading, error } }) => ({
|
||||||
|
manifest: get(deploymentGroup, 'version.manifest.raw', ''),
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
graphql(DeploymentGroupBySlugQuery, {
|
||||||
|
options: props => ({
|
||||||
|
variables: {
|
||||||
|
slug: props.match.params.deploymentGroup
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
props: ({ data: { deploymentGroups, loading, error } }) => ({
|
||||||
|
deploymentGroup: deploymentGroups && deploymentGroups.length
|
||||||
|
? deploymentGroups[0]
|
||||||
|
: null,
|
||||||
|
loading,
|
||||||
|
error
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)(Manifest);
|
@ -6,7 +6,7 @@ import { Row } from 'react-styled-flexboxgrid';
|
|||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
|
|
||||||
import { LayoutContainer } from '@components/layout';
|
import { LayoutContainer } from '@components/layout';
|
||||||
import { Loader, ErrorMessage } from '@components/messaging';
|
import { ErrorMessage } from '@components/messaging';
|
||||||
import { InstanceListItem, EmptyInstances } from '@components/instances';
|
import { InstanceListItem, EmptyInstances } from '@components/instances';
|
||||||
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
import { DeploymentGroupsLoading } from '@components/deployment-groups';
|
||||||
import { H2 } from 'joyent-ui-toolkit';
|
import { H2 } from 'joyent-ui-toolkit';
|
||||||
@ -40,6 +40,8 @@ class InstanceList extends Component {
|
|||||||
return (
|
return (
|
||||||
<LayoutContainer>
|
<LayoutContainer>
|
||||||
<Title>Instances</Title>
|
<Title>Instances</Title>
|
||||||
|
{_error}
|
||||||
|
{_loading}
|
||||||
{instanceList}
|
{instanceList}
|
||||||
</LayoutContainer>
|
</LayoutContainer>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
#import "./DeploymentGroupInfo.gql"
|
||||||
|
|
||||||
query DeploymentGroupBySlug($slug: String!) {
|
query DeploymentGroupBySlug($slug: String!) {
|
||||||
deploymentGroups(slug: $slug) {
|
deploymentGroups(slug: $slug) {
|
||||||
id
|
...DeploymentGroupInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,5 @@ fragment DeploymentGroupInfo on DeploymentGroup {
|
|||||||
id
|
id
|
||||||
name
|
name
|
||||||
slug
|
slug
|
||||||
|
imported
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
mutation provisionManifest($deploymentGroupId: ID!, $type: ManifestType!, $format: ManifestFormat!, $raw: String!) {
|
||||||
provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, raw: $raw) {
|
provisionManifest(deploymentGroupId: $deploymentGroupId, type: $type, format: $format, raw: $raw) {
|
||||||
manifestId
|
|
||||||
scale {
|
scale {
|
||||||
serviceName
|
serviceName
|
||||||
replicas
|
replicas
|
||||||
|
12
packages/cp-frontend/src/graphql/Manifest.gql
Normal file
12
packages/cp-frontend/src/graphql/Manifest.gql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
query ManifestById($deploymentGroupSlug: String!) {
|
||||||
|
deploymentGroup(slug: $deploymentGroupSlug) {
|
||||||
|
version {
|
||||||
|
manifest {
|
||||||
|
id
|
||||||
|
type
|
||||||
|
format
|
||||||
|
raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,8 @@ import { InstanceList } from '@containers/instances';
|
|||||||
import {
|
import {
|
||||||
DeploymentGroupList,
|
DeploymentGroupList,
|
||||||
DeploymentGroupCreate,
|
DeploymentGroupCreate,
|
||||||
DeploymentGroupImport
|
DeploymentGroupImport,
|
||||||
|
DeploymentGroupManifest
|
||||||
} from '@containers/deployment-groups';
|
} from '@containers/deployment-groups';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -66,6 +67,11 @@ const Router = (
|
|||||||
<Route path="/" exact component={rootRedirect} />
|
<Route path="/" exact component={rootRedirect} />
|
||||||
<Route path="/deployment-groups" exact component={DeploymentGroupList} />
|
<Route path="/deployment-groups" exact component={DeploymentGroupList} />
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="/deployment-groups/:deploymentGroup/services-list"
|
||||||
|
component={ServicesMenu}
|
||||||
|
/>
|
||||||
|
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/~create/:stage?"
|
path="/deployment-groups/~create/:stage?"
|
||||||
@ -87,7 +93,6 @@ const Router = (
|
|||||||
exact
|
exact
|
||||||
component={deploymentGroupRedirect}
|
component={deploymentGroupRedirect}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup/instances"
|
path="/deployment-groups/:deploymentGroup/instances"
|
||||||
@ -96,13 +101,28 @@ const Router = (
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup/services-list"
|
path="/deployment-groups/:deploymentGroup/manifest/:stage?"
|
||||||
component={ServicesMenu}
|
exact
|
||||||
|
component={DeploymentGroupManifest}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup/services-list"
|
path="/deployment-groups/:deploymentGroup/services-list"
|
||||||
component={ServiceList}
|
component={ServiceList}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="/deployment-groups/:deploymentGroup/services-topology"
|
||||||
|
component={ServicesTopology}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route
|
||||||
|
path="/deployment-groups/:deploymentGroup/services/:service/instances"
|
||||||
|
exact
|
||||||
|
component={InstanceList}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup/services-list/:service/scale"
|
path="/deployment-groups/:deploymentGroup/services-list/:service/scale"
|
||||||
exact
|
exact
|
||||||
@ -118,10 +138,7 @@ const Router = (
|
|||||||
path="/deployment-groups/:deploymentGroup/services-topology"
|
path="/deployment-groups/:deploymentGroup/services-topology"
|
||||||
component={ServicesMenu}
|
component={ServicesMenu}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path="/deployment-groups/:deploymentGroup/services-topology"
|
|
||||||
component={ServicesTopology}
|
|
||||||
/>
|
|
||||||
<Route
|
<Route
|
||||||
path="/deployment-groups/:deploymentGroup/services-topology/:service/scale"
|
path="/deployment-groups/:deploymentGroup/services-topology/:service/scale"
|
||||||
exact
|
exact
|
||||||
@ -138,11 +155,6 @@ const Router = (
|
|||||||
exact
|
exact
|
||||||
component={serviceRedirect}
|
component={serviceRedirect}
|
||||||
/>
|
/>
|
||||||
<Route
|
|
||||||
path="/deployment-groups/:deploymentGroup/services/:service/instances"
|
|
||||||
exact
|
|
||||||
component={InstanceList}
|
|
||||||
/>
|
|
||||||
|
|
||||||
</Container>
|
</Container>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
111
yarn.lock
111
yarn.lock
@ -186,6 +186,10 @@ ansi-regex@^2.0.0, ansi-regex@^2.1.1:
|
|||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||||
|
|
||||||
|
ansi-regex@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||||
|
|
||||||
ansi-styles@^1.1.0:
|
ansi-styles@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
|
||||||
@ -216,8 +220,8 @@ anymatch@^1.3.0:
|
|||||||
micromatch "^2.1.5"
|
micromatch "^2.1.5"
|
||||||
|
|
||||||
apollo-client@^1.4.0:
|
apollo-client@^1.4.0:
|
||||||
version "1.5.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.5.0.tgz#c0ce752f2fe1945dca2eaaa62c7907fdde384563"
|
resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-1.6.0.tgz#d2b831fd8e6e6c045ce91dc8b86a920d44fd77a9"
|
||||||
dependencies:
|
dependencies:
|
||||||
graphql "^0.10.0"
|
graphql "^0.10.0"
|
||||||
graphql-anywhere "^3.0.1"
|
graphql-anywhere "^3.0.1"
|
||||||
@ -493,6 +497,10 @@ ast-types@0.9.0:
|
|||||||
version "0.9.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623"
|
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.0.tgz#c8721c8747ae4d5b29b929e99c5317b4e8745623"
|
||||||
|
|
||||||
|
ast-types@0.9.6:
|
||||||
|
version "0.9.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9"
|
||||||
|
|
||||||
async-each@^1.0.0:
|
async-each@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
|
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
|
||||||
@ -1757,12 +1765,12 @@ camelcase@^4.0.0, camelcase@^4.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
|
||||||
|
|
||||||
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
caniuse-db@^1.0.30000187, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||||
version "1.0.30000694"
|
version "1.0.30000696"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000694.tgz#02009f4f82d2f0126e4c691b7cd5adb351935c01"
|
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000696.tgz#e71f5c61e1f96c7a3af4e791ac5db55e11737604"
|
||||||
|
|
||||||
caniuse-lite@^1.0.30000684:
|
caniuse-lite@^1.0.30000684:
|
||||||
version "1.0.30000694"
|
version "1.0.30000696"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000694.tgz#1492dab7c10c608c9d37a723e6e3e7873e0ce94f"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000696.tgz#30f2695d2a01a0dfd779a26ab83f4d134b3da5cc"
|
||||||
|
|
||||||
capture-stack-trace@^1.0.0:
|
capture-stack-trace@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
@ -3358,8 +3366,8 @@ eslint-plugin-import@^2.3.0:
|
|||||||
read-pkg-up "^2.0.0"
|
read-pkg-up "^2.0.0"
|
||||||
|
|
||||||
eslint-plugin-jsx-a11y@^5.0.3:
|
eslint-plugin-jsx-a11y@^5.0.3:
|
||||||
version "5.0.3"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.0.3.tgz#4a939f76ec125010528823331bf948cc573380b6"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.1.0.tgz#4a829634344e7a90391a9fb0fbd19810737d79c5"
|
||||||
dependencies:
|
dependencies:
|
||||||
aria-query "^0.5.0"
|
aria-query "^0.5.0"
|
||||||
array-includes "^3.0.3"
|
array-includes "^3.0.3"
|
||||||
@ -3489,7 +3497,7 @@ esprima@^2.6.0, esprima@~2.7.1:
|
|||||||
version "2.7.3"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
|
||||||
|
|
||||||
esprima@^3.1.1:
|
esprima@^3.1.1, esprima@~3.1.0:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
|
||||||
|
|
||||||
@ -4374,8 +4382,8 @@ hash-base@^2.0.0:
|
|||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
|
|
||||||
hash.js@^1.0.0, hash.js@^1.0.3:
|
hash.js@^1.0.0, hash.js@^1.0.3:
|
||||||
version "1.1.1"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.1.tgz#5cb2e796499224e69fd0b00ed01d2d4a16e7a323"
|
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.2.tgz#bf5c887825cfe40b9efde7bf11bd2db26e6bf01b"
|
||||||
dependencies:
|
dependencies:
|
||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
@ -4439,12 +4447,12 @@ home-or-tmp@^2.0.0:
|
|||||||
os-tmpdir "^1.0.1"
|
os-tmpdir "^1.0.1"
|
||||||
|
|
||||||
hosted-git-info@^2.1.4:
|
hosted-git-info@^2.1.4:
|
||||||
version "2.4.2"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67"
|
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
|
||||||
|
|
||||||
html-tags@^1.1.1:
|
html-tags@^2.0.0:
|
||||||
version "1.2.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-1.2.0.tgz#c78de65b5663aa597989dd2b7ab49200d7e4db98"
|
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-2.0.0.tgz#10b30a386085f43cede353cc8fa7cb0deeea668b"
|
||||||
|
|
||||||
http-errors@^1.3.0, http-errors@~1.6.1:
|
http-errors@^1.3.0, http-errors@~1.6.1:
|
||||||
version "1.6.1"
|
version "1.6.1"
|
||||||
@ -4999,7 +5007,7 @@ istanbul-lib-hook@^1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
append-transform "^0.4.0"
|
append-transform "^0.4.0"
|
||||||
|
|
||||||
istanbul-lib-instrument@^1.7.2:
|
istanbul-lib-instrument@^1.7.2, istanbul-lib-instrument@^1.7.3:
|
||||||
version "1.7.3"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.3.tgz#925b239163eabdd68cc4048f52c2fa4f899ecfa7"
|
resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.3.tgz#925b239163eabdd68cc4048f52c2fa4f899ecfa7"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5712,7 +5720,7 @@ lodash.flattendeep@^4.4.0:
|
|||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
|
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
|
||||||
|
|
||||||
lodash.get@^4.1.2:
|
lodash.get@^4.1.2, lodash.get@^4.4.2:
|
||||||
version "4.4.2"
|
version "4.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
|
||||||
|
|
||||||
@ -6344,8 +6352,8 @@ nopt@~1.0.10:
|
|||||||
abbrev "1"
|
abbrev "1"
|
||||||
|
|
||||||
normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5:
|
normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5:
|
||||||
version "2.3.8"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb"
|
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
|
||||||
dependencies:
|
dependencies:
|
||||||
hosted-git-info "^2.1.4"
|
hosted-git-info "^2.1.4"
|
||||||
is-builtin-module "^1.0.0"
|
is-builtin-module "^1.0.0"
|
||||||
@ -6387,8 +6395,8 @@ npm-run-path@^2.0.0:
|
|||||||
path-key "^2.0.0"
|
path-key "^2.0.0"
|
||||||
|
|
||||||
npmlog@^4.0.2, npmlog@^4.1.0:
|
npmlog@^4.0.2, npmlog@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5"
|
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||||
dependencies:
|
dependencies:
|
||||||
are-we-there-yet "~1.1.2"
|
are-we-there-yet "~1.1.2"
|
||||||
console-control-strings "~1.1.0"
|
console-control-strings "~1.1.0"
|
||||||
@ -6411,8 +6419,8 @@ number-is-nan@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||||
|
|
||||||
nyc@^11.0.2:
|
nyc@^11.0.2:
|
||||||
version "11.0.2"
|
version "11.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.0.2.tgz#9e592a697186028253b668516c38f079c39c08f3"
|
resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.0.3.tgz#0c28bc669a851621709bf7a08503034bee3812b6"
|
||||||
dependencies:
|
dependencies:
|
||||||
archy "^1.0.0"
|
archy "^1.0.0"
|
||||||
arrify "^1.0.1"
|
arrify "^1.0.1"
|
||||||
@ -6426,7 +6434,7 @@ nyc@^11.0.2:
|
|||||||
glob "^7.0.6"
|
glob "^7.0.6"
|
||||||
istanbul-lib-coverage "^1.1.1"
|
istanbul-lib-coverage "^1.1.1"
|
||||||
istanbul-lib-hook "^1.0.7"
|
istanbul-lib-hook "^1.0.7"
|
||||||
istanbul-lib-instrument "^1.7.2"
|
istanbul-lib-instrument "^1.7.3"
|
||||||
istanbul-lib-report "^1.1.1"
|
istanbul-lib-report "^1.1.1"
|
||||||
istanbul-lib-source-maps "^1.2.1"
|
istanbul-lib-source-maps "^1.2.1"
|
||||||
istanbul-reports "^1.1.1"
|
istanbul-reports "^1.1.1"
|
||||||
@ -6437,7 +6445,7 @@ nyc@^11.0.2:
|
|||||||
resolve-from "^2.0.0"
|
resolve-from "^2.0.0"
|
||||||
rimraf "^2.5.4"
|
rimraf "^2.5.4"
|
||||||
signal-exit "^3.0.1"
|
signal-exit "^3.0.1"
|
||||||
spawn-wrap "^1.3.6"
|
spawn-wrap "^1.3.7"
|
||||||
test-exclude "^4.1.1"
|
test-exclude "^4.1.1"
|
||||||
yargs "^8.0.1"
|
yargs "^8.0.1"
|
||||||
yargs-parser "^5.0.0"
|
yargs-parser "^5.0.0"
|
||||||
@ -7399,8 +7407,8 @@ read-installed@~4.0.3:
|
|||||||
graceful-fs "^4.1.2"
|
graceful-fs "^4.1.2"
|
||||||
|
|
||||||
read-package-json@^2.0.0:
|
read-package-json@^2.0.0:
|
||||||
version "2.0.5"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.5.tgz#f93a64e641529df68a08c64de46389e8a3f88845"
|
resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.9.tgz#fd3c21750d760a96c02abda60081e62133213a26"
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.1"
|
glob "^7.1.1"
|
||||||
json-parse-helpfulerror "^1.0.2"
|
json-parse-helpfulerror "^1.0.2"
|
||||||
@ -7517,7 +7525,7 @@ readline2@^1.0.1:
|
|||||||
is-fullwidth-code-point "^1.0.0"
|
is-fullwidth-code-point "^1.0.0"
|
||||||
mute-stream "0.0.5"
|
mute-stream "0.0.5"
|
||||||
|
|
||||||
recast@0.11.12, recast@^0.11.5:
|
recast@0.11.12:
|
||||||
version "0.11.12"
|
version "0.11.12"
|
||||||
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
|
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.12.tgz#a79e4d3f82d5d72a82ee177aeaa791e793bbe5d6"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -7526,6 +7534,15 @@ recast@0.11.12, recast@^0.11.5:
|
|||||||
private "~0.1.5"
|
private "~0.1.5"
|
||||||
source-map "~0.5.0"
|
source-map "~0.5.0"
|
||||||
|
|
||||||
|
recast@^0.11.5:
|
||||||
|
version "0.11.23"
|
||||||
|
resolved "https://registry.yarnpkg.com/recast/-/recast-0.11.23.tgz#451fd3004ab1e4df9b4e4b66376b2a21912462d3"
|
||||||
|
dependencies:
|
||||||
|
ast-types "0.9.6"
|
||||||
|
esprima "~3.1.0"
|
||||||
|
private "~0.1.5"
|
||||||
|
source-map "~0.5.0"
|
||||||
|
|
||||||
rechoir@^0.6.2:
|
rechoir@^0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
|
||||||
@ -8257,6 +8274,12 @@ sort-keys@^1.1.1, sort-keys@^1.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-plain-obj "^1.0.0"
|
is-plain-obj "^1.0.0"
|
||||||
|
|
||||||
|
sort-keys@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
|
||||||
|
dependencies:
|
||||||
|
is-plain-obj "^1.0.0"
|
||||||
|
|
||||||
source-list-map@^1.1.1:
|
source-list-map@^1.1.1:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1"
|
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1"
|
||||||
@ -8304,7 +8327,7 @@ spache@^1.1.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/spache/-/spache-1.1.0.tgz#8c68ba807630f0199429c2035c82ed96f5438cd5"
|
resolved "https://registry.yarnpkg.com/spache/-/spache-1.1.0.tgz#8c68ba807630f0199429c2035c82ed96f5438cd5"
|
||||||
|
|
||||||
spawn-wrap@^1.3.6:
|
spawn-wrap@^1.3.7:
|
||||||
version "1.3.7"
|
version "1.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.7.tgz#beb8bf4426d64b2b06871e0d7dee2643f1f8d1bc"
|
resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.7.tgz#beb8bf4426d64b2b06871e0d7dee2643f1f8d1bc"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -8492,11 +8515,11 @@ string-width@^1.0.0, string-width@^1.0.1, string-width@^1.0.2:
|
|||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
|
|
||||||
string-width@^2.0.0:
|
string-width@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.0.tgz#030664561fc146c9423ec7d978fe2457437fe6d0"
|
||||||
dependencies:
|
dependencies:
|
||||||
is-fullwidth-code-point "^2.0.0"
|
is-fullwidth-code-point "^2.0.0"
|
||||||
strip-ansi "^3.0.0"
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
string_decoder@^0.10.25, string_decoder@~0.10.x:
|
string_decoder@^0.10.25, string_decoder@~0.10.x:
|
||||||
version "0.10.31"
|
version "0.10.31"
|
||||||
@ -8533,6 +8556,12 @@ strip-ansi@^0.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ansi-regex "^0.2.1"
|
ansi-regex "^0.2.1"
|
||||||
|
|
||||||
|
strip-ansi@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^3.0.0"
|
||||||
|
|
||||||
strip-ansi@~0.1.0:
|
strip-ansi@~0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
|
||||||
@ -8662,8 +8691,8 @@ stylelint-selector-no-utility@^1.5.0:
|
|||||||
stylelint "^7.0.0"
|
stylelint "^7.0.0"
|
||||||
|
|
||||||
stylelint@^7.0.0, stylelint@^7.0.3, stylelint@^7.11.1:
|
stylelint@^7.0.0, stylelint@^7.0.3, stylelint@^7.11.1:
|
||||||
version "7.11.1"
|
version "7.12.0"
|
||||||
resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-7.11.1.tgz#c816c658baf7d9e5d167d82273fead37c97ae49d"
|
resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-7.12.0.tgz#bf302c265d7c2d6fe79b154a9fd873a80f8b4aa4"
|
||||||
dependencies:
|
dependencies:
|
||||||
autoprefixer "^6.0.0"
|
autoprefixer "^6.0.0"
|
||||||
balanced-match "^0.4.0"
|
balanced-match "^0.4.0"
|
||||||
@ -8677,7 +8706,7 @@ stylelint@^7.0.0, stylelint@^7.0.3, stylelint@^7.11.1:
|
|||||||
get-stdin "^5.0.0"
|
get-stdin "^5.0.0"
|
||||||
globby "^6.0.0"
|
globby "^6.0.0"
|
||||||
globjoin "^0.1.4"
|
globjoin "^0.1.4"
|
||||||
html-tags "^1.1.1"
|
html-tags "^2.0.0"
|
||||||
ignore "^3.2.0"
|
ignore "^3.2.0"
|
||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
known-css-properties "^0.2.0"
|
known-css-properties "^0.2.0"
|
||||||
@ -9677,7 +9706,7 @@ write-file-stdout@0.0.2:
|
|||||||
version "0.0.2"
|
version "0.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/write-file-stdout/-/write-file-stdout-0.0.2.tgz#c252d7c7c5b1b402897630e3453c7bfe690d9ca1"
|
resolved "https://registry.yarnpkg.com/write-file-stdout/-/write-file-stdout-0.0.2.tgz#c252d7c7c5b1b402897630e3453c7bfe690d9ca1"
|
||||||
|
|
||||||
write-json-file@^2.0.0, write-json-file@^2.1.0:
|
write-json-file@^2.0.0, write-json-file@^2.1.0, write-json-file@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.2.0.tgz#51862506bbb3b619eefab7859f1fd6c6d0530876"
|
resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.2.0.tgz#51862506bbb3b619eefab7859f1fd6c6d0530876"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9696,11 +9725,11 @@ write-pkg@^2.0.0:
|
|||||||
write-json-file "^2.0.0"
|
write-json-file "^2.0.0"
|
||||||
|
|
||||||
write-pkg@^3.0.1:
|
write-pkg@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.0.1.tgz#f95245805be6f6a4eb1d6c31c43b57226815e6e3"
|
resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.1.0.tgz#030a9994cc9993d25b4e75a9f1a1923607291ce9"
|
||||||
dependencies:
|
dependencies:
|
||||||
sort-keys "^1.1.2"
|
sort-keys "^2.0.0"
|
||||||
write-json-file "^2.0.0"
|
write-json-file "^2.2.0"
|
||||||
|
|
||||||
write@^0.2.1:
|
write@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user