feat(instances): CI - metadata resposive

This commit is contained in:
Fábio Moreira 2018-05-30 14:47:36 +01:00 committed by Sérgio Ramos
parent 2f9d135319
commit cad1431e79
3 changed files with 396 additions and 383 deletions

View File

@ -1,6 +1,8 @@
import React, { Fragment } from 'react';
import { Margin } from 'styled-components-spacing';
import Flex, { FlexItem } from 'styled-flex-component';
import { withTheme } from 'styled-components';
import { compose } from 'react-apollo';
import { Link } from 'react-router-dom';
import ReduxForm from 'declarative-redux-form';
@ -41,97 +43,105 @@ const Metadata = ({
shouldAsyncValidate,
handleAsyncValidate,
handleChangeAddOpen,
theme = {},
...props
}) => (
<Step name="metadata" getValue={handleGetValue} {...props}>
<StepHeader icon={<MetadataIcon />}>Metadata</StepHeader>
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata">
Metadata can be used to pass data to the instance. It can also be used to
inject a custom boot script. Unlike tags, metadata is only viewable inside
the instance.
</StepDescription>
<StepPreview>
<Margin top="3">
<Preview metadata={preview} disabled />
</Margin>
</StepPreview>
<StepOutlet>
{({ next }) => (
<Margin top="5">
{metadata.length ? (
<Fragment>
<Preview
metadata={metadata}
handleCancelEdit={handleCancelEdit}
handleRemoveMetadata={handleRemoveMetadata}
handleToggleExpanded={handleToggleExpanded}
handleUpdateMetadata={handleUpdateMetadata}
handleAddMetadata={handleAddMetadata}
shouldAsyncValidate={shouldAsyncValidate}
handleAsyncValidate={handleAsyncValidate}
handleChangeAddOpen={handleChangeAddOpen}
addOpen={addOpen}
/>
</Fragment>
) : null}
<ReduxForm
form={IR_MD_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleAddMetadata}
shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleAsyncValidate}
>
{props =>
addOpen ? (
<Fragment>
<KeyValue
{...props}
method="add"
input="textarea"
type="metadata"
id="metadata"
onCancel={() => handleChangeAddOpen(false)}
editor={Editor}
expanded
shadow={false}
/>
</Fragment>
) : (
<Margin top="5">
<Flex>
<FlexItem>
<Margin right="1">
<Button
id="button-add-metadata"
type="button"
onClick={() => handleChangeAddOpen(true)}
secondary
>
Add Metadata
</Button>
</Margin>
</FlexItem>
<FlexItem>
<Button
id="next-button-metadata"
type="button"
component={Link}
to={next}
>
Next
</Button>
</FlexItem>
</Flex>
</Margin>
)
}
</ReduxForm>
}) => {
const mobile = theme.screen === 'mobile';
return (
<Step name="metadata" getValue={handleGetValue} {...props}>
<StepHeader icon={<MetadataIcon />}>Metadata</StepHeader>
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata">
Metadata can be used to pass data to the instance. It can also be used
to inject a custom boot script. Unlike tags, metadata is only viewable
inside the instance.
</StepDescription>
<StepPreview>
<Margin top="3">
<Preview metadata={preview} disabled />
</Margin>
)}
</StepOutlet>
</Step>
);
</StepPreview>
<StepOutlet>
{({ next }) => (
<Margin top="5">
{metadata.length ? (
<Fragment>
<Preview
metadata={metadata}
handleCancelEdit={handleCancelEdit}
handleRemoveMetadata={handleRemoveMetadata}
handleToggleExpanded={handleToggleExpanded}
handleUpdateMetadata={handleUpdateMetadata}
handleAddMetadata={handleAddMetadata}
shouldAsyncValidate={shouldAsyncValidate}
handleAsyncValidate={handleAsyncValidate}
handleChangeAddOpen={handleChangeAddOpen}
addOpen={addOpen}
/>
</Fragment>
) : null}
<ReduxForm
form={IR_MD_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
onSubmit={handleAddMetadata}
shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleAsyncValidate}
>
{props =>
addOpen ? (
<Fragment>
<KeyValue
{...props}
method="add"
input="textarea"
type="metadata"
id="metadata"
onCancel={() => handleChangeAddOpen(false)}
editor={Editor}
expanded
shadow={false}
/>
</Fragment>
) : (
<Margin top="5">
<Flex column={mobile}>
<FlexItem>
<Margin right={mobile ? '0' : '1'}>
<Button
id="button-add-metadata"
type="button"
onClick={() => handleChangeAddOpen(true)}
secondary
>
Add Metadata
</Button>
</Margin>
</FlexItem>
<FlexItem>
<Margin top={mobile ? 1 : 0}>
<Button
id="next-button-metadata"
type="button"
component={Link}
to={next}
fluid={mobile}
>
Next
</Button>
</Margin>
</FlexItem>
</Flex>
</Margin>
)
}
</ReduxForm>
</Margin>
)}
</StepOutlet>
</Step>
);
};
export default compose(
connect(({ values }, ownProps) => {
@ -203,4 +213,4 @@ export default compose(
]);
}
}))
)(Metadata);
)(withTheme(({ ...rest }) => <Metadata {...rest} />));

