feat(instances): CI - Responsive behavior for tags #1121
This commit is contained in:
parent
c268d88a4d
commit
2f9d135319
@ -10,7 +10,7 @@ import { reset } from 'redux-form';
|
|||||||
import { destroy } from 'redux-form';
|
import { destroy } from 'redux-form';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
import styled from 'styled-components';
|
import styled, { withTheme } from 'styled-components';
|
||||||
|
|
||||||
import Step, {
|
import Step, {
|
||||||
Header as StepHeader,
|
Header as StepHeader,
|
||||||
@ -55,114 +55,122 @@ const Tag = ({ name, value, onRemoveClick }) => (
|
|||||||
</Margin>
|
</Margin>
|
||||||
);
|
);
|
||||||
|
|
||||||
const TagsContainer = ({
|
const TagsContainer = withTheme(
|
||||||
handleValidate,
|
({
|
||||||
handleGetValue,
|
handleValidate,
|
||||||
preview = [],
|
handleGetValue,
|
||||||
tags = [],
|
preview = [],
|
||||||
addOpen = true,
|
tags = [],
|
||||||
shouldAsyncValidate,
|
addOpen = true,
|
||||||
handleAddTag,
|
shouldAsyncValidate,
|
||||||
handleAsyncValidate,
|
handleAddTag,
|
||||||
handleChangeAddOpen,
|
handleAsyncValidate,
|
||||||
handleRemoveTag,
|
handleChangeAddOpen,
|
||||||
handleCancelEdit,
|
handleRemoveTag,
|
||||||
...props
|
handleCancelEdit,
|
||||||
}) => (
|
theme = {},
|
||||||
<Step name="tags" getValue={handleGetValue} {...props}>
|
...props
|
||||||
<StepHeader icon={<TagsIcon />}>Tags</StepHeader>
|
}) => {
|
||||||
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata/tags">
|
const mobile = theme.screen === 'mobile';
|
||||||
Tags can be used to identify your instances, group multiple instances
|
return (
|
||||||
together, define firewall and affinity rules, and more.
|
<Step name="tags" getValue={handleGetValue} {...props}>
|
||||||
</StepDescription>
|
<StepHeader icon={<TagsIcon />}>Tags</StepHeader>
|
||||||
<StepPreview>
|
<StepDescription href="https://docs.joyent.com/public-cloud/tags-metadata/tags">
|
||||||
<Margin top="3">
|
Tags can be used to identify your instances, group multiple instances
|
||||||
<TagCount total={preview.length} />
|
together, define firewall and affinity rules, and more.
|
||||||
<TagList>
|
</StepDescription>
|
||||||
{preview.map(({ name, value }, index) => (
|
<StepPreview>
|
||||||
<Tag name={name} value={value} />
|
<Margin top="3">
|
||||||
))}
|
<TagCount total={preview.length} />
|
||||||
</TagList>
|
<TagList>
|
||||||
</Margin>
|
{preview.map(({ name, value }, index) => (
|
||||||
</StepPreview>
|
<Tag name={name} value={value} />
|
||||||
<StepOutlet>
|
))}
|
||||||
{({ next }) => (
|
</TagList>
|
||||||
<Fragment>
|
</Margin>
|
||||||
{tags.length ? (
|
</StepPreview>
|
||||||
<Margin top="5">
|
<StepOutlet>
|
||||||
<TagCount total={tags.length} />
|
{({ next }) => (
|
||||||
<TagList>
|
|
||||||
{tags.map(({ name, value }, index) => (
|
|
||||||
<Tag
|
|
||||||
name={name}
|
|
||||||
value={value}
|
|
||||||
onRemoveClick={() => handleRemoveTag(index)}
|
|
||||||
id={`tag-${index}`}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</TagList>
|
|
||||||
</Margin>
|
|
||||||
) : null}
|
|
||||||
{addOpen ? (
|
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Margin top="2">
|
{tags.length ? (
|
||||||
<ReduxForm
|
<Margin top="5">
|
||||||
form={IR_TAG_F_ADD}
|
<TagCount total={tags.length} />
|
||||||
destroyOnUnmount={false}
|
<TagList>
|
||||||
forceUnregisterOnUnmount={true}
|
{tags.map(({ name, value }, index) => (
|
||||||
shouldAsyncValidate={shouldAsyncValidate}
|
<Tag
|
||||||
asyncValidate={handleValidate}
|
name={name}
|
||||||
onSubmit={handleAddTag}
|
value={value}
|
||||||
>
|
onRemoveClick={() => handleRemoveTag(index)}
|
||||||
{props => (
|
id={`tag-${index}`}
|
||||||
<Fragment>
|
|
||||||
<KeyValue
|
|
||||||
{...props}
|
|
||||||
method="add"
|
|
||||||
input="input"
|
|
||||||
type="tag"
|
|
||||||
id="tag"
|
|
||||||
expanded
|
|
||||||
borderless
|
|
||||||
onCancel={() => handleChangeAddOpen(false)}
|
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
))}
|
||||||
)}
|
</TagList>
|
||||||
</ReduxForm>
|
</Margin>
|
||||||
</Margin>
|
) : null}
|
||||||
</Fragment>
|
{addOpen ? (
|
||||||
) : (
|
<Fragment>
|
||||||
<Margin top="5">
|
<Margin top="2">
|
||||||
<Flex>
|
<ReduxForm
|
||||||
<FlexItem>
|
form={IR_TAG_F_ADD}
|
||||||
<Margin right="1">
|
destroyOnUnmount={false}
|
||||||
<Button
|
forceUnregisterOnUnmount={true}
|
||||||
id="add-tag-button"
|
shouldAsyncValidate={shouldAsyncValidate}
|
||||||
type="button"
|
asyncValidate={handleValidate}
|
||||||
onClick={() => handleChangeAddOpen(true)}
|
onSubmit={handleAddTag}
|
||||||
secondary
|
|
||||||
>
|
>
|
||||||
Add Tag
|
{props => (
|
||||||
</Button>
|
<Fragment>
|
||||||
|
<KeyValue
|
||||||
|
{...props}
|
||||||
|
method="add"
|
||||||
|
input="input"
|
||||||
|
type="tag"
|
||||||
|
id="tag"
|
||||||
|
expanded
|
||||||
|
borderless
|
||||||
|
onCancel={() => handleChangeAddOpen(false)}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
)}
|
||||||
|
</ReduxForm>
|
||||||
</Margin>
|
</Margin>
|
||||||
</FlexItem>
|
</Fragment>
|
||||||
<FlexItem>
|
) : (
|
||||||
<Button
|
<Margin top="5">
|
||||||
id="next-button-tags"
|
<Flex column={mobile}>
|
||||||
type="button"
|
<FlexItem>
|
||||||
component={Link}
|
<Margin right={mobile ? '0' : '1'}>
|
||||||
to={next}
|
<Button
|
||||||
>
|
id="add-tag-button"
|
||||||
Next
|
type="button"
|
||||||
</Button>
|
onClick={() => handleChangeAddOpen(true)}
|
||||||
</FlexItem>
|
secondary
|
||||||
</Flex>
|
fluid={mobile}
|
||||||
</Margin>
|
>
|
||||||
|
Add Tag
|
||||||
|
</Button>
|
||||||
|
</Margin>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem>
|
||||||
|
<Button
|
||||||
|
id="next-button-tags"
|
||||||
|
type="button"
|
||||||
|
component={Link}
|
||||||
|
to={next}
|
||||||
|
fluid={mobile}
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</Button>
|
||||||
|
</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
</Margin>
|
||||||
|
)}
|
||||||
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</StepOutlet>
|
||||||
)}
|
</Step>
|
||||||
</StepOutlet>
|
);
|
||||||
</Step>
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { Margin, Padding } from 'styled-components-spacing';
|
import { Margin, Padding } from 'styled-components-spacing';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import styled from 'styled-components';
|
import styled, { withTheme } from 'styled-components';
|
||||||
import { Row, Col as BaseCol } from 'joyent-react-styled-flexboxgrid';
|
import { Row, Col as BaseCol } from 'joyent-react-styled-flexboxgrid';
|
||||||
import { Field } from 'redux-form';
|
import { Field } from 'redux-form';
|
||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
@ -198,169 +198,152 @@ const InputKeyValue = ({
|
|||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const KeyValue = ({
|
export const KeyValue = withTheme(
|
||||||
id = null,
|
({
|
||||||
disabled = false,
|
id = null,
|
||||||
input = 'input',
|
disabled = false,
|
||||||
type = 'metadata',
|
input = 'input',
|
||||||
typeLabel = 'key',
|
type = 'metadata',
|
||||||
method = 'add',
|
typeLabel = 'key',
|
||||||
initialValues = {},
|
method = 'add',
|
||||||
error = null,
|
initialValues = {},
|
||||||
expanded = true,
|
error = null,
|
||||||
submitting = false,
|
expanded = true,
|
||||||
pristine = true,
|
submitting = false,
|
||||||
invalid = false,
|
pristine = true,
|
||||||
removing = false,
|
invalid = false,
|
||||||
onToggleExpanded,
|
removing = false,
|
||||||
onCancel = () => null,
|
onToggleExpanded,
|
||||||
onRemove = () => null,
|
onCancel = () => null,
|
||||||
editor = null,
|
onRemove = () => null,
|
||||||
onlyName = false,
|
editor = null,
|
||||||
onlyValue = false,
|
onlyName = false,
|
||||||
noRemove = false,
|
onlyValue = false,
|
||||||
borderless = false,
|
noRemove = false,
|
||||||
shadow = true,
|
borderless = false,
|
||||||
customHeader,
|
shadow = true,
|
||||||
headless = false,
|
customHeader,
|
||||||
noActions = false
|
headless = false,
|
||||||
}) => {
|
noActions = false,
|
||||||
const handleHeaderClick = method === 'edit' && onToggleExpanded;
|
theme = {}
|
||||||
const mobile = theme.screen === 'mobile';
|
}) => {
|
||||||
|
const handleHeaderClick = method === 'edit' && onToggleExpanded;
|
||||||
|
const mobile = theme.screen === 'mobile';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
collapsed={!expanded}
|
collapsed={!expanded}
|
||||||
actionable={Boolean(handleHeaderClick)}
|
actionable={Boolean(handleHeaderClick)}
|
||||||
borderless={borderless}
|
borderless={borderless}
|
||||||
headless={headless}
|
headless={headless}
|
||||||
shadow={shadow}
|
shadow={shadow}
|
||||||
>
|
>
|
||||||
{headless ? null : (
|
{headless ? null : (
|
||||||
<Header
|
<Header
|
||||||
secondary={false}
|
secondary={false}
|
||||||
transparent={false}
|
transparent={false}
|
||||||
actionable={Boolean(handleHeaderClick)}
|
actionable={Boolean(handleHeaderClick)}
|
||||||
onClick={handleHeaderClick}
|
onClick={handleHeaderClick}
|
||||||
>
|
|
||||||
<PaddingMaxWidth
|
|
||||||
left={borderless ? '0' : '3'}
|
|
||||||
right={borderless ? '0' : '3'}
|
|
||||||
>
|
>
|
||||||
<Flex alignCenter justifyBetween>
|
<PaddingMaxWidth
|
||||||
<Meta>
|
left={borderless ? '0' : '3'}
|
||||||
{method === 'add' || method === 'create' ? (
|
right={borderless ? '0' : '3'}
|
||||||
<H4>{`${titleCase(method)} ${type}`}</H4>
|
>
|
||||||
) : (
|
<Flex alignCenter justifyBetween>
|
||||||
<CollapsedKeyValue>
|
<Meta>
|
||||||
{customHeader ? customHeader : null}
|
{method === 'add' || method === 'create' ? (
|
||||||
{initialValues.name ? (
|
<H4>{`${titleCase(method)} ${type}`}</H4>
|
||||||
<Fragment>
|
) : (
|
||||||
{expanded ? (
|
<CollapsedKeyValue>
|
||||||
<span>{`${initialValues.name}${': '}`}</span>
|
{customHeader ? customHeader : null}
|
||||||
) : (
|
{initialValues.name ? (
|
||||||
<Bold>{`${initialValues.name}${': '}`}</Bold>
|
<Fragment>
|
||||||
)}
|
{expanded ? (
|
||||||
<span>{initialValues.value}</span>
|
<span>{`${initialValues.name}${': '}`}</span>
|
||||||
</Fragment>
|
) : (
|
||||||
) : null}
|
<Bold>{`${initialValues.name}${': '}`}</Bold>
|
||||||
</CollapsedKeyValue>
|
)}
|
||||||
)}
|
<span>{initialValues.value}</span>
|
||||||
</Meta>
|
</Fragment>
|
||||||
{handleHeaderClick ? (
|
) : null}
|
||||||
<ArrowIcon
|
</CollapsedKeyValue>
|
||||||
onClick={onToggleExpanded}
|
)}
|
||||||
direction={expanded ? 'up' : 'down'}
|
</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}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</Flex>
|
{input === 'textarea' ? (
|
||||||
</PaddingMaxWidth>
|
<TextareaKeyValue
|
||||||
</Header>
|
id={id}
|
||||||
)}
|
type={type}
|
||||||
{expanded ? (
|
submitting={disabled || submitting}
|
||||||
<CardOutlet>
|
onlyName={onlyName}
|
||||||
<Padding
|
onlyValue={onlyValue}
|
||||||
top={headless ? '0' : '3'}
|
editor={editor}
|
||||||
bottom={borderless ? '0' : '3'}
|
/>
|
||||||
horizontal={borderless ? '0' : '3'}
|
) : null}
|
||||||
>
|
{input !== 'textarea' && input !== 'input'
|
||||||
{error && !submitting ? (
|
? input(submitting)
|
||||||
<Row>
|
: null}
|
||||||
<Col xs="12">
|
<Margin top={mobile ? '3' : '2'}>
|
||||||
<Margin bottom="5">
|
<Row between="xs" middle="xs">
|
||||||
<Message error>
|
<Col xs={method === 'add' ? '12' : '7'} mobile={mobile}>
|
||||||
<MessageTitle>Ooops!</MessageTitle>
|
<Margin top={mobile ? '1' : '0'} inline>
|
||||||
<MessageDescription>{error}</MessageDescription>
|
<MarginalButton
|
||||||
</Message>
|
id={id ? 'kv-cancel-button-' + id : null}
|
||||||
</Margin>
|
type="button"
|
||||||
</Col>
|
onClick={onCancel}
|
||||||
</Row>
|
disabled={disabled || submitting}
|
||||||
) : null}
|
secondary
|
||||||
{input === 'input' ? (
|
fluid={mobile}
|
||||||
<InputKeyValue
|
>
|
||||||
id={id}
|
<span>Cancel</span>
|
||||||
onBlur={null}
|
</MarginalButton>
|
||||||
type={type}
|
</Margin>
|
||||||
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}
|
|
||||||
/>
|
|
||||||
) : 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}
|
|
||||||
fluid={mobile}
|
|
||||||
>
|
|
||||||
<span>{method === 'add' ? 'Create' : 'Save'}</span>
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
{!noRemove && (
|
|
||||||
<Col xs={method === 'add' ? false : '5'}>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
onClick={onCancel}
|
|
||||||
disabled={disabled || submitting}
|
|
||||||
secondary
|
|
||||||
>
|
|
||||||
<span>Cancel</span>
|
|
||||||
</MarginalButton>
|
|
||||||
<Button
|
<Button
|
||||||
id={id ? 'kv-submit-button-' + id : null}
|
id={id ? 'kv-submit-button-' + id : null}
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={pristine || invalid}
|
disabled={pristine || invalid}
|
||||||
loading={submitting && !removing}
|
loading={submitting && !removing}
|
||||||
|
fluid={mobile}
|
||||||
>
|
>
|
||||||
<span>{method === 'add' ? 'Create' : 'Save'}</span>
|
<span>{method === 'add' ? 'Create' : 'Save'}</span>
|
||||||
</Button>
|
</Button>
|
||||||
@ -378,7 +361,7 @@ export const KeyValue = ({
|
|||||||
error
|
error
|
||||||
id={id ? 'kv-remove-button-' + id : null}
|
id={id ? 'kv-remove-button-' + id : null}
|
||||||
>
|
>
|
||||||
<Margin right="2">
|
<Margin right={2}>
|
||||||
<DeleteIcon
|
<DeleteIcon
|
||||||
disabled={disabled || submitting}
|
disabled={disabled || submitting}
|
||||||
fill={disabled || submitting ? undefined : 'red'}
|
fill={disabled || submitting ? undefined : 'red'}
|
||||||
@ -390,13 +373,14 @@ export const KeyValue = ({
|
|||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
</Margin>
|
</Margin>
|
||||||
)}
|
)}
|
||||||
</Padding>
|
</Padding>
|
||||||
</CardOutlet>
|
</CardOutlet>
|
||||||
) : null}
|
) : null}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
);
|
||||||
|
|
||||||
KeyValue.propTypes = {
|
KeyValue.propTypes = {
|
||||||
input: PropTypes.oneOf(['input', 'textarea']).isRequired,
|
input: PropTypes.oneOf(['input', 'textarea']).isRequired,
|
||||||
|
Loading…
Reference in New Issue
Block a user