Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
078513f603 | ||
|
a1ff036db1 | ||
|
fc81d666d0 | ||
|
deb1a8436f | ||
|
cad1431e79 | ||
|
2f9d135319 | ||
|
c268d88a4d | ||
|
6698a8eacb | ||
|
1e8e89b3c8 | ||
|
063e40859d | ||
|
fc84358dff | ||
|
6736caaf45 | ||
|
5cb02d709c | ||
|
b66f761a9e | ||
|
8422cdfe8c | ||
|
109988536b | ||
|
d75ae0f14f | ||
|
5c98a4cecb | ||
|
0189822a08 | ||
|
5d46689869 | ||
|
04cb9c32f8 | ||
|
8e6adb1ef4 | ||
|
a1154b2520 | ||
|
155a065281 | ||
|
f388e52549 | ||
|
882085a170 | ||
|
77fd895b6c | ||
|
bd332423be | ||
|
91e1fb192b | ||
|
88fe0ea92d | ||
|
8bb4c31aba | ||
|
867e9b35a0 | ||
|
574c3add4e | ||
|
c233b0d757 | ||
|
84b2d67d2c | ||
|
062ff0ba67 | ||
|
b00baa7028 | ||
|
588b833045 | ||
|
b3edb3aa02 | ||
|
542b491b52 | ||
|
7d8b478d20 | ||
|
7531e503f2 | ||
|
d1b2ba0002 | ||
|
98a8b2eb5b | ||
|
de356e1fbe | ||
|
f9c89cbccc | ||
|
1317894f27 | ||
|
f007889283 | ||
|
831be94521 | ||
|
e321c20906 | ||
|
429ad17262 | ||
|
d591d93547 | ||
|
33d3d4343d | ||
|
32d5cdc293 | ||
|
316773d9b7 | ||
|
0ae1290a5e | ||
|
3f75f812fa |
@ -1,4 +1,9 @@
|
||||
packages/*/**
|
||||
prototypes/*/**
|
||||
artifacts
|
||||
reports
|
||||
.nyc_output
|
||||
coverage
|
||||
dist
|
||||
styleguide
|
||||
build
|
||||
consoles/*/lib/app
|
||||
node_modules
|
@ -1,8 +1,10 @@
|
||||
{
|
||||
"extends": "joyent-portal",
|
||||
"rules": {
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-console": 1,
|
||||
"new-cap": 0,
|
||||
"no-console": 0
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-negated-condition": 1,
|
||||
"camelcase": 1
|
||||
}
|
||||
}
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -165,3 +165,5 @@ prototypes/*/package-lock.json
|
||||
|
||||
_env*
|
||||
keys*
|
||||
/packages/*/public/index.html
|
||||
/consoles/*/public/index.html
|
||||
|
@ -15,6 +15,7 @@ yarn.lock
|
||||
dist
|
||||
build
|
||||
packages/*/lib/app
|
||||
consoles/*/lib/app
|
||||
|
||||
*.ico
|
||||
*.html
|
||||
|
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -9,24 +9,23 @@
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "echo 0",
|
||||
"prepublish": "echo 0",
|
||||
"lint": "echo 0",
|
||||
"lint:ci": "echo 0",
|
||||
"test": "echo 0",
|
||||
"test:ci": "echo 0"
|
||||
},
|
||||
"dependencies": {
|
||||
"apr-main": "^4.0.3",
|
||||
"brule": "^3.1.0",
|
||||
"cloudapi-gql": "^7.1.4",
|
||||
"cloudapi-gql": "^8.0.0",
|
||||
"execa": "^0.10.0",
|
||||
"h2o2": "^8.0.1",
|
||||
"hapi": "^17.3.1",
|
||||
"hapi-triton-auth": "^2.0.1",
|
||||
"hapi-webconsole-nav": "^1.2.0",
|
||||
"inert": "^5.1.0",
|
||||
"graphi": "^5.7.0",
|
||||
"h2o2": "^8.1.2",
|
||||
"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": "*",
|
||||
"rollover": "^1.0.0"
|
||||
"my-joy-service-groups": "*",
|
||||
"my-joy-templates": "*",
|
||||
"tsg-graphql": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,12 @@
|
||||
require('../.env.js');
|
||||
|
||||
const Main = require('apr-main');
|
||||
const CloudApiGql = require('cloudapi-gql');
|
||||
const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
|
||||
const Server = require('./server');
|
||||
const Ui = require('my-joy-images');
|
||||
|
||||
const {
|
||||
PORT = 4003,
|
||||
@ -25,19 +30,35 @@ Main(async () => {
|
||||
BASE_URL
|
||||
});
|
||||
|
||||
await server.register({
|
||||
plugin: CloudApiGql,
|
||||
options: {
|
||||
authStrategy: 'sso',
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName
|
||||
await server.register([
|
||||
{
|
||||
plugin: Graphi,
|
||||
options: {
|
||||
graphqlPath: '/graphql',
|
||||
graphiqlPath: '/graphiql',
|
||||
authStrategy: 'sso'
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
{
|
||||
plugin: CloudApiGql,
|
||||
options: {
|
||||
authStrategy: 'sso',
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
{
|
||||
plugin: Ui
|
||||
}
|
||||
});
|
||||
]);
|
||||
|
||||
await server.start();
|
||||
});
|
||||
|
@ -1,7 +1,12 @@
|
||||
require('../.env.js');
|
||||
|
||||
const Main = require('apr-main');
|
||||
const CloudApiGql = require('cloudapi-gql');
|
||||
const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
|
||||
const Server = require('./server');
|
||||
const Ui = require('my-joy-instances');
|
||||
|
||||
const {
|
||||
PORT = 4002,
|
||||
@ -25,19 +30,35 @@ Main(async () => {
|
||||
BASE_URL
|
||||
});
|
||||
|
||||
await server.register({
|
||||
plugin: CloudApiGql,
|
||||
options: {
|
||||
authStrategy: 'sso',
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName
|
||||
await server.register([
|
||||
{
|
||||
plugin: Graphi,
|
||||
options: {
|
||||
graphqlPath: '/graphql',
|
||||
graphiqlPath: '/graphiql',
|
||||
authStrategy: 'sso'
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
{
|
||||
plugin: CloudApiGql,
|
||||
options: {
|
||||
authStrategy: 'sso',
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
{
|
||||
plugin: Ui
|
||||
}
|
||||
});
|
||||
]);
|
||||
|
||||
await server.start();
|
||||
});
|
||||
|
@ -1,7 +1,12 @@
|
||||
require('../.env.js');
|
||||
|
||||
const Main = require('apr-main');
|
||||
const Nav = require('hapi-webconsole-nav');
|
||||
const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
|
||||
const Server = require('./server');
|
||||
const Ui = require('my-joy-navigation');
|
||||
|
||||
const Regions = require('../data/regions');
|
||||
const Categories = require('../data/categories');
|
||||
@ -30,22 +35,38 @@ Main(async () => {
|
||||
BASE_URL
|
||||
});
|
||||
|
||||
await server.register({
|
||||
plugin: Nav,
|
||||
options: {
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName,
|
||||
baseUrl,
|
||||
regions: Regions,
|
||||
accountServices: Account,
|
||||
categories: Categories
|
||||
await server.register([
|
||||
{
|
||||
plugin: Graphi,
|
||||
options: {
|
||||
graphqlPath: '/graphql',
|
||||
graphiqlPath: '/graphiql',
|
||||
authStrategy: 'sso'
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
{
|
||||
plugin: Nav,
|
||||
options: {
|
||||
keyPath,
|
||||
keyId,
|
||||
apiBaseUrl,
|
||||
dcName,
|
||||
baseUrl,
|
||||
regions: Regions,
|
||||
accountServices: Account,
|
||||
categories: Categories
|
||||
},
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
},
|
||||
{
|
||||
plugin: Ui
|
||||
}
|
||||
});
|
||||
]);
|
||||
|
||||
await server.start();
|
||||
});
|
||||
|
@ -1,6 +1,7 @@
|
||||
require('../.env.js');
|
||||
|
||||
const Hapi = require('hapi');
|
||||
const Sso = require('hapi-triton-auth');
|
||||
const Url = require('url');
|
||||
|
||||
const {
|
||||
COOKIE_PASSWORD,
|
||||
@ -8,12 +9,10 @@ const {
|
||||
SDC_KEY_PATH,
|
||||
SDC_ACCOUNT,
|
||||
SDC_KEY_ID,
|
||||
SDC_URL,
|
||||
DC_NAME
|
||||
SDC_URL
|
||||
} = process.env;
|
||||
|
||||
module.exports = async ({ PORT, BASE_URL }) => {
|
||||
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||
const keyPath = SDC_KEY_PATH;
|
||||
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||
const apiBaseUrl = SDC_URL;
|
||||
@ -50,6 +49,7 @@ module.exports = async ({ PORT, BASE_URL }) => {
|
||||
|
||||
server.events.on('log', (event, tags) => {
|
||||
if (tags.error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(event);
|
||||
}
|
||||
});
|
||||
@ -58,6 +58,7 @@ module.exports = async ({ PORT, BASE_URL }) => {
|
||||
const { tags } = event;
|
||||
if (tags.includes('error') && event.data && event.data.errors) {
|
||||
event.data.errors.forEach(error => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
78
bundle/src/service-groups.js
Normal file
78
bundle/src/service-groups.js
Normal 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
78
bundle/src/templates.js
Normal 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();
|
||||
});
|
@ -4,7 +4,16 @@ module.exports = {
|
||||
'scope-enum': [
|
||||
2,
|
||||
'always',
|
||||
['ui-toolkit', 'icons', 'instances', 'navigation', 'bundle', 'images']
|
||||
[
|
||||
'ui-toolkit',
|
||||
'icons',
|
||||
'instances',
|
||||
'navigation',
|
||||
'bundle',
|
||||
'images',
|
||||
'sg',
|
||||
'templates'
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
@ -1,16 +1,29 @@
|
||||
const Boom = require('boom');
|
||||
const Inert = require('inert');
|
||||
const Path = require('path');
|
||||
const RenderReact = require('hapi-render-react');
|
||||
const Wreck = require('wreck');
|
||||
const Url = require('url');
|
||||
const Intercept = require('apr-intercept');
|
||||
const Fs = require('mz/fs');
|
||||
|
||||
const { NAMESPACE = 'instances' } = process.env;
|
||||
const { NAMESPACE = 'images', 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/${NAMESPACE}/static/`);
|
||||
const buildRoot = Path.join(__dirname, '../build');
|
||||
const buildStatic = Path.join(buildRoot, `${NAMESPACE}`);
|
||||
const publicRoot = Path.join(__dirname, `../public/static/`);
|
||||
|
||||
await server.register([
|
||||
@ -57,15 +70,41 @@ exports.register = async server => {
|
||||
const { params } = request;
|
||||
const { rest } = params;
|
||||
|
||||
const publicPathname = Path.join(publicRoot, rest);
|
||||
const buildPathname = Path.join(buildRoot, rest);
|
||||
if (!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)
|
||||
);
|
||||
|
||||
const file = err ? buildPathname : publicPathname;
|
||||
return h.file(file, { confine: false });
|
||||
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
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
@ -6,13 +6,11 @@
|
||||
"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",
|
||||
"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:ci": "echo 0",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
@ -21,22 +19,24 @@
|
||||
"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",
|
||||
"cross-fetch": "^2.1.0",
|
||||
"boom": "^7.2.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": "^5.0.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",
|
||||
"lodash.find": "^4.6.0",
|
||||
@ -46,36 +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": "^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.0.3",
|
||||
"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"
|
||||
}
|
||||
}
|
@ -51,6 +51,7 @@ const getState = request => {
|
||||
module.exports = Document({
|
||||
namespace: 'images/',
|
||||
assets,
|
||||
Html: require('./html'),
|
||||
indexFile,
|
||||
getState
|
||||
});
|
@ -1,10 +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>Images</title>
|
||||
</Helmet>
|
||||
<Routes />
|
||||
</RootContainer>
|
||||
);
|
@ -2,11 +2,9 @@ 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 {
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
@ -22,18 +20,16 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
|
||||
<FlexItem flex>
|
||||
<FormGroup name="name" fluid field={Field}>
|
||||
<FormLabel>Image name</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Margin top="0.5">
|
||||
<Input placeholder={placeholderName} onBlur={null} required />
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<Divider height={remcalc(13)} transparent />
|
||||
<Margin left={1}>
|
||||
<Margin left="1">
|
||||
<Button
|
||||
type="button"
|
||||
marginTop={remcalc(8)}
|
||||
onClick={onRandomize}
|
||||
loading={randomizing}
|
||||
marginless
|
||||
@ -46,21 +42,21 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
<Margin top={3}>
|
||||
<Margin top="3">
|
||||
<FormGroup name="version" fluid field={Field}>
|
||||
<FormLabel>Version</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Margin top="0.5">
|
||||
<Input placeholder="Example: v1.0" onBlur={null} required />
|
||||
</Margin>
|
||||
<FormMeta />
|
||||
</FormGroup>
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Margin top={3}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin top="3">
|
||||
<FormGroup name="description" fluid field={Field}>
|
||||
<FormLabel>Description</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Margin top="0.5">
|
||||
<Textarea
|
||||
placeholder="Example: JarJarBinks, Anakin Skywalker, Obi Wan Kenobi, Qui-Gon Jinn, Han Solo, Wookies"
|
||||
fluid
|
@ -16,14 +16,14 @@ const Container = styled.div`
|
||||
export default ({ icon, children, collapsed = true, ...rest }) => (
|
||||
<Container {...rest}>
|
||||
<Flex>
|
||||
<Margin right={1}>
|
||||
<Margin right="1">
|
||||
<Flex alignCenter full>
|
||||
{icon}
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Small noMargin>{children}</Small>
|
||||
</Flex>
|
||||
<Margin top={1} bottom={collapsed ? 7 : 3}>
|
||||
<Margin top="1" bottom={collapsed ? 7 : 3}>
|
||||
<Divider height={remcalc(1)} />
|
||||
</Margin>
|
||||
</Container>
|
@ -5,8 +5,8 @@ import { P } from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ children }) => (
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Margin bottom={3}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin bottom="3">
|
||||
<P>{children}</P>
|
||||
</Margin>
|
||||
</Col>
|
@ -4,7 +4,7 @@ import { Margin, Padding } from 'styled-components-spacing';
|
||||
import Flex from 'styled-flex-component';
|
||||
|
||||
import { H3, Card } from 'joyent-ui-toolkit';
|
||||
import { NoPackages } from 'joyent-logo-assets';
|
||||
import { EmptyState } from 'joyent-icons';
|
||||
|
||||
const NoPackagesTitle = styled(H3)`
|
||||
color: ${props => props.theme.greyDark};
|
||||
@ -17,10 +17,10 @@ const FullWidthCard = styled(Card)`
|
||||
|
||||
export default ({ children }) => (
|
||||
<FullWidthCard>
|
||||
<Padding all={6}>
|
||||
<Padding all="6">
|
||||
<Flex alignCenter justifyCenter column>
|
||||
<Margin bottom={2}>
|
||||
<NoPackages />
|
||||
<Margin bottom="2">
|
||||
<EmptyState />
|
||||
</Margin>
|
||||
<NoPackagesTitle>{children}</NoPackagesTitle>
|
||||
</Flex>
|
@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
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 remcalc from 'remcalc';
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
PopoverTarget,
|
||||
Popover,
|
||||
PopoverItem,
|
||||
PopoverDivider,
|
||||
PopoverDivider as BasePopoverDivider,
|
||||
PopoverContainer,
|
||||
Radio,
|
||||
FormLabel,
|
||||
@ -56,11 +56,6 @@ const Content = styled(Padding)`
|
||||
|
||||
const Max = styled(Flex)`
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const DividerContainer = styled(Margin)`
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
const Actions = styled(Flex)`
|
||||
@ -71,9 +66,14 @@ const Actions = styled(Flex)`
|
||||
|
||||
const ActionsWrapper = styled(Flex)`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-left: ${remcalc(1)} solid ${props => props.theme.grey};
|
||||
`;
|
||||
|
||||
const PopoverDivider = styled(BasePopoverDivider)`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const Image = ({
|
||||
name,
|
||||
id,
|
||||
@ -84,39 +84,41 @@ export const Image = ({
|
||||
onRemove,
|
||||
onCreateInstance
|
||||
}) => (
|
||||
<Margin bottom={3}>
|
||||
<Margin bottom="3">
|
||||
<CardAnchor to={`/images/${id}`} component={Link}>
|
||||
<Card radius>
|
||||
{removing ? (
|
||||
<Padding all={2}>
|
||||
<Padding all="2">
|
||||
<StatusLoader />
|
||||
</Padding>
|
||||
) : (
|
||||
<Fragment>
|
||||
<CardHeader white radius>
|
||||
<Padding left={2} right={2}>
|
||||
<Padding left="2" right="2">
|
||||
<Flex full alignCenter>
|
||||
<Margin right={2}>
|
||||
{React.createElement(OS[os], {
|
||||
width: '24',
|
||||
height: '24'
|
||||
})}
|
||||
</Margin>
|
||||
<A to={`/images/${id}/summary`} component={Link}>
|
||||
{name}
|
||||
</A>
|
||||
<FlexItem>
|
||||
<Margin right="2">
|
||||
{React.createElement(OS[os], {
|
||||
width: '24',
|
||||
height: '24'
|
||||
})}
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<A to={`/images/${id}/summary`} component={Link}>
|
||||
{name}
|
||||
</A>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Padding>
|
||||
</CardHeader>
|
||||
<Flex justifyBetween>
|
||||
<Content left={2} top={2} bottom={2}>
|
||||
<Content left="2" top="2" bottom="2">
|
||||
<Max justifyBetween>
|
||||
<Max alignCenter>
|
||||
<Flex>{version}</Flex>
|
||||
<DividerContainer left={2}>
|
||||
<Divider width={remcalc(1)} height="100%" />
|
||||
</DividerContainer>
|
||||
<Type left={2}>{ImageType[type]}</Type>
|
||||
<Divider vertical />
|
||||
<Type>{ImageType[type]}</Type>
|
||||
</Max>
|
||||
</Max>
|
||||
</Content>
|
||||
@ -127,22 +129,26 @@ export const Image = ({
|
||||
<ActionsIcon />
|
||||
</ActionsWrapper>
|
||||
</PopoverTarget>
|
||||
<Popover placement="bottom">
|
||||
<PopoverItem disabled={false} onClick={onCreateInstance}>
|
||||
<ItemAnchor
|
||||
href={`${
|
||||
GLOBAL.origin
|
||||
}/instances/~create/?image=${name}`}
|
||||
target="__blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Create Instance
|
||||
</ItemAnchor>
|
||||
</PopoverItem>
|
||||
<Popover noPadding placement="bottom">
|
||||
<Padding horizontal="3" vertical="2">
|
||||
<PopoverItem disabled={false} onClick={onCreateInstance}>
|
||||
<ItemAnchor
|
||||
href={`${
|
||||
GLOBAL.origin
|
||||
}/instances/~create/?image=${name}`}
|
||||
target="__blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Create Instance
|
||||
</ItemAnchor>
|
||||
</PopoverItem>
|
||||
</Padding>
|
||||
<PopoverDivider />
|
||||
<PopoverItem disabled={removing} onClick={onRemove}>
|
||||
Remove
|
||||
</PopoverItem>
|
||||
<Padding horizontal="3" vertical="2">
|
||||
<PopoverItem disabled={removing} onClick={onRemove}>
|
||||
Remove
|
||||
</PopoverItem>
|
||||
</Padding>
|
||||
</Popover>
|
||||
</Actions>
|
||||
</PopoverContainer>
|
||||
@ -157,9 +163,9 @@ export const Image = ({
|
||||
export const Filters = ({ selected }) => (
|
||||
<Fragment>
|
||||
<FormGroup name="image-type" value="all" field={Field} type="radio">
|
||||
<Radio noMargin>
|
||||
<Radio>
|
||||
<Flex alignCenter>
|
||||
<Margin right={2}>
|
||||
<Margin horizontal="2">
|
||||
<FormLabel big normal={selected !== 'all'}>
|
||||
All
|
||||
</FormLabel>
|
||||
@ -175,7 +181,7 @@ export const Filters = ({ selected }) => (
|
||||
>
|
||||
<Radio noMargin>
|
||||
<Flex alignCenter>
|
||||
<Margin right={2}>
|
||||
<Margin horizontal="2">
|
||||
<FormLabel big normal={selected !== 'hardware-virtual-machine'}>
|
||||
Virtual machines
|
||||
</FormLabel>
|
||||
@ -191,7 +197,7 @@ export const Filters = ({ selected }) => (
|
||||
>
|
||||
<Radio noMargin>
|
||||
<Flex alignCenter>
|
||||
<Margin right={2}>
|
||||
<Margin horizontal="2">
|
||||
<FormLabel big normal={selected !== 'infrastructure-container'}>
|
||||
Infrastructure container
|
||||
</FormLabel>
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import forceArray from 'force-array';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import forceArray from 'force-array';
|
||||
|
||||
import {
|
||||
SectionList,
|
||||
@ -28,7 +28,7 @@ const Menu = ({ links = [] }) => {
|
||||
|
||||
return (
|
||||
<ViewContainer plain>
|
||||
<Margin bottom={6}>
|
||||
<Margin bottom="5" top="1">
|
||||
<SectionList>{getMenuItems(_links)}</SectionList>
|
||||
</Margin>
|
||||
</ViewContainer>
|
@ -1,18 +1,19 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
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 distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import titleCase from 'title-case';
|
||||
import remcalc from 'remcalc';
|
||||
import { ValueBreakpoints as breakpoints } from 'joyent-ui-toolkit';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardOutlet,
|
||||
H2,
|
||||
P,
|
||||
Label,
|
||||
Label as BaseLabel,
|
||||
Divider,
|
||||
Button,
|
||||
QueryBreakpoints,
|
||||
@ -37,11 +38,15 @@ const VerticalDivider = styled.div`
|
||||
align-self: flex-end;
|
||||
margin: 0 ${remcalc(18)};
|
||||
|
||||
@media (max-width: ${remcalc(767)}) {
|
||||
@media (max-width: ${remcalc(breakpoints.small.upper)}) {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const Label = styled(BaseLabel)`
|
||||
font-weight: 200;
|
||||
`;
|
||||
|
||||
const GreyLabel = styled(Label)`
|
||||
opacity: 0.5;
|
||||
padding-right: ${remcalc(3)};
|
||||
@ -71,7 +76,7 @@ export const Meta = ({ name, version, type, published_at, state, os }) => (
|
||||
<H2 bold>{name}</H2>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
<Margin top={2} bottom={3}>
|
||||
<Margin top="2" bottom="3">
|
||||
<Flex>
|
||||
<Label>{version}</Label>
|
||||
<VerticalDivider />
|
||||
@ -99,15 +104,15 @@ export const Meta = ({ name, version, type, published_at, state, os }) => (
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
|
||||
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={4}>
|
||||
<Padding all="5">
|
||||
<Meta {...image} />
|
||||
<Row between="xs">
|
||||
<Col xs={9}>
|
||||
<Col xs="9">
|
||||
<SmallOnly>
|
||||
<Button type="button" small icon>
|
||||
<DuplicateIcon light />
|
||||
@ -124,15 +129,14 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
|
||||
bold
|
||||
icon
|
||||
>
|
||||
<DuplicateIcon light />
|
||||
<span>Create Instance</span>
|
||||
</Button>
|
||||
</Medium>
|
||||
</Col>
|
||||
<Col xs={3}>
|
||||
<Col xs="3">
|
||||
<SmallOnly>
|
||||
<Button type="button" small icon error right>
|
||||
<DeleteIcon fill={theme.red} />
|
||||
<DeleteIcon fill="red" />
|
||||
</Button>
|
||||
</SmallOnly>
|
||||
<Medium>
|
||||
@ -145,8 +149,10 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
|
||||
error
|
||||
right
|
||||
>
|
||||
<DeleteIcon fill={theme.red} />
|
||||
<span>Remove</span>
|
||||
<Margin right="1">
|
||||
<DeleteIcon fill="red" />
|
||||
</Margin>
|
||||
<span>Delete</span>
|
||||
</Button>
|
||||
</Medium>
|
||||
</Col>
|
||||
@ -157,17 +163,23 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
|
||||
<Margin bottom="2">
|
||||
<P>{image.description}</P>
|
||||
</Margin>
|
||||
<CopiableField text={(image.id || '').split('-')[0]} label="ID" />
|
||||
<CopiableField text={image.id} label="UUID" />
|
||||
<Margin bottom="3">
|
||||
<CopiableField text={(image.id || '').split('-')[0]} label="ID" />
|
||||
</Margin>
|
||||
<Margin bottom="3">
|
||||
<CopiableField text={image.id} label="UUID" />
|
||||
</Margin>
|
||||
<Row>
|
||||
<Col xs={12} md={7}>
|
||||
<FormLabel>Operating system</FormLabel>
|
||||
<Input
|
||||
monospace
|
||||
onBlur={null}
|
||||
fluid
|
||||
value={titleCase(image.os)}
|
||||
/>
|
||||
<Col xs="12" md="7">
|
||||
<Margin bottom="3">
|
||||
<FormLabel>Operating system</FormLabel>
|
||||
<Input
|
||||
monospace
|
||||
onBlur={null}
|
||||
fluid
|
||||
value={titleCase(image.os)}
|
||||
/>
|
||||
</Margin>
|
||||
</Col>
|
||||
</Row>
|
||||
</Padding>
|
||||
@ -175,4 +187,4 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
));
|
||||
);
|
@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
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 => (
|
||||
<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 }) => (
|
||||
<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}>
|
@ -2,15 +2,8 @@ import React from 'react';
|
||||
import { Field } from 'redux-form';
|
||||
import Flex from 'styled-flex-component';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
Button,
|
||||
FormGroup,
|
||||
Input,
|
||||
FormLabel,
|
||||
Divider
|
||||
} from 'joyent-ui-toolkit';
|
||||
import { Button, FormGroup, Input, FormLabel } from 'joyent-ui-toolkit';
|
||||
|
||||
export const Toolbar = ({
|
||||
searchable = true,
|
||||
@ -21,16 +14,15 @@ export const Toolbar = ({
|
||||
actionable = false,
|
||||
onActionClick
|
||||
}) => (
|
||||
<Flex justifyBetween>
|
||||
<Flex justifyBetween alignEnd>
|
||||
<FormGroup name="filter" field={Field}>
|
||||
<FormLabel>{searchLabel}</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Margin top="0.5">
|
||||
<Input placeholder={searchPlaceholder} disabled={!searchable} />
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
{action ? (
|
||||
<FormGroup right>
|
||||
<Divider height={remcalc(21)} transparent />
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!actionable}
|
||||
@ -48,6 +40,5 @@ export const Toolbar = ({
|
||||
export default ({ handleSubmit, ...rest }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Toolbar {...rest} />
|
||||
<Divider height={remcalc(20)} transparent />
|
||||
</form>
|
||||
);
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import paramCase from 'param-case';
|
||||
import get from 'lodash.get';
|
||||
|
||||
@ -43,7 +44,9 @@ export default ({ match }) => {
|
||||
.filter(Boolean)
|
||||
.map(({ name, pathname }) => (
|
||||
<BreadcrumbItem key={name} to={pathname} component={Link}>
|
||||
{name}
|
||||
<Margin horizontal="1" vertical="3">
|
||||
{name}
|
||||
</Margin>
|
||||
</BreadcrumbItem>
|
||||
));
|
||||
|
@ -67,12 +67,12 @@ const NameContainer = ({
|
||||
onRandomize={handleRandomize}
|
||||
/>
|
||||
) : name ? (
|
||||
<Margin top={3}>
|
||||
<Margin top="3">
|
||||
<H3 bold noMargin>
|
||||
{name}
|
||||
</H3>
|
||||
{version ? (
|
||||
<Margin top={2}>
|
||||
<Margin top="2">
|
||||
<H4 bold noMargin>
|
||||
{version}
|
||||
</H4>
|
||||
@ -80,8 +80,8 @@ const NameContainer = ({
|
||||
) : null}
|
||||
{description ? (
|
||||
<Row>
|
||||
<Col xs={12} sm={8}>
|
||||
<Margin top={1}>
|
||||
<Col xs="12" sm="8">
|
||||
<Margin top="1">
|
||||
<P>{description}</P>
|
||||
</Margin>
|
||||
</Col>
|
||||
@ -92,13 +92,13 @@ const NameContainer = ({
|
||||
}
|
||||
</ReduxForm>
|
||||
{expanded ? (
|
||||
<Margin top={4} bottom={7}>
|
||||
<Margin top="4" bottom="7">
|
||||
<Button type="button" disabled={!name} onClick={handleNext}>
|
||||
Next
|
||||
</Button>
|
||||
</Margin>
|
||||
) : proceeded ? (
|
||||
<Margin top={4} bottom={7}>
|
||||
<Margin top="4" bottom="7">
|
||||
<Button type="button" onClick={handleEdit} secondary>
|
||||
Edit
|
||||
</Button>
|
||||
@ -166,6 +166,7 @@ export default compose(
|
||||
dispatch(set({ name: 'create-image-name-randomizing', value: false }));
|
||||
|
||||
if (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
@ -6,17 +6,10 @@ import { destroy, reset } from 'redux-form';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import get from 'lodash.get';
|
||||
import remcalc from 'remcalc';
|
||||
import Flex from 'styled-flex-component';
|
||||
|
||||
import {
|
||||
TagsIcon,
|
||||
Button,
|
||||
H3,
|
||||
TagList,
|
||||
Divider,
|
||||
KeyValue
|
||||
} from 'joyent-ui-toolkit';
|
||||
import { TagsIcon, Button, H3, TagList } from 'joyent-ui-toolkit';
|
||||
import { KeyValue } from 'joyent-ui-resource-widgets';
|
||||
|
||||
import Title from '@components/create-image/title';
|
||||
import Description from '@components/description';
|
||||
@ -66,7 +59,7 @@ export const Tags = ({
|
||||
) : null}
|
||||
{proceeded || expanded ? (
|
||||
<Fragment>
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<H3>
|
||||
{tags.length} Tag{tags.length === 1 ? '' : 's'}
|
||||
</H3>
|
||||
@ -102,12 +95,11 @@ export const Tags = ({
|
||||
expanded
|
||||
onCancel={() => handleChangeAddOpen(false)}
|
||||
/>
|
||||
<Divider height={remcalc(18)} transparent />
|
||||
</Fragment>
|
||||
) : null
|
||||
}
|
||||
</ReduxForm>
|
||||
<Margin top={1}>
|
||||
<Margin top="1">
|
||||
<Flex alignCenter>
|
||||
{expanded ? (
|
||||
<Button
|
||||
@ -118,11 +110,11 @@ export const Tags = ({
|
||||
Add Tag
|
||||
</Button>
|
||||
) : null}
|
||||
<Margin left={1}>{children}</Margin>
|
||||
<Margin left="1">{children}</Margin>
|
||||
</Flex>
|
||||
</Margin>
|
||||
{proceeded ? (
|
||||
<Margin top={1}>
|
||||
<Margin top="1">
|
||||
<Button type="button" onClick={handleEdit} secondary>
|
||||
Edit
|
||||
</Button>
|
@ -1,5 +1,3 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
@ -41,12 +39,12 @@ const Create = ({
|
||||
}) => (
|
||||
<ViewContainer>
|
||||
{loading ? (
|
||||
<Margin top={4}>
|
||||
<Margin top="4">
|
||||
<StatusLoader />
|
||||
</Margin>
|
||||
) : null}
|
||||
{loadingError ? (
|
||||
<Margin top={4}>
|
||||
<Margin top="4">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>{loadingError}</MessageDescription>
|
||||
@ -54,7 +52,7 @@ const Create = ({
|
||||
</Margin>
|
||||
) : null}
|
||||
{!loading && !loadingError ? (
|
||||
<Margin top={4} bottom={4}>
|
||||
<Margin top="4" bottom="5">
|
||||
<H2>Create Image</H2>
|
||||
</Margin>
|
||||
) : null}
|
||||
@ -78,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>
|
@ -2,7 +2,6 @@ import React, { Fragment } from 'react';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import { connect } from 'react-redux';
|
||||
import get from 'lodash.get';
|
||||
@ -41,20 +40,21 @@ export const List = ({
|
||||
handleRemove
|
||||
}) => (
|
||||
<ViewContainer main>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<ReduxForm form={LIST_TOOLBAR_FORM}>
|
||||
{props => <ToolbarForm {...props} actionable={!loading} />}
|
||||
</ReduxForm>
|
||||
<Divider height={remcalc(1)} />
|
||||
<Divider height={remcalc(24)} transparent />
|
||||
<Margin top="4">
|
||||
<ReduxForm form={LIST_TOOLBAR_FORM}>
|
||||
{props => <ToolbarForm {...props} actionable={!loading} />}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
<Margin vertical="4">
|
||||
<Divider />
|
||||
</Margin>
|
||||
{loading && !images.length ? (
|
||||
<Fragment>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<StatusLoader />
|
||||
</Fragment>
|
||||
) : null}
|
||||
{error && !images.length && !loading ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
@ -64,7 +64,7 @@ export const List = ({
|
||||
</Margin>
|
||||
) : null}
|
||||
<Fragment>
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="4">
|
||||
<ReduxForm
|
||||
form={LIST_TOGGLE_TYPE_FORM}
|
||||
initialValues={{ 'image-type': 'all' }}
|
||||
@ -78,7 +78,7 @@ export const List = ({
|
||||
</Margin>
|
||||
<Row>
|
||||
{images.map(image => (
|
||||
<Col sm={4}>
|
||||
<Col sm="4">
|
||||
<Image
|
||||
{...image}
|
||||
onCreateInstance={() => handleCreateInstance(image)}
|
@ -10,7 +10,7 @@ const SECTIONS = [
|
||||
|
||||
export default ({ match }) => {
|
||||
const imageId = get(match, 'params.image');
|
||||
const sections = imageId !== '~create' ? SECTIONS : [];
|
||||
const sections = imageId === '~create' ? [] : SECTIONS;
|
||||
|
||||
const links = sections.map(({ name, pathname }) => ({
|
||||
name,
|
@ -1,16 +1,14 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React from 'react';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { connect } from 'react-redux';
|
||||
import intercept from 'apr-intercept';
|
||||
import { set } from 'react-redux-values';
|
||||
import get from 'lodash.get';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
StatusLoader,
|
||||
Divider,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription
|
||||
@ -30,14 +28,9 @@ export const Summary = ({
|
||||
handleRemove
|
||||
}) => (
|
||||
<ViewContainer main>
|
||||
{loading && !image ? (
|
||||
<Fragment>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<StatusLoader />
|
||||
</Fragment>
|
||||
) : null}
|
||||
{loading && !image ? <StatusLoader /> : null}
|
||||
{error && !loading && !image ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
@ -47,7 +40,7 @@ export const Summary = ({
|
||||
</Margin>
|
||||
) : null}
|
||||
{mutationError ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
@ -14,11 +14,11 @@ import {
|
||||
H3,
|
||||
ViewContainer,
|
||||
StatusLoader,
|
||||
Divider,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription,
|
||||
TagList
|
||||
TagList,
|
||||
Divider
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Forms } from '@root/constants';
|
||||
@ -56,12 +56,14 @@ export const Tags = ({
|
||||
onActionClick={handleToggleAddOpen}
|
||||
action
|
||||
/>
|
||||
<Divider height={remcalc(1)} />
|
||||
<Margin vertical="4">
|
||||
<Divider height={remcalc(1)} />
|
||||
</Margin>
|
||||
</Margin>
|
||||
)}
|
||||
</ReduxForm>
|
||||
{error && !loading && !tags.length ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
@ -71,7 +73,7 @@ export const Tags = ({
|
||||
</Margin>
|
||||
) : null}
|
||||
{mutationError ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>{mutationError}</MessageDescription>
|
||||
@ -80,13 +82,13 @@ export const Tags = ({
|
||||
) : null}
|
||||
<ReduxForm
|
||||
form={TAGS_ADD_FORM}
|
||||
asyncValidate={handleAsyncValidate}
|
||||
shouldAsyncValidate={shouldAsyncValidate}
|
||||
asyncValidate={handleAsyncValidate}
|
||||
onSubmit={handleAddTag}
|
||||
>
|
||||
{props =>
|
||||
addOpen ? (
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<AddForm
|
||||
{...props}
|
||||
onToggleExpanded={() => handleToggleAddOpen(!addOpen)}
|
||||
@ -96,18 +98,19 @@ export const Tags = ({
|
||||
) : null
|
||||
}
|
||||
</ReduxForm>
|
||||
{!loading ? (
|
||||
<Margin bottom={4}>
|
||||
{loading ? null : (
|
||||
<Margin bottom="5">
|
||||
<H3>
|
||||
{tags.length} tag{tags.length === 1 ? '' : 's'}
|
||||
</H3>
|
||||
</Margin>
|
||||
) : null}
|
||||
)}
|
||||
{loading && !tags.length ? <StatusLoader /> : null}
|
||||
<TagList>
|
||||
{tags.map(({ name, value }) => (
|
||||
{tags.map(({ id, name, value }) => (
|
||||
<Tag
|
||||
key={value}
|
||||
key={id}
|
||||
id={id}
|
||||
name={name}
|
||||
value={value}
|
||||
onRemoveClick={!mutating && (() => handleRemoveTag(name))}
|
28
consoles/my-joy-images/src/html.js
Normal file
28
consoles/my-joy-images/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>
|
||||
);
|
@ -1,5 +1,6 @@
|
||||
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';
|
||||
@ -21,7 +22,9 @@ ReactDOM.hydrate(
|
||||
<ThemeProvider theme={theme}>
|
||||
<ReduxProvider store={createStore()}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
<HelmetProvider context={{}}>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
</BrowserRouter>
|
||||
</ReduxProvider>
|
||||
</ThemeProvider>
|
@ -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>
|
@ -17,7 +17,7 @@ import Breadcrumb from '@containers/breadcrumb';
|
||||
export const Route = () => (
|
||||
<ViewContainer main>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<Margin bottom={4}>
|
||||
<Margin bottom="5">
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
42
consoles/my-joy-images/src/state/apollo-client.js
Normal file
42
consoles/my-joy-images/src/state/apollo-client.js
Normal 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
|
||||
});
|
||||
};
|
@ -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';
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -14,14 +14,16 @@ const validateField = async (field, value) => {
|
||||
const validateSchema = async (schema, value) => {
|
||||
const errors = await reduce(
|
||||
keys(schema),
|
||||
async (errors, name) =>
|
||||
assign(errors, {
|
||||
[name]: await validateField(schema[name], value[name])
|
||||
}),
|
||||
async (errors, name) => {
|
||||
const msg = await validateField(schema[name], value[name]);
|
||||
return msg ? assign(errors, { [name]: msg }) : errors;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
throw errors;
|
||||
if (keys(errors).length) {
|
||||
throw errors;
|
||||
}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -64,4 +66,4 @@ const Schemas = {
|
||||
export const addTag = tag => validateSchema(Schemas.tag, tag);
|
||||
|
||||
export const instanceName = ({ name }) =>
|
||||
!name ? null : validateSchema(Schemas.instanceName, { name });
|
||||
name ? validateSchema(Schemas.instanceName, { name }) : null;
|
133
consoles/my-joy-instances/lib/index.js
Normal file
133
consoles/my-joy-instances/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 = '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');
|
@ -6,39 +6,38 @@
|
||||
"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",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"lint": "redrun lint:ci -- --fix",
|
||||
"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": "DEFAULT_TIMEOUT_INTERVAL=100000 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:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files"
|
||||
},
|
||||
"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",
|
||||
"constant-case": "^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": "^5.0.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",
|
||||
@ -52,41 +51,41 @@
|
||||
"lodash.isfunction": "^3.0.9",
|
||||
"lodash.isinteger": "^4.0.4",
|
||||
"lodash.isnan": "^3.0.2",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.reduce": "^4.6.0",
|
||||
"lodash.reverse": "^4.0.1",
|
||||
"lodash.some": "^4.6.0",
|
||||
"lodash.sortby": "^4.7.0",
|
||||
"lodash.uniqby": "^4.7.0",
|
||||
"lodash.values": "^4.3.0",
|
||||
"mz": "^2.7.0",
|
||||
"param-case": "^2.1.1",
|
||||
"query-string": "^6.0.0",
|
||||
"react": "^16.3.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-dom": "^16.3.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-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.0.3",
|
||||
"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"
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user