diff --git a/packages/cloudapi-gql/package.json b/packages/cloudapi-gql/package.json
index f1ea3962..642c2b2d 100644
--- a/packages/cloudapi-gql/package.json
+++ b/packages/cloudapi-gql/package.json
@@ -41,6 +41,7 @@
"triton": "^5.4.0"
},
"devDependencies": {
+ "graphql-faker": "^1.5.0",
"eslint": "^4.9.0",
"eslint-config-joyent-portal": "^3.2.0",
"eslint-plugin-graphql": "^1.4.0-1",
diff --git a/packages/my-joy-beta/package.json b/packages/my-joy-beta/package.json
index ac37f14e..aa69d37a 100644
--- a/packages/my-joy-beta/package.json
+++ b/packages/my-joy-beta/package.json
@@ -9,8 +9,10 @@
"dev": "REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
"start": "PORT=3069 joyent-react-scripts start",
"build": "NODE_ENV=production joyent-react-scripts build",
- "lint-ci": "eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
- "lint": "eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
+ "lint-ci":
+ "eslint . --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
+ "lint":
+ "eslint . --fix --ext .js --ext .md && echo 0 `# stylelint './src/**/*.js'`",
"test-ci": "echo 0 `# NODE_ENV=test ./test/run --env=jsdom --coverage`",
"test": "NODE_ENV=test ./test/run --env=jsdom",
"prepublish": "echo 0"
diff --git a/packages/my-joy-beta/src/components/instances/firewall-rule.js b/packages/my-joy-beta/src/components/instances/firewall-rule.js
index 5e70e0ad..168246d7 100644
--- a/packages/my-joy-beta/src/components/instances/firewall-rule.js
+++ b/packages/my-joy-beta/src/components/instances/firewall-rule.js
@@ -1,27 +1,15 @@
import React from 'react';
+import forceArray from 'force-array';
import {
- Card,
- CardMeta,
- CardTitle,
- CardLabel,
- CardView
+ TableTr,
+ TableTd
} from 'joyent-ui-toolkit';
-export default ({
- rule = '',
- global = false,
- enabled = false,
- first,
- last
-}) => (
-
-
-
- {rule}
-
-
-
-
-
+export default ({ rule = '', global = false, enabled = false }) => (
+
+ {rule}
+ {JSON.stringify(global)}
+ {JSON.stringify(enabled)}
+
);
diff --git a/packages/my-joy-beta/src/components/instances/index.js b/packages/my-joy-beta/src/components/instances/index.js
index 115137b4..1de93acc 100644
--- a/packages/my-joy-beta/src/components/instances/index.js
+++ b/packages/my-joy-beta/src/components/instances/index.js
@@ -1,4 +1,3 @@
-export { default as Item } from './item';
export { default as List } from './list';
export { default as KeyValue } from './key-value';
export { default as Network } from './network';
@@ -6,4 +5,3 @@ export { default as FirewallRule } from './firewall-rule';
export { default as Resize } from './resize';
export { default as CreateSnapshot } from './create-snapshot';
export { default as Snapshots } from './snapshots';
-export { default as Snapshot } from './snapshot';
diff --git a/packages/my-joy-beta/src/components/instances/list.js b/packages/my-joy-beta/src/components/instances/list.js
index cb5a3ebe..0cb45fd1 100644
--- a/packages/my-joy-beta/src/components/instances/list.js
+++ b/packages/my-joy-beta/src/components/instances/list.js
@@ -2,6 +2,8 @@ import React from 'react';
import { Row, Col } from 'react-styled-flexboxgrid';
import forceArray from 'force-array';
import find from 'lodash.find';
+import remcalc from 'remcalc';
+import titleCase from 'title-case';
import {
FormGroup,
@@ -14,12 +16,105 @@ import {
MessageTitle,
MessageDescription,
Button,
- QueryBreakpoints
+ QueryBreakpoints,
+ Table,
+ TableThead,
+ TableTr,
+ TableTh,
+ TableTbody,
+ TableTd,
+ Checkbox,
+ P,
+ DotIcon,
+ IconActions,
+ PopoverContainer,
+ PopoverTarget,
+ Popover,
+ PopoverItem,
+ PopoverDivider,
+ Anchor
} from 'joyent-ui-toolkit';
-import Item from './item';
+const { SmallOnly, Small, Medium } = QueryBreakpoints;
-const { SmallOnly, Medium } = QueryBreakpoints;
+const stateColor = {
+ PROVISIONING: 'primary',
+ RUNNING: 'green',
+ STOPPING: 'grey',
+ STOPPED: 'grey',
+ DELETED: 'secondaryActive',
+ FAILED: 'red'
+};
+
+const Item = ({
+ id,
+ name,
+ state,
+ allowedActions,
+ onStop,
+ onStart,
+ onReboot,
+ onResize,
+ onEnableFw,
+ onDisableFw,
+ onCreateSnap,
+ onStartSnap
+}) => (
+
+
+
+
+
+
+
+ {id.substring(0, 7)}
+
+
+ {name}
+
+
+ {titleCase(state)}
+
+
+
+
+
+
+
+ {!allowedActions.stop ? null : (
+ Stop
+ )}
+ {!allowedActions.start ? null : (
+ Start
+ )}
+ {!allowedActions.reboot ? null : (
+ Reboot
+ )}
+ {!allowedActions.enableFw ? null : (
+ Enable Firewall
+ )}
+ {!allowedActions.disableFw ? null : (
+ Disable Firewall
+ )}
+ {!allowedActions.disableFw ? null : (
+ Disable Firewall
+ )}
+
+ {!allowedActions.resize ? null : (
+ Resize
+ )}
+ {!allowedActions.createSnap ? null : (
+ Create Snapshot
+ )}
+ {!allowedActions.startSnap ? null : (
+ Start from Snapshot
+ )}
+ Delete
+
+
+
+
+);
export default ({
instances = [],
@@ -59,23 +154,39 @@ export default ({
});
};
- const _instances = forceArray(instances);
-
- const items = _instances.map((instance, i, all) => {
- const { id } = instance;
-
+ const items = forceArray(instances).map(instance => {
+ // eslint-disable-next-line camelcase
+ const { id, name, state, firewall_enabled, snapshots, brand } = instance;
const isSelected = Boolean(find(selected, ['id', id]));
const isSubmitting = isSelected && submitting;
- return (
-
- );
+ const allowedActions = {
+ stop: state === 'RUNNING',
+ start: state !== 'RUNNING',
+ reboot: true,
+ resize: brand === 'KVM',
+ // eslint-disable-next-line camelcase
+ enableFw: !firewall_enabled,
+ // eslint-disable-next-line camelcase
+ disableFw: firewall_enabled,
+ createSnap: true,
+ startSnap: Boolean(snapshots.length)
+ };
+
+ return {
+ ...instance,
+ isSubmitting,
+ isSelected,
+ allowedActions,
+ onStop: () => onAction({ name: 'stop', items: [instance] }),
+ onStart: () => onAction({ name: 'start', items: [instance] }),
+ onReboot: () => onAction({ name: 'reboot', items: [instance] }),
+ onResize: () => onAction({ name: 'resize', items: [instance] }),
+ onEnableFw: () => onAction({ name: 'enableFw', items: [instance] }),
+ onDisableFw: () => onAction({ name: 'disableFw', items: [instance] }),
+ onCreateSnap: () => onAction({ name: 'createSnap', items: [instance] }),
+ onStartSnap: () => onAction({ name: 'startSnap', items: [instance] })
+ };
});
const _loading =
@@ -93,6 +204,27 @@ export default ({
);
+ const _table = !items.length ? null : (
+
+
+
+
+
+ Id
+
+
+ Name
+
+
+ Status
+
+
+
+
+ {items.map(instance => )}
+
+ );
+
return (
);
};
diff --git a/packages/my-joy-beta/src/components/instances/network.js b/packages/my-joy-beta/src/components/instances/network.js
index 01f12e69..ab88e88d 100644
--- a/packages/my-joy-beta/src/components/instances/network.js
+++ b/packages/my-joy-beta/src/components/instances/network.js
@@ -2,22 +2,15 @@ import React from 'react';
import forceArray from 'force-array';
import {
- Card,
- CardMeta,
- CardTitle,
- CardLabel,
- CardView
+ TableTr,
+ TableTd
} from 'joyent-ui-toolkit';
-export default ({ name, gateway, subnet, resolvers = [], first, last }) => (
-
-
-
- {name}
- {gateway}
- {subnet}
- {forceArray(resolvers).join('\u00B7')}
-
-
-
+export default ({ name, gateway, subnet, resolvers = [] }) => (
+
+ {name}
+ {gateway}
+ {subnet}
+ {forceArray(resolvers).join('\u00B7')}
+
);
diff --git a/packages/my-joy-beta/src/components/instances/snapshot.js b/packages/my-joy-beta/src/components/instances/snapshot.js
deleted file mode 100644
index d11dbad8..00000000
--- a/packages/my-joy-beta/src/components/instances/snapshot.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import React from 'react';
-import titleCase from 'title-case';
-import moment from 'moment';
-
-import {
- Card,
- CardMeta,
- CardAction,
- CardTitle,
- CardLabel,
- CardView,
- Checkbox,
- FormGroup,
- QueryBreakpoints,
- StatusLoader
-} from 'joyent-ui-toolkit';
-
-const { SmallOnly, Small } = QueryBreakpoints;
-
-const stateColor = {
- QUEUED: 'blue',
- CANCELED: 'grey',
- FAILED: 'red',
- CREATED: 'green'
-};
-
-export default ({ name, state, created, loading, last, first }) => (
-
-
-
-
-
-
-
-
- {name}
- {moment.unix(created).fromNow()}
- {loading && (
-
-
-
- )}
- {!loading && (
-
- {titleCase(state)}
-
- )}
- {!loading && (
-
-
-
- )}
-
-
-
-);
diff --git a/packages/my-joy-beta/src/components/instances/snapshots.js b/packages/my-joy-beta/src/components/instances/snapshots.js
index 3788d9f0..2a226ce7 100644
--- a/packages/my-joy-beta/src/components/instances/snapshots.js
+++ b/packages/my-joy-beta/src/components/instances/snapshots.js
@@ -2,6 +2,7 @@ import React from 'react';
import { Row, Col } from 'react-styled-flexboxgrid';
import forceArray from 'force-array';
import find from 'lodash.find';
+import moment from 'moment';
import {
FormGroup,
@@ -14,13 +15,31 @@ import {
MessageTitle,
MessageDescription,
Button,
- QueryBreakpoints
+ QueryBreakpoints,
+ Table,
+ TableThead,
+ TableTr,
+ TableTh,
+ TableTbody,
+ TableTd,
+ Checkbox,
+ P
} from 'joyent-ui-toolkit';
-import Item from './snapshot';
-
const { SmallOnly, Medium } = QueryBreakpoints;
+const Item = ({ name, state, created }) => (
+
+
+
+
+
+
+ {name}
+ {moment.unix(created).fromNow()}
+
+);
+
export default ({
snapshots = [],
selected = [],
@@ -57,21 +76,16 @@ export default ({
);
- const items = _snapshots.map((snapshot, i, all) => {
+ const items = _snapshots.map(snapshot => {
const { name } = snapshot;
-
const isSelected = Boolean(find(selected, ['name', name]));
const isSubmitting = isSelected && submitting;
- return (
-
- );
+ return {
+ ...snapshot,
+ isSubmitting,
+ isSelected
+ };
});
const _error = error &&
@@ -82,6 +96,23 @@ export default ({
);
+ const _table = !items.length ? null : (
+
+
+
+
+
+ Name
+
+
+ Created
+
+
+
+ {items.map(snapshot => )}
+
+ );
+
return (
);
};
diff --git a/packages/my-joy-beta/src/containers/instances/firewall.js b/packages/my-joy-beta/src/containers/instances/firewall.js
index eab2013f..e50c96ff 100644
--- a/packages/my-joy-beta/src/containers/instances/firewall.js
+++ b/packages/my-joy-beta/src/containers/instances/firewall.js
@@ -11,7 +11,13 @@ import {
StatusLoader,
Message,
MessageDescription,
- MessageTitle
+ MessageTitle,
+ Table,
+ TableThead,
+ TableTr,
+ TableTh,
+ TableTbody,
+ P
} from 'joyent-ui-toolkit';
import GetFirewallRules from '@graphql/list-firewall-rules.gql';
@@ -28,16 +34,31 @@ const Firewall = ({
const _title = Firewall;
const _loading = !(loading && !values.length) ? null : ;
- const _firewall =
- !_loading &&
- values.map((rule, i, all) => (
-
- ));
+ const _firewall = (_loading && !values.length) ? null : (
+
+
+
+
+ Rule
+
+
+ Global
+
+
+ Enabled
+
+
+
+ {
+ values.map((network) => (
+
+ ))}
+
+
+ );
const _error =
error && !values.length && !_loading ? (
diff --git a/packages/my-joy-beta/src/containers/instances/networks.js b/packages/my-joy-beta/src/containers/instances/networks.js
index 4eb9ce99..91f3ef2b 100644
--- a/packages/my-joy-beta/src/containers/instances/networks.js
+++ b/packages/my-joy-beta/src/containers/instances/networks.js
@@ -11,7 +11,13 @@ import {
StatusLoader,
Message,
MessageDescription,
- MessageTitle
+ MessageTitle,
+ Table,
+ TableThead,
+ TableTr,
+ TableTh,
+ TableTbody,
+ P
} from 'joyent-ui-toolkit';
import GetNetworks from '@graphql/list-networks.gql';
@@ -22,16 +28,34 @@ const Networks = ({ networks = [], loading, error }) => {
const _title = Networks;
const _loading = !(loading && !values.length) ? null : ;
- const _networks =
- !_loading &&
- values.map((network, i, all) => (
-
- ));
+ const _networks = (_loading && !values.length) ? null : (
+
+
+
+
+ Name
+
+
+ Gateway
+
+
+ Subnet
+
+
+ Resolvers
+
+
+
+ {
+ values.map((network) => (
+
+ ))}
+
+
+ );
const _error =
error && !values.length && !_loading ? (
diff --git a/packages/ui-toolkit/package.json b/packages/ui-toolkit/package.json
index ad0d2f16..adc4ea94 100644
--- a/packages/ui-toolkit/package.json
+++ b/packages/ui-toolkit/package.json
@@ -75,6 +75,7 @@
"jest-snapshot": "^21.2.1",
"jest-styled-components": "^4.9.0",
"joyent-react-scripts": "^2.6.0",
+ "lodash.isboolean": "^3.0.3",
"navalia": "^1.2.0",
"react": "^16.0.0",
"react-docgen": "^3.0.0-beta8",
diff --git a/packages/ui-toolkit/src/card/demo.md b/packages/ui-toolkit/src/card/demo.md
index f8f3dd70..7b6d4adb 100644
--- a/packages/ui-toolkit/src/card/demo.md
+++ b/packages/ui-toolkit/src/card/demo.md
@@ -1,6 +1,6 @@
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
;
```
@@ -9,7 +9,7 @@ const { Card } = require('.');
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
;
```
@@ -18,7 +18,7 @@ const { Card } = require('.');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P } = require('../text');
@@ -31,10 +31,10 @@ const {
-
+
Nginx
-
+
4 of 4 instances
@@ -52,7 +52,7 @@ const {
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P } = require('../text');
@@ -66,10 +66,10 @@ const {
-
+
Nginx
-
+
4 of 4 instances
@@ -104,7 +104,7 @@ const {
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P, Small } = require('../text');
@@ -117,10 +117,10 @@ const {
-
+
Nginx
-
+
4 of 4 instances
@@ -143,7 +143,7 @@ const {
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P } = require('../text');
const { default: StatusLoader } = require('../status-loader');
@@ -184,10 +184,10 @@ const {
-
+
Nginx
-
+
4 of 4 instances
@@ -233,7 +233,7 @@ const {
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P } = require('../text');
const { IconActions } = require('../icons');
@@ -245,7 +245,7 @@ const { IconActions } = require('../icons');
Nginx
-
+
1 Instance
@@ -262,7 +262,7 @@ const { IconActions } = require('../icons');
```jsx
const React = require('react');
-const { Card, Outlet } = require('.');
+const { default: Card, Outlet } = require('.');
const { H4, P } = require('../text');
const { HealthyIcon } = require('../icons');
@@ -294,7 +294,7 @@ const { HealthyIcon } = require('../icons');
```jsx
const React = require('react');
-const { Card, Outlet } = require('.');
+const { default: Card, Outlet } = require('.');
const { H4, P } = require('../text');
const { HealthyIcon } = require('../icons');
@@ -326,7 +326,7 @@ const { HealthyIcon } = require('../icons');
```jsx
const React = require('react');
-const { Card, Outlet } = require('.');
+const { default: Card, Outlet } = require('.');
const { H4, P } = require('../text');
const { HealthyIcon } = require('../icons');
@@ -404,7 +404,7 @@ const { HealthyIcon } = require('../icons');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
const { H4, P } = require('../text');
const { HealthyIcon, IconActions, DataCenterIcon } = require('../icons');
@@ -414,15 +414,15 @@ const { HealthyIcon, IconActions, DataCenterIcon } = require('../icons');
-
+
Nginx
-
+
Healthy
-
+
eu-ams-1
diff --git a/packages/ui-toolkit/src/card/index.js b/packages/ui-toolkit/src/card/index.js
index dc8a7d26..c48854ba 100644
--- a/packages/ui-toolkit/src/card/index.js
+++ b/packages/ui-toolkit/src/card/index.js
@@ -1,4 +1,4 @@
-export { default as Card } from './card';
+export { default } from './card';
export { default as Outlet } from './outlet';
export {
diff --git a/packages/ui-toolkit/src/card/test.md b/packages/ui-toolkit/src/card/test.md
index f3a2b3ea..4524d4f3 100644
--- a/packages/ui-toolkit/src/card/test.md
+++ b/packages/ui-toolkit/src/card/test.md
@@ -2,7 +2,7 @@
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -36,7 +36,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -70,7 +70,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -128,7 +128,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -186,7 +186,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card } = require('.');
+const { default: Card } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -244,7 +244,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header } = require('.');
+const { default: Card, Header } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -317,7 +317,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header } = require('.');
+const { default: Card, Header } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -390,7 +390,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header } = require('.');
+const { default: Card, Header } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -463,7 +463,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -590,7 +590,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -729,7 +729,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -889,7 +889,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
@@ -1094,7 +1094,7 @@ const { Row, Col } = require('react-styled-flexboxgrid');
```jsx
const React = require('react');
-const { Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
+const { default: Card, Header, HeaderBox, HeaderMeta, Outlet } = require('.');
const { Row, Col } = require('react-styled-flexboxgrid');
[
diff --git a/packages/ui-toolkit/src/card/usage.md b/packages/ui-toolkit/src/card/usage.md
deleted file mode 100644
index 1c2abeac..00000000
--- a/packages/ui-toolkit/src/card/usage.md
+++ /dev/null
@@ -1,486 +0,0 @@
-#### Card > Headed > Collapsed
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { InstancesIconLight } = require('../icons');
-
-
-
-
- Nginx
-
-
-
-
-
-
- 4 of 4 instances
-
-
-
-
-
-
-;
-```
-
-#### Card > Headed
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
- Nginx
-
-
-
-
-
-
- 4 of 4 instances
-
-
-
-
-
-
-
-
- }
- iconPosition="left"
- label="Healthy"
- color="dark"
- />
-
-
-;
-```
-
-#### Card > Single state
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
- Nginx
-
-
-
-
-
-
- 4 of 4 instances
-
-
-
-
-
-
-
-
- 1 instance paused
- 1 instances stopped
- 1 instance not responding
-
-
-;
-```
-
-#### Card > Provisioning
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const StatusLoader = require('../status-loader').default;
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
-
- Nginx
-
-
-
-
-
-;
-```
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const StatusLoader = require('../status-loader').default;
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
- Nginx
-
-
-
-
-
-
- 4 of 4 instances
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Healthy
-
-
-
-;
-```
-
-#### Card > Disabled
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { InstancesIcon, HealthyIcon } = require('../icons');
-const StatusLoader = require('../status-loader').default;
-
-
-
-
- Nginx
-
-
-
-
-
- 4 of 4 instances
-
-
-
-
-
-
-
-
-
-
-;
-```
-
-#### Card > Instance
-
-```jsx
-const {
- CardDescription,
- CardOutlet,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { Row } = require('react-styled-flexboxgrid');
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
- percona_primary
-
-
-
-
- Healthy
-
-
-
-;
-```
-
-#### Card > Instance > Stacked
-
-```jsx
-const {
- CardDescription,
- CardOutlet,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { Row } = require('react-styled-flexboxgrid');
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
- percona_primary
- 4 instances
-
-
-
-
- Healthy
-
-
-
-;
-```
-
-#### Card > Instance > Group
-
-```jsx
-const {
- CardDescription,
- CardOutlet,
- CardTitle,
- CardView,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer
-} = require('./');
-
-const { Row } = require('react-styled-flexboxgrid');
-const { InstancesIconLight, HealthyIcon } = require('../icons');
-
-
-
-
-
- percona_primary
-
-
-
-
- Healthy
-
-
-
-
-
-
-
- percona_primary
-
-
-
-
- Healthy
-
-
-
-
-
-
-
- percona_primary
- 4 instances
-
-
-
-
- Healthy
-
-
-
-
-
;
-```
-
-#### Card > Instance > List
-
-```jsx
-const {
- Card,
- CardInfo,
- CardInfoLabel,
- CardInfoIconContainer,
- CardView,
- CardTitle,
- CardDescription,
- CardOptions
-} = require('./');
-
-const { HealthyIcon, DataCenterIcon } = require('../icons');
-
-
-
- WordPress_01
-
-
-
-
-
- Healthy
-
-
-
-
-
-
-
- Healthy
-
-
-
-
-;
-```
-
-#### Card > Secondary
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardGroupView,
- CardFooter
-} = require('./');
-
-
-
-
- $0.016 per hour
- 0.256 GB RAM
- 0.25 vCPUs
- 0.01 TB disk
- SSD
-
- Compute Optimise
-
-
-;
-```
-
-#### Card > Secondary > Active
-
-```jsx
-const {
- CardDescription,
- CardHeader,
- CardMeta,
- CardOptions,
- CardOutlet,
- CardSubTitle,
- CardTitle,
- CardView,
- CardGroupView,
- CardFooter
-} = require('./');
-
-
-
-
- $0.016 per hour
- 0.256 GB RAM
- 0.25 vCPUs
- 0.01 TB disk
- SSD
-
- Compute Optimise
-
-
-;
-```
diff --git a/packages/ui-toolkit/src/icons/dot.js b/packages/ui-toolkit/src/icons/dot.js
new file mode 100644
index 00000000..71a04586
--- /dev/null
+++ b/packages/ui-toolkit/src/icons/dot.js
@@ -0,0 +1,12 @@
+import remcalc from 'remcalc';
+import styled from 'styled-components';
+
+import Baseline from '../baseline';
+
+export default Baseline(styled.span`
+ width: ${remcalc(6)};
+ height: ${remcalc(6)};
+ border-radius: ${remcalc(3)};
+ background-color: ${props => props.theme[props.color]};
+ display: inline-block;
+`);
diff --git a/packages/ui-toolkit/src/icons/index.js b/packages/ui-toolkit/src/icons/index.js
index 6e82337c..0f683781 100644
--- a/packages/ui-toolkit/src/icons/index.js
+++ b/packages/ui-toolkit/src/icons/index.js
@@ -15,6 +15,7 @@ export { default as UserIcon } from './user';
export { default as UserIconLight } from './user-light';
export { default as DataCenterIcon } from './data-center';
export { default as DataCenterIconLight } from './data-center-light';
+export { default as DotIcon } from './dot';
export { default as ChevronIcon } from './chevron';
export { default as TritonIcon } from './triton';
export { default as TritonBetaIcon } from './triton-beta'
diff --git a/packages/ui-toolkit/src/index.js b/packages/ui-toolkit/src/index.js
index cab45194..ed6ed07c 100644
--- a/packages/ui-toolkit/src/index.js
+++ b/packages/ui-toolkit/src/index.js
@@ -114,6 +114,7 @@ export {
UserIcon,
DataCenterIcon,
DataCenterIconLight,
+ DotIcon,
ChevronIcon,
TritonIcon,
UserIconLight,
@@ -138,3 +139,12 @@ export {
Divider as PopoverDivider,
default as Popover
} from './popover';
+
+export {
+ default as Table,
+ Thead as TableThead,
+ Tr as TableTr,
+ Th as TableTh,
+ Tbody as TableTbody,
+ Td as TableTd
+} from './table';
diff --git a/packages/ui-toolkit/src/popover/item.js b/packages/ui-toolkit/src/popover/item.js
index 101c16f3..66f6c458 100644
--- a/packages/ui-toolkit/src/popover/item.js
+++ b/packages/ui-toolkit/src/popover/item.js
@@ -1,4 +1,5 @@
import remcalc from 'remcalc';
+
import { H4 } from '../text/headings';
export default H4.extend`
diff --git a/packages/ui-toolkit/src/table/index.js b/packages/ui-toolkit/src/table/index.js
new file mode 100644
index 00000000..b923022a
--- /dev/null
+++ b/packages/ui-toolkit/src/table/index.js
@@ -0,0 +1,262 @@
+import React from 'react';
+import { Broadcast, Subscriber } from 'joy-react-broadcast';
+import isBoolean from 'lodash.isboolean';
+import styled, { css } from 'styled-components';
+import is from 'styled-is';
+import remcalc from 'remcalc';
+
+import Baseline from '../baseline';
+import { bottomShadow } from '../boxes';
+import * as breakpoints from '../breakpoints';
+
+const { styled: query } = breakpoints;
+
+const handleBreakpoint = bp => props => {
+ const hidden =
+ (isBoolean(props[bp]) && !props[bp]) || Number(props[bp]) === 0;
+ const width = remcalc(props[bp]);
+
+ return `
+ width: ${width};
+
+ ${hidden &&
+ `
+ display: none;
+ `};
+ `;
+};
+
+const ColumnBorder = css`
+ ${is('border')`
+ border-${props => props.border}-width: ${remcalc(1)};
+ `};
+`;
+
+const Column = css`
+ border-width: ${remcalc(1)};
+ border-style: solid;
+ border-color: ${props => props.theme.grey};
+ border-spacing: 0;
+
+ ${is('disabled')`
+ border-color: ${props => props.theme.grey};
+ `};
+
+ white-space: nowrap;
+
+ box-sizing: border-box;
+ padding: 0 ${remcalc(8)} 0 ${remcalc(8)};
+ height: ${remcalc(48)};
+
+ ${handleBreakpoint('xs')};
+
+ ${query.small`
+ ${handleBreakpoint('sm')};
+ `};
+
+ ${query.medium`
+ ${handleBreakpoint('md')};
+ `};
+
+ ${query.xlargeUp`
+ ${handleBreakpoint('lg')};
+ `};
+
+ ${is('actionable')`
+ cursor: pointer;
+
+ &:hover {
+ background-color: ${props => props.theme.whiteHover};
+ }
+
+ &:active {
+ background-color: ${props => props.theme.whiteActive};
+ }
+ `};
+
+ ${is('baseline')`
+ vertical-align: baseline;
+ `};
+
+ ${is('sub')`
+ vertical-align: sub;
+ `};
+
+ ${is('text-top')`
+ vertical-align: text-top;
+ `};
+
+ ${is('text-bottom')`
+ vertical-align: text-bottom;
+ `};
+
+ ${is('middle')`
+ vertical-align: middle;
+ `};
+
+ ${is('top')`
+ vertical-align: top;
+ `};
+
+ ${is('bottom')`
+ vertical-align: bottom;
+ `};
+
+ ${is('center')`
+ text-align: center;
+ `};
+
+ ${is('left')`
+ text-align: left;
+ `};
+
+ ${is('right')`
+ text-align: right;
+ `};
+`;
+
+const BaseTable = styled.table`
+ border-collapse: collapse;
+ table-layout: fixed;
+ width: 100%;
+`;
+
+const BaseThead = styled.thead`
+ width: 100%;
+`;
+
+const BaseTbody = styled.tbody`
+ width: 100%;
+
+ border-width: ${remcalc(1)};
+ border-style: solid;
+ border-color: ${props => props.theme.grey};
+
+ ${is('shadow')`
+ box-shadow: ${bottomShadow};
+ `};
+
+ ${is('actionable')`
+ cursor: pointer;
+ `};
+
+ ${is('disabled')`
+ border-color: ${props => props.theme.grey};
+ `};
+`;
+
+const BaseTh = styled.th`
+ ${Column};
+
+ border-left-width: 0;
+ border-right-width: 0;
+ border-top-width: 0;
+ padding-top: 0;
+ padding-bottom: ${remcalc(5)};
+
+ ${ColumnBorder};
+`;
+
+const BaseTd = styled.td`
+ ${Column};
+
+ border-left-width: 0;
+ border-right-width: 0;
+
+ ${ColumnBorder};
+`;
+
+const BaseTr = styled.tr`
+ display: table-row;
+
+ color: ${props => props.theme.text};
+ background-color: ${props => props.theme.white};
+
+ ${is('actionable')`
+ cursor: pointer;
+ `};
+
+ ${is('disabled')`
+ background-color: ${props => props.theme.disabled};
+ color: ${props => props.theme.text};
+ cursor: default;
+ `};
+
+ /* override background when thead > tr */
+ ${is('header')`
+ color: ${props => props.theme.text};
+ background-color: transparent;
+ `};
+`;
+
+/**
+ * @example ./usage.md
+ */
+export default Baseline(({ children, ...rest }) => (
+
+ {children}
+
+));
+
+const Propagate = ({ children, ...rest }) => (
+
+ {({ disabled, header }) => (
+
+ {children({ disabled, header, ...rest })}
+
+ )}
+
+);
+
+export const Thead = Baseline(({ children, ...rest }) => (
+
+ {value => (
+
+ {children}
+
+ )}
+
+));
+
+export const Tr = Baseline(({ children, ...rest }) => (
+
+ {value => (
+
+ {children}
+
+ )}
+
+));
+
+export const Th = Baseline(({ children, ...rest }) => (
+
+ {value => (
+
+ {children}
+
+ )}
+
+));
+
+export const Tbody = Baseline(({ children, ...rest }) => (
+
+ {value => (
+
+ {children}
+
+ )}
+
+));
+
+export const Td = Baseline(({ children, ...rest }) => (
+
+ {value => (
+
+ {children}
+
+ )}
+
+));
diff --git a/packages/ui-toolkit/src/table/usage.md b/packages/ui-toolkit/src/table/usage.md
new file mode 100644
index 00000000..f090e0be
--- /dev/null
+++ b/packages/ui-toolkit/src/table/usage.md
@@ -0,0 +1,40 @@
+```jsx
+const React = require('react');
+const { default: Table, Thead, Tr, Th, Tbody, Td } = require('./');
+const { H4, P } = require('../text');
+
+
+
+
+ |
+ Name |
+ Status |
+ Short ID |
+ |
+
+
+
+
+ HB |
+ percona_high-ram-32_1 |
+ Provisioning |
+ 2252839a |
+ HB |
+
+
+ HB |
+ percona_high-ram-32_2 |
+ Provisioning |
+ 2252839b |
+ HB |
+
+
+ HB |
+ percona_high-ram-32_3 |
+ Provisioning |
+ 2252839b |
+ HB |
+
+
+
+```
diff --git a/packages/ui-toolkit/styleguide.config.js b/packages/ui-toolkit/styleguide.config.js
index 0d25bd14..ebd4874a 100644
--- a/packages/ui-toolkit/styleguide.config.js
+++ b/packages/ui-toolkit/styleguide.config.js
@@ -61,6 +61,7 @@ module.exports = {
name: 'Components',
components: () => [
'src/card/card.js',
+ 'src/table/index.js',
'src/breadcrumb/index.js',
'src/button/index.js',
'src/form/checkbox.js',
diff --git a/yarn.lock b/yarn.lock
index 9c22d5e3..83a13696 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7466,6 +7466,10 @@ lodash.isarraylike@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.isarraylike/-/lodash.isarraylike-4.2.0.tgz#4623310ab318804b667ddc3619058137559400c4"
+lodash.isboolean@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
+
lodash.isempty@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e"