feat(instances): add change name
This commit is contained in:
parent
0b9c464bb0
commit
5d274a419a
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@ import { Margin, Padding } from 'styled-components-spacing';
|
|||||||
import titleCase from 'title-case';
|
import titleCase from 'title-case';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
|
import { Field } from 'redux-form';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@ -21,7 +22,11 @@ import {
|
|||||||
DeleteIcon,
|
DeleteIcon,
|
||||||
StartIcon,
|
StartIcon,
|
||||||
StopIcon,
|
StopIcon,
|
||||||
InstanceTypeIcon
|
EditIcon,
|
||||||
|
InstanceTypeIcon,
|
||||||
|
Input,
|
||||||
|
FormMeta,
|
||||||
|
FormGroup
|
||||||
} from 'joyent-ui-toolkit';
|
} from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
import GLOBAL from '@state/global';
|
import GLOBAL from '@state/global';
|
||||||
@ -58,6 +63,10 @@ const Flex = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const Actionable = styled(Margin)`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
const VerticalDivider = styled.div`
|
const VerticalDivider = styled.div`
|
||||||
width: ${remcalc(1)};
|
width: ${remcalc(1)};
|
||||||
background: ${props => props.theme.grey};
|
background: ${props => props.theme.grey};
|
||||||
@ -77,11 +86,49 @@ export const Meta = ({
|
|||||||
state,
|
state,
|
||||||
brand,
|
brand,
|
||||||
image,
|
image,
|
||||||
|
editingName,
|
||||||
|
handleSubmit,
|
||||||
|
editName,
|
||||||
|
disabled,
|
||||||
|
submitting,
|
||||||
...instance
|
...instance
|
||||||
}) => [
|
}) => [
|
||||||
<Row middle="xs">
|
<Row middle="xs">
|
||||||
<Col xs={12}>
|
<Col xs={12}>
|
||||||
<H2>{instance.name}</H2>
|
<H2>
|
||||||
|
{editingName ? (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Flex style={{ alignItems: 'start' }}>
|
||||||
|
<FormGroup name="name" field={Field}>
|
||||||
|
<Input
|
||||||
|
onBlur={null}
|
||||||
|
type="text"
|
||||||
|
placeholder={instance.name}
|
||||||
|
disabled={disabled || submitting}
|
||||||
|
/>
|
||||||
|
<FormMeta />
|
||||||
|
</FormGroup>
|
||||||
|
<Margin left={1}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={submitting}
|
||||||
|
loading={submitting}
|
||||||
|
inline
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</Margin>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<Flex>
|
||||||
|
{instance.name}
|
||||||
|
<Actionable left={2} onClick={editName}>
|
||||||
|
<EditIcon />
|
||||||
|
</Actionable>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</H2>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>,
|
</Row>,
|
||||||
<Margin top={2} bottom={3}>
|
<Margin top={2} bottom={3}>
|
||||||
@ -131,14 +178,15 @@ export default withTheme(
|
|||||||
rebooting = false,
|
rebooting = false,
|
||||||
removing = false,
|
removing = false,
|
||||||
onAction,
|
onAction,
|
||||||
theme = {}
|
theme = {},
|
||||||
|
...props
|
||||||
}) => (
|
}) => (
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={12} sm={12} md={9}>
|
<Col xs={12} sm={12} md={9}>
|
||||||
<Card>
|
<Card>
|
||||||
<CardOutlet>
|
<CardOutlet>
|
||||||
<Padding all={4}>
|
<Padding all={4}>
|
||||||
<Meta {...instance} />
|
<Meta {...instance} {...props} />
|
||||||
<Row between="xs">
|
<Row between="xs">
|
||||||
<Col xs={9}>
|
<Col xs={9}>
|
||||||
<Button
|
<Button
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,14 @@ import React from 'react';
|
|||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { set } from 'react-redux-values';
|
import { set } from 'react-redux-values';
|
||||||
|
import { stopSubmit } from 'redux-form';
|
||||||
import { Margin } from 'styled-components-spacing';
|
import { Margin } from 'styled-components-spacing';
|
||||||
import intercept from 'apr-intercept';
|
import intercept from 'apr-intercept';
|
||||||
import isArray from 'lodash.isarray';
|
import isArray from 'lodash.isarray';
|
||||||
import some from 'lodash.some';
|
import some from 'lodash.some';
|
||||||
import isInteger from 'lodash.isinteger';
|
import isInteger from 'lodash.isinteger';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
|
import ReduxForm from 'declarative-redux-form';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ViewContainer,
|
ViewContainer,
|
||||||
@ -22,9 +24,13 @@ import StartInstance from '@graphql/start-instance.gql';
|
|||||||
import StopInstance from '@graphql/stop-instance.gql';
|
import StopInstance from '@graphql/stop-instance.gql';
|
||||||
import RebootInstance from '@graphql/reboot-instance.gql';
|
import RebootInstance from '@graphql/reboot-instance.gql';
|
||||||
import RemoveInstance from '@graphql/remove-instance.gql';
|
import RemoveInstance from '@graphql/remove-instance.gql';
|
||||||
|
import RenameMachine from '@graphql/rename-machine.gql';
|
||||||
import SummaryScreen from '@components/instances/summary';
|
import SummaryScreen from '@components/instances/summary';
|
||||||
import parseError from '@state/parse-error';
|
import parseError from '@state/parse-error';
|
||||||
import Confirm from '@state/confirm';
|
import Confirm from '@state/confirm';
|
||||||
|
import { instanceName as validateName } from '@state/validators';
|
||||||
|
|
||||||
|
const FORM = 'change-name';
|
||||||
|
|
||||||
export const Summary = ({
|
export const Summary = ({
|
||||||
instance,
|
instance,
|
||||||
@ -35,21 +41,39 @@ export const Summary = ({
|
|||||||
starting,
|
starting,
|
||||||
stopping,
|
stopping,
|
||||||
rebooting,
|
rebooting,
|
||||||
removing
|
removing,
|
||||||
|
editName,
|
||||||
|
editingName,
|
||||||
|
handleChangeName,
|
||||||
|
handleAsyncValidate,
|
||||||
|
shouldAsyncValidate
|
||||||
}) => {
|
}) => {
|
||||||
const _loading =
|
const _loading =
|
||||||
loading || (!instance && !loadingError) ? <StatusLoader /> : null;
|
loading || (!instance && !loadingError) ? <StatusLoader /> : null;
|
||||||
|
|
||||||
const _summary = !_loading &&
|
const _summary = !_loading &&
|
||||||
instance && (
|
instance && (
|
||||||
|
<ReduxForm
|
||||||
|
form={FORM}
|
||||||
|
onSubmit={handleChangeName}
|
||||||
|
initialValues={{ name: instance.name }}
|
||||||
|
asyncValidate={handleAsyncValidate}
|
||||||
|
shouldAsyncValidate={shouldAsyncValidate}
|
||||||
|
>
|
||||||
|
{props => (
|
||||||
<SummaryScreen
|
<SummaryScreen
|
||||||
|
{...props}
|
||||||
instance={instance}
|
instance={instance}
|
||||||
starting={starting}
|
starting={starting}
|
||||||
stopping={stopping}
|
stopping={stopping}
|
||||||
rebooting={rebooting}
|
rebooting={rebooting}
|
||||||
removing={removing}
|
removing={removing}
|
||||||
onAction={handleAction}
|
onAction={handleAction}
|
||||||
|
editName={editName}
|
||||||
|
editingName={editingName}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
</ReduxForm>
|
||||||
);
|
);
|
||||||
|
|
||||||
const _error = loadingError &&
|
const _error = loadingError &&
|
||||||
@ -135,6 +159,7 @@ const isPrivate = address => {
|
|||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
graphql(StopInstance, { name: 'stop' }),
|
graphql(StopInstance, { name: 'stop' }),
|
||||||
|
graphql(RenameMachine, { name: 'rename' }),
|
||||||
graphql(StartInstance, { name: 'start' }),
|
graphql(StartInstance, { name: 'start' }),
|
||||||
graphql(RebootInstance, { name: 'reboot' }),
|
graphql(RebootInstance, { name: 'reboot' }),
|
||||||
graphql(RemoveInstance, { name: 'remove' }),
|
graphql(RemoveInstance, { name: 'remove' }),
|
||||||
@ -171,7 +196,7 @@ export default compose(
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
connect(
|
connect(
|
||||||
(state, ownProps) => {
|
({ values }, ownProps) => {
|
||||||
const { instance = {} } = ownProps;
|
const { instance = {} } = ownProps;
|
||||||
const { id } = instance;
|
const { id } = instance;
|
||||||
|
|
||||||
@ -181,14 +206,61 @@ export default compose(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...ownProps,
|
...ownProps,
|
||||||
starting: state.values[`${id}-summary-starting`],
|
editingName: get(values, 'editing-name', false),
|
||||||
stopping: state.values[`${id}-summary-stoping`],
|
starting: values[`${id}-summary-starting`],
|
||||||
rebooting: state.values[`${id}-summary-rebooting`],
|
stopping: values[`${id}-summary-stoping`],
|
||||||
removing: state.values[`${id}-summary-removeing`],
|
rebooting: values[`${id}-summary-rebooting`],
|
||||||
mutationError: state.values[`${id}-summary-mutation-error`]
|
removing: values[`${id}-summary-removeing`],
|
||||||
|
mutationError: values[`${id}-summary-mutation-error`]
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
(disptach, ownProps) => ({
|
(dispatch, ownProps) => ({
|
||||||
|
shouldAsyncValidate: ({ trigger }) => {
|
||||||
|
return trigger === 'change';
|
||||||
|
},
|
||||||
|
handleAsyncValidate: validateName,
|
||||||
|
editName: () =>
|
||||||
|
dispatch(
|
||||||
|
set({
|
||||||
|
name: `editing-name`,
|
||||||
|
value: true
|
||||||
|
})
|
||||||
|
),
|
||||||
|
handleChangeName: async ({ name, id }) => {
|
||||||
|
const { instance } = ownProps;
|
||||||
|
|
||||||
|
if (name === instance.name) {
|
||||||
|
return dispatch(
|
||||||
|
set({
|
||||||
|
name: `editing-name`,
|
||||||
|
value: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const [err] = await intercept(
|
||||||
|
ownProps.rename({
|
||||||
|
variables: {
|
||||||
|
name,
|
||||||
|
id: get(ownProps, 'match.params.instance')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return dispatch(
|
||||||
|
stopSubmit(FORM, {
|
||||||
|
_error: parseError(err)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
set({
|
||||||
|
name: `editing-name`,
|
||||||
|
value: false
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
handleAction: async action => {
|
handleAction: async action => {
|
||||||
const { instance } = ownProps;
|
const { instance } = ownProps;
|
||||||
const { id } = instance;
|
const { id } = instance;
|
||||||
@ -201,7 +273,7 @@ export default compose(
|
|||||||
const name = `${id}-summary-${gerund}`;
|
const name = `${id}-summary-${gerund}`;
|
||||||
|
|
||||||
// sets loading to true
|
// sets loading to true
|
||||||
disptach(
|
dispatch(
|
||||||
set({
|
set({
|
||||||
name,
|
name,
|
||||||
value: true
|
value: true
|
||||||
@ -234,7 +306,7 @@ export default compose(
|
|||||||
value: parseError(err)
|
value: parseError(err)
|
||||||
});
|
});
|
||||||
|
|
||||||
return disptach([mutationError, setLoadingFalse].filter(Boolean));
|
return dispatch([mutationError, setLoadingFalse].filter(Boolean));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
6
packages/my-joy-instances/src/graphql/rename-machine.gql
Normal file
6
packages/my-joy-instances/src/graphql/rename-machine.gql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mutation renameMachine($id: ID!, $name: String!) {
|
||||||
|
renameMachine(id: $id, name: $name) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user