feat(my-joy-beta): revise Tags to use new KeyValue
This commit is contained in:
parent
2538453d98
commit
8f7694f7f4
10
package.json
10
package.json
@ -69,15 +69,9 @@
|
|||||||
},
|
},
|
||||||
"workspaces": ["packages/*", "prototypes/*"],
|
"workspaces": ["packages/*", "prototypes/*"],
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"graphql": "0.12.3",
|
"hoist-non-react-statics": "2.3.1",
|
||||||
"lodash": "4.17.4",
|
|
||||||
"lodash.keys": "4.2.0",
|
|
||||||
"lodash.defaults": "4.2.0",
|
|
||||||
"lodash.assign": "4.2.0",
|
|
||||||
"isarray": "'2.0.2",
|
|
||||||
"codemirror": "5.32.0",
|
|
||||||
"react": "16.2.0",
|
"react": "16.2.0",
|
||||||
"react-dom": "16.2.0",
|
"react-dom": "16.2.0",
|
||||||
"hoist-non-react-statics": "2.3.1"
|
"styled-components": "2.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,13 @@
|
|||||||
"repository": "github:yldio/joyent-portal",
|
"repository": "github:yldio/joyent-portal",
|
||||||
"main": "build/",
|
"main": "build/",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev":
|
"dev": "REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
||||||
"REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
|
||||||
"start": "PORT=3069 joyent-react-scripts start",
|
"start": "PORT=3069 joyent-react-scripts start",
|
||||||
"build": "NODE_ENV=production joyent-react-scripts build",
|
"build": "NODE_ENV=production joyent-react-scripts build",
|
||||||
"lint-ci":
|
"lint-ci": "eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
|
||||||
"eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
|
"lint": "eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
|
||||||
"lint":
|
|
||||||
"eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
|
|
||||||
"test": "NODE_ENV=test joyent-react-scripts test --env=jsdom",
|
"test": "NODE_ENV=test joyent-react-scripts test --env=jsdom",
|
||||||
"test-ci": "echo 0",
|
"test-ci": "npm run test",
|
||||||
"prepublish": "echo 0"
|
"prepublish": "echo 0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,86 +1,64 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import renderer from 'react-test-renderer';
|
import renderer from 'react-test-renderer';
|
||||||
import { reduxForm } from 'redux-form';
|
|
||||||
import 'jest-styled-components';
|
import 'jest-styled-components';
|
||||||
|
import Theme from '@mocks/theme';
|
||||||
|
|
||||||
import Store from '@mocks/store';
|
import { KeyValue } from '../key-value';
|
||||||
import KeyValue from '../key-value';
|
|
||||||
|
|
||||||
const KeyValueForm = reduxForm()(KeyValue);
|
// KeyValue.propTypes = {
|
||||||
|
// input: PropTypes.oneOf(['input', 'textarea']).isRequired,
|
||||||
|
// type: PropTypes.string.isRequired,
|
||||||
|
// method: PropTypes.oneOf(['add', 'edit']).isRequired,
|
||||||
|
// removing: PropTypes.bool.isRequired,
|
||||||
|
// expanded: PropTypes.bool.isRequired,
|
||||||
|
// onToggleExpanded: PropTypes.func,
|
||||||
|
// onCancel: PropTypes.func,
|
||||||
|
// onRemove: PropTypes.func
|
||||||
|
// };
|
||||||
|
|
||||||
it('renders <KeyValue /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Store>
|
|
||||||
<KeyValueForm />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue textarea /> with textareas', () => {
|
it('renders <KeyValue /> without throwing', () => expect(renderer.create(<Theme><KeyValue /></Theme>).toJSON()).toMatchSnapshot());
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Store>
|
|
||||||
<KeyValueForm textarea />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue expanded /> expanded', () => {
|
it('renders <KeyValue input="input" /> without throwing', () =>
|
||||||
const tree = renderer
|
expect(
|
||||||
.create(
|
renderer.create(<Theme><KeyValue input="input" /></Theme>).toJSON()
|
||||||
<Store>
|
).toMatchSnapshot());
|
||||||
<KeyValueForm expanded />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue submitting /> with loader', () => {
|
it('renders <KeyValue input="textarea" /> without throwing', () =>
|
||||||
const tree = renderer
|
expect(
|
||||||
.create(
|
renderer.create(<Theme><KeyValue input="textarea" /></Theme>).toJSON()
|
||||||
<Store>
|
).toMatchSnapshot());
|
||||||
<KeyValueForm submitting />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue first /> without top margin', () => {
|
it('renders <KeyValue type="tag" /> without throwing', () =>
|
||||||
const tree = renderer
|
expect(renderer.create(<Theme><KeyValue type="tag" /></Theme>).toJSON()).toMatchSnapshot());
|
||||||
.create(
|
|
||||||
<Store>
|
|
||||||
<KeyValueForm first />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue last /> with bottom border', () => {
|
it('renders <KeyValue method="add" /> without throwing', () =>
|
||||||
const tree = renderer
|
expect(
|
||||||
.create(
|
renderer.create(<Theme><KeyValue method="add" /></Theme>).toJSON()
|
||||||
<Store>
|
).toMatchSnapshot());
|
||||||
<KeyValueForm last />
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders <KeyValue label /> with proper label', () => {
|
it('renders <KeyValue method="edit" /> without throwing', () =>
|
||||||
const tree = renderer
|
expect(
|
||||||
.create(
|
renderer.create(<Theme><KeyValue method="edit" /></Theme>).toJSON()
|
||||||
<Store>
|
).toMatchSnapshot());
|
||||||
<KeyValueForm label="Label" />
|
|
||||||
</Store>
|
it('renders <KeyValue removing /> without throwing', () =>
|
||||||
)
|
expect(renderer.create(<Theme><KeyValue removing /></Theme>).toJSON()).toMatchSnapshot());
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
it('renders <KeyValue submitting removing /> without throwing', () =>
|
||||||
});
|
expect(
|
||||||
|
renderer.create(<Theme><KeyValue submitting removing /></Theme>).toJSON()
|
||||||
|
).toMatchSnapshot());
|
||||||
|
|
||||||
|
it('renders <KeyValue expanded /> without throwing', () =>
|
||||||
|
expect(renderer.create(<Theme><KeyValue expanded /></Theme>).toJSON()).toMatchSnapshot());
|
||||||
|
|
||||||
|
it('renders <KeyValue expanded removing /> without throwing', () =>
|
||||||
|
expect(
|
||||||
|
renderer.create(<Theme><KeyValue expanded removing /></Theme>).toJSON()
|
||||||
|
).toMatchSnapshot());
|
||||||
|
|
||||||
|
it('renders <KeyValue expanded submitting removing /> without throwing', () =>
|
||||||
|
expect(
|
||||||
|
renderer.create(<Theme><KeyValue expanded submitting removing /></Theme>).toJSON()
|
||||||
|
).toMatchSnapshot());
|
||||||
|
@ -2,12 +2,11 @@ import React, { PureComponent } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { withTheme } from 'styled-components';
|
import { withTheme } from 'styled-components';
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
import { Row, Col } from 'react-styled-flexboxgrid';
|
||||||
import Value from 'react-redux-values';
|
|
||||||
import { Field } from 'redux-form';
|
import { Field } from 'redux-form';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
import titleCase from 'title-case';
|
import titleCase from 'title-case';
|
||||||
import { Margin, Padding } from 'styled-components-spacing';
|
import { Padding } from 'styled-components-spacing';
|
||||||
import Flex, { FlexItem } from 'styled-flex-component';
|
import Flex, { FlexItem } from 'styled-flex-component';
|
||||||
import Editor from 'joyent-ui-toolkit/dist/es/editor';
|
import Editor from 'joyent-ui-toolkit/dist/es/editor';
|
||||||
|
|
||||||
@ -19,16 +18,13 @@ import {
|
|||||||
Card,
|
Card,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardHeaderMeta,
|
CardHeaderMeta,
|
||||||
CardHeaderBox,
|
|
||||||
CardOutlet,
|
CardOutlet,
|
||||||
ChevronIcon,
|
|
||||||
FormGroup,
|
FormGroup,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
Input,
|
Input,
|
||||||
FormMeta,
|
FormMeta,
|
||||||
Button,
|
Button,
|
||||||
Textarea,
|
Textarea,
|
||||||
Editor,
|
|
||||||
Divider,
|
Divider,
|
||||||
DeleteIcon
|
DeleteIcon
|
||||||
} from 'joyent-ui-toolkit';
|
} from 'joyent-ui-toolkit';
|
||||||
@ -44,7 +40,7 @@ const CollapsedKeyValue = styled.span`
|
|||||||
|
|
||||||
class ValueTextareaField extends PureComponent {
|
class ValueTextareaField extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { input, submitting } = this.props;
|
const { input = {}, submitting } = this.props;
|
||||||
|
|
||||||
return input.value === 'user-script' ? (
|
return input.value === 'user-script' ? (
|
||||||
<Field name="value" component={Editor} />
|
<Field name="value" component={Editor} />
|
||||||
@ -57,7 +53,7 @@ class ValueTextareaField extends PureComponent {
|
|||||||
const TextareaKeyValue = ({ type, submitting }) => [
|
const TextareaKeyValue = ({ type, submitting }) => [
|
||||||
<Row key="key">
|
<Row key="key">
|
||||||
<Col xs={12}>
|
<Col xs={12}>
|
||||||
<FormGroup name="name" reduxForm fluid>
|
<FormGroup name="name" field={Field} fluid>
|
||||||
<FormLabel>{titleCase(type)} key</FormLabel>
|
<FormLabel>{titleCase(type)} key</FormLabel>
|
||||||
<Input type="text" disabled={submitting} />
|
<Input type="text" disabled={submitting} />
|
||||||
<FormMeta />
|
<FormMeta />
|
||||||
@ -67,7 +63,7 @@ const TextareaKeyValue = ({ type, submitting }) => [
|
|||||||
</Row>,
|
</Row>,
|
||||||
<Row key="value">
|
<Row key="value">
|
||||||
<Col xs={12}>
|
<Col xs={12}>
|
||||||
<FormGroup name="value" reduxForm fluid>
|
<FormGroup name="value" field={Field} fluid>
|
||||||
<FormLabel>{titleCase(type)} value</FormLabel>
|
<FormLabel>{titleCase(type)} value</FormLabel>
|
||||||
<Field
|
<Field
|
||||||
name="name"
|
name="name"
|
||||||
@ -85,14 +81,15 @@ const TextareaKeyValue = ({ type, submitting }) => [
|
|||||||
const InputKeyValue = ({ type, submitting }) => (
|
const InputKeyValue = ({ type, submitting }) => (
|
||||||
<Flex full justifyStart contentStretch>
|
<Flex full justifyStart contentStretch>
|
||||||
<FlexItem basis="auto">
|
<FlexItem basis="auto">
|
||||||
<FormGroup name="name" reduxForm fluid>
|
<FormGroup name="name" field={Field} fluid>
|
||||||
<FormLabel>{titleCase(type)} key</FormLabel>
|
<FormLabel>{titleCase(type)} key</FormLabel>
|
||||||
<Input type="text" disabled={submitting} />
|
<Input type="text" disabled={submitting} />
|
||||||
<FormMeta />
|
<FormMeta />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
|
<FlexItem basis={remcalc(12)} />
|
||||||
<FlexItem basis="auto">
|
<FlexItem basis="auto">
|
||||||
<FormGroup name="value" reduxForm fluid>
|
<FormGroup name="value" field={Field} fluid>
|
||||||
<FormLabel>{titleCase(type)} value</FormLabel>
|
<FormLabel>{titleCase(type)} value</FormLabel>
|
||||||
<Input disabled={submitting} />
|
<Input disabled={submitting} />
|
||||||
<FormMeta />
|
<FormMeta />
|
||||||
@ -101,8 +98,7 @@ const InputKeyValue = ({ type, submitting }) => (
|
|||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
|
||||||
const KeyValue = withTheme(
|
export const KeyValue = ({
|
||||||
({
|
|
||||||
input = 'input',
|
input = 'input',
|
||||||
type = 'metadata',
|
type = 'metadata',
|
||||||
method = 'add',
|
method = 'add',
|
||||||
@ -115,12 +111,11 @@ const KeyValue = withTheme(
|
|||||||
onToggleExpanded = () => null,
|
onToggleExpanded = () => null,
|
||||||
onCancel = () => null,
|
onCancel = () => null,
|
||||||
onRemove = () => null,
|
onRemove = () => null,
|
||||||
theme
|
theme = {}
|
||||||
}) => {
|
}) => {
|
||||||
const handleHeaderClick = method === 'edit' && onToggleExpanded;
|
const handleHeaderClick = method === 'edit' && onToggleExpanded;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<Card collapsed={!expanded} actionable={!expanded} shadow>
|
<Card collapsed={!expanded} actionable={!expanded} shadow>
|
||||||
<CardHeader
|
<CardHeader
|
||||||
secondary={false}
|
secondary={false}
|
||||||
@ -136,18 +131,14 @@ const KeyValue = withTheme(
|
|||||||
<Field
|
<Field
|
||||||
name="name"
|
name="name"
|
||||||
type="text"
|
type="text"
|
||||||
component={({ input }) =>
|
component={({ input = {} }) =>
|
||||||
expanded ? (
|
expanded ? `${input.value}: ` : <b>{`${input.value}: `}</b>
|
||||||
`${input.value}: `
|
|
||||||
) : (
|
|
||||||
<b>{`${input.value}: `}</b>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Field
|
<Field
|
||||||
name="value"
|
name="value"
|
||||||
type="text"
|
type="text"
|
||||||
component={({ input }) => input.value}
|
component={({ input = {} }) => input.value}
|
||||||
/>
|
/>
|
||||||
</CollapsedKeyValue>
|
</CollapsedKeyValue>
|
||||||
)}
|
)}
|
||||||
@ -213,11 +204,8 @@ const KeyValue = withTheme(
|
|||||||
</Padding>
|
</Padding>
|
||||||
</CardOutlet>
|
</CardOutlet>
|
||||||
</Card>
|
</Card>
|
||||||
<Divider height={remcalc(13)} transparent />
|
|
||||||
</form>
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|
||||||
KeyValue.propTypes = {
|
KeyValue.propTypes = {
|
||||||
input: PropTypes.oneOf(['input', 'textarea']).isRequired,
|
input: PropTypes.oneOf(['input', 'textarea']).isRequired,
|
||||||
@ -230,4 +218,9 @@ KeyValue.propTypes = {
|
|||||||
onRemove: PropTypes.func
|
onRemove: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default props => <KeyValue {...props} />;
|
export default withTheme(({ handleSubmit, ...rest }) => (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<KeyValue {...rest} />
|
||||||
|
<Divider height={remcalc(13)} transparent />
|
||||||
|
</form>
|
||||||
|
));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Field } from 'redux-form';
|
||||||
import KeyValue from './key-value';
|
import KeyValue from './key-value';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -14,7 +15,7 @@ export const MenuForm = ({ searchable, onAdd }) => (
|
|||||||
<form>
|
<form>
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs={7} sm={5}>
|
<Col xs={7} sm={5}>
|
||||||
<FormGroup name="filter" fluid reduxForm>
|
<FormGroup name="filter" field={Field} fluid>
|
||||||
<FormLabel>Filter</FormLabel>
|
<FormLabel>Filter</FormLabel>
|
||||||
<Input disabled={!searchable} fluid />
|
<Input disabled={!searchable} fluid />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
@ -1,180 +1,75 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
import { Row, Col } from 'react-styled-flexboxgrid';
|
||||||
import { Margin } from 'styled-components-spacing';
|
import { Margin } from 'styled-components-spacing';
|
||||||
import Value from 'react-redux-values';
|
|
||||||
import ReduxForm from 'declarative-redux-form';
|
|
||||||
import { KeyValue } from '@components/instances';
|
import { KeyValue } from '@components/instances';
|
||||||
import { withTheme } from 'styled-components';
|
import { Field } from 'redux-form';
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
H3,
|
|
||||||
H4,
|
|
||||||
Divider,
|
|
||||||
FormGroup,
|
FormGroup,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
Input,
|
Input,
|
||||||
Button,
|
Button,
|
||||||
StatusLoader,
|
|
||||||
CloseIcon,
|
|
||||||
TagItem,
|
TagItem,
|
||||||
TagList,
|
TagList,
|
||||||
TagItemContainer
|
TagItemContainer
|
||||||
} from 'joyent-ui-toolkit';
|
} from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
const FlexEnd = styled(Col)`
|
export const MenuForm = ({ addable = true, searchable, onAdd }) => (
|
||||||
display: flex;
|
<form>
|
||||||
justify-content: flex-end;
|
<Row>
|
||||||
`;
|
<Col xs={7} sm={5}>
|
||||||
|
<FormGroup name="filter" field={Field} fluid>
|
||||||
const CloseIconActionable = styled(CloseIcon)`
|
|
||||||
cursor: pointer;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Tags = ({
|
|
||||||
handleRemove,
|
|
||||||
addKey,
|
|
||||||
handleCreate,
|
|
||||||
handleClear,
|
|
||||||
theme,
|
|
||||||
toggleEdit,
|
|
||||||
removeTag,
|
|
||||||
filterTags,
|
|
||||||
state,
|
|
||||||
edit,
|
|
||||||
tags
|
|
||||||
}) => {
|
|
||||||
const _filterTags = (
|
|
||||||
<Col md={4} xs={12}>
|
|
||||||
<FormGroup fluid>
|
|
||||||
<FormLabel>Filter</FormLabel>
|
<FormLabel>Filter</FormLabel>
|
||||||
<Input fluid type="text" onChange={filterTags} />
|
<Input disabled={!searchable} fluid />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
<Col xs={5} sm={7}>
|
||||||
|
<FormGroup right>
|
||||||
const _addTag = (
|
<FormLabel>⁣</FormLabel>
|
||||||
<Value name={`${addKey}-expanded`}>
|
|
||||||
{({ value: expanded, onValueChange }) =>
|
|
||||||
!expanded ? (
|
|
||||||
<FlexEnd mdOffset={4} md={4} xs={12}>
|
|
||||||
<Button secondary onClick={toggleEdit}>
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => onValueChange(!expanded)}
|
disabled={!searchable || !addable}
|
||||||
disabled={edit}
|
onClick={onAdd}
|
||||||
|
small
|
||||||
|
icon
|
||||||
|
fluid
|
||||||
>
|
>
|
||||||
Add tag
|
Add tag
|
||||||
</Button>
|
</Button>
|
||||||
</FlexEnd>
|
</FormGroup>
|
||||||
) : (
|
|
||||||
[
|
|
||||||
<FlexEnd mdOffset={4} md={4} xs={12}>
|
|
||||||
<Button disabled secondary onClick={toggleEdit}>
|
|
||||||
Edit
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
onClick={() => onValueChange(!expanded)}
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
Add tag
|
|
||||||
</Button>
|
|
||||||
</FlexEnd>,
|
|
||||||
<Col xs={12}>
|
|
||||||
<ReduxForm
|
|
||||||
form={addKey}
|
|
||||||
onSubmit={handleCreate}
|
|
||||||
id={addKey}
|
|
||||||
onClear={() => handleClear(addKey)}
|
|
||||||
onToggleExpanded={() => onValueChange(!expanded)}
|
|
||||||
onRemove={() => handleRemove(addKey)}
|
|
||||||
expanded={expanded}
|
|
||||||
label="tag"
|
|
||||||
create
|
|
||||||
>
|
|
||||||
{KeyValue}
|
|
||||||
</ReduxForm>
|
|
||||||
</Col>
|
</Col>
|
||||||
]
|
</Row>
|
||||||
)
|
</form>
|
||||||
}
|
);
|
||||||
</Value>
|
|
||||||
);
|
|
||||||
|
|
||||||
const _title = (
|
export const AddForm = props => (
|
||||||
<Margin bottom={3} key="tag-title">
|
<KeyValue {...props} method="add" input="input" type="tag" expanded />
|
||||||
<H3>
|
);
|
||||||
{tags.length} {tags.length === 1 ? 'Tag' : 'Tags'}
|
|
||||||
</H3>
|
|
||||||
</Margin>
|
|
||||||
);
|
|
||||||
|
|
||||||
const _noTags =
|
export const EditForm = props => (
|
||||||
!tags ||
|
<KeyValue {...props} method="edit" input="input" type="tag" expanded />
|
||||||
(tags.length === 0 && <H4 key="no-tags">No tags have been added yet</H4>);
|
);
|
||||||
|
|
||||||
const _list = tags.length > 0 && (
|
const Tag = ({ name, value, onClick }) => (
|
||||||
<TagList key="tag-list">
|
<Margin right={1} bottom={1} key={`${name}-${value}`}>
|
||||||
{tags
|
<TagItem onClick={onClick}>
|
||||||
.sort(
|
|
||||||
(a, b) =>
|
|
||||||
a.initialValues.name.toLowerCase() <
|
|
||||||
b.initialValues.name.toLowerCase()
|
|
||||||
? -1
|
|
||||||
: 1
|
|
||||||
)
|
|
||||||
.map(tag => (
|
|
||||||
<Margin
|
|
||||||
right={1}
|
|
||||||
bottom={1}
|
|
||||||
key={`${tag.initialValues.name}-${tag.initialValues.value}`}
|
|
||||||
>
|
|
||||||
<TagItem>
|
|
||||||
{state[
|
|
||||||
`${tag.initialValues.name}-${tag.initialValues.value}-deleting`
|
|
||||||
] ? (
|
|
||||||
<StatusLoader small />
|
|
||||||
) : (
|
|
||||||
<TagItemContainer>
|
<TagItemContainer>
|
||||||
{tag.initialValues.name}: {tag.initialValues.value}
|
{name}: {value}
|
||||||
{edit && (
|
|
||||||
<Margin left={2}>
|
|
||||||
<CloseIconActionable
|
|
||||||
onClick={() =>
|
|
||||||
removeTag(
|
|
||||||
tag.initialValues.name,
|
|
||||||
tag.initialValues.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
fill={theme.grey}
|
|
||||||
height={remcalc(9)}
|
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
)}
|
|
||||||
</TagItemContainer>
|
</TagItemContainer>
|
||||||
)}
|
|
||||||
</TagItem>
|
</TagItem>
|
||||||
</Margin>
|
</Margin>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default ({ values, onToggleEditing, ...rest }) => (
|
||||||
|
<TagList {...rest}>
|
||||||
|
{values.map(({ id, name, ...tag }) => (
|
||||||
|
<Tag
|
||||||
|
key={id}
|
||||||
|
id={id}
|
||||||
|
name={name}
|
||||||
|
{...tag}
|
||||||
|
onClick={onToggleEditing && (() => onToggleEditing(name))}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</TagList>
|
</TagList>
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
|
||||||
<Row bottom="md" key="tag-row">
|
|
||||||
{_filterTags}
|
|
||||||
{_addTag}
|
|
||||||
</Row>,
|
|
||||||
<Margin key="tag-divider" bottom={4} top={2}>
|
|
||||||
<Divider height="1px" />
|
|
||||||
</Margin>,
|
|
||||||
_title,
|
|
||||||
_list,
|
|
||||||
_noTags
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withTheme(Tags);
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import paramCase from 'param-case';
|
import paramCase from 'param-case';
|
||||||
import Value, { set } from 'react-redux-values';
|
import { Margin } from 'styled-components-spacing';
|
||||||
|
import { set } from 'react-redux-values';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { SubmissionError, reset, startSubmit, stopSubmit } from 'redux-form';
|
import { SubmissionError, reset, startSubmit, stopSubmit } from 'redux-form';
|
||||||
@ -12,12 +13,10 @@ import remcalc from 'remcalc';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ViewContainer,
|
ViewContainer,
|
||||||
Title,
|
|
||||||
StatusLoader,
|
StatusLoader,
|
||||||
Message,
|
Message,
|
||||||
MessageDescription,
|
MessageDescription,
|
||||||
MessageTitle,
|
MessageTitle,
|
||||||
Button,
|
|
||||||
Divider,
|
Divider,
|
||||||
H3
|
H3
|
||||||
} from 'joyent-ui-toolkit';
|
} from 'joyent-ui-toolkit';
|
||||||
@ -25,7 +24,6 @@ import {
|
|||||||
import GetMetadata from '@graphql/list-metadata.gql';
|
import GetMetadata from '@graphql/list-metadata.gql';
|
||||||
import UpdateMetadata from '@graphql/update-metadata.gql';
|
import UpdateMetadata from '@graphql/update-metadata.gql';
|
||||||
import DeleteMetadata from '@graphql/delete-metadata.gql';
|
import DeleteMetadata from '@graphql/delete-metadata.gql';
|
||||||
import { KeyValue } from '@components/instances';
|
|
||||||
import parseError from '@state/parse-error';
|
import parseError from '@state/parse-error';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -71,9 +69,9 @@ const Metadata = ({
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
const _count = !_loading ? (
|
const _count = !_loading ? (
|
||||||
<H3 marginBottom={remcalc(24)} marginTop={addOpen && remcalc(24)}>
|
<Margin bottom={4} top={addOpen && 4}>
|
||||||
{metadata.length} key:value pair
|
<H3>{metadata.length} key:value pair</H3>
|
||||||
</H3>
|
</Margin>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
const _metadata =
|
const _metadata =
|
||||||
|
@ -1,126 +1,110 @@
|
|||||||
import React, { Component } from 'react';
|
import React from 'react';
|
||||||
|
import { Margin } from 'styled-components-spacing';
|
||||||
import paramCase from 'param-case';
|
import paramCase from 'param-case';
|
||||||
import { compose, graphql } from 'react-apollo';
|
import { compose, graphql } from 'react-apollo';
|
||||||
import { set } from 'react-redux-values';
|
import { set } from 'react-redux-values';
|
||||||
import { SubmissionError, reset, stopSubmit } from 'redux-form';
|
import { SubmissionError, reset, stopSubmit, startSubmit } from 'redux-form';
|
||||||
|
import ReduxForm from 'declarative-redux-form';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import find from 'lodash.find';
|
import find from 'lodash.find';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
|
import intercept from 'apr-intercept';
|
||||||
|
import remcalc from 'remcalc';
|
||||||
|
|
||||||
|
import { ViewContainer, StatusLoader, Divider, H3 } from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ViewContainer,
|
default as TagList,
|
||||||
StatusLoader,
|
MenuForm as TagsMenuForm,
|
||||||
Message,
|
AddForm as TagsAddForm,
|
||||||
MessageDescription,
|
EditForm as TagsEditForm
|
||||||
MessageTitle
|
} from '@components/instances/tags';
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import TagsComponent from '@components/instances/tags';
|
|
||||||
|
|
||||||
import GetTags from '@graphql/list-tags.gql';
|
import GetTags from '@graphql/list-tags.gql';
|
||||||
import UpdateTags from '@graphql/update-tags.gql';
|
import UpdateTags from '@graphql/update-tags.gql';
|
||||||
import DeleteTag from '@graphql/delete-tag.gql';
|
import DeleteTag from '@graphql/delete-tag.gql';
|
||||||
|
import Index from '@state/gen-index';
|
||||||
|
import parseError from '@state/parse-error';
|
||||||
|
|
||||||
const TAG_FORM_KEY = (name, field) => `instance-tag-${name}-${field}`;
|
const MENU_FORM_NAME = 'instance-tags-list-menu';
|
||||||
const CREATE_TAG_FORM_KEY = name => `instance-create-tag-${name}`;
|
const ADD_FORM_NAME = 'instance-tags-add-new';
|
||||||
|
const EDIT_FORM_KEY = field => `instance-tags-${paramCase(field)}`;
|
||||||
|
|
||||||
class Tags extends Component {
|
const Tags = ({
|
||||||
constructor(props) {
|
tags = [],
|
||||||
super(props);
|
addOpen,
|
||||||
const { values: tags } = props;
|
editing,
|
||||||
this.state = {
|
|
||||||
tags,
|
|
||||||
edit: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps = ({ values: tags }) => {
|
|
||||||
this.setState({
|
|
||||||
tags
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
filterTags = e => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const { values: tags } = this.props;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
tags: tags.filter(
|
|
||||||
tag =>
|
|
||||||
tag.initialValues.value.includes(value) ||
|
|
||||||
tag.initialValues.name.includes(value)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
removeTag = (name, value) => {
|
|
||||||
const { handleRemove } = this.props;
|
|
||||||
|
|
||||||
handleRemove(name);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
[`${name}-${value}-deleting`]: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleEdit = () => {
|
|
||||||
const { edit } = this.state;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
edit: !edit
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render = () => {
|
|
||||||
const {
|
|
||||||
instance,
|
|
||||||
values = [],
|
|
||||||
loading,
|
loading,
|
||||||
error,
|
handleToggleAddOpen,
|
||||||
|
handleToggleEditing,
|
||||||
|
handleCancel,
|
||||||
|
handleEdit,
|
||||||
handleRemove,
|
handleRemove,
|
||||||
handleClear,
|
|
||||||
handleCreate
|
handleCreate
|
||||||
} = this.props;
|
}) => {
|
||||||
const _loading = !(loading && !values.length) ? null : <StatusLoader />;
|
const _loading = !(loading && !tags.length) ? null : <StatusLoader />;
|
||||||
const _addKey = instance && CREATE_TAG_FORM_KEY(instance.name);
|
|
||||||
const { edit, tags } = this.state;
|
|
||||||
|
|
||||||
// tags items forms
|
const _add = addOpen ? (
|
||||||
const _tags = !_loading && (
|
<ReduxForm
|
||||||
<TagsComponent
|
form={ADD_FORM_NAME}
|
||||||
toggleEdit={this.toggleEdit}
|
onSubmit={handleCreate}
|
||||||
removeTag={this.removeTag}
|
onCancel={() => handleToggleAddOpen(false)}
|
||||||
filterTags={this.filterTags}
|
>
|
||||||
state={this.state}
|
{TagsAddForm}
|
||||||
edit={edit}
|
</ReduxForm>
|
||||||
handleCreate={handleCreate}
|
) : null;
|
||||||
handleClear={handleClear}
|
|
||||||
addKey={_addKey}
|
|
||||||
tags={tags}
|
|
||||||
handleRemove={handleRemove}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
// fetching error
|
const _line = !_loading
|
||||||
const _error =
|
? [
|
||||||
error && !values.length && !_loading ? (
|
<Divider key="line" height={remcalc(1)} />,
|
||||||
<Message error>
|
<Divider key="after-line-space" height={remcalc(24)} transparent />
|
||||||
<MessageTitle>Ooops!</MessageTitle>
|
]
|
||||||
<MessageDescription>
|
: null;
|
||||||
An error occurred while loading your instance tags
|
|
||||||
</MessageDescription>
|
const _count = !_loading ? (
|
||||||
</Message>
|
<Margin bottom={4} top={addOpen && 4}>
|
||||||
|
<H3>{tags.length} tags</H3>
|
||||||
|
</Margin>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
const _tags = !_loading ? (
|
||||||
|
<TagList values={tags} onToggleEditing={!editing && handleToggleEditing} />
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
const _edit = editing ? (
|
||||||
|
<ReduxForm
|
||||||
|
form={editing.form}
|
||||||
|
initialValues={{ name: editing.name, value: editing.value }}
|
||||||
|
onSubmit={handleEdit}
|
||||||
|
onCancel={() => handleToggleEditing(false)}
|
||||||
|
onToggleExpanded={() => handleToggleEditing(false)}
|
||||||
|
onRemove={() => handleRemove(editing.form, editing)}
|
||||||
|
removing={editing.removing}
|
||||||
|
>
|
||||||
|
{TagsEditForm}
|
||||||
|
</ReduxForm>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ViewContainer center={Boolean(_loading)} main>
|
<ViewContainer main>
|
||||||
|
<ReduxForm
|
||||||
|
form={MENU_FORM_NAME}
|
||||||
|
searchable={!_loading}
|
||||||
|
addable={!editing}
|
||||||
|
onAdd={() => handleToggleAddOpen(!addOpen)}
|
||||||
|
>
|
||||||
|
{TagsMenuForm}
|
||||||
|
</ReduxForm>
|
||||||
|
<Divider height={remcalc(11)} transparent />
|
||||||
|
{_line}
|
||||||
{_loading}
|
{_loading}
|
||||||
{_error}
|
{_add}
|
||||||
|
{_edit}
|
||||||
|
{_count}
|
||||||
{_tags}
|
{_tags}
|
||||||
</ViewContainer>
|
</ViewContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
graphql(UpdateTags, { name: 'updateTags' }),
|
graphql(UpdateTags, { name: 'updateTags' }),
|
||||||
@ -138,84 +122,152 @@ export default compose(
|
|||||||
const instance = find(get(rest, 'machines', []), ['name', name]);
|
const instance = find(get(rest, 'machines', []), ['name', name]);
|
||||||
const tags = get(instance, 'tags', []);
|
const tags = get(instance, 'tags', []);
|
||||||
|
|
||||||
const values = tags.map(({ name, value }) => {
|
|
||||||
const field = paramCase(name);
|
|
||||||
const form = TAG_FORM_KEY(name, field);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
form,
|
tags,
|
||||||
initialValues: {
|
|
||||||
name,
|
|
||||||
value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
values,
|
|
||||||
instance,
|
instance,
|
||||||
|
index: Index(tags),
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
refetch
|
refetch
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
connect(null, (dispatch, ownProps) => {
|
connect(
|
||||||
const { instance, refetch, updateTags, deleteTag } = ownProps;
|
({ values, form }, { tags, index, ...ownProps }) => {
|
||||||
|
// get search value
|
||||||
|
const filter = get(form, `${MENU_FORM_NAME}.values.filter`, false);
|
||||||
|
// if user is searching something, get items that match that query
|
||||||
|
const filtered = filter
|
||||||
|
? index.search(filter).map(({ ref }) => find(tags, ['id', ref]))
|
||||||
|
: tags;
|
||||||
|
|
||||||
|
const editingTagName = get(values, 'editing-tag', null);
|
||||||
|
const removingTagName = get(values, 'removing-tag', null);
|
||||||
|
const editingTag =
|
||||||
|
editingTagName && find(filtered, ['name', editingTagName]);
|
||||||
|
const removingTag = editingTagName === removingTagName;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// reset sets values to initialValues
|
...ownProps,
|
||||||
handleClear: form => dispatch(reset(form)),
|
tags: filtered,
|
||||||
handleRemove: name =>
|
addOpen: get(values, 'add-tags-open', false),
|
||||||
Promise.resolve(
|
editing: editingTag && {
|
||||||
// set removing=true (so that we can have a specific removing spinner)
|
...editingTag,
|
||||||
// because remove button is not a submit button, we have to manually flip that flag
|
removing: Boolean(removingTag),
|
||||||
dispatch([set({ name: `${name}-removing`, value: true })])
|
form: EDIT_FORM_KEY(editingTag.name)
|
||||||
)
|
}
|
||||||
.then(() =>
|
};
|
||||||
// call mutation
|
},
|
||||||
|
(dispatch, ownProps) => {
|
||||||
|
return {
|
||||||
|
handleToggleAddOpen: value =>
|
||||||
|
dispatch(set({ name: `add-tags-open`, value })),
|
||||||
|
handleToggleEditing: value =>
|
||||||
|
dispatch(set({ name: `editing-tag`, value })),
|
||||||
|
handleEdit: async ({ name, value }, _, { form, initialValues }) => {
|
||||||
|
const { tags, instance, deleteTag, updateTags, refetch } = ownProps;
|
||||||
|
|
||||||
|
// call mutations
|
||||||
|
const [err] = await intercept(
|
||||||
|
Promise.all([
|
||||||
deleteTag({
|
deleteTag({
|
||||||
variables: {
|
variables: {
|
||||||
id: instance.id,
|
id: instance.id,
|
||||||
name
|
name: initialValues.name
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
)
|
|
||||||
// fetch tags again
|
|
||||||
.then(() => refetch())
|
|
||||||
// we only flip removing and submitting when there is an error.
|
|
||||||
// the reason for that is that tags is updated asyncronously and
|
|
||||||
// it takes longer to have an efect than the mutation
|
|
||||||
.catch(error =>
|
|
||||||
dispatch([
|
|
||||||
set({ name: `${name}-removing`, value: false }),
|
|
||||||
stopSubmit(name, {
|
|
||||||
_error: error.graphQLErrors
|
|
||||||
.map(({ message }) => message)
|
|
||||||
.join('\n')
|
|
||||||
})
|
|
||||||
])
|
|
||||||
),
|
|
||||||
handleCreate: ({ name, value }) =>
|
|
||||||
// call mutation
|
|
||||||
updateTags({
|
updateTags({
|
||||||
variables: {
|
variables: {
|
||||||
id: instance.id,
|
id: instance.id,
|
||||||
tags: [{ name, value }]
|
tags: [{ name, value }]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// fetch tags again
|
])
|
||||||
.then(() => refetch())
|
);
|
||||||
// reset create new tags form
|
|
||||||
.then(() => dispatch(reset(CREATE_TAG_FORM_KEY(instance.name))))
|
if (err) {
|
||||||
// submit is flipped once the promise is resolved
|
// show mutation error
|
||||||
.catch(error => {
|
|
||||||
throw new SubmissionError({
|
throw new SubmissionError({
|
||||||
_error: error.graphQLErrors
|
_error: parseError(err)
|
||||||
.map(({ message }) => message)
|
|
||||||
.join('\n')
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch([
|
||||||
|
set({ name: `editing-tag`, value: false }),
|
||||||
|
reset(form),
|
||||||
|
startSubmit(form)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// fetch tags again (even though we are polling)
|
||||||
|
return refetch();
|
||||||
|
},
|
||||||
|
handleRemove: async (form, { name }) => {
|
||||||
|
const { instance, deleteTag, refetch } = ownProps;
|
||||||
|
|
||||||
|
dispatch([
|
||||||
|
set({ name: `removing-tag`, value: name }),
|
||||||
|
startSubmit(form)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// call mutation
|
||||||
|
const [err] = await intercept(
|
||||||
|
deleteTag({
|
||||||
|
variables: {
|
||||||
|
id: instance.id,
|
||||||
|
name
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
// show mutation error
|
||||||
|
throw new SubmissionError({
|
||||||
|
_error: parseError(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch([
|
||||||
|
set({ name: `editing-tag`, value: false }),
|
||||||
|
set({ name: `removing-tag`, value: false }),
|
||||||
|
reset(form),
|
||||||
|
startSubmit(form)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// fetch tags again (even though we are polling)
|
||||||
|
return refetch();
|
||||||
|
},
|
||||||
|
handleCreate: async ({ name, value }) => {
|
||||||
|
const { updateTags, instance, refetch } = ownProps;
|
||||||
|
|
||||||
|
// call mutation
|
||||||
|
const [err] = await intercept(
|
||||||
|
updateTags({
|
||||||
|
variables: {
|
||||||
|
id: instance.id,
|
||||||
|
tags: [{ name, value }]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
// show mutation error
|
||||||
|
throw new SubmissionError({
|
||||||
|
_error: parseError(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch([
|
||||||
|
// reset create new tags form
|
||||||
|
reset(ADD_FORM_NAME),
|
||||||
|
stopSubmit(ADD_FORM_NAME),
|
||||||
|
// close add form
|
||||||
|
set({ name: `add-tags-open`, value: false })
|
||||||
|
]);
|
||||||
|
|
||||||
|
// fetch tags again (even though we are polling)
|
||||||
|
return refetch();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})
|
}
|
||||||
|
)
|
||||||
)(Tags);
|
)(Tags);
|
||||||
|
4
packages/my-joy-beta/src/mocks/__aliases__.js
Normal file
4
packages/my-joy-beta/src/mocks/__aliases__.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module.exports = {
|
||||||
|
'^joyent-ui-toolkit/dist/es/editor$': '<rootDir>/src/mocks/editor',
|
||||||
|
'^redux-form$': '<rootDir>/src/mocks/redux-form'
|
||||||
|
};
|
1
packages/my-joy-beta/src/mocks/editor.js
Normal file
1
packages/my-joy-beta/src/mocks/editor.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export default () => <span>joyent-maifest-editor</span>
|
3
packages/my-joy-beta/src/mocks/redux-form.js
Normal file
3
packages/my-joy-beta/src/mocks/redux-form.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const Field = ({ component = "input", children, ...rest }) => React.createElement(component, rest, children);
|
@ -11,6 +11,7 @@ class ManifestEditorBundle extends Component {
|
|||||||
|
|
||||||
this.handleRender = this.handleRender.bind(this);
|
this.handleRender = this.handleRender.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRender(ManifestEditor) {
|
handleRender(ManifestEditor) {
|
||||||
if (ManifestEditor) {
|
if (ManifestEditor) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -20,6 +21,7 @@ class ManifestEditorBundle extends Component {
|
|||||||
|
|
||||||
return <Loader />;
|
return <Loader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (!this.state.ManifestEditor) {
|
if (!this.state.ManifestEditor) {
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import remcalc from 'remcalc';
|
import remcalc from 'remcalc';
|
||||||
|
import is from 'styled-is';
|
||||||
|
|
||||||
export default styled.li`
|
export default styled.li`
|
||||||
border: ${remcalc(1)} solid ${props => props.theme.grey};
|
border: ${remcalc(1)} solid ${props => props.theme.grey};
|
||||||
@ -10,4 +11,8 @@ export default styled.li`
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
|
||||||
|
${is('onClick')`
|
||||||
|
cursor: pointer;
|
||||||
|
`};
|
||||||
`;
|
`;
|
||||||
|
43
yarn.lock
43
yarn.lock
@ -2273,9 +2273,9 @@ code-point-at@^1.0.0:
|
|||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||||
|
|
||||||
codemirror@5.32.0, codemirror@^5.18.2, codemirror@^5.32.0:
|
codemirror@^5.18.2, codemirror@^5.32.0:
|
||||||
version "5.32.0"
|
version "5.33.0"
|
||||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.32.0.tgz#cb6ff5d8ef36d0b10f031130e2d9ebeee92c902e"
|
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.33.0.tgz#462ad9a6fe8d38b541a9536a3997e1ef93b40c6a"
|
||||||
|
|
||||||
coleman-liau@^1.0.0:
|
coleman-liau@^1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@ -6566,10 +6566,6 @@ lodash._reinterpolate@~3.0.0:
|
|||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||||
|
|
||||||
lodash.assign@4.2.0:
|
|
||||||
version "4.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
|
|
||||||
|
|
||||||
lodash.camelcase@^4.3.0:
|
lodash.camelcase@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
||||||
@ -6582,7 +6578,7 @@ lodash.debounce@^4.0.8:
|
|||||||
version "4.0.8"
|
version "4.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
|
|
||||||
lodash.defaults@4.2.0, lodash.defaults@^4.2.0:
|
lodash.defaults@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
||||||
|
|
||||||
@ -6654,7 +6650,7 @@ lodash.isundefined@^3.0.1:
|
|||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48"
|
resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48"
|
||||||
|
|
||||||
lodash.keys@4.2.0, lodash.keys@^4.2.0:
|
lodash.keys@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205"
|
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205"
|
||||||
|
|
||||||
@ -6699,10 +6695,18 @@ lodash.uniq@^4.5.0:
|
|||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||||
|
|
||||||
lodash@4.17.2, lodash@4.17.4, "lodash@>=3.5 <5", lodash@^3.10.1, lodash@^3.3.1, lodash@^4.0.0, lodash@^4.1.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1:
|
lodash@4.17.2:
|
||||||
|
version "4.17.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.2.tgz#34a3055babe04ce42467b607d700072c7ff6bf42"
|
||||||
|
|
||||||
|
"lodash@>=3.5 <5", lodash@^4.0.0, lodash@^4.1.0, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.5.1:
|
||||||
version "4.17.4"
|
version "4.17.4"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
|
||||||
|
|
||||||
|
lodash@^3.10.1, lodash@^3.3.1:
|
||||||
|
version "3.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
|
||||||
|
|
||||||
log-symbols@^1.0.2:
|
log-symbols@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
|
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18"
|
||||||
@ -10118,9 +10122,9 @@ styled-components-spacing@^2.1.3:
|
|||||||
react-create-component-from-tag-prop "^1.2.1"
|
react-create-component-from-tag-prop "^1.2.1"
|
||||||
styled-components-breakpoint "^1.0.0-preview.3"
|
styled-components-breakpoint "^1.0.0-preview.3"
|
||||||
|
|
||||||
styled-components@2.2.4:
|
styled-components@2.2.4, styled-components@2.3.0, styled-components@^2.2.3, styled-components@^2.3.0:
|
||||||
version "2.2.4"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.2.4.tgz#dd87fd3dafd359e7a0d570aec1bd07d691c0b5a2"
|
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.3.0.tgz#d9cf4574e140fea6426e48632ed0ca4494537718"
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer "^5.0.3"
|
buffer "^5.0.3"
|
||||||
css-to-react-native "^2.0.3"
|
css-to-react-native "^2.0.3"
|
||||||
@ -10132,19 +10136,6 @@ styled-components@2.2.4:
|
|||||||
stylis "^3.4.0"
|
stylis "^3.4.0"
|
||||||
supports-color "^3.2.3"
|
supports-color "^3.2.3"
|
||||||
|
|
||||||
styled-components@^2.2.3, styled-components@^2.3.0:
|
|
||||||
version "2.3.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.3.3.tgz#351d0be84699db750c73d95617e4334157421f71"
|
|
||||||
dependencies:
|
|
||||||
buffer "^5.0.3"
|
|
||||||
css-to-react-native "^2.0.3"
|
|
||||||
fbjs "^0.8.9"
|
|
||||||
hoist-non-react-statics "^1.2.0"
|
|
||||||
is-plain-object "^2.0.1"
|
|
||||||
prop-types "^15.5.4"
|
|
||||||
stylis "^3.4.0"
|
|
||||||
supports-color "^3.2.3"
|
|
||||||
|
|
||||||
styled-flex-component@^2.1.0:
|
styled-flex-component@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/styled-flex-component/-/styled-flex-component-2.1.0.tgz#b1efab209965288a9e1d6dbe981692693568cca2"
|
resolved "https://registry.yarnpkg.com/styled-flex-component/-/styled-flex-component-2.1.0.tgz#b1efab209965288a9e1d6dbe981692693568cca2"
|
||||||
|
Loading…
Reference in New Issue
Block a user