Compare commits

...

57 Commits

Author SHA1 Message Date
johnytiago
078513f603 feat(instances): adds cli-details UI 2018-06-04 14:30:07 +01:00
Fábio Moreira
a1ff036db1 test(instances): updates snapshots 2018-06-04 12:48:09 +01:00
Fábio Moreira
fc81d666d0 feat(instances): CI - firewall responsive designs 2018-06-04 12:48:09 +01:00
Fábio Moreira
deb1a8436f feat(instances): user scripts responsive designs 2018-06-04 12:48:09 +01:00
Fábio Moreira
cad1431e79 feat(instances): CI - metadata resposive 2018-06-04 12:48:09 +01:00
Fábio Moreira
2f9d135319 feat(instances): CI - Responsive behavior for tags #1121 2018-06-04 12:48:09 +01:00
Fábio Moreira
c268d88a4d feat(instances): create instance - networks responsive next button 2018-06-04 12:48:09 +01:00
Fábio Moreira
6698a8eacb feat(ui-toolkit): key-value responsive 2018-06-04 12:48:09 +01:00
Fábio Moreira
1e8e89b3c8 feat(instances): theme resizer 2018-06-04 12:48:09 +01:00
Sérgio Ramos
063e40859d feat(sg): bootstrap 2018-06-04 11:46:08 +01:00
Sérgio Ramos
fc84358dff feat(templates): bootstrap 2018-06-04 11:46:08 +01:00
Fábio Moreira
6736caaf45
Implement responsive designs for CI: Networks (#1438)
* feat(instances): network section responive behaviour

* feat(instances): adjust network info container width

* test(instances): update network step snapshot

* test(instances): update network step snapshots
2018-05-28 13:38:21 +01:00
Fábio Moreira
5cb02d709c feat(instances): responsive layout for instance name card
fixes #1118
2018-05-24 10:34:55 +01:00
Fábio Moreira
b66f761a9e
#1406 - implement responsive rules on create instance (#1432)
* fix(instances): swap absolute media query value for defined breakpoint

* feat(ui-toolkit): update breakpoints

* feat(ui-toolkit): view container padding and max width

* feat(ui-toolkit): responsive image selector

* fix(ui-toolkit): delay parallax header hiding

* feat(instances): responsive rules for package selection

* test(instances): update snapshots

* fix(instances): use color variables on package card

* fix(instances): import breakpoints from ui-toolkit

* feat(instances): package selection for mobile or desktop version

* feat(instances): remove unnecessary col css props

* test(instances): update snapshots

* test(instances): update resource widgets snaphots
2018-05-23 12:41:40 +01:00
johnytiago
8422cdfe8c feat(instances): QA Instance Managment bug fixes. closes #1423 2018-05-21 11:37:26 +01:00
Joao Tiago
109988536b feat(instances): Fixes collase typo 2018-05-18 13:48:09 +01:00
johnytiago
d75ae0f14f feat(instances): Adds font antialiasing. closes #1418 2018-05-18 13:47:27 +01:00
johnytiago
5c98a4cecb feat(instances): refactor card headers #1417 2018-05-17 20:01:44 +01:00
johnytiago
0189822a08 feat(instances): bug fixes #1387 2018-05-17 18:14:00 +01:00
johnytiago
5d46689869 feat(instances): Adds better element ids 2018-05-17 18:03:08 +01:00
johnytiago
04cb9c32f8 feat(instances): Firewall empty state update, more QA 2018-05-17 17:50:11 +01:00
Fábio Moreira
8e6adb1ef4 test: update snapshots 2018-05-16 17:06:21 +01:00
Fábio Moreira
a1154b2520 feat(ui-toolkit): improve parallax scroll behaviour 2018-05-16 17:06:21 +01:00
Fábio Moreira
155a065281 feat(ui-toolkit): update spacing guidelines 2018-05-16 17:06:21 +01:00
Fábio Moreira
f388e52549 fix(ui-toolkit): add margin to playground tab headers 2018-05-16 17:06:21 +01:00
Fábio Moreira
882085a170 feat(ui-toolkit): skip parallax header after user scrolls 2018-05-16 17:06:21 +01:00
Fábio Moreira
77fd895b6c feat(ui-toolkit): add parallax header after scroll 2018-05-16 17:06:21 +01:00
Fábio Moreira
bd332423be feat(ui-toolkit): define next section for empty link 2018-05-16 17:06:21 +01:00
Fábio Moreira
91e1fb192b feat(ui-toolkit): refator bottomNav to work for subSections 2018-05-16 17:06:21 +01:00
Fábio Moreira
88fe0ea92d feat(ui-toolkit): replace bottom nav arrows with html entities 2018-05-16 17:06:21 +01:00
Fábio Moreira
8bb4c31aba feat(ui-toolkit): add bottom nav to jump to previous or next session 2018-05-16 17:06:21 +01:00
Fábio Moreira
867e9b35a0 fix(instances): change packages text and link 2018-05-11 12:58:56 +01:00
Fábio Moreira
574c3add4e fix(ui-toolkit): remove horizontal scroll on styleguide #1384 2018-05-11 12:58:27 +01:00
Fábio Moreira
c233b0d757 fix(ui-toolkit): styleguide minor bugs 2018-05-11 12:58:27 +01:00
johnytiago
84b2d67d2c feat(instances): Adds Counts, Updates Firewall 2018-05-11 12:57:39 +01:00
johnytiago
062ff0ba67 feat(instances): status icon cross, cns tags color 2018-05-11 12:57:39 +01:00
Sérgio Ramos
b00baa7028 fix(instances): don't send cns names unless they exist 2018-05-09 14:24:07 +01:00
Fábio Moreira
588b833045 fix(ui-toolkit): replace styled card with card component on section 2018-05-09 12:17:20 +01:00
Sérgio Ramos
b3edb3aa02 fix(instances): handle name/identity aff props 2018-05-09 12:06:10 +01:00
Sérgio Ramos
542b491b52 refactor(instances): s/network/networks 2018-05-09 11:36:16 +01:00
Sérgio Ramos
7d8b478d20 test(instances): update snapshots 2018-05-09 11:29:17 +01:00
Joao Tiago
7531e503f2 fix(instances): Save -> Next, Create takes to name card (#1411) 2018-05-09 11:27:33 +01:00
Sérgio Ramos
d1b2ba0002 fix(instances): add Next button to fw 2018-05-09 11:22:27 +01:00
Sérgio Ramos
98a8b2eb5b fix(instances): send tags when creating instance 2018-05-09 11:21:40 +01:00
Sérgio Ramos
de356e1fbe fix(instances): send user-script when creating instance 2018-05-09 11:11:03 +01:00
Sérgio Ramos
f9c89cbccc fix(instances): send network ids when creating instance 2018-05-09 10:57:37 +01:00
johnytiago
1317894f27 feat(instances): wip networks, tags 2018-05-09 10:52:31 +01:00
Sérgio Ramos
f007889283 fix: try to serve a static route before maping assets 2018-05-09 10:34:49 +01:00
Sérgio Ramos
831be94521 build: fix ssr build 2018-05-09 00:03:57 +01:00
Sérgio Ramos
e321c20906 fix(instances): s/userScript/user-script 2018-05-08 18:02:01 +01:00
Sérgio Ramos
429ad17262 refactor(instances): better disabled/isValid handling 2018-05-08 17:55:06 +01:00
Sérgio Ramos
d591d93547 fix: prevent image card from growing to much 2018-05-08 16:55:18 +01:00
Sérgio Ramos
33d3d4343d fix: add margins to section-list/menu 2018-05-08 16:00:11 +01:00
johnytiago
32d5cdc293 refactor(instances): refactor create instance flow
fixes #1354
2018-05-08 15:32:10 +01:00
johnytiago
316773d9b7 feat(ui-toolkit): remove all margins
fixes #1156
2018-05-08 15:32:10 +01:00
Sérgio Ramos
0ae1290a5e feat: support ssr on bundle 2018-05-07 13:34:10 +01:00
Sérgio Ramos
3f75f812fa feat: add support for react-helmet 2018-05-07 12:09:12 +01:00
1053 changed files with 86709 additions and 109998 deletions

View File

@ -1,4 +1,9 @@
packages/*/**
prototypes/*/**
artifacts artifacts
reports reports
.nyc_output
coverage
dist
styleguide
build
consoles/*/lib/app
node_modules

View File

@ -1,8 +1,10 @@
{ {
"extends": "joyent-portal", "extends": "joyent-portal",
"rules": { "rules": {
"jsx-a11y/href-no-hash": 0, "no-console": 1,
"new-cap": 0, "new-cap": 0,
"no-console": 0 "jsx-a11y/href-no-hash": 0,
"no-negated-condition": 1,
"camelcase": 1
} }
} }

2
.gitignore vendored
View File

@ -165,3 +165,5 @@ prototypes/*/package-lock.json
_env* _env*
keys* keys*
/packages/*/public/index.html
/consoles/*/public/index.html

View File

@ -15,6 +15,7 @@ yarn.lock
dist dist
build build
packages/*/lib/app packages/*/lib/app
consoles/*/lib/app
*.ico *.ico
*.html *.html

1
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -9,24 +9,23 @@
"build:lib": "echo 0", "build:lib": "echo 0",
"build:bundle": "echo 0", "build:bundle": "echo 0",
"prepublish": "echo 0", "prepublish": "echo 0",
"lint": "echo 0",
"lint:ci": "echo 0",
"test": "echo 0", "test": "echo 0",
"test:ci": "echo 0" "test:ci": "echo 0"
}, },
"dependencies": { "dependencies": {
"apr-main": "^4.0.3", "apr-main": "^4.0.3",
"brule": "^3.1.0", "cloudapi-gql": "^8.0.0",
"cloudapi-gql": "^7.1.4",
"execa": "^0.10.0", "execa": "^0.10.0",
"h2o2": "^8.0.1", "graphi": "^5.7.0",
"hapi": "^17.3.1", "h2o2": "^8.1.2",
"hapi-triton-auth": "^2.0.1", "hapi": "^17.5.0",
"hapi-webconsole-nav": "^1.2.0", "hapi-triton-auth": "^3.0.0",
"inert": "^5.1.0", "hapi-webconsole-nav": "^2.1.0",
"my-joy-images": "*", "my-joy-images": "*",
"my-joy-instances": "*", "my-joy-instances": "*",
"my-joy-navigation": "*", "my-joy-navigation": "*",
"rollover": "^1.0.0" "my-joy-service-groups": "*",
"my-joy-templates": "*",
"tsg-graphql": "^1.0.0"
} }
} }

View File

@ -1,7 +1,12 @@
require('../.env.js');
const Main = require('apr-main'); const Main = require('apr-main');
const CloudApiGql = require('cloudapi-gql'); const CloudApiGql = require('cloudapi-gql');
const Graphi = require('graphi');
const Url = require('url'); const Url = require('url');
const Server = require('./server'); const Server = require('./server');
const Ui = require('my-joy-images');
const { const {
PORT = 4003, PORT = 4003,
@ -25,7 +30,19 @@ Main(async () => {
BASE_URL BASE_URL
}); });
await server.register({ await server.register([
{
plugin: Graphi,
options: {
graphqlPath: '/graphql',
graphiqlPath: '/graphiql',
authStrategy: 'sso'
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: CloudApiGql, plugin: CloudApiGql,
options: { options: {
authStrategy: 'sso', authStrategy: 'sso',
@ -37,7 +54,11 @@ Main(async () => {
routes: { routes: {
prefix: `/${PREFIX}` prefix: `/${PREFIX}`
} }
}); },
{
plugin: Ui
}
]);
await server.start(); await server.start();
}); });

View File

@ -1,7 +1,12 @@
require('../.env.js');
const Main = require('apr-main'); const Main = require('apr-main');
const CloudApiGql = require('cloudapi-gql'); const CloudApiGql = require('cloudapi-gql');
const Graphi = require('graphi');
const Url = require('url'); const Url = require('url');
const Server = require('./server'); const Server = require('./server');
const Ui = require('my-joy-instances');
const { const {
PORT = 4002, PORT = 4002,
@ -25,7 +30,19 @@ Main(async () => {
BASE_URL BASE_URL
}); });
await server.register({ await server.register([
{
plugin: Graphi,
options: {
graphqlPath: '/graphql',
graphiqlPath: '/graphiql',
authStrategy: 'sso'
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: CloudApiGql, plugin: CloudApiGql,
options: { options: {
authStrategy: 'sso', authStrategy: 'sso',
@ -37,7 +54,11 @@ Main(async () => {
routes: { routes: {
prefix: `/${PREFIX}` prefix: `/${PREFIX}`
} }
}); },
{
plugin: Ui
}
]);
await server.start(); await server.start();
}); });

View File

@ -1,7 +1,12 @@
require('../.env.js');
const Main = require('apr-main'); const Main = require('apr-main');
const Nav = require('hapi-webconsole-nav'); const Nav = require('hapi-webconsole-nav');
const Graphi = require('graphi');
const Url = require('url'); const Url = require('url');
const Server = require('./server'); const Server = require('./server');
const Ui = require('my-joy-navigation');
const Regions = require('../data/regions'); const Regions = require('../data/regions');
const Categories = require('../data/categories'); const Categories = require('../data/categories');
@ -30,7 +35,19 @@ Main(async () => {
BASE_URL BASE_URL
}); });
await server.register({ await server.register([
{
plugin: Graphi,
options: {
graphqlPath: '/graphql',
graphiqlPath: '/graphiql',
authStrategy: 'sso'
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: Nav, plugin: Nav,
options: { options: {
keyPath, keyPath,
@ -45,7 +62,11 @@ Main(async () => {
routes: { routes: {
prefix: `/${PREFIX}` prefix: `/${PREFIX}`
} }
}); },
{
plugin: Ui
}
]);
await server.start(); await server.start();
}); });

View File

@ -1,6 +1,7 @@
require('../.env.js');
const Hapi = require('hapi'); const Hapi = require('hapi');
const Sso = require('hapi-triton-auth'); const Sso = require('hapi-triton-auth');
const Url = require('url');
const { const {
COOKIE_PASSWORD, COOKIE_PASSWORD,
@ -8,12 +9,10 @@ const {
SDC_KEY_PATH, SDC_KEY_PATH,
SDC_ACCOUNT, SDC_ACCOUNT,
SDC_KEY_ID, SDC_KEY_ID,
SDC_URL, SDC_URL
DC_NAME
} = process.env; } = process.env;
module.exports = async ({ PORT, BASE_URL }) => { module.exports = async ({ PORT, BASE_URL }) => {
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
const keyPath = SDC_KEY_PATH; const keyPath = SDC_KEY_PATH;
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`; const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
const apiBaseUrl = SDC_URL; const apiBaseUrl = SDC_URL;
@ -50,6 +49,7 @@ module.exports = async ({ PORT, BASE_URL }) => {
server.events.on('log', (event, tags) => { server.events.on('log', (event, tags) => {
if (tags.error) { if (tags.error) {
// eslint-disable-next-line no-console
console.log(event); console.log(event);
} }
}); });
@ -58,6 +58,7 @@ module.exports = async ({ PORT, BASE_URL }) => {
const { tags } = event; const { tags } = event;
if (tags.includes('error') && event.data && event.data.errors) { if (tags.includes('error') && event.data && event.data.errors) {
event.data.errors.forEach(error => { event.data.errors.forEach(error => {
// eslint-disable-next-line no-console
console.log(error); console.log(error);
}); });
} }

View File

@ -0,0 +1,78 @@
require('../.env.js');
const Main = require('apr-main');
const CloudApiGql = require('cloudapi-gql');
const Tsg = require('tsg-graphql');
const Graphi = require('graphi');
const Url = require('url');
const Server = require('./server');
const Ui = require('my-joy-service-groups');
const {
PORT = 4004,
BASE_URL = `http://0.0.0.0:${PORT}`,
PREFIX = 'service-groups',
DC_NAME,
TSG_URL = 'http://0.0.0.0:3000',
SDC_URL,
SDC_KEY_PATH,
SDC_ACCOUNT,
SDC_KEY_ID
} = process.env;
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
const keyPath = SDC_KEY_PATH;
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
Main(async () => {
const server = await Server({
PORT,
BASE_URL
});
await server.register([
{
plugin: Graphi,
options: {
graphqlPath: '/graphql',
graphiqlPath: '/graphiql',
authStrategy: 'sso'
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: Tsg,
options: {
authStrategy: 'sso',
keyPath,
keyId,
apiBaseUrl: TSG_URL,
dcName
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: CloudApiGql,
options: {
authStrategy: 'sso',
keyPath,
keyId,
apiBaseUrl: SDC_URL,
dcName
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: Ui
}
]);
await server.start();
});

78
bundle/src/templates.js Normal file
View File

@ -0,0 +1,78 @@
require('../.env.js');
const Main = require('apr-main');
const CloudApiGql = require('cloudapi-gql');
const Tsg = require('tsg-graphql');
const Graphi = require('graphi');
const Url = require('url');
const Server = require('./server');
const Ui = require('my-joy-templates');
const {
PORT = 4005,
BASE_URL = `http://0.0.0.0:${PORT}`,
PREFIX = 'templates',
DC_NAME,
TSG_URL = 'http://0.0.0.0:3000',
SDC_URL,
SDC_KEY_PATH,
SDC_ACCOUNT,
SDC_KEY_ID
} = process.env;
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
const keyPath = SDC_KEY_PATH;
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
Main(async () => {
const server = await Server({
PORT,
BASE_URL
});
await server.register([
{
plugin: Graphi,
options: {
graphqlPath: '/graphql',
graphiqlPath: '/graphiql',
authStrategy: 'sso'
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: Tsg,
options: {
authStrategy: 'sso',
keyPath,
keyId,
apiBaseUrl: TSG_URL,
dcName
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: CloudApiGql,
options: {
authStrategy: 'sso',
keyPath,
keyId,
apiBaseUrl: SDC_URL,
dcName
},
routes: {
prefix: `/${PREFIX}`
}
},
{
plugin: Ui
}
]);
await server.start();
});

View File

@ -4,7 +4,16 @@ module.exports = {
'scope-enum': [ 'scope-enum': [
2, 2,
'always', 'always',
['ui-toolkit', 'icons', 'instances', 'navigation', 'bundle', 'images'] [
'ui-toolkit',
'icons',
'instances',
'navigation',
'bundle',
'images',
'sg',
'templates'
]
] ]
} }
}; };

View File

@ -1,16 +1,29 @@
const Boom = require('boom');
const Inert = require('inert'); const Inert = require('inert');
const Path = require('path'); const Path = require('path');
const RenderReact = require('hapi-render-react'); const RenderReact = require('hapi-render-react');
const Wreck = require('wreck');
const Url = require('url');
const Intercept = require('apr-intercept'); const Intercept = require('apr-intercept');
const Fs = require('mz/fs'); const Fs = require('mz/fs');
const { NAMESPACE = 'instances' } = process.env; const { NAMESPACE = 'images', NODE_ENV = 'development' } = process.env;
exports.register = async server => { 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 relativeTo = Path.join(__dirname, 'app');
const buildRoot = Path.join(__dirname, `../build/${NAMESPACE}/static/`); const buildRoot = Path.join(__dirname, '../build');
const buildStatic = Path.join(buildRoot, `${NAMESPACE}`);
const publicRoot = Path.join(__dirname, `../public/static/`); const publicRoot = Path.join(__dirname, `../public/static/`);
await server.register([ await server.register([
@ -57,15 +70,41 @@ exports.register = async server => {
const { params } = request; const { params } = request;
const { rest } = params; const { rest } = params;
const publicPathname = Path.join(publicRoot, rest); if (!rest) {
const buildPathname = Path.join(buildRoot, rest); return Boom.notFound();
}
const [err] = await Intercept( const publicPathname = Path.join(publicRoot, rest);
const [err1] = await Intercept(
Fs.access(publicPathname, Fs.constants.R_OK) Fs.access(publicPathname, Fs.constants.R_OK)
); );
const file = err ? buildPathname : publicPathname; if (!err1) {
return h.file(file, { confine: false }); 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
});
} }
}, },
{ {

View File

@ -6,13 +6,11 @@
"repository": "github:yldio/joyent-portal", "repository": "github:yldio/joyent-portal",
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "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:test": "echo 0",
"build:lib": "echo 0", "build:lib": "echo 0",
"build:bundle": "NAMESPACE=images NODE_ENV=production redrun -p build:frontend build:ssr", "build:bundle": "NAMESPACE=images NODE_ENV=production redrun -p build:frontend build:ssr",
"prepublish": "NODE_ENV=production redrun build:bundle", "prepublish": "NODE_ENV=production redrun build:bundle",
"lint": "redrun lint:ci -- --fix",
"lint:ci": "NODE_ENV=test eslint . --ext .js --ext .md",
"test": "echo 0", "test": "echo 0",
"test:ci": "echo 0", "test:ci": "echo 0",
"build:frontend": "joyent-react-scripts build", "build:frontend": "joyent-react-scripts build",
@ -21,22 +19,24 @@
"dependencies": { "dependencies": {
"@manaflair/redux-batch": "^0.1.0", "@manaflair/redux-batch": "^0.1.0",
"apollo": "^0.2.2", "apollo": "^0.2.2",
"apollo-cache-inmemory": "^1.1.12", "apollo-cache-inmemory": "^1.2.2",
"apollo-client": "^2.2.8", "apollo-client": "^2.3.2",
"apollo-link-http": "^1.5.3", "apollo-link-http": "^1.5.4",
"apr-intercept": "^3.0.3", "apr-intercept": "^3.0.3",
"apr-reduce": "^3.0.3", "apr-reduce": "^3.0.3",
"cross-fetch": "^2.1.0", "boom": "^7.2.0",
"cross-fetch": "^2.2.0",
"date-fns": "^1.29.0", "date-fns": "^1.29.0",
"declarative-redux-form": "^2.0.8", "declarative-redux-form": "^2.0.8",
"exenv": "^1.2.2", "exenv": "^1.2.2",
"force-array": "^3.1.0", "force-array": "^3.1.0",
"fuse.js": "^3.2.0", "fuse.js": "^3.2.0",
"hapi-render-react": "^2.5.2", "hapi-render-react": "^2.5.2",
"hapi-render-react-joyent-document": "^5.0.0", "hapi-render-react-joyent-document": "^7.2.0",
"inert": "^5.1.0", "inert": "^5.1.0",
"joyent-logo-assets": "^1.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", "joyent-ui-toolkit": "^6.0.0",
"lodash.assign": "^4.2.0", "lodash.assign": "^4.2.0",
"lodash.find": "^4.6.0", "lodash.find": "^4.6.0",
@ -46,36 +46,37 @@
"lodash.keys": "^4.2.0", "lodash.keys": "^4.2.0",
"lodash.omit": "^4.5.0", "lodash.omit": "^4.5.0",
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"lunr": "^2.1.6", "lunr": "^2.2.1",
"mz": "^2.7.0", "mz": "^2.7.0",
"param-case": "^2.1.1", "param-case": "^2.1.1",
"react": "^16.3.1", "react": "^16.4.0",
"react-apollo": "^2.1.2", "react-apollo": "^2.1.4",
"react-dom": "^16.3.1", "react-dom": "^16.4.0",
"react-helmet-async": "0.1.0",
"react-redux": "^5.0.7", "react-redux": "^5.0.7",
"react-redux-values": "^1.1.2", "react-redux-values": "^1.1.2",
"react-router": "^4.2.0", "react-router": "^4.2.0",
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"redux": "^3.7.2", "redux": "^4.0.0",
"redux-form": "^7.3.0", "redux-form": "^7.3.0",
"remcalc": "^1.0.10", "remcalc": "^1.0.10",
"styled-components": "^3.2.5", "styled-components": "^3.3.0",
"styled-components-spacing": "^2.1.3", "styled-components-spacing": "^3.0.0",
"styled-flex-component": "^2.2.2", "styled-flex-component": "^2.2.2",
"styled-is": "^1.1.2", "styled-is": "^1.1.3",
"title-case": "^2.1.1", "title-case": "^2.1.1",
"yup": "^0.24.1" "yup": "^0.25.1"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",
"babel-preset-joyent-portal": "^7.0.1", "babel-preset-joyent-portal": "^7.0.1",
"eslint": "^4.19.1", "eslint": "^4.19.1",
"eslint-config-joyent-portal": "^3.3.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", "jest-styled-components": "^5.0.1",
"joyent-react-scripts": "^8.0.3", "joyent-react-scripts": "^8.2.1",
"react-screenshot-renderer": "^1.1.2", "react-screenshot-renderer": "^1.1.2",
"react-test-renderer": "^16.3.1", "react-test-renderer": "^16.4.0",
"redrun": "^6.0.2" "redrun": "^6.0.4"
} }
} }

View File

@ -51,6 +51,7 @@ const getState = request => {
module.exports = Document({ module.exports = Document({
namespace: 'images/', namespace: 'images/',
assets, assets,
Html: require('./html'),
indexFile, indexFile,
getState getState
}); });

View File

@ -1,10 +1,14 @@
import React from 'react'; import React from 'react';
import Helmet from 'react-helmet-async';
import { RootContainer } from 'joyent-ui-toolkit'; import { RootContainer } from 'joyent-ui-toolkit';
import Routes from '@root/routes'; import Routes from '@root/routes';
export default () => ( export default () => (
<RootContainer> <RootContainer>
<Helmet>
<title>Images</title>
</Helmet>
<Routes /> <Routes />
</RootContainer> </RootContainer>
); );

View File

@ -2,11 +2,9 @@ import React from 'react';
import { Field } from 'redux-form'; import { Field } from 'redux-form';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import Flex, { FlexItem } from 'styled-flex-component'; import Flex, { FlexItem } from 'styled-flex-component';
import remcalc from 'remcalc';
import { Row, Col } from 'joyent-react-styled-flexboxgrid'; import { Row, Col } from 'joyent-react-styled-flexboxgrid';
import { import {
Divider,
FormGroup, FormGroup,
FormLabel, FormLabel,
Input, Input,
@ -22,18 +20,16 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
<FlexItem flex> <FlexItem flex>
<FormGroup name="name" fluid field={Field}> <FormGroup name="name" fluid field={Field}>
<FormLabel>Image name</FormLabel> <FormLabel>Image name</FormLabel>
<Margin top={0.5}> <Margin top="0.5">
<Input placeholder={placeholderName} onBlur={null} required /> <Input placeholder={placeholderName} onBlur={null} required />
</Margin> </Margin>
<FormMeta /> <FormMeta />
</FormGroup> </FormGroup>
</FlexItem> </FlexItem>
<FlexItem> <FlexItem>
<Divider height={remcalc(13)} transparent /> <Margin left="1">
<Margin left={1}>
<Button <Button
type="button" type="button"
marginTop={remcalc(8)}
onClick={onRandomize} onClick={onRandomize}
loading={randomizing} loading={randomizing}
marginless marginless
@ -46,21 +42,21 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
</Margin> </Margin>
</FlexItem> </FlexItem>
</Flex> </Flex>
<Margin top={3}> <Margin top="3">
<FormGroup name="version" fluid field={Field}> <FormGroup name="version" fluid field={Field}>
<FormLabel>Version</FormLabel> <FormLabel>Version</FormLabel>
<Margin top={0.5}> <Margin top="0.5">
<Input placeholder="Example: v1.0" onBlur={null} required /> <Input placeholder="Example: v1.0" onBlur={null} required />
</Margin> </Margin>
<FormMeta /> <FormMeta />
</FormGroup> </FormGroup>
</Margin> </Margin>
<Row> <Row>
<Col xs={12} sm={8}> <Col xs="12" sm="8">
<Margin top={3}> <Margin top="3">
<FormGroup name="description" fluid field={Field}> <FormGroup name="description" fluid field={Field}>
<FormLabel>Description</FormLabel> <FormLabel>Description</FormLabel>
<Margin top={0.5}> <Margin top="0.5">
<Textarea <Textarea
placeholder="Example: JarJarBinks, Anakin Skywalker, Obi Wan Kenobi, Qui-Gon Jinn, Han Solo, Wookies" placeholder="Example: JarJarBinks, Anakin Skywalker, Obi Wan Kenobi, Qui-Gon Jinn, Han Solo, Wookies"
fluid fluid

View File

@ -16,14 +16,14 @@ const Container = styled.div`
export default ({ icon, children, collapsed = true, ...rest }) => ( export default ({ icon, children, collapsed = true, ...rest }) => (
<Container {...rest}> <Container {...rest}>
<Flex> <Flex>
<Margin right={1}> <Margin right="1">
<Flex alignCenter full> <Flex alignCenter full>
{icon} {icon}
</Flex> </Flex>
</Margin> </Margin>
<Small noMargin>{children}</Small> <Small noMargin>{children}</Small>
</Flex> </Flex>
<Margin top={1} bottom={collapsed ? 7 : 3}> <Margin top="1" bottom={collapsed ? 7 : 3}>
<Divider height={remcalc(1)} /> <Divider height={remcalc(1)} />
</Margin> </Margin>
</Container> </Container>

View File

@ -5,8 +5,8 @@ import { P } from 'joyent-ui-toolkit';
export default ({ children }) => ( export default ({ children }) => (
<Row> <Row>
<Col xs={12} sm={8}> <Col xs="12" sm="8">
<Margin bottom={3}> <Margin bottom="3">
<P>{children}</P> <P>{children}</P>
</Margin> </Margin>
</Col> </Col>

View File

@ -4,7 +4,7 @@ import { Margin, Padding } from 'styled-components-spacing';
import Flex from 'styled-flex-component'; import Flex from 'styled-flex-component';
import { H3, Card } from 'joyent-ui-toolkit'; import { H3, Card } from 'joyent-ui-toolkit';
import { NoPackages } from 'joyent-logo-assets'; import { EmptyState } from 'joyent-icons';
const NoPackagesTitle = styled(H3)` const NoPackagesTitle = styled(H3)`
color: ${props => props.theme.greyDark}; color: ${props => props.theme.greyDark};
@ -17,10 +17,10 @@ const FullWidthCard = styled(Card)`
export default ({ children }) => ( export default ({ children }) => (
<FullWidthCard> <FullWidthCard>
<Padding all={6}> <Padding all="6">
<Flex alignCenter justifyCenter column> <Flex alignCenter justifyCenter column>
<Margin bottom={2}> <Margin bottom="2">
<NoPackages /> <EmptyState />
</Margin> </Margin>
<NoPackagesTitle>{children}</NoPackagesTitle> <NoPackagesTitle>{children}</NoPackagesTitle>
</Flex> </Flex>

View File

@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { Field } from 'redux-form'; import { Field } from 'redux-form';
import Flex from 'styled-flex-component'; import Flex, { FlexItem } from 'styled-flex-component';
import { Padding, Margin } from 'styled-components-spacing'; import { Padding, Margin } from 'styled-components-spacing';
import remcalc from 'remcalc'; import remcalc from 'remcalc';
@ -15,7 +15,7 @@ import {
PopoverTarget, PopoverTarget,
Popover, Popover,
PopoverItem, PopoverItem,
PopoverDivider, PopoverDivider as BasePopoverDivider,
PopoverContainer, PopoverContainer,
Radio, Radio,
FormLabel, FormLabel,
@ -56,11 +56,6 @@ const Content = styled(Padding)`
const Max = styled(Flex)` const Max = styled(Flex)`
max-width: 100%; max-width: 100%;
height: 100%;
`;
const DividerContainer = styled(Margin)`
height: 100%;
`; `;
const Actions = styled(Flex)` const Actions = styled(Flex)`
@ -71,9 +66,14 @@ const Actions = styled(Flex)`
const ActionsWrapper = styled(Flex)` const ActionsWrapper = styled(Flex)`
height: 100%; height: 100%;
width: 100%;
border-left: ${remcalc(1)} solid ${props => props.theme.grey}; border-left: ${remcalc(1)} solid ${props => props.theme.grey};
`; `;
const PopoverDivider = styled(BasePopoverDivider)`
width: 100%;
`;
export const Image = ({ export const Image = ({
name, name,
id, id,
@ -84,39 +84,41 @@ export const Image = ({
onRemove, onRemove,
onCreateInstance onCreateInstance
}) => ( }) => (
<Margin bottom={3}> <Margin bottom="3">
<CardAnchor to={`/images/${id}`} component={Link}> <CardAnchor to={`/images/${id}`} component={Link}>
<Card radius> <Card radius>
{removing ? ( {removing ? (
<Padding all={2}> <Padding all="2">
<StatusLoader /> <StatusLoader />
</Padding> </Padding>
) : ( ) : (
<Fragment> <Fragment>
<CardHeader white radius> <CardHeader white radius>
<Padding left={2} right={2}> <Padding left="2" right="2">
<Flex full alignCenter> <Flex full alignCenter>
<Margin right={2}> <FlexItem>
<Margin right="2">
{React.createElement(OS[os], { {React.createElement(OS[os], {
width: '24', width: '24',
height: '24' height: '24'
})} })}
</Margin> </Margin>
</FlexItem>
<FlexItem>
<A to={`/images/${id}/summary`} component={Link}> <A to={`/images/${id}/summary`} component={Link}>
{name} {name}
</A> </A>
</FlexItem>
</Flex> </Flex>
</Padding> </Padding>
</CardHeader> </CardHeader>
<Flex justifyBetween> <Flex justifyBetween>
<Content left={2} top={2} bottom={2}> <Content left="2" top="2" bottom="2">
<Max justifyBetween> <Max justifyBetween>
<Max alignCenter> <Max alignCenter>
<Flex>{version}</Flex> <Flex>{version}</Flex>
<DividerContainer left={2}> <Divider vertical />
<Divider width={remcalc(1)} height="100%" /> <Type>{ImageType[type]}</Type>
</DividerContainer>
<Type left={2}>{ImageType[type]}</Type>
</Max> </Max>
</Max> </Max>
</Content> </Content>
@ -127,7 +129,8 @@ export const Image = ({
<ActionsIcon /> <ActionsIcon />
</ActionsWrapper> </ActionsWrapper>
</PopoverTarget> </PopoverTarget>
<Popover placement="bottom"> <Popover noPadding placement="bottom">
<Padding horizontal="3" vertical="2">
<PopoverItem disabled={false} onClick={onCreateInstance}> <PopoverItem disabled={false} onClick={onCreateInstance}>
<ItemAnchor <ItemAnchor
href={`${ href={`${
@ -139,10 +142,13 @@ export const Image = ({
Create Instance Create Instance
</ItemAnchor> </ItemAnchor>
</PopoverItem> </PopoverItem>
</Padding>
<PopoverDivider /> <PopoverDivider />
<Padding horizontal="3" vertical="2">
<PopoverItem disabled={removing} onClick={onRemove}> <PopoverItem disabled={removing} onClick={onRemove}>
Remove Remove
</PopoverItem> </PopoverItem>
</Padding>
</Popover> </Popover>
</Actions> </Actions>
</PopoverContainer> </PopoverContainer>
@ -157,9 +163,9 @@ export const Image = ({
export const Filters = ({ selected }) => ( export const Filters = ({ selected }) => (
<Fragment> <Fragment>
<FormGroup name="image-type" value="all" field={Field} type="radio"> <FormGroup name="image-type" value="all" field={Field} type="radio">
<Radio noMargin> <Radio>
<Flex alignCenter> <Flex alignCenter>
<Margin right={2}> <Margin horizontal="2">
<FormLabel big normal={selected !== 'all'}> <FormLabel big normal={selected !== 'all'}>
All All
</FormLabel> </FormLabel>
@ -175,7 +181,7 @@ export const Filters = ({ selected }) => (
> >
<Radio noMargin> <Radio noMargin>
<Flex alignCenter> <Flex alignCenter>
<Margin right={2}> <Margin horizontal="2">
<FormLabel big normal={selected !== 'hardware-virtual-machine'}> <FormLabel big normal={selected !== 'hardware-virtual-machine'}>
Virtual machines Virtual machines
</FormLabel> </FormLabel>
@ -191,7 +197,7 @@ export const Filters = ({ selected }) => (
> >
<Radio noMargin> <Radio noMargin>
<Flex alignCenter> <Flex alignCenter>
<Margin right={2}> <Margin horizontal="2">
<FormLabel big normal={selected !== 'infrastructure-container'}> <FormLabel big normal={selected !== 'infrastructure-container'}>
Infrastructure container Infrastructure container
</FormLabel> </FormLabel>

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import forceArray from 'force-array';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
import forceArray from 'force-array';
import { import {
SectionList, SectionList,
@ -28,7 +28,7 @@ const Menu = ({ links = [] }) => {
return ( return (
<ViewContainer plain> <ViewContainer plain>
<Margin bottom={6}> <Margin bottom="5" top="1">
<SectionList>{getMenuItems(_links)}</SectionList> <SectionList>{getMenuItems(_links)}</SectionList>
</Margin> </Margin>
</ViewContainer> </ViewContainer>

View File

@ -1,18 +1,19 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import { Row, Col } from 'joyent-react-styled-flexboxgrid'; import { Row, Col } from 'joyent-react-styled-flexboxgrid';
import { Margin, Padding } from 'styled-components-spacing'; import { Margin, Padding } from 'styled-components-spacing';
import styled, { withTheme } from 'styled-components'; import styled from 'styled-components';
import Flex, { FlexItem } from 'styled-flex-component'; import Flex, { FlexItem } from 'styled-flex-component';
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
import titleCase from 'title-case'; import titleCase from 'title-case';
import remcalc from 'remcalc'; import remcalc from 'remcalc';
import { ValueBreakpoints as breakpoints } from 'joyent-ui-toolkit';
import { import {
Card, Card,
CardOutlet, CardOutlet,
H2, H2,
P, P,
Label, Label as BaseLabel,
Divider, Divider,
Button, Button,
QueryBreakpoints, QueryBreakpoints,
@ -37,11 +38,15 @@ const VerticalDivider = styled.div`
align-self: flex-end; align-self: flex-end;
margin: 0 ${remcalc(18)}; margin: 0 ${remcalc(18)};
@media (max-width: ${remcalc(767)}) { @media (max-width: ${remcalc(breakpoints.small.upper)}) {
display: none; display: none;
} }
`; `;
const Label = styled(BaseLabel)`
font-weight: 200;
`;
const GreyLabel = styled(Label)` const GreyLabel = styled(Label)`
opacity: 0.5; opacity: 0.5;
padding-right: ${remcalc(3)}; padding-right: ${remcalc(3)};
@ -71,7 +76,7 @@ export const Meta = ({ name, version, type, published_at, state, os }) => (
<H2 bold>{name}</H2> <H2 bold>{name}</H2>
</FlexItem> </FlexItem>
</Flex> </Flex>
<Margin top={2} bottom={3}> <Margin top="2" bottom="3">
<Flex> <Flex>
<Label>{version}</Label> <Label>{version}</Label>
<VerticalDivider /> <VerticalDivider />
@ -99,15 +104,15 @@ export const Meta = ({ name, version, type, published_at, state, os }) => (
</Fragment> </Fragment>
); );
export default withTheme(({ theme = {}, onRemove, removing, ...image }) => ( export default ({ theme = {}, onRemove, removing, ...image }) => (
<Row> <Row>
<Col xs={12} sm={12} md={9}> <Col xs="12" sm="12" md="9">
<Card> <Card>
<CardOutlet> <CardOutlet>
<Padding all={4}> <Padding all="5">
<Meta {...image} /> <Meta {...image} />
<Row between="xs"> <Row between="xs">
<Col xs={9}> <Col xs="9">
<SmallOnly> <SmallOnly>
<Button type="button" small icon> <Button type="button" small icon>
<DuplicateIcon light /> <DuplicateIcon light />
@ -124,15 +129,14 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
bold bold
icon icon
> >
<DuplicateIcon light />
<span>Create Instance</span> <span>Create Instance</span>
</Button> </Button>
</Medium> </Medium>
</Col> </Col>
<Col xs={3}> <Col xs="3">
<SmallOnly> <SmallOnly>
<Button type="button" small icon error right> <Button type="button" small icon error right>
<DeleteIcon fill={theme.red} /> <DeleteIcon fill="red" />
</Button> </Button>
</SmallOnly> </SmallOnly>
<Medium> <Medium>
@ -145,8 +149,10 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
error error
right right
> >
<DeleteIcon fill={theme.red} /> <Margin right="1">
<span>Remove</span> <DeleteIcon fill="red" />
</Margin>
<span>Delete</span>
</Button> </Button>
</Medium> </Medium>
</Col> </Col>
@ -157,10 +163,15 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
<Margin bottom="2"> <Margin bottom="2">
<P>{image.description}</P> <P>{image.description}</P>
</Margin> </Margin>
<Margin bottom="3">
<CopiableField text={(image.id || '').split('-')[0]} label="ID" /> <CopiableField text={(image.id || '').split('-')[0]} label="ID" />
</Margin>
<Margin bottom="3">
<CopiableField text={image.id} label="UUID" /> <CopiableField text={image.id} label="UUID" />
</Margin>
<Row> <Row>
<Col xs={12} md={7}> <Col xs="12" md="7">
<Margin bottom="3">
<FormLabel>Operating system</FormLabel> <FormLabel>Operating system</FormLabel>
<Input <Input
monospace monospace
@ -168,6 +179,7 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
fluid fluid
value={titleCase(image.os)} value={titleCase(image.os)}
/> />
</Margin>
</Col> </Col>
</Row> </Row>
</Padding> </Padding>
@ -175,4 +187,4 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
</Card> </Card>
</Col> </Col>
</Row> </Row>
)); );

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import { TagItem, KeyValue } from 'joyent-ui-toolkit'; import { TagItem } from 'joyent-ui-toolkit';
import { KeyValue } from 'joyent-ui-resource-widgets';
export const AddForm = props => ( export const AddForm = props => (
<KeyValue {...props} method="add" input="input" type="tag" expanded /> <KeyValue {...props} method="add" input="input" type="tag" expanded />
@ -13,8 +14,8 @@ export const EditForm = props => (
export default ({ norMargin, name, value, onClick, onRemoveClick, active }) => ( export default ({ norMargin, name, value, onClick, onRemoveClick, active }) => (
<Margin <Margin
right={norMargin ? 0 : 1} right={norMargin ? '0' : '1'}
bottom={norMargin ? 0 : 1} bottom={norMargin ? '0' : '1'}
key={`${name}-${value}`} key={`${name}-${value}`}
> >
<TagItem onClick={onClick} active={active} onRemoveClick={onRemoveClick}> <TagItem onClick={onClick} active={active} onRemoveClick={onRemoveClick}>

View File

@ -2,15 +2,8 @@ import React from 'react';
import { Field } from 'redux-form'; import { Field } from 'redux-form';
import Flex from 'styled-flex-component'; import Flex from 'styled-flex-component';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import remcalc from 'remcalc';
import { import { Button, FormGroup, Input, FormLabel } from 'joyent-ui-toolkit';
Button,
FormGroup,
Input,
FormLabel,
Divider
} from 'joyent-ui-toolkit';
export const Toolbar = ({ export const Toolbar = ({
searchable = true, searchable = true,
@ -21,16 +14,15 @@ export const Toolbar = ({
actionable = false, actionable = false,
onActionClick onActionClick
}) => ( }) => (
<Flex justifyBetween> <Flex justifyBetween alignEnd>
<FormGroup name="filter" field={Field}> <FormGroup name="filter" field={Field}>
<FormLabel>{searchLabel}</FormLabel> <FormLabel>{searchLabel}</FormLabel>
<Margin top={0.5}> <Margin top="0.5">
<Input placeholder={searchPlaceholder} disabled={!searchable} /> <Input placeholder={searchPlaceholder} disabled={!searchable} />
</Margin> </Margin>
</FormGroup> </FormGroup>
{action ? ( {action ? (
<FormGroup right> <FormGroup right>
<Divider height={remcalc(21)} transparent />
<Button <Button
type="button" type="button"
disabled={!actionable} disabled={!actionable}
@ -48,6 +40,5 @@ export const Toolbar = ({
export default ({ handleSubmit, ...rest }) => ( export default ({ handleSubmit, ...rest }) => (
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<Toolbar {...rest} /> <Toolbar {...rest} />
<Divider height={remcalc(20)} transparent />
</form> </form>
); );

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Margin } from 'styled-components-spacing';
import paramCase from 'param-case'; import paramCase from 'param-case';
import get from 'lodash.get'; import get from 'lodash.get';
@ -43,7 +44,9 @@ export default ({ match }) => {
.filter(Boolean) .filter(Boolean)
.map(({ name, pathname }) => ( .map(({ name, pathname }) => (
<BreadcrumbItem key={name} to={pathname} component={Link}> <BreadcrumbItem key={name} to={pathname} component={Link}>
<Margin horizontal="1" vertical="3">
{name} {name}
</Margin>
</BreadcrumbItem> </BreadcrumbItem>
)); ));

View File

@ -67,12 +67,12 @@ const NameContainer = ({
onRandomize={handleRandomize} onRandomize={handleRandomize}
/> />
) : name ? ( ) : name ? (
<Margin top={3}> <Margin top="3">
<H3 bold noMargin> <H3 bold noMargin>
{name} {name}
</H3> </H3>
{version ? ( {version ? (
<Margin top={2}> <Margin top="2">
<H4 bold noMargin> <H4 bold noMargin>
{version} {version}
</H4> </H4>
@ -80,8 +80,8 @@ const NameContainer = ({
) : null} ) : null}
{description ? ( {description ? (
<Row> <Row>
<Col xs={12} sm={8}> <Col xs="12" sm="8">
<Margin top={1}> <Margin top="1">
<P>{description}</P> <P>{description}</P>
</Margin> </Margin>
</Col> </Col>
@ -92,13 +92,13 @@ const NameContainer = ({
} }
</ReduxForm> </ReduxForm>
{expanded ? ( {expanded ? (
<Margin top={4} bottom={7}> <Margin top="4" bottom="7">
<Button type="button" disabled={!name} onClick={handleNext}> <Button type="button" disabled={!name} onClick={handleNext}>
Next Next
</Button> </Button>
</Margin> </Margin>
) : proceeded ? ( ) : proceeded ? (
<Margin top={4} bottom={7}> <Margin top="4" bottom="7">
<Button type="button" onClick={handleEdit} secondary> <Button type="button" onClick={handleEdit} secondary>
Edit Edit
</Button> </Button>
@ -166,6 +166,7 @@ export default compose(
dispatch(set({ name: 'create-image-name-randomizing', value: false })); dispatch(set({ name: 'create-image-name-randomizing', value: false }));
if (err) { if (err) {
// eslint-disable-next-line no-console
console.error(err); console.error(err);
return; return;
} }

View File

@ -6,17 +6,10 @@ import { destroy, reset } from 'redux-form';
import ReduxForm from 'declarative-redux-form'; import ReduxForm from 'declarative-redux-form';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import get from 'lodash.get'; import get from 'lodash.get';
import remcalc from 'remcalc';
import Flex from 'styled-flex-component'; import Flex from 'styled-flex-component';
import { import { TagsIcon, Button, H3, TagList } from 'joyent-ui-toolkit';
TagsIcon, import { KeyValue } from 'joyent-ui-resource-widgets';
Button,
H3,
TagList,
Divider,
KeyValue
} from 'joyent-ui-toolkit';
import Title from '@components/create-image/title'; import Title from '@components/create-image/title';
import Description from '@components/description'; import Description from '@components/description';
@ -66,7 +59,7 @@ export const Tags = ({
) : null} ) : null}
{proceeded || expanded ? ( {proceeded || expanded ? (
<Fragment> <Fragment>
<Margin bottom={4}> <Margin bottom="5">
<H3> <H3>
{tags.length} Tag{tags.length === 1 ? '' : 's'} {tags.length} Tag{tags.length === 1 ? '' : 's'}
</H3> </H3>
@ -102,12 +95,11 @@ export const Tags = ({
expanded expanded
onCancel={() => handleChangeAddOpen(false)} onCancel={() => handleChangeAddOpen(false)}
/> />
<Divider height={remcalc(18)} transparent />
</Fragment> </Fragment>
) : null ) : null
} }
</ReduxForm> </ReduxForm>
<Margin top={1}> <Margin top="1">
<Flex alignCenter> <Flex alignCenter>
{expanded ? ( {expanded ? (
<Button <Button
@ -118,11 +110,11 @@ export const Tags = ({
Add Tag Add Tag
</Button> </Button>
) : null} ) : null}
<Margin left={1}>{children}</Margin> <Margin left="1">{children}</Margin>
</Flex> </Flex>
</Margin> </Margin>
{proceeded ? ( {proceeded ? (
<Margin top={1}> <Margin top="1">
<Button type="button" onClick={handleEdit} secondary> <Button type="button" onClick={handleEdit} secondary>
Edit Edit
</Button> </Button>

View File

@ -1,5 +1,3 @@
/* eslint-disable camelcase */
import React from 'react'; import React from 'react';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import ReduxForm from 'declarative-redux-form'; import ReduxForm from 'declarative-redux-form';
@ -41,12 +39,12 @@ const Create = ({
}) => ( }) => (
<ViewContainer> <ViewContainer>
{loading ? ( {loading ? (
<Margin top={4}> <Margin top="4">
<StatusLoader /> <StatusLoader />
</Margin> </Margin>
) : null} ) : null}
{loadingError ? ( {loadingError ? (
<Margin top={4}> <Margin top="4">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{loadingError}</MessageDescription> <MessageDescription>{loadingError}</MessageDescription>
@ -54,7 +52,7 @@ const Create = ({
</Margin> </Margin>
) : null} ) : null}
{!loading && !loadingError ? ( {!loading && !loadingError ? (
<Margin top={4} bottom={4}> <Margin top="4" bottom="5">
<H2>Create Image</H2> <H2>Create Image</H2>
</Margin> </Margin>
) : null} ) : null}
@ -78,7 +76,7 @@ const Create = ({
{({ handleSubmit, submitting }) => {({ handleSubmit, submitting }) =>
!loading && !loadingError ? ( !loading && !loadingError ? (
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<Margin top={step === 'tag' ? 7 : 4}> <Margin top={step === 'tag' ? '7' : '4'}>
<Button disabled={disabled} loading={submitting}> <Button disabled={disabled} loading={submitting}>
Create Image Create Image
</Button> </Button>

View File

@ -2,7 +2,6 @@ import React, { Fragment } from 'react';
import { compose, graphql } from 'react-apollo'; import { compose, graphql } from 'react-apollo';
import ReduxForm from 'declarative-redux-form'; import ReduxForm from 'declarative-redux-form';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import remcalc from 'remcalc';
import { Row, Col } from 'joyent-react-styled-flexboxgrid'; import { Row, Col } from 'joyent-react-styled-flexboxgrid';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import get from 'lodash.get'; import get from 'lodash.get';
@ -41,20 +40,21 @@ export const List = ({
handleRemove handleRemove
}) => ( }) => (
<ViewContainer main> <ViewContainer main>
<Divider height={remcalc(30)} transparent /> <Margin top="4">
<ReduxForm form={LIST_TOOLBAR_FORM}> <ReduxForm form={LIST_TOOLBAR_FORM}>
{props => <ToolbarForm {...props} actionable={!loading} />} {props => <ToolbarForm {...props} actionable={!loading} />}
</ReduxForm> </ReduxForm>
<Divider height={remcalc(1)} /> </Margin>
<Divider height={remcalc(24)} transparent /> <Margin vertical="4">
<Divider />
</Margin>
{loading && !images.length ? ( {loading && !images.length ? (
<Fragment> <Fragment>
<Divider height={remcalc(30)} transparent />
<StatusLoader /> <StatusLoader />
</Fragment> </Fragment>
) : null} ) : null}
{error && !images.length && !loading ? ( {error && !images.length && !loading ? (
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription> <MessageDescription>
@ -64,7 +64,7 @@ export const List = ({
</Margin> </Margin>
) : null} ) : null}
<Fragment> <Fragment>
<Margin bottom={4}> <Margin bottom="4">
<ReduxForm <ReduxForm
form={LIST_TOGGLE_TYPE_FORM} form={LIST_TOGGLE_TYPE_FORM}
initialValues={{ 'image-type': 'all' }} initialValues={{ 'image-type': 'all' }}
@ -78,7 +78,7 @@ export const List = ({
</Margin> </Margin>
<Row> <Row>
{images.map(image => ( {images.map(image => (
<Col sm={4}> <Col sm="4">
<Image <Image
{...image} {...image}
onCreateInstance={() => handleCreateInstance(image)} onCreateInstance={() => handleCreateInstance(image)}

View File

@ -10,7 +10,7 @@ const SECTIONS = [
export default ({ match }) => { export default ({ match }) => {
const imageId = get(match, 'params.image'); const imageId = get(match, 'params.image');
const sections = imageId !== '~create' ? SECTIONS : []; const sections = imageId === '~create' ? [] : SECTIONS;
const links = sections.map(({ name, pathname }) => ({ const links = sections.map(({ name, pathname }) => ({
name, name,

View File

@ -1,16 +1,14 @@
import React, { Fragment } from 'react'; import React from 'react';
import { compose, graphql } from 'react-apollo'; import { compose, graphql } from 'react-apollo';
import { Margin } from 'styled-components-spacing'; import { Margin } from 'styled-components-spacing';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import intercept from 'apr-intercept'; import intercept from 'apr-intercept';
import { set } from 'react-redux-values'; import { set } from 'react-redux-values';
import get from 'lodash.get'; import get from 'lodash.get';
import remcalc from 'remcalc';
import { import {
ViewContainer, ViewContainer,
StatusLoader, StatusLoader,
Divider,
Message, Message,
MessageTitle, MessageTitle,
MessageDescription MessageDescription
@ -30,14 +28,9 @@ export const Summary = ({
handleRemove handleRemove
}) => ( }) => (
<ViewContainer main> <ViewContainer main>
{loading && !image ? ( {loading && !image ? <StatusLoader /> : null}
<Fragment>
<Divider height={remcalc(30)} transparent />
<StatusLoader />
</Fragment>
) : null}
{error && !loading && !image ? ( {error && !loading && !image ? (
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription> <MessageDescription>
@ -47,7 +40,7 @@ export const Summary = ({
</Margin> </Margin>
) : null} ) : null}
{mutationError ? ( {mutationError ? (
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription> <MessageDescription>

View File

@ -14,11 +14,11 @@ import {
H3, H3,
ViewContainer, ViewContainer,
StatusLoader, StatusLoader,
Divider,
Message, Message,
MessageTitle, MessageTitle,
MessageDescription, MessageDescription,
TagList TagList,
Divider
} from 'joyent-ui-toolkit'; } from 'joyent-ui-toolkit';
import { Forms } from '@root/constants'; import { Forms } from '@root/constants';
@ -56,12 +56,14 @@ export const Tags = ({
onActionClick={handleToggleAddOpen} onActionClick={handleToggleAddOpen}
action action
/> />
<Margin vertical="4">
<Divider height={remcalc(1)} /> <Divider height={remcalc(1)} />
</Margin> </Margin>
</Margin>
)} )}
</ReduxForm> </ReduxForm>
{error && !loading && !tags.length ? ( {error && !loading && !tags.length ? (
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription> <MessageDescription>
@ -71,7 +73,7 @@ export const Tags = ({
</Margin> </Margin>
) : null} ) : null}
{mutationError ? ( {mutationError ? (
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{mutationError}</MessageDescription> <MessageDescription>{mutationError}</MessageDescription>
@ -80,13 +82,13 @@ export const Tags = ({
) : null} ) : null}
<ReduxForm <ReduxForm
form={TAGS_ADD_FORM} form={TAGS_ADD_FORM}
asyncValidate={handleAsyncValidate}
shouldAsyncValidate={shouldAsyncValidate} shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleAsyncValidate}
onSubmit={handleAddTag} onSubmit={handleAddTag}
> >
{props => {props =>
addOpen ? ( addOpen ? (
<Margin bottom={4}> <Margin bottom="5">
<AddForm <AddForm
{...props} {...props}
onToggleExpanded={() => handleToggleAddOpen(!addOpen)} onToggleExpanded={() => handleToggleAddOpen(!addOpen)}
@ -96,18 +98,19 @@ export const Tags = ({
) : null ) : null
} }
</ReduxForm> </ReduxForm>
{!loading ? ( {loading ? null : (
<Margin bottom={4}> <Margin bottom="5">
<H3> <H3>
{tags.length} tag{tags.length === 1 ? '' : 's'} {tags.length} tag{tags.length === 1 ? '' : 's'}
</H3> </H3>
</Margin> </Margin>
) : null} )}
{loading && !tags.length ? <StatusLoader /> : null} {loading && !tags.length ? <StatusLoader /> : null}
<TagList> <TagList>
{tags.map(({ name, value }) => ( {tags.map(({ id, name, value }) => (
<Tag <Tag
key={value} key={id}
id={id}
name={name} name={name}
value={value} value={value}
onRemoveClick={!mutating && (() => handleRemoveTag(name))} onRemoveClick={!mutating && (() => handleRemoveTag(name))}

View 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>
);

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { HelmetProvider } from 'react-helmet-async';
import { ThemeProvider } from 'styled-components'; import { ThemeProvider } from 'styled-components';
import { Provider as ReduxProvider } from 'react-redux'; import { Provider as ReduxProvider } from 'react-redux';
import { ApolloProvider } from 'react-apollo'; import { ApolloProvider } from 'react-apollo';
@ -21,7 +22,9 @@ ReactDOM.hydrate(
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<ReduxProvider store={createStore()}> <ReduxProvider store={createStore()}>
<BrowserRouter> <BrowserRouter>
<HelmetProvider context={{}}>
<App /> <App />
</HelmetProvider>
</BrowserRouter> </BrowserRouter>
</ReduxProvider> </ReduxProvider>
</ThemeProvider> </ThemeProvider>

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { Fragment } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom'; import { Route, Switch, Redirect } from 'react-router-dom';
import get from 'lodash.get'; import get from 'lodash.get';
@ -19,6 +19,8 @@ import Create from '@containers/create';
import Tags from '@containers/tags'; import Tags from '@containers/tags';
import { Route as ServerError } from '@root/server-error'; import { Route as ServerError } from '@root/server-error';
const { REACT_APP_DEV = false } = process.env;
export default () => ( export default () => (
<PageContainer> <PageContainer>
{/* Breadcrumb */} {/* Breadcrumb */}
@ -70,6 +72,41 @@ export default () => (
<Route path="/" exact component={() => <Redirect to="/images" />} /> <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> <noscript>
<ViewContainer main> <ViewContainer main>
<Message warning> <Message warning>

View File

@ -17,7 +17,7 @@ import Breadcrumb from '@containers/breadcrumb';
export const Route = () => ( export const Route = () => (
<ViewContainer main> <ViewContainer main>
<Divider height={remcalc(30)} transparent /> <Divider height={remcalc(30)} transparent />
<Margin bottom={4}> <Margin bottom="5">
<Message error> <Message error>
<MessageTitle>Ooops!</MessageTitle> <MessageTitle>Ooops!</MessageTitle>
<MessageDescription> <MessageDescription>

View File

@ -0,0 +1,42 @@
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';
const {
REACT_APP_GQL_PORT = global.port,
REACT_APP_GQL_PROTOCOL = global.protocol,
REACT_APP_GQL_HOSTNAME = global.hostname
} = process.env;
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 = {}, request = {}) => {
const host = get(request, 'raw.req.headers.host', '');
let cache = new InMemoryCache();
if (global.__APOLLO_STATE__) {
cache = cache.restore(global.__APOLLO_STATE__);
}
return new ApolloClient({
cache,
link: new HttpLink({
uri: host ? `${REACT_APP_GQL_PROTOCOL}//${host}/images/graphql` : URI,
credentials: 'same-origin',
fetch,
headers: {
'X-CSRF-Token': global.cookie.replace(
/(?:(?:^|.*;\s*)crumb\s*=\s*([^;]*).*$)|^.*$/,
'$1'
)
}
}),
...opts
});
};

View File

@ -1,8 +1,12 @@
import { canUseDOM } from 'exenv'; import { canUseDOM } from 'exenv';
import queryString from 'query-string';
export default (() => { const { NODE_ENV = 'development' } = process.env;
export const Global = () => {
if (!canUseDOM) { if (!canUseDOM) {
return { return {
protocol: NODE_ENV === 'development' ? 'http:' : 'https:',
cookie: '' cookie: ''
}; };
} }
@ -11,10 +15,15 @@ export default (() => {
port: window.location.port, port: window.location.port,
protocol: window.location.protocol.replace(/:$/, ''), protocol: window.location.protocol.replace(/:$/, ''),
hostname: window.location.hostname, hostname: window.location.hostname,
pathname: window.location.pathname,
origin: window.location.origin, origin: window.location.origin,
cookie: document.cookie || '', cookie: document.cookie || '',
search: window.location.search,
query: queryString.parse(window.location.search || ''),
__REDUX_DEVTOOLS_EXTENSION__: window.__REDUX_DEVTOOLS_EXTENSION__, __REDUX_DEVTOOLS_EXTENSION__: window.__REDUX_DEVTOOLS_EXTENSION__,
__APOLLO_STATE__: window.__APOLLO_STATE__, __APOLLO_STATE__: window.__APOLLO_STATE__,
__REDUX_STATE__: window.__REDUX_STATE__ __REDUX_STATE__: window.__REDUX_STATE__
}; };
})(); };
export default Global();

View File

@ -2,7 +2,7 @@ import intercept from 'apr-intercept';
import keys from 'lodash.keys'; import keys from 'lodash.keys';
import reduce from 'apr-reduce'; import reduce from 'apr-reduce';
import assign from 'lodash.assign'; import assign from 'lodash.assign';
import yup from 'yup'; import * as yup from 'yup';
/*****************************************************************************/ /*****************************************************************************/
@ -14,14 +14,16 @@ const validateField = async (field, value) => {
const validateSchema = async (schema, value) => { const validateSchema = async (schema, value) => {
const errors = await reduce( const errors = await reduce(
keys(schema), keys(schema),
async (errors, name) => async (errors, name) => {
assign(errors, { const msg = await validateField(schema[name], value[name]);
[name]: await validateField(schema[name], value[name]) return msg ? assign(errors, { [name]: msg }) : errors;
}), },
{} {}
); );
if (keys(errors).length) {
throw errors; throw errors;
}
}; };
/*****************************************************************************/ /*****************************************************************************/
@ -64,4 +66,4 @@ const Schemas = {
export const addTag = tag => validateSchema(Schemas.tag, tag); export const addTag = tag => validateSchema(Schemas.tag, tag);
export const instanceName = ({ name }) => export const instanceName = ({ name }) =>
!name ? null : validateSchema(Schemas.instanceName, { name }); name ? validateSchema(Schemas.instanceName, { name }) : null;

View 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 = 'instances', 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');

View File

@ -6,39 +6,38 @@
"repository": "github:yldio/joyent-portal", "repository": "github:yldio/joyent-portal",
"main": "lib/index.js", "main": "lib/index.js",
"scripts": { "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:test": "echo 0",
"build:lib": "echo 0", "build:lib": "echo 0",
"build:bundle": "NAMESPACE=instances NODE_ENV=production redrun -p build:frontend build:ssr", "build:bundle": "NAMESPACE=instances NODE_ENV=production redrun -p build:frontend build:ssr",
"prepublish": "NODE_ENV=production redrun build:bundle", "prepublish": "NODE_ENV=production redrun build:bundle",
"lint": "redrun lint:ci -- --fix", "test": "DEFAULT_TIMEOUT_INTERVAL=100000 NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
"lint:ci": "NODE_ENV=test eslint . --ext .js --ext .md",
"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'", "test:ci": "NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
"build:frontend": "joyent-react-scripts build", "build:frontend": "joyent-react-scripts build",
"build:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files" "build:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files"
}, },
"dependencies": { "dependencies": {
"@manaflair/redux-batch": "^0.1.0", "@manaflair/redux-batch": "^0.1.0",
"apollo-cache-inmemory": "^1.1.12", "apollo-cache-inmemory": "^1.2.2",
"apollo-client": "^2.2.8", "apollo-client": "^2.3.2",
"apollo-link-http": "^1.5.3", "apollo-link-http": "^1.5.4",
"apr-intercept": "^3.0.3", "apr-intercept": "^3.0.3",
"apr-reduce": "^3.0.3", "apr-reduce": "^3.0.3",
"boom": "^7.2.0",
"bytes": "^3.0.0", "bytes": "^3.0.0",
"clipboard-copy": "^2.0.0", "clipboard-copy": "^2.0.0",
"constant-case": "^2.0.0", "cross-fetch": "^2.2.0",
"cross-fetch": "^2.1.0",
"date-fns": "^1.29.0", "date-fns": "^1.29.0",
"declarative-redux-form": "^2.0.8", "declarative-redux-form": "^2.0.8",
"exenv": "^1.2.2", "exenv": "^1.2.2",
"fuse.js": "^3.2.0", "fuse.js": "^3.2.0",
"hapi-render-react": "^2.5.2", "hapi-render-react": "^2.5.2",
"hapi-render-react-joyent-document": "^5.0.0", "hapi-render-react-joyent-document": "^7.2.0",
"inert": "^5.1.0", "inert": "^5.1.0",
"joyent-logo-assets": "^1.1.0", "joyent-logo-assets": "^1.1.0",
"joyent-ui-resource-step": "^1.0.0",
"joyent-manifest-editor": "^1.4.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", "joyent-ui-toolkit": "^6.0.0",
"lodash.find": "^4.6.0", "lodash.find": "^4.6.0",
"lodash.findindex": "^4.6.0", "lodash.findindex": "^4.6.0",
@ -52,41 +51,41 @@
"lodash.isfunction": "^3.0.9", "lodash.isfunction": "^3.0.9",
"lodash.isinteger": "^4.0.4", "lodash.isinteger": "^4.0.4",
"lodash.isnan": "^3.0.2", "lodash.isnan": "^3.0.2",
"lodash.omit": "^4.5.0",
"lodash.reduce": "^4.6.0", "lodash.reduce": "^4.6.0",
"lodash.reverse": "^4.0.1", "lodash.reverse": "^4.0.1",
"lodash.some": "^4.6.0", "lodash.some": "^4.6.0",
"lodash.sortby": "^4.7.0", "lodash.sortby": "^4.7.0",
"lodash.uniqby": "^4.7.0",
"lodash.values": "^4.3.0", "lodash.values": "^4.3.0",
"mz": "^2.7.0",
"param-case": "^2.1.1", "param-case": "^2.1.1",
"query-string": "^6.0.0", "query-string": "^6.1.0",
"react": "^16.3.1", "react": "^16.4.0",
"react-apollo": "^2.1.2", "react-apollo": "^2.1.4",
"react-dom": "^16.3.1", "react-dom": "^16.4.0",
"react-helmet-async": "0.1.0",
"react-redux": "^5.0.7", "react-redux": "^5.0.7",
"react-redux-values": "^1.1.2", "react-redux-values": "^1.1.2",
"react-router": "^4.2.0", "react-router": "^4.2.0",
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"redux": "^3.7.2", "redux": "^4.0.0",
"redux-form": "^7.3.0", "redux-form": "^7.3.0",
"remcalc": "^1.0.10", "remcalc": "^1.0.10",
"styled-components": "^3.2.5", "styled-components": "^3.3.0",
"styled-components-spacing": "^2.1.3", "styled-components-spacing": "^3.0.0",
"styled-flex-component": "^2.2.2", "styled-flex-component": "^2.2.2",
"title-case": "^2.1.1", "title-case": "^2.1.1",
"yup": "^0.24.1" "yup": "^0.25.1"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",
"babel-preset-joyent-portal": "^7.0.1", "babel-preset-joyent-portal": "^7.0.1",
"eslint": "^4.19.1", "eslint": "^4.19.1",
"eslint-config-joyent-portal": "^3.3.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", "jest-styled-components": "^5.0.1",
"joyent-react-scripts": "^8.0.3", "joyent-react-scripts": "^8.2.1",
"react-screenshot-renderer": "^1.1.2", "react-screenshot-renderer": "^1.1.2",
"react-test-renderer": "^16.3.1", "react-test-renderer": "^16.4.0",
"redrun": "^6.0.2" "redrun": "^6.0.4"
} }
} }

Some files were not shown because too many files have changed in this diff Show More