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
|
artifacts
|
||||||
reports
|
reports
|
||||||
|
.nyc_output
|
||||||
|
coverage
|
||||||
|
dist
|
||||||
|
styleguide
|
||||||
|
build
|
||||||
|
consoles/*/lib/app
|
||||||
|
node_modules
|
@ -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
2
.gitignore
vendored
@ -165,3 +165,5 @@ prototypes/*/package-lock.json
|
|||||||
|
|
||||||
_env*
|
_env*
|
||||||
keys*
|
keys*
|
||||||
|
/packages/*/public/index.html
|
||||||
|
/consoles/*/public/index.html
|
||||||
|
@ -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
1
.vscode/settings.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
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': [
|
'scope-enum': [
|
||||||
2,
|
2,
|
||||||
'always',
|
'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 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
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
});
|
});
|
@ -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>
|
||||||
);
|
);
|
@ -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
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
||||||
));
|
);
|
@ -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}>
|
@ -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>
|
||||||
);
|
);
|
@ -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>
|
||||||
));
|
));
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
@ -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>
|
@ -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>
|
@ -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)}
|
@ -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,
|
@ -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>
|
@ -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))}
|
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 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>
|
@ -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>
|
@ -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>
|
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 { 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();
|
@ -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;
|
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",
|
"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
Loading…
Reference in New Issue
Block a user