feat: constants in IC (phase 1)

This commit is contained in:
Sérgio Ramos 2018-03-01 14:32:55 +00:00 committed by Sérgio Ramos
parent cd242d7505
commit d7f83c59fa
41 changed files with 326 additions and 321 deletions

View File

@ -56,7 +56,8 @@
"styled-components-spacing": "^2.1.3",
"styled-flex-component": "^2.2.1",
"styled-is": "^1.1.2",
"title-case": "^2.1.1"
"title-case": "^2.1.1",
"yup": "^0.24.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -104,7 +104,7 @@ export const AddServiceForm = ({
<Margin top={3.5} left={2}>
<Button
type="submit"
disabled={submitting || invalid}
disabled={submitting}
loading={submitting}
inline
>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@ -9,16 +9,17 @@ Array [
<span
className="c0"
>
Must
:
</span>,
" be on a ",
"same",
" node as the instance(s) identified by the instance ",
"name",
" ",
"key “",
"\\" and the instance tag value",
" ",
" \\"",
"equalling",
" “",
"test",
"”",
]
`;
@ -32,16 +33,21 @@ Array [
<span
className="c0"
>
Must
:
</span>,
" be on a ",
"same",
" node as the instance(s) identified by the instance ",
"tag",
" ",
"key “",
"two",
"\\" and the instance tag value",
" ",
"equalling",
" \\"",
"one",
"”",
]
`;
@ -83,7 +89,7 @@ exports[`renders <Rule/> without throwing 1`] = `
}
.c5 {
width: 4.125rem;
width: 4.5rem;
position: relative;
padding: 0.75rem;
padding-right: 1.5625rem;
@ -383,8 +389,8 @@ exports[`renders <Rule/> without throwing 1`] = `
appearance: none;
min-height: 0;
max-width: 22.1875rem;
width: 4.125rem;
max-width: 4.125rem;
width: 4.5rem;
max-width: 4.5rem;
text-overflow: ellipsis;
}
@ -685,7 +691,7 @@ exports[`renders <Rule/> without throwing 1`] = `
"lineHeight": "3rem",
}
}
width="4.125rem"
width="4.5rem"
>
<select
className="c5 c6"
@ -698,7 +704,7 @@ exports[`renders <Rule/> without throwing 1`] = `
"lineHeight": "3rem",
}
}
width="4.125rem"
width="4.5rem"
>
<option
value="should"
@ -945,7 +951,7 @@ exports[`renders <Rule/> without throwing 2`] = `
}
.c5 {
width: 4.125rem;
width: 4.5rem;
position: relative;
padding: 0.75rem;
padding-right: 1.5625rem;
@ -1245,8 +1251,8 @@ exports[`renders <Rule/> without throwing 2`] = `
appearance: none;
min-height: 0;
max-width: 22.1875rem;
width: 4.125rem;
max-width: 4.125rem;
width: 4.5rem;
max-width: 4.5rem;
text-overflow: ellipsis;
}
@ -1547,7 +1553,7 @@ exports[`renders <Rule/> without throwing 2`] = `
"lineHeight": "3rem",
}
}
width="4.125rem"
width="4.5rem"
>
<select
className="c5 c6"
@ -1560,7 +1566,7 @@ exports[`renders <Rule/> without throwing 2`] = `
"lineHeight": "3rem",
}
}
width="4.125rem"
width="4.5rem"
>
<option
value="should"

View File

