feat(sg): bootstrap
This commit is contained in:
parent
a787ab5cb7
commit
6c62f4d6ec
|
@ -1,4 +1,9 @@
|
|||
packages/*/**
|
||||
prototypes/*/**
|
||||
artifacts
|
||||
reports
|
||||
.nyc_output
|
||||
coverage
|
||||
dist
|
||||
styleguide
|
||||
build
|
||||
lib/app
|
||||
node_modules
|
|
@ -1,8 +1,10 @@
|
|||
{
|
||||
"extends": "joyent-portal",
|
||||
"rules": {
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-console": 1,
|
||||
"new-cap": 0,
|
||||
"no-console": 0
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-negated-condition": 1,
|
||||
"camelcase": 1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,6 @@
|
|||
"build:lib": "echo 0",
|
||||
"build:bundle": "echo 0",
|
||||
"prepublish": "echo 0",
|
||||
"lint": "echo 0",
|
||||
"lint:ci": "echo 0",
|
||||
"test": "echo 0",
|
||||
"test:ci": "echo 0"
|
||||
},
|
||||
|
@ -19,6 +17,7 @@
|
|||
"brule": "^3.1.0",
|
||||
"cloudapi-gql": "^7.1.4",
|
||||
"execa": "^0.10.0",
|
||||
"graphql-tools": "^2.24.0",
|
||||
"h2o2": "^8.0.1",
|
||||
"hapi": "^17.3.1",
|
||||
"hapi-triton-auth": "^2.0.1",
|
||||
|
|
|
@ -13,7 +13,6 @@ const {
|
|||
} = process.env;
|
||||
|
||||
module.exports = async ({ PORT, BASE_URL }) => {
|
||||
const dcName = DC_NAME || Url.parse(SDC_URL).host.split('.')[0];
|
||||
const keyPath = SDC_KEY_PATH;
|
||||
const keyId = `/${SDC_ACCOUNT}/keys/${SDC_KEY_ID}`;
|
||||
const apiBaseUrl = SDC_URL;
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
const Main = require('apr-main');
|
||||
const {
|
||||
makeExecutableSchema,
|
||||
addMockFunctionsToSchema
|
||||
} = require('graphql-tools');
|
||||
const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
const Path = require('path');
|
||||
const Fs = require('fs');
|
||||
|
||||
const Server = require('./server');
|
||||
|
||||
const {
|
||||
PORT = 4004,
|
||||
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||
PREFIX = 'service-groups'
|
||||
} = process.env;
|
||||
|
||||
const ServiceGroupsGql = {
|
||||
name: 'tsg-gql',
|
||||
register: async server => {
|
||||
const typeDefs = Fs.readFileSync(
|
||||
Path.join(__dirname, 'tsg.graphql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs
|
||||
});
|
||||
|
||||
addMockFunctionsToSchema({ schema });
|
||||
|
||||
const graphiOptions = {
|
||||
graphiqlPath: '/graphiql',
|
||||
schema
|
||||
};
|
||||
|
||||
await server.register({
|
||||
plugin: Graphi,
|
||||
options: graphiOptions
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Main(async () => {
|
||||
const server = await Server({
|
||||
PORT,
|
||||
BASE_URL
|
||||
});
|
||||
|
||||
await server.register({
|
||||
plugin: ServiceGroupsGql,
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
});
|
||||
|
||||
await server.start();
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
const Main = require('apr-main');
|
||||
const {
|
||||
makeExecutableSchema,
|
||||
addMockFunctionsToSchema
|
||||
} = require('graphql-tools');
|
||||
const Graphi = require('graphi');
|
||||
const Url = require('url');
|
||||
const Path = require('path');
|
||||
const Fs = require('fs');
|
||||
|
||||
const Server = require('./server');
|
||||
|
||||
const {
|
||||
PORT = 4005,
|
||||
BASE_URL = `http://0.0.0.0:${PORT}`,
|
||||
PREFIX = 'templates'
|
||||
} = process.env;
|
||||
|
||||
const ServiceGroupsGql = {
|
||||
name: 'tsg-gql',
|
||||
register: async server => {
|
||||
const typeDefs = Fs.readFileSync(
|
||||
Path.join(__dirname, 'tsg.graphql'),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
const schema = makeExecutableSchema({
|
||||
typeDefs
|
||||
});
|
||||
|
||||
addMockFunctionsToSchema({ schema });
|
||||
|
||||
const graphiOptions = {
|
||||
graphiqlPath: '/graphiql',
|
||||
schema
|
||||
};
|
||||
|
||||
await server.register({
|
||||
plugin: Graphi,
|
||||
options: graphiOptions
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Main(async () => {
|
||||
const server = await Server({
|
||||
PORT,
|
||||
BASE_URL
|
||||
});
|
||||
|
||||
await server.register({
|
||||
plugin: ServiceGroupsGql,
|
||||
routes: {
|
||||
prefix: `/${PREFIX}`
|
||||
}
|
||||
});
|
||||
|
||||
await server.start();
|
||||
});
|
|
@ -0,0 +1,128 @@
|
|||
input KeyValueInput {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type KeyValue {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Network {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Image {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Package {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
type Group {
|
||||
# The universal identifier (UUID) of the group.
|
||||
id: ID!
|
||||
# The name of the group. The group name is limited to a maximum of 182 alphanumeric characters.
|
||||
name: String
|
||||
# A unique identifier for the template that the group is associated with.
|
||||
template: Template
|
||||
# The number of compute instances to run and maintain a specified number (the "desired count") of instances.
|
||||
capacity: Int
|
||||
# When this group was created. ISO8601 date format.
|
||||
created_at: String
|
||||
# When this group's details were last updated. ISO8601 date format.
|
||||
updated_at: String
|
||||
}
|
||||
|
||||
input GroupInput {
|
||||
# The name of the group. The group name is limited to a maximum of 182 alphanumeric characters.
|
||||
name: String
|
||||
# A unique identifier for the template that the group is associated with.
|
||||
template: ID
|
||||
# The number of compute instances to run and maintain a specified number (the "desired count") of instances.
|
||||
capacity: Int
|
||||
}
|
||||
|
||||
type Template {
|
||||
# The universal identifier (UUID) of the template.
|
||||
id: ID!
|
||||
# The name of the template.
|
||||
name: String
|
||||
# The unique identifier (UUID) of the package to use when launching compute instances.
|
||||
package: Package
|
||||
# The unique identifier (UUID) of the image to use when launching compute instances.
|
||||
image: Image
|
||||
# Whether to enable or disable the firewall on the instances launched. Default is false.
|
||||
firewall_enabled: Boolean
|
||||
# A list of unique network identifiers to attach to the compute instances launched.
|
||||
networks: [Network]
|
||||
# Arbitrary data to be copied to the instances on boot. This will not be executed.
|
||||
userdata: String
|
||||
# A mapping of metadata (a key-value pairs) to apply to the instances launched.
|
||||
metadata: [KeyValue]
|
||||
# A mapping of tags (a key-value pairs) to apply to the instances launched.
|
||||
tags: [KeyValue]
|
||||
# When this template was created. ISO8601 date format.
|
||||
created_at: String
|
||||
}
|
||||
|
||||
input TemplateInput {
|
||||
# The name of the template.
|
||||
name: String!
|
||||
# The unique identifier (UUID) of the package to use when launching compute instances.
|
||||
package: ID!
|
||||
# The unique identifier (UUID) of the image to use when launching compute instances.
|
||||
image: ID!
|
||||
# Whether to enable or disable the firewall on the instances launched. Default is false.
|
||||
firewall_enabled: Boolean
|
||||
# A list of unique network identifiers to attach to the compute instances launched.
|
||||
networks: [ID]
|
||||
# Arbitrary data to be copied to the instances on boot. This will not be executed.
|
||||
userdata: String
|
||||
# A mapping of metadata (a key-value pairs) to apply to the instances launched.
|
||||
metadata: [KeyValueInput]
|
||||
# A mapping of tags (a key-value pairs) to apply to the instances launched.
|
||||
tags: [KeyValueInput]
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
# Create a new group.
|
||||
createGroup(group: GroupInput!): Group
|
||||
|
||||
# Update an existing group
|
||||
updateGroup(
|
||||
# UUID of group to update.
|
||||
id: ID!
|
||||
group: GroupInput!
|
||||
): Group
|
||||
|
||||
# Delete a group.
|
||||
deleteGroup(id: ID!): Group
|
||||
|
||||
# Create a new template.
|
||||
createTemplate(template: TemplateInput!): Template
|
||||
|
||||
# Delete an existing template.
|
||||
deleteTemplate(id: ID!): Template
|
||||
}
|
||||
|
||||
type Query {
|
||||
# List all of the existing groups
|
||||
groups: [Group]
|
||||
|
||||
# Retrieve a specific group
|
||||
group(
|
||||
# The universal identifier (UUID) of the group.
|
||||
id: ID!
|
||||
): Group
|
||||
|
||||
# List all of the existing templates
|
||||
templates: [Template]
|
||||
|
||||
# Retrieve a specific template
|
||||
template(
|
||||
# The universal identifier (UUID) of the template.
|
||||
id: ID!
|
||||
): Template
|
||||
}
|
|
@ -4,7 +4,16 @@ module.exports = {
|
|||
'scope-enum': [
|
||||
2,
|
||||
'always',
|
||||
['ui-toolkit', 'icons', 'instances', 'navigation', 'bundle', 'images']
|
||||
[
|
||||
'ui-toolkit',
|
||||
'icons',
|
||||
'instances',
|
||||
'navigation',
|
||||
'bundle',
|
||||
'images',
|
||||
'sg',
|
||||
'templates'
|
||||
]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "joyent-portal",
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"new-cap": 0,
|
||||
"camelcase": 1,
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-negated-condition": 0
|
||||
}
|
||||
}
|
|
@ -11,8 +11,6 @@
|
|||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=images NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"lint": "redrun lint:ci -- --fix",
|
||||
"lint:ci": "NODE_ENV=test eslint . --ext .js --ext .md",
|
||||
"test": "echo 0",
|
||||
"test:ci": "echo 0",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
|
|
|
@ -6,7 +6,6 @@ import remcalc from 'remcalc';
|
|||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
|
||||
import {
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
|
@ -29,7 +28,6 @@ export default ({ placeholderName, randomizing, onRandomize }) => (
|
|||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<Divider height={remcalc(13)} transparent />
|
||||
<Margin left={1}>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
|
@ -2,15 +2,8 @@ import React from 'react';
|
|||
import { Field } from 'redux-form';
|
||||
import Flex from 'styled-flex-component';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
Button,
|
||||
FormGroup,
|
||||
Input,
|
||||
FormLabel,
|
||||
Divider
|
||||
} from 'joyent-ui-toolkit';
|
||||
import { Button, FormGroup, Input, FormLabel } from 'joyent-ui-toolkit';
|
||||
|
||||
export const Toolbar = ({
|
||||
searchable = true,
|
||||
|
@ -30,7 +23,6 @@ export const Toolbar = ({
|
|||
</FormGroup>
|
||||
{action ? (
|
||||
<FormGroup right>
|
||||
<Divider height={remcalc(21)} transparent />
|
||||
<Button
|
||||
type="button"
|
||||
disabled={!actionable}
|
||||
|
@ -48,6 +40,5 @@ export const Toolbar = ({
|
|||
export default ({ handleSubmit, ...rest }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Toolbar {...rest} />
|
||||
<Divider height={remcalc(20)} transparent />
|
||||
</form>
|
||||
);
|
||||
|
|
|
@ -6,17 +6,9 @@ import { destroy, reset } from 'redux-form';
|
|||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import get from 'lodash.get';
|
||||
import remcalc from 'remcalc';
|
||||
import Flex from 'styled-flex-component';
|
||||
|
||||
import {
|
||||
TagsIcon,
|
||||
Button,
|
||||
H3,
|
||||
TagList,
|
||||
Divider,
|
||||
KeyValue
|
||||
} from 'joyent-ui-toolkit';
|
||||
import { TagsIcon, Button, H3, TagList, KeyValue } from 'joyent-ui-toolkit';
|
||||
|
||||
import Title from '@components/create-image/title';
|
||||
import Description from '@components/description';
|
||||
|
@ -102,7 +94,6 @@ export const Tags = ({
|
|||
expanded
|
||||
onCancel={() => handleChangeAddOpen(false)}
|
||||
/>
|
||||
<Divider height={remcalc(18)} transparent />
|
||||
</Fragment>
|
||||
) : null
|
||||
}
|
||||
|
|
|
@ -41,15 +41,12 @@ export const List = ({
|
|||
handleRemove
|
||||
}) => (
|
||||
<ViewContainer main>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<ReduxForm form={LIST_TOOLBAR_FORM}>
|
||||
{props => <ToolbarForm {...props} actionable={!loading} />}
|
||||
</ReduxForm>
|
||||
<Divider height={remcalc(1)} />
|
||||
<Divider height={remcalc(24)} transparent />
|
||||
{loading && !images.length ? (
|
||||
<Fragment>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<StatusLoader />
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
|
|
@ -5,12 +5,10 @@ import { connect } from 'react-redux';
|
|||
import intercept from 'apr-intercept';
|
||||
import { set } from 'react-redux-values';
|
||||
import get from 'lodash.get';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
StatusLoader,
|
||||
Divider,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription
|
||||
|
@ -32,7 +30,6 @@ export const Summary = ({
|
|||
<ViewContainer main>
|
||||
{loading && !image ? (
|
||||
<Fragment>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<StatusLoader />
|
||||
</Fragment>
|
||||
) : null}
|
||||
|
|
|
@ -14,11 +14,11 @@ import {
|
|||
H3,
|
||||
ViewContainer,
|
||||
StatusLoader,
|
||||
Divider,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription,
|
||||
TagList
|
||||
TagList,
|
||||
Divider
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Forms } from '@root/constants';
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
RootContainer,
|
||||
|
@ -8,15 +7,13 @@ import {
|
|||
ViewContainer,
|
||||
Message,
|
||||
MessageDescription,
|
||||
MessageTitle,
|
||||
Divider
|
||||
MessageTitle
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import Breadcrumb from '@containers/breadcrumb';
|
||||
|
||||
export const Route = () => (
|
||||
<ViewContainer main>
|
||||
<Divider height={remcalc(30)} transparent />
|
||||
<Margin bottom={4}>
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
.nyc_output
|
||||
coverage
|
||||
dist
|
||||
build
|
||||
lib/app
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"extends": "joyent-portal",
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"new-cap": 0,
|
||||
"camelcase": 1,
|
||||
"jsx-a11y/href-no-hash": 0,
|
||||
"no-negated-condition": 0
|
||||
}
|
||||
}
|
|
@ -11,8 +11,6 @@
|
|||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=instances NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"lint": "redrun lint:ci -- --fix",
|
||||
"lint:ci": "NODE_ENV=test eslint . --ext .js --ext .md",
|
||||
"test": "DEFAULT_TIMEOUT_INTERVAL=100000 NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
|
||||
"test:ci": "NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
|
|
|
@ -124,7 +124,6 @@ export const AddServiceForm = ({
|
|||
>
|
||||
Add
|
||||
</Button>
|
||||
<Divider height={remcalc(4)} transparent />
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
|
|
|
@ -5,7 +5,6 @@ import Flex, { FlexItem } from 'styled-flex-component';
|
|||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
|
@ -27,7 +26,6 @@ export default ({ placeholderName, randomizing, onRandomize, onSave }) => (
|
|||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<Divider height={remcalc(13)} transparent />
|
||||
<Margin left={1}>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
|
@ -63,7 +63,7 @@ const MarginalPaginationItem = styled(PaginationItem)`
|
|||
`;
|
||||
|
||||
const Actions = styled(Flex)`
|
||||
height: ${remcalc(48)};
|
||||
height: 100%;
|
||||
`;
|
||||
|
||||
export const FetchingItem = () => (
|
||||
|
|
|
@ -3,15 +3,8 @@ import { Field } from 'redux-form';
|
|||
import Flex from 'styled-flex-component';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { Link } from 'react-router-dom';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
FormGroup,
|
||||
Input,
|
||||
FormLabel,
|
||||
Button,
|
||||
Divider
|
||||
} from 'joyent-ui-toolkit';
|
||||
import { FormGroup, Input, FormLabel, Button } from 'joyent-ui-toolkit';
|
||||
|
||||
export const Toolbar = ({
|
||||
searchLabel = 'Filter',
|
||||
|
@ -30,7 +23,6 @@ export const Toolbar = ({
|
|||
</Margin>
|
||||
</FormGroup>
|
||||
<FormGroup right>
|
||||
<Divider height={remcalc(21)} transparent />
|
||||
<Button
|
||||
type={actionTo || onActionClick ? 'button' : 'submit'}
|
||||
disabled={!actionable}
|
||||
|
@ -49,6 +41,5 @@ export const Toolbar = ({
|
|||
export default ({ handleSubmit, ...rest }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Toolbar {...rest} />
|
||||
<Divider height={remcalc(20)} transparent />
|
||||
</form>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
RootContainer,
|
||||
|
@ -8,15 +7,13 @@ import {
|
|||
ViewContainer,
|
||||
Message,
|
||||
MessageDescription,
|
||||
MessageTitle,
|
||||
Divider
|
||||
MessageTitle
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import Breadcrumb from '@containers/navigation/breadcrumb';
|
||||
|
||||
export const Route = () => (
|
||||
<ViewContainer main>
|
||||
<Divider height={remcalc(24)} transparent />
|
||||
<Margin bottom={4}>
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
build
|
||||
dist
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"extends": "joyent-portal",
|
||||
"rules": {
|
||||
"no-console": 0,
|
||||
"new-cap": 0,
|
||||
"camelcase": 1,
|
||||
// temp
|
||||
"no-undef": 1,
|
||||
"no-debugger": 1,
|
||||
"no-negated-condition": 0,
|
||||
"jsx-a11y/href-no-hash": 0
|
||||
}
|
||||
}
|
|
@ -10,8 +10,6 @@
|
|||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=navigation NODE_ENV=production redrun build",
|
||||
"prepublish": "NAMESPACE=navigation NODE_ENV=production redrun build",
|
||||
"lint": "redrun lint:ci -- --fix",
|
||||
"lint:ci": "NODE_ENV=test eslint . --ext .js --ext .md",
|
||||
"test": "echo 0",
|
||||
"test:ci": "redrun test",
|
||||
"build": "PREACT=1 joyent-react-scripts build"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"ignore": ["_document.js", "_aliases.js"],
|
||||
"presets": [
|
||||
[
|
||||
"joyent-portal",
|
||||
{
|
||||
"aliases": true,
|
||||
"autoAliases": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
lib/app
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"setup": {
|
||||
"compile": "npm run build",
|
||||
"start": "serve -s build --port 3069 --single",
|
||||
"href": "http://0.0.0.0:3069"
|
||||
},
|
||||
"extends": "lighthouse:default"
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
!lib/app
|
||||
!dist
|
||||
!build
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"test": ["./src/**/*.js"],
|
||||
"extends": ["stylelint-config-joyent-portal"]
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"libs": ["ecmascript", "browser"],
|
||||
"plugins": {
|
||||
"doc_comment": true,
|
||||
"local-scope": true,
|
||||
"jsx": true,
|
||||
"node": true,
|
||||
"webpack": {
|
||||
"configPath":
|
||||
"../../node_modules/joyent-react-scripts/src/webpack.config.dev.js"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
const Inert = require('inert');
|
||||
const Path = require('path');
|
||||
const RenderReact = require('hapi-render-react');
|
||||
const Intercept = require('apr-intercept');
|
||||
const Fs = require('mz/fs');
|
||||
|
||||
const { NAMESPACE = 'service-groups' } = process.env;
|
||||
|
||||
exports.register = async server => {
|
||||
const relativeTo = Path.join(__dirname, 'app');
|
||||
const buildRoot = Path.join(__dirname, `../build/${NAMESPACE}/static/`);
|
||||
const publicRoot = Path.join(__dirname, `../public/static/`);
|
||||
|
||||
await server.register([
|
||||
{
|
||||
plugin: Inert
|
||||
},
|
||||
{
|
||||
plugin: RenderReact
|
||||
}
|
||||
]);
|
||||
|
||||
server.route([
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/service-worker.js`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/service-worker.js')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/favicon.ico`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/favicon.ico')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/static/{rest*}`,
|
||||
config: {
|
||||
auth: false
|
||||
},
|
||||
handler: async (request, h) => {
|
||||
const { params } = request;
|
||||
const { rest } = params;
|
||||
|
||||
const publicPathname = Path.join(publicRoot, rest);
|
||||
const buildPathname = Path.join(buildRoot, rest);
|
||||
|
||||
const [err] = await Intercept(
|
||||
Fs.access(publicPathname, Fs.constants.R_OK)
|
||||
);
|
||||
|
||||
const file = err ? buildPathname : publicPathname;
|
||||
return h.file(file, { confine: false });
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/~server-error`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'server-error',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/{path*}`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'app',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
exports.pkg = require('../package.json');
|
|
@ -0,0 +1,51 @@
|
|||
{
|
||||
"name": "my-joy-service-groups",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MPL-2.0",
|
||||
"repository": "github:yldio/joyent-portal",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "NAMESPACE=service-groups NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3072 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=service-groups NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"test": "DEFAULT_TIMEOUT_INTERVAL=100000 NODE_ENV=test joyent-react-scripts test --env=jsdom",
|
||||
"test:ci": "NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
"build:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files"
|
||||
},
|
||||
"dependencies": {
|
||||
"@manaflair/redux-batch": "^0.1.0",
|
||||
"cross-fetch": "^2.1.0",
|
||||
"exenv": "^1.2.2",
|
||||
"hapi-render-react": "^2.5.2",
|
||||
"hapi-render-react-joyent-document": "^5.0.0",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"react": "^16.3.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-redux-values": "^1.1.2",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"redux": "^3.7.2",
|
||||
"redux-form": "^7.3.0",
|
||||
"remcalc": "^1.0.10",
|
||||
"styled-components": "^3.2.5",
|
||||
"styled-components-spacing": "^2.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"jest-image-snapshot": "^2.4.0",
|
||||
"jest-styled-components": "^5.0.1",
|
||||
"joyent-react-scripts": "^8.0.3",
|
||||
"react-screenshot-renderer": "^1.1.2",
|
||||
"react-test-renderer": "^16.3.1",
|
||||
"redrun": "^6.0.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="theme-color" content="#1E313B">
|
||||
|
||||
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> -->
|
||||
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> -->
|
||||
<title>My Joyent β</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header"></div>
|
||||
<div id="root"></div>
|
||||
<script src="/navigation/static/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"short_name": "Joyent",
|
||||
"name": "My Joyent β",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#1E313B",
|
||||
"background_color": "#FAFAFA"
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Libre Franklin'), local('LibreFranklin-Regular'),
|
||||
url(../fonts/libre-franklin/libre-franklin-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Libre Franklin Medium'), local('LibreFranklin-Medium'),
|
||||
url(../fonts/libre-franklin/libre-franklin-medium.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Libre Franklin SemiBold'), local('LibreFranklin-SemiBold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-semibold.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Libre Franklin Bold'), local('LibreFranklin-Bold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-bold.ttf) format('truetype');
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto Mono'), local('RobotoMono-Regular'),
|
||||
url(../fonts/roboto-mono/roboto-mono-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Mono Bold'), local('RobotoMono-Bold'),
|
||||
url(../fonts/roboto-mono/roboto-mono-bold.ttf) format('truetype');
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
Copyright (c) 2015, Impallari Type (www.impallari.com)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,20 @@
|
|||
# my-joy-service-groups
|
||||
|
||||
[![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg?style=flat-square)](https://opensource.org/licenses/MPL-2.0)
|
||||
[![standard-readme compliant](https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Usage](#usage)
|
||||
* [License](#license)
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
npm run start
|
||||
open http://0.0.0.0:3069
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MPL-2.0
|
|
@ -0,0 +1 @@
|
|||
module.exports = {};
|
|
@ -0,0 +1,56 @@
|
|||
const get = require('lodash.get');
|
||||
const Document = require('hapi-render-react-joyent-document');
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
|
||||
const { theme } = require('joyent-ui-toolkit');
|
||||
const { default: createClient } = require('./state/apollo-client');
|
||||
const { default: createStore } = require('./state/redux-store');
|
||||
|
||||
const indexFile = path.join(__dirname, '../../build/index.html');
|
||||
const assets = require('../../build/asset-manifest.json');
|
||||
|
||||
const { NODE_ENV = 'development' } = process.env;
|
||||
|
||||
const getState = request => {
|
||||
const { req } = request.raw;
|
||||
const { headers } = req;
|
||||
const { host } = headers;
|
||||
|
||||
const protocol = NODE_ENV === 'development' ? 'http:' : 'https:';
|
||||
const _font = get(theme, 'font.href', () => '');
|
||||
const _mono = get(theme, 'monoFont.href', () => '');
|
||||
const _addr = url.parse(`${protocol}//${host}`);
|
||||
|
||||
const _theme = Object.assign({}, theme, {
|
||||
font: Object.assign({}, theme.font, {
|
||||
href: () =>
|
||||
_font(
|
||||
Object.assign(_addr, {
|
||||
namespace: 'service-groups'
|
||||
})
|
||||
)
|
||||
}),
|
||||
monoFont: Object.assign({}, theme.monoFont, {
|
||||
href: () =>
|
||||
_mono(
|
||||
Object.assign(_addr, {
|
||||
namespace: 'service-groups'
|
||||
})
|
||||
)
|
||||
})
|
||||
});
|
||||
|
||||
return {
|
||||
theme: _theme,
|
||||
createClient,
|
||||
createStore
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = Document({
|
||||
namespace: 'service-groups/',
|
||||
assets,
|
||||
indexFile,
|
||||
getState
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
import React from 'react';
|
||||
|
||||
import { RootContainer } from 'joyent-ui-toolkit';
|
||||
import Routes from '@root/routes';
|
||||
|
||||
export default () => (
|
||||
<RootContainer>
|
||||
<Routes />
|
||||
</RootContainer>
|
||||
);
|
|
@ -0,0 +1,154 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import remcalc from 'remcalc';
|
||||
import styled from 'styled-components';
|
||||
import titleCase from 'title-case';
|
||||
import { Link } from 'react-router-dom';
|
||||
import queryString from 'query-string';
|
||||
|
||||
import {
|
||||
Anchor,
|
||||
FormGroup,
|
||||
Checkbox,
|
||||
Table,
|
||||
TableThead,
|
||||
TableTr,
|
||||
TableTh,
|
||||
TableTd,
|
||||
TableTbody,
|
||||
PaginationTableFoot,
|
||||
PaginationItem,
|
||||
StatusLoader,
|
||||
ActionsIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Global } from '@state/global';
|
||||
|
||||
const A = styled(Anchor)`
|
||||
color: ${props => props.theme.text};
|
||||
text-decoration: none;
|
||||
font-weight: ${props => props.theme.font.weight.semibold};
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
`;
|
||||
|
||||
const MarginalPaginationItem = styled(PaginationItem)`
|
||||
margin: 0 ${remcalc(3)};
|
||||
`;
|
||||
|
||||
export const FetchingItem = () => (
|
||||
<TableTr colSpan="6">
|
||||
<TableTd colSpan="6" middle center>
|
||||
<StatusLoader />
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export const Item = ({ id = '', name, capacity, template, created_at }) => (
|
||||
<TableTr>
|
||||
<TableTd padding="0" middle left>
|
||||
<FormGroup name={id}>
|
||||
<Checkbox noMargin />
|
||||
</FormGroup>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<A to={`/service-groups/${id}`} component={Link}>
|
||||
{name}
|
||||
</A>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
{capacity}
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<A to={`/templates/${template.id}`} component={Link}>
|
||||
{template.name}
|
||||
</A>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
{distanceInWordsToNow(created_at)}
|
||||
</TableTd>
|
||||
<TableTd padding="0" hasBorder="left" center middle>
|
||||
<ActionsIcon disabled />
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
);
|
||||
|
||||
export default ({
|
||||
sortBy = 'name',
|
||||
sortOrder = 'desc',
|
||||
submitting = false,
|
||||
allSelected = false,
|
||||
toggleSelectAll = () => null,
|
||||
onSortBy = () => null,
|
||||
children
|
||||
}) => (
|
||||
<form>
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="32" padding="0" middle left>
|
||||
<FormGroup>
|
||||
<Checkbox
|
||||
checked={allSelected}
|
||||
disabled={submitting}
|
||||
onChange={toggleSelectAll}
|
||||
noMargin
|
||||
/>
|
||||
</FormGroup>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
onClick={() => onSortBy('name')}
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'name'}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Name</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="0"
|
||||
sm="120"
|
||||
onClick={() => onSortBy('capacity')}
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'capacity'}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Desired #</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="0"
|
||||
sm="160"
|
||||
onClick={() => onSortBy('template')}
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'template'}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Template</span>
|
||||
</TableTh>
|
||||
<TableTh
|
||||
xs="0"
|
||||
sm="160"
|
||||
onClick={() => onSortBy('created')}
|
||||
sortOrder={sortOrder}
|
||||
showSort={sortBy === 'created'}
|
||||
left
|
||||
middle
|
||||
actionable
|
||||
>
|
||||
<span>Created</span>
|
||||
</TableTh>
|
||||
<TableTh xs="60" padding="0" />
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>{children}</TableTbody>
|
||||
</Table>
|
||||
</form>
|
||||
);
|
|
@ -0,0 +1,353 @@
|
|||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
||||
import { Row, Col } from 'joyent-react-styled-flexboxgrid';
|
||||
import { Padding, Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import styled, { withTheme } from 'styled-components';
|
||||
import titleCase from 'title-case';
|
||||
import remcalc from 'remcalc';
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardOutlet,
|
||||
H2,
|
||||
H3,
|
||||
P,
|
||||
Label,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
Checkbox,
|
||||
Anchor,
|
||||
Button,
|
||||
Hr,
|
||||
Table,
|
||||
TableThead,
|
||||
TableTbody,
|
||||
PaginationTableFoot,
|
||||
PaginationItem,
|
||||
TableTr,
|
||||
TableTh,
|
||||
TableTd,
|
||||
DotIcon,
|
||||
DeleteIcon,
|
||||
ArrowIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const GreyLabel = styled(Label)`
|
||||
opacity: 0.5;
|
||||
padding-right: ${remcalc(3)};
|
||||
`;
|
||||
|
||||
const VerticalDivider = styled.div`
|
||||
width: ${remcalc(1)};
|
||||
background: ${props => props.theme.grey};
|
||||
height: ${remcalc(24)};
|
||||
display: flex;
|
||||
align-self: flex-end;
|
||||
margin: 0 ${remcalc(12)};
|
||||
`;
|
||||
|
||||
const stateColor = {
|
||||
PROVISIONING: 'primary',
|
||||
RUNNING: 'green',
|
||||
STOPPING: 'grey',
|
||||
STOPPED: 'grey',
|
||||
DELETED: 'secondaryActive',
|
||||
FAILED: 'red'
|
||||
};
|
||||
|
||||
export const Meta = withTheme(
|
||||
({ name, template, created, updated, status, theme }) => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all="5">
|
||||
<H2>{name}</H2>
|
||||
<Margin top="2">
|
||||
<P>35/35 desired instances</P>
|
||||
</Margin>
|
||||
<Margin top="3" bottom="3">
|
||||
<Hr />
|
||||
</Margin>
|
||||
<Margin bottom="3">
|
||||
<Flex>
|
||||
<FlexItem>
|
||||
<Padding right="3">
|
||||
<GreyLabel inline>Template: </GreyLabel>
|
||||
<Label inline> {template}</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<VerticalDivider />
|
||||
<FlexItem>
|
||||
<Padding right="3">
|
||||
<GreyLabel inline>Created: </GreyLabel>
|
||||
<Label inline> {distanceInWordsToNow(created)} ago</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<VerticalDivider />
|
||||
<FlexItem>
|
||||
<Padding horizontal="3">
|
||||
<GreyLabel inline>Updated: </GreyLabel>
|
||||
<Label inline> {distanceInWordsToNow(updated)} ago</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
<VerticalDivider />
|
||||
<FlexItem>
|
||||
<Padding left="3">
|
||||
<GreyLabel inline>Status: </GreyLabel>
|
||||
<Label inline>
|
||||
<DotIcon
|
||||
right={remcalc(6)}
|
||||
size={remcalc(15)}
|
||||
color={stateColor[status]}
|
||||
/>
|
||||
{titleCase(status)}
|
||||
</Label>
|
||||
</Padding>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Row between="xs">
|
||||
<Col xs="6">
|
||||
<Margin right="1" inline>
|
||||
<Button type="button" bold icon>
|
||||
<span>Edit Service Group</span>
|
||||
</Button>
|
||||
</Margin>
|
||||
<Button type="button" secondary bold icon>
|
||||
<span>View instances</span>
|
||||
</Button>
|
||||
</Col>
|
||||
<Col xs="6">
|
||||
<Button type="button" secondary bold right icon error>
|
||||
<Margin right={2}>
|
||||
<DeleteIcon fill={theme.red} />
|
||||
</Margin>
|
||||
<span>Remove</span>
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Padding>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
)
|
||||
);
|
||||
|
||||
export const EventLogContainer = () => (
|
||||
<Card>
|
||||
<CardOutlet>
|
||||
<Padding all="5">
|
||||
<H3>Event log</H3>
|
||||
<Margin top="5" bottom="3">
|
||||
<Flex justifyBetween alignEnd>
|
||||
<FormGroup name="filter">
|
||||
<Margin bottom="0.5">
|
||||
<FormLabel>Filter</FormLabel>
|
||||
</Margin>
|
||||
<Flex alignCenter>
|
||||
<FlexItem>
|
||||
<Margin right="5">
|
||||
<Input />
|
||||
</Margin>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<FormGroup>
|
||||
<Margin right="3">
|
||||
<Checkbox>
|
||||
<Margin left="2">
|
||||
<Label>Show census checks</Label>
|
||||
</Margin>
|
||||
</Checkbox>
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
<FlexItem>
|
||||
<FormGroup>
|
||||
<Margin right="3">
|
||||
<Checkbox>
|
||||
<Margin left="2">
|
||||
<Label>Show users activity</Label>
|
||||
</Margin>
|
||||
</Checkbox>
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
</FlexItem>
|
||||
</Flex>
|
||||
</FormGroup>
|
||||
</Flex>
|
||||
</Margin>
|
||||
<Margin bottom="5">
|
||||
<Hr />
|
||||
</Margin>
|
||||
<Table>
|
||||
<TableThead>
|
||||
<TableTr>
|
||||
<TableTh xs="200" left middle actionable>
|
||||
<span>Time & date</span>
|
||||
</TableTh>
|
||||
<TableTh left middle actionable>
|
||||
<span>Log description</span>
|
||||
</TableTh>
|
||||
<TableTh xs="230" left middle actionable>
|
||||
<span>Actor ID</span>
|
||||
</TableTh>
|
||||
</TableTr>
|
||||
</TableThead>
|
||||
<TableTbody>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:52 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>5 of 5 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census check</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:50 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Destroying instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:45 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>10 of 5 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:17 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>‘Desired instances’ set to 5</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>raoulmillais</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr disabled>
|
||||
<TableTd colSpan="3" middle left shrinken>
|
||||
<Anchor>
|
||||
Show hidden actions (63) <ArrowIcon fill="primary" />
|
||||
</Anchor>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:16 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Provisioning instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:16 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>7 of 10 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:11 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>10 of 10 instances running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:11 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Provisioning instances</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:10 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>0 of 10 instance running</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Census checks</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:09 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Job working</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>09:51 - 28/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Job submission</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>tritionServiceGroups</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
<TableTr>
|
||||
<TableTd middle left>
|
||||
<span>12:08 - 26/03/2018</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>Service group deployed</span>
|
||||
</TableTd>
|
||||
<TableTd middle left>
|
||||
<span>raoulmillais</span>
|
||||
</TableTd>
|
||||
</TableTr>
|
||||
</TableTbody>
|
||||
<PaginationTableFoot colSpan="3">
|
||||
<PaginationItem to="" component={Link} disabled prev>
|
||||
Prev
|
||||
</PaginationItem>
|
||||
<PaginationItem to="" component={Link} active>
|
||||
1
|
||||
</PaginationItem>
|
||||
<PaginationItem to="" component={Link} disabled next>
|
||||
Next
|
||||
</PaginationItem>
|
||||
</PaginationTableFoot>
|
||||
</Table>
|
||||
</Padding>
|
||||
</CardOutlet>
|
||||
</Card>
|
||||
);
|
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import Flex from 'styled-flex-component';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { FormGroup, Input, FormLabel, Button } from 'joyent-ui-toolkit';
|
||||
|
||||
export const Toolbar = ({
|
||||
searchLabel = 'Filter',
|
||||
searchPlaceholder = '',
|
||||
searchable = true,
|
||||
actionLabel = 'Create',
|
||||
actionable = true,
|
||||
onActionClick,
|
||||
actionTo
|
||||
}) => (
|
||||
<Flex justifyBetween alignEnd>
|
||||
<FormGroup name="filter">
|
||||
<FormLabel>{searchLabel}</FormLabel>
|
||||
<Margin top={0.5}>
|
||||
<Input placeholder={searchPlaceholder} disabled={!searchable} />
|
||||
</Margin>
|
||||
</FormGroup>
|
||||
<FormGroup right>
|
||||
<Button
|
||||
type={actionTo || onActionClick ? 'button' : 'submit'}
|
||||
disabled={!actionable}
|
||||
component={actionTo ? Link : undefined}
|
||||
to={actionTo}
|
||||
onClick={onActionClick}
|
||||
icon
|
||||
fluid
|
||||
>
|
||||
{actionLabel}
|
||||
</Button>
|
||||
</FormGroup>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export default ({ handleSubmit, ...rest }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Toolbar {...rest} />
|
||||
</form>
|
||||
);
|
|
@ -0,0 +1,36 @@
|
|||
import React from 'react';
|
||||
import renderer from 'react-test-renderer';
|
||||
import 'jest-styled-components';
|
||||
|
||||
import Breadcrumb from '../breadcrumb';
|
||||
import Theme from '@mocks/theme';
|
||||
|
||||
it('renders <Breadcrumb /> without throwing', () => {
|
||||
expect(
|
||||
renderer
|
||||
.create(
|
||||
<Theme>
|
||||
<Breadcrumb />
|
||||
</Theme>
|
||||
)
|
||||
.toJSON()
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders <Breadcrumb match /> without throwing', () => {
|
||||
const match = {
|
||||
params: {
|
||||
sg: 'id'
|
||||
}
|
||||
};
|
||||
|
||||
expect(
|
||||
renderer
|
||||
.create(
|
||||
<Theme>
|
||||
<Breadcrumb match={match} />
|
||||
</Theme>
|
||||
)
|
||||
.toJSON()
|
||||
).toMatchSnapshot();
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import paramCase from 'param-case';
|
||||
import get from 'lodash.get';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
|
||||
import { Breadcrumb, BreadcrumbItem } from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ match }) => {
|
||||
const serviceGroupId = get(match, 'params.sg');
|
||||
|
||||
const links = [
|
||||
{
|
||||
name: 'Compute',
|
||||
pathname: '/'
|
||||
},
|
||||
{
|
||||
name: 'Service Groups',
|
||||
pathname: '/service-groups'
|
||||
}
|
||||
]
|
||||
.concat(
|
||||
serviceGroupId && [
|
||||
{
|
||||
name: paramCase(serviceGroupId),
|
||||
pathname: `/service-groups/${serviceGroupId}`
|
||||
}
|
||||
]
|
||||
)
|
||||
.filter(Boolean)
|
||||
.map(({ name, pathname }) => (
|
||||
<BreadcrumbItem key={name} to={pathname} component={Link}>
|
||||
<Margin vertical={2}>{name}</Margin>
|
||||
</BreadcrumbItem>
|
||||
));
|
||||
|
||||
return <Breadcrumb>{links}</Breadcrumb>;
|
||||
};
|
|
@ -0,0 +1,140 @@
|
|||
import React, { Component } from 'react';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { Margin, Padding } from 'styled-components-spacing';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import {
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageTitle,
|
||||
MessageDescription,
|
||||
Button
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import { Provider as ResourceSteps } from 'joyent-ui-resource-step';
|
||||
import Template from './template';
|
||||
import Name from './name';
|
||||
|
||||
const names = {
|
||||
template: 'SG_TEMPLATE',
|
||||
deploy: 'SG_DEPLOY'
|
||||
};
|
||||
|
||||
class CreateTemplate extends Component {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.isValids = {};
|
||||
}
|
||||
|
||||
setIsValid = name => ref => {
|
||||
if (!ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { isValid } = ref;
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isValids = Object.assign({}, this.isValids, {
|
||||
[name]: isValid
|
||||
});
|
||||
};
|
||||
|
||||
isFormValid = () => {
|
||||
const { steps } = this.props;
|
||||
|
||||
return Boolean(
|
||||
Object.keys(this.isValids).filter(
|
||||
name => !this.isValids[name](steps[name] || {})
|
||||
).length
|
||||
);
|
||||
};
|
||||
|
||||
isStepValid = step => {
|
||||
const { steps } = this.props;
|
||||
const fn = this.isValids[step];
|
||||
const values = steps[step];
|
||||
|
||||
if (!fn || !values) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fn(values);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { error, match, steps, handleDefocus } = this.props;
|
||||
const { params } = match;
|
||||
const { step } = params;
|
||||
const { template, name } = steps;
|
||||
|
||||
return (
|
||||
<ViewContainer main>
|
||||
<Padding top="5">
|
||||
<ResourceSteps namespace="service-groups/~create">
|
||||
<Margin bottom="4">
|
||||
<Template
|
||||
ref={this.setIsValid('template')}
|
||||
expanded={step === 'template'}
|
||||
next="image"
|
||||
saved={get(steps, 'template.id', false)}
|
||||
onDefocus={handleDefocus('template')}
|
||||
preview={template}
|
||||
isValid={this.isStepValid('template')}
|
||||
/>
|
||||
</Margin>
|
||||
<Margin bottom="4">
|
||||
<Name
|
||||
ref={this.setIsValid('name')}
|
||||
expanded={step === 'name'}
|
||||
next="image"
|
||||
saved={get(steps, 'name.name', false)}
|
||||
onDefocus={handleDefocus('name')}
|
||||
preview={name}
|
||||
isValid={this.isStepValid('name')}
|
||||
/>
|
||||
</Margin>
|
||||
</ResourceSteps>
|
||||
<Margin top={5} bottom={3}>
|
||||
{error ? (
|
||||
<Margin bottom={4}>
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>{error}</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
) : null}
|
||||
<ReduxForm form={names.deploy}>
|
||||
{({ handleSubmit, submitting }) => (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Button disabled={!this.isFormValid()} loading={submitting}>
|
||||
Deploy
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
</ReduxForm>
|
||||
</Margin>
|
||||
</Padding>
|
||||
</ViewContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
connect(
|
||||
({ values = {} }) => ({
|
||||
steps: {
|
||||
name: values[names.name]
|
||||
}
|
||||
}),
|
||||
(dispatch, ownProps) => ({
|
||||
handleDefocus: name => value =>
|
||||
dispatch(set({ name: names[name], value }))
|
||||
})
|
||||
)
|
||||
)(CreateTemplate);
|
|
@ -0,0 +1,38 @@
|
|||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
|
||||
import { ViewContainer } from 'joyent-ui-toolkit';
|
||||
|
||||
import { Toolbar } from '@components/toolbar';
|
||||
import ServiceGroupsList, { Item as ServiceGroupsItem } from '@components/list';
|
||||
import ListServiceGroups from '@graphql/list-service-groups.gql';
|
||||
|
||||
const ServiceGroups = ({ groups = [] }) => (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<Margin bottom={3}>
|
||||
<Toolbar
|
||||
searchLabel="Filter service groups"
|
||||
actionLabel="Create Service Group"
|
||||
actionTo="/service-groups/~create"
|
||||
/>
|
||||
</Margin>
|
||||
<ServiceGroupsList>
|
||||
{groups.map(({ id, ...sg }) => (
|
||||
<ServiceGroupsItem key={id} id={id} {...sg} />
|
||||
))}
|
||||
</ServiceGroupsList>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
graphql(ListServiceGroups, {
|
||||
options: ({ location }) => ({
|
||||
ssr: false,
|
||||
pollInterval: 1000
|
||||
}),
|
||||
props: ({ data }) => data
|
||||
})
|
||||
)(ServiceGroups);
|
|
@ -0,0 +1,60 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import { Field } from 'redux-form';
|
||||
import { reset } from 'redux-form';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import Step, {
|
||||
Header as StepHeader,
|
||||
Description as StepDescription,
|
||||
Preview as StepPreview,
|
||||
Outlet as StepOutlet
|
||||
} from 'joyent-ui-resource-step';
|
||||
|
||||
import {
|
||||
H2,
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
FormMeta,
|
||||
Button,
|
||||
RandomizeIcon,
|
||||
InstanceCountIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const Template = ({ handleGetValue, preview = {}, ...props }) => (
|
||||
<Step name="name" getValue={handleGetValue} {...props}>
|
||||
<StepHeader icon={<InstanceCountIcon />}>
|
||||
Name and instance count
|
||||
</StepHeader>
|
||||
<StepDescription>
|
||||
Input the name of your Service Group and the desired number of instances
|
||||
this group will aim to maintain. You can scale up or down your Service
|
||||
Group anytime after commisioning.
|
||||
</StepDescription>
|
||||
<StepPreview>
|
||||
<Margin top="5" />
|
||||
</StepPreview>
|
||||
<StepOutlet />
|
||||
</Step>
|
||||
);
|
||||
|
||||
const Container = compose(connect(null, null))(Template);
|
||||
|
||||
export default class extends PureComponent {
|
||||
isValid = values => {
|
||||
return false;
|
||||
};
|
||||
|
||||
render = () => {
|
||||
const { children, ...props } = this.props;
|
||||
return <Container {...props}>{children}</Container>;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
|
||||
import { ViewContainer } from 'joyent-ui-toolkit';
|
||||
|
||||
import { Meta, EventLogContainer } from '@components/summary';
|
||||
|
||||
export default () => (
|
||||
<ViewContainer main>
|
||||
<Margin top="5">
|
||||
<Margin bottom="5">
|
||||
<Meta name="delightful-stingray" />
|
||||
</Margin>
|
||||
<EventLogContainer />
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
|
@ -0,0 +1,58 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
import Flex, { FlexItem } from 'styled-flex-component';
|
||||
import { compose, graphql } from 'react-apollo';
|
||||
import { Link } from 'react-router-dom';
|
||||
import ReduxForm from 'declarative-redux-form';
|
||||
import { connect } from 'react-redux';
|
||||
import { set } from 'react-redux-values';
|
||||
import { Field } from 'redux-form';
|
||||
import { reset } from 'redux-form';
|
||||
import get from 'lodash.get';
|
||||
|
||||
import Step, {
|
||||
Header as StepHeader,
|
||||
Description as StepDescription,
|
||||
Preview as StepPreview,
|
||||
Outlet as StepOutlet
|
||||
} from 'joyent-ui-resource-step';
|
||||
|
||||
import {
|
||||
H2,
|
||||
Divider,
|
||||
FormGroup,
|
||||
FormLabel,
|
||||
Input,
|
||||
FormMeta,
|
||||
Button,
|
||||
RandomizeIcon,
|
||||
NameIcon
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
const Template = ({ handleGetValue, preview = {}, ...props }) => (
|
||||
<Step name="template" getValue={handleGetValue} {...props}>
|
||||
<StepHeader icon={<NameIcon />}>Select template</StepHeader>
|
||||
<StepDescription>
|
||||
Select the template you’d like to deloy your instances from. Once a
|
||||
Service Group is deployed with a templates, any changes to that template
|
||||
will not effect the acting service group.
|
||||
</StepDescription>
|
||||
<StepPreview>
|
||||
<Margin top="5" />
|
||||
</StepPreview>
|
||||
<StepOutlet />
|
||||
</Step>
|
||||
);
|
||||
|
||||
const Container = compose(connect(null, null))(Template);
|
||||
|
||||
export default class extends PureComponent {
|
||||
isValid = values => {
|
||||
return false;
|
||||
};
|
||||
|
||||
render = () => {
|
||||
const { children, ...props } = this.props;
|
||||
return <Container {...props}>{children}</Container>;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
query groups {
|
||||
groups {
|
||||
id
|
||||
name
|
||||
template {
|
||||
name
|
||||
}
|
||||
capacity
|
||||
created_at
|
||||
updated_at
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
import { ApolloProvider } from 'react-apollo';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import isFunction from 'lodash.isfunction';
|
||||
import isFinite from 'lodash.isfinite';
|
||||
|
||||
import { theme } from 'joyent-ui-toolkit';
|
||||
|
||||
import createStore from '@state/redux-store';
|
||||
import createClient from '@state/apollo-client';
|
||||
import App from './app';
|
||||
|
||||
if (!isFunction(Number.isFinite)) {
|
||||
Number.isFinite = isFinite;
|
||||
}
|
||||
|
||||
ReactDOM.hydrate(
|
||||
<ApolloProvider client={createClient()}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ReduxProvider store={createStore()}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</ReduxProvider>
|
||||
</ThemeProvider>
|
||||
</ApolloProvider>,
|
||||
document.getElementById('root')
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
'^redux-form$': '<rootDir>/src/mocks/redux-form',
|
||||
'^react-responsive$': '<rootDir>/src/mocks/react-responsive',
|
||||
'^react-router-dom$': '<rootDir>/src/mocks/react-router-dom',
|
||||
'^declarative-redux-form$': '<rootDir>/src/mocks/declarative-redux-form'
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
import React from 'react';
|
||||
|
||||
export default ({ children, ...props }) => React.createElement(children, props);
|
|
@ -0,0 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
export default ({ query, children }) => (
|
||||
<span name="react-responsive-mock" query={query}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
|
@ -0,0 +1,4 @@
|
|||
import React from 'react';
|
||||
|
||||
export const Field = ({ children, ...rest }) =>
|
||||
React.createElement('a', rest, children);
|
|
@ -0,0 +1,4 @@
|
|||
import React from 'react';
|
||||
|
||||
export const Field = ({ component = 'input', children, ...rest }) =>
|
||||
React.createElement(component, rest, children);
|
|
@ -0,0 +1,23 @@
|
|||
import React from 'react';
|
||||
import { ThemeProvider } from 'styled-components';
|
||||
|
||||
import {
|
||||
theme,
|
||||
RootContainer,
|
||||
PageContainer,
|
||||
ViewContainer
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
export default ({ children, ss }) => (
|
||||
<ThemeProvider theme={theme}>
|
||||
{ss ? (
|
||||
<RootContainer>
|
||||
<PageContainer>
|
||||
<ViewContainer>{children}</ViewContainer>
|
||||
</PageContainer>
|
||||
</RootContainer>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</ThemeProvider>
|
||||
);
|
|
@ -0,0 +1,55 @@
|
|||
import React from 'react';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
PageContainer,
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageDescription,
|
||||
MessageTitle,
|
||||
Footer
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import Breadcrumb from '@containers/breadcrumb';
|
||||
import { Route as ServerError } from '@root/server-error';
|
||||
|
||||
import Summary from '@containers/summary';
|
||||
import List from '@containers/list';
|
||||
import Create from '@containers/create';
|
||||
|
||||
export default () => (
|
||||
<PageContainer>
|
||||
{/* Breadcrumb */}
|
||||
<Switch>
|
||||
<Route
|
||||
path="/service-groups/~create/:section?"
|
||||
exact
|
||||
component={Breadcrumb}
|
||||
/>
|
||||
<Route path="/service-groups/:sg?/:section?" component={Breadcrumb} />
|
||||
</Switch>
|
||||
|
||||
{/* Containers */}
|
||||
<Switch>
|
||||
<Route path="/service-groups" exact component={List} />
|
||||
<Route path="/service-groups/~create/:step?" exact component={Create} />
|
||||
<Route path="/service-groups/:sg/:section?" exact component={Summary} />
|
||||
</Switch>
|
||||
|
||||
<Route path="/~server-error" exact component={ServerError} />
|
||||
|
||||
<Route path="/" exact component={() => <Redirect to="/service-groups" />} />
|
||||
|
||||
<noscript>
|
||||
<ViewContainer main>
|
||||
<Message warning>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
You need to enable JavaScript to run this app.
|
||||
</MessageDescription>
|
||||
</Message>
|
||||
</ViewContainer>
|
||||
</noscript>
|
||||
<Footer />
|
||||
</PageContainer>
|
||||
);
|
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
import { Margin } from 'styled-components-spacing';
|
||||
|
||||
import {
|
||||
RootContainer,
|
||||
PageContainer,
|
||||
ViewContainer,
|
||||
Message,
|
||||
MessageDescription,
|
||||
MessageTitle
|
||||
} from 'joyent-ui-toolkit';
|
||||
|
||||
import Breadcrumb from '@containers/breadcrumb';
|
||||
|
||||
export const Route = () => (
|
||||
<ViewContainer main>
|
||||
<Margin bottom={4}>
|
||||
<Message error>
|
||||
<MessageTitle>Ooops!</MessageTitle>
|
||||
<MessageDescription>
|
||||
An error occurred while loading your page
|
||||
</MessageDescription>
|
||||
</Message>
|
||||
</Margin>
|
||||
</ViewContainer>
|
||||
);
|
||||
|
||||
export default () => (
|
||||
<RootContainer>
|
||||
<PageContainer>
|
||||
<Breadcrumb />
|
||||
<Route />
|
||||
</PageContainer>
|
||||
</RootContainer>
|
||||
);
|
|
@ -0,0 +1,39 @@
|
|||
import { ApolloClient } from 'apollo-client';
|
||||
import { HttpLink } from 'apollo-link-http';
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory';
|
||||
import fetch from 'cross-fetch';
|
||||
|
||||
import global from './global';
|
||||
|
||||
const {
|
||||
REACT_APP_GQL_PORT = global.port,
|
||||
REACT_APP_GQL_PROTOCOL = global.protocol,
|
||||
REACT_APP_GQL_HOSTNAME = global.hostname
|
||||
} = process.env;
|
||||
|
||||
const PORT = REACT_APP_GQL_PORT ? `:${REACT_APP_GQL_PORT}` : '';
|
||||
const URI = `${REACT_APP_GQL_PROTOCOL}://${REACT_APP_GQL_HOSTNAME}${PORT}/service-groups/graphql`;
|
||||
|
||||
export default (opts = {}) => {
|
||||
let cache = new InMemoryCache();
|
||||
|
||||
if (global.__APOLLO_STATE__) {
|
||||
cache = cache.restore(global.__APOLLO_STATE__);
|
||||
}
|
||||
|
||||
return new ApolloClient({
|
||||
cache,
|
||||
link: new HttpLink({
|
||||
uri: URI,
|
||||
credentials: 'same-origin',
|
||||
fetch,
|
||||
headers: {
|
||||
'X-CSRF-Token': global.cookie.replace(
|
||||
/(?:(?:^|.*;\s*)crumb\s*=\s*([^;]*).*$)|^.*$/,
|
||||
'$1'
|
||||
)
|
||||
}
|
||||
}),
|
||||
...opts
|
||||
});
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
import { canUseDOM } from 'exenv';
|
||||
import queryString from 'query-string';
|
||||
|
||||
export const Global = () => {
|
||||
if (!canUseDOM) {
|
||||
return {
|
||||
cookie: ''
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
port: window.location.port,
|
||||
protocol: window.location.protocol.replace(/:$/, ''),
|
||||
hostname: window.location.hostname,
|
||||
pathname: window.location.pathname,
|
||||
origin: window.location.origin,
|
||||
cookie: document.cookie || '',
|
||||
search: window.location.search,
|
||||
query: queryString.parse(window.location.search || ''),
|
||||
__REDUX_DEVTOOLS_EXTENSION__: window.__REDUX_DEVTOOLS_EXTENSION__,
|
||||
__APOLLO_STATE__: window.__APOLLO_STATE__,
|
||||
__REDUX_STATE__: window.__REDUX_STATE__
|
||||
};
|
||||
};
|
||||
|
||||
export default Global();
|
|
@ -0,0 +1,4 @@
|
|||
export default ({ graphQLErrors = [], message = '' }) =>
|
||||
graphQLErrors.length
|
||||
? graphQLErrors.map(({ message }) => message).join('\n')
|
||||
: message;
|
|
@ -0,0 +1,24 @@
|
|||
import { reduxBatch } from '@manaflair/redux-batch';
|
||||
import { createStore, combineReducers, compose } from 'redux';
|
||||
import { reducer as formReducer } from 'redux-form';
|
||||
import { reducer as valuesReducer } from 'react-redux-values';
|
||||
import global from './global';
|
||||
|
||||
export default () => {
|
||||
return createStore(
|
||||
combineReducers({
|
||||
values: valuesReducer,
|
||||
form: formReducer,
|
||||
ui: (state = {}) => state
|
||||
}),
|
||||
global.__REDUX_STATE__ || {},
|
||||
compose(
|
||||
reduxBatch,
|
||||
// If you are using the devToolsExtension, you can add it here also
|
||||
// eslint-disable-next-line no-negated-condition
|
||||
typeof global.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined'
|
||||
? global.__REDUX_DEVTOOLS_EXTENSION__()
|
||||
: f => f
|
||||
)
|
||||
);
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
import { theme } from 'joyent-ui-toolkit';
|
||||
|
||||
const font = theme.font.href({
|
||||
namespace: 'service-groups'
|
||||
});
|
||||
|
||||
const monoFont = theme.monoFont.href({
|
||||
namespace: 'service-groups'
|
||||
});
|
||||
|
||||
export default {
|
||||
...theme,
|
||||
font: {
|
||||
...theme.font,
|
||||
href: () => font
|
||||
},
|
||||
monoFont: {
|
||||
...theme.monoFont,
|
||||
href: () => monoFont
|
||||
}
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"ignore": ["_document.js", "_aliases.js"],
|
||||
"presets": [
|
||||
[
|
||||
"joyent-portal",
|
||||
{
|
||||
"aliases": true,
|
||||
"autoAliases": true
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
lib/app
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"setup": {
|
||||
"compile": "npm run build",
|
||||
"start": "serve -s build --port 3069 --single",
|
||||
"href": "http://0.0.0.0:3069"
|
||||
},
|
||||
"extends": "lighthouse:default"
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
||||
yarn-error.log*
|
||||
|
||||
## Image Snapshots Diff
|
||||
|
||||
**/__diff_output__
|
||||
|
||||
!lib/app
|
||||
!dist
|
||||
!build
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"test": ["./src/**/*.js"],
|
||||
"extends": ["stylelint-config-joyent-portal"]
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"libs": ["ecmascript", "browser"],
|
||||
"plugins": {
|
||||
"doc_comment": true,
|
||||
"local-scope": true,
|
||||
"jsx": true,
|
||||
"node": true,
|
||||
"webpack": {
|
||||
"configPath":
|
||||
"../../node_modules/joyent-react-scripts/src/webpack.config.dev.js"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
const Inert = require('inert');
|
||||
const Path = require('path');
|
||||
const RenderReact = require('hapi-render-react');
|
||||
const Intercept = require('apr-intercept');
|
||||
const Fs = require('mz/fs');
|
||||
|
||||
const { NAMESPACE = 'templates' } = process.env;
|
||||
|
||||
exports.register = async server => {
|
||||
const relativeTo = Path.join(__dirname, 'app');
|
||||
const buildRoot = Path.join(__dirname, `../build/${NAMESPACE}/static/`);
|
||||
const publicRoot = Path.join(__dirname, `../public/static/`);
|
||||
|
||||
await server.register([
|
||||
{
|
||||
plugin: Inert
|
||||
},
|
||||
{
|
||||
plugin: RenderReact
|
||||
}
|
||||
]);
|
||||
|
||||
server.route([
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/service-worker.js`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/service-worker.js')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/favicon.ico`,
|
||||
config: {
|
||||
auth: false,
|
||||
handler: {
|
||||
file: {
|
||||
path: Path.join(__dirname, '../build/favicon.ico')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: 'GET',
|
||||
path: `/${NAMESPACE}/static/{rest*}`,
|
||||
config: {
|
||||
auth: false
|
||||
},
|
||||
handler: async (request, h) => {
|
||||
const { params } = request;
|
||||
const { rest } = params;
|
||||
|
||||
const publicPathname = Path.join(publicRoot, rest);
|
||||
const buildPathname = Path.join(buildRoot, rest);
|
||||
|
||||
const [err] = await Intercept(
|
||||
Fs.access(publicPathname, Fs.constants.R_OK)
|
||||
);
|
||||
|
||||
const file = err ? buildPathname : publicPathname;
|
||||
return h.file(file, { confine: false });
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/~server-error`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'server-error',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
method: '*',
|
||||
path: `/${NAMESPACE}/{path*}`,
|
||||
handler: {
|
||||
view: {
|
||||
name: 'app',
|
||||
relativeTo
|
||||
}
|
||||
}
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
||||
exports.pkg = require('../package.json');
|
|
@ -0,0 +1,53 @@
|
|||
{
|
||||
"name": "my-joy-templates",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"license": "MPL-2.0",
|
||||
"repository": "github:yldio/joyent-portal",
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"dev": "NAMESPACE=templates NODE_ENV=development REACT_APP_GQL_PORT=4000 PORT=3071 joyent-react-scripts start",
|
||||
"build:test": "echo 0",
|
||||
"build:lib": "echo 0",
|
||||
"build:bundle": "NAMESPACE=templates NODE_ENV=production redrun -p build:frontend build:ssr",
|
||||
"prepublish": "NODE_ENV=production redrun build:bundle",
|
||||
"test": "DEFAULT_TIMEOUT_INTERVAL=100000 NODE_ENV=test joyent-react-scripts test --env=jsdom",
|
||||
"test:ci": "NODE_ENV=test joyent-react-scripts test --env=jsdom --testPathIgnorePatterns='.ui.js'",
|
||||
"build:frontend": "joyent-react-scripts build",
|
||||
"build:ssr": "SSR=1 UMD=1 babel src --out-dir lib/app --copy-files"
|
||||
},
|
||||
"dependencies": {
|
||||
"@manaflair/redux-batch": "^0.1.0",
|
||||
"cross-fetch": "^2.1.0",
|
||||
"exenv": "^1.2.2",
|
||||
"hapi-render-react": "^2.5.2",
|
||||
"hapi-render-react-joyent-document": "^5.0.0",
|
||||
"inert": "^5.1.0",
|
||||
"joyent-ui-instance-steps": "^1.0.0",
|
||||
"joyent-ui-resource-step": "^1.0.0",
|
||||
"joyent-ui-toolkit": "^6.0.0",
|
||||
"lodash.get": "^4.4.2",
|
||||
"react": "^16.3.1",
|
||||
"react-apollo": "^2.1.2",
|
||||
"react-dom": "^16.3.1",
|
||||
"react-redux-values": "^1.1.2",
|
||||
"react-router-dom": "^4.2.2",
|
||||
"redux": "^3.7.2",
|
||||
"redux-form": "^7.3.0",
|
||||
"remcalc": "^1.0.10",
|
||||
"styled-components": "^3.2.5",
|
||||
"styled-components-spacing": "^2.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-preset-joyent-portal": "^7.0.1",
|
||||
"eslint": "^4.19.1",
|
||||
"eslint-config-joyent-portal": "^3.3.1",
|
||||
"jest-image-snapshot": "^2.4.0",
|
||||
"jest-styled-components": "^5.0.1",
|
||||
"joyent-react-scripts": "^8.0.3",
|
||||
"react-screenshot-renderer": "^1.1.2",
|
||||
"react-test-renderer": "^16.3.1",
|
||||
"redrun": "^6.0.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="theme-color" content="#1E313B">
|
||||
|
||||
<!-- <link rel="manifest" href="%PUBLIC_URL%/manifest.json"> -->
|
||||
<!-- <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> -->
|
||||
<title>My Joyent β</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header"></div>
|
||||
<div id="root"></div>
|
||||
<script src="/navigation/static/main.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"short_name": "Joyent",
|
||||
"name": "My Joyent β",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"start_url": "./index.html",
|
||||
"display": "standalone",
|
||||
"theme_color": "#1E313B",
|
||||
"background_color": "#FAFAFA"
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Libre Franklin'), local('LibreFranklin-Regular'),
|
||||
url(../fonts/libre-franklin/libre-franklin-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Libre Franklin Medium'), local('LibreFranklin-Medium'),
|
||||
url(../fonts/libre-franklin/libre-franklin-medium.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local('Libre Franklin SemiBold'), local('LibreFranklin-SemiBold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-semibold.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Libre Franklin';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Libre Franklin Bold'), local('LibreFranklin-Bold'),
|
||||
url(../fonts/libre-franklin/libre-franklin-bold.ttf) format('truetype');
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto Mono'), local('RobotoMono-Regular'),
|
||||
url(../fonts/roboto-mono/roboto-mono-regular.ttf) format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Roboto Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Mono Bold'), local('RobotoMono-Bold'),
|
||||
url(../fonts/roboto-mono/roboto-mono-bold.ttf) format('truetype');
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,93 @@
|
|||
Copyright (c) 2015, Impallari Type (www.impallari.com)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue