refactor(instances): refactor create instance flow

fixes #1354
This commit is contained in:
johnytiago 2018-04-12 10:53:00 +01:00 committed by Sérgio Ramos
parent 316773d9b7
commit 32d5cdc293
683 changed files with 25062 additions and 52331 deletions

1
.gitignore vendored
View File

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

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

@ -0,0 +1 @@
{}

View File

@ -5,7 +5,7 @@ const RenderReact = require('hapi-render-react');
const Intercept = require('apr-intercept');
const Fs = require('mz/fs');
const { NAMESPACE = 'images' } = process.env;
const { NAMESPACE = 'images', NODE_ENV = 'development' } = process.env;
exports.register = async server => {
let manifest = {};

View File

@ -15,7 +15,7 @@ import {
PopoverTarget,
Popover,
PopoverItem,
PopoverDivider,
PopoverDivider as BasePopoverDivider,
PopoverContainer,
Radio,
FormLabel,
@ -59,10 +59,6 @@ const Max = styled(Flex)`
height: 100%;
`;
const DividerContainer = styled(Margin)`
height: 100%;
`;
const Actions = styled(Flex)`
width: ${remcalc(48)};
height: ${remcalc(48)};
@ -71,9 +67,14 @@ const Actions = styled(Flex)`
const ActionsWrapper = styled(Flex)`
height: 100%;
width: 100%;
border-left: ${remcalc(1)} solid ${props => props.theme.grey};
`;
const PopoverDivider = styled(BasePopoverDivider)`
width: 100%;
`;
export const Image = ({
name,
id,
@ -113,10 +114,8 @@ export const Image = ({
<Max justifyBetween>
<Max alignCenter>
<Flex>{version}</Flex>
<DividerContainer left={2}>
<Divider width={remcalc(1)} height="100%" />
</DividerContainer>
<Type left={2}>{ImageType[type]}</Type>
<Divider vertical />
<Type>{ImageType[type]}</Type>
</Max>
</Max>
</Content>
@ -127,22 +126,26 @@ export const Image = ({
<ActionsIcon />
</ActionsWrapper>
</PopoverTarget>
<Popover placement="bottom">
<PopoverItem disabled={false} onClick={onCreateInstance}>
<ItemAnchor
href={`${
GLOBAL.origin
}/instances/~create/?image=${name}`}
target="__blank"
rel="noopener noreferrer"
>
Create Instance
</ItemAnchor>
</PopoverItem>
<Popover noPadding placement="bottom">
<Padding horizontal={3} vertical={2}>
<PopoverItem disabled={false} onClick={onCreateInstance}>
<ItemAnchor
href={`${
GLOBAL.origin
}/instances/~create/?image=${name}`}
target="__blank"
rel="noopener noreferrer"
>
Create Instance
</ItemAnchor>
</PopoverItem>
</Padding>
<PopoverDivider />
<PopoverItem disabled={removing} onClick={onRemove}>
Remove
</PopoverItem>
<Padding horizontal={3} vertical={2}>
<PopoverItem disabled={removing} onClick={onRemove}>
Remove
</PopoverItem>
</Padding>
</Popover>
</Actions>
</PopoverContainer>
@ -157,9 +160,9 @@ export const Image = ({
export const Filters = ({ selected }) => (
<Fragment>
<FormGroup name="image-type" value="all" field={Field} type="radio">
<Radio noMargin>
<Radio>
<Flex alignCenter>
<Margin right={2}>
<Margin horizontal={2}>
<FormLabel big normal={selected !== 'all'}>
All
</FormLabel>
@ -175,7 +178,7 @@ export const Filters = ({ selected }) => (
>
<Radio noMargin>
<Flex alignCenter>
<Margin right={2}>
<Margin horizontal={2}>
<FormLabel big normal={selected !== 'hardware-virtual-machine'}>
Virtual machines
</FormLabel>
@ -191,7 +194,7 @@ export const Filters = ({ selected }) => (
>
<Radio noMargin>
<Flex alignCenter>
<Margin right={2}>
<Margin horizontal={2}>
<FormLabel big normal={selected !== 'infrastructure-container'}>
Infrastructure container
</FormLabel>

View File

@ -1,7 +1,7 @@
import React from 'react';
import forceArray from 'force-array';
import { Margin } from 'styled-components-spacing';
import { NavLink } from 'react-router-dom';
import forceArray from 'force-array';
import {
SectionList,

View File

@ -104,7 +104,7 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
<Col xs={12} sm={12} md={9}>
<Card>
<CardOutlet>
<Padding all={4}>
<Padding all={5}>
<Meta {...image} />
<Row between="xs">
<Col xs={9}>
@ -124,7 +124,6 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
bold
icon
>
<DuplicateIcon light />
<span>Create Instance</span>
</Button>
</Medium>
@ -145,7 +144,9 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
error
right
>
<DeleteIcon fill={theme.red} />
<Margin right="1">
<DeleteIcon fill={theme.red} />
</Margin>
<span>Remove</span>
</Button>
</Medium>
@ -157,17 +158,23 @@ export default withTheme(({ theme = {}, onRemove, removing, ...image }) => (
<Margin bottom="2">
<P>{image.description}</P>
</Margin>
<CopiableField text={(image.id || '').split('-')[0]} label="ID" />
<CopiableField text={image.id} label="UUID" />
<Margin bottom={3}>
<CopiableField text={(image.id || '').split('-')[0]} label="ID" />
</Margin>
<Margin bottom={3}>
<CopiableField text={image.id} label="UUID" />
</Margin>
<Row>
<Col xs={12} md={7}>
<FormLabel>Operating system</FormLabel>
<Input
monospace
onBlur={null}
fluid
value={titleCase(image.os)}
/>
<Margin bottom={3}>
<FormLabel>Operating system</FormLabel>
<Input
monospace
onBlur={null}
fluid
value={titleCase(image.os)}
/>
</Margin>
</Col>
</Row>
</Padding>

View File

@ -2,15 +2,8 @@ import React from 'react';
import { Field } from 'redux-form';
import Flex from 'styled-flex-component';
import { Margin } from 'styled-components-spacing';
import remcalc from 'remcalc';
import {
Button,
FormGroup,
Input,
FormLabel,
Divider
} from 'joyent-ui-toolkit';
import { Button, FormGroup, Input, FormLabel } from 'joyent-ui-toolkit';
export const Toolbar = ({
searchable = true,
@ -21,7 +14,7 @@ export const Toolbar = ({
actionable = false,
onActionClick
}) => (
<Flex justifyBetween>
<Flex justifyBetween alignEnd>
<FormGroup name="filter" field={Field}>
<FormLabel>{searchLabel}</FormLabel>
<Margin top={0.5}>
@ -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>
);

View File

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

View File

@ -66,7 +66,7 @@ export const Tags = ({
) : null}
{proceeded || expanded ? (
<Fragment>
<Margin bottom={4}>
<Margin bottom={5}>
<H3>
{tags.length} Tag{tags.length === 1 ? '' : 's'}
</H3>

View File

@ -54,7 +54,7 @@ const Create = ({
</Margin>
) : null}
{!loading && !loadingError ? (
<Margin top={4} bottom={4}>
<Margin top={4} bottom={5}>
<H2>Create Image</H2>
</Margin>
) : null}

View File

@ -11,6 +11,7 @@ import { set } from 'react-redux-values';
import Fuse from 'fuse.js';
import {
H3,
ViewContainer,
Divider,
StatusLoader,
@ -41,12 +42,17 @@ export const List = ({
handleRemove
}) => (
<ViewContainer main>
<Divider height={remcalc(30)} transparent />
<ReduxForm form={LIST_TOOLBAR_FORM}>
{props => <ToolbarForm {...props} actionable={!loading} />}
</ReduxForm>
<Divider height={remcalc(1)} />
<Divider height={remcalc(24)} transparent />
<Margin top={5}>
<H3>Images</H3>
</Margin>
<Margin top={4}>
<ReduxForm form={LIST_TOOLBAR_FORM}>
{props => <ToolbarForm {...props} actionable={!loading} />}
</ReduxForm>
</Margin>
<Margin vertical={4}>
<Divider />
</Margin>
{loading && !images.length ? (
<Fragment>
<Divider height={remcalc(30)} transparent />
@ -54,7 +60,7 @@ export const List = ({
</Fragment>
) : null}
{error && !images.length && !loading ? (
<Margin bottom={4}>
<Margin bottom={5}>
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>

View File

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

View File

@ -56,12 +56,14 @@ export const Tags = ({
onActionClick={handleToggleAddOpen}
action
/>
<Divider height={remcalc(1)} />
<Margin vertical="4">
<Divider height={remcalc(1)} />
</Margin>
</Margin>
)}
</ReduxForm>
{error && !loading && !tags.length ? (
<Margin bottom={4}>
<Margin bottom={5}>
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>
@ -71,7 +73,7 @@ export const Tags = ({
</Margin>
) : null}
{mutationError ? (
<Margin bottom={4}>
<Margin bottom={5}>
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>{mutationError}</MessageDescription>
@ -80,13 +82,13 @@ export const Tags = ({
) : null}
<ReduxForm
form={TAGS_ADD_FORM}
asyncValidate={handleAsyncValidate}
shouldAsyncValidate={shouldAsyncValidate}
asyncValidate={handleAsyncValidate}
onSubmit={handleAddTag}
>
{props =>
addOpen ? (
<Margin bottom={4}>
<Margin bottom={5}>
<AddForm
{...props}
onToggleExpanded={() => handleToggleAddOpen(!addOpen)}
@ -97,7 +99,7 @@ export const Tags = ({
}
</ReduxForm>
{!loading ? (
<Margin bottom={4}>
<Margin bottom={5}>
<H3>
{tags.length} tag{tags.length === 1 ? '' : 's'}
</H3>
@ -105,9 +107,10 @@ export const Tags = ({
) : null}
{loading && !tags.length ? <StatusLoader /> : null}
<TagList>
{tags.map(({ name, value }) => (
{tags.map(({ id, name, value }) => (
<Tag
key={value}
key={id}
id={id}
name={name}
value={value}
onRemoveClick={!mutating && (() => handleRemoveTag(name))}

View File

@ -10,12 +10,11 @@ module.exports = ({
<head>
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="theme-color" content="#1E313B" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
/>
<meta name="theme-color" content="#1E313B" />
{head}
</head>

View File

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

View File

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

View File

@ -14,14 +14,16 @@ const validateField = async (field, value) => {
const validateSchema = async (schema, value) => {
const errors = await reduce(
keys(schema),
async (errors, name) =>
assign(errors, {
[name]: await validateField(schema[name], value[name])
}),
async (errors, name) => {
const msg = await validateField(schema[name], value[name]);
return !msg ? errors : assign(errors, { [name]: msg });
},
{}
);
throw errors;
if (keys(errors).length) {
throw errors;
}
};
/*****************************************************************************/
@ -61,7 +63,10 @@ const Schemas = {
/*****************************************************************************/
export const addTag = tag => validateSchema(Schemas.tag, tag);
export const addTag = tag => {
console.log(tag);
validateSchema(Schemas.tag, tag);
};
export const instanceName = ({ name }) =>
!name ? null : validateSchema(Schemas.instanceName, { name });

View File

@ -38,6 +38,7 @@
"hapi-render-react-joyent-document": "^7.1.0",
"inert": "^5.1.0",
"joyent-logo-assets": "^1.1.0",
"joyent-ui-resource-step": "^1.0.0",
"joyent-manifest-editor": "^1.4.0",
"joyent-react-styled-flexboxgrid": "^2.2.3",
"joyent-ui-toolkit": "^6.0.0",

View File

@ -1,6 +1,5 @@
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');

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