@ -39,7 +39,7 @@ export const Rule = ({ valid, ...rule }) => (
<Select
style={style}
touched={rule.conditional}
width={remcalc(66)}
width={remcalc(72)}
embedded
>
<option value="should">should</option>
@ -129,7 +129,7 @@ export const Rule = ({ valid, ...rule }) => (
</Margin>
);
export const Header = rule => (
export const Header = ({ rule }) => (
<Fragment>
<Bold>{titleCase(rule.conditional)}:</Bold> be on a {rule.placement} node as
the instance(s) identified by the instance {rule.type}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -0,0 +1,48 @@
export const Forms = {
IC_AFF_F_ADD: 'INSTANCE_CREATION_AFFINITY_FORM_ADD',
IC_AFF_F_EDIT: 'INSTANCE_CREATION_AFFINITY_FORM_EDIT',
IC_CNS_F: 'INSTANCE_CREATION_CNS_FORM',
IC_NAME_F: 'INSTANCE_CREATION_NAME_FORM',
IC_FW_F_ENABLED: 'INSTANCE_CREATION_FW_ENABLED',
IC_FW_F_INACTIVE: 'INSTANCE_CREATION_FW_INACTIVE',
IC_IMG_F: 'INSTANCE_CREATION_IMAGE_FORM',
IC_MD_F_ADD: 'INSTANCE_CREATION_METADATA_FORM_ADD',
IC_MD_F_EDIT: index => `INSTANCE_CREATION_METADATA_FORM_EDIT_${index}`,
IC_TAG_F_ADD: 'INSTANCE_CREATION_TAG_FORM_ADD',
IC_TAG_F_EDIT: index => `INSTANCE_CREATION_TAG_FORM_EDIT_${index}`,
IC_NW_F: 'INSTANCE_CREATION_NETWORKS_FORM',
IC_PKG_F_SELECT: 'INSTANCE_CREATION_PACKAGE_FORM_SELECT',
IC_PKG_F_FILTER: 'INSTANCE_CREATION_PACKAGE_FORM_FILTER',
IC_US_F: 'INSTANCE_CREATION_USERSCRIPT_FORM',
IC_F: 'INSTANCE_CREATION_FORM'
};
export const Values = {
IC_AFF_V_ADD_OPEN: 'INSTANCE_CREATION_AFFINITY_VALUE_ADD_OPEN',
IC_AFF_V_EDIT_OPEN: 'INSTANCE_CREATION_AFFINITY_VALUE_EDIT_OPEN',
IC_AFF_V_AFF: 'INSTANCE_CREATION_AFFINITY_VALUE_AFFINITY',
IC_CNS_V_ENABLED: 'INSTANCE_CREATION_CNS_VALUE_ENABLED',
IC_CNS_V_PROCEEDED: 'INSTANCE_CREATION_CNS_VALUE_PROCEEDED',
IC_CNS_V_SERVICES: 'INSTANCE_CREATION_CNS_VALUE_SERVICES',
IC_FW_V_PROCEEDED: 'INSTANCE_CREATION_FIREWALL_VALUE_PROCEEDED',
IC_IMG_V_PROCEEDED: 'INSTANCE_CREATION_IMG_VALUE_PROCEEDED',
IC_IMG_V_VMS: 'INSTANCE_CREATION_IMG_VALUE_VMS',
IC_MD_V_PROCEEDED: 'INSTANCE_CREATION_METADATA_VALUE_PROCEEDED',
IC_MD_V_ADD_OPEN: 'INSTANCE_CREATION_METADATA_VALUE_ADD_OPEN',
IC_MD_V_MD: 'INSTANCE_CREATION_METADATA_VALUE_ADD_METADATA',
IC_NAME_V_PROCEEDED: 'INSTANCE_CREATION_NAME_VALUE_PROCEEDED',
IC_NAME_V_RANDOMIZING: 'INSTANCE_CREATION_NAME_VALUE_RANDOMIZING',
IC_NW_V_PROCEEDED: 'INSTANCE_CREATION_NETWORKS_VALUE_PROCEEDED',
IC_NW_V_INFO_EXPANDED: id =>
`INSTANCE_CREATION_NETWORKS_VALUE_${id}_INFO_EXPANDED`,
IC_NW_V_MACHINES_EXPANDED: id =>
`INSTANCE_CREATION_NETWORKS_VALUE_${id}_MACHINES_EXPANDED`,
IC_PKG_V_PROCEEDED: 'INSTANCE_CREATION_PACKAGE_VALUE_PROCEEDED',
IC_PKG_V_SORT_BY: 'INSTANCE_CREATION_PACKAGE_VALUE_SORT_BY',
IC_PKG_V_SORT_ORDER: 'INSTANCE_CREATION_PACKAGE_VALUE_SORT_ORDER',
IC_TAG_V_PROCEEDED: 'INSTANCE_CREATION_TAG_VALUE_PROCEEDED',
IC_TAG_V_ADD_OPEN: 'INSTANCE_CREATION_TAG_VALUE_ADD_OPEN',
IC_TAG_V_TAGS: 'INSTANCE_CREATION_TAG_VALUE_TAGS',
IC_US_V_PROCEEDED: 'INSTANCE_CREATION_USERSCRIPT_VALUE_PROCEEDED',
IC_US_V_OPEN: 'INSTANCE_CREATION_USERSCRIPT_VALUE_OPEN'
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

@ -14,9 +14,10 @@ import Title from '@components/create-instance/title';
import { Rule, Header } from '@components/create-instance/affinity';
import Description from '@components/description';
import { addAffinityRule as validateRule } from '@state/validators';
import { Forms, Values } from '@root/constants';
const FORM_NAME_CREATE = 'CREATE-INSTANCE-AFFINITY-ADD';
const FORM_NAME_EDIT = 'CREATE-INSTANCE-AFFINITY-EDIT';
const { IC_AFF_F_ADD, IC_AFF_F_EDIT } = Forms;
const { IC_AFF_V_ADD_OPEN, IC_AFF_V_EDIT_OPEN, IC_AFF_V_AFF } = Values;
const RULE_DEFAULTS = {
conditional: 'should',
@ -69,7 +70,7 @@ export const Affinity = ({
</Description>
) : null}
<ReduxForm
form={FORM_NAME_EDIT}
form={IC_AFF_F_EDIT}
initialValues={exitingRule}
destroyOnUnmount={false}
forceUnregisterOnUnmount={false}
@ -83,7 +84,7 @@ export const Affinity = ({
<KeyValue
{...formProps}
expanded={editOpen}
customHeader={<Header {...exitingRule} />}
customHeader={<Header rule={exitingRule} />}
method="edit"
input={inputProps => (
<Rule
@ -105,7 +106,7 @@ export const Affinity = ({
}
</ReduxForm>
<ReduxForm
form={FORM_NAME_CREATE}
form={IC_AFF_F_ADD}
initialValues={RULE_DEFAULTS}
destroyOnUnmount={false}
forceUnregisterOnUnmount={false}
@ -163,12 +164,12 @@ export const Affinity = ({
export default compose(
connect(({ values, form }, ownProps) => {
const editingRule = get(form, `${FORM_NAME_EDIT}.values`, null);
const creatingRule = get(form, `${FORM_NAME_CREATE}.values`, null);
const exitingRule = get(values, 'create-instance-affinity', null);
const editingRule = get(form, `${IC_AFF_F_EDIT}.values`, null);
const creatingRule = get(form, `${IC_AFF_F_ADD}.values`, null);
const exitingRule = get(values, IC_AFF_V_AFF, null);
const addOpen = get(values, 'create-instance-affinity-add-open', false);
const editOpen = get(values, 'create-instance-affinity-edit-open', false);
const addOpen = get(values, IC_AFF_V_ADD_OPEN, false);
const editOpen = get(values, IC_AFF_V_EDIT_OPEN, false);
return {
addOpen,
@ -182,53 +183,44 @@ export default compose(
shouldAsyncValidate: ({ trigger }) => {
return trigger === 'submit';
},
handleAsyncValidate: validateRule,
handleAsyncValidate: ({ type, ...aff }) => {
return type === 'name'
? validateRule({ ...aff, key: 'default', type })
: validateRule({ ...aff, type });
},
handleEdit: () => {
return history.push(`/~create/affinity${history.location.search}`);
},
handleCreateAffinityRules: value => {
const toggleToClosed = set({
name: 'create-instance-affinity-add-open',
value: false
});
const appendAffinityRule = set({
name: 'create-instance-affinity',
value
});
return dispatch([
destroy(FORM_NAME_CREATE),
toggleToClosed,
appendAffinityRule
destroy(IC_AFF_F_ADD),
set({ name: IC_AFF_V_ADD_OPEN, value: false }),
set({ name: IC_AFF_V_AFF, value })
]);
},
handleUpdateAffinityRule: value => {
return dispatch([
destroy(FORM_NAME_EDIT),
set({ name: 'create-instance-affinity', value })
destroy(IC_AFF_F_EDIT),
set({ name: IC_AFF_V_EDIT_OPEN, value: false }),
set({ name: IC_AFF_V_AFF, value })
]);
},
handleChangeAddOpen: value => {
return dispatch([
reset(FORM_NAME_CREATE),
set({ name: 'create-instance-affinity-add-open', value })
reset(IC_AFF_F_ADD),
set({ name: IC_AFF_V_ADD_OPEN, value })
]);
},
handleToggleExpanded: value => {
return dispatch(
set({ name: 'create-instance-affinity-edit-open', value })
);
return dispatch(set({ name: IC_AFF_V_EDIT_OPEN, value }));
},
handleCancelEdit: () => {
return dispatch([
set({ name: 'create-instance-affinity-edit-open', value: false })
]);
return dispatch([set({ name: IC_AFF_V_EDIT_OPEN, value: false })]);
},
handleRemoveAffinityRule: () => {
return dispatch([
destroy(FORM_NAME_EDIT),
set({ name: 'create-instance-affinity', value: null })
destroy(IC_AFF_F_EDIT),
set({ name: IC_AFF_V_AFF, value: null })
]);
}
}))

View File

@ -14,8 +14,10 @@ import Cns, { Footer, AddServiceForm } from '@components/cns';
import Description from '@components/description';
import GetAccount from '@graphql/get-account.gql';
import { addCnsService as validateServiceName } from '@state/validators';
import { Forms, Values } from '@root/constants';
const CNS_FORM = 'create-instance-cns';
const { IC_CNS_F, IC_NAME_F } = Forms;
const { IC_CNS_V_ENABLED, IC_CNS_V_PROCEEDED, IC_CNS_V_SERVICES } = Values;
const CNSContainer = ({
submitted,
@ -66,7 +68,7 @@ const CNSContainer = ({
onRemoveService={handleRemoveService}
>
<ReduxForm
form={`${CNS_FORM}-new-service`}
form={IC_CNS_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleAddService}
@ -114,14 +116,9 @@ export default compose(
})
}),
connect(({ form, values }, { id }) => {
const proceeded = get(values, `${CNS_FORM}-proceeded`, false);
const instanceName = get(
form,
'create-instance-name.values.name',
'<instance-name>'
);
const serviceNames = get(values, `${CNS_FORM}-services`, []);
const proceeded = get(values, IC_CNS_V_PROCEEDED, false);
const instanceName = get(form, `${IC_NAME_F}.values.name`, '<inst-name>');
const serviceNames = get(values, IC_CNS_V_SERVICES, []);
// REPLACE WITH DATA CENTER
const dataCenter = 'us-east-1';
@ -158,7 +155,7 @@ export default compose(
});
return {
cnsEnabled: get(values, `${CNS_FORM}-enabled`, true),
cnsEnabled: get(values, IC_CNS_V_ENABLED, true),
instanceName,
proceeded: proceeded || serviceNames.length,
hostnames,
@ -167,32 +164,30 @@ export default compose(
}),
connect(null, (dispatch, { history, cnsEnabled, serviceNames = [] }) => ({
handleNext: () => {
dispatch(set({ name: `${CNS_FORM}-proceeded`, value: true }));
dispatch(set({ name: IC_CNS_V_PROCEEDED, value: true }));
return history.push(`/~create/affinity${history.location.search}`);
},
handleEdit: () => {
dispatch(set({ name: `${CNS_FORM}-proceeded`, value: true }));
dispatch(set({ name: IC_CNS_V_PROCEEDED, value: true }));
history.push(`/~create/cns${history.location.search}`);
},
shouldAsyncValidate: ({ trigger }) => {
return trigger === 'submit';
},
handleAsyncValidate: validateServiceName,
handleToggleCnsEnabled: ({ target }) =>
dispatch(set({ name: `${CNS_FORM}-enabled`, value: !cnsEnabled })),
handleToggleCnsEnabled: ({ target }) => {
return dispatch(set({ name: IC_CNS_V_ENABLED, value: !cnsEnabled }));
},
handleAddService: ({ name }) => {
dispatch([
destroy(`${CNS_FORM}-new-service`),
set({
name: `${CNS_FORM}-services`,
value: serviceNames.concat(name)
})
return dispatch([
destroy(IC_CNS_F),
set({ name: IC_CNS_V_SERVICES, value: serviceNames.concat(name) })
]);
},
handleRemoveService: value => {
return dispatch(
set({
name: `${CNS_FORM}-services`,
name: IC_CNS_V_SERVICES,
value: serviceNames.filter(name => name !== value)
})
);

View File

@ -22,8 +22,10 @@ import Title from '@components/create-instance/title';
import Description from '@components/description';
import Empty from '@components/empty';
import ListFwRules from '@graphql/list-fw-rules.gql';
import { Forms, Values } from '@root/constants';
const FORM_NAME = 'CREATE-INSTANCE-FIREWALL';
const { IC_FW_F_ENABLED, IC_FW_F_INACTIVE } = Forms;
const { IC_FW_V_PROCEEDED, IC_TAG_V_TAGS } = Values;
const Firewall = ({
defaultRules = [],
@ -62,7 +64,7 @@ const Firewall = ({
<Flex>
<FlexItem>
<ReduxForm
form={`${FORM_NAME}-enabled`}
form={IC_FW_F_ENABLED}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
>
@ -77,7 +79,7 @@ const Firewall = ({
</FlexItem>
<FlexItem>
<ReduxForm
form={`${FORM_NAME}-inactive`}
form={IC_FW_F_INACTIVE}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
>
@ -154,24 +156,18 @@ export default compose(
connect(
({ form, values }, ownProps) => ({
...ownProps,
proceeded: get(values, 'create-instance-firewall-proceeded', false),
enabled: get(form, `${FORM_NAME}-enabled.values.enabled`, false),
showInactive: get(form, `${FORM_NAME}-inactive.values.inactive`, false),
tags: get(values, 'create-instance-tags', [])
proceeded: get(values, IC_FW_V_PROCEEDED, false),
enabled: get(form, `${IC_FW_F_ENABLED}.values.enabled`, false),
showInactive: get(form, `${IC_FW_F_INACTIVE}.values.inactive`, false),
tags: get(values, IC_TAG_V_TAGS, [])
}),
(dispatch, { history }) => ({
handleNext: () => {
dispatch(
set({ name: 'create-instance-firewall-proceeded', value: true })
);
dispatch(set({ name: IC_FW_V_PROCEEDED, value: true }));
return history.push(`/~create/cns${history.location.search}`);
},
handleEdit: () => {
dispatch(
set({ name: 'create-instance-firewall-proceeded', value: true })
);
dispatch(set({ name: IC_FW_V_PROCEEDED, value: true }));
return history.push(`/~create/firewall${history.location.search}`);
}
})

View File

@ -19,6 +19,10 @@ import Title from '@components/create-instance/title';
import Description from '@components/description';
import imageData from '@data/images-map.json';
import GetImages from '@graphql/get-images.gql';
import { Forms, Values } from '@root/constants';
const { IC_IMG_F } = Forms;
const { IC_IMG_V_PROCEEDED, IC_IMG_V_VMS } = Values;
const HarcodedImage = (image = {}) => (
<Fragment>
@ -27,7 +31,7 @@ const HarcodedImage = (image = {}) => (
</Title>
{image.id ? (
<ReduxForm
form="create-instance-image"
form={IC_IMG_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
initialValues={{ image: image.id }}
@ -85,7 +89,7 @@ const ImageContainer = ({
</Description>
) : null}
<ReduxForm
form="create-instance-image"
form={IC_IMG_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
initialValues={{ vms: true }}
@ -130,9 +134,9 @@ const ImageContainer = ({
export default compose(
connect(
({ form, values }, ownProps) => {
const proceeded = get(values, 'create-instance-image-proceeded', false);
const image = get(form, 'create-instance-image.values.image', null);
const vms = get(values, 'vms', true);
const proceeded = get(values, IC_IMG_V_PROCEEDED, false);
const image = get(form, `${IC_IMG_F}.values.image`, null);
const vms = get(values, IC_IMG_V_VMS, true);
return {
...ownProps,
@ -143,19 +147,17 @@ export default compose(
},
(dispatch, { history }) => ({
handleNext: () => {
dispatch(set({ name: 'create-instance-image-proceeded', value: true }));
dispatch(set({ name: IC_IMG_V_PROCEEDED, value: true }));
return history.push(`/~create/package${history.location.search}`);
},
handleEdit: () => {
return history.push(`/~create/image${history.location.search}`);
},
handleSelectLatest: ({ versions }) => {
const id = versions[0].id;
return dispatch(change('create-instance-image', 'image', id));
return dispatch(change(IC_IMG_F, 'image', versions[0].id));
},
setImageType: isVm => {
return dispatch(set({ name: 'vms', value: isVm }));
return dispatch(set({ name: IC_IMG_V_VMS, value: isVm }));
}
})
),

View File

@ -11,7 +11,7 @@ import intercept from 'apr-intercept';
import constantCase from 'constant-case';
import queryString from 'query-string';
import get from 'lodash.get';
import Values from 'lodash.values';
import lvalues from 'lodash.values';
import omit from 'lodash.omit';
import uniqBy from 'lodash.uniqby';
@ -36,8 +36,18 @@ import CNS from '@containers/create-instance/cns';
import Affinity from '@containers/create-instance/affinity';
import CreateInstanceMutation from '@graphql/create-instance.gql';
import parseError from '@state/parse-error';
import { Forms, Values } from '@root/constants';
const CREATE_FORM = 'CREATE-INSTANCE';
const { IC_F, IC_NAME_F, IC_IMG_F, IC_PKG_F_SELECT, IC_NW_F, IC_US_F } = Forms;
const {
IC_MD_V_MD,
IC_TAG_V_TAGS,
IC_AFF_V_AFF,
IC_CNS_V_ENABLED,
IC_CNS_V_SERVICES,
IC_FW_F_ENABLED
} = Values;
const CreateInstance = ({
step,
@ -137,7 +147,7 @@ const CreateInstance = ({
</Message>
</Margin>
) : null}
<ReduxForm form={CREATE_FORM} onSubmit={handleSubmit}>
<ReduxForm form={IC_F} onSubmit={handleSubmit}>
{({ handleSubmit, submitting }) => (
<form onSubmit={handleSubmit}>
<Button disabled={disabled} loading={submitting}>
@ -154,20 +164,19 @@ export default compose(
graphql(CreateInstanceMutation, { name: 'createInstance' }),
connect(({ form, values }, { match, location }) => {
const query = queryString.parse(location.search);
const FORM_NAME = 'create-instance-name';
const step = get(match, 'params.step', 'name');
const error = get(form, `${CREATE_FORM}.error`, null);
const name = get(form, `${FORM_NAME}.values.name`, '');
const image = get(form, 'create-instance-image.values.image', '');
const pkg = get(form, 'create-instance-package.values.package', '');
const networks = get(form, 'CREATE-INSTANCE-NETWORKS.values', {});
const error = get(form, `${IC_F}.error`, null);
const name = get(form, `${IC_NAME_F}.values.name`, '');
const image = get(form, `${IC_IMG_F}.values.image`, '');
const pkg = get(form, `${IC_PKG_F_SELECT}.values.package`, '');
const networks = get(form, `${IC_NW_F}.values`, {});
const enabled =
name.length &&
image.length &&
pkg.length &&
Values(networks).filter(Boolean).length;
lvalues(networks).filter(Boolean).length;
if (!enabled) {
return {
@ -178,17 +187,16 @@ export default compose(
};
}
const metadata = get(values, 'create-instance-metadata', []);
const receivedTags = get(values, 'create-instance-tags', []);
const affinity = get(values, 'create-instance-affinity', []);
const cns = get(values, 'create-instance-cns-enabled', true);
const cnsServices = get(values, 'create-instance-cns-services', null);
const userScript = get(values, 'create-instance-user-script', {});
const tags = receivedTags.map(a => omit(a, 'expanded'));
const metadata = get(values, IC_MD_V_MD, []);
const tags = get(values, IC_TAG_V_TAGS, []).map(tag => tag); // clone
const affinity = get(values, IC_AFF_V_AFF, null);
const cns = get(values, IC_CNS_V_ENABLED, true);
const cnsServices = get(values, IC_CNS_V_SERVICES, null);
const userScript = get(form, `${IC_US_F}.values.value`, '');
const firewall_enabled = get(
form,
'CREATE-INSTANCE-FIREWALL.values.enabled',
`${IC_FW_F_ENABLED}.values.enabled`,
false
);
@ -236,14 +244,14 @@ export default compose(
history
} = ownProps;
return {
handleSubmit: async () => {
const _affinity = affinity
.map(aff => ({
...aff,
value: aff.type === 'name' ? aff.name : aff.value
}))
.map(({ conditional, placement, identity, key, pattern, value }) => {
const parseAffRule = ({
conditional,
placement,
identity,
key,
pattern,
value
}) => {
const type = constantCase(
`${conditional}_${placement === 'same' ? 'equal' : 'not_equal'}`
);
@ -257,18 +265,25 @@ export default compose(
};
const _key = identity === 'name' ? 'instance' : key;
const _value = patterns[pattern](value);
const _value = patterns[pattern](type === 'name' ? name : value);
return {
type,
key: _key,
value: _value
};
});
};
return {
handleSubmit: async () => {
const _affinity = affinity ? parseAffRule(affinity) : null;
const _name = name.toLowerCase();
const _metadata = metadata.map(a => omit(a, 'open'));
const _tags = uniqBy(tags, 'name').map(a => omit(a, 'expanded'));
const _tags = uniqBy(tags.map(a => omit(a, 'expanded')), 'name').map(
a => omit(a, 'expanded')
);
const _networks = Object.keys(networks).filter(
network => networks[network]
);
@ -283,7 +298,7 @@ export default compose(
name: _name,
package: pkg,
image,
affinity: _affinity.length ? _affinity : undefined,
affinity: _affinity,
metadata: _metadata,
tags: _tags,
firewall_enabled,
@ -299,7 +314,6 @@ export default compose(
}
dispatch([destroyAll(), forms.map(name => destroy(name))]);
history.push(`/${res.data.createMachine.name}`);
}
};

View File

@ -14,9 +14,10 @@ import Editor from 'joyent-ui-toolkit/dist/es/editor';
import Title from '@components/create-instance/title';
import Description from '@components/description';
import { addMetadata as validateMetadata } from '@state/validators';
import { Forms, Values } from '@root/constants';
const FORM_NAME_CREATE = 'CREATE-INSTANCE-METADATA-ADD';
const FORM_NAME_EDIT = i => `CREATE-INSTANCE-METADATA-EDIT-${i}`;
const { IC_MD_F_ADD, IC_MD_F_EDIT } = Forms;
const { IC_MD_V_PROCEEDED, IC_MD_V_ADD_OPEN, IC_MD_V_MD } = Values;
export const Metadata = ({
id,
@ -68,7 +69,7 @@ export const Metadata = ({
) : null}
{metadata.map(({ name, value, open }, index) => (
<ReduxForm
form={FORM_NAME_EDIT(index)}
form={IC_MD_F_EDIT(index)}
key={index}
initialValues={{ name, value }}
destroyOnUnmount={false}
@ -103,7 +104,7 @@ export const Metadata = ({
</ReduxForm>
))}
<ReduxForm
form={FORM_NAME_CREATE}
form={IC_MD_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleAddMetadata}
@ -152,9 +153,9 @@ export const Metadata = ({
export default compose(
connect(({ values }, ownProps) => {
const proceeded = get(values, 'create-instance-metadata-proceeded', false);
const addOpen = get(values, 'create-instance-metadata-add-open', false);
const metadata = get(values, 'create-instance-metadata', []);
const proceeded = get(values, IC_MD_V_PROCEEDED, false);
const addOpen = get(values, IC_MD_V_ADD_OPEN, false);
const metadata = get(values, IC_MD_V_MD, []);
return {
proceeded: proceeded || metadata.length,
@ -164,17 +165,11 @@ export default compose(
}),
connect(null, (dispatch, { metadata = [], history }) => ({
handleNext: () => {
dispatch(
set({ name: 'create-instance-metadata-proceeded', value: true })
);
dispatch(set({ name: IC_MD_V_PROCEEDED, value: true }));
return history.push(`/~create/user-script${history.location.search}`);
},
handleEdit: () => {
dispatch(
set({ name: 'create-instance-metadata-proceeded', value: true })
);
dispatch(set({ name: IC_MD_V_PROCEEDED, value: true }));
return history.push(`/~create/metadata${history.location.search}`);
},
shouldAsyncValidate: ({ trigger }) => {
@ -182,21 +177,14 @@ export default compose(
},
handleAsyncValidate: validateMetadata,
handleAddMetadata: value => {
const toggleToClosed = set({
name: `create-instance-metadata-add-open`,
value: false
});
const toggleToClosed = set({ name: IC_MD_V_ADD_OPEN, value: false });
const appendMetadata = set({
name: `create-instance-metadata`,
name: IC_MD_V_MD,
value: metadata.concat([{ ...value, open: false }])
});
return dispatch([
destroy(FORM_NAME_CREATE),
toggleToClosed,
appendMetadata
]);
return dispatch([destroy(IC_MD_F_ADD), toggleToClosed, appendMetadata]);
},
handleUpdateMetadata: (index, newMetadata) => {
metadata[index] = {
@ -205,14 +193,14 @@ export default compose(
};
return dispatch([
destroy(FORM_NAME_EDIT(index)),
set({ name: `create-instance-metadata`, value: metadata.slice() })
destroy(IC_MD_F_EDIT(index)),
set({ name: IC_MD_V_MD, value: metadata.slice() })
]);
},
handleChangeAddOpen: value => {
return dispatch([
reset(FORM_NAME_CREATE),
set({ name: `create-instance-metadata-add-open`, value })
reset(IC_MD_F_ADD),
set({ name: IC_MD_V_ADD_OPEN, value })
]);
},
handleToggleExpanded: index => {
@ -221,12 +209,7 @@ export default compose(
open: !metadata[index].open
};
return dispatch(
set({
name: `create-instance-metadata`,
value: metadata.slice()
})
);
return dispatch(set({ name: IC_MD_V_MD, value: metadata.slice() }));
},
handleCancelEdit: index => {
metadata[index] = {
@ -235,16 +218,16 @@ export default compose(
};
return dispatch([
reset(FORM_NAME_EDIT(index)),
set({ name: `create-instance-metadata`, value: metadata.slice() })
reset(IC_MD_F_EDIT(index)),
set({ name: IC_MD_V_MD, value: metadata.slice() })
]);
},
handleRemoveMetadata: index => {
metadata.splice(index, 1);
return dispatch([
destroy(FORM_NAME_EDIT(index)),
set({ name: `create-instance-metadata`, value: metadata.slice() })
destroy(IC_MD_F_EDIT(index)),
set({ name: IC_MD_V_MD, value: metadata.slice() })
]);
}
}))

View File

@ -16,8 +16,10 @@ import Description from '@components/description';
import { instanceName as validateName } from '@state/validators';
import createClient from '@state/apollo-client';
import GetRandomName from '@graphql/get-random-name.gql';
import { Forms, Values } from '@root/constants';
const FORM_NAME = 'create-instance-name';
const { IC_NAME_F } = Forms;
const { IC_NAME_V_PROCEEDED, IC_NAME_V_RANDOMIZING } = Values;
const NameContainer = ({
expanded,
@ -47,7 +49,7 @@ const NameContainer = ({
</Description>
) : null}
<ReduxForm
form={FORM_NAME}
form={IC_NAME_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleNext}
@ -96,14 +98,9 @@ export default compose(
}),
connect(
({ form, values }, ownProps) => {
const name = get(form, `${FORM_NAME}.values.name`, '');
const proceeded = get(values, 'create-instance-name-proceeded', false);
const randomizing = get(
values,
'create-instance-name-randomizing',
false
);
const name = get(form, `${IC_NAME_F}.values.name`, '');
const randomizing = get(values, IC_NAME_V_RANDOMIZING, false);
const proceeded = get(values, IC_NAME_V_PROCEEDED, false);
return {
...ownProps,
@ -114,7 +111,7 @@ export default compose(
},
(dispatch, { history, query }) => ({
handleNext: () => {
dispatch(set({ name: 'create-instance-name-proceeded', value: true }));
dispatch(set({ name: IC_NAME_V_PROCEEDED, value: true }));
return history.push(
`/~create/${query.image ? 'package' : 'image'}${
history.location.search
@ -129,9 +126,7 @@ export default compose(
},
handleAsyncValidate: validateName,
handleRandomize: async () => {
dispatch(
set({ name: 'create-instance-name-randomizing', value: true })
);
dispatch(set({ name: IC_NAME_V_RANDOMIZING, value: true }));
const [err, res] = await intercept(
createClient().query({
@ -140,9 +135,7 @@ export default compose(
})
);
dispatch(
set({ name: 'create-instance-name-randomizing', value: false })
);
dispatch(set({ name: IC_NAME_V_RANDOMIZING, value: false }));
if (err) {
console.error(err);
@ -152,7 +145,7 @@ export default compose(
const { data } = res;
const { rndName } = data;
return dispatch(change(FORM_NAME, 'name', rndName));
return dispatch(change(IC_NAME_F, 'name', rndName));
}
})
)

View File

@ -15,8 +15,14 @@ import Title from '@components/create-instance/title';
import Network from '@components/create-instance/network';
import Description from '@components/description';
import ListNetworks from '@graphql/list-networks.gql';
import { Forms, Values } from '@root/constants';
const FORM_NAME = 'CREATE-INSTANCE-NETWORKS';
const { IC_NW_F } = Forms;
const {
IC_NW_V_PROCEEDED,
IC_NW_V_INFO_EXPANDED,
IC_NW_V_MACHINES_EXPANDED
} = Values;
export const Networks = ({
networks = [],
@ -62,7 +68,7 @@ export const Networks = ({
) : null}
{loading && expanded ? <StatusLoader /> : null}
<ReduxForm
form={FORM_NAME}
form={IC_NW_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
initialValues={initialValues}
@ -128,16 +134,11 @@ export default compose(
}),
connect(
({ values, form }, { networks }) => {
const selected = get(form, `${FORM_NAME}.values`, {});
const proceeded = get(values, IC_NW_V_PROCEEDED, false);
const selected = get(form, `${IC_NW_F}.values`, {});
const empty = id => !includes(Object.keys(selected), id);
const _public = find(networks, ['name', 'Joyent-SDC-Public']);
const proceeded = get(
values,
'create-instance-networks-proceeded',
false
);
const initialValues = _public
? {
[_public.id]: true
@ -151,22 +152,14 @@ export default compose(
return {
...network,
id,
name,
selected:
empty(id) && name === 'Joyent-SDC-Public'
? true
: Boolean(selected[id]),
infoExpanded: get(
values,
`create-instance-networks-${id}-info-expanded`,
false
),
machinesExpanded: get(
values,
`create-instance-networks-${id}-machines-expanded`,
false
),
id
machinesExpanded: get(values, IC_NW_V_MACHINES_EXPANDED(id), false),
infoExpanded: get(values, IC_NW_V_INFO_EXPANDED(id), false)
};
});
@ -179,33 +172,21 @@ export default compose(
},
(dispatch, { history }) => ({
handleNext: () => {
dispatch(
set({ name: 'create-instance-networks-proceeded', value: true })
);
dispatch(set({ name: IC_NW_V_PROCEEDED, value: true }));
return history.push(`/~create/firewall${history.location.search}`);
},
handleEdit: () => {
dispatch(
set({ name: 'create-instance-networks-proceeded', value: true })
);
dispatch(set({ name: IC_NW_V_PROCEEDED, value: true }));
return history.push(`/~create/networks${history.location.search}`);
},
setInfoExpanded: (id, expanded) => {
return dispatch(
set({
name: `create-instance-networks-${id}-info-expanded`,
value: expanded
})
set({ name: IC_NW_V_INFO_EXPANDED(id), value: expanded })
);
},
setMachinesExpanded: (id, expanded) => {
return dispatch(
set({
name: `create-instance-networks-${id}-machines-expanded`,
value: expanded
})
set({ name: IC_NW_V_MACHINES_EXPANDED(id), value: expanded })
);
}
})

View File

@ -26,9 +26,16 @@ import Title from '@components/create-instance/title';
import Description from '@components/description';
import getPackages from '@graphql/get-packages.gql';
import priceData from '@data/prices.json';
import { Forms, Values } from '@root/constants';
const FORM_NAME = 'create-instance-package';
const FILTERS = 'create-instance-package-filters';
const { IC_PKG_F_SELECT, IC_PKG_F_FILTER } = Forms;
const {
IC_PKG_V_PROCEEDED,
IC_PKG_V_SORT_BY,
IC_PKG_V_SORT_ORDER,
IC_IMG_V_VMS
} = Values;
const PackageContainer = ({
expanded,
@ -69,7 +76,7 @@ const PackageContainer = ({
</Description>
) : null}
<ReduxForm
form={`${FORM_NAME}-filters`}
form={IC_PKG_F_FILTER}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
>
@ -80,7 +87,7 @@ const PackageContainer = ({
}
</ReduxForm>
<ReduxForm
form={FORM_NAME}
form={IC_PKG_F_SELECT}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleNext}
@ -162,37 +169,37 @@ export default compose(
}),
connect(
({ form, values }, { packages, ...ownProps }) => {
const proceeded = get(values, 'create-instance-package-proceeded', false);
const _sortBy = get(values, 'packages-list-sort-by', 'price');
const _sortOrder = get(values, 'packages-list-sort-order', 'asc');
const ssdOnly = get(form, `${FILTERS}.values.ssd`, false);
const proceeded = get(values, IC_PKG_V_PROCEEDED, false);
const _sortBy = get(values, IC_PKG_V_SORT_BY, 'price');
const _sortOrder = get(values, IC_PKG_V_SORT_ORDER, 'asc');
const ssdOnly = get(form, `${IC_PKG_F_FILTER}.values.ssd`, false);
const computeOptimized = get(
form,
`${FILTERS}.values.compute-optimized`,
`${IC_PKG_F_FILTER}.values.compute-optimized`,
false
);
const generalPurpose = get(
form,
`${FILTERS}.values.general-purpose`,
`${IC_PKG_F_FILTER}.values.general-purpose`,
false
);
const storageOptimized = get(
form,
`${FILTERS}.values.storage-optimized`,
`${IC_PKG_F_FILTER}.values.storage-optimized`,
false
);
const memoryOptimized = get(
form,
`${FILTERS}.values.memory-optimized`,
`${IC_PKG_F_FILTER}.values.memory-optimized`,
false
);
const vmSelected = get(form, 'create-instance-vms.values.vms', false);
const pkgSelected = get(form, `${FORM_NAME}.values.package`, null);
const vmSelected = get(values, IC_IMG_V_VMS, true);
const pkgSelected = get(form, `${IC_PKG_F_SELECT}.values.package`, null);
const selected = find(packages, ['id', pkgSelected]);
const sorted = sortBy(packages, [_sortBy]);
@ -228,31 +235,25 @@ export default compose(
},
(dispatch, { history }) => ({
handleNext: () => {
dispatch(
set({ name: 'create-instance-package-proceeded', value: true })
);
dispatch(set({ name: IC_PKG_V_PROCEEDED, value: true }));
return history.push(`/~create/tags${history.location.search}`);
},
handleEdit: () => {
return history.push(`/~create/package${history.location.search}`);
},
handleResetFilters: () => {
dispatch(destroy(`${FORM_NAME}-filters`));
dispatch(destroy(IC_PKG_F_FILTER));
},
handleRowClick: id => {
dispatch(change(FORM_NAME, 'package', id));
dispatch(change(IC_PKG_F_SELECT, 'package', id));
},
handleSortBy: (newSortBy, sortOrder) => {
dispatch([
set({
name: `packages-list-sort-order`,
name: IC_PKG_V_SORT_BY,
value: sortOrder === 'desc' ? 'asc' : 'desc'
}),
set({
name: `packages-list-sort-by`,
value: newSortBy
})
set({ name: IC_PKG_V_SORT_ORDER, value: newSortBy })
]);
}
})

View File

@ -21,9 +21,10 @@ import Title from '@components/create-instance/title';
import Description from '@components/description';
import Tag from '@components/tags';
import { addTag as validateTag } from '@state/validators';
import { Forms, Values } from '@root/constants';
const FORM_NAME_CREATE = 'CREATE-INSTANCE-TAGS-ADD';
const FORM_NAME_EDIT = i => `CREATE-INSTANCE-TAGS-EDIT-${i}`;
const { IC_TAG_F_ADD, IC_TAG_F_EDIT } = Forms;
const { IC_TAG_V_PROCEEDED, IC_TAG_V_ADD_OPEN, IC_TAG_V_TAGS } = Values;
export const Tags = ({
step,
@ -84,7 +85,7 @@ export const Tags = ({
</Fragment>
) : null}
<ReduxForm
form={FORM_NAME_CREATE}
form={IC_TAG_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
shouldAsyncValidate={shouldAsyncValidate}
@ -132,9 +133,9 @@ export const Tags = ({
export default compose(
connect(({ values }, ownProps) => {
const proceeded = get(values, 'create-instance-tags-proceeded', false);
const addOpen = get(values, 'create-instance-tags-add-open', false);
const tags = get(values, 'create-instance-tags', []);
const proceeded = get(values, IC_TAG_V_PROCEEDED, false);
const addOpen = get(values, IC_TAG_V_ADD_OPEN, false);
const tags = get(values, IC_TAG_V_TAGS, []);
return {
proceeded: proceeded || tags.length,
@ -144,11 +145,11 @@ export default compose(
}),
connect(null, (dispatch, { tags = [], history }) => ({
handleNext: () => {
dispatch(set({ name: 'create-instance-tags-proceeded', value: true }));
dispatch(set({ name: IC_TAG_V_PROCEEDED, value: true }));
return history.push(`/~create/metadata${history.location.search}`);
},
handleEdit: () => {
dispatch(set({ name: 'create-instance-tags-proceeded', value: true }));
dispatch(set({ name: IC_TAG_V_PROCEEDED, value: true }));
return history.push(`/~create/tags${history.location.search}`);
},
shouldAsyncValidate: ({ trigger }) => {
@ -156,17 +157,14 @@ export default compose(
},
handleAsyncValidate: validateTag,
handleAddTag: value => {
const toggleToClosed = set({
name: `create-instance-tags-add-open`,
value: false
});
const toggleToClosed = set({ name: IC_TAG_V_ADD_OPEN, value: false });
const appendTag = set({
name: `create-instance-tags`,
name: IC_TAG_V_TAGS,
value: tags.concat([{ ...value, expanded: false }])
});
return dispatch([destroy(FORM_NAME_CREATE), toggleToClosed, appendTag]);
return dispatch([destroy(IC_TAG_F_ADD), toggleToClosed, appendTag]);
},
handleUpdateTag: (index, newTag) => {
tags[index] = {
@ -175,14 +173,14 @@ export default compose(
};
return dispatch([
destroy(FORM_NAME_EDIT(index)),
set({ name: `create-instance-tags`, value: tags.slice() })
destroy(IC_TAG_F_EDIT(index)),
set({ name: IC_TAG_V_TAGS, value: tags.slice() })
]);
},
handleChangeAddOpen: value => {
return dispatch([
reset(FORM_NAME_CREATE),
set({ name: `create-instance-tags-add-open`, value })
reset(IC_TAG_F_ADD),
set({ name: IC_TAG_V_ADD_OPEN, value })
]);
},
handleToggleExpanded: index => {
@ -191,12 +189,7 @@ export default compose(
expanded: !tags[index].expanded
};
return dispatch(
set({
name: `create-instance-tags`,
value: tags.slice()
})
);
return dispatch(set({ name: IC_TAG_V_TAGS, value: tags.slice() }));
},
handleCancelEdit: index => {
tags[index] = {
@ -205,16 +198,16 @@ export default compose(
};
return dispatch([
reset(FORM_NAME_EDIT(index)),
set({ name: `create-instance-tags`, value: tags.slice() })
reset(IC_TAG_F_EDIT(index)),
set({ name: IC_TAG_V_TAGS, value: tags.slice() })
]);
},
handleRemoveTag: index => {
tags.splice(index, 1);
return dispatch([
destroy(FORM_NAME_EDIT(index)),
set({ name: `create-instance-tags`, value: tags.slice() })
destroy(IC_TAG_F_EDIT(index)),
set({ name: IC_TAG_V_TAGS, value: tags.slice() })
]);
}
}))

View File

@ -11,9 +11,13 @@ import { ScriptIcon, Button } from 'joyent-ui-toolkit';
import Title from '@components/create-instance/title';
import Description from '@components/description';
import UserScriptForm, { Overview } from '@components/create-instance/user-script';
import UserScriptForm, {
Overview
} from '@components/create-instance/user-script';
import { Forms, Values } from '@root/constants';
const FORM_NAME = 'create-instance-user-script';
const { IC_US_F } = Forms;
const { IC_US_V_PROCEEDED, IC_US_V_OPEN } = Values;
export const UserScript = ({
expanded,
@ -44,7 +48,7 @@ export const UserScript = ({
</Description>
{formOpen ? (
<ReduxForm
form={FORM_NAME}
form={IC_US_F}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleSubmit}
@ -87,15 +91,11 @@ export const UserScript = ({
export default compose(
connect(
({ values, form }, ownProps) => {
const formOpen = get(values, 'create-instance-user-script-open', false);
const script = get(form, `${FORM_NAME}.values.value`, '');
const formOpen = get(values, IC_US_V_OPEN, false);
const script = get(form, `${IC_US_F}.values.value`, '');
const lines = script.split('\n').length;
const proceeded = get(
values,
'create-instance-user-script-proceeded',
false
);
const proceeded = get(values, IC_US_V_PROCEEDED, false);
return {
script,
@ -109,21 +109,19 @@ export default compose(
(dispatch, { history }) => ({
handleEdit: () => {
dispatch([
set({ name: 'create-instance-user-script-proceeded', value: true }),
set({ name: `create-instance-user-script-open`, value: true })
set({ name: IC_US_V_PROCEEDED, value: true }),
set({ name: IC_US_V_OPEN, value: true })
]);
return history.push(`/~create/user-script${history.location.search}`);
},
handleChangeOpenForm: value => {
return dispatch([
set({ name: `create-instance-user-script-open`, value })
]);
return dispatch([set({ name: IC_US_V_OPEN, value })]);
},
handleSubmit: value => {
dispatch([
set({ name: `create-instance-user-script-open`, value: false }),
set({ name: 'create-instance-user-script-proceeded', value: true })
set({ name: IC_US_V_OPEN, value: false }),
set({ name: IC_US_V_PROCEEDED, value: true })
]);
return history.push(`/~create/networks${history.location.search}`);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -101,7 +101,7 @@ export const Tags = ({
form={editing.form}
initialValues={{ name: editing.name, value: editing.value }}
shouldAsyncValidate={shouldAsyncValidate}
handleAsyncValidate={handleAsyncValidate}
asyncValidate={handleAsyncValidate}
onSubmit={handleEdit}
>
{props => (

View File

@ -14,14 +14,16 @@ const validateField = async (field, value) => {
const validateSchema = async (schema, value) => {
const errors = await reduce(
keys(schema),
async (errors, name) =>
assign(errors, {
[name]: await validateField(schema[name], value[name])
}),
async (errors, name) => {
const msg = await validateField(schema[name], value[name]);
return !msg ? errors : assign(errors, { [name]: msg });
},
{}
);
if (keys(errors).length) {
throw errors;
}
};
/*****************************************************************************/