parent
396af2d2e6
commit
52d651a598
@ -29,6 +29,7 @@
|
|||||||
"lodash.find": "^4.6.0",
|
"lodash.find": "^4.6.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.includes": "^4.3.0",
|
"lodash.includes": "^4.3.0",
|
||||||
|
"lodash.isarray": "^4.0.0",
|
||||||
"lodash.isfinite": "^3.3.2",
|
"lodash.isfinite": "^3.3.2",
|
||||||
"lodash.isfunction": "^3.0.8",
|
"lodash.isfunction": "^3.0.8",
|
||||||
"lodash.isstring": "^4.0.1",
|
"lodash.isstring": "^4.0.1",
|
||||||
|
209
packages/my-joy-beta/src/components/cns.js
Normal file
209
packages/my-joy-beta/src/components/cns.js
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import React, { Fragment } from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import remcalc from 'remcalc';
|
||||||
|
import { Margin, Padding } from 'styled-components-spacing';
|
||||||
|
import Flex, { FlexItem } from 'styled-flex-component';
|
||||||
|
import { Field } from 'redux-form';
|
||||||
|
|
||||||
|
import {
|
||||||
|
P,
|
||||||
|
H3,
|
||||||
|
Card,
|
||||||
|
Divider,
|
||||||
|
TagList,
|
||||||
|
Input,
|
||||||
|
Toggle,
|
||||||
|
Small,
|
||||||
|
Button,
|
||||||
|
FormGroup,
|
||||||
|
FormLabel,
|
||||||
|
PublicIcon,
|
||||||
|
PrivateIcon
|
||||||
|
} from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
|
import Tag from '@components/tags';
|
||||||
|
|
||||||
|
const SmallBordered = styled(Small)`
|
||||||
|
padding-right: ${remcalc(12)};
|
||||||
|
margin-right: ${remcalc(12)};
|
||||||
|
border-right: ${remcalc(1)} solid ${props => props.theme.grey};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Header = () => (
|
||||||
|
<Fragment>
|
||||||
|
<H3>Hostnames</H3>
|
||||||
|
<Padding bottom={2}>
|
||||||
|
<P>
|
||||||
|
Default hostnames are automatically generated from both the instance
|
||||||
|
name and any attached networks.
|
||||||
|
</P>
|
||||||
|
</Padding>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Footer = ({ enabled, submitting, onToggle }) => (
|
||||||
|
<Fragment>
|
||||||
|
<Margin bottom={4} top={4}>
|
||||||
|
<FormGroup name="cns-enabled">
|
||||||
|
<Flex alignCenter>
|
||||||
|
<FormLabel>Disabled CNS</FormLabel>
|
||||||
|
<Toggle checked={enabled} onChange={onToggle} disabled={submitting}>
|
||||||
|
Enabled CNS
|
||||||
|
</Toggle>
|
||||||
|
</Flex>
|
||||||
|
</FormGroup>
|
||||||
|
</Margin>
|
||||||
|
{enabled ? (
|
||||||
|
<Margin bottom={4}>
|
||||||
|
<P>*All hostnames listed here will be confirmed after deployment.</P>
|
||||||
|
</Margin>
|
||||||
|
) : null}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const HostnamesHeader = () => (
|
||||||
|
<Margin top={4}>
|
||||||
|
<H3>CNS service hostnames</H3>
|
||||||
|
<Padding bottom={3}>
|
||||||
|
<P>
|
||||||
|
CNS service hostnames are created by attaching a CNS service name to one
|
||||||
|
or more instances. You can serve multiple instances under the same
|
||||||
|
hostname by assigning them to a matching CNS service name.
|
||||||
|
</P>
|
||||||
|
</Padding>
|
||||||
|
</Margin>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const AddServiceForm = ({
|
||||||
|
handleSubmit,
|
||||||
|
submitting,
|
||||||
|
disabled,
|
||||||
|
pristine
|
||||||
|
}) => (
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<Flex alignEnd>
|
||||||
|
<FormGroup name="name" field={Field}>
|
||||||
|
<FormLabel>Attach to new CNS service name</FormLabel>
|
||||||
|
<Input
|
||||||
|
onBlur={null}
|
||||||
|
type="text"
|
||||||
|
placeholder="Example: mySQLdb"
|
||||||
|
disabled={disabled || submitting}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<Margin left={2}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={disabled || pristine}
|
||||||
|
loading={submitting}
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</Margin>
|
||||||
|
</Flex>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Hostname = ({ values = [], network, service, ...hostname }) => (
|
||||||
|
<Fragment>
|
||||||
|
{values.length ? (
|
||||||
|
<Margin bottom={4}>
|
||||||
|
<Flex>
|
||||||
|
<SmallBordered bold noMargin>
|
||||||
|
{network && service
|
||||||
|
? 'Network CNS service'
|
||||||
|
: network
|
||||||
|
? 'Network'
|
||||||
|
: service ? 'CNS service' : 'Instance name'}{' '}
|
||||||
|
hostname{values.length === 1 ? '' : 's'}
|
||||||
|
</SmallBordered>
|
||||||
|
<FlexItem>
|
||||||
|
<Margin right={1}>
|
||||||
|
{hostname.public ? <PublicIcon /> : <PrivateIcon />}
|
||||||
|
</Margin>
|
||||||
|
</FlexItem>
|
||||||
|
<FlexItem>
|
||||||
|
<Small noMargin>{hostname.public ? 'Public' : 'Private'}</Small>
|
||||||
|
</FlexItem>
|
||||||
|
</Flex>
|
||||||
|
{values.map(value => (
|
||||||
|
<Input onBlur={null} disabled monospace fluid value={value} />
|
||||||
|
))}
|
||||||
|
</Margin>
|
||||||
|
) : null}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
const DefaultHostnames = ({ hostnames }) => (
|
||||||
|
<Fragment>
|
||||||
|
<Header />
|
||||||
|
<Flex column>
|
||||||
|
{hostnames.map(({ value, ...hostname }) => (
|
||||||
|
<Hostname key={value} value={value} {...hostname} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CnsHostnames = ({
|
||||||
|
hostnames = [],
|
||||||
|
services = [],
|
||||||
|
onRemoveService = () => null,
|
||||||
|
children = null
|
||||||
|
}) => (
|
||||||
|
<Fragment>
|
||||||
|
<HostnamesHeader />
|
||||||
|
{services.length ? (
|
||||||
|
<Margin bottom={3}>
|
||||||
|
<FormLabel>Existing CNS service name(s)</FormLabel>
|
||||||
|
<Margin top={1}>
|
||||||
|
<TagList>
|
||||||
|
{services.map(value => (
|
||||||
|
<Tag
|
||||||
|
active
|
||||||
|
key={value}
|
||||||
|
value={value}
|
||||||
|
onRemoveClick={
|
||||||
|
onRemoveService && (() => onRemoveService(value))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</TagList>
|
||||||
|
</Margin>
|
||||||
|
</Margin>
|
||||||
|
) : null}
|
||||||
|
{children}
|
||||||
|
<Margin top={4}>
|
||||||
|
<Flex column>
|
||||||
|
{hostnames.map(({ value, ...hostname }) => (
|
||||||
|
<Hostname key={value} value={value} {...hostname} />
|
||||||
|
))}
|
||||||
|
</Flex>
|
||||||
|
</Margin>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
hostnames = [],
|
||||||
|
services = [],
|
||||||
|
onRemoveService,
|
||||||
|
children = null
|
||||||
|
}) => (
|
||||||
|
<Card>
|
||||||
|
<Padding all={4} bottom={0}>
|
||||||
|
<DefaultHostnames
|
||||||
|
hostnames={hostnames.filter(({ service }) => !service)}
|
||||||
|
/>
|
||||||
|
<Divider height={remcalc(1)} />
|
||||||
|
<Margin top={4}>
|
||||||
|
<CnsHostnames
|
||||||
|
services={services}
|
||||||
|
hostnames={hostnames.filter(({ service }) => service)}
|
||||||
|
onRemoveService={onRemoveService}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</CnsHostnames>
|
||||||
|
</Margin>
|
||||||
|
</Padding>
|
||||||
|
</Card>
|
||||||
|
);
|
@ -1,95 +0,0 @@
|
|||||||
import React, { Fragment } from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
import { Margin, Padding } from 'styled-components-spacing';
|
|
||||||
import Flex, { FlexItem } from 'styled-flex-component';
|
|
||||||
import { Field } from 'redux-form';
|
|
||||||
|
|
||||||
import {
|
|
||||||
P,
|
|
||||||
H3,
|
|
||||||
Input,
|
|
||||||
Small,
|
|
||||||
Button,
|
|
||||||
FormGroup,
|
|
||||||
FormLabel,
|
|
||||||
PublicIcon,
|
|
||||||
PrivateIcon
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const SmallBordered = styled(Small)`
|
|
||||||
padding-right: ${remcalc(12)};
|
|
||||||
margin-right: ${remcalc(12)};
|
|
||||||
border-right: ${remcalc(1)} solid ${props => props.theme.grey};
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const Header = () => (
|
|
||||||
<Fragment>
|
|
||||||
<H3>Hostnames</H3>
|
|
||||||
<Padding bottom={2}>
|
|
||||||
<P>
|
|
||||||
Default hostnames are automatically generated from both the instance
|
|
||||||
name and any attached networks.
|
|
||||||
</P>
|
|
||||||
</Padding>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const HostnamesHeader = () => (
|
|
||||||
<Margin top={4}>
|
|
||||||
<H3>CNS service hostnames</H3>
|
|
||||||
<Padding bottom={3}>
|
|
||||||
<P>
|
|
||||||
CNS service hostnames are created by attaching a CNS service name to one
|
|
||||||
or more instances. You can serve multiple instances under the same
|
|
||||||
hostname by assigning them to a matching CNS service name.
|
|
||||||
</P>
|
|
||||||
</Padding>
|
|
||||||
</Margin>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const AddServiceForm = ({ handleSubmit, pristine }) => (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<Flex alignEnd>
|
|
||||||
<FormGroup name="name" field={Field}>
|
|
||||||
<FormLabel>Attach to new CNS service name</FormLabel>
|
|
||||||
<Input onBlur={null} type="text" placeholder="Example: mySQLdb" />
|
|
||||||
</FormGroup>
|
|
||||||
<Margin left={2}>
|
|
||||||
<Button type="submit" disabled={pristine}>
|
|
||||||
Add
|
|
||||||
</Button>
|
|
||||||
</Margin>
|
|
||||||
</Flex>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Hostname = ({ values = [], network, service, ...hostname }) => (
|
|
||||||
<Fragment>
|
|
||||||
{values.length ? (
|
|
||||||
<Margin bottom={4}>
|
|
||||||
<Flex>
|
|
||||||
<SmallBordered bold noMargin>
|
|
||||||
{network && service
|
|
||||||
? 'Network CNS service'
|
|
||||||
: network
|
|
||||||
? 'Network'
|
|
||||||
: service ? 'CNS service' : 'Instance name'}{' '}
|
|
||||||
hostname{values.length === 1 ? '' : 's'}
|
|
||||||
</SmallBordered>
|
|
||||||
<FlexItem>
|
|
||||||
<Margin right={1}>
|
|
||||||
{hostname.public ? <PublicIcon /> : <PrivateIcon />}
|
|
||||||
</Margin>
|
|
||||||
</FlexItem>
|
|
||||||
<FlexItem>
|
|
||||||
<Small noMargin>{hostname.public ? 'Public' : 'Private'}</Small>
|
|
||||||
</FlexItem>
|
|
||||||
</Flex>
|
|
||||||
{values.map(value => (
|
|
||||||
<Input onBlur={null} disabled monospace fluid value={value} />
|
|
||||||
))}
|
|
||||||
</Margin>
|
|
||||||
) : null}
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
@ -163,13 +163,13 @@ export const KeyValue = ({
|
|||||||
{initialValues.name ? (
|
{initialValues.name ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{expanded ? (
|
{expanded ? (
|
||||||
<span>{`${initialValues.name}${type === 'metadata'
|
<span>{`${initialValues.name}${
|
||||||
? '-'
|
type === 'metadata' ? '-' : ':'
|
||||||
: ':'}`}</span>
|
}`}</span>
|
||||||
) : (
|
) : (
|
||||||
<b>{`${initialValues.name}${type === 'metadata'
|
<b>{`${initialValues.name}${
|
||||||
? '-'
|
type === 'metadata' ? '-' : ':'
|
||||||
: ':'}`}</b>
|
}`}</b>
|
||||||
)}
|
)}
|
||||||
<span>{initialValues.value}</span>
|
<span>{initialValues.value}</span>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -398,6 +398,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
@ -1930,6 +1931,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
@ -4756,6 +4758,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
|
@ -547,6 +547,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/network/sdn"
|
href="https://docs.joyent.com/public-cloud/network/sdn"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
@ -963,334 +964,7 @@ Array [
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
.c7 {
|
<form />,
|
||||||
color: rgba(73,73,73,1);
|
|
||||||
line-height: 1.5rem;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c7 + p,
|
|
||||||
.c7 + small,
|
|
||||||
.c7 + h1,
|
|
||||||
.c7 + h2,
|
|
||||||
.c7 + label,
|
|
||||||
.c7 + h3,
|
|
||||||
.c7 + h4,
|
|
||||||
.c7 + h5,
|
|
||||||
.c7 + div,
|
|
||||||
.c7 + span {
|
|
||||||
padding-bottom: 2.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c8 {
|
|
||||||
background-color: rgb(216,216,216);
|
|
||||||
margin: 0;
|
|
||||||
height: 0.0625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 {
|
|
||||||
-webkit-order: 0;
|
|
||||||
-ms-flex-order: 0;
|
|
||||||
order: 0;
|
|
||||||
-webkit-flex-basis: auto;
|
|
||||||
-ms-flex-preferred-size: auto;
|
|
||||||
flex-basis: auto;
|
|
||||||
-webkit-box-flex: 0;
|
|
||||||
-webkit-flex-grow: 0;
|
|
||||||
-ms-flex-positive: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
-webkit-flex-shrink: 1;
|
|
||||||
-ms-flex-negative: 1;
|
|
||||||
flex-shrink: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c12 {
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 1rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
margin-top: 0.5rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c10 {
|
|
||||||
margin-right: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c9 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: nowrap;
|
|
||||||
-ms-flex-wrap: nowrap;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
-webkit-box-pack: start;
|
|
||||||
-webkit-justify-content: flex-start;
|
|
||||||
-ms-flex-pack: start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
-webkit-align-content: stretch;
|
|
||||||
-ms-flex-line-pack: stretch;
|
|
||||||
align-content: stretch;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c4 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: nowrap;
|
|
||||||
-ms-flex-wrap: nowrap;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
-webkit-box-pack: start;
|
|
||||||
-webkit-justify-content: flex-start;
|
|
||||||
-ms-flex-pack: start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
-webkit-align-content: stretch;
|
|
||||||
-ms-flex-line-pack: stretch;
|
|
||||||
align-content: stretch;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c11 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: nowrap;
|
|
||||||
-ms-flex-wrap: nowrap;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
-webkit-box-pack: start;
|
|
||||||
-webkit-justify-content: flex-start;
|
|
||||||
-ms-flex-pack: start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
-webkit-align-content: stretch;
|
|
||||||
-ms-flex-line-pack: stretch;
|
|
||||||
align-content: stretch;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
display: inline-block;
|
|
||||||
background-color: rgb(255,255,255);
|
|
||||||
border: 0.0625rem solid rgb(216,216,216);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
min-width: 18.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 100%;
|
|
||||||
-ms-flex-preferred-size: 100%;
|
|
||||||
flex-basis: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:48em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 66.66666666666667%;
|
|
||||||
-ms-flex-preferred-size: 66.66666666666667%;
|
|
||||||
flex-basis: 66.66666666666667%;
|
|
||||||
max-width: 66.66666666666667%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<div
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c3"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
name2
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c8 c0"
|
|
||||||
height="0.0625rem"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c10"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c11"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c12"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className=""
|
|
||||||
height="16"
|
|
||||||
innerRef={undefined}
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"transform": "rotate(0deg)",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewBox="0 0 12 16"
|
|
||||||
width="12"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M10,6V4A4,4,0,0,0,2,4V6H2A2,2,0,0,0,0,8v6a2,2,0,0,0,2,2h8a2,2,0,0,0,2-2V8A2,2,0,0,0,10,6ZM4,4c0-1.65.35-2,2-2s2,.35,2,2V6H4Zm6,9a1,1,0,0,1-1,1H3a1,1,0,0,1-1-1V9A1,1,0,0,1,3,8H9a1,1,0,0,1,1,1ZM6,13H6a1,1,0,0,1-1-1V10A1,1,0,0,1,6,9H6a1,1,0,0,1,1,1v2A1,1,0,0,1,6,13Z"
|
|
||||||
fill="rgba(73, 73, 73, 1)"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
Private
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className=""
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c11"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c12"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
height="13"
|
|
||||||
viewBox="0 0 9 13"
|
|
||||||
width="9"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M0,0V13H9V0ZM7,11H2V2H7ZM3,4H6V3H3ZM3,6H6V5H3ZM3,8H6V7H3Z"
|
|
||||||
fill="rgba(73, 73, 73, 1)"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
<p
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
Data center network
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>,
|
|
||||||
.c0 {
|
.c0 {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
@ -1535,6 +1209,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/network/sdn"
|
href="https://docs.joyent.com/public-cloud/network/sdn"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
@ -3409,6 +3084,10 @@ Array [
|
|||||||
margin-right: 0.25rem;
|
margin-right: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c10 {
|
||||||
|
margin-right: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.c2 {
|
.c2 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
@ -3422,10 +3101,6 @@ Array [
|
|||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.c10 {
|
|
||||||
margin-right: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c9 {
|
.c9 {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -webkit-flex;
|
display: -webkit-flex;
|
||||||
@ -3446,29 +3121,6 @@ Array [
|
|||||||
align-content: stretch;
|
align-content: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.c4 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: nowrap;
|
|
||||||
-ms-flex-wrap: nowrap;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
-webkit-box-pack: start;
|
|
||||||
-webkit-justify-content: flex-start;
|
|
||||||
-ms-flex-pack: start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
-webkit-align-content: stretch;
|
|
||||||
-ms-flex-line-pack: stretch;
|
|
||||||
align-content: stretch;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c11 {
|
.c11 {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -webkit-flex;
|
display: -webkit-flex;
|
||||||
@ -3493,6 +3145,29 @@ Array [
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c4 {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
-webkit-flex-wrap: nowrap;
|
||||||
|
-ms-flex-wrap: nowrap;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
-webkit-box-pack: start;
|
||||||
|
-webkit-justify-content: flex-start;
|
||||||
|
-ms-flex-pack: start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
-webkit-align-content: stretch;
|
||||||
|
-ms-flex-line-pack: stretch;
|
||||||
|
align-content: stretch;
|
||||||
|
-webkit-flex-direction: column;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.c3 {
|
.c3 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: rgb(255,255,255);
|
background-color: rgb(255,255,255);
|
||||||
|
@ -384,6 +384,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
@ -1889,6 +1890,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
@ -2525,6 +2527,7 @@ Array [
|
|||||||
|
|
||||||
<a
|
<a
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
||||||
|
rel="noopener noreferrer"
|
||||||
target="__blank"
|
target="__blank"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
|
@ -60,6 +60,7 @@ export const Affinity = ({
|
|||||||
<a
|
<a
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://docs.joyent.com/public-cloud/instances/docker/how/start-containers#controlling-container-placement"
|
href="https://docs.joyent.com/public-cloud/instances/docker/how/start-containers#controlling-container-placement"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
</a>
|
</a>
|
||||||
|
@ -4,37 +4,17 @@ import ReduxForm from 'declarative-redux-form';
|
|||||||
import { destroy } from 'redux-form';
|
import { destroy } from 'redux-form';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
import { Margin, Padding } from 'styled-components-spacing';
|
import { Margin } from 'styled-components-spacing';
|
||||||
import Flex from 'styled-flex-component';
|
|
||||||
import { set } from 'react-redux-values';
|
import { set } from 'react-redux-values';
|
||||||
import punycode from 'punycode';
|
import punycode from 'punycode';
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import {
|
import { CnsIcon, H3, Button, FormLabel, TagList } from 'joyent-ui-toolkit';
|
||||||
CnsIcon,
|
|
||||||
P,
|
|
||||||
Card,
|
|
||||||
H3,
|
|
||||||
Button,
|
|
||||||
FormGroup,
|
|
||||||
FormLabel,
|
|
||||||
Toggle,
|
|
||||||
Divider,
|
|
||||||
TagList,
|
|
||||||
StatusLoader
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Hostname,
|
|
||||||
Header,
|
|
||||||
AddServiceForm,
|
|
||||||
HostnamesHeader
|
|
||||||
} from '@components/create-instance/cns';
|
|
||||||
|
|
||||||
|
import Cns, { Footer, AddServiceForm } from '@components/cns';
|
||||||
import Tag from '@components/tags';
|
import Tag from '@components/tags';
|
||||||
import Title from '@components/create-instance/title';
|
import Title from '@components/create-instance/title';
|
||||||
import Description from '@components/description';
|
import Description from '@components/description';
|
||||||
import getAccount from '@graphql/get-account.gql';
|
import GetAccount from '@graphql/get-account.gql';
|
||||||
|
|
||||||
const CNS_FORM = 'create-instance-cns';
|
const CNS_FORM = 'create-instance-cns';
|
||||||
|
|
||||||
@ -50,8 +30,7 @@ const CNSContainer = ({
|
|||||||
handleEdit,
|
handleEdit,
|
||||||
handleToggleCnsEnabled,
|
handleToggleCnsEnabled,
|
||||||
handleAddService,
|
handleAddService,
|
||||||
handleRemoveService,
|
handleRemoveService
|
||||||
loading
|
|
||||||
}) => (
|
}) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Title onClick={!expanded && !proceeded && handleEdit} icon={<CnsIcon />}>
|
<Title onClick={!expanded && !proceeded && handleEdit} icon={<CnsIcon />}>
|
||||||
@ -73,43 +52,11 @@ const CNSContainer = ({
|
|||||||
) : null}
|
) : null}
|
||||||
<div>
|
<div>
|
||||||
{expanded && cnsEnabled ? (
|
{expanded && cnsEnabled ? (
|
||||||
<Card>
|
<Cns
|
||||||
<Padding all={4} bottom={0}>
|
hostnames={hostnames}
|
||||||
<Header />
|
services={serviceNames}
|
||||||
{loading ? (
|
onRemoveService={handleRemoveService}
|
||||||
<Margin all={2}>
|
>
|
||||||
{' '}
|
|
||||||
<StatusLoader />
|
|
||||||
</Margin>
|
|
||||||
) : (
|
|
||||||
<Flex column>
|
|
||||||
{hostnames
|
|
||||||
.filter(({ service }) => !service)
|
|
||||||
.map(({ value, ...hostname }) => (
|
|
||||||
<Hostname key={value} value={value} {...hostname} />
|
|
||||||
))}
|
|
||||||
</Flex>
|
|
||||||
)}
|
|
||||||
<Divider height={remcalc(1)} />
|
|
||||||
<Margin top={4}>
|
|
||||||
<HostnamesHeader />
|
|
||||||
{serviceNames.length ? (
|
|
||||||
<Margin bottom={3}>
|
|
||||||
<FormLabel>Existing CNS service name(s)</FormLabel>
|
|
||||||
<Margin top={1}>
|
|
||||||
<TagList>
|
|
||||||
{serviceNames.map((value, index) => (
|
|
||||||
<Tag
|
|
||||||
active
|
|
||||||
key={index}
|
|
||||||
value={value}
|
|
||||||
onRemoveClick={() => handleRemoveService(index)}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</TagList>
|
|
||||||
</Margin>
|
|
||||||
</Margin>
|
|
||||||
) : null}
|
|
||||||
<ReduxForm
|
<ReduxForm
|
||||||
form={`${CNS_FORM}-new-service`}
|
form={`${CNS_FORM}-new-service`}
|
||||||
destroyOnUnmount={false}
|
destroyOnUnmount={false}
|
||||||
@ -118,36 +65,11 @@ const CNSContainer = ({
|
|||||||
>
|
>
|
||||||
{props => <AddServiceForm {...props} />}
|
{props => <AddServiceForm {...props} />}
|
||||||
</ReduxForm>
|
</ReduxForm>
|
||||||
<Margin top={4}>
|
</Cns>
|
||||||
<Flex column>
|
|
||||||
{hostnames
|
|
||||||
.filter(({ service }) => service)
|
|
||||||
.map(({ value, ...hostname }) => (
|
|
||||||
<Hostname key={value} value={value} {...hostname} />
|
|
||||||
))}
|
|
||||||
</Flex>
|
|
||||||
</Margin>
|
|
||||||
</Margin>
|
|
||||||
</Padding>
|
|
||||||
</Card>
|
|
||||||
) : null}
|
) : null}
|
||||||
{expanded ? (
|
{expanded ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Margin bottom={4} top={4}>
|
<Footer enabled={cnsEnabled} onToggle={handleToggleCnsEnabled} />
|
||||||
<FormGroup name="cns-enabled">
|
|
||||||
<Flex alignCenter>
|
|
||||||
<FormLabel>Disabled CNS</FormLabel>
|
|
||||||
<Toggle checked={cnsEnabled} onChange={handleToggleCnsEnabled}>
|
|
||||||
Enabled CNS
|
|
||||||
</Toggle>
|
|
||||||
</Flex>
|
|
||||||
</FormGroup>
|
|
||||||
</Margin>
|
|
||||||
<Margin bottom={4}>
|
|
||||||
<P>
|
|
||||||
*All hostnames listed here will be confirmed after deployment.
|
|
||||||
</P>
|
|
||||||
</Margin>
|
|
||||||
<Margin bottom={4}>
|
<Margin bottom={4}>
|
||||||
<Button type="button" onClick={handleNext}>
|
<Button type="button" onClick={handleNext}>
|
||||||
Next
|
Next
|
||||||
@ -184,9 +106,8 @@ const CNSContainer = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
graphql(getAccount, {
|
graphql(GetAccount, {
|
||||||
props: ({ data: { loading, account: { id } = [] } }) => ({
|
props: ({ data: { account: { id = '<account-id>' } = [] } }) => ({
|
||||||
loading,
|
|
||||||
id
|
id
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
@ -252,7 +173,7 @@ export default compose(
|
|||||||
handleAddService: ({ name }) => {
|
handleAddService: ({ name }) => {
|
||||||
const serviceName = punycode
|
const serviceName = punycode
|
||||||
.encode(name.toLowerCase().replace(/\s/g, '-'))
|
.encode(name.toLowerCase().replace(/\s/g, '-'))
|
||||||
.replace(/\-$/, '');
|
.replace(/-$/, '');
|
||||||
|
|
||||||
dispatch([
|
dispatch([
|
||||||
destroy(`${CNS_FORM}-new-service`),
|
destroy(`${CNS_FORM}-new-service`),
|
||||||
@ -262,11 +183,12 @@ export default compose(
|
|||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
handleRemoveService: index => {
|
handleRemoveService: value => {
|
||||||
serviceNames.splice(index, 1);
|
|
||||||
|
|
||||||
return dispatch(
|
return dispatch(
|
||||||
set({ name: `${CNS_FORM}-services`, value: serviceNames.slice() })
|
set({
|
||||||
|
name: `${CNS_FORM}-services`,
|
||||||
|
value: serviceNames.filter(name => name !== value)
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
@ -43,6 +43,7 @@ const Firewall = ({
|
|||||||
<a
|
<a
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://docs.joyent.com/public-cloud/network/firewall"
|
href="https://docs.joyent.com/public-cloud/network/firewall"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
</a>
|
</a>
|
||||||
|
@ -45,6 +45,7 @@ export const Metadata = ({
|
|||||||
<a
|
<a
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/metadata"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
</a>
|
</a>
|
||||||
|
@ -44,6 +44,7 @@ export const Networks = ({
|
|||||||
<a
|
<a
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://docs.joyent.com/public-cloud/network/sdn"
|
href="https://docs.joyent.com/public-cloud/network/sdn"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Read more
|
Read more
|
||||||
</a>
|
</a>
|
||||||
@ -65,7 +66,7 @@ export const Networks = ({
|
|||||||
<form>
|
<form>
|
||||||
{networks.map(
|
{networks.map(
|
||||||
({ id, selected, infoExpanded, machinesExpanded, ...network }) =>
|
({ id, selected, infoExpanded, machinesExpanded, ...network }) =>
|
||||||
!expanded && !selected ? null : (
|
expanded || (selected && proceeded) ? (
|
||||||
<Network
|
<Network
|
||||||
key={id}
|
key={id}
|
||||||
id={id}
|
id={id}
|
||||||
@ -79,7 +80,7 @@ export const Networks = ({
|
|||||||
}
|
}
|
||||||
{...network}
|
{...network}
|
||||||
/>
|
/>
|
||||||
)
|
) : null
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -42,6 +42,7 @@ export const Tags = ({
|
|||||||
<a
|
<a
|
||||||
target="__blank"
|
target="__blank"
|
||||||
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
href="https://docs.joyent.com/public-cloud/tags-metadata/tags"
|
||||||
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Read the docs
|
Read the docs
|
||||||
</a>
|
</a>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,205 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
import 'jest-styled-components';
|
||||||
|
|
||||||
|
import { Cns } from '../cns';
|
||||||
|
import Theme from '@mocks/theme';
|
||||||
|
|
||||||
|
// services = [],
|
||||||
|
// hostnames = [],
|
||||||
|
// disabled = false,
|
||||||
|
// loading = false,
|
||||||
|
// mutationError = false,
|
||||||
|
// loadingError = null
|
||||||
|
|
||||||
|
it('renders <Cns /> without throwing', () => {
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns loading /> without throwing', () => {
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns loading />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns loadingError /> without throwing', () => {
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns loadingError />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns mutationError /> without throwing', () => {
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns mutationError="mutation error" />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns mutating /> without throwing', () => {
|
||||||
|
const services = ['serbice', 'dssasda', 'dsasd'];
|
||||||
|
|
||||||
|
const hostnames = [
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff'],
|
||||||
|
public: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
public: true,
|
||||||
|
service: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
service: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns mutating services={services} hostnames={hostnames} />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns disabled /> without throwing', () => {
|
||||||
|
const services = ['serbice', 'dssasda', 'dsasd'];
|
||||||
|
|
||||||
|
const hostnames = [
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff'],
|
||||||
|
public: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
public: true,
|
||||||
|
service: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
service: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns disabled services={services} hostnames={hostnames} />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns services /> without throwing', () => {
|
||||||
|
const services = ['serbice', 'dssasda', 'dsasd'];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns services={services} />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns hostnames /> without throwing', () => {
|
||||||
|
const hostnames = [
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff'],
|
||||||
|
public: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
public: true,
|
||||||
|
service: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
service: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns hostnames={hostnames} />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders <Cns services hostnames /> without throwing', () => {
|
||||||
|
const services = ['serbice', 'dssasda', 'dsasd'];
|
||||||
|
|
||||||
|
const hostnames = [
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff'],
|
||||||
|
public: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['stuffy-stuff']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
public: true,
|
||||||
|
service: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: ['serbice', 'dssasda', 'dsasd'],
|
||||||
|
service: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(
|
||||||
|
renderer
|
||||||
|
.create(
|
||||||
|
<Theme>
|
||||||
|
<Cns disabled services={services} hostnames={hostnames} />
|
||||||
|
</Theme>
|
||||||
|
)
|
||||||
|
.toJSON()
|
||||||
|
).toMatchSnapshot();
|
||||||
|
});
|
@ -60,7 +60,7 @@ it('renders <Networks networks /> without throwing', () => {
|
|||||||
fabric: false,
|
fabric: false,
|
||||||
subnet: '255.255.255.0',
|
subnet: '255.255.255.0',
|
||||||
provision_start_ip: '192.168.1.2',
|
provision_start_ip: '192.168.1.2',
|
||||||
provision_end_ip: '192.168.1.253',
|
provision_end_ip: '192.168.1.253'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
350
packages/my-joy-beta/src/containers/instances/cns.js
Normal file
350
packages/my-joy-beta/src/containers/instances/cns.js
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import intercept from 'apr-intercept';
|
||||||
|
import { compose, graphql } from 'react-apollo';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { SubmissionError, destroy } from 'redux-form';
|
||||||
|
import ReduxForm from 'declarative-redux-form';
|
||||||
|
import { set, destroy as destroyValue } from 'react-redux-values';
|
||||||
|
import { Margin } from 'styled-components-spacing';
|
||||||
|
import find from 'lodash.find';
|
||||||
|
import isBoolean from 'lodash.isboolean';
|
||||||
|
import isArray from 'lodash.isarray';
|
||||||
|
import get from 'lodash.get';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ViewContainer,
|
||||||
|
StatusLoader,
|
||||||
|
Message,
|
||||||
|
MessageTitle,
|
||||||
|
MessageDescription
|
||||||
|
} from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
|
import Description from '@components/description';
|
||||||
|
import Cns, { Footer, AddServiceForm } from '@components/cns';
|
||||||
|
import GetAccount from '@graphql/get-account.gql';
|
||||||
|
import UpdateTags from '@graphql/update-tags.gql';
|
||||||
|
import GetTags from '@graphql/list-tags.gql';
|
||||||
|
import parseError from '@state/parse-error';
|
||||||
|
|
||||||
|
const CNS_FORM = 'cns-new-service';
|
||||||
|
|
||||||
|
const CnsContainer = ({
|
||||||
|
services = [],
|
||||||
|
hostnames = [],
|
||||||
|
disabled = false,
|
||||||
|
handleToggleCnsEnabled,
|
||||||
|
handleAddService,
|
||||||
|
handleRemoveService,
|
||||||
|
mutating = false,
|
||||||
|
loading = false,
|
||||||
|
mutationError = false,
|
||||||
|
loadingError = null
|
||||||
|
}) => (
|
||||||
|
<ViewContainer main>
|
||||||
|
<Margin bottom={1}>
|
||||||
|
<Description>
|
||||||
|
Triton CNS is used to automatically update hostnames for your
|
||||||
|
instances*. You can serve multiple instances (with multiple IP
|
||||||
|
addresses) under the same hostname by matching the CNS service names.{' '}
|
||||||
|
<a
|
||||||
|
href="https://docs.joyent.com/private-cloud/install/cns"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Read the docs
|
||||||
|
</a>
|
||||||
|
</Description>
|
||||||
|
</Margin>
|
||||||
|
{loading ? <StatusLoader /> : null}
|
||||||
|
{!loading && loadingError ? (
|
||||||
|
<Message error>
|
||||||
|
<MessageTitle>Ooops!</MessageTitle>
|
||||||
|
<MessageDescription>
|
||||||
|
An error occurred while loading your CNS services
|
||||||
|
</MessageDescription>
|
||||||
|
</Message>
|
||||||
|
) : null}
|
||||||
|
{!loading && mutationError ? (
|
||||||
|
<Message error>
|
||||||
|
<MessageTitle>Ooops!</MessageTitle>
|
||||||
|
<MessageDescription>{mutationError}</MessageDescription>
|
||||||
|
</Message>
|
||||||
|
) : null}
|
||||||
|
{!loading && !disabled ? (
|
||||||
|
<Cns
|
||||||
|
services={services}
|
||||||
|
hostnames={hostnames}
|
||||||
|
onRemoveService={
|
||||||
|
!mutating && (name => handleRemoveService(name, services))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ReduxForm
|
||||||
|
form={CNS_FORM}
|
||||||
|
destroyOnUnmount={false}
|
||||||
|
forceUnregisterOnUnmount={true}
|
||||||
|
onSubmit={val => handleAddService(val, services)}
|
||||||
|
>
|
||||||
|
{props => <AddServiceForm {...props} disabled={mutating} />}
|
||||||
|
</ReduxForm>
|
||||||
|
</Cns>
|
||||||
|
) : null}
|
||||||
|
{!loading && !loadingError ? (
|
||||||
|
<Footer
|
||||||
|
enabled={!disabled}
|
||||||
|
submitting={mutating}
|
||||||
|
onToggle={() => handleToggleCnsEnabled(!disabled)}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</ViewContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
export { CnsContainer as Cns };
|
||||||
|
|
||||||
|
class CnsClass extends PureComponent {
|
||||||
|
componentWillMount() {
|
||||||
|
const { reset = () => null } = this.props;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { reset, children, ...rest } = this.props;
|
||||||
|
|
||||||
|
return <CnsContainer {...rest}>{children}</CnsContainer>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
graphql(UpdateTags, { name: 'updateTags' }),
|
||||||
|
graphql(GetAccount, {
|
||||||
|
props: ({ data }) => {
|
||||||
|
const { account = {} } = data;
|
||||||
|
const { id = '<account-id>' } = account;
|
||||||
|
|
||||||
|
return { id };
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
graphql(GetTags, {
|
||||||
|
options: ({ match }) => ({
|
||||||
|
variables: {
|
||||||
|
fetchPolicy: 'network-only',
|
||||||
|
name: get(match, 'params.instance')
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
props: ({ data }) => {
|
||||||
|
const { loading, error, variables, refetch, ...rest } = data;
|
||||||
|
const { name } = variables;
|
||||||
|
|
||||||
|
const instance = find(get(rest, 'machines', []), ['name', name]);
|
||||||
|
const tags = get(instance, 'tags', []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
tags,
|
||||||
|
instance,
|
||||||
|
loading,
|
||||||
|
loadingError: error,
|
||||||
|
refetch
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
connect(
|
||||||
|
({ values, form }, { id, instance = {}, tags = [] }) => {
|
||||||
|
const { name = '<instance-name>' } = instance;
|
||||||
|
|
||||||
|
const cnsDisable = find(tags, ['name', 'triton.cns.disable']) || {};
|
||||||
|
const cnsServices = find(tags, ['name', 'triton.cns.services']) || {};
|
||||||
|
|
||||||
|
let disabled = JSON.parse(cnsDisable.value || 'false');
|
||||||
|
let services = (cnsServices.value || '').split(/,/gi).filter(Boolean);
|
||||||
|
|
||||||
|
const adding = get(form, `${CNS_FORM}.submitting`, false);
|
||||||
|
const toggling = get(values, `cns-${instance.id}-toggling`, false);
|
||||||
|
const removing = get(values, `cns-${instance.id}-removing`, false);
|
||||||
|
const enabled = get(values, `cns-${instance.id}-enabled`, undefined);
|
||||||
|
const togglingError = get(
|
||||||
|
values,
|
||||||
|
`cns-${instance.id}-toggling-error`,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const removingError = get(
|
||||||
|
values,
|
||||||
|
`cns-${instance.id}-removing-error`,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
const svcs = get(values, `cns-${instance.id}-svcs`, undefined);
|
||||||
|
|
||||||
|
if (isBoolean(enabled)) {
|
||||||
|
disabled = !enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isArray(svcs)) {
|
||||||
|
services = svcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// REPLACE WITH DATA CENTER
|
||||||
|
const dataCenter = 'us-east-1';
|
||||||
|
|
||||||
|
const defaultHostnames = [
|
||||||
|
{
|
||||||
|
values: [`${name}.inst.${id}.${dataCenter}.triton.zone`],
|
||||||
|
public: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: [`${name}.inst.${id}.${dataCenter}.cns.joyent.com`]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: [],
|
||||||
|
public: true,
|
||||||
|
service: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
values: [],
|
||||||
|
service: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const hostnames = defaultHostnames.map(hostname => {
|
||||||
|
if (!hostname.service) {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...hostname,
|
||||||
|
values: services.map(name => {
|
||||||
|
const postfix = hostname.public
|
||||||
|
? '.triton.zone'
|
||||||
|
: '.cns.joyent.com';
|
||||||
|
return `${name}.svc.${id}.${dataCenter}${postfix}`;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
hostnames,
|
||||||
|
disabled,
|
||||||
|
services,
|
||||||
|
mutating: toggling || removing || adding,
|
||||||
|
mutationError: togglingError || removingError
|
||||||
|
};
|
||||||
|
},
|
||||||
|
(dispatch, { instance = {}, refetch, updateTags }) => ({
|
||||||
|
reset: () => {
|
||||||
|
dispatch([
|
||||||
|
destroyValue({ name: `cns-${instance.id}-removing` }),
|
||||||
|
destroyValue({ name: `cns-${instance.id}-svcs` }),
|
||||||
|
destroyValue({ name: `cns-${instance.id}-removing-error` }),
|
||||||
|
destroyValue({ name: `cns-${instance.id}-toggling` }),
|
||||||
|
destroyValue({ name: `cns-${instance.id}-enabled` }),
|
||||||
|
destroyValue({ name: `cns-${instance.id}-toggling-error` })
|
||||||
|
]);
|
||||||
|
|
||||||
|
return refetch();
|
||||||
|
},
|
||||||
|
handleRemoveService: async (name, services) => {
|
||||||
|
const value = services.filter(svc => name !== svc);
|
||||||
|
|
||||||
|
dispatch([
|
||||||
|
set({ name: `cns-${instance.id}-removing`, value: true }),
|
||||||
|
set({ name: `cns-${instance.id}-svcs`, value })
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [err] = await intercept(
|
||||||
|
updateTags({
|
||||||
|
variables: {
|
||||||
|
id: instance.id,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
name: 'triton.cns.services',
|
||||||
|
value: value.join(',')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const setLoadingFalse = set({
|
||||||
|
name: `cns-${instance.id}-removing`,
|
||||||
|
value: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return dispatch([
|
||||||
|
setLoadingFalse,
|
||||||
|
set({
|
||||||
|
name: `cns-${instance.id}-removing-error`,
|
||||||
|
value: parseError(err)
|
||||||
|
}),
|
||||||
|
set({ name: `cns-${instance.id}-svcs`, value: null })
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatch(setLoadingFalse);
|
||||||
|
},
|
||||||
|
handleToggleCnsEnabled: async disabled => {
|
||||||
|
dispatch([
|
||||||
|
set({ name: `cns-${instance.id}-toggling`, value: true }),
|
||||||
|
set({ name: `cns-${instance.id}-enabled`, value: !disabled })
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [err] = await intercept(
|
||||||
|
updateTags({
|
||||||
|
variables: {
|
||||||
|
id: instance.id,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
name: 'triton.cns.disable',
|
||||||
|
value: disabled ? 'true' : 'false'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const setLoadingFalse = set({
|
||||||
|
name: `cns-${instance.id}-toggling`,
|
||||||
|
value: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
return dispatch([
|
||||||
|
setLoadingFalse,
|
||||||
|
set({
|
||||||
|
name: `cns-${instance.id}-toggling-error`,
|
||||||
|
value: parseError(err)
|
||||||
|
}),
|
||||||
|
set({ name: `cns-${instance.id}-enabled`, value: null })
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatch(setLoadingFalse);
|
||||||
|
},
|
||||||
|
handleAddService: async ({ name }, services) => {
|
||||||
|
const value = services.concat(name);
|
||||||
|
|
||||||
|
dispatch(set({ name: `cns-${instance.id}-svcs`, value }));
|
||||||
|
|
||||||
|
const [err] = await intercept(
|
||||||
|
updateTags({
|
||||||
|
variables: {
|
||||||
|
id: instance.id,
|
||||||
|
tags: [
|
||||||
|
{
|
||||||
|
name: 'triton.cns.services',
|
||||||
|
value: value.join(',')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
dispatch(set({ name: `cns-${instance.id}-svcs`, services }));
|
||||||
|
|
||||||
|
throw new SubmissionError({
|
||||||
|
_error: parseError(err)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatch(destroy(CNS_FORM));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)(CnsClass);
|
@ -1,62 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { compose, graphql } from 'react-apollo';
|
|
||||||
import find from 'lodash.find';
|
|
||||||
import get from 'lodash.get';
|
|
||||||
|
|
||||||
import {
|
|
||||||
ViewContainer,
|
|
||||||
StatusLoader,
|
|
||||||
Message,
|
|
||||||
MessageDescription,
|
|
||||||
MessageTitle
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import ListDNS from '@graphql/list-dns.gql';
|
|
||||||
|
|
||||||
const DNS = ({ instance, loading, error }) => {
|
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
const { name, dns_names } = instance || {};
|
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
const _loading = loading && !name && !dns_names && <StatusLoader />;
|
|
||||||
const _summary = !_loading &&
|
|
||||||
instance && <pre>{JSON.stringify(dns_names, null, 2)}</pre>;
|
|
||||||
|
|
||||||
const _error = error &&
|
|
||||||
!_loading &&
|
|
||||||
!instance && (
|
|
||||||
<Message error>
|
|
||||||
<MessageTitle>Ooops!</MessageTitle>
|
|
||||||
<MessageDescription>
|
|
||||||
An error occurred while loading your instance DNS
|
|
||||||
</MessageDescription>
|
|
||||||
</Message>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ViewContainer center={Boolean(_loading)} main>
|
|
||||||
{_loading}
|
|
||||||
{_error}
|
|
||||||
{_summary}
|
|
||||||
</ViewContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
DNS.propTypes = {
|
|
||||||
loading: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
export default compose(
|
|
||||||
graphql(ListDNS, {
|
|
||||||
options: ({ match }) => ({
|
|
||||||
variables: {
|
|
||||||
name: get(match, 'params.instance')
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
props: ({ data: { loading, error, variables, ...rest } }) => ({
|
|
||||||
instance: find(get(rest, 'machines', []), ['name', variables.name]),
|
|
||||||
loading,
|
|
||||||
error
|
|
||||||
})
|
|
||||||
})
|
|
||||||
)(DNS);
|
|
@ -4,6 +4,6 @@ export { default as Tags } from './tags';
|
|||||||
export { default as Metadata } from './metadata';
|
export { default as Metadata } from './metadata';
|
||||||
export { default as Networks } from './networks';
|
export { default as Networks } from './networks';
|
||||||
export { default as Firewall } from './firewall';
|
export { default as Firewall } from './firewall';
|
||||||
export { default as Dns } from './dns';
|
export { default as Cns } from './cns';
|
||||||
export { default as Snapshots } from './snapshots';
|
export { default as Snapshots } from './snapshots';
|
||||||
export { default as Resize } from './resize';
|
export { default as Resize } from './resize';
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import paramCase from 'param-case';
|
|
||||||
import titleCase from 'title-case';
|
|
||||||
import isString from 'lodash.isstring';
|
|
||||||
import get from 'lodash.get';
|
import get from 'lodash.get';
|
||||||
|
|
||||||
import { Menu } from '@components/navigation';
|
import { Menu } from '@components/navigation';
|
||||||
@ -11,17 +8,7 @@ export default connect((state, { match }) => {
|
|||||||
const allSections = get(state, 'ui.sections');
|
const allSections = get(state, 'ui.sections');
|
||||||
const sections = instanceSlug ? allSections.instances : [];
|
const sections = instanceSlug ? allSections.instances : [];
|
||||||
|
|
||||||
const links = sections
|
const links = sections.map(({ name, pathname }) => ({
|
||||||
.map(
|
|
||||||
section =>
|
|
||||||
!isString(section)
|
|
||||||
? section
|
|
||||||
: {
|
|
||||||
pathname: paramCase(section),
|
|
||||||
name: titleCase(section)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.map(({ name, pathname }) => ({
|
|
||||||
name,
|
name,
|
||||||
pathname: `/instances/${instanceSlug}/${pathname}`
|
pathname: `/instances/${instanceSlug}/${pathname}`
|
||||||
}));
|
}));
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
Metadata as InstanceMetadata,
|
Metadata as InstanceMetadata,
|
||||||
Networks as InstanceNetworks,
|
Networks as InstanceNetworks,
|
||||||
Firewall as InstanceFirewall,
|
Firewall as InstanceFirewall,
|
||||||
Dns as InstanceDns,
|
Cns as InstanceCns,
|
||||||
Snapshots as InstanceSnapshots,
|
Snapshots as InstanceSnapshots,
|
||||||
Resize as InstanceResize
|
Resize as InstanceResize
|
||||||
} from '@containers/instances';
|
} from '@containers/instances';
|
||||||
@ -77,12 +77,16 @@ export default () => (
|
|||||||
exact
|
exact
|
||||||
component={InstanceFirewall}
|
component={InstanceFirewall}
|
||||||
/>
|
/>
|
||||||
<Route path="/instances/:instance/dns" exact component={InstanceDns} />
|
|
||||||
<Route
|
<Route
|
||||||
path="/instances/:instance/snapshots"
|
path="/instances/:instance/snapshots"
|
||||||
exact
|
exact
|
||||||
component={InstanceSnapshots}
|
component={InstanceSnapshots}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/instances/:instance/cns-dns"
|
||||||
|
exact
|
||||||
|
component={InstanceCns}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/instances/:instance"
|
path="/instances/:instance"
|
||||||
exact
|
exact
|
||||||
|
@ -5,6 +5,7 @@ import { ApolloClient } from 'apollo-client';
|
|||||||
import { HttpLink } from 'apollo-link-http';
|
import { HttpLink } from 'apollo-link-http';
|
||||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||||
import { reducer as valuesReducer } from 'react-redux-values';
|
import { reducer as valuesReducer } from 'react-redux-values';
|
||||||
|
import paramCase from 'param-case';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
REACT_APP_GQL_PORT = 443,
|
REACT_APP_GQL_PORT = 443,
|
||||||
@ -22,7 +23,17 @@ export const client = new ApolloClient({
|
|||||||
const initialState = {
|
const initialState = {
|
||||||
ui: {
|
ui: {
|
||||||
sections: {
|
sections: {
|
||||||
instances: ['summary', 'tags', 'metadata', 'networks', 'snapshots']
|
instances: [
|
||||||
|
'Summary',
|
||||||
|
'CNS & DNS',
|
||||||
|
'Snapshots',
|
||||||
|
'Tags',
|
||||||
|
'Metadata',
|
||||||
|
'Networks'
|
||||||
|
].map(name => ({
|
||||||
|
pathname: paramCase(name),
|
||||||
|
name
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
12
yarn.lock
12
yarn.lock
@ -3829,8 +3829,8 @@ eslint-plugin-flowtype@2.39.1:
|
|||||||
lodash "^4.15.0"
|
lodash "^4.15.0"
|
||||||
|
|
||||||
eslint-plugin-flowtype@^2.39.1:
|
eslint-plugin-flowtype@^2.39.1:
|
||||||
version "2.41.0"
|
version "2.41.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.41.0.tgz#fd5221c60ba917c059d7ef69686a99cca09fd871"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.41.1.tgz#0996e1ea1d501dfc945802453a304ae9e8098b78"
|
||||||
dependencies:
|
dependencies:
|
||||||
lodash "^4.15.0"
|
lodash "^4.15.0"
|
||||||
|
|
||||||
@ -4926,8 +4926,8 @@ graphql-tag@^2.6.1:
|
|||||||
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.6.1.tgz#4788d509f6e29607d947fc47a40c4e18f736d34a"
|
resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.6.1.tgz#4788d509f6e29607d947fc47a40c4e18f736d34a"
|
||||||
|
|
||||||
graphql-tools@^2.6.1:
|
graphql-tools@^2.6.1:
|
||||||
version "2.18.0"
|
version "2.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.18.0.tgz#8e2d6436f9adba1d579c1a1710ae95e7f5e7248b"
|
resolved "https://registry.yarnpkg.com/graphql-tools/-/graphql-tools-2.19.0.tgz#04e1065532ab877aff3ad1883530fb56804ce9bf"
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-link "^1.0.0"
|
apollo-link "^1.0.0"
|
||||||
apollo-utilities "^1.0.1"
|
apollo-utilities "^1.0.1"
|
||||||
@ -6656,6 +6656,10 @@ lodash.intersection@^4.4.0:
|
|||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705"
|
resolved "https://registry.yarnpkg.com/lodash.intersection/-/lodash.intersection-4.4.0.tgz#0a11ba631d0e95c23c7f2f4cbb9a692ed178e705"
|
||||||
|
|
||||||
|
lodash.isarray@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403"
|
||||||
|
|
||||||
lodash.isarraylike@^4.2.0:
|
lodash.isarraylike@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isarraylike/-/lodash.isarraylike-4.2.0.tgz#4623310ab318804b667ddc3619058137559400c4"
|
resolved "https://registry.yarnpkg.com/lodash.isarraylike/-/lodash.isarraylike-4.2.0.tgz#4623310ab318804b667ddc3619058137559400c4"
|
||||||
|
Loading…
Reference in New Issue
Block a user