Skip to content

Commit 537be23

Browse files
author
Ives van Hoorne
committed
UI
1 parent 1346093 commit 537be23

File tree

11 files changed

+279
-14
lines changed

11 files changed

+279
-14
lines changed

src/app/components/ZeitLogo.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React from 'react';
2+
import IconBase from 'react-icons/IconBase';
3+
4+
export default () => (
5+
<IconBase viewBox="0 0 226 200">
6+
<defs>
7+
<linearGradient
8+
x1="196.572434%"
9+
y1="228.815483%"
10+
x2="50%"
11+
y2="50%"
12+
id="l1"
13+
>
14+
<stop style={{ stopColor: '#000' }} offset="0%" />
15+
<stop style={{ stopColor: '#fff' }} offset="100%" />
16+
</linearGradient>
17+
</defs>
18+
<g stroke="none" strokeWidth="1" fillRule="evenodd">
19+
<g transform="translate(-141.000000, -156.000000)" fill="url(#l1)">
20+
<polygon points="254 156.459299 367 356 141 356 " />
21+
</g>
22+
</g>
23+
</IconBase>
24+
);
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
4+
import CrossIcon from 'react-icons/lib/md/clear';
5+
import ChevronIcon from 'react-icons/lib/md/keyboard-arrow-right';
6+
import Margin from 'app/components/spacing/Margin';
7+
import Tooltip from 'app/components/Tooltip';
8+
9+
const Container = styled.div`
10+
display: inline-flex;
11+
border-radius: 4px;
12+
overflow: hidden;
13+
`;
14+
15+
const IntegrationBlock = styled.div`
16+
display: inline-flex;
17+
18+
align-items: center;
19+
20+
background-color: ${props => props.bgColor};
21+
22+
color: white;
23+
24+
font-size: 1.25rem;
25+
26+
padding: 1rem 1.5rem;
27+
`;
28+
29+
const Details = styled.div`
30+
display: inline-flex;
31+
justify-content: center;
32+
align-items: center;
33+
padding: 0.75rem 1rem;
34+
background-color: rgba(0, 0, 0, 0.3);
35+
`;
36+
37+
const Name = styled.span`
38+
margin-left: 0.75rem;
39+
font-size: 1.375rem;
40+
`;
41+
42+
const Heading = styled.div`
43+
color: rgba(255, 255, 255, 0.5);
44+
font-size: 0.75rem;
45+
margin-bottom: 0.25rem;
46+
`;
47+
48+
const Info = styled.div`font-weight: 400;`;
49+
50+
const Action = styled.div`
51+
display: flex;
52+
transition: 0.3s ease all;
53+
border: 1px solid
54+
${props => (props.red ? 'rgba(255, 0, 0, 0.4)' : props.theme.secondary)};
55+
border-radius: 4px;
56+
57+
justify-content: center;
58+
align-items: center;
59+
60+
color: ${props => (props.red ? 'rgba(255, 0, 0, 0.6)' : 'white')};
61+
62+
background-color: ${props =>
63+
props.red ? 'transparent' : props.theme.secondary};
64+
65+
opacity: 0.8;
66+
cursor: pointer;
67+
68+
height: 1.5rem;
69+
width: 1.5rem;
70+
71+
&:hover {
72+
opacity: 1;
73+
74+
color: white;
75+
background-color: ${props =>
76+
props.red ? 'rgba(255, 0, 0, 0.6)' : props.theme.secondary};
77+
}
78+
`;
79+
80+
type DetailProps = {
81+
heading: string,
82+
info: string,
83+
signOut: ?Function,
84+
signIn: ?Function,
85+
};
86+
87+
const DetailInfo = ({ heading, info, signOut, signIn }: DetailProps) => (
88+
<Details>
89+
<Margin right={2}>
90+
<Heading>{heading}</Heading>
91+
<Info>{info}</Info>
92+
</Margin>
93+
94+
{signOut ? (
95+
<Tooltip title="Sign out">
96+
<Action onClick={signOut} red>
97+
<CrossIcon />
98+
</Action>
99+
</Tooltip>
100+
) : (
101+
<Tooltip title="Sign in">
102+
<Action onClick={signIn}>
103+
<ChevronIcon />
104+
</Action>
105+
</Tooltip>
106+
)}
107+
</Details>
108+
);
109+
110+
type Props = {
111+
Icon: React.CElement,
112+
name: string,
113+
color: string,
114+
description: string,
115+
loggedIn: boolean,
116+
};
117+
118+
export default ({ Icon, name, description, color, loggedIn }: Props) => (
119+
<Container>
120+
<IntegrationBlock bgColor={color}>
121+
<Icon />
122+
<Name>{name}</Name>
123+
</IntegrationBlock>
124+
{!loggedIn ? (
125+
<DetailInfo
126+
signOut={() => {}}
127+
heading="Signed in as"
128+
129+
/>
130+
) : (
131+
<DetailInfo signIn={() => {}} heading="Enables" info={description} />
132+
)}
133+
</Container>
134+
);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
3+
import ZeitLogo from 'app/components/ZeitLogo';
4+
5+
import Integration from './Integration';
6+
7+
export default () => (
8+
<div>
9+
<Integration
10+
name="ZEIT"
11+
color="black"
12+
description="Deployments"
13+
Icon={ZeitLogo}
14+
/>
15+
</div>
16+
);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
3+
import Title from '../MenuTitle';
4+
5+
import Integrations from './Integrations';
6+
7+
export default () => (
8+
<div>
9+
<Title>Integrations</Title>
10+
11+
<Integrations />
12+
</div>
13+
);