View File

@ -55,123 +55,121 @@ const Tag = ({ name, value, onRemoveClick }) => (
</Margin>
);
const TagsContainer = withTheme(
({
handleValidate,
handleGetValue,
preview = [],
tags = [],
addOpen = true,
shouldAsyncValidate,
handleAddTag,
handleAsyncValidate,
handleChangeAddOpen,
handleRemoveTag,
handleCancelEdit,
theme = {},
...props
}) => {
const mobile = theme.screen === 'mobile';
return (
<Step name="tags" getValue={handleGetValue} {...props}>
<StepHeader icon={<TagsIcon />}>Tags</StepHeader>
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata/tags">
Tags can be used to identify your instances, group multiple instances
together, define firewall and affinity rules, and more.
</StepDescription>
<StepPreview>
<Margin top="3">
<TagCount total={preview.length} />
<TagList>
{preview.map(({ name, value }, index) => (
<Tag name={name} value={value} />
))}
</TagList>
</Margin>
</StepPreview>
<StepOutlet>
{({ next }) => (
<Fragment>
{tags.length ? (
<Margin top="5">
<TagCount total={tags.length} />
<TagList>
{tags.map(({ name, value }, index) => (
<Tag
name={name}
value={value}
onRemoveClick={() => handleRemoveTag(index)}
id={`tag-${index}`}
/>
))}
</TagList>
const TagsContainer = ({
handleValidate,
handleGetValue,
preview = [],
tags = [],
addOpen = true,
shouldAsyncValidate,
handleAddTag,
handleAsyncValidate,
handleChangeAddOpen,
handleRemoveTag,
handleCancelEdit,
theme = {},
...props
}) => {
const mobile = theme.screen === 'mobile';
return (
<Step name="tags" getValue={handleGetValue} {...props}>
<StepHeader icon={<TagsIcon />}>Tags</StepHeader>
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata/tags">
Tags can be used to identify your instances, group multiple instances
together, define firewall and affinity rules, and more.
</StepDescription>
<StepPreview>
<Margin top="3">
<TagCount total={preview.length} />
<TagList>
{preview.map(({ name, value }, index) => (
<Tag name={name} value={value} />
))}
</TagList>
</Margin>
</StepPreview>
<StepOutlet>
{({ next }) => (
<Fragment>
{tags.length ? (
<Margin top="5">
<TagCount total={tags.length} />
<TagList>
{tags.map(({ name, value }, index) => (
<Tag
name={name}
value={value}
onRemoveClick={() => handleRemoveTag(index)}
id={`tag-${index}`}
/>
))}
</TagList>
</Margin>
) : null}
{addOpen ? (
<Fragment>
<Margin top="2">
<ReduxForm
form={IR_TAG_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleValidate}
onSubmit={handleAddTag}
>
{props => (
<Fragment>
<KeyValue
{...props}
method="add"
input="input"
type="tag"
id="tag"
expanded
borderless
onCancel={() => handleChangeAddOpen(false)}
/>
</Fragment>
)}
</ReduxForm>
</Margin>
) : null}
{addOpen ? (
<Fragment>
<Margin top="2">
<ReduxForm
form={IR_TAG_F_ADD}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleValidate}
onSubmit={handleAddTag}
>
{props => (
<Fragment>
<KeyValue
{...props}
method="add"
input="input"
type="tag"
id="tag"
expanded
borderless
onCancel={() => handleChangeAddOpen(false)}
/>
</Fragment>
)}
</ReduxForm>
</Margin>
</Fragment>
) : (
<Margin top="5">
<Flex column={mobile}>
<FlexItem>
<Margin right={mobile ? '0' : '1'}>
<Button
id="add-tag-button"
type="button"
onClick={() => handleChangeAddOpen(true)}
secondary
fluid={mobile}
>
Add Tag
</Button>
</Margin>
</FlexItem>
<FlexItem>
</Fragment>
) : (
<Margin top="5">
<Flex column={mobile}>
<FlexItem>
<Margin right={mobile ? '0' : '1'}>
<Button
id="next-button-tags"
id="add-tag-button"
type="button"
component={Link}
to={next}
onClick={() => handleChangeAddOpen(true)}
secondary
fluid={mobile}
>
Next
Add Tag
</Button>
</FlexItem>
</Flex>
</Margin>
)}
</Fragment>
)}
</StepOutlet>
</Step>
);
}
);
</Margin>
</FlexItem>
<FlexItem>
<Button
id="next-button-tags"
type="button"
component={Link}
to={next}
fluid={mobile}
>
Next
</Button>
</FlexItem>
</Flex>
</Margin>
)}
</Fragment>
)}
</StepOutlet>
</Step>
);
};
export default compose(
connect(({ values }, ownProps) => {
@ -225,4 +223,4 @@ export default compose(
]);
}
}))
)(TagsContainer);
)(withTheme(({ ...rest }) => <Metadata {...rest} />));

