feat(bundle): support sso
|
@ -0,0 +1,85 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const Brule = require('brule');
|
||||||
|
const Hapi = require('hapi');
|
||||||
|
const Inert = require('inert');
|
||||||
|
const Main = require('apr-main');
|
||||||
|
const Rollover = require('rollover');
|
||||||
|
|
||||||
|
const Sso = require('minio-proto-auth');
|
||||||
|
const Ui = require('my-joy-beta');
|
||||||
|
const Nav = require('joyent-navigation');
|
||||||
|
const Api = require('cloudapi-gql');
|
||||||
|
|
||||||
|
const {
|
||||||
|
PORT = 3069,
|
||||||
|
COOKIE_PASSWORD,
|
||||||
|
COOKIE_DOMAIN,
|
||||||
|
SDC_KEY_PATH,
|
||||||
|
SDC_ACCOUNT,
|
||||||
|
SDC_KEY_ID,
|
||||||
|
SDC_URL,
|
||||||
|
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||||
|
ROLLBAR_SERVER_TOKEN,
|
||||||
|
NODE_ENV = 'development'
|
||||||
|
} = process.env;
|
||||||
|
|
||||||
|
const server = Hapi.server({
|
||||||
|
port: PORT,
|
||||||
|
host: '127.0.0.1'
|
||||||
|
});
|
||||||
|
|
||||||
|
Main(async () => {
|
||||||
|
await server.register([
|
||||||
|
// {
|
||||||
|
// plugin: Rollover,
|
||||||
|
// options: {
|
||||||
|
// rollbar: {
|
||||||
|
// accessToken: ROLLBAR_SERVER_TOKEN,
|
||||||
|
// reportLevel: 'error'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
plugin: Brule,
|
||||||
|
options: {
|
||||||
|
auth: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Sso,
|
||||||
|
options: {
|
||||||
|
cookie: {
|
||||||
|
password: COOKIE_PASSWORD,
|
||||||
|
domain: COOKIE_DOMAIN,
|
||||||
|
isSecure: false,
|
||||||
|
isHttpOnly: true,
|
||||||
|
ttl: 1000 * 60 * 60 // 1 hour
|
||||||
|
},
|
||||||
|
sso: {
|
||||||
|
keyPath: SDC_KEY_PATH,
|
||||||
|
keyId: '/' + SDC_ACCOUNT + '/keys/' + SDC_KEY_ID,
|
||||||
|
apiBaseUrl: SDC_URL,
|
||||||
|
url: 'https://sso.joyent.com/login',
|
||||||
|
permissions: { cloudapi: ['/my/*'] },
|
||||||
|
baseUrl: BASE_URL,
|
||||||
|
isDev: NODE_ENV === 'development'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Nav
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Ui
|
||||||
|
},
|
||||||
|
{
|
||||||
|
plugin: Api
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.auth.default('sso');
|
||||||
|
|
||||||
|
await server.start();
|
||||||
|
console.log(`server started at http://localhost:${server.info.port}`);
|
||||||
|
});
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"name": "joyent-portal-bundle",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"license": "MPL-2.0",
|
||||||
|
"scripts": {
|
||||||
|
"start": "NODE_ENV=development PORT=3069 REACT_APP_GQL_PORT=3069 REACT_APP_GQL_PROTOCOL=http node -r ./_env.js index.js",
|
||||||
|
"prepublish": "echo 0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"apr-main": "^2.0.2",
|
||||||
|
"brule": "^3.1.0",
|
||||||
|
"cloudapi-gql": "^4.3.1",
|
||||||
|
"hapi": "^17.2.0",
|
||||||
|
"inert": "^5.1.0",
|
||||||
|
"joyent-navigation": "^1.0.0",
|
||||||
|
"minio-proto-auth": "^1.1.0",
|
||||||
|
"my-joy-beta": "^1.0.0",
|
||||||
|
"rollover": "^1.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
TRITON_ACCOUNT=$(triton account get | awk -F": " '/id:/{print $2}')
|
||||||
|
TRITON_DC=$(triton profile get | awk -F"/" '/url:/{print $3}' | awk -F'.' '{print $1}')
|
||||||
|
|
||||||
|
DEFAULT_DOMAIN=${TRITON_ACCOUNT}.${TRITON_DC}.cns.triton.zone
|
||||||
|
|
||||||
|
read -p "Enter the domain name you plan to use for this key [$DEFAULT_DOMAIN]: " domain
|
||||||
|
domain="${domain:-$DEFAULT_DOMAIN}"
|
||||||
|
echo -n "Enter the password to use for the key: "
|
||||||
|
read -s password
|
||||||
|
echo
|
||||||
|
echo "Generating key for $domain"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
keys_path=keys-$domain
|
||||||
|
mkdir -p $keys_path
|
||||||
|
|
||||||
|
openssl genrsa -aes256 -passout pass:$password -out $keys_path/ca.key 4096
|
||||||
|
chmod 400 $keys_path/ca.key
|
||||||
|
openssl req -new -x509 -sha256 -days 730 -key $keys_path/ca.key -out $keys_path/ca.crt -passin pass:$password -subj "/CN=copilot"
|
||||||
|
chmod 444 $keys_path/ca.crt
|
||||||
|
|
||||||
|
|
||||||
|
openssl genrsa -out $keys_path/server.key 2048
|
||||||
|
chmod 400 $keys_path/server.key
|
||||||
|
openssl req -new -key $keys_path/server.key -sha256 -out $keys_path/server.csr -passin pass:$password -subj "/CN=$domain"
|
||||||
|
openssl x509 -req -days 365 -sha256 -in $keys_path/server.csr -passin pass:$password -CA $keys_path/ca.crt -CAkey $keys_path/ca.key -set_serial 1 -out $keys_path/server.crt
|
||||||
|
chmod 444 $keys_path/server.crt
|
||||||
|
|
||||||
|
openssl genrsa -out $keys_path/client.key 2048
|
||||||
|
openssl req -new -key $keys_path/client.key -out $keys_path/client.csr -subj "/CN=$domain"
|
||||||
|
openssl x509 -req -days 365 -sha256 -in $keys_path/client.csr -CA $keys_path/ca.crt -CAkey $keys_path/ca.key -set_serial 2 -out $keys_path/client.crt -passin pass:$password
|
||||||
|
openssl pkcs12 -export -clcerts -in $keys_path/client.crt -inkey $keys_path/client.key -out $keys_path/client.p12 -passout pass:$password
|
||||||
|
|
||||||
|
# open $keys_path/client.p12 &
|
||||||
|
echo
|
||||||
|
echo "You can complete setup by running './setup.sh ~/path/to/TRITON_PRIVATE_KEY $keys_path/ca.crt $keys_path/server.key $keys_path/server.crt'"
|
|
@ -0,0 +1,235 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo
|
||||||
|
echo 'Usage ./setup.sh ~/path/to/TRITON_PRIVATE_KEY ~/path/to/CA_CRT ~/path/to/SERVER_KEY ~/path/to/SERVER_CRT'
|
||||||
|
echo
|
||||||
|
echo 'Checks that your Triton and Docker environment is sane and configures'
|
||||||
|
echo 'an environment file to use.'
|
||||||
|
echo
|
||||||
|
echo 'TRITON_PRIVATE_KEY is the filesystem path to an SSH private key'
|
||||||
|
echo 'used to connect to Triton.'
|
||||||
|
echo
|
||||||
|
echo 'CA_CRT is the filesystem path to a certificate authority crt file.'
|
||||||
|
echo
|
||||||
|
echo 'SERVER_KEY is the filesystem path to a TLS server key file.'
|
||||||
|
echo
|
||||||
|
echo 'SERVER_CRT is the filesystem path to a TLS server crt file.'
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for correct configuration
|
||||||
|
check() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Please provide a path to a SSH private key to access Triton.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$1" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'SSH private key for Triton is unreadable.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Assign args to named vars
|
||||||
|
TRITON_PRIVATE_KEY_PATH=$1
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z "$2" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Please provide a path to the NGINX CA crt file.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$2" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'CA certificate for NGINX is unreadable.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NGINX_CA_CRT_PATH=$2
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z "$3" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Please provide a path to the server key file.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$3" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Server key file for NGINX is unreadable.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NGINX_SERVER_KEY_PATH=$3
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z "$4" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Please provide a path to the server crt file.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$4" ]; then
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Server crt file for NGINX is unreadable.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
|
||||||
|
help
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
NGINX_SERVER_CRT_PATH=$4
|
||||||
|
|
||||||
|
command -v docker >/dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Docker is required, but does not appear to be installed.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
echo 'See https://docs.joyent.com/public-cloud/api-access/docker'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command -v triton >/dev/null 2>&1 || {
|
||||||
|
echo
|
||||||
|
tput rev # reverse
|
||||||
|
tput bold # bold
|
||||||
|
echo 'Error! Joyent Triton CLI is required, but does not appear to be installed.'
|
||||||
|
tput sgr0 # clear
|
||||||
|
echo 'See https://www.joyent.com/blog/introducing-the-triton-command-line-tool'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TRITON_USER=$(triton profile get | awk -F": " '/account:/{print $2}')
|
||||||
|
TRITON_DC=$(triton profile get | awk -F"/" '/url:/{print $3}' | awk -F'.' '{print $1}')
|
||||||
|
TRITON_ACCOUNT=$(triton account get | awk -F": " '/id:/{print $2}')
|
||||||
|
|
||||||
|
SDC_URL=$(triton env | grep SDC_URL | awk -F"=" '{print $2}' | awk -F"\"" '{print $2}')
|
||||||
|
SDC_ACCOUNT=$(triton env | grep SDC_ACCOUNT | awk -F"=" '{print $2}' | awk -F"\"" '{print $2}')
|
||||||
|
SDC_KEY_ID=$(triton env | grep SDC_KEY_ID | awk -F"=" '{print $2}' | awk -F"\"" '{print $2}')
|
||||||
|
|
||||||
|
DOCKER_CERT_PATH=$(triton env | grep DOCKER_CERT_PATH | awk -F"=" '{print $2}')
|
||||||
|
DOCKER_HOST=$(triton env | grep DOCKER_HOST | awk -F"=" '{print $2}')
|
||||||
|
|
||||||
|
rm _env_consul
|
||||||
|
rm _env_mysql
|
||||||
|
rm _env
|
||||||
|
|
||||||
|
echo MYSQL_DATABASE=bridge-db >> _env_mysql
|
||||||
|
echo 'MYSQL_ROOT_PASSWORD='$(cat /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 12) >> _env_mysql
|
||||||
|
echo MYSQL_USER=bridge-user >> _env_mysql
|
||||||
|
echo 'MYSQL_PASSWORD='$(cat /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 8) >> _env_mysql
|
||||||
|
|
||||||
|
echo >> _env_mysql
|
||||||
|
|
||||||
|
echo '# Consul discovery via Triton CNS' >> _env_consul
|
||||||
|
echo CONSUL=bridge-consul.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.joyent.com >> _env_consul
|
||||||
|
echo CONSUL_AGENT=1 >> _env_consul
|
||||||
|
echo >> _env_consul
|
||||||
|
|
||||||
|
TRITON_CREDS_PATH=/root/.triton
|
||||||
|
|
||||||
|
echo '# Allowed list of account Ids who can access the site' >> _env
|
||||||
|
echo ALLOWED_ACCOUNTS=${TRITON_ACCOUNT} >> _env
|
||||||
|
echo >> _env
|
||||||
|
|
||||||
|
echo '# Site URL' >> _env
|
||||||
|
echo BASE_URL=https://bridge.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.triton.zone >> _env
|
||||||
|
echo COOKIE_DOMAIN=triton.zone >> _env
|
||||||
|
echo >> _env
|
||||||
|
|
||||||
|
echo '# MySQL via Triton CNS' >> _env
|
||||||
|
echo MYSQL_HOST=bridge-mysql.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.joyent.com >> _env
|
||||||
|
echo >> _env
|
||||||
|
|
||||||
|
echo PORT=8080 >> _env
|
||||||
|
echo 'COOKIE_PASSWORD='$(cat /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 36) >> _env
|
||||||
|
echo SDC_KEY_PATH=/root/.ssh/id_rsa >> _env
|
||||||
|
echo DOCKER_CERT_PATH=${TRITON_CREDS_PATH} >> _env
|
||||||
|
echo TRITON_CREDS_PATH=${TRITON_CREDS_PATH} >> _env
|
||||||
|
echo DOCKER_TLS_VERIFY=1 >> _env
|
||||||
|
echo DOCKER_HOST=${DOCKER_HOST} >> _env
|
||||||
|
echo SDC_URL=${SDC_URL} >> _env
|
||||||
|
echo SDC_ACCOUNT=${SDC_ACCOUNT} >> _env
|
||||||
|
echo SDC_KEY_ID=${SDC_KEY_ID} >> _env
|
||||||
|
echo CONSUL=bridge-consul.svc.${TRITON_ACCOUNT}.${TRITON_DC}.cns.joyent.com >> _env
|
||||||
|
|
||||||
|
echo TRITON_CA=$(cat "${DOCKER_CERT_PATH}"/ca.pem | tr '\n' '#') >> _env
|
||||||
|
echo TRITON_CA_PATH=${TRITON_CREDS_PATH}/ca.pem >> _env
|
||||||
|
echo TRITON_KEY=$(cat "${DOCKER_CERT_PATH}"/key.pem | tr '\n' '#') >> _env
|
||||||
|
echo TRITON_KEY_PATH=${TRITON_CREDS_PATH}/key.pem >> _env
|
||||||
|
echo TRITON_CERT=$(cat "${DOCKER_CERT_PATH}"/cert.pem | tr '\n' '#') >> _env
|
||||||
|
echo TRITON_CERT_PATH=${TRITON_CREDS_PATH}/cert.pem >> _env
|
||||||
|
|
||||||
|
echo SDC_KEY=$(cat "${TRITON_PRIVATE_KEY_PATH}" | tr '\n' '#') >> _env
|
||||||
|
echo SDC_KEY_PUB=$(cat "${TRITON_PRIVATE_KEY_PATH}".pub | tr '\n' '#') >> _env
|
||||||
|
|
||||||
|
echo NGINX_CA_CRT=$(cat "${NGINX_CA_CRT_PATH}" | tr '\n' '#') >> _env
|
||||||
|
echo NGINX_SERVER_KEY=$(cat "${NGINX_SERVER_KEY_PATH}" | tr '\n' '#') >> _env
|
||||||
|
echo NGINX_SERVER_CRT=$(cat "${NGINX_SERVER_CRT_PATH}" | tr '\n' '#') >> _env
|
||||||
|
|
||||||
|
echo >> _env
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------------------------------------------------
|
||||||
|
# parse arguments
|
||||||
|
|
||||||
|
# Get function list
|
||||||
|
funcs=($(declare -F -p | cut -d " " -f 3))
|
||||||
|
|
||||||
|
until
|
||||||
|
if [ ! -z "$1" ]; then
|
||||||
|
# check if the first arg is a function in this file, or use a default
|
||||||
|
if [[ " ${funcs[@]} " =~ " $1 " ]]; then
|
||||||
|
cmd=$1
|
||||||
|
shift 1
|
||||||
|
else
|
||||||
|
cmd="check"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$cmd "$@"
|
||||||
|
if [ $? == 127 ]; then
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
do
|
||||||
|
echo
|
||||||
|
done
|
|
@ -4,7 +4,7 @@ module.exports = {
|
||||||
'scope-enum': [
|
'scope-enum': [
|
||||||
2,
|
2,
|
||||||
'always',
|
'always',
|
||||||
['ui-toolkit', 'icons', 'my-joy-beta', 'navigation']
|
['ui-toolkit', 'icons', 'my-joy-beta', 'navigation', 'bundle']
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -71,7 +71,5 @@
|
||||||
"breeze-nexttick": "0.2.1",
|
"breeze-nexttick": "0.2.1",
|
||||||
"zen-observable": "0.7.1"
|
"zen-observable": "0.7.1"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": ["packages/*", "bundle"]
|
||||||
"packages/*"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"babel-preset-joyent-portal": "^6.0.1",
|
"babel-preset-joyent-portal": "^6.0.1",
|
||||||
"eslint": "^4.13.1",
|
"eslint": "^4.13.1",
|
||||||
"eslint-config-joyent-portal": "^3.2.0",
|
"eslint-config-joyent-portal": "^3.2.0",
|
||||||
"joyent-react-scripts": "^6.5.1",
|
"joyent-react-scripts": "^7.2.0",
|
||||||
"react": "^16.2.0",
|
"react": "^16.2.0",
|
||||||
"redrun": "^5.10.0"
|
"redrun": "^5.10.0"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
const Inert = require('inert');
|
||||||
|
const Path = require('path');
|
||||||
|
const Execa = require('execa');
|
||||||
|
const { readFile } = require('mz/fs');
|
||||||
|
|
||||||
|
exports.register = async server => {
|
||||||
|
await Execa('npm', ['run', 'build'], {
|
||||||
|
cwd: Path.join(__dirname, '..'),
|
||||||
|
stdio: 'inherit'
|
||||||
|
});
|
||||||
|
|
||||||
|
const indexFile = await readFile(
|
||||||
|
Path.join(__dirname, '../build/index.html'),
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
|
||||||
|
await server.register(Inert);
|
||||||
|
|
||||||
|
server.route([
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/static/{path*}',
|
||||||
|
config: {
|
||||||
|
auth: false,
|
||||||
|
handler: {
|
||||||
|
directory: {
|
||||||
|
path: Path.join(__dirname, '../build/static/'),
|
||||||
|
redirectToSlash: true,
|
||||||
|
index: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
method: '*',
|
||||||
|
path: '/{path*}',
|
||||||
|
config: {
|
||||||
|
handler: (request, h) => {
|
||||||
|
return h.response(indexFile).type('text/html');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.pkg = require('../package.json');
|
|
@ -4,7 +4,7 @@
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"repository": "github:yldio/joyent-portal",
|
"repository": "github:yldio/joyent-portal",
|
||||||
"main": "build/",
|
"main": "lib/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
"dev": "REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
||||||
"start": "PORT=3069 joyent-react-scripts start",
|
"start": "PORT=3069 joyent-react-scripts start",
|
||||||
|
@ -24,7 +24,6 @@
|
||||||
"constant-case": "^2.0.0",
|
"constant-case": "^2.0.0",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.29.0",
|
||||||
"declarative-redux-form": "^2.0.8",
|
"declarative-redux-form": "^2.0.8",
|
||||||
"joyent-manifest-editor": "^1.4.0",
|
|
||||||
"joyent-ui-toolkit": "^4.4.1",
|
"joyent-ui-toolkit": "^4.4.1",
|
||||||
"lodash.find": "^4.6.0",
|
"lodash.find": "^4.6.0",
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
|
@ -33,6 +32,7 @@
|
||||||
"lodash.sortby": "^4.7.0",
|
"lodash.sortby": "^4.7.0",
|
||||||
"lodash.uniqby": "^4.7.0",
|
"lodash.uniqby": "^4.7.0",
|
||||||
"lunr": "^2.1.5",
|
"lunr": "^2.1.5",
|
||||||
|
"mz": "^2.7.0",
|
||||||
"normalized-styled-components": "^1.0.17",
|
"normalized-styled-components": "^1.0.17",
|
||||||
"param-case": "^2.1.1",
|
"param-case": "^2.1.1",
|
||||||
"prop-types": "^15.6.0",
|
"prop-types": "^15.6.0",
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
"eslint": "^4.13.1",
|
"eslint": "^4.13.1",
|
||||||
"eslint-config-joyent-portal": "^3.2.0",
|
"eslint-config-joyent-portal": "^3.2.0",
|
||||||
"jest-styled-components": "^4.9.0",
|
"jest-styled-components": "^4.9.0",
|
||||||
"joyent-react-scripts": "^6.5.1",
|
"joyent-react-scripts": "^7.2.0",
|
||||||
"react-test-renderer": "^16.2.0",
|
"react-test-renderer": "^16.2.0",
|
||||||
"redrun": "^5.10.0"
|
"redrun": "^5.10.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="header"></div>
|
<div id="header"></div>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="text/javascript" src="//localhost:3000/static/js/bundle.js"></script>
|
<script type="text/javascript" src="/nav-static/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -64,7 +64,7 @@ export const AddServiceForm = ({ handleSubmit, pristine }) => (
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const Hostname = ({ values, network, service, ...hostname }) => (
|
export const Hostname = ({ values = [], network, service, ...hostname }) => (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{values.length ? (
|
{values.length ? (
|
||||||
<Margin bottom={4}>
|
<Margin bottom={4}>
|
||||||
|
|
|
@ -153,12 +153,13 @@ export default ({
|
||||||
<FormGroup name="image" field={Field}>
|
<FormGroup name="image" field={Field}>
|
||||||
<Version onBlur={null}>
|
<Version onBlur={null}>
|
||||||
<option selected>Version</option>
|
<option selected>Version</option>
|
||||||
{image.versions && image.versions.map(version => (
|
{image.versions &&
|
||||||
<option
|
image.versions.map(version => (
|
||||||
key={`${version.name} - ${version.version}`}
|
<option
|
||||||
value={version.id}
|
key={`${version.name} - ${version.version}`}
|
||||||
>{`${version.name} - ${version.version}`}</option>
|
value={version.id}
|
||||||
))}
|
>{`${version.name} - ${version.version}`}</option>
|
||||||
|
))}
|
||||||
</Version>
|
</Version>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -84,7 +84,7 @@ export const Item = ({
|
||||||
<PopoverTarget box>
|
<PopoverTarget box>
|
||||||
<ActionsIcon />
|
<ActionsIcon />
|
||||||
</PopoverTarget>
|
</PopoverTarget>
|
||||||
<Popover placement="top">
|
<Popover placement="bottom">
|
||||||
<PopoverItem disabled={!allowedActions.start} onClick={onStart}>
|
<PopoverItem disabled={!allowedActions.start} onClick={onStart}>
|
||||||
Start
|
Start
|
||||||
</PopoverItem>
|
</PopoverItem>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Field } from 'redux-form';
|
import { Field } from 'redux-form';
|
||||||
|
import remcalc from 'remcalc';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Row,
|
Row,
|
||||||
|
@ -7,7 +8,8 @@ import {
|
||||||
FormGroup,
|
FormGroup,
|
||||||
Input,
|
Input,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
Button
|
Button,
|
||||||
|
Divider
|
||||||
} from 'joyent-ui-toolkit';
|
} from 'joyent-ui-toolkit';
|
||||||
|
|
||||||
export const Toolbar = ({
|
export const Toolbar = ({
|
||||||
|
@ -45,5 +47,6 @@ 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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -32,6 +32,7 @@ import {
|
||||||
AddServiceForm,
|
AddServiceForm,
|
||||||
HostnamesHeader
|
HostnamesHeader
|
||||||
} from '@components/create-instance/cns';
|
} from '@components/create-instance/cns';
|
||||||
|
|
||||||
import Title from '@components/create-instance/title';
|
import Title from '@components/create-instance/title';
|
||||||
import Tag from '@components/instances/tags';
|
import Tag from '@components/instances/tags';
|
||||||
import Description from '@components/create-instance/description';
|
import Description from '@components/create-instance/description';
|
||||||
|
@ -42,7 +43,7 @@ const CNSContainer = ({
|
||||||
submitted,
|
submitted,
|
||||||
expanded,
|
expanded,
|
||||||
proceeded,
|
proceeded,
|
||||||
serviceNames,
|
serviceNames = [],
|
||||||
instanceName,
|
instanceName,
|
||||||
cnsEnabled = true,
|
cnsEnabled = true,
|
||||||
hostnames = [],
|
hostnames = [],
|
||||||
|
@ -196,6 +197,7 @@ export default compose(
|
||||||
'create-instance-name.values.name',
|
'create-instance-name.values.name',
|
||||||
'<instance-name>'
|
'<instance-name>'
|
||||||
);
|
);
|
||||||
|
|
||||||
const serviceNames = get(values, `${CNS_FORM}-services`, []);
|
const serviceNames = get(values, `${CNS_FORM}-services`, []);
|
||||||
|
|
||||||
// REPLACE WITH DATA CENTER
|
// REPLACE WITH DATA CENTER
|
||||||
|
@ -220,12 +222,12 @@ export default compose(
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
hostnames.map(hostname => {
|
hostnames.forEach(hostname => {
|
||||||
if (!hostname.service) {
|
if (!hostname.service) {
|
||||||
return hostname;
|
return hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
return serviceNames.map(name => {
|
serviceNames.forEach(name => {
|
||||||
const postfix = hostname.public ? '.triton.zone' : '.cns.joyent.com';
|
const postfix = hostname.public ? '.triton.zone' : '.cns.joyent.com';
|
||||||
const value = `${name}.svc.${id}.${dataCenter}${postfix}`;
|
const value = `${name}.svc.${id}.${dataCenter}${postfix}`;
|
||||||
hostname.values.push(value);
|
hostname.values.push(value);
|
||||||
|
@ -249,12 +251,10 @@ export default compose(
|
||||||
handleToggleCnsEnabled: ({ target }) =>
|
handleToggleCnsEnabled: ({ target }) =>
|
||||||
dispatch(set({ name: `${CNS_FORM}-enabled`, value: !cnsEnabled })),
|
dispatch(set({ name: `${CNS_FORM}-enabled`, value: !cnsEnabled })),
|
||||||
handleAddService: ({ name }) => {
|
handleAddService: ({ name }) => {
|
||||||
const serviceName = punycode.encode(
|
const serviceName = punycode
|
||||||
name
|
.encode(name.toLowerCase().replace(/\s/g, '-'))
|
||||||
.toLowerCase()
|
.replace(/\-$/, '');
|
||||||
.split(' ')
|
|
||||||
.join('-')
|
|
||||||
);
|
|
||||||
dispatch([
|
dispatch([
|
||||||
destroy(`${CNS_FORM}-new-service`),
|
destroy(`${CNS_FORM}-new-service`),
|
||||||
set({
|
set({
|
||||||
|
|
|
@ -50,7 +50,7 @@ const ImageContainer = ({
|
||||||
onSubmit={handleNext}
|
onSubmit={handleNext}
|
||||||
>
|
>
|
||||||
{props =>
|
{props =>
|
||||||
(loading && expanded) ? (
|
loading && expanded ? (
|
||||||
<StatusLoader />
|
<StatusLoader />
|
||||||
) : expanded ? (
|
) : expanded ? (
|
||||||
<Image
|
<Image
|
||||||
|
|
|
@ -100,7 +100,7 @@ export default compose(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(/^[a-zA-Z0-9][a-zA-Z0-9\\_\\.\\-]*$/).test(name)) {
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9\\_\\.\\-]*$/.test(name)) {
|
||||||
throw {
|
throw {
|
||||||
name: 'Invalid name'
|
name: 'Invalid name'
|
||||||
};
|
};
|
||||||
|
|
|
@ -118,7 +118,9 @@ export const Metadata = ({
|
||||||
<ToolbarForm
|
<ToolbarForm
|
||||||
{...props}
|
{...props}
|
||||||
searchable={!_loading}
|
searchable={!_loading}
|
||||||
actionLabel="Add metadata"
|
searchLabel="Filter metadata"
|
||||||
|
searchPlaceholder="Search by name or value"
|
||||||
|
actionLabel="Add Metadata"
|
||||||
actionable={!_loading}
|
actionable={!_loading}
|
||||||
onActionClick={() => handleToggleAddOpen(!addOpen)}
|
onActionClick={() => handleToggleAddOpen(!addOpen)}
|
||||||
/>
|
/>
|
||||||
|
@ -140,7 +142,7 @@ export default compose(
|
||||||
graphql(DeleteMetadata, { name: 'deleteMetadata' }),
|
graphql(DeleteMetadata, { name: 'deleteMetadata' }),
|
||||||
graphql(GetMetadata, {
|
graphql(GetMetadata, {
|
||||||
options: ({ match }) => ({
|
options: ({ match }) => ({
|
||||||
// pollInterval: 1000,
|
pollInterval: 1000,
|
||||||
variables: {
|
variables: {
|
||||||
name: get(match, 'params.instance')
|
name: get(match, 'params.instance')
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import get from 'lodash.get';
|
||||||
import sort from 'lodash.sortby';
|
import sort from 'lodash.sortby';
|
||||||
import { set } from 'react-redux-values';
|
import { set } from 'react-redux-values';
|
||||||
import ReduxForm from 'declarative-redux-form';
|
import ReduxForm from 'declarative-redux-form';
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
import intercept from 'apr-intercept';
|
import intercept from 'apr-intercept';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -77,12 +76,10 @@ const Snapshots = ({
|
||||||
!loading && createSnapshotOpen ? (
|
!loading && createSnapshotOpen ? (
|
||||||
<ReduxForm form={CREATE_FORM_NAME} onSubmit={handleCreateSnapshot}>
|
<ReduxForm form={CREATE_FORM_NAME} onSubmit={handleCreateSnapshot}>
|
||||||
{props => (
|
{props => (
|
||||||
<Margin top={5}>
|
<SnapshotAddForm
|
||||||
<SnapshotAddForm
|
{...props}
|
||||||
{...props}
|
onCancel={() => toggleCreateSnapshotOpen(false)}
|
||||||
onCancel={() => toggleCreateSnapshotOpen(false)}
|
/>
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
)}
|
)}
|
||||||
</ReduxForm>
|
</ReduxForm>
|
||||||
) : null;
|
) : null;
|
||||||
|
|
|
@ -117,7 +117,9 @@ export const Tags = ({
|
||||||
<ToolbarForm
|
<ToolbarForm
|
||||||
{...props}
|
{...props}
|
||||||
searchable={!_loading}
|
searchable={!_loading}
|
||||||
actionLabel="Add tag"
|
searchLabel="Filter tags"
|
||||||
|
searchPlaceholder="Search by name or value"
|
||||||
|
actionLabel="Add Tag"
|
||||||
actionable={!editing}
|
actionable={!editing}
|
||||||
onActionClick={() => handleToggleAddOpen(!addOpen)}
|
onActionClick={() => handleToggleAddOpen(!addOpen)}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
const Inert = require('inert');
|
||||||
|
const Path = require('path');
|
||||||
|
const Execa = require('execa');
|
||||||
|
const { readFile } = require('mz/fs');
|
||||||
|
|
||||||
|
const ROOT = Path.join(__dirname, '../build');
|
||||||
|
|
||||||
|
exports.register = async server => {
|
||||||
|
await Execa('npm', ['run', 'build'], {
|
||||||
|
cwd: Path.join(__dirname, '..'),
|
||||||
|
stdio: 'inherit'
|
||||||
|
});
|
||||||
|
|
||||||
|
const manifest = require('../build/asset-manifest.json');
|
||||||
|
|
||||||
|
await server.register(Inert);
|
||||||
|
|
||||||
|
server.route([
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
path: '/nav-static/{path*}',
|
||||||
|
config: {
|
||||||
|
auth: false,
|
||||||
|
handler: (request, h) => {
|
||||||
|
const { params } = request;
|
||||||
|
const { path } = params;
|
||||||
|
|
||||||
|
const file = manifest[path];
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return h.continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.file(Path.join(ROOT, file), { confine: ROOT });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.pkg = require('../package.json');
|
|
@ -2,15 +2,16 @@
|
||||||
"name": "joyent-navigation",
|
"name": "joyent-navigation",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"main": "src",
|
"main": "lib",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "PREACT=1 NODE_ENV=development joyent-react-scripts start",
|
"dev": "PREACT=1 REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
||||||
"build": "PREACT=1 NODE_ENV=production joyent-react-scripts build",
|
"build": "PREACT=1 NODE_ENV=production joyent-react-scripts build",
|
||||||
"test": "NODE_ENV=test joyent-react-scripts test",
|
"test": "NODE_ENV=test joyent-react-scripts test",
|
||||||
"test-ci": "npm run test",
|
"test-ci": "npm run test",
|
||||||
"fmt": "prettier --write --single-quote *.md src/**/*.js src/**/*.gql",
|
"fmt": "prettier --write --single-quote *.md src/**/*.js src/**/*.gql",
|
||||||
"lint-ci": "eslint . --ext .js --ext .md",
|
"lint-ci": "eslint . --ext .js --ext .md",
|
||||||
"lint": "eslint . --fix --ext .js --ext .md"
|
"lint": "eslint . --fix --ext .js --ext .md",
|
||||||
|
"prepublish": "echo 0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"apollo-cache-inmemory": "^1.1.5",
|
"apollo-cache-inmemory": "^1.1.5",
|
||||||
|
@ -39,6 +40,6 @@
|
||||||
"babel-preset-joyent-portal": "^6.0.1",
|
"babel-preset-joyent-portal": "^6.0.1",
|
||||||
"eslint": "^4.15.0",
|
"eslint": "^4.15.0",
|
||||||
"eslint-config-joyent-portal": "^3.2.0",
|
"eslint-config-joyent-portal": "^3.2.0",
|
||||||
"joyent-react-scripts": "^6.5.1"
|
"joyent-react-scripts": "^7.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ const Services = ({ categories = [] }) => (
|
||||||
{chunk(categories, 4).map(chunk => (
|
{chunk(categories, 4).map(chunk => (
|
||||||
<Row>
|
<Row>
|
||||||
{chunk.map(({ name, services }) => (
|
{chunk.map(({ name, services }) => (
|
||||||
<Col xs={12} md={6} lg={3}>
|
<Col xs={12} sm={6} md={4} lg={3}>
|
||||||
<ServiceCategory>{name}</ServiceCategory>
|
<ServiceCategory>{name}</ServiceCategory>
|
||||||
{services.map(({ name, description }) => (
|
{services.map(({ name, description }) => (
|
||||||
<Service>
|
<Service>
|
||||||
|
|
|
@ -31,6 +31,14 @@ const getHeader = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const getAccount = gql`
|
||||||
|
{
|
||||||
|
account {
|
||||||
|
login
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const Panel = ({ name = '', expanded = false, children, ...rest }) => {
|
const Panel = ({ name = '', expanded = false, children, ...rest }) => {
|
||||||
if (!expanded) {
|
if (!expanded) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -45,7 +53,7 @@ const Panel = ({ name = '', expanded = false, children, ...rest }) => {
|
||||||
return React.createElement(overlay, rest, children);
|
return React.createElement(overlay, rest, children);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Navigation = ({ toggleSectionOpen, isOpen, activePanel }) => (
|
const Navigation = ({ login, toggleSectionOpen, isOpen, activePanel }) => (
|
||||||
<Header onOutsideClick={() => toggleSectionOpen()}>
|
<Header onOutsideClick={() => toggleSectionOpen()}>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderItem>
|
<HeaderItem>
|
||||||
|
@ -76,20 +84,31 @@ const Navigation = ({ toggleSectionOpen, isOpen, activePanel }) => (
|
||||||
</HeaderItemIcon>
|
</HeaderItemIcon>
|
||||||
</HeaderItem>
|
</HeaderItem>
|
||||||
<HeaderDividerItem />
|
<HeaderDividerItem />
|
||||||
<HeaderItem>
|
{login ? (
|
||||||
<HeaderItemContent>
|
<HeaderItem>
|
||||||
<HeaderItemSubContent>Account:</HeaderItemSubContent> George
|
<HeaderItemContent>
|
||||||
</HeaderItemContent>
|
<HeaderItemSubContent>Account:</HeaderItemSubContent> {login}
|
||||||
<HeaderItemIcon>
|
</HeaderItemContent>
|
||||||
<Avatar />
|
<HeaderItemIcon>
|
||||||
</HeaderItemIcon>
|
<Avatar />
|
||||||
</HeaderItem>
|
</HeaderItemIcon>
|
||||||
|
</HeaderItem>
|
||||||
|
) : null}
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
<Panel expanded={isOpen} name={activePanel} />
|
<Panel expanded={isOpen} name={activePanel} />
|
||||||
</Header>
|
</Header>
|
||||||
);
|
);
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
graphql(getAccount, {
|
||||||
|
props: ({ data }) => {
|
||||||
|
const { account = {}, loading = false, error = null } = data;
|
||||||
|
|
||||||
|
const { login } = account;
|
||||||
|
|
||||||
|
return { login, loading, error };
|
||||||
|
}
|
||||||
|
}),
|
||||||
graphql(getHeader, {
|
graphql(getHeader, {
|
||||||
props: ({ data }) => {
|
props: ({ data }) => {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
"eslint": "^4.13.1",
|
"eslint": "^4.13.1",
|
||||||
"eslint-config-joyent-portal": "^3.2.0",
|
"eslint-config-joyent-portal": "^3.2.0",
|
||||||
"jest-styled-components": "^4.9.0",
|
"jest-styled-components": "^4.9.0",
|
||||||
"joyent-react-scripts": "^6.5.1",
|
"joyent-react-scripts": "^7.2.0",
|
||||||
"lodash.isboolean": "^3.0.3",
|
"lodash.isboolean": "^3.0.3",
|
||||||
"react": "^16.2.0",
|
"react": "^16.2.0",
|
||||||
"react-docgen": "^3.0.0-beta8",
|
"react-docgen": "^3.0.0-beta8",
|
||||||
|
|
|
@ -44,7 +44,6 @@ Array [
|
||||||
}
|
}
|
||||||
|
|
||||||
.c0 {
|
.c0 {
|
||||||
min-width: 9.5rem;
|
|
||||||
box-shadow: 0 0.125rem 0.375rem rgba(0,0,0,0.1);
|
box-shadow: 0 0.125rem 0.375rem rgba(0,0,0,0.1);
|
||||||
border: 0.0625rem solid rgb(216,216,216);
|
border: 0.0625rem solid rgb(216,216,216);
|
||||||
padding: 0.9375rem 1.125rem 0.1875rem 1.125rem;
|
padding: 0.9375rem 1.125rem 0.1875rem 1.125rem;
|
||||||
|
|
|
@ -13,7 +13,6 @@ import Baseline from '../baseline';
|
||||||
const arrowClassName = rndId();
|
const arrowClassName = rndId();
|
||||||
|
|
||||||
const Popper = styled(BasePopper)`
|
const Popper = styled(BasePopper)`
|
||||||
min-width: ${remcalc(152)};
|
|
||||||
box-shadow: 0 ${remcalc(2)} ${remcalc(6)} rgba(0, 0, 0, 0.1);
|
box-shadow: 0 ${remcalc(2)} ${remcalc(6)} rgba(0, 0, 0, 0.1);
|
||||||
border: ${remcalc(1)} solid ${props => props.theme.grey};
|
border: ${remcalc(1)} solid ${props => props.theme.grey};
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ exports[`Button H1 1`] = `
|
||||||
font-size: 2.25rem;
|
font-size: 2.25rem;
|
||||||
line-height: 2.8125rem;
|
line-height: 2.8125rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
font-stretch: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ export const H1 = NH1.extend`
|
||||||
font-size: ${remcalc(36)};
|
font-size: ${remcalc(36)};
|
||||||
line-height: ${remcalc(45)};
|
line-height: ${remcalc(45)};
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
font-stretch: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
|
@ -115,7 +116,6 @@ export const H3 = styled.h3`
|
||||||
|
|
||||||
export const H4 = styled.h4`
|
export const H4 = styled.h4`
|
||||||
color: ${props => props.theme.text};
|
color: ${props => props.theme.text};
|
||||||
|
|
||||||
font-weight: ${props => props.theme.font.weight.semibold};
|
font-weight: ${props => props.theme.font.weight.semibold};
|
||||||
line-height: ${remcalc(24)};
|
line-height: ${remcalc(24)};
|
||||||
font-size: ${remcalc(15)};
|
font-size: ${remcalc(15)};
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
"babel-preset-joyent-portal": "^6.0.1",
|
"babel-preset-joyent-portal": "^6.0.1",
|
||||||
"eslint": "^4.11.0",
|
"eslint": "^4.11.0",
|
||||||
"eslint-config-joyent-portal": "^3.2.0",
|
"eslint-config-joyent-portal": "^3.2.0",
|
||||||
"joyent-react-scripts": "^6.5.1",
|
"joyent-react-scripts": "^7.2.0",
|
||||||
"prettier": "^1.8.2",
|
"prettier": "^1.8.2",
|
||||||
"stylelint": "^8.4.0",
|
"stylelint": "^8.4.0",
|
||||||
"stylelint-config-joyent-portal": "^2.0.1"
|
"stylelint-config-joyent-portal": "^2.0.1"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"presets": "joyent-portal"
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
src/components/base/*.css
|
|
||||||
node_modules
|
|
||||||
coverage
|
|
||||||
.nyc_output
|
|
||||||
docs/static
|
|
||||||
!docs/static/index.html
|
|
||||||
docs/node_modules
|
|
||||||
dist
|
|
||||||
package-lock.json
|
|
|
@ -1,4 +0,0 @@
|
||||||
.nyc_output
|
|
||||||
coverage
|
|
||||||
dist
|
|
||||||
build
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "joyent-portal",
|
|
||||||
"rules": {
|
|
||||||
"no-console": 0,
|
|
||||||
"new-cap": 0,
|
|
||||||
// temp
|
|
||||||
"no-undef": 1,
|
|
||||||
"no-debugger": 1,
|
|
||||||
"no-negated-condition": 0,
|
|
||||||
"jsx-a11y/href-no-hash": 0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
/node_modules
|
|
||||||
|
|
||||||
# testing
|
|
||||||
/coverage
|
|
||||||
|
|
||||||
# production
|
|
||||||
/build
|
|
||||||
|
|
||||||
# misc
|
|
||||||
.DS_Store
|
|
||||||
.env
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
{
|
|
||||||
"extends": ["stylelint-config-joyent-portal"]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"libs": [
|
|
||||||
"ecmascript",
|
|
||||||
"browser"
|
|
||||||
],
|
|
||||||
"plugins": {
|
|
||||||
"doc_comment": true,
|
|
||||||
"local-scope": true,
|
|
||||||
"jsx": true,
|
|
||||||
"node": true,
|
|
||||||
"webpack": {
|
|
||||||
"configPath": "./node_modules/react-scripts/config/webpack.config.dev.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
language: node_js
|
|
||||||
node_js:
|
|
||||||
- "8"
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
|
@ -1,20 +0,0 @@
|
||||||
# my-joyent
|
|
||||||
|
|
||||||
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)
|
|
||||||
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg)](https://github.com/RichardLitt/standard-readme)
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
* [Usage](#usage)
|
|
||||||
* [License](#license)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run start
|
|
||||||
open http://0.0.0.0:3069
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MPL-2.0
|
|
|
@ -1,66 +0,0 @@
|
||||||
{
|
|
||||||
"name": "joyent-create-instance-icons",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"license": "MPL-2.0",
|
|
||||||
"private": true,
|
|
||||||
"repository": "github:yldio/joyent-portal",
|
|
||||||
"main": "build/",
|
|
||||||
"scripts": {
|
|
||||||
"dev":
|
|
||||||
"REACT_APP_GQL_PORT=4000 PORT=3069 REACT_APP_GQL_PROTOCOL=http joyent-react-scripts start",
|
|
||||||
"start": "PORT=3069 joyent-react-scripts start",
|
|
||||||
"build": "NODE_ENV=production joyent-react-scripts build",
|
|
||||||
"lint:css": "echo 0 `# stylelint './src/**/*.js'`",
|
|
||||||
"lint:js": "eslint . --fix",
|
|
||||||
"lint": "redrun -s lint:*",
|
|
||||||
"test": "NODE_ENV=test ./test/run --env=jsdom",
|
|
||||||
"test-ci": "echo 0 `# NODE_ENV=test ./test/run --env=jsdom --coverage`",
|
|
||||||
"prepublish": "echo 0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"animate-css-styled-components": "^0.0.20",
|
|
||||||
"apollo": "^0.2.2",
|
|
||||||
"graphql-tag": "^2.5.0",
|
|
||||||
"joyent-ui-toolkit": "^2.0.1",
|
|
||||||
"lodash.isempty": "^4.4.0",
|
|
||||||
"lodash.isequal": "^4.5.0",
|
|
||||||
"normalized-styled-components": "^1.0.17",
|
|
||||||
"prop-types": "^15.6.0",
|
|
||||||
"react": "^16.1.1",
|
|
||||||
"react-apollo": "^1.4.16",
|
|
||||||
"react-dom": "^16.1.1",
|
|
||||||
"react-popper": "^0.7.4",
|
|
||||||
"react-redux": "^5.0.6",
|
|
||||||
"react-router": "^4.2.0",
|
|
||||||
"react-router-dom": "^4.2.2",
|
|
||||||
"react-styled-flexboxgrid": "^2.1.1",
|
|
||||||
"recompose": "^0.26.0",
|
|
||||||
"redux": "^3.7.2",
|
|
||||||
"redux-form": "^7.1.2",
|
|
||||||
"remcalc": "^1.0.9",
|
|
||||||
"styled-components": "^2.3.0",
|
|
||||||
"styled-components-spacing": "^2.1.3",
|
|
||||||
"styled-is": "^1.1.0",
|
|
||||||
"unitcalc": "^1.1.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"apr-for-each": "^1.0.6",
|
|
||||||
"apr-main": "^2.0.2",
|
|
||||||
"babel-minify-webpack-plugin": "^0.2.0",
|
|
||||||
"babel-preset-joyent-portal": "^6.0.1",
|
|
||||||
"commitizen": "^2.9.6",
|
|
||||||
"cross-env": "^5.1.1",
|
|
||||||
"eslint": "^4.11.0",
|
|
||||||
"eslint-config-joyent-portal": "3.2.0",
|
|
||||||
"eslint-config-prettier": "^2.7.0",
|
|
||||||
"eslint-plugin-markdown": "^1.0.0-beta.6",
|
|
||||||
"joyent-react-scripts": "^6.5.1",
|
|
||||||
"lodash.sortby": "^4.7.0",
|
|
||||||
"mz": "^2.7.0",
|
|
||||||
"react-scripts": "^1.0.17",
|
|
||||||
"react-test-renderer": "^16.1.1",
|
|
||||||
"redrun": "^5.10.0",
|
|
||||||
"stylelint": "^8.4.0",
|
|
||||||
"stylelint-config-joyent-portal": "^2.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 24 KiB |
|
@ -1,27 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
|
||||||
<meta name="theme-color" content="#1E313B">
|
|
||||||
<title>My Joyent</title>
|
|
||||||
<style>
|
|
||||||
html, body, #root {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#root {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="root"></div>
|
|
||||||
<noscript>
|
|
||||||
You need to enable Javascript to view this page
|
|
||||||
</noscript>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,30 +0,0 @@
|
||||||
{
|
|
||||||
"short_name": "Joyent",
|
|
||||||
"name": "My Joyent",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "192x192",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "256x256",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "384x384",
|
|
||||||
"type": "image/png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "512x512",
|
|
||||||
"type": "image/png"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": "./index.html",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#1E313B",
|
|
||||||
"background_color": "#FAFAFA"
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { ThemeProvider } from 'styled-components';
|
|
||||||
import { theme, RootContainer } from 'joyent-ui-toolkit';
|
|
||||||
import { ApolloProvider } from 'react-apollo';
|
|
||||||
|
|
||||||
import { client, store } from '@state/store';
|
|
||||||
import Router from '@root/router';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
const fullTheme = {
|
|
||||||
...theme,
|
|
||||||
flexboxgrid: {
|
|
||||||
gridSize: 12, // rem
|
|
||||||
gutterWidth: 1.25, // rem
|
|
||||||
outerMargin: 1.875, // rem
|
|
||||||
mediaQuery: 'only screen',
|
|
||||||
container: {
|
|
||||||
sm: 46, // rem
|
|
||||||
md: 56, // rem
|
|
||||||
lg: 59 // rem
|
|
||||||
},
|
|
||||||
breakpoints: {
|
|
||||||
xs: 0, // em
|
|
||||||
sm: 48, // em
|
|
||||||
md: 64, // em
|
|
||||||
lg: 75 // em
|
|
||||||
}
|
|
||||||
},
|
|
||||||
spacing: {
|
|
||||||
0.5: remcalc(4),
|
|
||||||
0: remcalc(0),
|
|
||||||
1: remcalc(6),
|
|
||||||
2: remcalc(12),
|
|
||||||
3: remcalc(18),
|
|
||||||
4: remcalc(24),
|
|
||||||
5: remcalc(30),
|
|
||||||
6: remcalc(36),
|
|
||||||
7: remcalc(42),
|
|
||||||
8: remcalc(48),
|
|
||||||
9: remcalc(54),
|
|
||||||
10: remcalc(60)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => (
|
|
||||||
<ApolloProvider client={client} store={store}>
|
|
||||||
<ThemeProvider theme={fullTheme}>
|
|
||||||
<RootContainer>
|
|
||||||
<Router />
|
|
||||||
</RootContainer>
|
|
||||||
</ThemeProvider>
|
|
||||||
</ApolloProvider>
|
|
||||||
);
|
|
|
@ -1 +0,0 @@
|
||||||
<svg width="176" height="60" viewBox="0 0 176 60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>joyent-cloud-1</title><desc>Created using Figma</desc><path id="a" fill="#D8D8D8" d="M175.67 60a16.303 16.303 0 0 0-2.724-7.875 16.344 16.344 0 0 0-6.262-5.508 16.37 16.37 0 0 0-16.115.838 38.689 38.689 0 0 0-5.527-30.199 38.775 38.775 0 0 0-11.168-11.013A38.85 38.85 0 0 0 103.561 1.1a38.839 38.839 0 0 0-14.184 6.714 38.77 38.77 0 0 0-10.362 11.773 38.707 38.707 0 0 0-4.843 14.909 25.76 25.76 0 0 0-13.037-7.712 25.79 25.79 0 0 0-15.123.944 25.746 25.746 0 0 0-11.974 9.273 25.684 25.684 0 0 0-4.677 14.39 16.35 16.35 0 0 0-7.919-5.67 16.375 16.375 0 0 0-9.744-.166 16.352 16.352 0 0 0-8.107 5.399A16.31 16.31 0 0 0 0 60h175.67z"/></svg>
|
|
Before Width: | Height: | Size: 775 B |
|
@ -1 +0,0 @@
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>cpu</title><path fill="#8043DC" fill-rule="evenodd" d="M8 16h8V8H8v8zm-1 1h10V7H7v10z"/><path fill="#8043DC" fill-rule="evenodd" d="M20 18c0 1.103-.897 2-2 2H6c-1.103 0-2-.897-2-2V6c0-1.103.897-2 2-2h12c1.103 0 2 .897 2 2v12zm3-5a1 1 0 1 0 0-2h-1v-1h1a1 1 0 1 0 0-2h-1V6a4 4 0 0 0-4-4h-2V1a1 1 0 1 0-2 0v1h-1V1a1 1 0 1 0-2 0v1h-1V1a1 1 0 1 0-2 0v1H6a4 4 0 0 0-4 4v2H1a1 1 0 1 0 0 2h1v1H1a1 1 0 1 0 0 2h1v1H1a1 1 0 1 0 0 2h1v2a4 4 0 0 0 4 4h2v1a1 1 0 1 0 2 0v-1h1v1a1 1 0 1 0 2 0v-1h1v1a1 1 0 1 0 2 0v-1h2a4 4 0 0 0 4-4v-2h1a1 1 0 1 0 0-2h-1v-1h1z"/></svg>
|
|
Before Width: | Height: | Size: 645 B |
|
@ -1 +0,0 @@
|
||||||
<svg width="22" height="20" viewBox="0 0 22 20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Icon: GP</title><desc>Created using Figma</desc><path fill="#E08A0E" fill-rule="evenodd" d="M17 16a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7 17h1v-2H7v2zm-2 0h1v-2H5v2zm-2 0h1v-2H3v2zm14-7a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7 11h1V9H7v2zm-2 0h1V9H5v2zm-2 0h1V9H3v2zm16-7a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5h1V3H7v2zM5 5h1V3H5v2zM3 5h1V3H3v2zM2 18h18v-4H2v4zm0-6h18V8H2v4zm0-6h18V2H2v4zm20-4a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v4c0 .366.105.705.277 1A1.977 1.977 0 0 0 0 8v4c0 .366.105.705.277 1A1.977 1.977 0 0 0 0 14v4a2 2 0 0 0 2 2h18a2 2 0 0 0 2-2v-4c0-.366-.105-.705-.277-1 .172-.295.277-.634.277-1V8c0-.366-.105-.705-.277-1 .172-.295.277-.634.277-1V2z"/></svg>
|
|
Before Width: | Height: | Size: 772 B |
Before Width: | Height: | Size: 23 KiB |
|
@ -1 +0,0 @@
|
||||||
<svg width="23" height="23" viewBox="0 0 23 23" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Icon: MO</title><desc>Created using Figma</desc><path transform="rotate(45 7.8 18.83)" fill="#32ABCF" fill-rule="evenodd" d="M3 15h3v-2H3v2zm0 2.999h3v-2H3v2zm0-6h3v-2H3v2zm0-3h3V7H3v2zM3 6h3V4H3v2zM2 20h7V2H2v18zM12 9a1 1 0 1 0 0-2h-1V6h1a1 1 0 1 0 0-2h-1V2a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v18a2 2 0 0 0 2 2h7a2 2 0 0 0 2-2v-2h1a1 1 0 1 0 0-2h-1v-1h1a1 1 0 1 0 0-2h-1v-1h1a1 1 0 1 0 0-2h-1V9h1z"/></svg>
|
|
Before Width: | Height: | Size: 534 B |
|
@ -1,2 +0,0 @@
|
||||||
<svg viewBox="0 0 6 11" width="6" height="11" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><desc>Created using Figma</desc><path transform="matrix(0 1 -1 0 6 7.3)" fill="#464646" fill-rule="evenodd" d="M.685 0L0 .85 2.136 3 0 5.15.685 6l2.982-3L.685 0z"/>
|
|
||||||
<path id="b" fill-rule="evenodd" d="M.685 0L0 .85 2.136 3 0 5.15.685 6l2.982-3L.685 0z" transform="matrix(0 -1 1 0 0 3.7)" fill="#464646"/></svg>
|
|
Before Width: | Height: | Size: 434 B |
|
@ -1 +0,0 @@
|
||||||
<svg width="20" height="20" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>Icon: SO</title><desc>Created using Figma</desc><path fill="#A88A83" fill-rule="evenodd" d="M18 17a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v14zM17 0H3a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V3a3 3 0 0 0-3-3z"/><path transform="translate(4 4)" fill="#A88A83" fill-rule="evenodd" d="M6 11c-2.757 0-5-2.243-5-5s2.243-5 5-5 5 2.243 5 5-2.243 5-5 5zM6 0a6 6 0 0 0 0 12A6 6 0 0 0 6 0z"/><path transform="translate(9 9)" fill="#A88A83" fill-rule="evenodd" d="M0 1a1 1 0 1 0 2 0 1 1 0 1 0-2 0z"/></svg>
|
|
Before Width: | Height: | Size: 658 B |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
|
@ -1,192 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import { compose, withState } from 'recompose';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
import { FadeIn, SlideInDown } from 'animate-css-styled-components';
|
|
||||||
|
|
||||||
import {
|
|
||||||
CardOutlet,
|
|
||||||
CardHeader,
|
|
||||||
CardHeaderMeta,
|
|
||||||
Card,
|
|
||||||
ArrowIcon,
|
|
||||||
Input,
|
|
||||||
Button,
|
|
||||||
Select,
|
|
||||||
H5
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const MarginInline = styled(Margin)`
|
|
||||||
display: inline;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const capitalizeFirstLetter = string =>
|
|
||||||
string.charAt(0).toUpperCase() + string.slice(1);
|
|
||||||
|
|
||||||
const FullWidthCard = styled(Card)`
|
|
||||||
flex-basis: 100%;
|
|
||||||
margin-bottom: ${remcalc(18)};
|
|
||||||
overflow: hidden;
|
|
||||||
height: auto;
|
|
||||||
`;
|
|
||||||
const enhance = compose(withState('open', 'toggleCard', true));
|
|
||||||
|
|
||||||
const ListRules = ({ rule, open, toggleCard, updateRule, deleteRule }) => (
|
|
||||||
<FadeIn duration="0.8s">
|
|
||||||
<FullWidthCard shadow collapsed={open}>
|
|
||||||
<CardHeader
|
|
||||||
onClick={() => toggleCard(n => !n)}
|
|
||||||
actionable
|
|
||||||
secondary={false}
|
|
||||||
transparent={false}
|
|
||||||
>
|
|
||||||
<CardHeaderMeta>
|
|
||||||
<Row between="xs" middle="xs">
|
|
||||||
<Col xs={11}>
|
|
||||||
<b>{capitalizeFirstLetter(rule.instance)}</b>
|
|
||||||
{`: be on ${rule.be} node as the instance(s) identified by the `}
|
|
||||||
{!rule.tagKey
|
|
||||||
? `${rule.type} ${rule.match} "${rule.value}"`
|
|
||||||
: `tag key ${rule.tagKeyType} "${rule.tagKey}" and tag value ${rule.tagValueType} "${rule.tagValue}"`}
|
|
||||||
</Col>
|
|
||||||
<Col>
|
|
||||||
<ArrowIcon />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</CardHeaderMeta>
|
|
||||||
</CardHeader>
|
|
||||||
<CardOutlet>
|
|
||||||
<SlideInDown duration="0.5s">
|
|
||||||
<div>
|
|
||||||
<H5 inline>The instance</H5>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
value={rule.instance}
|
|
||||||
onChange={e => updateRule({ ...rule, instance: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>must</option>
|
|
||||||
<option>should</option>
|
|
||||||
</Select>
|
|
||||||
<H5 inline>be on</H5>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
value={rule.be}
|
|
||||||
onChange={e => updateRule({ ...rule, be: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>the same</option>
|
|
||||||
<option>a different</option>
|
|
||||||
</Select>
|
|
||||||
<H5 inline>node as the instance(s) identified by the</H5>
|
|
||||||
<div>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
left
|
|
||||||
value={rule.type}
|
|
||||||
onChange={e => updateRule({ ...rule, type: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>instance name</option>
|
|
||||||
<option>tag</option>
|
|
||||||
</Select>
|
|
||||||
{rule.type === 'instance name'
|
|
||||||
? [
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
value={rule.match}
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, match: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
value={rule.value}
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, value: e.target.value })}
|
|
||||||
placeholder="Example instance name: nginx"
|
|
||||||
/>
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
value={rule.tagKeyType}
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, tagKeyType: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
value={rule.tagKey}
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, tagKey: e.target.value })}
|
|
||||||
placeholder="key"
|
|
||||||
/>,
|
|
||||||
<H5 inline>and value</H5>,
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select
|
|
||||||
fluid
|
|
||||||
embedded
|
|
||||||
value={rule.tagValueType}
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, tagValueType: e.target.value })}
|
|
||||||
>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
required
|
|
||||||
onChange={e =>
|
|
||||||
updateRule({ ...rule, tagValue: e.target.value })}
|
|
||||||
value={rule.tagValue}
|
|
||||||
placeholder="value"
|
|
||||||
/>
|
|
||||||
]}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button secondary onClick={() => toggleCard(n => !n)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button secondary onClick={() => deleteRule(rule.id)}>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => toggleCard(n => !n)}>Edit</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</SlideInDown>
|
|
||||||
</CardOutlet>
|
|
||||||
</FullWidthCard>
|
|
||||||
</FadeIn>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default enhance(ListRules);
|
|
|
@ -1,784 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Packages /> without throwing 1`] = `
|
|
||||||
.c1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c7 {
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 600;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-flex-grow: 4;
|
|
||||||
-ms-flex-grow: 4;
|
|
||||||
flex-grow: 4;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem 1.125rem 0 1.125rem;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
min-height: 7.875rem;
|
|
||||||
margin-bottom: 0.625rem;
|
|
||||||
border: 0.0625rem solid;
|
|
||||||
box-shadow: 0 0.125rem 0 0 rgba(0,0,0,0.05);
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-right: 0rem;
|
|
||||||
margin-left: 0rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid;
|
|
||||||
box-shadow: 0px 2px 0px rgba(0,0,0,0.05);
|
|
||||||
min-height: 11.5625rem;
|
|
||||||
min-width: 292px;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c4 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
margin: 0;
|
|
||||||
height: auto;
|
|
||||||
padding-top: 0;
|
|
||||||
min-width: auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
-webkit-transform: translateY(-50%);
|
|
||||||
-ms-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.c9 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
font-stretch: normal;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
-webkit-box-pack: end;
|
|
||||||
-webkit-justify-content: flex-end;
|
|
||||||
-ms-flex-pack: end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c8 {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 1.125rem;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c10 {
|
|
||||||
font-weight: 400;
|
|
||||||
-webkit-flex-grow: 1;
|
|
||||||
-ms-flex-grow: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c11 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 0.8125rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: rgba(73,73,73,0.8);
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
margin-right: 1.125rem;
|
|
||||||
margin-bottom: 1.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
min-width: 100%;
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-top: 2.25rem;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 100%;
|
|
||||||
-ms-flex-basis: 100%;
|
|
||||||
flex-basis: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:48em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 50%;
|
|
||||||
-ms-flex-basis: 50%;
|
|
||||||
flex-basis: 50%;
|
|
||||||
max-width: 50%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:64em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 33.333333333333336%;
|
|
||||||
-ms-flex-basis: 33.333333333333336%;
|
|
||||||
flex-basis: 33.333333333333336%;
|
|
||||||
max-width: 33.333333333333336%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:75em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 25%;
|
|
||||||
-ms-flex-basis: 25%;
|
|
||||||
flex-basis: 25%;
|
|
||||||
max-width: 25%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c5 {
|
|
||||||
-webkit-flex-basis: 50%;
|
|
||||||
-ms-flex-basis: 50%;
|
|
||||||
flex-basis: 50%;
|
|
||||||
max-width: 50%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<section
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.016
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.256
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.25
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
10
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.033
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.768
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.5
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
25
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.066
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
1.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
50
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.131
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
3.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
2
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
100
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.263
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
7.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
4
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
200
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.525
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
15.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
8
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
400
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router, PackagesMock, FiltersMock } from '@mocks/';
|
|
||||||
import { Packages } from '../';
|
|
||||||
|
|
||||||
it('renders <Packages /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Packages packages={PackagesMock} filters={FiltersMock} />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,212 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import rndId from 'rnd-id';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
|
|
||||||
import ListRules from './List';
|
|
||||||
import CreateRule from './rule';
|
|
||||||
|
|
||||||
import { AffinityIcon, H6, Divider, Button, P } from 'joyent-ui-toolkit';
|
|
||||||
import { FadeIn } from 'animate-css-styled-components';
|
|
||||||
|
|
||||||
const RowMargin = styled(Row)`
|
|
||||||
margin-top: ${remcalc(-24)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Flex = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: ${remcalc(8)};
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-right: ${remcalc(6)};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const defaultValues = {
|
|
||||||
instance: 'must',
|
|
||||||
be: 'the same',
|
|
||||||
type: 'instance name',
|
|
||||||
match: 'equalling',
|
|
||||||
value: null,
|
|
||||||
tagValue: null,
|
|
||||||
tagKey: null,
|
|
||||||
tagKeyType: 'equaling',
|
|
||||||
tagValueType: 'equaling'
|
|
||||||
};
|
|
||||||
|
|
||||||
class Affinity extends Component {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
rule: defaultValues,
|
|
||||||
rules: [],
|
|
||||||
open: [],
|
|
||||||
showRuleCreation: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
instanceChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, instance: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
beChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, be: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
typeChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, type: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
matchChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, match: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
valueChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, value: e.target.value, id: rndId() }
|
|
||||||
});
|
|
||||||
|
|
||||||
tagKeyChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, tagKey: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
tagValueChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, tagValue: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
tagKeyTypeChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, tagKeyType: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
tagValueTypeChange = e =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rule: { ...this.state.rule, tagValueType: e.target.value }
|
|
||||||
});
|
|
||||||
|
|
||||||
submit = () =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rules: [...this.state.rules, this.state.rule],
|
|
||||||
rule: defaultValues,
|
|
||||||
showRuleCreation: false
|
|
||||||
});
|
|
||||||
|
|
||||||
toggleForm = () =>
|
|
||||||
this.setState({ showRuleCreation: !this.state.showRuleCreation });
|
|
||||||
|
|
||||||
open = id => this.setState({ open: this.state.open.push(id) });
|
|
||||||
|
|
||||||
deleteRule = id =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rules: this.state.rules.filter(rule => rule.id !== id)
|
|
||||||
});
|
|
||||||
|
|
||||||
updateRule = rule =>
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
rules: this.state.rules.map(r => {
|
|
||||||
if (r.id === rule.id) {
|
|
||||||
r = rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
return r;
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
_renderInfo = () => (
|
|
||||||
<RowMargin>
|
|
||||||
<Col xs={8}>
|
|
||||||
<P>
|
|
||||||
Affinity rules control the location of instances to help reduce
|
|
||||||
traffic across networks and keep the workload balanced. With strict
|
|
||||||
rules, instances are only provisioned when the criteria is met. {' '}
|
|
||||||
<a href="https://apidocs.joyent.com/docker/features/placement ">
|
|
||||||
Read the docs
|
|
||||||
</a>
|
|
||||||
</P>
|
|
||||||
</Col>
|
|
||||||
</RowMargin>
|
|
||||||
);
|
|
||||||
|
|
||||||
render = () => {
|
|
||||||
const { rule, rules, showRuleCreation } = this.state;
|
|
||||||
return [
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Margin bottom={6}>
|
|
||||||
<Flex>
|
|
||||||
<AffinityIcon />
|
|
||||||
<H6>Affinity</H6>
|
|
||||||
</Flex>
|
|
||||||
<Divider height="1px" />
|
|
||||||
</Margin>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
this._renderInfo(),
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
{rules.length > 0 &&
|
|
||||||
rules.map(rule => [
|
|
||||||
<Margin top={2}>
|
|
||||||
<ListRules
|
|
||||||
key={rule.id}
|
|
||||||
rule={rule}
|
|
||||||
deleteRule={this.deleteRule}
|
|
||||||
updateRule={this.updateRule}
|
|
||||||
/>
|
|
||||||
</Margin>
|
|
||||||
])}
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
{showRuleCreation ? (
|
|
||||||
<FadeIn duration="0.8s">
|
|
||||||
<CreateRule
|
|
||||||
instanceChange={this.instanceChange}
|
|
||||||
typeChange={this.typeChange}
|
|
||||||
matchChange={this.matchChange}
|
|
||||||
valueChange={this.valueChange}
|
|
||||||
tagKeyChange={this.tagKeyChange}
|
|
||||||
tagValueChange={this.tagValueChange}
|
|
||||||
tagKeyTypeChange={this.tagKeyTypeChange}
|
|
||||||
tagValueTypeChange={this.tagValueTypeChange}
|
|
||||||
toggleForm={this.toggleForm}
|
|
||||||
submit={this.submit}
|
|
||||||
rule={rule}
|
|
||||||
/>
|
|
||||||
</FadeIn>
|
|
||||||
) : (
|
|
||||||
<Margin top={2}>
|
|
||||||
<Button secondary bold onClick={this.toggleForm}>
|
|
||||||
Create affinity rule
|
|
||||||
</Button>
|
|
||||||
</Margin>
|
|
||||||
)}
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Affinity;
|
|
|
@ -1,140 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Input,
|
|
||||||
Button,
|
|
||||||
H4,
|
|
||||||
H5,
|
|
||||||
CardOutlet,
|
|
||||||
Select,
|
|
||||||
CardHeader,
|
|
||||||
CardHeaderMeta,
|
|
||||||
Card
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const MarginInline = styled(Margin)`
|
|
||||||
display: inline;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default ({
|
|
||||||
instanceChange,
|
|
||||||
beChange,
|
|
||||||
typeChange,
|
|
||||||
valueChange,
|
|
||||||
tagKeyChange,
|
|
||||||
tagValueChange,
|
|
||||||
toggleForm,
|
|
||||||
submit,
|
|
||||||
rule,
|
|
||||||
tagKeyTypeChange,
|
|
||||||
tagValueTypeChange,
|
|
||||||
matchChange
|
|
||||||
}) => [
|
|
||||||
<Margin top={2}>
|
|
||||||
<Card shadow>
|
|
||||||
<CardHeader secondary={false} transparent={false}>
|
|
||||||
<CardHeaderMeta>
|
|
||||||
<Row between="xs" middle="xs">
|
|
||||||
<Col xs={12}>
|
|
||||||
<H4>Create an affinity rule</H4>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</CardHeaderMeta>
|
|
||||||
</CardHeader>
|
|
||||||
<CardOutlet>
|
|
||||||
<div>
|
|
||||||
<H5 inline>The instance</H5>
|
|
||||||
<Select fluid embedded onChange={instanceChange}>
|
|
||||||
<option>must</option>
|
|
||||||
<option>should</option>
|
|
||||||
</Select>
|
|
||||||
<H5 inline>be on</H5>
|
|
||||||
<Select fluid embedded onChange={beChange}>
|
|
||||||
<option>the same</option>
|
|
||||||
<option>a different</option>
|
|
||||||
</Select>
|
|
||||||
<H5 inline>node as the instance(s) identified by the</H5>
|
|
||||||
<div>
|
|
||||||
<Select fluid embedded left onChange={typeChange}>
|
|
||||||
<option>instance name</option>
|
|
||||||
<option>tag</option>
|
|
||||||
</Select>
|
|
||||||
{rule.type === 'instance name'
|
|
||||||
? [
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select fluid embedded onChange={matchChange}>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
onChange={valueChange}
|
|
||||||
required
|
|
||||||
value={rule.value}
|
|
||||||
placeholder="Example instance name: nginx"
|
|
||||||
/>
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select fluid embedded onChange={tagKeyTypeChange}>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
onChange={tagKeyChange}
|
|
||||||
required
|
|
||||||
value={rule.tagKey}
|
|
||||||
placeholder="key"
|
|
||||||
/>,
|
|
||||||
<H5 inline>and value</H5>,
|
|
||||||
<MarginInline right={1}>
|
|
||||||
<Select fluid embedded onChange={tagValueTypeChange}>
|
|
||||||
<option>equalling</option>
|
|
||||||
<option>not equalling</option>
|
|
||||||
<option>containing</option>
|
|
||||||
<option>starting with</option>
|
|
||||||
<option>ending with</option>
|
|
||||||
</Select>
|
|
||||||
</MarginInline>,
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
embedded
|
|
||||||
type="text"
|
|
||||||
onChange={tagValueChange}
|
|
||||||
required
|
|
||||||
value={rule.tagValue}
|
|
||||||
placeholder="value"
|
|
||||||
/>
|
|
||||||
]}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Button secondary onClick={toggleForm}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={submit}
|
|
||||||
disabled={!(rule.value || (rule.tagKey && rule.tagValue))}
|
|
||||||
>
|
|
||||||
Create
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardOutlet>
|
|
||||||
</Card>
|
|
||||||
</Margin>
|
|
||||||
];
|
|
|
@ -1,161 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Package /> without throwing 1`] = `
|
|
||||||
.c4 {
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 600;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-flex-grow: 4;
|
|
||||||
-ms-flex-grow: 4;
|
|
||||||
flex-grow: 4;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem 1.125rem 0 1.125rem;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-webkit-justify-content: center;
|
|
||||||
-ms-flex-pack: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
min-height: 7.875rem;
|
|
||||||
margin-bottom: 0.625rem;
|
|
||||||
border: 0.0625rem solid;
|
|
||||||
box-shadow: 0 0.125rem 0 0 rgba(0,0,0,0.05);
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-right: 0rem;
|
|
||||||
margin-left: 0rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid;
|
|
||||||
box-shadow: 0px 2px 0px rgba(0,0,0,0.05);
|
|
||||||
min-height: 11.5625rem;
|
|
||||||
min-width: 292px;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
color: #808080;
|
|
||||||
-webkit-flex-basis: 0;
|
|
||||||
-ms-flex-basis: 0;
|
|
||||||
flex-basis: 0;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-webkit-justify-content: center;
|
|
||||||
-ms-flex-pack: center;
|
|
||||||
justify-content: center;
|
|
||||||
-webkit-flex-grow: 0;
|
|
||||||
-ms-flex-grow: 0;
|
|
||||||
flex-grow: 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-webkit-justify-content: center;
|
|
||||||
-ms-flex-pack: center;
|
|
||||||
justify-content: center;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0 c1"
|
|
||||||
name="card"
|
|
||||||
>
|
|
||||||
<test-file-mock
|
|
||||||
alt="Cloud"
|
|
||||||
className="c2"
|
|
||||||
width="175"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className="c3 c4"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
There are no packages that meet your criteria
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c6 c3 c4"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c5"
|
|
||||||
>
|
|
||||||
Please adjust the filters to see some packages here
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router } from '@mocks/';
|
|
||||||
import Empty from '../';
|
|
||||||
|
|
||||||
it('renders <Package /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Empty />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,25 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import { Card, H4, H5 } from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import Cloud from '../../assets/cloud.svg';
|
|
||||||
|
|
||||||
const CardStyled = styled(Card)`
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
display: flex;
|
|
||||||
padding: ${remcalc(18)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Empty = () => (
|
|
||||||
<CardStyled transparent>
|
|
||||||
<Cloud width="175" alt="Cloud" />
|
|
||||||
<H4>There are no packages that meet your criteria</H4>
|
|
||||||
<H5>Please adjust the filters to see some packages here</H5>
|
|
||||||
</CardStyled>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default Empty;
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router, FiltersMock, PackagesMock, Store } from '@mocks/';
|
|
||||||
import Filters from '../filters';
|
|
||||||
|
|
||||||
it('renders <Filters /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Store>
|
|
||||||
<Router>
|
|
||||||
<Filters filters={FiltersMock} packages={PackagesMock} />
|
|
||||||
</Router>
|
|
||||||
</Store>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,150 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import isEqual from 'lodash.isequal';
|
|
||||||
import { reduxForm } from 'redux-form';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
import { Col, Row } from 'react-styled-flexboxgrid';
|
|
||||||
import { reset } from 'redux-form';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { default as defaultState } from '@state/state';
|
|
||||||
|
|
||||||
import Inputs from './inputs';
|
|
||||||
import { returnIcon } from '../icons';
|
|
||||||
|
|
||||||
import {
|
|
||||||
FormGroup,
|
|
||||||
Checkbox,
|
|
||||||
Label,
|
|
||||||
H6,
|
|
||||||
Divider,
|
|
||||||
H4,
|
|
||||||
P,
|
|
||||||
PackageIcon
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const Flex = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: ${remcalc(8)};
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-right: ${remcalc(6)};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const FullWidth = styled(Margin)`
|
|
||||||
width: 100%;
|
|
||||||
,`;
|
|
||||||
|
|
||||||
const RowMargin = styled(Row)`
|
|
||||||
margin-top: ${remcalc(-24)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
class Filters extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
const { filters: { cpu, cost, ram, disk } } = this.props;
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
ram,
|
|
||||||
cpu,
|
|
||||||
disk,
|
|
||||||
cost,
|
|
||||||
reset: 0
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleResetClick = () => {
|
|
||||||
const {
|
|
||||||
dispatch,
|
|
||||||
filterReset,
|
|
||||||
filters: { cpu, cost, ram, disk }
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
filterReset();
|
|
||||||
dispatch(reset('type'));
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
ram,
|
|
||||||
cpu,
|
|
||||||
disk,
|
|
||||||
cost,
|
|
||||||
reset: this.state.reset + 1
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
filters,
|
|
||||||
ramChange,
|
|
||||||
cpuChange,
|
|
||||||
diskChange,
|
|
||||||
costChange
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
return [
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Margin bottom={6}>
|
|
||||||
<Flex>
|
|
||||||
<PackageIcon />
|
|
||||||
<H6>Package</H6>
|
|
||||||
</Flex>
|
|
||||||
<Divider height="1px" />
|
|
||||||
</Margin>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<RowMargin>
|
|
||||||
<Col xs={8}>
|
|
||||||
<P>
|
|
||||||
A package defines the specs of your instance. On Triton, packages
|
|
||||||
can only increase in size.{' '}
|
|
||||||
<a href="https://docs.joyent.com/public-cloud/instances/packages/sizing">
|
|
||||||
Read the docs
|
|
||||||
</a>
|
|
||||||
</P>
|
|
||||||
</Col>
|
|
||||||
</RowMargin>,
|
|
||||||
<Row>
|
|
||||||
<Col>
|
|
||||||
<Margin vertical={2}>
|
|
||||||
<H4>Filters</H4>
|
|
||||||
</Margin>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<Row>
|
|
||||||
{filters.groups
|
|
||||||
.sort((a, b) => (a.name < b.name ? -1 : 1))
|
|
||||||
.map((group, i) => (
|
|
||||||
<Col>
|
|
||||||
<FormGroup
|
|
||||||
name={group.name}
|
|
||||||
key={group.name}
|
|
||||||
type="checkbox"
|
|
||||||
reduxForm
|
|
||||||
>
|
|
||||||
<Checkbox>
|
|
||||||
{returnIcon(group.name)}
|
|
||||||
<Label>{group.name}</Label>
|
|
||||||
</Checkbox>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
</Row>,
|
|
||||||
<FullWidth top={2}>
|
|
||||||
<Inputs
|
|
||||||
ramChange={value => ramChange(value)}
|
|
||||||
cpuChange={value => cpuChange(value)}
|
|
||||||
diskChange={value => diskChange(value)}
|
|
||||||
costChange={value => costChange(value)}
|
|
||||||
filters={filters}
|
|
||||||
disabled={isEqual(filters, defaultState.filters)}
|
|
||||||
onResetClick={this.handleResetClick}
|
|
||||||
reset={this.state.reset}
|
|
||||||
/>
|
|
||||||
</FullWidth>
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default reduxForm({ form: 'type' })(Filters);
|
|
|
@ -1 +0,0 @@
|
||||||
export { default as Filters } from './filters';
|
|
|
@ -1,331 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
import {
|
|
||||||
FormGroup,
|
|
||||||
FormLabel,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Button,
|
|
||||||
InputDropdown
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import { Padding, Margin } from 'styled-components-spacing';
|
|
||||||
|
|
||||||
const RowFullWidth = styled(Row)`
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Divider = styled.div`
|
|
||||||
width: ${remcalc(1)};
|
|
||||||
background: ${props => props.theme.grey};
|
|
||||||
height: ${remcalc(66)};
|
|
||||||
margin: 0 ${remcalc(14)};
|
|
||||||
margin-bottom: ${remcalc(9)};
|
|
||||||
display: flex;
|
|
||||||
align-self: flex-end;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const isToBeMultiplied = (name, state, target) =>
|
|
||||||
(name === 'ram' && state[name][`${target}Selected`] === 'MB') ||
|
|
||||||
(name === 'disk' && state[name][`${target}Selected`] === 'GB');
|
|
||||||
|
|
||||||
const valuesToSend = (changed, target, value) => ({
|
|
||||||
min: !isNaN(parseFloat(changed.min)) ? parseFloat(changed.min) : 0,
|
|
||||||
max: !isNaN(parseFloat(changed.max)) ? parseFloat(changed.max) : 0,
|
|
||||||
[target]: parseFloat(value)
|
|
||||||
});
|
|
||||||
|
|
||||||
const ramLogic = ram => ({
|
|
||||||
min: ram.min > 1 ? ram.min : ram.min * 1000,
|
|
||||||
minSelected: 'MB',
|
|
||||||
max: ram.max > 1 ? ram.max : ram.max * 1000,
|
|
||||||
maxSelected: 'GB'
|
|
||||||
});
|
|
||||||
|
|
||||||
const diskLogic = disk => ({
|
|
||||||
min: disk.min > 1 ? disk.min : disk.min * 1000,
|
|
||||||
minSelected: 'GB',
|
|
||||||
max: disk.max > 1 ? disk.max : disk.max * 1000,
|
|
||||||
maxSelected: 'TB'
|
|
||||||
});
|
|
||||||
|
|
||||||
class Inputs extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
const { filters: { cpu, cost, ram, disk }, reset } = this.props;
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
ram: ramLogic(ram),
|
|
||||||
cpu,
|
|
||||||
disk: diskLogic(disk),
|
|
||||||
cost,
|
|
||||||
reset
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps = nextProps => {
|
|
||||||
const { filters: { cpu, cost, ram, disk }, reset } = nextProps;
|
|
||||||
if (reset !== this.state.reset) {
|
|
||||||
this.setState({
|
|
||||||
ram: ramLogic(ram),
|
|
||||||
cpu,
|
|
||||||
disk: diskLogic(disk),
|
|
||||||
cost,
|
|
||||||
reset
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = (e, name, target) => {
|
|
||||||
const changed = this.state[name];
|
|
||||||
const value = (e.target || {}).value;
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.props[`${name}Change`](
|
|
||||||
valuesToSend(
|
|
||||||
{
|
|
||||||
min: isToBeMultiplied(name, this.state, 'min')
|
|
||||||
? changed.min / 1000
|
|
||||||
: changed.min,
|
|
||||||
max: isToBeMultiplied(name, this.state, 'max')
|
|
||||||
? changed.max / 1000
|
|
||||||
: changed.max
|
|
||||||
},
|
|
||||||
target,
|
|
||||||
isToBeMultiplied(name, this.state, target) ? value / 1000 : value
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
[name]: {
|
|
||||||
...this.state[name],
|
|
||||||
[target]: value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleSelectChange = (e, name, target, valueTarget) => {
|
|
||||||
const value = (e.target || {}).value;
|
|
||||||
const isToBeMultiplied =
|
|
||||||
(name === 'ram' && value === 'MB') || (name === 'disk' && value === 'GB');
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
[name]: {
|
|
||||||
...this.state[name],
|
|
||||||
[target]: value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.props[`${name}Change`](
|
|
||||||
valuesToSend(
|
|
||||||
this.state[name],
|
|
||||||
valueTarget,
|
|
||||||
isToBeMultiplied
|
|
||||||
? this.state[name][valueTarget] / 1000
|
|
||||||
: this.state[name][valueTarget]
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
handleBlur = (e, name, target) => {
|
|
||||||
const changed = this.state[name];
|
|
||||||
const value = (e.target || {}).value;
|
|
||||||
|
|
||||||
this.props[`${name}Change`](
|
|
||||||
valuesToSend(
|
|
||||||
{
|
|
||||||
min: isToBeMultiplied(name, this.state, 'min')
|
|
||||||
? changed.min / 1000
|
|
||||||
: changed.min,
|
|
||||||
max: isToBeMultiplied(name, this.state, 'max')
|
|
||||||
? changed.max / 1000
|
|
||||||
: changed.max
|
|
||||||
},
|
|
||||||
target,
|
|
||||||
isToBeMultiplied(name, this.state, target) ? value / 1000 : value
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
...this.state,
|
|
||||||
[name]: {
|
|
||||||
...this.state[name],
|
|
||||||
[target]: value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { cpu, cost, ram, disk } = this.state;
|
|
||||||
const { onResetClick, disabled } = this.props;
|
|
||||||
|
|
||||||
return [
|
|
||||||
<Row bottom="xs">
|
|
||||||
<Col>
|
|
||||||
<Padding top={1}>
|
|
||||||
<FormLabel>RAM</FormLabel>
|
|
||||||
</Padding>
|
|
||||||
<FormGroup flex center>
|
|
||||||
<InputDropdown>
|
|
||||||
<Input
|
|
||||||
wrapped
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'ram', 'min')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'ram', 'min')}
|
|
||||||
value={ram.min}
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
onChange={e =>
|
|
||||||
this.handleSelectChange(e, 'ram', 'minSelected', 'min')}
|
|
||||||
value={ram.minSelected}
|
|
||||||
wrapped
|
|
||||||
fluid
|
|
||||||
>
|
|
||||||
<option value="MB">MB</option>
|
|
||||||
<option value="GB">GB</option>
|
|
||||||
</Select>
|
|
||||||
</InputDropdown>
|
|
||||||
<Padding horizontal={2}>to</Padding>
|
|
||||||
<InputDropdown>
|
|
||||||
<Input
|
|
||||||
wrapped
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'ram', 'max')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'ram', 'max')}
|
|
||||||
value={ram.max}
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
onChange={e =>
|
|
||||||
this.handleSelectChange(e, 'ram', 'maxSelected', 'max')}
|
|
||||||
value={ram.maxSelected}
|
|
||||||
wrapped
|
|
||||||
fluid
|
|
||||||
>
|
|
||||||
<option value="MB">MB</option>
|
|
||||||
<option value="GB">GB</option>
|
|
||||||
</Select>
|
|
||||||
</InputDropdown>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
<Divider />
|
|
||||||
<Col>
|
|
||||||
<Padding top={1}>
|
|
||||||
<FormLabel>Disk</FormLabel>
|
|
||||||
</Padding>
|
|
||||||
<FormGroup flex center>
|
|
||||||
<InputDropdown>
|
|
||||||
<Input
|
|
||||||
wrapped
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'disk', 'min')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'disk', 'min')}
|
|
||||||
value={disk.min}
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
onChange={e =>
|
|
||||||
this.handleSelectChange(e, 'disk', 'minSelected', 'min')}
|
|
||||||
value={disk.minSelected}
|
|
||||||
wrapped
|
|
||||||
fluid
|
|
||||||
>
|
|
||||||
<option value="GB">GB</option>
|
|
||||||
<option value="TB">TB</option>
|
|
||||||
</Select>
|
|
||||||
</InputDropdown>
|
|
||||||
<Padding horizontal={2}>to</Padding>
|
|
||||||
<InputDropdown>
|
|
||||||
<Input
|
|
||||||
wrapped
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'disk', 'max')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'disk', 'max')}
|
|
||||||
value={disk.max}
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
onChange={e =>
|
|
||||||
this.handleSelectChange(e, 'disk', 'maxSelected', 'min')}
|
|
||||||
value={disk.maxSelected}
|
|
||||||
wrapped
|
|
||||||
fluid
|
|
||||||
>
|
|
||||||
<option value="GB">GB</option>
|
|
||||||
<option value="TB">TB</option>
|
|
||||||
</Select>
|
|
||||||
</InputDropdown>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<RowFullWidth>
|
|
||||||
<Col>
|
|
||||||
<Padding top={1}>
|
|
||||||
<FormLabel>vCPUs</FormLabel>
|
|
||||||
</Padding>
|
|
||||||
<FormGroup flex center>
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'cpu', 'min')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'cpu', 'min')}
|
|
||||||
value={cpu.min}
|
|
||||||
/>
|
|
||||||
<Padding horizontal={2}>to</Padding>
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'cpu', 'max')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'cpu', 'max')}
|
|
||||||
value={cpu.max}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
<Divider />
|
|
||||||
<Col>
|
|
||||||
<Padding top={1}>
|
|
||||||
<FormLabel>$/hour</FormLabel>
|
|
||||||
</Padding>
|
|
||||||
<FormGroup flex center>
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'cost', 'min')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'cost', 'min')}
|
|
||||||
value={cost.min}
|
|
||||||
/>
|
|
||||||
<Padding horizontal={2}>to</Padding>
|
|
||||||
<Input
|
|
||||||
small
|
|
||||||
type="text"
|
|
||||||
onChange={e => this.handleChange(e, 'cost', 'max')}
|
|
||||||
onBlur={e => this.handleBlur(e, 'cost', 'max')}
|
|
||||||
value={cost.max}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
</Col>
|
|
||||||
</RowFullWidth>,
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Margin vertical={2}>
|
|
||||||
<Button
|
|
||||||
disabled={disabled}
|
|
||||||
secondary
|
|
||||||
small
|
|
||||||
bold
|
|
||||||
onClick={onResetClick}
|
|
||||||
>
|
|
||||||
Reset All Filters
|
|
||||||
</Button>
|
|
||||||
</Margin>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Inputs;
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Home /> without throwing 1`] = `
|
|
||||||
<MemoryRouter>
|
|
||||||
<Home
|
|
||||||
filters={
|
|
||||||
Object {
|
|
||||||
"cost": Object {
|
|
||||||
"max": 0.525,
|
|
||||||
"min": 0.016,
|
|
||||||
},
|
|
||||||
"cpu": Object {
|
|
||||||
"max": 3.25,
|
|
||||||
"min": 0.25,
|
|
||||||
},
|
|
||||||
"disk": Object {
|
|
||||||
"max": 107.26,
|
|
||||||
"min": 0.01,
|
|
||||||
},
|
|
||||||
"groups": Array [
|
|
||||||
Object {
|
|
||||||
"name": "Compute Optimized",
|
|
||||||
"selected": false,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"name": "Memory Optimized",
|
|
||||||
"selected": false,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"name": "General Purpose",
|
|
||||||
"selected": false,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"name": "Storage Optimized",
|
|
||||||
"selected": false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"ram": Object {
|
|
||||||
"max": 50.688,
|
|
||||||
"min": 0.256,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</MemoryRouter>
|
|
||||||
`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import ShallowRenderer from 'react-test-renderer/shallow';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router, FiltersMock } from '@mocks/';
|
|
||||||
import Home from '../home';
|
|
||||||
|
|
||||||
it('renders <Home /> without throwing', () => {
|
|
||||||
const renderer = new ShallowRenderer();
|
|
||||||
renderer.render(
|
|
||||||
<Router>
|
|
||||||
<Home filters={FiltersMock} />
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
const tree = renderer.getRenderOutput();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,118 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import { Filters } from '@components/filters';
|
|
||||||
import PackagesHOC from '@containers/packages';
|
|
||||||
import AffinityHOC from '@containers/affinity';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
import {
|
|
||||||
Message,
|
|
||||||
BreadcrumbItem,
|
|
||||||
Anchor,
|
|
||||||
Button,
|
|
||||||
MessageTitle,
|
|
||||||
MessageDescription
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
class Home extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
showMessage: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
closeMessage = () => {
|
|
||||||
this.setState({
|
|
||||||
showMessage: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
changeValue = (key, value) => {
|
|
||||||
const { filters, onFilterChange } = this.props;
|
|
||||||
|
|
||||||
onFilterChange({
|
|
||||||
...filters,
|
|
||||||
[key]: value
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillReceiveProps = nextProps => {
|
|
||||||
const values = nextProps.form.type.values;
|
|
||||||
const type = nextProps.form.type;
|
|
||||||
if (nextProps.form !== this.props.form && type && values) {
|
|
||||||
const { filters, onFilterChange } = this.props;
|
|
||||||
|
|
||||||
const groups = Object.keys(type.registeredFields).map(key => ({
|
|
||||||
name: key,
|
|
||||||
selected: values[key] ? values[key] : false
|
|
||||||
}));
|
|
||||||
|
|
||||||
onFilterChange({
|
|
||||||
...filters,
|
|
||||||
groups
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { showMessage } = this.state;
|
|
||||||
const { filters, onFilterReset, packages } = this.props;
|
|
||||||
const _msg = showMessage ? (
|
|
||||||
<Message onCloseClick={this.closeMessage}>
|
|
||||||
<MessageTitle>Choosing deployment data center</MessageTitle>
|
|
||||||
<MessageDescription>
|
|
||||||
Not all data centres have all configurations of instances available.
|
|
||||||
Make sure that you choose the data center that suits your
|
|
||||||
requirements. <Anchor href="#">Learn More</Anchor>
|
|
||||||
</MessageDescription>
|
|
||||||
</Message>
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
const breadcrumbLinks = [
|
|
||||||
{ name: 'Instances', pathname: '/' },
|
|
||||||
{ name: 'Create Instance', pathname: '/' }
|
|
||||||
].map(({ name, pathname }) => (
|
|
||||||
<BreadcrumbItem key={name} to={pathname}>
|
|
||||||
{name}
|
|
||||||
</BreadcrumbItem>
|
|
||||||
));
|
|
||||||
|
|
||||||
return [
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>{breadcrumbLinks}</Col>
|
|
||||||
</Row>,
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}><Margin bottom={7}>{_msg}</Margin></Col>
|
|
||||||
</Row>,
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Filters
|
|
||||||
packages={packages}
|
|
||||||
filters={filters}
|
|
||||||
filterReset={onFilterReset}
|
|
||||||
ramChange={value => this.changeValue('ram', value)}
|
|
||||||
cpuChange={value => this.changeValue('cpu', value)}
|
|
||||||
diskChange={value => this.changeValue('disk', value)}
|
|
||||||
costChange={value => this.changeValue('cost', value)}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<Margin top={2}>
|
|
||||||
<PackagesHOC />
|
|
||||||
</Margin>,
|
|
||||||
<Row end="xs">
|
|
||||||
<Col xs={12}>
|
|
||||||
<Margin top={5}>
|
|
||||||
<Button>Next</Button>
|
|
||||||
</Margin>
|
|
||||||
</Col>
|
|
||||||
</Row>,
|
|
||||||
<Margin top={5}>
|
|
||||||
<AffinityHOC />
|
|
||||||
</Margin>
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Home;
|
|
|
@ -1 +0,0 @@
|
||||||
export { default as Home } from './home';
|
|
|
@ -1,51 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
import CpuIcon from '../../assets/cpu.svg';
|
|
||||||
import GpIcon from '../../assets/gp.svg';
|
|
||||||
import MoIcon from '../../assets/mo.svg';
|
|
||||||
import SoIcon from '../../assets/so.svg';
|
|
||||||
import { TooltipContainer, TooltipTarget, Tooltip } from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
|
|
||||||
const IconWrapper = styled.div`
|
|
||||||
float: left;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Flex = styled.div`
|
|
||||||
display: flex;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const returnIcon = group => {
|
|
||||||
let icon;
|
|
||||||
switch (group) {
|
|
||||||
case 'Compute Optimized':
|
|
||||||
icon = <CpuIcon width="24" height="24" />;
|
|
||||||
break;
|
|
||||||
case 'General Purpose':
|
|
||||||
icon = <GpIcon width="24" height="24" />;
|
|
||||||
break;
|
|
||||||
case 'Memory Optimized':
|
|
||||||
icon = <MoIcon width="24" height="24" />;
|
|
||||||
break;
|
|
||||||
case 'Storage Optimized':
|
|
||||||
icon = <SoIcon width="24" height="24" />;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
icon = <GpIcon width="24" height="24" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IconWrapper>
|
|
||||||
<TooltipContainer hoverable>
|
|
||||||
<TooltipTarget>
|
|
||||||
<Margin horizontal={2}>
|
|
||||||
<Flex>{icon}</Flex>
|
|
||||||
</Margin>
|
|
||||||
</TooltipTarget>
|
|
||||||
<Tooltip placement="bottom">{group}</Tooltip>
|
|
||||||
</TooltipContainer>
|
|
||||||
</IconWrapper>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,76 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Header /> without throwing 1`] = `
|
|
||||||
.c2 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.875rem;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 1.8125rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 + p,
|
|
||||||
.c2 + small,
|
|
||||||
.c2 + h1,
|
|
||||||
.c2 + h2,
|
|
||||||
.c2 + label,
|
|
||||||
.c2 + h3,
|
|
||||||
.c2 + h4,
|
|
||||||
.c2 + h5,
|
|
||||||
.c2 + div,
|
|
||||||
.c2 + span {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex: 1 1 auto;
|
|
||||||
-ms-flex: 1 1 auto;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
-webkit-align-self: stretch;
|
|
||||||
-ms-flex-item-align: stretch;
|
|
||||||
align-self: stretch;
|
|
||||||
-webkit-order: 0;
|
|
||||||
-ms-flex-order: 0;
|
|
||||||
order: 0;
|
|
||||||
padding: 0.84375rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
max-height: 3.3125rem;
|
|
||||||
min-height: 3.3125rem;
|
|
||||||
padding: 0 1.125rem;
|
|
||||||
line-height: 1.5625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
border-style: none;
|
|
||||||
width: 5.4375rem;
|
|
||||||
height: 1.5625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<h2
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/"
|
|
||||||
name="Go to home"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="Triton Logo"
|
|
||||||
className="c3"
|
|
||||||
src="test-file-mock"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,174 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <NotFound /> without throwing 1`] = `
|
|
||||||
.c5 {
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.5rem;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 + p,
|
|
||||||
.c5 + small,
|
|
||||||
.c5 + h1,
|
|
||||||
.c5 + h2,
|
|
||||||
.c5 + label,
|
|
||||||
.c5 + h3,
|
|
||||||
.c5 + h4,
|
|
||||||
.c5 + h5,
|
|
||||||
.c5 + div,
|
|
||||||
.c5 + span {
|
|
||||||
padding-bottom: 2.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-webkit-justify-content: center;
|
|
||||||
-ms-flex-pack: center;
|
|
||||||
justify-content: center;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.9375rem 1.125rem;
|
|
||||||
position: relative;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
text-align: center;
|
|
||||||
font-style: normal;
|
|
||||||
font-stretch: normal;
|
|
||||||
line-height: normal;
|
|
||||||
-webkit-letter-spacing: normal;
|
|
||||||
-moz-letter-spacing: normal;
|
|
||||||
-ms-letter-spacing: normal;
|
|
||||||
letter-spacing: normal;
|
|
||||||
text-decoration: none;
|
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: middle;
|
|
||||||
touch-action: manipulation;
|
|
||||||
cursor: pointer;
|
|
||||||
background-image: none;
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
border: solid 0.0625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6:focus {
|
|
||||||
outline: 0;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6:hover {
|
|
||||||
border: solid 0.0625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6:active,
|
|
||||||
.c6:active:hover,
|
|
||||||
.c6:active:focus {
|
|
||||||
background-image: none;
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6[disabled] {
|
|
||||||
cursor: not-allowed;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
margin-right: auto;
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
font-size: 2rem;
|
|
||||||
margin: 0.625rem 0;
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 2.25rem;
|
|
||||||
line-height: 2.8125rem;
|
|
||||||
font-style: normal;
|
|
||||||
font-stretch: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 + p,
|
|
||||||
.c3 + small,
|
|
||||||
.c3 + h1,
|
|
||||||
.c3 + h2,
|
|
||||||
.c3 + label,
|
|
||||||
.c3 + h3,
|
|
||||||
.c3 + h4,
|
|
||||||
.c3 + h5,
|
|
||||||
.c3 + div,
|
|
||||||
.c3 + span {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
margin-top: 3.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c4 {
|
|
||||||
margin-bottom: 1.875rem;
|
|
||||||
max-width: 30.625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:48em) {
|
|
||||||
.c0 {
|
|
||||||
width: 46rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:64em) {
|
|
||||||
.c0 {
|
|
||||||
width: 61rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:75em) {
|
|
||||||
.c0 {
|
|
||||||
width: 76rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width:48rem) {
|
|
||||||
.c0 {
|
|
||||||
padding-left: 0.375rem;
|
|
||||||
padding-right: 0.375rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<h1
|
|
||||||
className="c2 c3"
|
|
||||||
>
|
|
||||||
I have no memory of this place
|
|
||||||
</h1>
|
|
||||||
<p
|
|
||||||
className="c4 c5"
|
|
||||||
>
|
|
||||||
HTTP 404: We can’t find what you are looking for. Next time, always follow your nose.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
className="c6"
|
|
||||||
href="/"
|
|
||||||
onClick={[Function]}
|
|
||||||
primary={true}
|
|
||||||
>
|
|
||||||
Back home
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,83 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <SectionNav /> without throwing 1`] = `
|
|
||||||
.c0 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
font-weight: 400;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
margin-right: 1.4375rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
font-weight: 400;
|
|
||||||
text-decoration: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3.active {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 1.125rem 0 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<ul
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
aria-current="true"
|
|
||||||
className="active c3 active"
|
|
||||||
href="/"
|
|
||||||
onClick={[Function]}
|
|
||||||
style={Object {}}
|
|
||||||
>
|
|
||||||
Instances
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
Custom images
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
Docker images
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
Docker registries
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router } from '@mocks/';
|
|
||||||
import { Header } from '../';
|
|
||||||
|
|
||||||
it('renders <Header /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Header />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
import { Router } from '@mocks/';
|
|
||||||
|
|
||||||
import { NotFound } from '../';
|
|
||||||
|
|
||||||
it('renders <NotFound /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<NotFound />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Header,
|
|
||||||
HeaderBrand,
|
|
||||||
TritonIcon,
|
|
||||||
HeaderNav,
|
|
||||||
HeaderItem,
|
|
||||||
DataCenterIcon,
|
|
||||||
UserIcon
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const HeaderBrandStyled = styled(HeaderBrand)`
|
|
||||||
margin-top: ${remcalc(6)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const NavHeader = () => (
|
|
||||||
<Header>
|
|
||||||
<HeaderBrandStyled>
|
|
||||||
<TritonIcon />
|
|
||||||
</HeaderBrandStyled>
|
|
||||||
<HeaderNav>
|
|
||||||
<li>
|
|
||||||
<Link className="active" to="/">
|
|
||||||
Compute
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
</HeaderNav>
|
|
||||||
<HeaderItem>Return to existing portal</HeaderItem>
|
|
||||||
<HeaderItem>
|
|
||||||
<DataCenterIcon light />eu-east-1
|
|
||||||
</HeaderItem>
|
|
||||||
<HeaderItem>
|
|
||||||
<UserIcon light />Nicola
|
|
||||||
</HeaderItem>
|
|
||||||
</Header>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default NavHeader;
|
|
|
@ -1,2 +0,0 @@
|
||||||
export { default as Header } from './header';
|
|
||||||
export { default as NotFound } from './not-found';
|
|
|
@ -1,31 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { H1, P, Button, ViewContainer } from 'joyent-ui-toolkit';
|
|
||||||
import { Margin } from 'styled-components-spacing';
|
|
||||||
|
|
||||||
const NotFound = ({
|
|
||||||
title = 'I have no memory of this place',
|
|
||||||
message = `HTTP 404: We can’t find what you are looking for.
|
|
||||||
Next time, always follow your nose.`,
|
|
||||||
link = 'Back home',
|
|
||||||
to = '/'
|
|
||||||
}) => (
|
|
||||||
<ViewContainer>
|
|
||||||
<Margin top={10}>
|
|
||||||
<H1>{title}</H1>
|
|
||||||
<P>{message}</P>
|
|
||||||
<Margin top={5}>
|
|
||||||
<Button to={to}>{link}</Button>
|
|
||||||
</Margin>
|
|
||||||
</Margin>
|
|
||||||
</ViewContainer>
|
|
||||||
);
|
|
||||||
|
|
||||||
NotFound.propTypes = {
|
|
||||||
title: PropTypes.string,
|
|
||||||
message: PropTypes.string,
|
|
||||||
link: PropTypes.string,
|
|
||||||
to: PropTypes.string
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NotFound;
|
|
|
@ -1,276 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Package /> without throwing 1`] = `
|
|
||||||
.c3 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 {
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 600;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-flex-grow: 4;
|
|
||||||
-ms-flex-grow: 4;
|
|
||||||
flex-grow: 4;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem 1.125rem 0 1.125rem;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
min-height: 7.875rem;
|
|
||||||
margin-bottom: 0.625rem;
|
|
||||||
border: 0.0625rem solid;
|
|
||||||
box-shadow: 0 0.125rem 0 0 rgba(0,0,0,0.05);
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-right: 0rem;
|
|
||||||
margin-left: 0rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid;
|
|
||||||
box-shadow: 0px 2px 0px rgba(0,0,0,0.05);
|
|
||||||
min-height: 11.5625rem;
|
|
||||||
min-width: 292px;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
margin: 0;
|
|
||||||
height: auto;
|
|
||||||
padding-top: 0;
|
|
||||||
min-width: auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c4 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
-webkit-transform: translateY(-50%);
|
|
||||||
-ms-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.c7 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
font-stretch: normal;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
-webkit-box-pack: end;
|
|
||||||
-webkit-justify-content: flex-end;
|
|
||||||
-ms-flex-pack: end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 1.125rem;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c8 {
|
|
||||||
font-weight: 400;
|
|
||||||
-webkit-flex-grow: 1;
|
|
||||||
-ms-flex-grow: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c9 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 0.8125rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: rgba(73,73,73,0.8);
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
margin-right: 1.125rem;
|
|
||||||
margin-bottom: 1.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c3 {
|
|
||||||
-webkit-flex-basis: 50%;
|
|
||||||
-ms-flex-basis: 50%;
|
|
||||||
flex-basis: 50%;
|
|
||||||
max-width: 50%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0 c1"
|
|
||||||
name="card"
|
|
||||||
onClick={undefined}
|
|
||||||
selected={undefined}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c3"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.263
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c6 c5"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
7.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c6 c5"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
4
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c6 c5"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
200
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c6 c5"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c7"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c5"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
selected={undefined}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,30 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router } from '@mocks/';
|
|
||||||
import Package from '../';
|
|
||||||
|
|
||||||
const pack = {
|
|
||||||
disk: 200,
|
|
||||||
group: 'Compute Optimized',
|
|
||||||
memory: 7.8,
|
|
||||||
name: 'High CPU 7.75',
|
|
||||||
price: '0.263',
|
|
||||||
vcpus: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
it('renders <Package /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Package pack={pack} />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,38 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { reduxForm } from 'redux-form';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import { returnIcon } from '../icons';
|
|
||||||
|
|
||||||
import { TableTr, TableTd, H4, Radio, FormGroup } from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const FormGroupStyled = styled(FormGroup)`
|
|
||||||
float: left;
|
|
||||||
margin-right: ${remcalc(24)};
|
|
||||||
margin-top: ${remcalc(3)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Package = ({
|
|
||||||
pack: { price, memory, vcpus, disk, group, ssd, name },
|
|
||||||
selected,
|
|
||||||
onClick
|
|
||||||
}) => (
|
|
||||||
<TableTr selected={selected}>
|
|
||||||
<TableTd>
|
|
||||||
<FormGroupStyled name={name}>
|
|
||||||
<Radio onClick={onClick} name={name} value={name} checked={selected} />
|
|
||||||
</FormGroupStyled>
|
|
||||||
{returnIcon(group)}
|
|
||||||
<H4>{name}</H4>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd right>
|
|
||||||
{memory > 1 ? `${parseInt(memory, 10)} GB` : `${memory * 1000} MB`}
|
|
||||||
</TableTd>
|
|
||||||
<TableTd right>{disk > 1 ? `${disk} TB` : `${disk * 1000} GB`}</TableTd>
|
|
||||||
<TableTd right>{vcpus}</TableTd>
|
|
||||||
<TableTd right>{price.toFixed(3)}</TableTd>
|
|
||||||
</TableTr>
|
|
||||||
);
|
|
||||||
|
|
||||||
export default reduxForm({ form: 'selected' })(Package);
|
|
|
@ -1,784 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Packages /> without throwing 1`] = `
|
|
||||||
.c1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c5 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
-webkit-flex: 0 0 auto;
|
|
||||||
-ms-flex: 0 0 auto;
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding-right: 0.5rem;
|
|
||||||
padding-left: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c7 {
|
|
||||||
font-size: 0.9375rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 600;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-align-items: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-flex-grow: 4;
|
|
||||||
-ms-flex-grow: 4;
|
|
||||||
flex-grow: 4;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0.75rem 1.125rem 0 1.125rem;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
position: relative;
|
|
||||||
height: auto;
|
|
||||||
min-height: 7.875rem;
|
|
||||||
margin-bottom: 0.625rem;
|
|
||||||
border: 0.0625rem solid;
|
|
||||||
box-shadow: 0 0.125rem 0 0 rgba(0,0,0,0.05);
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
margin-right: 0rem;
|
|
||||||
margin-left: 0rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid;
|
|
||||||
box-shadow: 0px 2px 0px rgba(0,0,0,0.05);
|
|
||||||
min-height: 11.5625rem;
|
|
||||||
min-width: 292px;
|
|
||||||
cursor: pointer;
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c4 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
margin: 0;
|
|
||||||
height: auto;
|
|
||||||
padding-top: 0;
|
|
||||||
min-width: auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c6 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex: 0 1 auto;
|
|
||||||
-ms-flex: 0 1 auto;
|
|
||||||
flex: 0 1 auto;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
display: block;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
-webkit-transform: translateY(-50%);
|
|
||||||
-ms-transform: translateY(-50%);
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.c9 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-style: normal;
|
|
||||||
font-stretch: normal;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
-webkit-box-pack: end;
|
|
||||||
-webkit-justify-content: flex-end;
|
|
||||||
-ms-flex-pack: end;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c8 {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 0 1.125rem;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c10 {
|
|
||||||
font-weight: 400;
|
|
||||||
-webkit-flex-grow: 1;
|
|
||||||
-ms-flex-grow: 1;
|
|
||||||
flex-grow: 1;
|
|
||||||
-webkit-flex-basis: 5.625rem;
|
|
||||||
-ms-flex-basis: 5.625rem;
|
|
||||||
flex-basis: 5.625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c11 {
|
|
||||||
display: inline-block;
|
|
||||||
-webkit-flex-direction: column;
|
|
||||||
-ms-flex-direction: column;
|
|
||||||
flex-direction: column;
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 0.8125rem;
|
|
||||||
font-weight: 500;
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: rgba(73,73,73,0.8);
|
|
||||||
-webkit-transition: all 300ms ease;
|
|
||||||
transition: all 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 {
|
|
||||||
margin-right: 1.125rem;
|
|
||||||
margin-bottom: 1.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
min-width: 100%;
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
-webkit-flex-wrap: wrap;
|
|
||||||
-ms-flex-wrap: wrap;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
margin-top: 2.25rem;
|
|
||||||
margin-right: -0.5rem;
|
|
||||||
margin-left: -0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 100%;
|
|
||||||
-ms-flex-basis: 100%;
|
|
||||||
flex-basis: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:48em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 50%;
|
|
||||||
-ms-flex-basis: 50%;
|
|
||||||
flex-basis: 50%;
|
|
||||||
max-width: 50%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:64em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 33.333333333333336%;
|
|
||||||
-ms-flex-basis: 33.333333333333336%;
|
|
||||||
flex-basis: 33.333333333333336%;
|
|
||||||
max-width: 33.333333333333336%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:75em) {
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex-basis: 25%;
|
|
||||||
-ms-flex-basis: 25%;
|
|
||||||
flex-basis: 25%;
|
|
||||||
max-width: 25%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width:0em) {
|
|
||||||
.c5 {
|
|
||||||
-webkit-flex-basis: 50%;
|
|
||||||
-ms-flex-basis: 50%;
|
|
||||||
flex-basis: 50%;
|
|
||||||
max-width: 50%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<section
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.016
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.256
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.25
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
10
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.033
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.768
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
0.5
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
25
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.066
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
1.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
1
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
50
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.131
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
3.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
2
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
100
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.263
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
7.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
4
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
200
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c2 c3"
|
|
||||||
name="card"
|
|
||||||
onClick={[Function]}
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c4"
|
|
||||||
name="card-view"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c5"
|
|
||||||
name="card-meta"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c6"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c7"
|
|
||||||
name="card-title"
|
|
||||||
>
|
|
||||||
$
|
|
||||||
0.525
|
|
||||||
per hour
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
15.8
|
|
||||||
GB RAM
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
8
|
|
||||||
vCPUs
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
400
|
|
||||||
TB disk
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c8 c7"
|
|
||||||
name="card-subtitle"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c9"
|
|
||||||
>
|
|
||||||
Magnetic
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="c10 c7"
|
|
||||||
name="card-footer"
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className="c11"
|
|
||||||
selected={false}
|
|
||||||
>
|
|
||||||
Compute Optimized
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router, PackagesMock, FiltersMock } from '@mocks/';
|
|
||||||
import { Packages } from '../';
|
|
||||||
|
|
||||||
it('renders <Packages /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Packages packages={PackagesMock} filters={FiltersMock} />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
export { default as Packages } from './list';
|
|
|
@ -1,248 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Row, Col } from 'react-styled-flexboxgrid';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import remcalc from 'remcalc';
|
|
||||||
|
|
||||||
import Package from '@components/package';
|
|
||||||
import Empty from '@components/empty';
|
|
||||||
import sortBy from 'lodash.sortby';
|
|
||||||
import isEqual from 'lodash.isequal';
|
|
||||||
import is from 'styled-is';
|
|
||||||
import {
|
|
||||||
Table,
|
|
||||||
TableThead,
|
|
||||||
TableTbody,
|
|
||||||
TableThFooter,
|
|
||||||
TableTr,
|
|
||||||
TableTh,
|
|
||||||
ArrowIcon
|
|
||||||
} from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
const ArrowIconStyled = styled(ArrowIcon)`
|
|
||||||
margin-left: ${remcalc(4)};
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
top: ${remcalc(-3)};
|
|
||||||
transition: transform 200ms ease;
|
|
||||||
|
|
||||||
path {
|
|
||||||
fill: ${props => props.theme.text};
|
|
||||||
}
|
|
||||||
|
|
||||||
${is('selected', 'down')`
|
|
||||||
transform: rotate(180deg);
|
|
||||||
`};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Span = styled.span`
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
`;
|
|
||||||
|
|
||||||
class Packages extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
packages: props.packages.sort((a, b) => (a.price > b.price ? 1 : -1)),
|
|
||||||
selected: null,
|
|
||||||
price: true,
|
|
||||||
ordered: 'price'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClick = id => {
|
|
||||||
this.setState({
|
|
||||||
selected: id !== this.state.selected ? id : null
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
componentWillReceiveProps = nextProps => {
|
|
||||||
this.setState({
|
|
||||||
packages: nextProps.packages
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
order = column => {
|
|
||||||
const { packages } = this.state;
|
|
||||||
const desc = sortBy(packages, [column]).reverse();
|
|
||||||
const asc = sortBy(packages, [column]);
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
packages: isEqual(packages, asc) ? desc : asc,
|
|
||||||
ordered: column,
|
|
||||||
[column]: !isEqual(packages, asc)
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
_cards = () => {
|
|
||||||
const { selected, packages, ordered } = this.state;
|
|
||||||
|
|
||||||
return packages.length > 0 ? (
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Table>
|
|
||||||
<TableThead>
|
|
||||||
<TableTr>
|
|
||||||
<TableTh selected={ordered === 'name'}>
|
|
||||||
<div>
|
|
||||||
<Span role="button" onClick={() => this.order('name')}>
|
|
||||||
Name{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'name' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.name}
|
|
||||||
onClick={() => this.order('name')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'memory'}>
|
|
||||||
<div>
|
|
||||||
<Span role="button" onClick={() => this.order('memory')}>
|
|
||||||
RAM{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'memory' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.memory}
|
|
||||||
onClick={() => this.order('memory')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'disk'}>
|
|
||||||
<div>
|
|
||||||
<Span role="button" onClick={() => this.order('disk')}>
|
|
||||||
Disk{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'disk' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.disk}
|
|
||||||
onClick={() => this.order('disk')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'vcpus'}>
|
|
||||||
<div>
|
|
||||||
<Span role="button" onClick={() => this.order('vcpus')}>
|
|
||||||
vCPU{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'vcpus' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.vcpus}
|
|
||||||
onClick={() => this.order('vcpus')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'price'}>
|
|
||||||
<div>
|
|
||||||
<Span role="button" onClick={() => this.order('price')}>
|
|
||||||
$/hour{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'price' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected={ordered === 'price'}
|
|
||||||
down={this.state.price}
|
|
||||||
onClick={() => this.order('price')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThead>
|
|
||||||
<TableTbody>
|
|
||||||
{packages.map(pack => (
|
|
||||||
<Package
|
|
||||||
pack={pack}
|
|
||||||
onClick={() => this.handleClick(pack.id)}
|
|
||||||
selected={selected === pack.id}
|
|
||||||
key={pack.id}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</TableTbody>
|
|
||||||
<TableThFooter>
|
|
||||||
<TableTr>
|
|
||||||
<TableTh selected={ordered === 'name'}>
|
|
||||||
<Span role="button" onClick={() => this.order('name')}>
|
|
||||||
Name{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'name' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.name}
|
|
||||||
onClick={() => this.order('name')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'memory'}>
|
|
||||||
<Span role="button" onClick={() => this.order('memory')}>
|
|
||||||
RAM{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'memory' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.memory}
|
|
||||||
onClick={() => this.order('memory')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'disk'}>
|
|
||||||
<Span role="button" onClick={() => this.order('disk')}>
|
|
||||||
Disk{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'disk' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.disk}
|
|
||||||
onClick={() => this.order('disk')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'vcpus'}>
|
|
||||||
<Span role="button" onClick={() => this.order('vcpus')}>
|
|
||||||
vCPU{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'vcpus' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected
|
|
||||||
down={this.state.vcpus}
|
|
||||||
onClick={() => this.order('vcpus')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableTh>
|
|
||||||
<TableTh right xs="100" selected={ordered === 'price'}>
|
|
||||||
<Span role="button" onClick={() => this.order('price')}>
|
|
||||||
$/hour{' '}
|
|
||||||
</Span>
|
|
||||||
{ordered === 'price' && (
|
|
||||||
<ArrowIconStyled
|
|
||||||
selected={ordered === 'price'}
|
|
||||||
down={this.state.price}
|
|
||||||
onClick={() => this.order('price')}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThFooter>
|
|
||||||
</Table>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
) : (
|
|
||||||
<Row>
|
|
||||||
<Col xs={12}>
|
|
||||||
<Empty />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
render = () => this._cards();
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Packages;
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import PackagesHOC from '../';
|
|
||||||
import { Router, Store } from '@mocks/';
|
|
||||||
|
|
||||||
it('renders <PackagesHOC /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Store>
|
|
||||||
<PackagesHOC />
|
|
||||||
</Store>
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import Affinity from '@components/affinity';
|
|
||||||
|
|
||||||
const AffinityHOC = ({ affinity }) => <Affinity affinity={affinity} />;
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
affinity: state.form.affinityForm
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(AffinityHOC);
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import HomeHOC from '../';
|
|
||||||
import { Router, Store } from '@mocks/';
|
|
||||||
|
|
||||||
it('renders <HomeHOC /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Store>
|
|
||||||
<HomeHOC />
|
|
||||||
</Store>
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { ViewContainer } from 'joyent-ui-toolkit';
|
|
||||||
|
|
||||||
import { Home } from '@components/home';
|
|
||||||
import { changeFilters, resetFilters } from '../../state/actions';
|
|
||||||
|
|
||||||
const HomeHOC = props => (
|
|
||||||
<ViewContainer main>
|
|
||||||
<Home {...props} />
|
|
||||||
</ViewContainer>
|
|
||||||
);
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
filters: state.app.filters,
|
|
||||||
packages: state.app.packages,
|
|
||||||
form: state.form
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
onFilterChange: filters => {
|
|
||||||
dispatch(changeFilters(filters));
|
|
||||||
},
|
|
||||||
onFilterReset: () => {
|
|
||||||
dispatch(resetFilters());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(HomeHOC);
|
|
|
@ -1,76 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <Header /> without throwing 1`] = `
|
|
||||||
.c2 {
|
|
||||||
margin: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1.875rem;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 1.8125rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c2 + p,
|
|
||||||
.c2 + small,
|
|
||||||
.c2 + h1,
|
|
||||||
.c2 + h2,
|
|
||||||
.c2 + label,
|
|
||||||
.c2 + h3,
|
|
||||||
.c2 + h4,
|
|
||||||
.c2 + h5,
|
|
||||||
.c2 + div,
|
|
||||||
.c2 + span {
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c1 {
|
|
||||||
-webkit-flex: 1 1 auto;
|
|
||||||
-ms-flex: 1 1 auto;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
-webkit-align-self: stretch;
|
|
||||||
-ms-flex-item-align: stretch;
|
|
||||||
align-self: stretch;
|
|
||||||
-webkit-order: 0;
|
|
||||||
-ms-flex-order: 0;
|
|
||||||
order: 0;
|
|
||||||
padding: 0.84375rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0 {
|
|
||||||
max-height: 3.3125rem;
|
|
||||||
min-height: 3.3125rem;
|
|
||||||
padding: 0 1.125rem;
|
|
||||||
line-height: 1.5625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c3 {
|
|
||||||
border-style: none;
|
|
||||||
width: 5.4375rem;
|
|
||||||
height: 1.5625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="c0"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="c1"
|
|
||||||
>
|
|
||||||
<h2
|
|
||||||
className="c2"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="/"
|
|
||||||
name="Go to home"
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="Triton Logo"
|
|
||||||
className="c3"
|
|
||||||
src="test-file-mock"
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
|
@ -1,3 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`renders <withNotFound /> without throwing 1`] = `<withNotFound />`;
|
|
|
@ -1,21 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { Router } from '@mocks/';
|
|
||||||
import { Header } from '../';
|
|
||||||
|
|
||||||
it('renders <Header /> without throwing', () => {
|
|
||||||
const tree = renderer
|
|
||||||
.create(
|
|
||||||
<Router>
|
|
||||||
<Header />
|
|
||||||
</Router>
|
|
||||||
)
|
|
||||||
.toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
|
@ -1,14 +0,0 @@
|
||||||
/**
|
|
||||||
* @jest-environment jsdom
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
import 'jest-styled-components';
|
|
||||||
|
|
||||||
import { withNotFound } from '../';
|
|
||||||
|
|
||||||
it('renders <withNotFound /> without throwing', () => {
|
|
||||||
const tree = renderer.create(<withNotFound />).toJSON();
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|