src/app/containers/Preferences/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import CreditCardIcon from 'react-icons/lib/md/credit-card';
1010
import BrowserIcon from 'react-icons/lib/go/browser';
1111
import StarIcon from 'react-icons/lib/go/star';
1212
import CodeFormatIcon from 'react-icons/lib/fa/dedent';
13+
import IntegrationIcon from 'react-icons/lib/md/device-hub';
1314

1415
import SideNavigation from './SideNavigation';
1516

1617
import EditorSettings from './EditorPageSettings/EditorSettings';
1718
import PreviewSettings from './EditorPageSettings/PreviewSettings';
1819
import CodeFormatting from './CodeFormatting';
1920
import PaymentInfo from './PaymentInfo';
21+
import Integrations from './Integrations';
2022
import Badges from './Badges';
2123

2224
const Container = styled.div`
@@ -51,6 +53,7 @@ class Preferences extends React.PureComponent {
5153

5254
getItems = () => {
5355
const hasSubscription = Boolean(this.props.user.subscription);
56+
const signedIn = Boolean(this.props.user.jwt);
5457
return [
5558
{
5659
title: 'Editor',
@@ -67,6 +70,11 @@ class Preferences extends React.PureComponent {
6770
icon: <BrowserIcon />,
6871
content: <PreviewSettings />,
6972
},
73+
signedIn && {
74+
title: 'Integrations',
75+
icon: <IntegrationIcon />,
76+
content: <Integrations />,
77+
},
7078
hasSubscription && {
7179
title: 'Payment Info',
7280
icon: <CreditCardIcon />,

src/app/pages/Sandbox/Editor/Content/Header/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Download from 'react-icons/lib/go/cloud-download';
99
import PlusIcon from 'react-icons/lib/go/plus';
1010
import GithubIcon from 'react-icons/lib/go/mark-github';
1111
import ChevronLeft from 'react-icons/lib/md/chevron-left';
12+
import ZeitIcon from 'app/components/ZeitLogo';
1213
import HeartIcon from 'react-icons/lib/fa/heart-o';
1314
import FullHeartIcon from 'react-icons/lib/fa/heart';
1415
import TwitterIcon from 'react-icons/lib/fa/twitter';
@@ -31,6 +32,8 @@ import UserMenu from 'app/containers/UserMenu';
3132
import Preferences from 'app/containers/Preferences';
3233
import NewSandbox from 'app/containers/modals/NewSandbox';
3334

35+
import deploy from 'app/store/entities/sandboxes/utils/deploy';
36+
3437
import Action from './Action';
3538
import FeedbackView from './FeedbackView';
3639
import ShareView from './ShareView';
@@ -104,6 +107,11 @@ export default class Header extends React.PureComponent<Props> {
104107
sandboxActions.massUpdateModules(sandbox.id);
105108
};
106109

110+
deploySandbox = () => {
111+
const { sandbox, sandboxActions } = this.props;
112+
sandboxActions.deploy(sandbox.id);
113+
};
114+
107115
zipSandbox = () => {
108116
const { sandbox, sandboxActions } = this.props;
109117
sandboxActions.createZip(sandbox.id);
@@ -215,6 +223,7 @@ export default class Header extends React.PureComponent<Props> {
215223
Icon={Save}
216224
/>
217225
<Action title="Download" Icon={Download} onClick={this.zipSandbox} />
226+
<Action title="Deploy" Icon={ZeitIcon} onClick={this.deploySandbox} />
218227
<ShareView sandbox={sandbox} />
219228
</Left>
220229

src/app/store/entities/sandboxes/actions/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const SET_CURRENT_MODULE = 'SET_CURRENT_MODULE';
5151
export const SET_PROJECT_VIEW = 'SET_PROJECT_VIEW';
5252
export const SET_VIEW_MODE = 'SET_VIEW_MODE';
5353
export const CREATE_ZIP = 'CREATE_ZIP';
54+
export const DEPLOY_SANDBOX = 'DEPLOY_SANDBOX';
5455
export const SET_SANDBOX_PRIVACY = 'SET_SANDBOX_PRIVACY';
5556
export const FORCE_RENDER = 'FORCE_RENDER';
5657

@@ -325,6 +326,24 @@ export default {
325326
);
326327
},
327328

329+
deploy: (id: string) => async (dispatch: Function, getState: Function) => {
330+
dispatch({
331+
type: DEPLOY_SANDBOX,
332+
id,
333+
});
334+
const modules = modulesSelector(getState());
335+
const directories = directoriesSelector(getState());
336+
const sandbox = singleSandboxSelector(getState(), { id });
337+
338+
const deploy = await import('../utils/deploy');
339+
340+
deploy.default(
341+
sandbox,
342+
sandbox.modules.map(x => modules[x]),
343+
sandbox.directories.map(x => directories[x])
344+
);
345+
},
346+
328347
deleteSandbox: (id: string) => async (dispatch: Function) => {
329348
await dispatch(
330349
doRequest(DELETE_SANDBOX_API_ACTIONS, `sandboxes/${id}`, {

src/app/store/entities/sandboxes/utils/create-zip/create-react-app-typescript/index.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ export default function createZip(
7373
getHTML(modules, sandbox.externalResources)
7474
);
7575

76-
if (
77-
!modules.find(x => x.directoryShortid == null && x.title === 'README.md')
78-
) {
79-
zip.file('README.md', files['./README.md']);
80-
}
8176
zip.file(
8277
'package.json',
8378
createPackageJSON(

src/app/store/entities/sandboxes/utils/create-zip/create-react-app/index.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,6 @@ export default function createZip(
7373
getHTML(modules, sandbox.externalResources)
7474
);
7575

76-
if (
77-
!modules.find(x => x.directoryShortid == null && x.title === 'README.md')
78-
) {
79-
zip.file('README.md', files['./README.md']);
80-
}
8176
zip.file(
8277
'package.json',
8378
createPackageJSON(

src/app/store/entities/sandboxes/utils/create-zip/index.js

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ function slugify(text) {
5353

5454
export function createPackageJSON(
5555
sandbox: Sandbox,
56-
dependencies,
57-
devDependencies,
58-
scripts,
56+
dependencies: Object,
57+
devDependencies: Object,
58+
scripts: Object,
5959
extra: Object
6060
) {
6161
const name = slugify(sandbox.title || sandbox.id);
@@ -93,7 +93,7 @@ export function createDirectoryWithFiles(
9393
.forEach(x => createDirectoryWithFiles(modules, directories, x, newZip));
9494
}
9595

96-
export default (async function createZip(
96+
export async function createZip(
9797
sandbox: Sandbox,
9898
modules: Array<Module>,
9999
directories: Array<Directory>
@@ -122,9 +122,25 @@ export default (async function createZip(
122122
generator.default(zip, sandbox, modules, directories)
123123
);
124124
}
125+
125126
if (promise) {
126127
await promise;
127128
const file = await zip.generateAsync({ type: 'blob' });
129+
130+
return file;
131+
}
132+
133+
return null;
134+
}
135+
136+
export default (async function downloadZip(
137+
sandbox: Sandbox,
138+
modules: Array<Module>,
139+
directories: Array<Directory>
140+
) {
141+
const file = await createZip(sandbox, modules, directories);
142+
143+
if (file) {
128144
saveAs(file, `${slugify(sandbox.title || sandbox.id)}.zip`);
129145
}
130146
});

0 commit comments

Comments
 (0)