View File

@ -83,7 +83,8 @@ const TextareaKeyValue = ({
submitting,
onlyName,
onlyValue,
editor
editor,
mobile
}) => (
<Fragment>
{onlyValue ? null : (
@ -97,7 +98,12 @@ const TextareaKeyValue = ({
>
<FormLabel>{titleCase(type)} key</FormLabel>
<Margin top="0.5">
<Input onBlur={null} type="text" disabled={submitting} />
<Input
onBlur={null}
type="text"
disabled={submitting}
fluid={mobile}
/>
<Row>
<Col sm="7">
<FormMeta />
@ -105,6 +111,7 @@ const TextareaKeyValue = ({
</Row>
</Margin>
</FormGroup>
<Divider height={remcalc(12)} transparent />
</Col>
</Row>
)}
@ -133,6 +140,7 @@ const TextareaKeyValue = ({
</Col>
</Row>
</FormGroup>
<Divider height={remcalc(12)} transparent />
</Col>
</Row>
)}
@ -149,7 +157,7 @@ const InputKeyValue = ({
fluid = false
}) => (
<Flex wrap justifyStart contentStretch column={fluid}>
{!onlyValue ? (
{onlyValue ? null : (
<FlexItem basis="auto">
<FormGroup
id={id ? 'kv-input-name-' + id : null}
@ -170,7 +178,7 @@ const InputKeyValue = ({
</Margin>
</FormGroup>
</FlexItem>
) : null}
)}
{onlyName ? null : (
<Fragment>
<FlexItem basis="auto">
@ -198,189 +206,186 @@ const InputKeyValue = ({
</Flex>
);
export const KeyValue = withTheme(
({
id = null,
disabled = false,
input = 'input',
type = 'metadata',
typeLabel = 'key',
method = 'add',
initialValues = {},
error = null,
expanded = true,
submitting = false,
pristine = true,
invalid = false,
removing = false,
onToggleExpanded,
onCancel = () => null,
onRemove = () => null,
editor = null,
onlyName = false,
onlyValue = false,
noRemove = false,
borderless = false,
shadow = true,
customHeader,
headless = false,
noActions = false,
theme = {}
}) => {
const handleHeaderClick = method === 'edit' && onToggleExpanded;
const mobile = theme.screen === 'mobile';
export const KeyValue = ({
id = null,
disabled = false,
input = 'input',
type = 'metadata',
typeLabel = 'key',
method = 'add',
initialValues = {},
error = null,
expanded = true,
submitting = false,
pristine = true,
invalid = false,
removing = false,
onToggleExpanded,
onCancel = () => null,
onRemove = () => null,
theme = {},
editor = null,
onlyName = false,
onlyValue = false,
noRemove = false,
borderless = false,
shadow = true,
customHeader,
headless = false
}) => {
const handleHeaderClick = method === 'edit' && onToggleExpanded;
const mobile = theme.screen === 'mobile';
return (
<Card
collapsed={!expanded}
actionable={Boolean(handleHeaderClick)}
borderless={borderless}
headless={headless}
shadow={shadow}
>
{headless ? null : (
<Header
secondary={false}
transparent={false}
actionable={Boolean(handleHeaderClick)}
onClick={handleHeaderClick}
return (
<Card
collapsed={!expanded}
actionable={Boolean(handleHeaderClick)}
borderless={borderless}
headless={headless}
shadow={shadow}
>
{headless ? null : (
<Header
secondary={false}
transparent={false}
actionable={Boolean(handleHeaderClick)}
onClick={handleHeaderClick}
>
<PaddingMaxWidth
left={borderless ? '0' : '3'}
right={borderless ? '0' : '3'}
>
<PaddingMaxWidth
left={borderless ? '0' : '3'}
right={borderless ? '0' : '3'}
>
<Flex alignCenter justifyBetween>
<Meta>
{method === 'add' || method === 'create' ? (
<H4>{`${titleCase(method)} ${type}`}</H4>
) : (
<CollapsedKeyValue>
{customHeader ? customHeader : null}
{initialValues.name ? (
<Fragment>
{expanded ? (
<span>{`${initialValues.name}${': '}`}</span>
) : (
<Bold>{`${initialValues.name}${': '}`}</Bold>
)}
<span>{initialValues.value}</span>
</Fragment>
) : null}
</CollapsedKeyValue>
)}
</Meta>
{handleHeaderClick ? (
<ArrowIcon
onClick={onToggleExpanded}
direction={expanded ? 'up' : 'down'}
/>
) : null}
</Flex>
</PaddingMaxWidth>
</Header>
)}
{expanded ? (
<CardOutlet>
<Padding
top={headless ? '0' : '3'}
bottom={borderless ? '0' : '3'}
horizontal={borderless ? '0' : '3'}
>
{error && !submitting ? (
<Row>
<Col xs="12">
<Margin bottom="5">
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{error}</MessageDescription>
</Message>
</Margin>
</Col>
</Row>
) : null}
{input === 'input' ? (
<InputKeyValue
id={id}
onBlur={null}
type={type}
typeLabel={typeLabel}
submitting={disabled || submitting}
onlyName={onlyName}
onlyValue={onlyValue}
fluid={mobile}
<Flex alignCenter justifyBetween>
<Meta>
{method === 'add' || method === 'create' ? (
<H4>{`${titleCase(method)} ${type}`}</H4>
) : (
<CollapsedKeyValue>
{customHeader ? customHeader : null}
{initialValues.name ? (
<Fragment>
{expanded ? (
<span>{`${initialValues.name}${': '}`}</span>
) : (
<Bold>{`${initialValues.name}${': '}`}</Bold>
)}
<span>{initialValues.value}</span>
</Fragment>
) : null}
</CollapsedKeyValue>
)}
</Meta>
{handleHeaderClick ? (
<ArrowIcon
onClick={onToggleExpanded}
direction={expanded ? 'up' : 'down'}
/>
) : null}
{input === 'textarea' ? (
<TextareaKeyValue
id={id}
type={type}
submitting={disabled || submitting}
onlyName={onlyName}
onlyValue={onlyValue}
editor={editor}
/>
) : null}
{input !== 'textarea' && input !== 'input'
? input(submitting)
: null}
<Margin top={mobile ? '3' : '2'}>
<Row between="xs" middle="xs">
<Col xs={method === 'add' ? '12' : '7'} mobile={mobile}>
<Margin top={mobile ? '1' : '0'} inline>
<MarginalButton
id={id ? 'kv-cancel-button-' + id : null}
type="button"
onClick={onCancel}
disabled={disabled || submitting}
secondary
fluid={mobile}
>
<span>Cancel</span>
</MarginalButton>
</Margin>
<Button
id={id ? 'kv-submit-button-' + id : null}
type="submit"
disabled={pristine || invalid}
loading={submitting && !removing}
</Flex>
</PaddingMaxWidth>
</Header>
)}
{expanded ? (
<CardOutlet>
<Padding
top={headless ? '0' : '3'}
bottom={borderless ? '0' : '3'}
horizontal={borderless ? '0' : '3'}
>
{error && !submitting ? (
<Row>
<Col xs="12">
<Margin bottom="5">
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{error}</MessageDescription>
</Message>
</Margin>
</Col>
</Row>
) : null}
{input === 'input' ? (
<InputKeyValue
id={id}
onBlur={null}
type={type}
typeLabel={typeLabel}
submitting={disabled || submitting}
onlyName={onlyName}
onlyValue={onlyValue}
fluid={mobile}
/>
) : null}
{input === 'textarea' ? (
<TextareaKeyValue
id={id}
type={type}
submitting={disabled || submitting}
onlyName={onlyName}
onlyValue={onlyValue}
editor={editor}
mobile={mobile}
/>
) : null}
{input !== 'textarea' && input !== 'input'
? input(submitting)
: null}
<Margin top={mobile ? '3' : '2'}>
<Row between="xs" middle="xs">
<Col xs={method === 'add' ? '12' : '7'} mobile={mobile}>
<Margin top={mobile ? '1' : '0'} inline>
<MarginalButton
id={id ? 'kv-cancel-button-' + id : null}
type="button"
onClick={onCancel}
disabled={disabled || submitting}
secondary
fluid={mobile}
>
<span>{method === 'add' ? 'Create' : 'Save'}</span>
<span>Cancel</span>
</MarginalButton>
</Margin>
<Button
id={id ? 'kv-submit-button-' + id : null}
type="submit"
disabled={pristine || invalid}
loading={submitting && !removing}
fluid={mobile}
>
<span>{method === 'add' ? 'Create' : 'Save'}</span>
</Button>
</Col>
{!noRemove && (
<Col xs={method === 'add' ? false : '5'}>
<Button
type="button"
onClick={onRemove}
disabled={disabled || submitting}
loading={removing}
secondary
right
icon
error
id={id ? 'kv-remove-button-' + id : null}
>
<Margin right="2">
<DeleteIcon
disabled={disabled || submitting}
fill={disabled || submitting ? undefined : theme.red}
/>
</Margin>
<span>Delete</span>
</Button>
</Col>
{!noRemove && (
<Col xs={method === 'add' ? false : '5'}>
<Button
type="button"
onClick={onRemove}
disabled={disabled || submitting}
loading={removing}
secondary
right
icon
error
id={id ? 'kv-remove-button-' + id : null}
>
<Margin right={2}>
<DeleteIcon
disabled={disabled || submitting}
fill={disabled || submitting ? undefined : 'red'}
/>
</Margin>
<span>Delete</span>
</Button>
</Col>
)}
</Row>
</Margin>
)}
</Padding>
</CardOutlet>
) : null}
</Card>
);
}
);
)}
</Row>
</Margin>
</Padding>
</CardOutlet>
) : null}
</Card>
);
};
KeyValue.propTypes = {
input: PropTypes.oneOf(['input', 'textarea']).isRequired,
@ -397,8 +402,8 @@ KeyValue.propTypes = {
onRemove: PropTypes.func
};
export default ({ handleSubmit, ...rest }) => (
export default withTheme(({ handleSubmit, ...rest }) => (
<form onSubmit={handleSubmit}>
<KeyValue {...rest} />
</form>
);
));