feat: constants in IC (phase 1)
@ -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",
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 20 KiB |
@ -104,7 +104,7 @@ export const AddServiceForm = ({
|
||||
<Margin top={3.5} left={2}>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={submitting || invalid}
|
||||
disabled={submitting}
|
||||
loading={submitting}
|
||||
inline
|
||||
>
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
@ -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"
|
||||
|
@ -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}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
48
packages/my-joy-instances/src/constants.js
Normal 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'
|
||||
};
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
@ -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 })
|
||||
]);
|
||||
}
|
||||
}))
|
||||
|
@ -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)
|
||||
})
|
||||
);
|
||||
|
@ -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}`);
|
||||
}
|
||||
})
|
||||
|
@ -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 }));
|
||||
}
|
||||
})
|
||||
),
|
||||
|
@ -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}`);
|
||||
}
|
||||
};
|
||||
|
@ -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() })
|
||||
]);
|
||||
}
|
||||
}))
|
||||
|
@ -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));
|
||||
}
|
||||
})
|
||||
)
|
||||
|
@ -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 })
|
||||
);
|
||||
}
|
||||
})
|
||||
|
@ -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 })
|
||||
]);
|
||||
}
|
||||
})
|
||||
|
@ -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() })
|
||||
]);
|
||||
}
|
||||
}))
|
||||
|
@ -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}`);
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@ -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 => (
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|