feat(sg): bootstrap
This commit is contained in:
parent
fc84358dff
commit
063e40859d
@ -5,5 +5,5 @@ coverage
|
||||
dist
|
||||
styleguide
|
||||
build
|
||||
lib/app
|
||||
consoles/*/lib/app
|
||||
node_modules
|
@ -18,12 +18,14 @@
|
||||
"execa": "^0.10.0",
|
||||
"graphi": "^5.7.0",
|
||||
"h2o2": "^8.1.2",
|
||||
"hapi": "^17.4.0",
|
||||
"hapi": "^17.5.0",
|
||||
"hapi-triton-auth": "^3.0.0",
|
||||
"hapi-webconsole-nav": "^2.1.0",
|
||||
"my-joy-images": "*",
|
||||
"my-joy-instances": "*",
|
||||
"my-joy-navigation": "*",
|
||||
"my-joy-service-groups": "*",
|
||||
"my-joy-templates": "*",
|
||||
"tsg-graphql": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
|
||||
const Server = require('./server');
|
||||
const Ui = require('my-joy-service-groups');
|
||||
|
||||
const {
|
||||
PORT = 4004,
|
||||
@ -67,6 +68,9 @@ Main(async () => {
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
{
|
||||
plugin: Ui
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -7,6 +7,7 @@ const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
|
||||
const Server = require('./server');
|
||||
const Ui = require('my-joy-templates');
|
||||
|
||||
const {
|
||||
PORT = 4005,
|
||||
@ -67,6 +68,9 @@ Main(async () => {
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
{
|
||||
plugin: Ui
|
||||
}
|
||||
]);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"repository": "github:yldio/joyent-portal",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "NAMESPACE=images NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3070 joyent-react-scripts start",
|
||||
"dev": "REACT_APP_DEV=1 NAMESPACE=images NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3070 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=images NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
@ -19,23 +19,23 @@
|
||||
"dependencies": {
|
||||
"@manaflair/redux-batch": "^0.1.0",
|
||||
"apollo": "^0.2.2",
|
||||
"apollo-cache-inmemory": "^1.1.12",
|
||||
"apollo-client": "^2.2.8",
|
||||
"apollo-link-http": "^1.5.3",
|
||||
"apollo-cache-inmemory": "^1.2.2",
|
||||
"apollo-client": "^2.3.2",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apr-intercept": "^3.0.3",
|
||||
"apr-reduce": "^3.0.3",
|
||||
"boom": "^7.2.0",
|
||||
"cross-fetch": "^2.1.0",
|
||||
"cross-fetch": "^2.2.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"declarative-redux-form": "^2.0.8",
|
||||
"exenv": "^1.2.2",
|
||||
"force-array": "^3.1.0",
|
||||
"fuse.js": "^3.2.0",
|
||||
"hapi-render-react": "^2.5.2",
|
||||
"hapi-render-react-joyent-document": "^7.1.0",
|
||||
"hapi-render-react-joyent-document": "^7.2.0",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-logo-assets": "^1.1.0",
|
||||
"joyent-react-styled-flexboxgrid": "^2.2.3",
|
||||
"joyent-react-styled-flexboxgrid": "^3.1.0",
|
||||
"joyent-ui-resource-widgets": "^1.0.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
"lodash.assign": "^4.2.0",
|
||||
@ -46,37 +46,37 @@
|
||||
"lodash.keys": "^4.2.0",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"lunr": "^2.1.6",
|
||||
"lunr": "^2.2.1",
|
||||
"mz": "^2.7.0",
|
||||
"param-case": "^2.1.1",
|
||||
"react": "^16.3.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-helmet-async": "0.0.5",
|
||||
"react": "^16.4.0",
|
||||
"react-apollo": "^2.1.4",
|
||||
"react-dom": "^16.4.0",
|
||||
"react-helmet-async": "0.1.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-redux-values": "^1.1.2",
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"redux": "^3.7.2",
|
||||
"redux": "^4.0.0",
|
||||
"redux-form": "^7.3.0",
|
||||
"remcalc": "^1.0.10",
|
||||
"styled-components": "^3.2.5",
|
||||
"styled-components-spacing": "^2.1.3",
|
||||
"styled-components": "^3.3.0",
|
||||
"styled-components-spacing": "^3.0.0",
|
||||
"styled-flex-component": "^2.2.2",
|
||||
"styled-is": "^1.1.2",
|
||||
"styled-is": "^1.1.3",
|
||||
"title-case": "^2.1.1",
|
||||
"yup": "^0.24.1"
|
||||
"yup": "^0.25.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"jest-image-snapshot": "^2.4.0",
|
||||
"jest-image-snapshot": "^2.4.2",
|
||||
"jest-styled-components": "^5.0.1",
|
||||
"joyent-react-scripts": "^8.2.0",
|
||||
"joyent-react-scripts": "^8.2.1",
|
||||
"react-screenshot-renderer": "^1.1.2",
|
||||
"react-test-renderer": "^16.3.1",
|
||||
"redrun": "^6.0.2"
|
||||
"react-test-renderer": "^16.4.0",
|
||||
"redrun": "^6.0.4"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import React from 'react';
|
||||
import { Field } from 'redux-form';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import remcalc from 'remcalc';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
|
||||
import {
|
||||
@ -31,7 +30,6 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
|
||||
<Margin left="1">
|
||||
<Button
|
||||
type="button"
|
||||
marginTop={remcalc(8)}
|
||||
onClick={onRandomize}
|
||||
loading={randomizing}
|
||||
marginless
|
||||
@ -54,7 +52,7 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin top="3">
|
||||
<FormGroup name="description" fluid field={Field}>
|
||||
<FormLabel>Description</FormLabel>
|
||||
|
@ -5,7 +5,7 @@ import { P } from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ children }) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin bottom="3">
|
||||
<P>{children}</P>
|
||||
</Margin>
|
||||
|
@ -17,7 +17,7 @@ const FullWidthCard = styled(Card)`
|
||||
|
||||
export default ({ children }) => (
|
||||
<FullWidthCard>
|
||||
<Padding all={6}>
|
||||
<Padding all="6">
|
||||
<Flex alignCenter justifyCenter column>
|
||||
<Margin bottom="2">
|
||||
<EmptyState />
|
||||
|
@ -88,7 +88,7 @@ export const Image = ({
|
||||
<CardAnchor to={`/images/${id}`} component={Link}>
|
||||
<Card radius>
|
||||
{removing ? (
|
||||
<Padding all={2}>
|
||||
<Padding all="2">
|
||||
<StatusLoader />
|
||||
</Padding>
|
||||
) : (
|
||||
|
@ -106,13 +106,13 @@ export const Meta = ({ name, version, type, published_at, state, os }) => (
|
||||
|
||||
export default ({ theme = {}, onRemove, removing, ...image }) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={12} md={9}>
|
||||
<Col xs="12" sm="12" md="9">
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all={5}>
|
||||
<Padding all="5">
|
||||
<Meta {...image} />
|
||||
<Row between="xs">
|
||||
<Col xs={9}>
|
||||
<Col xs="9">
|
||||
<SmallOnly>
|
||||
<Button type="button" small icon>
|
||||
<DuplicateIcon light />
|
||||
@ -133,7 +133,7 @@ export default ({ theme = {}, onRemove, removing, ...image }) => (
|
||||
</Button>
|
||||
</Medium>
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<Col xs="3">
|
||||
<SmallOnly>
|
||||
<Button type="button" small icon error right>
|
||||
<DeleteIcon fill="red" />
|
||||
@ -170,7 +170,7 @@ export default ({ theme = {}, onRemove, removing, ...image }) => (
|
||||
<CopiableField text={image.id} label="UUID" />
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} md={7}>
|
||||
<Col xs="12" md="7">
|
||||
<Margin bottom="3">
|
||||
<FormLabel>Operating system</FormLabel>
|
||||
<Input
|
||||
|
@ -14,8 +14,8 @@ export const EditForm = props => (
|
||||
|
||||
export default ({ norMargin, name, value, onClick, onRemoveClick, active }) => (
|
||||
<Margin
|
||||
right={norMargin ? 0 : 1}
|
||||
bottom={norMargin ? 0 : 1}
|
||||
right={norMargin ? '0' : '1'}
|
||||
bottom={norMargin ? '0' : '1'}
|
||||
key={`${name}-${value}`}
|
||||
>
|
||||
<TagItem onClick={onClick} active={active} onRemoveClick={onRemoveClick}>
|
||||
|
@ -80,7 +80,7 @@ const NameContainer = ({
|
||||
) : null}
|
||||
{description ? (
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin top="1">
|
||||
<P>{description}</P>
|
||||
</Margin>
|
||||
|
@ -76,7 +76,7 @@ const Create = ({
|
||||
{({ handleSubmit, submitting }) =>
|
||||
!loading && !loadingError ? (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Margin top={step === 'tag' ? 7 : 4}>
|
||||
<Margin top={step === 'tag' ? '7' : '4'}>
|
||||
<Button disabled={disabled} loading={submitting}>
|
||||
Create Image
|
||||
</Button>
|
||||
|
@ -78,7 +78,7 @@ export const List = ({
|
||||
</Margin>
|
||||
<Row>
|
||||
{images.map(image => (
|
||||
<Col sm={4}>
|
||||
<Col sm="4">
|
||||
<Image
|
||||
{...image}
|
||||
onCreateInstance={() => handleCreateInstance(image)}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
import get from 'lodash.get';
|
||||
|
||||
@ -19,6 +19,8 @@ import Create from '@containers/create';
|
||||
import Tags from '@containers/tags';
|
||||
import { Route as ServerError } from '@root/server-error';
|
||||
|
||||
const { REACT_APP_DEV = false } = process.env;
|
||||
|
||||
export default () => (
|
||||
<PageContainer>
|
||||
{/* Breadcrumb */}
|
||||
@ -70,6 +72,41 @@ export default () => (
|
||||
|
||||
<Route path="/" exact component={() => <Redirect to="/images" />} />
|
||||
|
||||
{REACT_APP_DEV ? (
|
||||
<Fragment>
|
||||
<Route
|
||||
path="/instances"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3069${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/templates"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3071${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/service-groups"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3072${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
||||
<noscript>
|
||||
<ViewContainer main>
|
||||
<Message warning>
|
||||
|
@ -2,6 +2,7 @@ import { ApolloClient } from 'apollo-client';
|
||||
import { HttpLink } from 'apollo-link-http';
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||
import fetch from 'cross-fetch';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import global from './global';
|
||||
|
||||
@ -14,7 +15,9 @@ const {
|
||||
const PORT = REACT_APP_GQL_PORT ? `:${REACT_APP_GQL_PORT}` : '';
|
||||
const URI = `${REACT_APP_GQL_PROTOCOL}://${REACT_APP_GQL_HOSTNAME}${PORT}/images/graphql`;
|
||||
|
||||
export default (opts = {}) => {
|
||||
export default (opts = {}, request = {}) => {
|
||||
const host = get(request, 'raw.req.headers.host', '');
|
||||
|
||||
let cache = new InMemoryCache();
|
||||
|
||||
if (global.__APOLLO_STATE__) {
|
||||
@ -24,7 +27,7 @@ export default (opts = {}) => {
|
||||
return new ApolloClient({
|
||||
cache,
|
||||
link: new HttpLink({
|
||||
uri: URI,
|
||||
uri: host ? `${REACT_APP_GQL_PROTOCOL}//${host}/images/graphql` : URI,
|
||||
credentials: 'same-origin',
|
||||
fetch,
|
||||
headers: {
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { canUseDOM } from 'exenv';
|
||||
import queryString from 'query-string';
|
||||
|
||||
export default (() => {
|
||||
const { NODE_ENV = 'development' } = process.env;
|
||||
|
||||
export const Global = () => {
|
||||
if (!canUseDOM) {
|
||||
return {
|
||||
protocol: NODE_ENV === 'development' ? 'http:' : 'https:',
|
||||
cookie: ''
|
||||
};
|
||||
}
|
||||
@ -11,10 +15,15 @@ export default (() => {
|
||||
port: window.location.port,
|
||||
protocol: window.location.protocol.replace(/:$/, ''),
|
||||
hostname: window.location.hostname,
|
||||
pathname: window.location.pathname,
|
||||
origin: window.location.origin,
|
||||
cookie: document.cookie || '',
|
||||
search: window.location.search,
|
||||
query: queryString.parse(window.location.search || ''),
|
||||
__REDUX_DEVTOOLS_EXTENSION__: window.__REDUX_DEVTOOLS_EXTENSION__,
|
||||
__APOLLO_STATE__: window.__APOLLO_STATE__,
|
||||
__REDUX_STATE__: window.__REDUX_STATE__
|
||||
};
|
||||
})();
|
||||
};
|
||||
|
||||
export default Global();
|
||||
|
@ -2,7 +2,7 @@ import intercept from 'apr-intercept';
|
||||
import keys from 'lodash.keys';
|
||||
import reduce from 'apr-reduce';
|
||||
import assign from 'lodash.assign';
|
||||
import yup from 'yup';
|
||||
import * as yup from 'yup';
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
"repository": "github:yldio/joyent-portal",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "NAMESPACE=instances NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3069 joyent-react-scripts start",
|
||||
"dev": "REACT_APP_DEV=1 NAMESPACE=instances NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3069 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=instances NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
@ -18,26 +18,26 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@manaflair/redux-batch": "^0.1.0",
|
||||
"apollo-cache-inmemory": "^1.1.12",
|
||||
"apollo-client": "^2.2.8",
|
||||
"apollo-link-http": "^1.5.3",
|
||||
"apollo-cache-inmemory": "^1.2.2",
|
||||
"apollo-client": "^2.3.2",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apr-intercept": "^3.0.3",
|
||||
"apr-reduce": "^3.0.3",
|
||||
"boom": "^7.2.0",
|
||||
"bytes": "^3.0.0",
|
||||
"clipboard-copy": "^2.0.0",
|
||||
"cross-fetch": "^2.1.0",
|
||||
"cross-fetch": "^2.2.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"declarative-redux-form": "^2.0.8",
|
||||
"exenv": "^1.2.2",
|
||||
"fuse.js": "^3.2.0",
|
||||
"hapi-render-react": "^2.5.2",
|
||||
"hapi-render-react-joyent-document": "^7.1.0",
|
||||
"hapi-render-react-joyent-document": "^7.2.0",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-logo-assets": "^1.1.0",
|
||||
"joyent-ui-resource-step": "^1.0.0",
|
||||
"joyent-manifest-editor": "^1.4.0",
|
||||
"joyent-react-styled-flexboxgrid": "^2.2.3",
|
||||
"joyent-react-styled-flexboxgrid": "^3.1.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
"lodash.find": "^4.6.0",
|
||||
"lodash.findindex": "^4.6.0",
|
||||
@ -56,35 +56,36 @@
|
||||
"lodash.some": "^4.6.0",
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"lodash.values": "^4.3.0",
|
||||
"mz": "^2.7.0",
|
||||
"param-case": "^2.1.1",
|
||||
"query-string": "^6.1.0",
|
||||
"react": "^16.3.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-helmet-async": "0.0.5",
|
||||
"react": "^16.4.0",
|
||||
"react-apollo": "^2.1.4",
|
||||
"react-dom": "^16.4.0",
|
||||
"react-helmet-async": "0.1.0",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-redux-values": "^1.1.2",
|
||||
"react-router": "^4.2.0",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"redux": "^3.7.2",
|
||||
"redux": "^4.0.0",
|
||||
"redux-form": "^7.3.0",
|
||||
"remcalc": "^1.0.10",
|
||||
"styled-components": "^3.2.5",
|
||||
"styled-components-spacing": "^2.1.3",
|
||||
"styled-components": "^3.3.0",
|
||||
"styled-components-spacing": "^3.0.0",
|
||||
"styled-flex-component": "^2.2.2",
|
||||
"title-case": "^2.1.1",
|
||||
"yup": "^0.24.1"
|
||||
"yup": "^0.25.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"jest-image-snapshot": "^2.4.0",
|
||||
"jest-image-snapshot": "^2.4.2",
|
||||
"jest-styled-components": "^5.0.1",
|
||||
"joyent-react-scripts": "^8.2.0",
|
||||
"joyent-react-scripts": "^8.2.1",
|
||||
"react-screenshot-renderer": "^1.1.2",
|
||||
"react-test-renderer": "^16.3.1",
|
||||
"redrun": "^6.0.2"
|
||||
"react-test-renderer": "^16.4.0",
|
||||
"redrun": "^6.0.4"
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -203,7 +203,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -326,7 +326,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -587,9 +587,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -924,7 +929,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
.c8 {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
border-radius: 50%;
|
||||
@ -933,7 +938,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
margin-left: 0rem;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
.c11 {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -1081,7 +1086,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
@ -1096,29 +1101,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.c8:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c8:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c10 {
|
||||
.c9 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
@ -1134,32 +1117,32 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.c10:not(:first-child) {
|
||||
.c9:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c10:not(:last-child) {
|
||||
.c9:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c11 {
|
||||
.c10 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
border-bottom-width: 0;
|
||||
border-left-width: 0.0625rem !important;
|
||||
}
|
||||
|
||||
.c11:not(:first-child) {
|
||||
.c10:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c11:not(:last-child) {
|
||||
.c10:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
@ -1180,7 +1163,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
}
|
||||
|
||||
@media only screen and (min-width:37.4375rem) {
|
||||
.c10 {
|
||||
.c9 {
|
||||
width: 10rem;
|
||||
display: table-cell;
|
||||
}
|
||||
@ -1232,19 +1215,19 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="c8"
|
||||
className="c1"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
/>
|
||||
<td
|
||||
className="c8"
|
||||
className="c1"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
>
|
||||
<span
|
||||
className="c9"
|
||||
className="c8"
|
||||
color={undefined}
|
||||
size="0.75rem"
|
||||
/>
|
||||
@ -1252,7 +1235,7 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
|
||||
</td>
|
||||
<td
|
||||
className="c10"
|
||||
className="c9"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
@ -1260,14 +1243,14 @@ exports[`renders <Item /> without throwing 1`] = `
|
||||
almost NaN years
|
||||
</td>
|
||||
<td
|
||||
className="c11"
|
||||
className="c10"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
>
|
||||
<div
|
||||
box={true}
|
||||
className="c12"
|
||||
className="c11"
|
||||
onClick={[Function]}
|
||||
onMouseEnter={undefined}
|
||||
onMouseLeave={undefined}
|
||||
@ -1340,7 +1323,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
.c8 {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
border-radius: 50%;
|
||||
@ -1349,7 +1332,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
margin-left: 0rem;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
.c11 {
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -1497,7 +1480,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
@ -1512,29 +1495,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.c8:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c8:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c10 {
|
||||
.c9 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
@ -1550,32 +1511,32 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.c10:not(:first-child) {
|
||||
.c9:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c10:not(:last-child) {
|
||||
.c9:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
.c11 {
|
||||
.c10 {
|
||||
border-width: 0.0625rem;
|
||||
border-style: solid;
|
||||
border-color: rgb(216,216,216);
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
border-bottom-width: 0;
|
||||
border-left-width: 0.0625rem !important;
|
||||
}
|
||||
|
||||
.c11:not(:first-child) {
|
||||
.c10:not(:first-child) {
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.c11:not(:last-child) {
|
||||
.c10:not(:last-child) {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
@ -1596,7 +1557,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
}
|
||||
|
||||
@media only screen and (min-width:37.4375rem) {
|
||||
.c10 {
|
||||
.c9 {
|
||||
width: 10rem;
|
||||
display: table-cell;
|
||||
}
|
||||
@ -1648,7 +1609,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
className="c8"
|
||||
className="c1"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
@ -1656,13 +1617,13 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
name
|
||||
</td>
|
||||
<td
|
||||
className="c8"
|
||||
className="c1"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
>
|
||||
<span
|
||||
className="c9"
|
||||
className="c8"
|
||||
color={undefined}
|
||||
size="0.75rem"
|
||||
/>
|
||||
@ -1670,7 +1631,7 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
Started
|
||||
</td>
|
||||
<td
|
||||
className="c10"
|
||||
className="c9"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
@ -1678,14 +1639,14 @@ exports[`renders <Item {...item} /> without throwing 1`] = `
|
||||
6 months
|
||||
</td>
|
||||
<td
|
||||
className="c11"
|
||||
className="c10"
|
||||
disabled={undefined}
|
||||
name="td"
|
||||
selected={undefined}
|
||||
>
|
||||
<div
|
||||
box={true}
|
||||
className="c12"
|
||||
className="c11"
|
||||
onClick={[Function]}
|
||||
onMouseEnter={undefined}
|
||||
onMouseLeave={undefined}
|
||||
@ -2146,7 +2107,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -2269,7 +2230,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -2530,9 +2491,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -3029,7 +2995,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -3152,7 +3118,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -3413,9 +3379,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -3912,7 +3883,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -3971,7 +3942,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -4296,9 +4267,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -4795,7 +4771,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -4854,7 +4830,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -5179,9 +5155,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -5678,7 +5659,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 2rem;
|
||||
display: table-cell;
|
||||
@ -5801,7 +5782,7 @@ Array [
|
||||
border-spacing: 0;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
padding: 0 0rem;
|
||||
padding: 0 1.5rem;
|
||||
height: 3.75rem;
|
||||
width: 3.75rem;
|
||||
display: table-cell;
|
||||
@ -6062,9 +6043,14 @@ Array [
|
||||
className="c4"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
|
@ -1294,6 +1294,11 @@ exports[`renders <Summary /> without throwing 1`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -2905,6 +2910,11 @@ exports[`renders <Summary instance /> without throwing 1`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -4833,6 +4843,11 @@ exports[`renders <Summary instance /> without throwing 2`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -7042,6 +7057,11 @@ exports[`renders <Summary starting stopping rebooting removing /> without throwi
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -8756,6 +8776,11 @@ exports[`renders <Summary state /> without throwing 1`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -10446,6 +10471,11 @@ exports[`renders <Summary state /> without throwing 2`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -12298,6 +12328,11 @@ exports[`renders <Summary state /> without throwing 3`] = `
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -9,7 +9,7 @@ const P = styled(BaseP)`
|
||||
|
||||
export default ({ href = '', children }) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={7}>
|
||||
<Col xs="12" sm="7">
|
||||
<P>
|
||||
{children}{' '}
|
||||
{href ? (
|
||||
|
@ -26,7 +26,7 @@ export default ({
|
||||
}) => (
|
||||
<StickyFooter fill="#FAFAFA" fixed bottom>
|
||||
<Row between="xs" middle="xs">
|
||||
<Col xs={7}>
|
||||
<Col xs="7">
|
||||
<Flex>
|
||||
{onStart && [
|
||||
<SmallOnly key="small-only">
|
||||
@ -125,7 +125,7 @@ export default ({
|
||||
</Flex>
|
||||
</Col>
|
||||
{onRemove && (
|
||||
<Col xs={5}>
|
||||
<Col xs="5">
|
||||
<SmallOnly key="small-only">
|
||||
<Button
|
||||
type="button"
|
||||
|
@ -98,8 +98,8 @@ export const Item = ({
|
||||
onClick
|
||||
}) => (
|
||||
<TableTr>
|
||||
<TableTd padding="0" paddingLeft={remcalc(12)} middle left>
|
||||
<FormGroup name={id} paddingTop={remcalc(4)} field={Field}>
|
||||
<TableTd middle left>
|
||||
<FormGroup name={id} field={Field}>
|
||||
<Checkbox noMargin />
|
||||
</FormGroup>
|
||||
</TableTd>
|
||||
@ -125,12 +125,12 @@ export const Item = ({
|
||||
<code>{id.substring(0, 7)}</code>
|
||||
</TableTd>
|
||||
{mutating ? (
|
||||
<TableTd padding="0" hasBorder="left" center middle>
|
||||
<TableTd hasBorder="left" center middle>
|
||||
<ActionsIcon disabled />
|
||||
</TableTd>
|
||||
) : (
|
||||
<PopoverContainer clickable>
|
||||
<TableTd padding="0" hasBorder="left">
|
||||
<TableTd hasBorder="left">
|
||||
<PopoverTarget box>
|
||||
<Actions alignCenter justifyCenter>
|
||||
<ActionsIcon />
|
||||
@ -149,7 +149,7 @@ export const Item = ({
|
||||
<PopoverItem disabled={!allowedActions.remove} onClick={onRemove}>
|
||||
Delete
|
||||
</PopoverItem>
|
||||
<Padding bottom={2}>
|
||||
<Padding bottom="2">
|
||||
<PopoverDivider />
|
||||
</Padding>
|
||||
<PopoverItem disabled={false} onClick={onCreateImage}>
|
||||
@ -191,8 +191,8 @@ export default ({
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="32" padding="0" paddingLeft={remcalc(12)} middle left>
|
||||
<FormGroup paddingTop={remcalc(4)}>
|
||||
<TableTh xs="32" middle left>
|
||||
<FormGroup>
|
||||
<Checkbox
|
||||
checked={allSelected}
|
||||
disabled={submitting || noInstances}
|
||||
@ -246,7 +246,7 @@ export default ({
|
||||
>
|
||||
<span>Short ID </span>
|
||||
</TableTh>
|
||||
<TableTh xs="60" padding="0" />
|
||||
<TableTh xs="60" />
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>{children}</TableTbody>
|
||||
|
@ -43,8 +43,8 @@ export const Item = ({ name, state, created, onStart, onRemove, mutating }) => (
|
||||
</TableTd>
|
||||
) : (
|
||||
<Fragment>
|
||||
<TableTd padding="0" paddingLeft={remcalc(12)} middle left>
|
||||
<FormGroup paddingTop={remcalc(4)} name={name} field={Field}>
|
||||
<TableTd middle left>
|
||||
<FormGroup name={name} field={Field}>
|
||||
<Checkbox noMargin />
|
||||
</FormGroup>
|
||||
</TableTd>
|
||||
@ -59,7 +59,7 @@ export const Item = ({ name, state, created, onStart, onRemove, mutating }) => (
|
||||
{distanceInWordsToNow(created)}
|
||||
</TableTd>
|
||||
<PopoverContainer clickable>
|
||||
<TableTd padding="0" hasBorder="left">
|
||||
<TableTd hasBorder="left">
|
||||
<PopoverTarget box>
|
||||
<ActionsIcon />
|
||||
</PopoverTarget>
|
||||
@ -111,8 +111,8 @@ export default ({
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="32" padding="0" paddingLeft={remcalc(12)} middle left>
|
||||
<FormGroup paddingTop={remcalc(4)}>
|
||||
<TableTh xs="32" middle left>
|
||||
<FormGroup>
|
||||
<Checkbox
|
||||
checked={allSelected}
|
||||
disabled={submitting}
|
||||
@ -154,7 +154,7 @@ export default ({
|
||||
>
|
||||
<span>Created </span>
|
||||
</TableTh>
|
||||
<TableTh xs="60" padding="0" />
|
||||
<TableTh xs="60" />
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
|
@ -99,7 +99,7 @@ export const Meta = ({
|
||||
...instance
|
||||
}) => [
|
||||
<Row middle="xs">
|
||||
<Col xs={12}>
|
||||
<Col xs="12">
|
||||
<Margin bottom="1">
|
||||
<H2>
|
||||
{editingName ? (
|
||||
@ -129,7 +129,7 @@ export const Meta = ({
|
||||
) : (
|
||||
<Flex>
|
||||
{instance.name}
|
||||
<Actionable left={2} onClick={editName}>
|
||||
<Actionable left="2" onClick={editName}>
|
||||
<EditIcon />
|
||||
</Actionable>
|
||||
</Flex>
|
||||
@ -187,14 +187,14 @@ export default ({
|
||||
...props
|
||||
}) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={12} md={9}>
|
||||
<Col xs="12" sm="12" md="9">
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all={5}>
|
||||
<Padding all="5">
|
||||
<Meta {...instance} {...props} />
|
||||
<Margin top="3">
|
||||
<Row between="xs">
|
||||
<Col xs={9}>
|
||||
<Col xs="9">
|
||||
<Flex>
|
||||
<FlexItem>
|
||||
<Margin right="1">
|
||||
@ -283,7 +283,7 @@ export default ({
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<Col xs="3">
|
||||
<SmallOnly>
|
||||
<Button
|
||||
type="button"
|
||||
|
@ -260,6 +260,18 @@ exports[`renders <Cns /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c16 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -371,18 +383,6 @@ exports[`renders <Cns /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c29 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -1013,6 +1013,18 @@ exports[`renders <Cns disabled /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c13 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -1037,18 +1049,6 @@ exports[`renders <Cns disabled /> without throwing 1`] = `
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
font-weight: 600;
|
||||
white-space: pre;
|
||||
@ -1669,6 +1669,18 @@ exports[`renders <Cns hostnames /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c36 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c16 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -1780,18 +1792,6 @@ exports[`renders <Cns hostnames /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c36 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c39 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -3701,6 +3701,18 @@ exports[`renders <Cns loadingError /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c30 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c21 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -3788,18 +3800,6 @@ exports[`renders <Cns loadingError /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c30 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c34 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -4511,6 +4511,18 @@ exports[`renders <Cns mutating /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c36 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c16 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -4622,18 +4634,6 @@ exports[`renders <Cns mutating /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c36 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c28 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -6356,6 +6356,18 @@ exports[`renders <Cns mutationError /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c30 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c21 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -6467,18 +6479,6 @@ exports[`renders <Cns mutationError /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c30 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c34 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -7308,6 +7308,18 @@ exports[`renders <Cns services /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c16 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -7419,18 +7431,6 @@ exports[`renders <Cns services /> without throwing 1`] = `
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c29 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -8214,6 +8214,18 @@ exports[`renders <Cns services hostnames /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c13 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -8238,18 +8250,6 @@ exports[`renders <Cns services hostnames /> without throwing 1`] = `
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
font-weight: 600;
|
||||
white-space: pre;
|
||||
|
@ -551,9 +551,14 @@ Array [
|
||||
className="c26"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -1452,9 +1457,14 @@ Array [
|
||||
className="c26"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -2301,9 +2311,14 @@ Array [
|
||||
className="c26"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -3202,9 +3217,14 @@ Array [
|
||||
className="c26"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -4681,9 +4701,14 @@ exports[`renders <Firewall loadingError /> without throwing 1`] = `
|
||||
className="c32"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -5594,9 +5619,14 @@ exports[`renders <Firewall mutationError /> without throwing 1`] = `
|
||||
className="c32"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -194,6 +194,31 @@ exports[`renders <Metadata /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -222,31 +247,6 @@ exports[`renders <Metadata /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -1139,6 +1139,44 @@ exports[`renders <Metadata addOpen /> without throwing 1`] = `
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c35 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -1195,44 +1233,6 @@ exports[`renders <Metadata addOpen /> without throwing 1`] = `
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c35 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -1995,6 +1995,31 @@ exports[`renders <Metadata error /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -2023,31 +2048,6 @@ exports[`renders <Metadata error /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -2544,6 +2544,31 @@ exports[`renders <Metadata loading /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -2572,31 +2597,6 @@ exports[`renders <Metadata loading /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -3710,6 +3710,44 @@ exports[`renders <Metadata metadata /> without throwing 1`] = `
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c35 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -3766,44 +3804,6 @@ exports[`renders <Metadata metadata /> without throwing 1`] = `
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c35 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
|
@ -246,9 +246,14 @@ exports[`renders <Networks /> without throwing 1`] = `
|
||||
className="c12"
|
||||
>
|
||||
<svg
|
||||
height={109}
|
||||
height="109"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 119.34 109.47"
|
||||
width={119}
|
||||
width="119"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlnsXlink="http://www.w3.org/1999/xlink"
|
||||
>
|
||||
@ -1642,6 +1647,11 @@ exports[`renders <Networks networks /> without throwing 1`] = `
|
||||
>
|
||||
<svg
|
||||
height="16.2"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 16.2 16.2"
|
||||
width="16.2"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -2175,6 +2185,11 @@ exports[`renders <Networks networks /> without throwing 1`] = `
|
||||
>
|
||||
<svg
|
||||
height="13"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9 13"
|
||||
width="9"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -2006,6 +2006,11 @@ exports[`renders <Summary starting stopping rebooting removing /> without throwi
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -3989,6 +3994,11 @@ exports[`renders <Summary starting stopping rebooting removing /> without throwi
|
||||
>
|
||||
<svg
|
||||
height="17.07"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(0deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 17.07 17.07"
|
||||
width="17.07"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
@ -194,6 +194,31 @@ exports[`renders <Tags /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -222,31 +247,6 @@ exports[`renders <Tags /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -1143,6 +1143,44 @@ exports[`renders <Tags addOpen /> without throwing 1`] = `
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c31 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -1249,44 +1287,6 @@ exports[`renders <Tags addOpen /> without throwing 1`] = `
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c31 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -1941,6 +1941,31 @@ exports[`renders <Tags editable /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -1969,31 +1994,6 @@ exports[`renders <Tags editable /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -2919,6 +2919,44 @@ exports[`renders <Tags editing /> without throwing 1`] = `
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c33 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -3025,44 +3063,6 @@ exports[`renders <Tags editing /> without throwing 1`] = `
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c33 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -4348,6 +4348,44 @@ exports[`renders <Tags editing.removing /> without throwing 1`] = `
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c33 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -4454,44 +4492,6 @@ exports[`renders <Tags editing.removing /> without throwing 1`] = `
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c33 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -5195,6 +5195,31 @@ exports[`renders <Tags error /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -5223,31 +5248,6 @@ exports[`renders <Tags error /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -5684,6 +5684,31 @@ exports[`renders <Tags loading /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -5712,31 +5737,6 @@ exports[`renders <Tags loading /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
@ -6156,6 +6156,31 @@ exports[`renders <Tags tags /> without throwing 1`] = `
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -6184,31 +6209,6 @@ exports[`renders <Tags tags /> without throwing 1`] = `
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: none;
|
||||
overflow: hidden;
|
||||
height: auto;
|
||||
-webkit-padding-before: 0;
|
||||
-webkit-padding-start: 0;
|
||||
-webkit-padding-end: 0;
|
||||
-webkit-padding-after: 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
box-sizing: border-box;
|
||||
width: 18.75rem;
|
||||
|
@ -61,10 +61,10 @@ const CnsContainer = ({
|
||||
</Description>
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} sm={12} md={9}>
|
||||
<Col xs="12" sm="12" md="9">
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all={5}>
|
||||
<Padding all="5">
|
||||
{loading ? <StatusLoader /> : null}
|
||||
{!loading && loadingError ? (
|
||||
<Margin bottom="5">
|
||||
|
@ -365,13 +365,13 @@ export default compose(
|
||||
handleAction: async ({ selected, name }) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (
|
||||
!(await Confirm(
|
||||
!await Confirm(
|
||||
`Do you want to ${name} ${
|
||||
selected.length === 1
|
||||
? `"${selected[0].name}"`
|
||||
: `${selected.length} instances`
|
||||
}`
|
||||
))
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ export default compose(
|
||||
'initialValues.name'
|
||||
);
|
||||
|
||||
if (!(await Confirm(`Do you want to remove "${name}"?`))) {
|
||||
if (!await Confirm(`Do you want to remove "${name}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -349,13 +349,13 @@ export default compose(
|
||||
handleAction: async ({ name, selected = [] }) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (
|
||||
!(await Confirm(
|
||||
!await Confirm(
|
||||
`Do you want to ${name} ${
|
||||
selected.length === 1
|
||||
? `"${selected[0].name}"`
|
||||
: `${selected.length} snapshots`
|
||||
}`
|
||||
))
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ export default compose(
|
||||
const { instance } = ownProps;
|
||||
const { id } = instance;
|
||||
|
||||
if (!(await Confirm(`Do you want to ${action} "${instance.name}"?`))) {
|
||||
if (!await Confirm(`Do you want to ${action} "${instance.name}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,7 +285,7 @@ export default compose(
|
||||
},
|
||||
handleRemove: async (form, { name }) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (!(await Confirm(`Do you want to remove "${name}"?`))) {
|
||||
if (!await Confirm(`Do you want to remove "${name}"?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,7 @@ import { BrowserRouter } from 'react-router-dom';
|
||||
import isFunction from 'lodash.isfunction';
|
||||
import isFinite from 'lodash.isfinite';
|
||||
|
||||
import { theme } from 'joyent-ui-toolkit';
|
||||
|
||||
import theme from '@state/theme';
|
||||
import createStore from '@state/redux-store';
|
||||
import createClient from '@state/apollo-client';
|
||||
import App from './app';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import get from 'lodash.get';
|
||||
|
||||
@ -27,6 +27,8 @@ import {
|
||||
UserScript as InstanceUserScript
|
||||
} from '@containers/instances';
|
||||
|
||||
const { REACT_APP_DEV = false } = process.env;
|
||||
|
||||
export default () => (
|
||||
<PageContainer>
|
||||
{/* Breadcrumb */}
|
||||
@ -102,6 +104,41 @@ export default () => (
|
||||
|
||||
<Route path="/" exact component={() => <Redirect to="/instances" />} />
|
||||
|
||||
{REACT_APP_DEV ? (
|
||||
<Fragment>
|
||||
<Route
|
||||
path="/images"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3070${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/templates"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3071${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/service-groups"
|
||||
component={({ location }) =>
|
||||
window.location.replace(
|
||||
`${window.location.protocol}//${window.location.hostname}:3072${
|
||||
location.pathname
|
||||
}${location.search}`
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
||||
<noscript>
|
||||
<ViewContainer main>
|
||||
<Message warning>
|
||||
|
@ -2,6 +2,7 @@ import { ApolloClient } from 'apollo-client';
|
||||
import { HttpLink } from 'apollo-link-http';
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||
import fetch from 'cross-fetch';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import global from './global';
|
||||
|
||||
@ -14,7 +15,9 @@ const {
|
||||
const PORT = REACT_APP_GQL_PORT ? `:${REACT_APP_GQL_PORT}` : '';
|
||||
const URI = `${REACT_APP_GQL_PROTOCOL}://${REACT_APP_GQL_HOSTNAME}${PORT}/instances/graphql`;
|
||||
|
||||
export default (opts = {}) => {
|
||||
export default (opts = {}, request = {}) => {
|
||||
const host = get(request, 'raw.req.headers.host', '');
|
||||
|
||||
let cache = new InMemoryCache();
|
||||
|
||||
if (global.__APOLLO_STATE__) {
|
||||
@ -24,7 +27,7 @@ export default (opts = {}) => {
|
||||
return new ApolloClient({
|
||||
cache,
|
||||
link: new HttpLink({
|
||||
uri: URI,
|
||||
uri: host ? `${REACT_APP_GQL_PROTOCOL}//${host}/instances/graphql` : URI,
|
||||
credentials: 'same-origin',
|
||||
fetch,
|
||||
headers: {
|
||||
|
@ -1,9 +1,12 @@
|
||||
import { canUseDOM } from 'exenv';
|
||||
import queryString from 'query-string';
|
||||
|
||||
const { NODE_ENV = 'development' } = process.env;
|
||||
|
||||
export const Global = () => {
|
||||
if (!canUseDOM) {
|
||||
return {
|
||||
protocol: NODE_ENV === 'development' ? 'http:' : 'https:',
|
||||
cookie: ''
|
||||
};
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import intercept from 'apr-intercept';
|
||||
import keys from 'lodash.keys';
|
||||
import reduce from 'apr-reduce';
|
||||
import assign from 'lodash.assign';
|
||||
import yup from 'yup';
|
||||
import * as yup from 'yup';
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
@ -15,16 +15,16 @@
|
||||
"build": "PREACT=1 joyent-react-scripts build"
|
||||
},
|
||||
"dependencies": {
|
||||
"apollo-cache-inmemory": "^1.1.12",
|
||||
"apollo-client": "^2.2.8",
|
||||
"apollo-link": "^1.2.1",
|
||||
"apollo-link-http": "^1.5.3",
|
||||
"apollo-cache-inmemory": "^1.2.2",
|
||||
"apollo-client": "^2.3.2",
|
||||
"apollo-link": "^1.2.2",
|
||||
"apollo-link-http": "^1.5.4",
|
||||
"apollo-link-state": "^0.4.1",
|
||||
"apr-intercept": "^3.0.3",
|
||||
"boom": "^7.2.0",
|
||||
"emotion": "^9.1.1",
|
||||
"emotion-theming": "^9.0.0",
|
||||
"graphql-tag": "^2.8.0",
|
||||
"emotion": "^9.1.3",
|
||||
"emotion-theming": "^9.1.2",
|
||||
"graphql-tag": "^2.9.2",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-icons": "^5.1.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
@ -34,20 +34,20 @@
|
||||
"mz": "^2.7.0",
|
||||
"outy": "^0.1.2",
|
||||
"pascal-case": "^2.0.1",
|
||||
"preact": "^8.2.7",
|
||||
"preact": "^8.2.9",
|
||||
"preact-compat": "^3.18.0",
|
||||
"preact-emotion": "^9.1.1",
|
||||
"preact-emotion": "^9.1.3",
|
||||
"preact-emotion-flexboxgrid": "^2.0.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-apollo": "^2.1.4",
|
||||
"remcalc": "^1.0.10",
|
||||
"stickybits": "^3.2.0"
|
||||
"stickybits": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^8.2.2",
|
||||
"babel-eslint": "^8.2.3",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"joyent-react-scripts": "^8.2.0",
|
||||
"redrun": "^6.0.2"
|
||||
"joyent-react-scripts": "^8.2.1",
|
||||
"redrun": "^6.0.4"
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ const Datacenters = ({ expanded, regions = [] }) =>
|
||||
<RegionContainer>
|
||||
<Row>
|
||||
{regions[region].map(({ name, datacenters }) => (
|
||||
<Col key={name} xs={12} md={6} lg={3}>
|
||||
<Col key={name} xs="12" md="6" lg="3">
|
||||
<DatacenterPlace>{name}</DatacenterPlace>
|
||||
{datacenters.map(({ name, url }) => (
|
||||
<Datacenter key={name}>
|
||||
|
@ -64,7 +64,7 @@ const Services = ({ expanded = false, categories = [], loading }) =>
|
||||
<Row>
|
||||
{!loading &&
|
||||
categories.map(({ name, services }) => (
|
||||
<CategoryWrapper xs={12} sm={6} md={4}>
|
||||
<CategoryWrapper xs="12" sm="6" md="4">
|
||||
<ServiceCategory>{name}</ServiceCategory>
|
||||
{services.map(({ name, description, url, tags }) => (
|
||||
<Service>
|
||||
|
12
consoles/my-joy-service-groups/.babelrc
Normal file
12
consoles/my-joy-service-groups/.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"ignore": ["_document.js", "_aliases.js"],
|
||||
"presets": [
|
||||
[
|
||||
"joyent-portal",
|
||||
{
|
||||
"aliases": true,
|
||||
"autoAliases": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
25
consoles/my-joy-service-groups/.gitignore
vendored
Normal file
25
consoles/my-joy-service-groups/.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
lib/app
|
||||
|
8
consoles/my-joy-service-groups/.lighthouserc
Normal file
8
consoles/my-joy-service-groups/.lighthouserc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"setup": {
|
||||
"compile": "npm run build",
|
||||
"start": "serve -s build --port 3069 --single",
|
||||
"href": "http://0.0.0.0:3069"
|
||||
},
|
||||
"extends": "lighthouse:default"
|
||||
}
|
27
consoles/my-joy-service-groups/.npmignore
Normal file
27
consoles/my-joy-service-groups/.npmignore
Normal file
@ -0,0 +1,27 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
!lib/app
|
||||
!dist
|
||||
!build
|
||||
|
4
consoles/my-joy-service-groups/.stylelintrc
Normal file
4
consoles/my-joy-service-groups/.stylelintrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"test": ["./src/**/*.js"],
|
||||
"extends": ["stylelint-config-joyent-portal"]
|
||||
}
|
13
consoles/my-joy-service-groups/.tern-project
Normal file
13
consoles/my-joy-service-groups/.tern-project
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"libs": ["ecmascript", "browser"],
|
||||
"plugins": {
|
||||
"doc_comment": true,
|
||||
"local-scope": true,
|
||||
"jsx": true,
|
||||
"node": true,
|
||||
"webpack": {
|
||||
"configPath":
|
||||
"../../node_modules/joyent-react-scripts/src/webpack.config.dev.js"
|
||||
}
|
||||
}
|
||||
}
|
0
consoles/my-joy-service-groups/.yarnclean
Normal file
0
consoles/my-joy-service-groups/.yarnclean
Normal file
133
consoles/my-joy-service-groups/lib/index.js
Normal file
133
consoles/my-joy-service-groups/lib/index.js
Normal file
@ -0,0 +1,133 @@
|
||||
const Boom = require('boom');
|
||||
const Inert = require('inert');
|
||||
const Path = require('path');
|
||||
const RenderReact = require('hapi-render-react');
|
||||
const Intercept = require('apr-intercept');
|
||||
const Fs = require('mz/fs');
|
||||
|
||||
const { NAMESPACE = 'service-groups', NODE_ENV = 'development' } = process.env;
|
||||
|
||||
exports.register = async server => {
|
||||
let manifest = {};
|
||||
|
||||
try {
|
||||
manifest = require('../build/asset-manifest.json');
|
||||
} catch (err) {
|
||||
if (NODE_ENV === 'production') {
|
||||
throw err;
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
const relativeTo = Path.join(__dirname, 'app');
|
||||
const buildRoot = Path.join(__dirname, '../build');
|
||||
const buildStatic = Path.join(buildRoot, `${NAMESPACE}`);
|
||||
const publicRoot = Path.join(__dirname, `../public/static/`);
|
||||
|
||||
await server.register([
|
||||
{
|
||||
plugin: Inert
|
||||
},
|
||||
{
|
||||
plugin: RenderReact
|
||||
}
|
||||
]);
|
||||
|
||||
server.route([
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/service-worker.js`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/service-worker.js')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/favicon.ico`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/favicon.ico')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/static/{rest*}`,
|
||||
config: {
|
||||
auth: false
|
||||
},
|
||||
handler: async (request, h) => {
|
||||
const { params } = request;
|
||||
const { rest } = params;
|
||||
|
||||
if (!rest) {
|
||||
return Boom.notFound();
|
||||
}
|
||||
|
||||
const publicPathname = Path.join(publicRoot, rest);
|
||||
const [err1] = await Intercept(
|
||||
Fs.access(publicPathname, Fs.constants.R_OK)
|
||||
);
|
||||
|
||||
if (!err1) {
|
||||
return h.file(publicPathname, {
|
||||
confine: publicRoot
|
||||
});
|
||||
}
|
||||
|
||||
const buildPathname = Path.join(buildStatic, 'static', rest);
|
||||
const [err2] = await Intercept(
|
||||
Fs.access(buildPathname, Fs.constants.R_OK)
|
||||
);
|
||||
|
||||
if (!err2) {
|
||||
return h.file(buildPathname, {
|
||||
confine: buildStatic
|
||||
});
|
||||
}
|
||||
|
||||
const filename = manifest[rest];
|
||||
if (!filename) {
|
||||
return Boom.notFound();
|
||||
}
|
||||
|
||||
const buildMapPathname = Path.join(buildRoot, filename);
|
||||
return h.file(buildMapPathname, {
|
||||
confine: buildStatic
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/~server-error`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'server-error',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/{path*}`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'app',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
exports.pkg = require('../package.json');
|
73
consoles/my-joy-service-groups/package.json
Normal file
73
consoles/my-joy-service-groups/package.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "my-joy-service-groups",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MPL-2.0",
|
||||
"repository": "github:yldio/joyent-portal",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "REACT_APP_DEV=1 NAMESPACE=service-groups NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3072 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=service-groups NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"test": "DEFAULT_TIMEOUT_INTERVAL=100000 NODE_ENV=test joyent-react-scripts test --env=jsdom",
|
||||
"test:ci": "NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
"build:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files"
|
||||
},
|
||||
"dependencies": {
|
||||
"@manaflair/redux-batch": "^0.1.0",
|
||||
"apr-intercept": "^3.0.3",
|
||||
"boom": "^7.2.0",
|
||||
"cross-fetch": "^2.2.0",
|
||||
"date-fns": "^1.29.0",
|
||||
"declarative-redux-form": "^2.0.8",
|
||||
"exenv": "^1.2.2",
|
||||
"fuse.js": "^3.2.0",
|
||||
"hapi-render-react": "^2.5.2",
|
||||
"hapi-render-react-joyent-document": "^7.2.0",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-react-styled-flexboxgrid": "^3.1.0",
|
||||
"joyent-ui-resource-widgets": "^1.0.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"lodash.find": "^4.6.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"lodash.isstring": "^4.0.1",
|
||||
"lodash.keys": "^4.2.0",
|
||||
"lodash.reverse": "^4.0.1",
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"mz": "^2.7.0",
|
||||
"param-case": "^2.1.1",
|
||||
"plur": "^3.0.1",
|
||||
"query-string": "^6.1.0",
|
||||
"react": "^16.4.0",
|
||||
"react-apollo": "^2.1.4",
|
||||
"react-dom": "^16.4.0",
|
||||
"react-helmet-async": "0.1.0",
|
||||
"react-if": "^2.2.2",
|
||||
"react-redux": "^5.0.7",
|
||||
"react-redux-values": "^1.1.2",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"redux": "^4.0.0",
|
||||
"redux-form": "^7.3.0",
|
||||
"remcalc": "^1.0.10",
|
||||
"styled-components": "^3.3.0",
|
||||
"styled-components-spacing": "^3.0.0",
|
||||
"styled-flex-component": "^2.2.2",
|
||||
"yup": "^0.25.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"jest-image-snapshot": "^2.4.2",
|
||||
"jest-styled-components": "^5.0.1",
|
||||
"joyent-react-scripts": "^8.2.1",
|
||||
"react-screenshot-renderer": "^1.1.2",
|
||||
"react-test-renderer": "^16.4.0",
|
||||
"redrun": "^6.0.4"
|
||||
}
|
||||
}
|
15
consoles/my-joy-service-groups/public/manifest.json
Normal file
15
consoles/my-joy-service-groups/public/manifest.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "Joyent",
|
||||
"name": "My Joyent β",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#1E313B",
|
||||
"background_color": "#FAFAFA"
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Libre Franklin'), local('LibreFranklin-Regular'),
|
||||
url(../fonts/libre-franklin/libre-franklin-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Libre Franklin Medium'), local('LibreFranklin-Medium'),
|
||||
url(../fonts/libre-franklin/libre-franklin-medium.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Libre Franklin SemiBold'), local('LibreFranklin-SemiBold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-semibold.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Libre Franklin Bold'), local('LibreFranklin-Bold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-bold.ttf) format('truetype');
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto Mono'), local('RobotoMono-Regular'),
|
||||
url(../fonts/roboto-mono/roboto-mono-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Mono Bold'), local('RobotoMono-Bold'),
|
||||
url(../fonts/roboto-mono/roboto-mono-bold.ttf) format('truetype');
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,93 @@
|
||||
Copyright (c) 2015, Impallari Type (www.impallari.com)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
202
consoles/my-joy-service-groups/public/static/fonts/roboto-mono/license.txt
Executable file
202
consoles/my-joy-service-groups/public/static/fonts/roboto-mono/license.txt
Executable file
@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
Binary file not shown.
Binary file not shown.
20
consoles/my-joy-service-groups/readme.md
Normal file
20
consoles/my-joy-service-groups/readme.md
Normal file
@ -0,0 +1,20 @@
|
||||
# my-joy-service-groups
|
||||
|
||||
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg?style=flat-square)](https://opensource.org/licenses/MPL-2.0)
|
||||
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Usage](#usage)
|
||||
* [License](#license)
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
npm run start
|
||||
open http://0.0.0.0:3069
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MPL-2.0
|
9
consoles/my-joy-service-groups/src/_aliases.js
Normal file
9
consoles/my-joy-service-groups/src/_aliases.js
Normal file
@ -0,0 +1,9 @@
|
||||
const { SSR } = process.env;
|
||||
|
||||
const aliases = {};
|
||||
|
||||
if (SSR) {
|
||||
aliases['^joyent-ui-toolkit/dist/es/editor$'] = './src/mocks/editor';
|
||||
}
|
||||
|
||||
module.exports = aliases;
|
54
consoles/my-joy-service-groups/src/_document.js
Normal file
54
consoles/my-joy-service-groups/src/_document.js
Normal file
@ -0,0 +1,54 @@
|
||||
const get = require('lodash.get');
|
||||
const Document = require('hapi-render-react-joyent-document');
|
||||
const url = require('url');
|
||||
|
||||
const { theme } = require('joyent-ui-toolkit');
|
||||
const { default: createClient } = require('./state/apollo-client');
|
||||
const { default: createStore } = require('./state/redux-store');
|
||||
|
||||
const assets = require('../../build/asset-manifest.json');
|
||||
|
||||
const { NODE_ENV = 'development' } = process.env;
|
||||
|
||||
const getState = request => {
|
||||
const { req } = request.raw;
|
||||
const { headers } = req;
|
||||
const { host } = headers;
|
||||
|
||||
const protocol = NODE_ENV === 'development' ? 'http:' : 'https:';
|
||||
const _font = get(theme, 'font.href', () => '');
|
||||
const _mono = get(theme, 'monoFont.href', () => '');
|
||||
const _addr = url.parse(`${protocol}//${host}`);
|
||||
|
||||
const _theme = Object.assign({}, theme, {
|
||||
font: Object.assign({}, theme.font, {
|
||||
href: () =>
|
||||
_font(
|
||||
Object.assign(_addr, {
|
||||
namespace: 'service-groups'
|
||||
})
|
||||
)
|
||||
}),
|
||||
monoFont: Object.assign({}, theme.monoFont, {
|
||||
href: () =>
|
||||
_mono(
|
||||
Object.assign(_addr, {
|
||||
namespace: 'service-groups'
|
||||
})
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
theme: _theme,
|
||||
createClient,
|
||||
createStore
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Document({
|
||||
namespace: 'service-groups/',
|
||||
assets,
|
||||
Html: require('./html'),
|
||||
getState
|
||||
});
|
14
consoles/my-joy-service-groups/src/app.js
Normal file
14
consoles/my-joy-service-groups/src/app.js
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet-async';
|
||||
|
||||
import { RootContainer } from 'joyent-ui-toolkit';
|
||||
import Routes from '@root/routes';
|
||||
|
||||
export default () => (
|
||||
<RootContainer>
|
||||
<Helmet>
|
||||
<title>Service Groups</title>
|
||||
</Helmet>
|
||||
<Routes />
|
||||
</RootContainer>
|
||||
);
|
251
consoles/my-joy-service-groups/src/components/list.js
Normal file
251
consoles/my-joy-service-groups/src/components/list.js
Normal file
@ -0,0 +1,251 @@
|
||||
import React from 'react';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import styled from 'styled-components';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Field } from 'redux-form';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardOutlet,
|
||||
Anchor,
|
||||
Button,
|
||||
H3,
|
||||
P,
|
||||
FormGroup,
|
||||
Checkbox,
|
||||
Table,
|
||||
TableThead,
|
||||
TableTr,
|
||||
TableTh,
|
||||
TableTd,
|
||||
TableTbody,
|
||||
StickyFooter,
|
||||
StatusLoader,
|
||||
DeleteIcon,
|
||||
EmptyStateIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const A = styled(Anchor)`
|
||||
color: ${props => props.theme.text};
|
||||
text-decoration: none;
|
||||
font-weight: ${props => props.theme.font.weight.semibold};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
`;
|
||||
|
||||
export const BulkFooter = ({ items = [], onRemove }) => {
|
||||
const disabled = items.some(({ removing }) => removing);
|
||||
|
||||
return (
|
||||
<StickyFooter fill="disabled" fixed bottom>
|
||||
<Row between="xs" middle="xs">
|
||||
<Col xs="7">
|
||||
<Flex>
|
||||
<Margin right="1">
|
||||
<Button
|
||||
type="button"
|
||||
component={Link}
|
||||
to={`/service-groups/~edit/${items[0].id}/name`}
|
||||
disabled={disabled || items.length > 1}
|
||||
icon
|
||||
>
|
||||
<span>Edit Service Group</span>
|
||||
</Button>
|
||||
</Margin>
|
||||
<Button
|
||||
type="button"
|
||||
component={Link}
|
||||
to={`/instances?sg=${items[0].id}`}
|
||||
disabled={disabled || items.length > 1}
|
||||
secondary
|
||||
icon
|
||||
>
|
||||
<span>View instances</span>
|
||||
</Button>
|
||||
</Flex>
|
||||
</Col>
|
||||
<Col xs="5">
|
||||
<Flex justifyEnd alignCenter>
|
||||
<FlexItem>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={ev => onRemove(ev, items)}
|
||||
disabled={disabled}
|
||||
error
|
||||
secondary
|
||||
icon
|
||||
>
|
||||
<Margin right="1">
|
||||
<DeleteIcon fill={disabled ? 'grey' : 'red'} />
|
||||
</Margin>
|
||||
<span>Remove</span>
|
||||
</Button>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Col>
|
||||
</Row>
|
||||
</StickyFooter>
|
||||
);
|
||||
};
|
||||
|
||||
export const LoadingRow = ({ children }) => (
|
||||
<TableTr colSpan="5">
|
||||
<TableTd colSpan="5" middle center>
|
||||
<Margin vertical="5">
|
||||
<StatusLoader>{children}</StatusLoader>
|
||||
</Margin>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export const EmptyCard = () => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Row center="xs">
|
||||
<Col xs="12" sm="9" md="8" lg="6">
|
||||
<Padding all="5">
|
||||
<Margin bottom="3">
|
||||
<EmptyStateIcon />
|
||||
</Margin>
|
||||
<Margin bottom="2">
|
||||
<H3 bold>No service groups found</H3>
|
||||
</Margin>
|
||||
<P>You can create a new service group with the below button.</P>
|
||||
<Margin top="3">
|
||||
<Button
|
||||
type="button"
|
||||
component={Link}
|
||||
to="/service-groups/~create/template"
|
||||
>
|
||||
Create service group
|
||||
</Button>
|
||||
</Margin>
|
||||
</Padding>
|
||||
</Col>
|
||||
</Row>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
);
|
||||
|
||||
export const EmptyRow = () => (
|
||||
<TableTr colSpan="5">
|
||||
<TableTd colSpan="5" middle center>
|
||||
<Padding vertical="4">
|
||||
<P>You have no service groups that match your query</P>
|
||||
</Padding>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export const Item = ({
|
||||
id = '',
|
||||
name,
|
||||
capacity,
|
||||
template,
|
||||
created,
|
||||
...group
|
||||
}) => (
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<FormGroup name={id} field={Field}>
|
||||
<Checkbox noMargin />
|
||||
</FormGroup>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<A to={`/service-groups/${id}`} component={Link}>
|
||||
{name}
|
||||
</A>
|
||||
</TableTd>
|
||||
<TableTd xs="0" sm="120" middle left>
|
||||
{capacity}
|
||||
</TableTd>
|
||||
<TableTd xs="0" sm="180" middle left>
|
||||
{template.name}
|
||||
</TableTd>
|
||||
<TableTd xs="0" sm="180" middle left>
|
||||
{distanceInWordsToNow(created)}
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export default ({
|
||||
sortBy = 'name',
|
||||
sortOrder = 'desc',
|
||||
submitting = false,
|
||||
checked = false,
|
||||
onToggleCheckAll = () => null,
|
||||
onSortBy = () => null,
|
||||
children
|
||||
}) => (
|
||||
<form>
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="42" middle left>
|
||||
<FormGroup>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
disabled={submitting}
|
||||
onChange={onToggleCheckAll}
|
||||
noMargin
|
||||
/>
|
||||
</FormGroup>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'name'}
|
||||
onClick={() => onSortBy('name')}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Name</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'capacity'}
|
||||
onClick={() => onSortBy('capacity')}
|
||||
xs="0"
|
||||
sm="120"
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Desired #</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'template'}
|
||||
onClick={() => onSortBy('template')}
|
||||
xs="0"
|
||||
sm="180"
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Template</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'created'}
|
||||
onClick={() => onSortBy('created')}
|
||||
xs="0"
|
||||
sm="180"
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Created</span>
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>{children}</TableTbody>
|
||||
</Table>
|
||||
</form>
|
||||
);
|
367
consoles/my-joy-service-groups/src/components/summary.js
Normal file
367
consoles/my-joy-service-groups/src/components/summary.js
Normal file
@ -0,0 +1,367 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import { Padding, Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import styled from 'styled-components';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardOutlet,
|
||||
H2,
|
||||
H3,
|
||||
P,
|
||||
Label,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
Checkbox,
|
||||
Anchor,
|
||||
Button,
|
||||
Hr,
|
||||
Table,
|
||||
TableThead,
|
||||
TableTbody,
|
||||
PaginationTableFoot,
|
||||
PaginationItem,
|
||||
TableTr,
|
||||
TableTh,
|
||||
TableTd,
|
||||
DeleteIcon,
|
||||
ArrowIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const GreyLabel = styled(Label)`
|
||||
opacity: 0.5;
|
||||
padding-right: ${remcalc(3)};
|
||||
`;
|
||||
|
||||
const VerticalDivider = styled.div`
|
||||
width: ${remcalc(1)};
|
||||
background: ${props => props.theme.grey};
|
||||
height: ${remcalc(24)};
|
||||
display: flex;
|
||||
align-self: flex-end;
|
||||
margin: 0 ${remcalc(12)};
|
||||
`;
|
||||
|
||||
export const Meta = ({
|
||||
id,
|
||||
name,
|
||||
capacity,
|
||||
template,
|
||||
created,
|
||||
updated,
|
||||
status,
|
||||
onRemove,
|
||||
removing = false
|
||||
}) => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all="5">
|
||||
<H2>{name}</H2>
|
||||
<Margin top="2">
|
||||
<P>{capacity} desired instances</P>
|
||||
</Margin>
|
||||
<Margin top="3" bottom="3">
|
||||
<Hr />
|
||||
</Margin>
|
||||
<Margin bottom="3">
|
||||
<Flex>
|
||||
<FlexItem>
|
||||
<Padding right="3">
|
||||
<GreyLabel inline>Template: </GreyLabel>
|
||||
<Label inline>
|
||||
{' '}
|
||||
<Anchor
|
||||
to={`/templates/${template.id}`}
|
||||
component={Link}
|
||||
tertiary
|
||||
>
|
||||
{template.name}
|
||||
</Anchor>
|
||||
</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<VerticalDivider />
|
||||
<FlexItem>
|
||||
<Padding right="3">
|
||||
<GreyLabel inline>Created: </GreyLabel>
|
||||
<Label inline> {distanceInWordsToNow(created)} ago</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<VerticalDivider />
|
||||
<FlexItem>
|
||||
<Padding horizontal="3">
|
||||
<GreyLabel inline>Updated: </GreyLabel>
|
||||
<Label inline> {distanceInWordsToNow(updated)} ago</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Row between="xs">
|
||||
<Col xs="6">
|
||||
<Margin right="1" inline>
|
||||
<Button
|
||||
type="button"
|
||||
to={`/service-groups/~edit/${id}/name`}
|
||||
component={Link}
|
||||
bold
|
||||
icon
|
||||
>
|
||||
<span>Edit Service Group</span>
|
||||
</Button>
|
||||
</Margin>
|
||||
<Button
|
||||
type="button"
|
||||
to={`/instances?sg=${id}`}
|
||||
component={Link}
|
||||
secondary
|
||||
bold
|
||||
icon
|
||||
>
|
||||
<span>View instances</span>
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs="6">
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onRemove}
|
||||
loading={removing}
|
||||
secondary
|
||||
bold
|
||||
right
|
||||
icon
|
||||
error
|
||||
>
|
||||
<Margin right="2">
|
||||
<DeleteIcon fill="red" />
|
||||
</Margin>
|
||||
<span>Remove</span>
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Padding>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
);
|
||||
|
||||
export const EventLogContainer = () => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all="5">
|
||||
<H3>Event log</H3>
|
||||
<Margin top="5" bottom="3">
|
||||
<Flex justifyBetween alignEnd>
|
||||
<FormGroup name="filter">
|
||||
<Margin bottom="0.5">
|
||||
<FormLabel>Filter</FormLabel>
|
||||
</Margin>
|
||||
<Flex alignCenter>
|
||||
<FlexItem>
|
||||
<Margin right="5">
|
||||
<Input />
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<FormGroup>
|
||||
<Margin right="3">
|
||||
<Checkbox>
|
||||
<Margin left="2">
|
||||
<Label>Show census checks</Label>
|
||||
</Margin>
|
||||
</Checkbox>
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<FormGroup>
|
||||
<Margin right="3">
|
||||
<Checkbox>
|
||||
<Margin left="2">
|
||||
<Label>Show users activity</Label>
|
||||
</Margin>
|
||||
</Checkbox>
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</FormGroup>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Margin bottom="5">
|
||||
<Hr />
|
||||
</Margin>
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="200" left middle actionable>
|
||||
<span>Time & date</span>
|
||||
</TableTh>
|
||||
<TableTh left middle actionable>
|
||||
<span>Log description</span>
|
||||
</TableTh>
|
||||
<TableTh xs="230" left middle actionable>
|
||||
<span>Actor ID</span>
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:52 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>5 of 5 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census check</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:50 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Destroying instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:45 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>10 of 5 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:17 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>‘Desired instances’ set to 5</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>raoulmillais</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr disabled>
|
||||
<TableTd colSpan="3" middle left shrinken>
|
||||
<Anchor>
|
||||
Show hidden actions (63) <ArrowIcon fill="primary" />
|
||||
</Anchor>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:16 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Provisioning instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:16 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>7 of 10 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:11 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>10 of 10 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:11 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Provisioning instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:10 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>0 of 10 instance running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:09 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Job working</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:51 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Job submission</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:08 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Service group deployed</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>raoulmillais</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
</TableTbody>
|
||||
<PaginationTableFoot colSpan="3">
|
||||
<PaginationItem to="" component={Link} disabled prev>
|
||||
Prev
|
||||
</PaginationItem>
|
||||
<PaginationItem to="" component={Link} active>
|
||||
1
|
||||
</PaginationItem>
|
||||
<PaginationItem to="" component={Link} disabled next>
|
||||
Next
|
||||
</PaginationItem>
|
||||
</PaginationTableFoot>
|
||||
</Table>
|
||||
</Padding>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
);
|
175
consoles/my-joy-service-groups/src/components/templates.js
Normal file
175
consoles/my-joy-service-groups/src/components/templates.js
Normal file
@ -0,0 +1,175 @@
|
||||
import React from 'react';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import styled from 'styled-components';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Field } from 'redux-form';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardOutlet,
|
||||
H4,
|
||||
P,
|
||||
Button,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Radio,
|
||||
StatusLoader,
|
||||
Table,
|
||||
TableThead,
|
||||
TableTr,
|
||||
TableTh,
|
||||
TableTd,
|
||||
TableTbody,
|
||||
ExternalIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const Name = styled.span`
|
||||
color: ${props => props.theme.text};
|
||||
text-decoration: none;
|
||||
font-weight: ${props => props.theme.font.weight.semibold};
|
||||
`;
|
||||
|
||||
export const EmptyCard = () => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Row center="xs">
|
||||
<Col xs="12" sm="9" md="8" lg="6">
|
||||
<Padding all="5">
|
||||
<H4 bold>No templates found</H4>
|
||||
<P>
|
||||
In order to deploy a Service Group, you’ll need to first create a
|
||||
template to base your instances off of. Click below to continue
|
||||
</P>
|
||||
<Margin top="3">
|
||||
<Button
|
||||
type="button"
|
||||
component={Link}
|
||||
to="/templates/~create/name"
|
||||
secondary
|
||||
icon
|
||||
>
|
||||
<Margin right="2">
|
||||
<ExternalIcon />
|
||||
</Margin>
|
||||
<span>Create template</span>
|
||||
</Button>
|
||||
</Margin>
|
||||
</Padding>
|
||||
</Col>
|
||||
</Row>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
);
|
||||
|
||||
export const EmptyRow = () => (
|
||||
<TableTr colSpan="5">
|
||||
<TableTd colSpan="5" middle center>
|
||||
<Padding vertical="4">
|
||||
<P>You have no templates that match your query</P>
|
||||
</Padding>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export const LoadingRow = ({ children }) => (
|
||||
<TableTr colSpan="5">
|
||||
<TableTd colSpan="5" middle center>
|
||||
<Margin vertical="5">
|
||||
<StatusLoader>{children}</StatusLoader>
|
||||
</Margin>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export const Item = ({ id = '', name, image, created, ...template }) => (
|
||||
<TableTr>
|
||||
<TableTd colSpan="2" middle left>
|
||||
<FormGroup name="template" value={id} type="radio" field={Field}>
|
||||
<Radio onBlur={null} noMargin>
|
||||
<Margin left="5">
|
||||
<FormLabel noMargin actionable>
|
||||
<Name>{name}</Name>
|
||||
</FormLabel>
|
||||
</Margin>
|
||||
</Radio>
|
||||
</FormGroup>
|
||||
</TableTd>
|
||||
<TableTd xs="0" sm="160" middle left>
|
||||
{image.substring(0, 7)}
|
||||
</TableTd>
|
||||
<TableTd xs="0" sm="160" middle left>
|
||||
{template.package.substring(0, 7)}
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
{distanceInWordsToNow(created)}
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export default ({
|
||||
sortBy = 'name',
|
||||
sortOrder = 'desc',
|
||||
submitting = false,
|
||||
checked = false,
|
||||
onToggleCheckAll = () => null,
|
||||
onSortBy = () => null,
|
||||
children
|
||||
}) => (
|
||||
<form>
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="42" middle left />
|
||||
<TableTh
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'name'}
|
||||
onClick={() => onSortBy('name')}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Name</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="0"
|
||||
sm="160"
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'image'}
|
||||
onClick={() => onSortBy('image')}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Image</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="0"
|
||||
sm="160"
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'package'}
|
||||
onClick={() => onSortBy('package')}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Package</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="180"
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'created'}
|
||||
onClick={() => onSortBy('created')}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Created</span>
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>{children}</TableTbody>
|
||||
</Table>
|
||||
</form>
|
||||
);
|
49
consoles/my-joy-service-groups/src/components/toolbar.js
Normal file
49
consoles/my-joy-service-groups/src/components/toolbar.js
Normal file
@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import Flex from 'styled-flex-component';
|
||||
import { If, Then } from 'react-if';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Field } from 'redux-form';
|
||||
|
||||
import { FormGroup, Input, FormLabel, Button } from 'joyent-ui-toolkit';
|
||||
|
||||
export const Toolbar = ({
|
||||
searchLabel = 'Filter',
|
||||
searchPlaceholder = '',
|
||||
searchable = true,
|
||||
actionLabel = 'Create',
|
||||
actionable = true,
|
||||
onActionClick,
|
||||
actionTo
|
||||
}) => (
|
||||
<Flex justifyBetween alignEnd>
|
||||
<FormGroup name="filter" field={Field}>
|
||||
<FormLabel>{searchLabel}</FormLabel>
|
||||
<Margin top="0.5">
|
||||
<Input placeholder={searchPlaceholder} disabled={!searchable} />
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
<If condition={actionable}>
|
||||
<Then>
|
||||
<FormGroup right>
|
||||
<Button
|
||||
type={actionTo || onActionClick ? 'button' : 'submit'}
|
||||
component={actionTo ? Link : undefined}
|
||||
to={actionTo}
|
||||
onClick={onActionClick}
|
||||
icon
|
||||
fluid
|
||||
>
|
||||
{actionLabel}
|
||||
</Button>
|
||||
</FormGroup>
|
||||
</Then>
|
||||
</If>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export default ({ handleSubmit, ...rest }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Toolbar {...rest} />
|
||||
</form>
|
||||
);
|
23
consoles/my-joy-service-groups/src/constants.js
Normal file
23
consoles/my-joy-service-groups/src/constants.js
Normal file
@ -0,0 +1,23 @@
|
||||
export const Forms = {
|
||||
SGC_F: 'SERVICE_GROUP_CREATE_FORM',
|
||||
SGC_T_F: 'SERVICE_GROUP_CREATE_TEMPLATE_FORM',
|
||||
SGC_F_F: 'SERVICE_GROUP_CREATE_FILTER_FORM',
|
||||
SGC_N_F: 'SERVICE_GROUP_CREATE_NAME_FORM',
|
||||
SGE_F: 'SERVICE_GROUP_EDIT_FORM',
|
||||
SGL_F_F: 'SERVICE_GROUP_LIST_FILTER_FORM',
|
||||
SGL_T_F: 'SERVICE_GROUP_LIST_TABLE_FORM'
|
||||
};
|
||||
|
||||
export const Values = {
|
||||
SGC_N_V: 'SERVICE_GROUP_CREATE_NAME_VALUE',
|
||||
SGC_T_V: 'SERVICE_GROUP_CREATE_TEMPLATE_VALUE',
|
||||
SGE_N_V: 'SERVICE_GROUP_EDIT_NAME_VALUE',
|
||||
SGC_T_SB_V: 'SERVICE_GROUP_CREATE_TEMPLATE_SORT_BY_VALUE',
|
||||
SGC_T_SO_V: 'SERVICE_GROUP_CREATE_TEMPLATE_SORT_ORDER_VALUE',
|
||||
SGL_R_V: id => `SERVICE_GROUP_LIST_REMOVING_VALUE-${id}`,
|
||||
SGL_E_V: 'SERVICE_GROUP_LIST_ERROR_VALUE',
|
||||
SGL_SB_V: 'SERVICE_GROUP_LIST_SORT_BY_VALUE',
|
||||
SGL_SO_V: 'SERVICE_GROUP_LIST_SORT_ORDER_VALUE',
|
||||
SGS_R_V: id => `SERVICE_GROUP_SUMMARY_REMOVING_VALUE-${id}`,
|
||||
SGS_E_V: id => `SERVICE_GROUP_SUMMARY_ERROR_VALUE-${id}`
|
||||
};
|
@ -0,0 +1,503 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders <Breadcrumb /> without throwing 1`] = `
|
||||
.c11 {
|
||||
margin-left: 0.375rem;
|
||||
margin-right: 0.375rem;
|
||||
margin-top: 1.125rem;
|
||||
margin-bottom: 1.125rem;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: 1.875rem;
|
||||
padding-left: 1.875rem;
|
||||
}
|
||||
|
||||
.c5 {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.c6 {
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex: 1 1 auto;
|
||||
-ms-flex: 1 1 auto;
|
||||
flex: 1 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.625rem;
|
||||
margin-left: -0.625rem;
|
||||
}
|
||||
|
||||
.c7 {
|
||||
box-sizing: border-box;
|
||||
-webkit-flex: 0 0 auto;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
padding-right: 0.625rem;
|
||||
padding-left: 0.625rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c1 {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 78.75rem;
|
||||
}
|
||||
|
||||
.c10 {
|
||||
margin: 0;
|
||||
color: rgb(73,73,73);
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c8:first-child a {
|
||||
color: inherit;
|
||||
-webkit-text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.c8:last-child svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.c0 {
|
||||
border-bottom: 0.0625rem solid rgb(216,216,216);
|
||||
}
|
||||
|
||||
@media only screen and (min-width:48em) {
|
||||
.c5 {
|
||||
width: 46rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:64em) {
|
||||
.c5 {
|
||||
width: 56rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:75em) {
|
||||
.c5 {
|
||||
width: 59rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:0em) {
|
||||
.c7 {
|
||||
-webkit-flex-basis: 100%;
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width:37.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:37.5rem) and (max-width:62.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 1.875rem;
|
||||
padding-right: 1.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:62.5rem) and (max-width:87.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 4.375rem;
|
||||
padding-right: 4.375rem;
|
||||
}
|
||||
}
|
||||
|
||||
<div
|
||||
className="c0 c1 c2"
|
||||
>
|
||||
<div
|
||||
className="c3"
|
||||
>
|
||||
<div
|
||||
className="c4 c5"
|
||||
>
|
||||
<div
|
||||
className="c6"
|
||||
name="breadcrum"
|
||||
>
|
||||
<div
|
||||
className="c7"
|
||||
>
|
||||
<div
|
||||
className="c8"
|
||||
>
|
||||
<h4
|
||||
className="c9 c10"
|
||||
name="breadcrum-item"
|
||||
>
|
||||
<div
|
||||
className="c11"
|
||||
>
|
||||
Compute
|
||||
</div>
|
||||
</h4>
|
||||
<svg
|
||||
height="6"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(-90deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9.6 6"
|
||||
width="9.6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.6,1.12,8.24,0,4.8,3.5,1.36,0,0,1.12,4.8,6Z"
|
||||
fill="rgb(151, 151, 151)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
className="c8"
|
||||
>
|
||||
<h4
|
||||
className="c9 c10"
|
||||
name="breadcrum-item"
|
||||
>
|
||||
<div
|
||||
className="c11"
|
||||
>
|
||||
Service Groups
|
||||
</div>
|
||||
</h4>
|
||||
<svg
|
||||
height="6"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(-90deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9.6 6"
|
||||
width="9.6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.6,1.12,8.24,0,4.8,3.5,1.36,0,0,1.12,4.8,6Z"
|
||||
fill="rgb(151, 151, 151)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders <Breadcrumb match /> without throwing 1`] = `
|
||||
.c11 {
|
||||
margin-left: 0.375rem;
|
||||
margin-right: 0.375rem;
|
||||
margin-top: 1.125rem;
|
||||
margin-bottom: 1.125rem;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
padding-top: 0.375rem;
|
||||
padding-bottom: 0.375rem;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
padding-right: 1.875rem;
|
||||
padding-left: 1.875rem;
|
||||
}
|
||||
|
||||
.c5 {
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.c6 {
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex: 1 1 auto;
|
||||
-ms-flex: 1 1 auto;
|
||||
flex: 1 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.625rem;
|
||||
margin-left: -0.625rem;
|
||||
}
|
||||
|
||||
.c7 {
|
||||
box-sizing: border-box;
|
||||
-webkit-flex: 0 0 auto;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex: 0 0 auto;
|
||||
padding-right: 0.625rem;
|
||||
padding-left: 0.625rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.c1 {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
max-width: 78.75rem;
|
||||
}
|
||||
|
||||
.c10 {
|
||||
margin: 0;
|
||||
color: rgb(73,73,73);
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
display: -webkit-inline-box;
|
||||
display: -webkit-inline-flex;
|
||||
display: -ms-inline-flexbox;
|
||||
display: inline-flex;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c8:first-child a {
|
||||
color: inherit;
|
||||
-webkit-text-decoration: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.c8:last-child svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.c0 {
|
||||
border-bottom: 0.0625rem solid rgb(216,216,216);
|
||||
}
|
||||
|
||||
@media only screen and (min-width:48em) {
|
||||
.c5 {
|
||||
width: 46rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:64em) {
|
||||
.c5 {
|
||||
width: 56rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:75em) {
|
||||
.c5 {
|
||||
width: 59rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:0em) {
|
||||
.c7 {
|
||||
-webkit-flex-basis: 100%;
|
||||
-ms-flex-preferred-size: 100%;
|
||||
flex-basis: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width:37.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:37.5rem) and (max-width:62.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 1.875rem;
|
||||
padding-right: 1.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width:62.5rem) and (max-width:87.4375rem) {
|
||||
.c4 {
|
||||
padding-left: 4.375rem;
|
||||
padding-right: 4.375rem;
|
||||
}
|
||||
}
|
||||
|
||||
<div
|
||||
className="c0 c1 c2"
|
||||
>
|
||||
<div
|
||||
className="c3"
|
||||
>
|
||||
<div
|
||||
className="c4 c5"
|
||||
>
|
||||
<div
|
||||
className="c6"
|
||||
name="breadcrum"
|
||||
>
|
||||
<div
|
||||
className="c7"
|
||||
>
|
||||
<div
|
||||
className="c8"
|
||||
>
|
||||
<h4
|
||||
className="c9 c10"
|
||||
name="breadcrum-item"
|
||||
>
|
||||
<div
|
||||
className="c11"
|
||||
>
|
||||
Compute
|
||||
</div>
|
||||
</h4>
|
||||
<svg
|
||||
height="6"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(-90deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9.6 6"
|
||||
width="9.6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.6,1.12,8.24,0,4.8,3.5,1.36,0,0,1.12,4.8,6Z"
|
||||
fill="rgb(151, 151, 151)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
className="c8"
|
||||
>
|
||||
<h4
|
||||
className="c9 c10"
|
||||
name="breadcrum-item"
|
||||
>
|
||||
<div
|
||||
className="c11"
|
||||
>
|
||||
Service Groups
|
||||
</div>
|
||||
</h4>
|
||||
<svg
|
||||
height="6"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(-90deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9.6 6"
|
||||
width="9.6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.6,1.12,8.24,0,4.8,3.5,1.36,0,0,1.12,4.8,6Z"
|
||||
fill="rgb(151, 151, 151)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
className="c8"
|
||||
>
|
||||
<h4
|
||||
className="c9 c10"
|
||||
name="breadcrum-item"
|
||||
>
|
||||
<div
|
||||
className="c11"
|
||||
>
|
||||
id
|
||||
</div>
|
||||
</h4>
|
||||
<svg
|
||||
height="6"
|
||||
style={
|
||||
Object {
|
||||
"transform": "rotate(-90deg)",
|
||||
}
|
||||
}
|
||||
viewBox="0 0 9.6 6"
|
||||
width="9.6"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.6,1.12,8.24,0,4.8,3.5,1.36,0,0,1.12,4.8,6Z"
|
||||
fill="rgb(151, 151, 151)"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import 'jest-styled-components';
|
||||
|
||||
import Breadcrumb from '../breadcrumb';
|
||||
import Theme from '@mocks/theme';
|
||||
|
||||
it('renders <Breadcrumb /> without throwing', () => {
|
||||
expect(
|
||||
renderer
|
||||
.create(
|
||||
<Theme>
|
||||
<Breadcrumb />
|
||||
</Theme>
|
||||
)
|
||||
.toJSON()
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders <Breadcrumb match /> without throwing', () => {
|
||||
const match = {
|
||||
params: {
|
||||
sg: 'id'
|
||||
}
|
||||
};
|
||||
|
||||
expect(
|
||||
renderer
|
||||
.create(
|
||||
<Theme>
|
||||
<Breadcrumb match={match} />
|
||||
</Theme>
|
||||
)
|
||||
.toJSON()
|
||||
).toMatchSnapshot();
|
||||
});
|
40
consoles/my-joy-service-groups/src/containers/breadcrumb.js
Normal file
40
consoles/my-joy-service-groups/src/containers/breadcrumb.js
Normal file
@ -0,0 +1,40 @@
|
||||
import React from 'react';
|
||||
import paramCase from 'param-case';
|
||||
import get from 'lodash.get';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
|
||||
import { Breadcrumb, BreadcrumbItem } from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ match }) => {
|
||||
const serviceGroupId = get(match, 'params.sg');
|
||||
|
||||
const links = [
|
||||
{
|
||||
name: 'Compute',
|
||||
pathname: '/'
|
||||
},
|
||||
{
|
||||
name: 'Service Groups',
|
||||
pathname: '/service-groups'
|
||||
}
|
||||
]
|
||||
.concat(
|
||||
serviceGroupId && [
|
||||
{
|
||||
name: paramCase(serviceGroupId),
|
||||
pathname: `/service-groups/${serviceGroupId}`
|
||||
}
|
||||
]
|
||||
)
|
||||
.filter(Boolean)
|
||||
.map(({ name, pathname }) => (
|
||||
<BreadcrumbItem key={name} to={pathname} component={Link}>
|
||||
<Margin horizontal="1" vertical="3">
|
||||
{name}
|
||||
</Margin>
|
||||
</BreadcrumbItem>
|
||||
));
|
||||
|
||||
return <Breadcrumb>{links}</Breadcrumb>;
|
||||
};
|
237
consoles/my-joy-service-groups/src/containers/create.js
Normal file
237
consoles/my-joy-service-groups/src/containers/create.js
Normal file
@ -0,0 +1,237 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { If, Then } from 'react-if';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { SubmissionError, destroy } from 'redux-form';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { set, destroyAll } from 'react-redux-values';
|
||||
import intercept from 'apr-intercept';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription,
|
||||
Button
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import {
|
||||
PostCreation,
|
||||
PostCreationContent,
|
||||
PostCreationTitle
|
||||
} from 'joyent-ui-resource-widgets';
|
||||
|
||||
import { Provider as ResourceSteps } from 'joyent-ui-resource-step';
|
||||
|
||||
import parseError from '@state/parse-error';
|
||||
import { Forms, Values } from '@root/constants';
|
||||
import ListServiceGroups from '@graphql/list-service-groups.gql';
|
||||
import CreateServiceGroup from '@graphql/create-service-group.gql';
|
||||
import GetServiceGroup from '@graphql/get-service-group.gql';
|
||||
import Template from './steps/template';
|
||||
import Name from './steps/name';
|
||||
|
||||
const { SGC_F } = Forms;
|
||||
const { SGC_N_V, SGC_T_V } = Values;
|
||||
|
||||
class CreateTemplate extends Component {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.isValids = {};
|
||||
}
|
||||
|
||||
setIsValid = name => ref => {
|
||||
if (!ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { isValid } = ref;
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isValids = Object.assign({}, this.isValids, {
|
||||
[name]: isValid
|
||||
});
|
||||
};
|
||||
|
||||
isFormValid = () => {
|
||||
const { steps } = this.props;
|
||||
|
||||
return Boolean(
|
||||
Object.keys(this.isValids).filter(
|
||||
name => !this.isValids[name](steps[name] || {})
|
||||
).length
|
||||
);
|
||||
};
|
||||
|
||||
isStepValid = step => {
|
||||
const { steps } = this.props;
|
||||
const fn = this.isValids[step];
|
||||
const values = steps[step];
|
||||
|
||||
if (!fn || !values) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fn(values);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { match, steps, handleDefocus, handleSubmit } = this.props;
|
||||
const { params } = match;
|
||||
const { step } = params;
|
||||
const { template, name } = steps;
|
||||
|
||||
const disabled = !(
|
||||
template &&
|
||||
template.id &&
|
||||
name &&
|
||||
name.name &&
|
||||
name.capacity
|
||||
);
|
||||
|
||||
return (
|
||||
<ViewContainer main>
|
||||
<Padding top="5">
|
||||
<ResourceSteps namespace="service-groups/~create">
|
||||
<Margin bottom="4">
|
||||
<Template
|
||||
ref={this.setIsValid('template')}
|
||||
expanded={step === 'template'}
|
||||
next="name"
|
||||
saved={get(steps, 'template.id', false)}
|
||||
onDefocus={handleDefocus(SGC_T_V)}
|
||||
preview={template}
|
||||
isValid={this.isStepValid('template')}
|
||||
/>
|
||||
</Margin>
|
||||
<Margin bottom="4">
|
||||
<Name
|
||||
ref={this.setIsValid('name')}
|
||||
expanded={step === 'name'}
|
||||
saved={get(steps, 'name.name', false)}
|
||||
onDefocus={handleDefocus(SGC_N_V)}
|
||||
preview={name}
|
||||
isValid={this.isStepValid('name')}
|
||||
/>
|
||||
</Margin>
|
||||
</ResourceSteps>
|
||||
<Margin top="5" bottom="3">
|
||||
<ReduxForm form={SGC_F} onSubmit={handleSubmit}>
|
||||
{({ handleSubmit, submitting, error }) => (
|
||||
<Fragment>
|
||||
<If condition={error}>
|
||||
<Then>
|
||||
<Margin bottom="4">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>{error}</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</Then>
|
||||
</If>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Button loading={submitting} disabled={disabled}>
|
||||
Deploy
|
||||
</Button>
|
||||
</form>
|
||||
</Fragment>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
</Padding>
|
||||
</ViewContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const Success = ({ match }) => {
|
||||
const id = match.params.sg;
|
||||
|
||||
return (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<PostCreation id={id} object="service group">
|
||||
<PostCreationTitle>
|
||||
You have successfully created a service group
|
||||
</PostCreationTitle>
|
||||
<PostCreationContent>
|
||||
Your service group has been created and is currently being
|
||||
processed. It should only take a few minutes and will then appear in
|
||||
your console.
|
||||
</PostCreationContent>
|
||||
</PostCreation>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default compose(
|
||||
graphql(CreateServiceGroup, { name: 'createServiceGroup' }),
|
||||
connect(({ form, values = {} }) => ({
|
||||
forms: Object.keys(form),
|
||||
steps: {
|
||||
name: get(values, SGC_N_V),
|
||||
template: get(values, SGC_T_V)
|
||||
}
|
||||
})),
|
||||
connect(null, (dispatch, { forms, steps, history, createServiceGroup }) => ({
|
||||
handleDefocus: name => value => {
|
||||
return dispatch(set({ name, value }));
|
||||
},
|
||||
handleSubmit: async () => {
|
||||
const [err, res] = await intercept(
|
||||
createServiceGroup({
|
||||
variables: {
|
||||
name: steps.name.name,
|
||||
template: steps.template.id,
|
||||
capacity: steps.name.capacity
|
||||
},
|
||||
update: (proxy, { data: { createGroup: group } }) => {
|
||||
try {
|
||||
proxy.writeQuery({
|
||||
query: ListServiceGroups,
|
||||
data: {
|
||||
groups: proxy
|
||||
.readQuery({ query: ListServiceGroups })
|
||||
.groups.concat([group])
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
proxy.writeQuery({
|
||||
query: GetServiceGroup,
|
||||
variables: { id: group.id },
|
||||
data: { group }
|
||||
});
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (err) {
|
||||
throw new SubmissionError({
|
||||
_error: parseError(err)
|
||||
});
|
||||
}
|
||||
|
||||
const { data } = res;
|
||||
const { createGroup: cg } = data;
|
||||
const { id } = cg;
|
||||
|
||||
dispatch([destroyAll(), forms.map(name => destroy(name))]);
|
||||
history.push(`/service-groups/~create/${id}/success`);
|
||||
}
|
||||
}))
|
||||
)(CreateTemplate);
|
215
consoles/my-joy-service-groups/src/containers/edit.js
Normal file
215
consoles/my-joy-service-groups/src/containers/edit.js
Normal file
@ -0,0 +1,215 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { SubmissionError, destroy } from 'redux-form';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { set, destroyAll } from 'react-redux-values';
|
||||
import intercept from 'apr-intercept';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription,
|
||||
Button,
|
||||
StatusLoader
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import {
|
||||
PostCreation,
|
||||
PostCreationContent,
|
||||
PostCreationTitle
|
||||
} from 'joyent-ui-resource-widgets';
|
||||
|
||||
import { Provider as ResourceSteps } from 'joyent-ui-resource-step';
|
||||
|
||||
import parseError from '@state/parse-error';
|
||||
import { Forms, Values } from '@root/constants';
|
||||
import ListServiceGroups from '@graphql/list-service-groups.gql';
|
||||
import UpdateServiceGroup from '@graphql/update-service-group.gql';
|
||||
import GetServiceGroup from '@graphql/get-service-group.gql';
|
||||
import Template from './steps/template';
|
||||
import Name from './steps/name';
|
||||
|
||||
const { SGE_F } = Forms;
|
||||
const { SGE_N_V } = Values;
|
||||
|
||||
const EditTemplate = ({
|
||||
match,
|
||||
steps,
|
||||
loading,
|
||||
initialCapacity,
|
||||
handleDefocus,
|
||||
handleSubmit
|
||||
}) => {
|
||||
const { params } = match;
|
||||
const { step, sg } = params;
|
||||
const { template, name } = steps;
|
||||
|
||||
const disabled = name && name.capacity && initialCapacity === name.capacity;
|
||||
|
||||
return (
|
||||
<ViewContainer main>
|
||||
<Padding top="5">
|
||||
<If condition={loading}>
|
||||
<Then>
|
||||
<StatusLoader />
|
||||
</Then>
|
||||
<Else>
|
||||
<Fragment>
|
||||
<ResourceSteps namespace={`service-groups/~edit/${sg}`}>
|
||||
<Margin bottom="4">
|
||||
<Template next="name" preview={template} readOnly />
|
||||
</Margin>
|
||||
<Margin bottom="4">
|
||||
<Name
|
||||
expanded={step === 'name'}
|
||||
saved={get(steps, 'name.name', false)}
|
||||
onDefocus={handleDefocus(SGE_N_V)}
|
||||
preview={name}
|
||||
readOnlyName
|
||||
/>
|
||||
</Margin>
|
||||
</ResourceSteps>
|
||||
<Margin top="5" bottom="3">
|
||||
<ReduxForm form={SGE_F} onSubmit={handleSubmit}>
|
||||
{({ handleSubmit, submitting, error }) => (
|
||||
<Fragment>
|
||||
<If condition={error}>
|
||||
<Then>
|
||||
<Margin bottom="4">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>{error}</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</Then>
|
||||
</If>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Button loading={submitting} disabled={disabled}>
|
||||
Update
|
||||
</Button>
|
||||
</form>
|
||||
</Fragment>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
</Fragment>
|
||||
</Else>
|
||||
</If>
|
||||
</Padding>
|
||||
</ViewContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export const Success = ({ match }) => {
|
||||
const id = match.params.sg;
|
||||
|
||||
return (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<PostCreation id={id} object="service group">
|
||||
<PostCreationTitle>
|
||||
You have successfully updated a service group
|
||||
</PostCreationTitle>
|
||||
<PostCreationContent>
|
||||
Your service group has been updated and is currently being
|
||||
processed. It should only take a few minutes and the changes will
|
||||
reflected in your console.
|
||||
</PostCreationContent>
|
||||
</PostCreation>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default compose(
|
||||
graphql(UpdateServiceGroup, { name: 'updateServiceGroup' }),
|
||||
graphql(GetServiceGroup, {
|
||||
options: ({ match }) => ({
|
||||
ssr: true,
|
||||
variables: {
|
||||
id: get(match, 'params.sg')
|
||||
}
|
||||
}),
|
||||
props: ({ data: { networkStatus, error, group } }) => ({
|
||||
loading: networkStatus === 1,
|
||||
error,
|
||||
group
|
||||
})
|
||||
}),
|
||||
connect(({ form, values = {} }, { group = {} }) => {
|
||||
const { template, capacity, name } = group;
|
||||
|
||||
return {
|
||||
forms: Object.keys(form),
|
||||
initialCapacity: capacity,
|
||||
steps: {
|
||||
name: get(values, SGE_N_V) || { name, capacity },
|
||||
template
|
||||
}
|
||||
};
|
||||
}),
|
||||
connect(
|
||||
null,
|
||||
(dispatch, { forms, group, steps, history, updateServiceGroup }) => ({
|
||||
handleDefocus: name => value => {
|
||||
return dispatch(set({ name, value }));
|
||||
},
|
||||
handleSubmit: async () => {
|
||||
const [err, res] = await intercept(
|
||||
updateServiceGroup({
|
||||
variables: {
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
template: group.template.id,
|
||||
capacity: steps.name.capacity
|
||||
},
|
||||
update: (proxy, { data: { createGroup: group } }) => {
|
||||
try {
|
||||
proxy.writeQuery({
|
||||
query: ListServiceGroups,
|
||||
data: {
|
||||
groups: proxy
|
||||
.readQuery({ query: ListServiceGroups })
|
||||
.groups.map(g => (g.id === group.id ? group : g))
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
try {
|
||||
proxy.writeQuery({
|
||||
query: GetServiceGroup,
|
||||
variables: { id: group.id },
|
||||
data: { group }
|
||||
});
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (err) {
|
||||
throw new SubmissionError({
|
||||
_error: parseError(err)
|
||||
});
|
||||
}
|
||||
|
||||
const { data } = res;
|
||||
const { updateGroup: ug } = data;
|
||||
const { id } = ug;
|
||||
|
||||
dispatch([destroyAll(), forms.map(name => destroy(name))]);
|
||||
history.push(`/service-groups/~edit/${id}/success`);
|
||||
}
|
||||
})
|
||||
)
|
||||
)(EditTemplate);
|
289
consoles/my-joy-service-groups/src/containers/list.js
Normal file
289
consoles/my-joy-service-groups/src/containers/list.js
Normal file
@ -0,0 +1,289 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { change } from 'redux-form';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import intercept from 'apr-intercept';
|
||||
import get from 'lodash.get';
|
||||
import isString from 'lodash.isstring';
|
||||
import sort from 'lodash.sortby';
|
||||
import reverse from 'lodash.reverse';
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import ServiceGroupsList, {
|
||||
Item as ServiceGroupsItem,
|
||||
EmptyCard as ServiceGroupsEmptyCard,
|
||||
EmptyRow as ServiceGroupsEmptyRow,
|
||||
LoadingRow,
|
||||
BulkFooter
|
||||
} from '@components/list';
|
||||
|
||||
import { Toolbar } from '@components/toolbar';
|
||||
import ListServiceGroups from '@graphql/list-service-groups.gql';
|
||||
import RemoveServiceGroup from '@graphql/remove-service-group.gql';
|
||||
import { Forms, Values } from '@root/constants';
|
||||
import parseError from '@state/parse-error';
|
||||
import Confirm from '@state/confirm';
|
||||
|
||||
const { SGL_F_F, SGL_T_F } = Forms;
|
||||
const { SGL_R_V, SGL_E_V, SGL_SB_V, SGL_SO_V } = Values;
|
||||
|
||||
const ServiceGroups = ({
|
||||
filter,
|
||||
empty,
|
||||
checked = [],
|
||||
groups = [],
|
||||
error = false,
|
||||
loading = false,
|
||||
sortBy = 'name',
|
||||
sortOrder = 'asc',
|
||||
handleSortBy,
|
||||
handleToggleCheckAll,
|
||||
handleRemove
|
||||
}) => (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<Margin bottom="3">
|
||||
<ReduxForm form={SGL_F_F}>
|
||||
{() => (
|
||||
<If condition={empty}>
|
||||
<Else>
|
||||
<form>
|
||||
<Toolbar
|
||||
searchable={filter || groups.length}
|
||||
searchLabel="Filter service groups"
|
||||
actionLabel="Create service group"
|
||||
actionTo="/service-groups/~create/template"
|
||||
actionable={!(!loading && !groups.length && !filter)}
|
||||
/>
|
||||
</form>
|
||||
</Else>
|
||||
</If>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
<If condition={error}>
|
||||
<Then>
|
||||
<Margin bottom="3">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
<If condition={isString(error)}>
|
||||
<Then>
|
||||
<Fragment>{error}</Fragment>
|
||||
</Then>
|
||||
<Else>
|
||||
<Fragment>
|
||||
An error occurred while loading your service groups
|
||||
</Fragment>
|
||||
</Else>
|
||||
</If>
|
||||
</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</Then>
|
||||
</If>
|
||||
<ReduxForm form={SGL_T_F}>
|
||||
{props => (
|
||||
<If condition={empty}>
|
||||
<Then>
|
||||
<ServiceGroupsEmptyCard />
|
||||
</Then>
|
||||
<Else>
|
||||
<ServiceGroupsList
|
||||
{...props}
|
||||
checked={checked.length === groups.length}
|
||||
sortBy={sortBy}
|
||||
sortOrder={sortOrder}
|
||||
onSortBy={newSortBy =>
|
||||
handleSortBy(newSortBy, { sortOrder, sortBy })
|
||||
}
|
||||
onToggleCheckAll={() =>
|
||||
handleToggleCheckAll(checked.length !== groups.length)
|
||||
}
|
||||
>
|
||||
<If condition={groups.length}>
|
||||
<Then>
|
||||
<Fragment>
|
||||
{groups.map(({ id, removing, ...group }) => (
|
||||
<If condition={removing}>
|
||||
<Then>
|
||||
<LoadingRow key={id}>Removing...</LoadingRow>
|
||||
</Then>
|
||||
<Else>
|
||||
<ServiceGroupsItem key={id} id={id} {...group} />
|
||||
</Else>
|
||||
</If>
|
||||
))}
|
||||
</Fragment>
|
||||
</Then>
|
||||
<Else>
|
||||
<If condition={loading}>
|
||||
<Then>
|
||||
<LoadingRow />
|
||||
</Then>
|
||||
<Else>
|
||||
<ServiceGroupsEmptyRow />
|
||||
</Else>
|
||||
</If>
|
||||
</Else>
|
||||
</If>
|
||||
</ServiceGroupsList>
|
||||
</Else>
|
||||
</If>
|
||||
)}
|
||||
</ReduxForm>
|
||||
<If condition={checked.length}>
|
||||
<Then>
|
||||
<BulkFooter items={checked} onRemove={handleRemove} />
|
||||
</Then>
|
||||
</If>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
graphql(RemoveServiceGroup, { name: 'removeGroup' }),
|
||||
graphql(ListServiceGroups, {
|
||||
options: ({ location }) => ({
|
||||
ssr: true,
|
||||
pollInterval: 1000
|
||||
}),
|
||||
props: ({ data: { error, groups = [], networkStatus, refetch } }) => ({
|
||||
refetch,
|
||||
error,
|
||||
loading: networkStatus === 1,
|
||||
groups,
|
||||
index: new Fuse(groups, {
|
||||
keys: ['id', 'name', 'created']
|
||||
})
|
||||
})
|
||||
}),
|
||||
connect(
|
||||
(state, ownProps) => {
|
||||
const { form, values: flags } = state;
|
||||
const { groups: items, index, loading, error: loadingError } = ownProps;
|
||||
const filter = get(form, `${SGL_F_F}.values.filter`, '');
|
||||
const mutationError = get(flags, SGL_E_V, null);
|
||||
const sortBy = get(flags, SGL_SB_V, 'name');
|
||||
const sortOrder = get(flags, SGL_SO_V, 'asc');
|
||||
|
||||
const groups = sort(
|
||||
(filter.length ? index.search(filter) : items).map(
|
||||
({ id, ...groups }) => ({
|
||||
...groups,
|
||||
removing: get(flags, SGL_R_V(id), false),
|
||||
id
|
||||
})
|
||||
),
|
||||
[sortBy]
|
||||
);
|
||||
|
||||
const values = get(form, `${SGL_T_F}.values`, {});
|
||||
const checked = groups.length && groups.filter(({ id }) => values[id]);
|
||||
|
||||
return {
|
||||
filter,
|
||||
empty: !filter && !loading && !groups.length,
|
||||
error: Boolean(loadingError) || mutationError,
|
||||
groups: sortOrder === 'asc' ? groups : reverse(groups),
|
||||
checked,
|
||||
sortBy,
|
||||
sortOrder
|
||||
};
|
||||
},
|
||||
(dispatch, { templates = [], refetch, removeGroup }) => {
|
||||
return {
|
||||
handleToggleCheckAll: newChecked => {
|
||||
return dispatch(
|
||||
templates.map(({ id }) => change(SGL_T_F, id, newChecked))
|
||||
);
|
||||
},
|
||||
handleSortBy: (newSortBy, { sortBy: currentSortBy, sortOrder }) => {
|
||||
// sort prop is the same, toggle
|
||||
if (currentSortBy === newSortBy) {
|
||||
return dispatch(
|
||||
set({
|
||||
name: SGL_SO_V,
|
||||
value: sortOrder === 'desc' ? 'asc' : 'desc'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
dispatch([
|
||||
set({
|
||||
name: SGL_SO_V,
|
||||
value: 'desc'
|
||||
}),
|
||||
set({
|
||||
name: SGL_SB_V,
|
||||
value: newSortBy
|
||||
})
|
||||
]);
|
||||
},
|
||||
handleRemove: async (ev, checked = []) => {
|
||||
// eslint-disable-next-line no-alert
|
||||
if (
|
||||
!await Confirm(
|
||||
`Do you want to remove ${
|
||||
checked.length === 1
|
||||
? `"${checked[0].name}"`
|
||||
: `${checked.length} service groups`
|
||||
}`
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(
|
||||
checked.map(({ id }) =>
|
||||
set({
|
||||
name: SGL_R_V(id),
|
||||
value: true
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const [err] = await intercept(
|
||||
Promise.all(
|
||||
checked.map(({ id }) =>
|
||||
removeGroup({
|
||||
variables: { id }
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
await refetch();
|
||||
|
||||
dispatch(
|
||||
[
|
||||
...checked.map(({ id }) =>
|
||||
set({
|
||||
name: SGL_R_V(id),
|
||||
value: false
|
||||
})
|
||||
),
|
||||
err
|
||||
? set({
|
||||
name: SGL_E_V,
|
||||
value: parseError(err)
|
||||
})
|
||||
: undefined
|
||||
].filter(Boolean)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
)
|
||||
)(ServiceGroups);
|
171
consoles/my-joy-service-groups/src/containers/steps/name.js
Normal file
171
consoles/my-joy-service-groups/src/containers/steps/name.js
Normal file
@ -0,0 +1,171 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import { compose } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import { Field, change } from 'redux-form';
|
||||
import { withRouter } from 'react-router';
|
||||
import get from 'lodash.get';
|
||||
import plur from 'plur';
|
||||
|
||||
import Step, {
|
||||
Header as StepHeader,
|
||||
Description as StepDescription,
|
||||
Preview as StepPreview,
|
||||
Outlet as StepOutlet
|
||||
} from 'joyent-ui-resource-step';
|
||||
|
||||
import {
|
||||
H2,
|
||||
P,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
FormMeta,
|
||||
Button,
|
||||
InstanceCountIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Forms } from '@root/constants';
|
||||
import { name as validateName } from '@state/validators';
|
||||
|
||||
const { SGC_N_F } = Forms;
|
||||
|
||||
const Name = ({
|
||||
history,
|
||||
handleGetValue,
|
||||
preview = {},
|
||||
readOnlyName,
|
||||
initialValues,
|
||||
handleValidate,
|
||||
handlePlusClick,
|
||||
handleMinusClick,
|
||||
...props
|
||||
}) => (
|
||||
<Step name="name" getValue={handleGetValue} {...props}>
|
||||
<StepHeader icon={<InstanceCountIcon />}>
|
||||
Name and instance count
|
||||
</StepHeader>
|
||||
<StepDescription>
|
||||
Input the name of your Service Group and the desired number of instances
|
||||
this group will aim to maintain. You can scale up or down your Service
|
||||
Group anytime after commisioning.
|
||||
</StepDescription>
|
||||
<StepPreview>
|
||||
<Margin top="3">
|
||||
<Margin bottom="2">
|
||||
<H2>{preview.name}</H2>
|
||||
</Margin>
|
||||
<P>
|
||||
{preview.capacity} {plur('instance', preview.capacity)}
|
||||
</P>
|
||||
</Margin>
|
||||
</StepPreview>
|
||||
<StepOutlet>
|
||||
{({ next }) => (
|
||||
<Margin top="3">
|
||||
<ReduxForm
|
||||
form={SGC_N_F}
|
||||
validate={handleValidate}
|
||||
initialValues={initialValues}
|
||||
destroyOnUnmount={false}
|
||||
forceUnregisterOnUnmount={false}
|
||||
enableReinitialize
|
||||
keepDirtyOnReinitialize
|
||||
>
|
||||
{({ pristine, invalid }) => (
|
||||
<form onSubmit={() => history.push(next)}>
|
||||
<Margin bottom="5">
|
||||
<FormGroup name="name" fluid field={Field}>
|
||||
<FormLabel>Service group name</FormLabel>
|
||||
<Margin top="0.5">
|
||||
<Flex>
|
||||
<FlexItem>
|
||||
<Input
|
||||
onBlur={null}
|
||||
type="text"
|
||||
disabled={readOnlyName}
|
||||
/>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
<Margin bottom="5">
|
||||
<FormGroup name="capacity" fluid field={Field}>
|
||||
<FormLabel>Desired number of instances</FormLabel>
|
||||
<Margin top="0.5">
|
||||
<Flex>
|
||||
<FlexItem>
|
||||
<Input
|
||||
type="number"
|
||||
onBlur={null}
|
||||
onPlusClick={handlePlusClick}
|
||||
onMinusClick={handleMinusClick}
|
||||
xSmall
|
||||
/>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
<Button
|
||||
type="button"
|
||||
component={Link}
|
||||
to={next}
|
||||
disabled={pristine || invalid}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
)}
|
||||
</StepOutlet>
|
||||
</Step>
|
||||
);
|
||||
|
||||
const Container = compose(
|
||||
withRouter,
|
||||
connect((store, { preview = {} }) => {
|
||||
const { form } = store;
|
||||
|
||||
return {
|
||||
handleGetValue: () => get(form, `${SGC_N_F}.values`, {}),
|
||||
initialValues: {
|
||||
capacity: 1,
|
||||
...preview
|
||||
}
|
||||
};
|
||||
}),
|
||||
connect(null, (dispatch, { handleGetValue }) => ({
|
||||
handleValidate: validateName,
|
||||
handlePlusClick: ({ shiftKey, metaKey }) => {
|
||||
const count = metaKey ? 100 : shiftKey ? 10 : 1;
|
||||
const capacity = handleGetValue().capacity || 0;
|
||||
return dispatch(change(SGC_N_F, 'capacity', capacity + count));
|
||||
},
|
||||
handleMinusClick: ({ shiftKey, metaKey }) => {
|
||||
const count = metaKey ? 100 : shiftKey ? 10 : 1;
|
||||
const capacity = handleGetValue().capacity || 0;
|
||||
return dispatch(change(SGC_N_F, 'capacity', capacity - count));
|
||||
}
|
||||
}))
|
||||
)(Name);
|
||||
|
||||
export default class extends PureComponent {
|
||||
isValid(values) {
|
||||
const msgs = validateName(values);
|
||||
return !msgs || !Object.values(msgs).length;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, ...props } = this.props;
|
||||
return <Container {...props}>{children}</Container>;
|
||||
}
|
||||
}
|
333
consoles/my-joy-service-groups/src/containers/steps/template.js
Normal file
333
consoles/my-joy-service-groups/src/containers/steps/template.js
Normal file
@ -0,0 +1,333 @@
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import { Field } from 'redux-form';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import get from 'lodash.get';
|
||||
import sort from 'lodash.sortby';
|
||||
import reverse from 'lodash.reverse';
|
||||
import find from 'lodash.find';
|
||||
import Fuse from 'fuse.js';
|
||||
|
||||
import Step, {
|
||||
Header as StepHeader,
|
||||
Description as StepDescription,
|
||||
Preview as StepPreview,
|
||||
Outlet as StepOutlet
|
||||
} from 'joyent-ui-resource-step';
|
||||
|
||||
import {
|
||||
H2,
|
||||
Label,
|
||||
Divider,
|
||||
Button,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
TemplateIcon,
|
||||
StatusLoader,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import TemplatesList, {
|
||||
Item as TemplatesItem,
|
||||
EmptyCard as TemplatesEmptyCard,
|
||||
EmptyRow as TemplatesEmptyRow,
|
||||
LoadingRow
|
||||
} from '@components/templates';
|
||||
|
||||
import { Global } from '@state/global.js';
|
||||
import GetTemplate from '@graphql/get-template.gql';
|
||||
import ListTemplates from '@graphql/list-templates.gql';
|
||||
import { Forms, Values } from '@root/constants';
|
||||
|
||||
const { SGC_T_F, SGC_F_F } = Forms;
|
||||
const { SGC_T_SB_V, SGC_T_SO_V } = Values;
|
||||
|
||||
class Template extends Component {
|
||||
getSnapshotBeforeUpdate(prevProps, prevState) {
|
||||
const { preview: prev } = prevProps;
|
||||
const { preview: next, onDefocus, readOnly } = this.props;
|
||||
|
||||
if (!(readOnly && prev !== next && onDefocus)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onDefocus(next);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
loading = false,
|
||||
empty = false,
|
||||
handleGetValue,
|
||||
preview = {},
|
||||
initialValues,
|
||||
templates = [],
|
||||
filter = '',
|
||||
sortBy = 'name',
|
||||
sortOrder = 'asc',
|
||||
expanded = false,
|
||||
readOnly = false,
|
||||
error = null,
|
||||
handleSortBy,
|
||||
...props
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Step
|
||||
name="template"
|
||||
getValue={handleGetValue}
|
||||
readOnly={readOnly}
|
||||
expanded={readOnly ? false : expanded}
|
||||
{...props}
|
||||
>
|
||||
<StepHeader icon={<TemplateIcon />}>Select template</StepHeader>
|
||||
<StepDescription>
|
||||
Select the template you’d like to deloy your instances from. Once a
|
||||
Service Group is deployed with a templates, any changes to that
|
||||
template will not effect the acting service group.
|
||||
</StepDescription>
|
||||
<StepPreview>
|
||||
<Margin top="5">
|
||||
<If condition={loading && !preview.name}>
|
||||
<Then>
|
||||
<StatusLoader />
|
||||
</Then>
|
||||
<Else>
|
||||
<Fragment>
|
||||
<Margin bottom="2">
|
||||
<H2>{preview.name}</H2>
|
||||
</Margin>
|
||||
<Flex alignCenter>
|
||||
<FlexItem>
|
||||
<Padding right="3">
|
||||
<Label inline>{preview.image}</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<Divider vertical />
|
||||
<FlexItem>
|
||||
<Padding right="3" left="3">
|
||||
<Label inline>{preview.package}</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<Divider vertical />
|
||||
<FlexItem>
|
||||
<Padding right="3" left="3">
|
||||
<Label inline>
|
||||
{distanceInWordsToNow(preview.created)}
|
||||
</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Fragment>
|
||||
</Else>
|
||||
</If>
|
||||
</Margin>
|
||||
</StepPreview>
|
||||
<StepOutlet>
|
||||
{({ next }) => (
|
||||
<Margin top="5">
|
||||
<If condition={error}>
|
||||
<Then>
|
||||
<Margin bottom="3">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
An error occurred while loading your templates
|
||||
</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</Then>
|
||||
</If>
|
||||
<ReduxForm form={SGC_F_F}>
|
||||
{props => (
|
||||
<If condition={empty}>
|
||||
<Else>
|
||||
<Margin bottom="3">
|
||||
<FormGroup name="filter" field={Field}>
|
||||
<FormLabel>Filter</FormLabel>
|
||||
<Margin top="0.5">
|
||||
<Input disabled={!(filter || templates.length)} />
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
</Else>
|
||||
</If>
|
||||
)}
|
||||
</ReduxForm>
|
||||
<ReduxForm form={SGC_T_F} initialValues={initialValues}>
|
||||
{({ pristine }) => (
|
||||
<Fragment>
|
||||
<If condition={empty}>
|
||||
<Then>
|
||||
<TemplatesEmptyCard />
|
||||
</Then>
|
||||
<Else>
|
||||
<TemplatesList
|
||||
{...props}
|
||||
sortBy={sortBy}
|
||||
sortOrder={sortOrder}
|
||||
onSortBy={newSortBy =>
|
||||
handleSortBy(newSortBy, { sortOrder, sortBy })
|
||||
}
|
||||
>
|
||||
<If condition={templates.length}>
|
||||
<Then>
|
||||
<Fragment>
|
||||
{templates.map(({ id, ...template }) => (
|
||||
<TemplatesItem
|
||||
key={id}
|
||||
id={id}
|
||||
{...template}
|
||||
/>
|
||||
))}
|
||||
</Fragment>
|
||||
</Then>
|
||||
<Else>
|
||||
<If condition={loading}>
|
||||
<Then>
|
||||
<LoadingRow />
|
||||
</Then>
|
||||
<Else>
|
||||
<TemplatesEmptyRow />
|
||||
</Else>
|
||||
</If>
|
||||
</Else>
|
||||
</If>
|
||||
</TemplatesList>
|
||||
</Else>
|
||||
</If>
|
||||
<Margin top="5">
|
||||
<Button
|
||||
type="button"
|
||||
disabled={pristine}
|
||||
component={Link}
|
||||
to={next}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</Margin>
|
||||
</Fragment>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
)}
|
||||
</StepOutlet>
|
||||
</Step>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
graphql(ListTemplates, {
|
||||
options: ({ location }) => {
|
||||
const tmpl = Global().query.template;
|
||||
|
||||
return {
|
||||
ssr: true,
|
||||
fetchPolicy: tmpl ? 'cache-only' : 'cache-and-network'
|
||||
};
|
||||
},
|
||||
props: ({ data: { error, templates = [], networkStatus } }) => ({
|
||||
error,
|
||||
loading: networkStatus === 1,
|
||||
templates,
|
||||
index: new Fuse(templates, {
|
||||
keys: ['id', 'name', 'created']
|
||||
})
|
||||
})
|
||||
}),
|
||||
graphql(GetTemplate, {
|
||||
options: ({ match }) => {
|
||||
const tmpl = Global().query.template;
|
||||
|
||||
return {
|
||||
ssr: true,
|
||||
fetchPolicy: tmpl ? 'cache-and-network' : 'cache-only',
|
||||
variables: {
|
||||
id: tmpl
|
||||
}
|
||||
};
|
||||
},
|
||||
props: ({ data }) => {
|
||||
const { variables, networkStatus, error, template } = data;
|
||||
|
||||
if (!variables.id) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return {
|
||||
readOnly: Boolean(variables.id),
|
||||
loading: networkStatus === 1,
|
||||
error,
|
||||
preview: template
|
||||
};
|
||||
}
|
||||
}),
|
||||
connect(
|
||||
(state, ownProps) => {
|
||||
const { form, values: flags } = state;
|
||||
const { templates: items, preview = {}, loading, index } = ownProps;
|
||||
|
||||
const filter = get(form, `${SGC_F_F}.values.filter`, '');
|
||||
const sortBy = get(flags, SGC_T_SB_V, 'name');
|
||||
const sortOrder = get(flags, SGC_T_SO_V, 'asc');
|
||||
|
||||
const templates = sort(filter.length ? index.search(filter) : items, [
|
||||
sortBy
|
||||
]);
|
||||
|
||||
return {
|
||||
filter,
|
||||
empty: !filter && !loading && !templates.length,
|
||||
handleGetValue: () => {
|
||||
return find(templates, [
|
||||
'id',
|
||||
get(form, `${SGC_T_F}.values.template`)
|
||||
]);
|
||||
},
|
||||
initialValues: {
|
||||
template: preview.id
|
||||
},
|
||||
templates: sortOrder === 'asc' ? templates : reverse(templates),
|
||||
sortBy,
|
||||
sortOrder
|
||||
};
|
||||
},
|
||||
(dispatch, { templates = [], refetch, removeGroup }) => {
|
||||
return {
|
||||
handleSortBy: (newSortBy, { sortBy: currentSortBy, sortOrder }) => {
|
||||
// sort prop is the same, toggle
|
||||
if (currentSortBy === newSortBy) {
|
||||
return dispatch(
|
||||
set({
|
||||
name: SGC_T_SO_V,
|
||||
value: sortOrder === 'desc' ? 'asc' : 'desc'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
dispatch([
|
||||
set({
|
||||
name: SGC_T_SO_V,
|
||||
value: 'desc'
|
||||
}),
|
||||
set({
|
||||
name: SGC_T_SB_V,
|
||||
value: newSortBy
|
||||
})
|
||||
]);
|
||||
}
|
||||
};
|
||||
}
|
||||
)
|
||||
)(Template);
|
141
consoles/my-joy-service-groups/src/containers/summary.js
Normal file
141
consoles/my-joy-service-groups/src/containers/summary.js
Normal file
@ -0,0 +1,141 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { If, Then, Else } from 'react-if';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import intercept from 'apr-intercept';
|
||||
import isString from 'lodash.isstring';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
StatusLoader,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Meta, EventLogContainer } from '@components/summary';
|
||||
import GetServiceGroup from '@graphql/get-service-group.gql';
|
||||
import RemoveServiceGroup from '@graphql/remove-service-group.gql';
|
||||
import ListServiceGroups from '@graphql/list-service-groups.gql';
|
||||
import { Values } from '@root/constants';
|
||||
import parseError from '@state/parse-error';
|
||||
import Confirm from '@state/confirm';
|
||||
|
||||
const { SGS_R_V, SGS_E_V } = Values;
|
||||
|
||||
const Summary = ({
|
||||
loading = false,
|
||||
error = null,
|
||||
group = null,
|
||||
removing = false,
|
||||
handleRemove
|
||||
}) => (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<If condition={error}>
|
||||
<Then>
|
||||
<Margin bottom="3">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
<If condition={isString(error)}>
|
||||
<Then>
|
||||
<Fragment>{error}</Fragment>
|
||||
</Then>
|
||||
<Else>
|
||||
<Fragment>
|
||||
An error occurred while loading your service groups
|
||||
</Fragment>
|
||||
</Else>
|
||||
</If>
|
||||
</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</Then>
|
||||
</If>
|
||||
<If condition={loading && !group}>
|
||||
<Then>
|
||||
<StatusLoader />
|
||||
</Then>
|
||||
<Else>
|
||||
<Fragment>
|
||||
<Margin bottom="5">
|
||||
<Meta {...group} removing={removing} onRemove={handleRemove} />
|
||||
</Margin>
|
||||
<EventLogContainer />
|
||||
</Fragment>
|
||||
</Else>
|
||||
</If>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
graphql(RemoveServiceGroup, { name: 'removeGroup' }),
|
||||
graphql(GetServiceGroup, {
|
||||
options: ({ match }) => ({
|
||||
ssr: true,
|
||||
pollInterval: 1000,
|
||||
variables: {
|
||||
id: get(match, 'params.sg')
|
||||
}
|
||||
}),
|
||||
props: ({ data: { loading, networkStatus, error, group } }) => ({
|
||||
loading: networkStatus === 1,
|
||||
error,
|
||||
group
|
||||
})
|
||||
}),
|
||||
connect(
|
||||
({ values }, { group = {}, error: loadingError }) => ({
|
||||
error: Boolean(loadingError) || get(values, SGS_E_V(group.id), false),
|
||||
removing: get(values, SGS_R_V(group.id), false)
|
||||
}),
|
||||
(dispatch, { history, group, removeGroup }) => ({
|
||||
handleDefocus: name => value => {
|
||||
return dispatch(set({ name, value }));
|
||||
},
|
||||
handleRemove: async () => {
|
||||
const { id, name } = group;
|
||||
if (!await Confirm(`Do you want to remove ${name}?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(set({ name: SGS_R_V(id), value: true }));
|
||||
|
||||
const [err] = await intercept(
|
||||
removeGroup({
|
||||
variables: { id },
|
||||
update: proxy => {
|
||||
try {
|
||||
proxy.writeQuery({
|
||||
query: ListServiceGroups,
|
||||
data: {
|
||||
groups: proxy
|
||||
.readQuery({ query: ListServiceGroups })
|
||||
.groups.filter(g => g.id !== id)
|
||||
}
|
||||
});
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(
|
||||
[
|
||||
set({ name: SGS_R_V(id), value: false }),
|
||||
err ? set({ name: SGS_E_V(id), value: parseError(err) }) : undefined
|
||||
].filter(Boolean)
|
||||
);
|
||||
|
||||
history.push('/service-groups');
|
||||
}
|
||||
})
|
||||
)
|
||||
)(Summary);
|
@ -0,0 +1,16 @@
|
||||
mutation createServiceGroup($name: String!, $template: ID!, $capacity: Int!) {
|
||||
createGroup(name: $name, template: $template, capacity: $capacity) {
|
||||
id
|
||||
name
|
||||
template {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
created
|
||||
}
|
||||
capacity
|
||||
created
|
||||
updated
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
query group($id: ID!) {
|
||||
group(id: $id) {
|
||||
id
|
||||
name
|
||||
template {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
created
|
||||
}
|
||||
capacity
|
||||
created
|
||||
updated
|
||||
}
|
||||
}
|
20
consoles/my-joy-service-groups/src/graphql/get-template.gql
Normal file
20
consoles/my-joy-service-groups/src/graphql/get-template.gql
Normal file
@ -0,0 +1,20 @@
|
||||
query template($id: ID!) {
|
||||
template(id: $id) {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
enableFirewall
|
||||
networks
|
||||
userdata
|
||||
metadata {
|
||||
name
|
||||
value
|
||||
}
|
||||
tags {
|
||||
name
|
||||
value
|
||||
}
|
||||
created
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
query groups {
|
||||
groups {
|
||||
id
|
||||
name
|
||||
template {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
created
|
||||
}
|
||||
capacity
|
||||
created
|
||||
updated
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
query templates {
|
||||
templates {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
created
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
mutation removeServiceGroup($id: ID!) {
|
||||
deleteGroup(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
mutation updateServiceGroup(
|
||||
$id: ID!
|
||||
$name: String!
|
||||
$template: ID!
|
||||
$capacity: Int!
|
||||
) {
|
||||
updateGroup(id: $id, name: $name, template: $template, capacity: $capacity) {
|
||||
id
|
||||
name
|
||||
template {
|
||||
id
|
||||
name
|
||||
package
|
||||
image
|
||||
created
|
||||
}
|
||||
capacity
|
||||
created
|
||||
updated
|
||||
}
|
||||
}
|
28
consoles/my-joy-service-groups/src/html.js
Normal file
28
consoles/my-joy-service-groups/src/html.js
Normal file
@ -0,0 +1,28 @@
|
||||
const React = require('react');
|
||||
|
||||
module.exports = ({
|
||||
htmlAttrs = {},
|
||||
bodyAttrs = {},
|
||||
head = [],
|
||||
children = null
|
||||
}) => (
|
||||
<html {...htmlAttrs}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
|
||||
/>
|
||||
<meta name="theme-color" content="#1E313B" />
|
||||
|
||||
{head}
|
||||
</head>
|
||||
<body {...bodyAttrs}>
|
||||
<div id="header" />
|
||||
{children ? null : <div id="root" />}
|
||||
{children}
|
||||
<script src="/navigation/static/main.js" />
|
||||
</body>
|
||||
</html>
|
||||
);
|
33
consoles/my-joy-service-groups/src/index.js
Normal file
33
consoles/my-joy-service-groups/src/index.js
Normal file
@ -0,0 +1,33 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
import { ApolloProvider } from 'react-apollo';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import isFunction from 'lodash.isfunction';
|
||||
import isFinite from 'lodash.isfinite';
|
||||
|
||||
import theme from '@state/theme';
|
||||
import createStore from '@state/redux-store';
|
||||
import createClient from '@state/apollo-client';
|
||||
import App from './app';
|
||||
|
||||
if (!isFunction(Number.isFinite)) {
|
||||
Number.isFinite = isFinite;
|
||||
}
|
||||
|
||||
ReactDOM.hydrate(
|
||||
<ApolloProvider client={createClient()}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ReduxProvider store={createStore()}>
|
||||
<BrowserRouter>
|
||||
<HelmetProvider context={{}}>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
</BrowserRouter>
|
||||
</ReduxProvider>
|
||||
</ThemeProvider>
|
||||
</ApolloProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
6
consoles/my-joy-service-groups/src/mocks/__aliases__.js
Normal file
6
consoles/my-joy-service-groups/src/mocks/__aliases__.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
'^redux-form$': '<rootDir>/src/mocks/redux-form',
|
||||
'^react-responsive$': '<rootDir>/src/mocks/react-responsive',
|
||||
'^react-router-dom$': '<rootDir>/src/mocks/react-router-dom',
|
||||
'^declarative-redux-form$': '<rootDir>/src/mocks/declarative-redux-form'
|
||||
};
|
@ -0,0 +1,3 @@
|
||||
import React from 'react';
|
||||
|
||||
export default ({ children, ...props }) => React.createElement(children, props);
|
7
consoles/my-joy-service-groups/src/mocks/react-responsive.js
vendored
Normal file
7
consoles/my-joy-service-groups/src/mocks/react-responsive.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
export default ({ query, children }) => (
|
||||
<span name="react-responsive-mock" query={query}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
4
consoles/my-joy-service-groups/src/mocks/react-router-dom.js
vendored
Normal file
4
consoles/my-joy-service-groups/src/mocks/react-router-dom.js
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
import React from 'react';
|
||||
|
||||
export const Field = ({ children, ...rest }) =>
|
||||
React.createElement('a', rest, children);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user