feat(images): initial commit for create image
This commit is contained in:
parent
ca1236fb80
commit
7d0ce55070
|
@ -21,6 +21,7 @@
|
|||
"date-fns": "^1.29.0",
|
||||
"declarative-redux-form": "^2.0.8",
|
||||
"joyent-ui-toolkit": "^5.0.0",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"lunr": "^2.1.5",
|
||||
"mz": "^2.7.0",
|
||||
"react": "^16.2.0",
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import React from 'react';
|
||||
import { Field } from 'redux-form';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import remcalc from 'remcalc';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
|
||||
import {
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
FormMeta,
|
||||
Button,
|
||||
RandomizeIcon,
|
||||
Textarea
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ placeholderName, randomizing, onRandomize }) => (
|
||||
<form>
|
||||
<Flex wrap>
|
||||
<FlexItem flex>
|
||||
<FormGroup name="name" fluid field={Field}>
|
||||
<FormLabel>Image name</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Input placeholder={placeholderName} onBlur={null} required />
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<Divider height={remcalc(13)} transparent />
|
||||
<Margin left={1}>
|
||||
<Button
|
||||
type="button"
|
||||
marginTop={remcalc(8)}
|
||||
onClick={onRandomize}
|
||||
loading={randomizing}
|
||||
marginless
|
||||
secondary
|
||||
icon
|
||||
>
|
||||
<RandomizeIcon />
|
||||
<span>Randomize</span>
|
||||
</Button>
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
<Margin top={3}>
|
||||
<FormGroup name="version" fluid field={Field}>
|
||||
<FormLabel>Version</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Input placeholder="Example: v1.0" onBlur={null} required />
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Margin top={3}>
|
||||
<FormGroup name="description" fluid field={Field}>
|
||||
<FormLabel>Description</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Textarea placeholder="Example: JarJarBinks, Anakin Skywalker, Obi Wan Kenobi, Qui-Gon Jinn, Han Solo, Wookies" fluid />
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
</Col>
|
||||
</Row>
|
||||
</form>
|
||||
);
|
|
@ -0,0 +1,30 @@
|
|||
import React from 'react';
|
||||
import Flex from 'styled-flex-component';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
import styled from 'styled-components';
|
||||
import is from 'styled-is';
|
||||
|
||||
import { Divider, Small } from 'joyent-ui-toolkit';
|
||||
|
||||
const Container = styled.div`
|
||||
${is('onClick')`
|
||||
cursor: pointer;
|
||||
`};
|
||||
`;
|
||||
|
||||
export default ({ icon, children, collapsed = true, ...rest }) => (
|
||||
<Container {...rest}>
|
||||
<Flex>
|
||||
<Margin right={1}>
|
||||
<Flex alignCenter full>
|
||||
{icon}
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Small noMargin>{children}</Small>
|
||||
</Flex>
|
||||
<Margin top={1} bottom={collapsed ? 7 : 3}>
|
||||
<Divider height={remcalc(1)} />
|
||||
</Margin>
|
||||
</Container>
|
||||
);
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { P } from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ children }) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Margin bottom={3}>
|
||||
<P>{children}</P>
|
||||
</Margin>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
|
@ -0,0 +1,61 @@
|
|||
import React, { Component } from 'react';
|
||||
import scrollToElement from 'scroll-to-element';
|
||||
|
||||
function slideDown(el) {
|
||||
const { style } = el;
|
||||
const INITIAL = 'initial';
|
||||
const HIDDEN = 'hidden';
|
||||
|
||||
// Get element height
|
||||
style.transition = INITIAL;
|
||||
style.visibility = HIDDEN;
|
||||
style.maxHeight = INITIAL;
|
||||
const offsetHeight = el.offsetHeight;
|
||||
const height = offsetHeight + 'px';
|
||||
style.removeProperty('visibility');
|
||||
style.maxHeight = '0';
|
||||
style.overflow = HIDDEN;
|
||||
|
||||
const timing = `${parseInt(height, 10) * 1.9}ms linear`;
|
||||
|
||||
// Begin transition
|
||||
style.transition = `max-height ${timing}, opacity ${timing}`;
|
||||
requestAnimationFrame(() => {
|
||||
style.maxHeight = height;
|
||||
style.opacity = '1';
|
||||
});
|
||||
|
||||
window.setTimeout(() => {
|
||||
style.removeProperty('overflow');
|
||||
style.removeProperty('max-height');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
const Animated = WrappedComponent =>
|
||||
class Animated extends Component {
|
||||
componentDidUpdate() {
|
||||
const { match, step } = this.props;
|
||||
if (match.params.step === step) {
|
||||
slideDown(this.wrapper);
|
||||
scrollToElement(this.wrapper, {
|
||||
offset: -50
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate = nextProps =>
|
||||
this.props.match.params.step !== nextProps.match.params.step;
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
ref={w => {
|
||||
this.wrapper = w;
|
||||
}}
|
||||
>
|
||||
<WrappedComponent {...this.props} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Animated;
|
|
@ -0,0 +1,179 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { set } from 'react-redux-values';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { change } from 'redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import intercept from 'apr-intercept';
|
||||
import get from 'lodash.get';
|
||||
import punycode from 'punycode';
|
||||
|
||||
import { NameIcon, H3, Button, H4, P } from 'joyent-ui-toolkit';
|
||||
|
||||
import Title from '@components/create-image/title';
|
||||
import Animated from '@containers/create-image/animated';
|
||||
import Name from '@components/create-image/name';
|
||||
import Description from '@components/description';
|
||||
import GetRandomName from '@graphql/get-random-name.gql';
|
||||
import { client } from '@state/store';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
|
||||
const FORM_NAME = 'create-image-details';
|
||||
|
||||
const NameContainer = ({
|
||||
expanded,
|
||||
proceeded,
|
||||
name,
|
||||
version,
|
||||
description,
|
||||
placeholderName,
|
||||
randomizing,
|
||||
handleAsyncValidation,
|
||||
shouldAsyncValidate,
|
||||
handleNext,
|
||||
handleRandomize,
|
||||
handleEdit,
|
||||
step
|
||||
}) => (
|
||||
<Fragment>
|
||||
<Title
|
||||
id={step}
|
||||
onClick={!expanded && !name && handleEdit}
|
||||
collapsed={!expanded && !proceeded}
|
||||
icon={<NameIcon />}
|
||||
>
|
||||
Image name and details
|
||||
</Title>
|
||||
{expanded ? (
|
||||
<Description>
|
||||
Here you can name your custom image, version it, and give it a description so that you can identify it elsewhere in the Triton ecosystem.
|
||||
</Description>
|
||||
) : null}
|
||||
<ReduxForm
|
||||
form={FORM_NAME}
|
||||
destroyOnUnmount={false}
|
||||
forceUnregisterOnUnmount={true}
|
||||
onSubmit={handleNext}
|
||||
asyncValidate={handleAsyncValidation}
|
||||
shouldAsyncValidate={shouldAsyncValidate}
|
||||
>
|
||||
{props =>
|
||||
expanded ? (
|
||||
<Name
|
||||
{...props}
|
||||
placeholderName={placeholderName}
|
||||
randomizing={randomizing}
|
||||
onRandomize={handleRandomize}
|
||||
/>
|
||||
) : name ? (
|
||||
<Margin top={3}>
|
||||
<H3 bold noMargin>{name}</H3>
|
||||
<Margin top={2}><H4 bold noMargin>{version}</H4></Margin>
|
||||
<Row>
|
||||
<Col xs={12} sm={8}><Margin top={1}><P>{description}</P></Margin></Col></Row>
|
||||
</Margin>
|
||||
) : null
|
||||
}
|
||||
</ReduxForm>
|
||||
{expanded ? (
|
||||
<Margin top={4} bottom={7}>
|
||||
<Button type="button" disabled={!name} onClick={handleNext}>
|
||||
Next
|
||||
</Button>
|
||||
</Margin>
|
||||
) : proceeded ? (
|
||||
<Margin top={4} bottom={7}>
|
||||
<Button type="button" onClick={handleEdit} secondary>
|
||||
Edit
|
||||
</Button>
|
||||
</Margin>
|
||||
) : null}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
Animated,
|
||||
graphql(GetRandomName, {
|
||||
fetchPolicy: 'network-only',
|
||||
props: ({ data }) => ({
|
||||
placeholderName: data.rndName || ''
|
||||
})
|
||||
}),
|
||||
connect(
|
||||
({ form, values }, ownProps) => {
|
||||
const name = get(form, `${FORM_NAME}.values.name`, '');
|
||||
const version = get(form, `${FORM_NAME}.values.version`, '');
|
||||
const description = get(form, `${FORM_NAME}.values.description`, '');
|
||||
|
||||
const proceeded = get(values, 'create-image-name-proceeded', false);
|
||||
|
||||
const randomizing = get(
|
||||
values,
|
||||
'create-image-name-randomizing',
|
||||
false
|
||||
);
|
||||
|
||||
return {
|
||||
...ownProps,
|
||||
proceeded,
|
||||
randomizing,
|
||||
name,
|
||||
version,
|
||||
description
|
||||
};
|
||||
},
|
||||
(dispatch, { history }) => ({
|
||||
shouldAsyncValidate: ({ trigger }) => trigger === 'submit',
|
||||
handleAsyncValidation: async ({ name }) => {
|
||||
const sanitized = punycode.encode(name).replace(/-$/, '');
|
||||
|
||||
if (sanitized !== name) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw {
|
||||
name: 'Special characters are not accepted'
|
||||
};
|
||||
}
|
||||
|
||||
if (!/^[a-zA-Z0-9][a-zA-Z0-9\\_\\.\\-]*$/.test(name)) {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw {
|
||||
name: 'Invalid name'
|
||||
};
|
||||
}
|
||||
},
|
||||
handleNext: () => {
|
||||
dispatch(set({ name: 'create-image-name-proceeded', value: true }));
|
||||
|
||||
return history.push(`/~create/tag`);
|
||||
},
|
||||
handleEdit: () => history.push(`/~create/name`),
|
||||
handleRandomize: async () => {
|
||||
dispatch(
|
||||
set({ name: 'create-image-name-randomizing', value: true })
|
||||
);
|
||||
|
||||
const [err, res] = await intercept(
|
||||
client.query({
|
||||
fetchPolicy: 'network-only',
|
||||
query: GetRandomName
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(
|
||||
set({ name: 'create-image-name-randomizing', value: false })
|
||||
);
|
||||
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
const { data } = res;
|
||||
const { rndName } = data;
|
||||
|
||||
return dispatch(change(FORM_NAME, 'name', rndName));
|
||||
}
|
||||
})
|
||||
)
|
||||
)(NameContainer);
|
|
@ -0,0 +1,208 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { set } from 'react-redux-values';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { compose } from 'react-apollo';
|
||||
import { destroy, reset } from 'redux-form';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import get from 'lodash.get';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
TagsIcon,
|
||||
Button,
|
||||
H3,
|
||||
TagList,
|
||||
Divider,
|
||||
KeyValue
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import Title from '@components/create-image/title';
|
||||
import Animated from '@containers/create-image/animated';
|
||||
import Description from '@components/description';
|
||||
import Tag from '@components/tags';
|
||||
|
||||
const FORM_NAME_CREATE = 'CREATE-IMAGE-TAGS-ADD';
|
||||
const FORM_NAME_EDIT = i => `CREATE-IMAGE-TAGS-EDIT-${i}`;
|
||||
|
||||
export const Tags = ({
|
||||
tags = [],
|
||||
expanded,
|
||||
proceeded,
|
||||
addOpen,
|
||||
handleAddTag,
|
||||
handleRemoveTag,
|
||||
handleUpdateTag,
|
||||
handleToggleExpanded,
|
||||
handleCancelEdit,
|
||||
handleChangeAddOpen,
|
||||
handleNext,
|
||||
step,
|
||||
handleEdit
|
||||
}) => (
|
||||
<Fragment>
|
||||
<Title
|
||||
id={step}
|
||||
onClick={!expanded && !proceeded && handleEdit}
|
||||
collapsed={!expanded && !proceeded}
|
||||
icon={<TagsIcon />}
|
||||
>
|
||||
Tags
|
||||
</Title>
|
||||
{expanded ? (
|
||||
<Description>
|
||||
Tags can be used to identify your images, group multiple images
|
||||
together, define firewall and affinity rules, and more.{' '}
|
||||
<a
|
||||
target="__blank"
|
||||
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read the docs
|
||||
</a>
|
||||
</Description>
|
||||
) : null}
|
||||
{proceeded || expanded ? (
|
||||
<Fragment>
|
||||
<Margin bottom={4}>
|
||||
<H3>
|
||||
{tags.length} Tag{tags.length === 1 ? '' : 's'}
|
||||
</H3>
|
||||
</Margin>
|
||||
<TagList>
|
||||
{tags.map(({ name, value }, index) => (
|
||||
<Tag
|
||||
key={index}
|
||||
name={name}
|
||||
value={value}
|
||||
onRemoveClick={expanded && (() => handleRemoveTag(index))}
|
||||
/>
|
||||
))}
|
||||
</TagList>
|
||||
</Fragment>
|
||||
) : null}
|
||||
<ReduxForm
|
||||
form={FORM_NAME_CREATE}
|
||||
destroyOnUnmount={false}
|
||||
forceUnregisterOnUnmount={true}
|
||||
onSubmit={handleAddTag}
|
||||
>
|
||||
{props =>
|
||||
expanded && addOpen ? (
|
||||
<Fragment>
|
||||
<KeyValue
|
||||
{...props}
|
||||
method="add"
|
||||
input="input"
|
||||
type="tag"
|
||||
expanded
|
||||
onCancel={() => handleChangeAddOpen(false)}
|
||||
/>
|
||||
<Divider height={remcalc(18)} transparent />
|
||||
</Fragment>
|
||||
) : null
|
||||
}
|
||||
</ReduxForm>
|
||||
{expanded ? (
|
||||
<Margin top={1} bottom={7}>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => handleChangeAddOpen(true)}
|
||||
secondary
|
||||
>
|
||||
Add Tag
|
||||
</Button>
|
||||
<Button type="button" onClick={handleNext}>
|
||||
Next
|
||||
</Button>
|
||||
</Margin>
|
||||
) : proceeded ? (
|
||||
<Margin top={1} bottom={7}>
|
||||
<Button type="button" onClick={handleEdit} secondary>
|
||||
Edit
|
||||
</Button>
|
||||
</Margin>
|
||||
) : null}
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
Animated,
|
||||
connect(({ values }, ownProps) => ({
|
||||
proceeded: get(values, 'create-image-tags-proceeded', false),
|
||||
addOpen: get(values, 'create-image-tags-add-open', false),
|
||||
tags: get(values, 'create-image-tags', [])
|
||||
})),
|
||||
connect(null, (dispatch, { tags = [], history }) => ({
|
||||
handleNext: () => {
|
||||
dispatch(set({ name: 'create-image-tags-proceeded', value: true }));
|
||||
|
||||
return history.push(`/~create/create`);
|
||||
},
|
||||
handleEdit: () => {
|
||||
return history.push(`/~create/tags`);
|
||||
},
|
||||
handleAddTag: value => {
|
||||
const toggleToClosed = set({
|
||||
name: `create-image-tags-add-open`,
|
||||
value: false
|
||||
});
|
||||
|
||||
const appendTag = set({
|
||||
name: `create-image-tags`,
|
||||
value: tags.concat([{ ...value, expanded: false }])
|
||||
});
|
||||
|
||||
return dispatch([destroy(FORM_NAME_CREATE), toggleToClosed, appendTag]);
|
||||
},
|
||||
handleUpdateTag: (index, newTag) => {
|
||||
tags[index] = {
|
||||
...newTag,
|
||||
expanded: false
|
||||
};
|
||||
|
||||
return dispatch([
|
||||
destroy(FORM_NAME_EDIT(index)),
|
||||
set({ name: `create-image-tags`, value: tags.slice() })
|
||||
]);
|
||||
},
|
||||
handleChangeAddOpen: value => {
|
||||
return dispatch([
|
||||
reset(FORM_NAME_CREATE),
|
||||
set({ name: `create-image-tags-add-open`, value })
|
||||
]);
|
||||
},
|
||||
handleToggleExpanded: index => {
|
||||
tags[index] = {
|
||||
...tags[index],
|
||||
expanded: !tags[index].expanded
|
||||
};
|
||||
|
||||
return dispatch(
|
||||
set({
|
||||
name: `create-image-tags`,
|
||||
value: tags.slice()
|
||||
})
|
||||
);
|
||||
},
|
||||
handleCancelEdit: index => {
|
||||
tags[index] = {
|
||||
...tags[index],
|
||||
expanded: false
|
||||
};
|
||||
|
||||
return dispatch([
|
||||
reset(FORM_NAME_EDIT(index)),
|
||||
set({ name: `create-image-tags`, value: tags.slice() })
|
||||
]);
|
||||
},
|
||||
handleRemoveTag: index => {
|
||||
tags.splice(index, 1);
|
||||
|
||||
return dispatch([
|
||||
destroy(FORM_NAME_EDIT(index)),
|
||||
set({ name: `create-image-tags`, value: tags.slice() })
|
||||
]);
|
||||
}
|
||||
}))
|
||||
)(Tags);
|
|
@ -1,3 +1,142 @@
|
|||
/* eslint-disable camelcase */
|
||||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { destroyAll } from 'react-redux-values';
|
||||
import { destroy } from 'redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'react-apollo';
|
||||
import get from 'lodash.get';
|
||||
import uniqBy from 'lodash.uniqby';
|
||||
import omit from 'lodash.omit';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
export default () => <p>hello world</p>;
|
||||
import { ViewContainer, H2, Button, Divider } from 'joyent-ui-toolkit';
|
||||
|
||||
import Name from '@containers/create-image/name';
|
||||
import Tags from '@containers/create-image/tags';
|
||||
|
||||
const CREATE_FORM = 'CREATE-IMAGE';
|
||||
|
||||
const CreateImage = ({ step, history, location, match, disabled, handleSubmit }) => (
|
||||
<ViewContainer>
|
||||
<Margin top={4} bottom={4}>
|
||||
<H2>Create Image</H2>
|
||||
</Margin>
|
||||
<Name
|
||||
history={history}
|
||||
match={match}
|
||||
step="name"
|
||||
expanded={match.params.step === 'name'}
|
||||
/>
|
||||
<Tags
|
||||
history={history}
|
||||
match={match}
|
||||
step="tag"
|
||||
expanded={match.params.step === 'tag'}
|
||||
/>
|
||||
<Margin top={7}><Divider height={remcalc(1)} /></Margin>
|
||||
<Margin top={4} bottom={10}>
|
||||
<ReduxForm form={CREATE_FORM} onSubmit={handleSubmit}>
|
||||
{({ handleSubmit, submitting }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Button disabled={disabled} loading={submitting}>
|
||||
Create Image
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
connect(({ form, values }) => {
|
||||
const FORM_NAME = 'create-image-details';
|
||||
const nameFilled = get(form, `${FORM_NAME}.values.name`, '');
|
||||
|
||||
const disabled = !get(values, `create-image-name-proceeded`, false) || !nameFilled.length
|
||||
|
||||
if (disabled) {
|
||||
return { disabled };
|
||||
}
|
||||
|
||||
const name = get(
|
||||
form,
|
||||
`${FORM_NAME}.values.name`,
|
||||
'<instance-name>'
|
||||
);
|
||||
|
||||
const description = get(
|
||||
form,
|
||||
`${FORM_NAME}.values.description`,
|
||||
'<instance-description>'
|
||||
);
|
||||
|
||||
const version = get(
|
||||
form,
|
||||
`${FORM_NAME}.values.version`,
|
||||
'<instance-version>'
|
||||
);
|
||||
|
||||
const tags = get(values, 'create-image-tags', []);
|
||||
|
||||
return {
|
||||
forms: Object.keys(form), // improve this
|
||||
name,
|
||||
description,
|
||||
version,
|
||||
tags,
|
||||
disabled
|
||||
};
|
||||
}),
|
||||
connect(null, (dispatch, {
|
||||
name,
|
||||
description,
|
||||
version,
|
||||
tags,
|
||||
forms,
|
||||
createImage,
|
||||
history
|
||||
}) => ({
|
||||
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: {
|
||||
// name: _name,
|
||||
// version: _version,
|
||||
// description: _description,
|
||||
// package: pkg,
|
||||
// tags: _tags,
|
||||
// }
|
||||
// })
|
||||
// );
|
||||
|
||||
// if (err) {
|
||||
// return dispatch(
|
||||
// stopSubmit(CREATE_FORM, {
|
||||
// _error: parseError(err)
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
// eslint-disable-next-line no-alert
|
||||
window.alert(`
|
||||
Image Created!!
|
||||
name: ${_name}
|
||||
description: ${_description}
|
||||
version: ${_version}
|
||||
tags: ${_tags.map(tag => tag.name)}
|
||||
`)
|
||||
|
||||
dispatch([destroyAll(), forms.map(name => destroy(name))]);
|
||||
|
||||
// history.push(`/images/${res.data.createImage.name}`);
|
||||
}
|
||||
})
|
||||
))(CreateImage);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
query rndImageName {
|
||||
rndName
|
||||
}
|
|
@ -20,13 +20,21 @@ export default () => (
|
|||
</Switch>
|
||||
{/* Menu */}
|
||||
<Switch>
|
||||
<Route path="/~create" component={() => null} />
|
||||
<Route path="/~create" component={Menu} />
|
||||
<Route path="/:image/:section?" component={Menu} />
|
||||
</Switch>
|
||||
{/* Create Image */}
|
||||
<Switch>
|
||||
<Route
|
||||
path="/~create/"
|
||||
exact
|
||||
component={() => <Redirect to="/~create/name" />}
|
||||
/>
|
||||
<Route path="/~create/:step" component={Create} />
|
||||
</Switch>
|
||||
{/* Images */}
|
||||
<Switch>
|
||||
<Route path="/" exact component={List} />
|
||||
<Route path="/~create" exact component={Create} />
|
||||
<Route path="/:image/summary" exact component={Summary} />
|
||||
<Route path="/:image/tags" exact component={Tags} />
|
||||
<Route
|
||||
|
|
|
@ -14,6 +14,7 @@ const BaseTextarea = TextareaInput.extend`
|
|||
${is('fluid')`
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
`};
|
||||
`;
|
||||
|
||||
|
|
Loading…
Reference in New Issue