diff --git a/packages/app/src/app/components/DeploymentIntegration/DeploymentIntegration.tsx b/packages/app/src/app/components/DeploymentIntegration/DeploymentIntegration.tsx
new file mode 100644
index 00000000000..80fb7490167
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/DeploymentIntegration.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+
+import { DetailInfo } from './DetailInfo';
+import {
+ Container,
+ Down,
+ IntegrationBlock,
+ Name,
+ Notice,
+ Up,
+} from './elements';
+
+export const DeploymentIntegration = ({
+ beta = false,
+ children,
+ color,
+ deploy,
+ Icon,
+ light = false,
+ loading = false,
+ name,
+ open = true,
+ toggle,
+}) => (
+
+
+
+
+
+ {name}
+
+ {beta && Beta}
+
+
+ {open ? : }
+
+
+ {open ? (
+
+ ) : null}
+
+);
diff --git a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/DetailInfo.tsx b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/DetailInfo.tsx
new file mode 100644
index 00000000000..a313c44f4e1
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/DetailInfo.tsx
@@ -0,0 +1,17 @@
+import Margin from '@codesandbox/common/lib/components/spacing/Margin';
+import { Button } from '@codesandbox/common/lib/components/Button';
+import React from 'react';
+
+import { Details, Info } from './elements';
+
+export const DetailInfo = ({ info, deploy, bgColor, light, loading }) => (
+
+
+ {info}
+
+
+
+
+);
diff --git a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.js b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.js
deleted file mode 100644
index a0536cc1338..00000000000
--- a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import styled from 'styled-components';
-
-export const Details = styled.div`
- display: inline-flex;
- justify-content: space-between;
- align-items: center;
- flex: 3;
- padding: 0.75rem 1rem;
- background-color: ${props => props.bgColor};
- margin-top: -1px;
-`;
-
-export const Heading = styled.div`
- color: ${props => (props.light ? 'rgba(0, 0, 0)' : 'rgba(255, 255, 255)')};
- font-size: 0.75rem;
- margin-bottom: 0.25rem;
-`;
-
-export const Info = styled.div`
- font-weight: 400;
- color: ${props => (props.light ? 'rgba(0, 0, 0)' : 'rgba(255, 255, 255)')};
-`;
diff --git a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.ts b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.ts
new file mode 100644
index 00000000000..65ca606f251
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/elements.ts
@@ -0,0 +1,28 @@
+import styled, { css } from 'styled-components';
+
+export const Details = styled.div<{ bgColor: string }>`
+ ${({ bgColor }) => css`
+ display: inline-flex;
+ justify-content: space-between;
+ align-items: center;
+ flex: 3;
+ padding: 0.75rem 1rem;
+ background-color: ${bgColor};
+ margin-top: -1px;
+ `}
+`;
+
+export const Heading = styled.div<{ light: boolean }>`
+ ${({ light }) => css`
+ color: ${light ? '#000000' : '#ffffff'};
+ font-size: 0.75rem;
+ margin-bottom: 0.25rem;
+ `}
+`;
+
+export const Info = styled.div<{ light: boolean }>`
+ ${({ light }) => css`
+ color: ${light ? '#000000' : '#ffffff'};
+ font-weight: 400;
+ `}
+`;
diff --git a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.js b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.js
deleted file mode 100644
index b4178879c12..00000000000
--- a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import Margin from '@codesandbox/common/lib/components/spacing/Margin';
-import { Button } from '@codesandbox/common/lib/components/Button';
-
-import { Details, Info } from './elements';
-
-function DetailInfo({ info, deploy, bgColor, light, loading }) {
- return (
-
-
- {info}
-
-
-
- );
-}
-
-export default DetailInfo;
diff --git a/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.ts b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.ts
new file mode 100644
index 00000000000..ce08e94b82d
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/DetailInfo/index.ts
@@ -0,0 +1 @@
+export { DetailInfo } from './DetailInfo';
diff --git a/packages/app/src/app/components/DeploymentIntegration/elements.js b/packages/app/src/app/components/DeploymentIntegration/elements.js
deleted file mode 100644
index fec2bf88ca0..00000000000
--- a/packages/app/src/app/components/DeploymentIntegration/elements.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import styled, { css } from 'styled-components';
-
-export const Container = styled.div`
- display: inline-flex;
- border-radius: 4px;
- overflow: hidden;
- width: 100%;
- flex-direction: column;
- font-size: 0.875rem;
-
- color: ${props =>
- props.light || props.theme.light ? 'rgba(0, 0, 0)' : 'rgba(255, 255, 255)'};
-
- ${props =>
- props.loading &&
- css`
- opacity: 0.5;
- pointer-events: none;
- `};
-`;
-
-export const IntegrationBlock = styled.div`
- display: inline-flex;
- align-items: center;
- cursor: pointer;
- box-sizing: border-box;
- background-color: ${props => props.bgColor};
- flex: 1;
- color: white;
- padding: 0.75em 0.75em;
- min-height: 45px;
- font-size: 1em;
- justify-content: space-between;
-
- > div {
- display: flex;
- align-items: center;
- }
-`;
-
-export const Name = styled.span`
- margin-left: 0.75em;
- font-size: 1.375em;
- color: ${props => (props.light ? 'rgba(0, 0, 0)' : 'rgba(255, 255, 255)')};
-`;
diff --git a/packages/app/src/app/components/DeploymentIntegration/elements.ts b/packages/app/src/app/components/DeploymentIntegration/elements.ts
new file mode 100644
index 00000000000..c7a6b7cfc1a
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/elements.ts
@@ -0,0 +1,68 @@
+import BaseNotice from '@codesandbox/common/lib/components/Notice';
+import BaseDown from 'react-icons/lib/fa/angle-down';
+import BaseUp from 'react-icons/lib/fa/angle-up';
+import styled, { css } from 'styled-components';
+
+export const Container = styled.div`
+ ${({ theme }) => css`
+ display: inline-flex;
+ border-radius: 4px;
+ overflow: hidden;
+ width: 100%;
+ flex-direction: column;
+ font-size: 0.875rem;
+
+ color: ${theme.light ? '#000000' : '#ffffff'};
+ `}
+`;
+
+export const Down = styled(BaseDown)<{ light: boolean }>`
+ ${({ light }) => css`
+ fill: ${light ? '#000000' : '#ffffff'};
+ cursor: pointer;
+ width: 1.5rem;
+ height: auto;
+ `}
+`;
+
+export const IntegrationBlock = styled.div<{ bgColor: string }>`
+ ${({ bgColor }) => css`
+ display: inline-flex;
+ align-items: center;
+ cursor: pointer;
+ box-sizing: border-box;
+ background-color: ${bgColor};
+ flex: 1;
+ color: white;
+ padding: 0.75em 0.75em;
+ min-height: 45px;
+ font-size: 1em;
+ justify-content: space-between;
+
+ > div {
+ display: flex;
+ align-items: center;
+ }
+ `}
+`;
+
+export const Name = styled.span<{ light: boolean }>`
+ ${({ light }) => css`
+ margin-left: 0.75em;
+ font-size: 1.375em;
+ color: ${light ? '#000000' : '#ffffff'};
+ `}
+`;
+
+export const Notice = styled(BaseNotice)`
+ margin-left: 0.7rem;
+`;
+
+export const Up = styled(BaseUp)<{ light: boolean }>`
+ ${({ light }) => css`
+ fill: ${light ? '#000000' : '#ffffff'};
+ cursor: pointer;
+ width: 1.5rem;
+ height: auto;
+ `}
+`;
diff --git a/packages/app/src/app/components/DeploymentIntegration/index.js b/packages/app/src/app/components/DeploymentIntegration/index.js
deleted file mode 100644
index b50e5ab9dee..00000000000
--- a/packages/app/src/app/components/DeploymentIntegration/index.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import React from 'react';
-import Down from 'react-icons/lib/fa/angle-down';
-import Up from 'react-icons/lib/fa/angle-up';
-import Notice from '@codesandbox/common/lib/components/Notice';
-import DetailInfo from './DetailInfo';
-import { Container, IntegrationBlock, Name } from './elements';
-
-const Integration = ({
- light,
- Icon,
- name,
- deploy,
- children,
- loading,
- beta,
- color,
- open = true,
- toggle,
-}) => (
-
-
-
-
- {name}
- {beta && (
-
- Beta
-
- )}
-
- {open ? (
-
- ) : (
-
- )}
-
- {open ? (
-
- ) : null}
-
-);
-
-export default Integration;
diff --git a/packages/app/src/app/components/DeploymentIntegration/index.ts b/packages/app/src/app/components/DeploymentIntegration/index.ts
new file mode 100644
index 00000000000..39a6f994236
--- /dev/null
+++ b/packages/app/src/app/components/DeploymentIntegration/index.ts
@@ -0,0 +1 @@
+export { DeploymentIntegration } from './DeploymentIntegration';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/index.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/index.tsx
index a9ffa87f0ba..99987e33db3 100644
--- a/packages/app/src/app/pages/Sandbox/Editor/Workspace/index.tsx
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/index.tsx
@@ -1,20 +1,25 @@
import VERSION from '@codesandbox/common/lib/version';
import { observer } from 'mobx-react-lite';
import React from 'react';
+// Fix css prop types in styled-components (see https://github.com/DefinitelyTyped/DefinitelyTyped/issues/31245#issuecomment-463640878)
+import * as CSSProps from 'styled-components/cssprop'; // eslint-disable-line
+
import SocialInfo from 'app/components/SocialInfo';
import { useStore } from 'app/store';
import getWorkspaceItems, {
getDisabledItems,
} from 'app/store/modules/workspace/items';
+
+import ConfigurationFiles from './items/ConfigurationFiles';
+import { Deployment } from './items/Deployment';
import Files from './items/Files';
import { GitHub } from './items/GitHub';
-import Server from './items/Server';
import Live from './items/Live';
import { More } from './items/More';
-import Deployment from './items/Deployment';
-import ConfigurationFiles from './items/ConfigurationFiles';
import { NotOwnedSandboxInfo } from './items/NotOwnedSandboxInfo';
import { ProjectInfo } from './items/ProjectInfo';
+import Server from './items/Server';
+
import { Advertisement } from './Advertisement';
import Chat from './Chat';
import { ConnectionNotice } from './ConnectionNotice';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Deployment.tsx
similarity index 63%
rename from packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.tsx
rename to packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Deployment.tsx
index 86b8b20a43b..41d6c892b15 100644
--- a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.tsx
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Deployment.tsx
@@ -1,27 +1,33 @@
-import React, { useEffect } from 'react';
import { observer } from 'mobx-react-lite';
+import React, { useEffect } from 'react';
import { useStore, useSignals } from 'app/store';
+
import { Description } from '../../elements';
-import ZeitDeployments from './Zeit';
-import NetlifyDeployments from './Netlify';
+
import { More } from '../More';
-const Deployment = observer(() => {
- const store = useStore();
- const signals = useSignals();
+import { Netlify } from './Netlify';
+import { Zeit } from './Zeit';
- const showPlaceholder =
- !store.editor.currentSandbox.owned || !store.isLoggedIn;
+export const Deployment = observer(() => {
+ const {
+ editor: { currentSandbox },
+ isLoggedIn,
+ } = useStore();
+ const {
+ deployment: { getDeploys },
+ } = useSignals();
+ const showPlaceholder = !(currentSandbox.owned && isLoggedIn);
useEffect(() => {
if (!showPlaceholder) {
- signals.deployment.getDeploys();
+ getDeploys();
}
- }, [showPlaceholder, signals]);
+ }, [getDeploys, showPlaceholder]);
if (showPlaceholder) {
- const message = store.isLoggedIn ? (
+ const message = isLoggedIn ? (
<>
You need to own this sandbox to deploy this sandbox to Netlify or ZEIT.{' '}
Fork this sandbox to make a deploy!
@@ -39,10 +45,10 @@ const Deployment = observer(() => {
You can deploy a production version of your sandbox using one our
supported providers.
-
-
+
+
+
+
);
});
-
-export default Deployment;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Elements.js b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Elements.js
deleted file mode 100644
index c73e8a26046..00000000000
--- a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Elements.js
+++ /dev/null
@@ -1,129 +0,0 @@
-import styled, { css } from 'styled-components';
-
-const mapColorToState = (state, theme) => {
- const STARTING = ['DEPLOYING', 'BUILDING', 'INITIALIZING'];
- const ERROR = ['DEPLOYMENT_ERROR', 'BUILD_ERROR', 'ERROR'];
- const STARTED = ['BOOTED', 'READY'];
-
- if (STARTING.includes(state)) return '#fccb7e';
- if (ERROR.includes(state)) return theme.red;
- if (STARTED.includes(state)) return theme.green;
- if (state === 'FROZEN') return theme.blue;
-
- return theme.gray;
-};
-
-export const State = styled.span`
- align-items: center;
- display: flex;
- text-transform: capitalize;
- margin-bottom: 0.5rem;
-
- &:before {
- content: '';
- display: block;
- width: 10px;
- height: 10px;
- border-radius: 50%;
- margin-right: 0.5rem;
- background: ${props => mapColorToState(props.state, props.theme)};
- }
-`;
-
-export const Deploys = styled.ul`
- list-style: none;
- padding: 0;
- margin-top: 1rem;
- flex-direction: column;
- font-size: 0.875rem;
- margin: 0 0.25rem;
-`;
-
-export const Deploy = styled.li`
- display: flex;
- margin-bottom: 1.5rem;
- flex-direction: column;
-`;
-
-export const Name = styled.span`
- font-weight: 600;
- color: ${props =>
- props.theme.light || props.light
- ? 'rgba(0, 0, 0, 0.8)'
- : 'rgba(255, 255, 255, 0.8)'};
- font-size: 1rem;
- margin-top: 0;
- vertical-align: middle;
-
- span {
- color: ${props =>
- props.theme.light || props.light
- ? props.theme.background3.darken(0.5)
- : props.theme.background3.lighten(0.5)};
- font-size: 12px;
- margin-left: 0.5rem;
- }
-`;
-
-export const Link = styled.a`
- padding: 0.25rem 0.4rem;
- background-color: ${props => props.theme.secondary};
- text-decoration: none;
- border: none;
- font-size: 0.75rem;
- color: white;
- border-radius: 2px;
- font-weight: 600;
- margin-top: 0.75rem;
- display: flex;
- align-items: center;
- flex-grow: 0;
- max-width: 50%;
-
- svg {
- margin-right: 10px;
- }
-
- ${props =>
- props.disabled &&
- css`
- background: ${props.theme.gray};
- pointer-events: none;
- `};
-
- &:disabled {
- background: ${props => props.theme.gray};
- }
-`;
-
-export const Action = Link.withComponent('button');
-
-export const ButtonContainer = styled.section`
- display: flex;
- > *:not(:last-child) {
- margin-right: 0.5rem;
- }
-`;
-
-export const DeploysWrapper = styled.div`
- background: rgb(0, 0, 0);
- border-radius: 4px;
- font-size: 0.875rem;
- color: rgba(255, 255, 255, 0.8);
- padding: 0.75rem 1rem;
- padding: 0.75rem 0rem;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- margin: 0.5rem 0.75rem;
- margin-top: 0;
-`;
-
-export const Wrapper = styled.div`
- opacity: 1;
- ${props =>
- props.loading &&
- css`
- opacity: 0.5;
- pointer-events: none;
- `};
-`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify.js b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify.js
deleted file mode 100644
index 2f9719c8b5a..00000000000
--- a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify.js
+++ /dev/null
@@ -1,206 +0,0 @@
-import React, { Component } from 'react';
-import { inject, observer } from 'mobx-react';
-
-import LinkIcon from 'react-icons/lib/fa/external-link';
-import Cogs from 'react-icons/lib/fa/cogs';
-import LightningIcon from 'react-icons/lib/md/flash-on';
-import NetlifyLogo from 'app/components/NetlifyLogo';
-import DeploymentIntegration from 'app/components/DeploymentIntegration';
-import getTemplate from '@codesandbox/common/lib/templates';
-import { Button } from '@codesandbox/common/lib/components/Button';
-import { resolveDirectory } from '@codesandbox/common/lib/sandbox/modules';
-import getNetlifyConfig from 'app/utils/getNetlifyConfig';
-import { WorkspaceInputContainer, WorkspaceSubtitle } from '../../elements';
-import {
- Deploys,
- Deploy,
- Name,
- Link,
- DeploysWrapper,
- Wrapper,
- ButtonContainer,
-} from './Elements';
-
-const getFunctionDir = sandbox => {
- try {
- return resolveDirectory(
- getNetlifyConfig(sandbox).functions,
- sandbox.modules,
- sandbox.directories
- );
- } catch (e) {
- return [];
- }
-};
-
-class NetlifyDeployment extends Component {
- state = { show: false };
-
- toggleNetlify = () =>
- this.setState(state => ({
- show: !state.show,
- }));
-
- componentDidMount() {
- this.props.signals.deployment.getNetlifyDeploys();
- }
-
- render() {
- const {
- store: { deployment, editor },
- signals,
- } = this.props;
-
- const template = getTemplate(editor.currentSandbox.template);
- const { show } = this.state;
- const functionDirectory = getFunctionDir(editor.currentSandbox);
-
- const functions = editor.currentSandbox.modules.filter(
- m => m.directoryShortid === functionDirectory.shortid
- );
- return (
- template.netlify !== false && (
-
-
- this.toggleNetlify()}
- color="#fff"
- light
- Icon={NetlifyLogo}
- name="netlify"
- beta
- deploy={() => signals.deployment.deployWithNetlify()}
- >
- Deploy your sandbox site on{' '}
-
- Netlify
-
-
-
- {deployment.netlifySite && show ? (
-
- Sandbox Site
-
-
-
- {deployment.netlifySite.name}
- {!deployment.building && Building
}
- {functions.length ? (
- <>
-
- Functions
-
-
- {functions.map(file => (
-
-
- {file.title.split('.js')[0]}
-
- ))}
-
- >
- ) : null}
-
-
- Actions
-
-
-
- {deployment.building ? (
- <>
- Building...
- >
- ) : (
- <>
- Visit
- >
- )}
-
-
- {deployment.netlifyClaimUrl ? (
-
- Claim Site
-
- ) : null}
-
- {deployment.netlifyLogs ? (
-
- ) : null}
-
-
-
-
- ) : null}
-
- )
- );
- }
-}
-export default inject('signals', 'store')(observer(NetlifyDeployment));
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/DeployButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/DeployButton.tsx
new file mode 100644
index 00000000000..3dd64fa8fb0
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/DeployButton.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+
+import { DeploymentIntegration } from 'app/components/DeploymentIntegration';
+import NetlifyLogo from 'app/components/NetlifyLogo';
+import { useSignals, useStore } from 'app/store';
+
+import { DeployButtonContainer } from '../../elements';
+
+export const DeployButton = ({ isOpen, toggle }) => {
+ const {
+ deployment: { deployWithNetlify },
+ } = useSignals();
+ const {
+ deployment: { building, deploying },
+ } = useStore();
+
+ return (
+
+
+ Deploy your sandbox site on{' '}
+
+ Netlify
+
+
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/index.ts
new file mode 100644
index 00000000000..85f358de062
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/DeployButton/index.ts
@@ -0,0 +1 @@
+export { DeployButton } from './DeployButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/Netlify.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/Netlify.tsx
new file mode 100644
index 00000000000..627cd1073b2
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/Netlify.tsx
@@ -0,0 +1,41 @@
+import getTemplate from '@codesandbox/common/lib/templates';
+import { observer } from 'mobx-react-lite';
+import React, { useEffect, useState } from 'react';
+
+import { useSignals, useStore } from 'app/store';
+
+import { Wrapper } from '../elements';
+
+import { DeployButton } from './DeployButton';
+import { SiteInfo } from './SiteInfo';
+
+export const Netlify = observer(() => {
+ const {
+ deployment: { getNetlifyDeploys },
+ } = useSignals();
+ const {
+ deployment: { deploying, netlifySite },
+ editor: { currentSandbox },
+ } = useStore();
+
+ const [isVisible, setVisible] = useState(false);
+
+ useEffect(() => {
+ getNetlifyDeploys();
+ }, [getNetlifyDeploys]);
+
+ const template = getTemplate(currentSandbox.template);
+
+ return (
+ template.netlify !== false && (
+
+ setVisible(show => !show)}
+ />
+
+ {netlifySite && isVisible ? : null}
+
+ )
+ );
+});
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/Actions.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/Actions.tsx
new file mode 100644
index 00000000000..aefd7239f85
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/Actions.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import { useStore } from 'app/store';
+
+import { ButtonContainer } from '../../../elements';
+
+import { SubTitle } from '../elements';
+
+import { ClaimSiteButton } from './ClaimSiteButton';
+import { VisitSiteButton } from './VisitSiteButton';
+
+export const Actions = () => {
+ const {
+ deployment: { netlifyClaimUrl },
+ } = useStore();
+
+ return (
+ <>
+ Actions
+
+
+
+
+ {netlifyClaimUrl ? : null}
+
+ >
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/ClaimSiteButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/ClaimSiteButton.tsx
new file mode 100644
index 00000000000..c04621085f3
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/ClaimSiteButton.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { useStore } from 'app/store';
+
+import { Link } from '../../../../elements';
+
+export const ClaimSiteButton = () => {
+ const {
+ deployment: { building, netlifyClaimUrl },
+ } = useStore();
+
+ return (
+
+ Claim Site
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/index.ts
new file mode 100644
index 00000000000..46c9f71ac31
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/ClaimSiteButton/index.ts
@@ -0,0 +1 @@
+export { ClaimSiteButton } from './ClaimSiteButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/VisitSiteButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/VisitSiteButton.tsx
new file mode 100644
index 00000000000..22c903536f3
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/VisitSiteButton.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import LinkIcon from 'react-icons/lib/fa/external-link';
+import Cogs from 'react-icons/lib/fa/cogs';
+
+import { useStore } from 'app/store';
+
+import { Link } from '../../../../elements';
+
+export const VisitSiteButton = () => {
+ const {
+ deployment: { building, netlifySite },
+ } = useStore();
+
+ return (
+
+ {building ? (
+ <>
+ Building...
+ >
+ ) : (
+ <>
+ Visit
+ >
+ )}
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/index.ts
new file mode 100644
index 00000000000..3acc92dff09
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/VisitSiteButton/index.ts
@@ -0,0 +1 @@
+export { VisitSiteButton } from './VisitSiteButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/index.ts
new file mode 100644
index 00000000000..ac0eab8d42a
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Actions/index.ts
@@ -0,0 +1 @@
+export { Actions } from './Actions';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/Function.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/Function.tsx
new file mode 100644
index 00000000000..43e676c6c1a
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/Function.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import LightningIcon from 'react-icons/lib/md/flash-on';
+
+import { useStore } from 'app/store';
+
+import { Link } from '../../../../elements';
+
+export const Function = ({ function: { title } }) => {
+ const {
+ deployment: {
+ building,
+ netlifySite: { url: siteUrl },
+ },
+ } = useStore();
+
+ const functionName = title.split('.js')[0];
+
+ return (
+
+
+
+ {functionName}
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/elements.ts
new file mode 100644
index 00000000000..93ed43e001e
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/elements.ts
@@ -0,0 +1,7 @@
+import styled from 'styled-components';
+
+import { Link as BaseLink } from '../../../../elements';
+
+export const Section = styled(BaseLink)`
+ margin-right: 0.5rem;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/index.ts
new file mode 100644
index 00000000000..4b53a265c1c
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Function/index.ts
@@ -0,0 +1 @@
+export { Function } from './Function';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Functions.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Functions.tsx
new file mode 100644
index 00000000000..2ce2e84c6f3
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/Functions.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import { SubTitle } from '../elements';
+
+import { Section } from './elements';
+import { Function } from './Function';
+
+export const Functions = ({ functions }) => (
+ <>
+ Functions
+
+
+ {functions.map(func => (
+
+ ))}
+
+ >
+);
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/elements.ts
new file mode 100644
index 00000000000..c1b21402fea
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/elements.ts
@@ -0,0 +1,6 @@
+import styled from 'styled-components';
+
+export const Section = styled.section`
+ display: flex;
+ margin-bottom: 0.5rem;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/index.ts
new file mode 100644
index 00000000000..baa1aa42491
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/Functions/index.ts
@@ -0,0 +1 @@
+export { Functions } from './Functions';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/SiteInfo.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/SiteInfo.tsx
new file mode 100644
index 00000000000..5fa8f38ace2
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/SiteInfo.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { observer } from 'mobx-react-lite';
+
+import { useStore } from 'app/store';
+import getNetlifyConfig from 'app/utils/getNetlifyConfig';
+
+import { resolveDirectory } from '@codesandbox/common/lib/sandbox/modules';
+
+import {
+ WorkspaceInputContainer,
+ WorkspaceSubtitle,
+} from '../../../../elements';
+
+import { Deploys, Deploy, Name } from '../../elements';
+
+import { Actions } from './Actions';
+import { SiteInfoWrapper } from './elements';
+import { Functions } from './Functions';
+import { ViewLogsButton } from './ViewLogsButton';
+
+const getFunctionDir = sandbox => {
+ try {
+ return resolveDirectory(
+ getNetlifyConfig(sandbox).functions,
+ sandbox.modules,
+ sandbox.directories
+ );
+ } catch {
+ return undefined;
+ }
+};
+
+export const SiteInfo = observer(() => {
+ const {
+ deployment: { building, netlifyLogs, netlifySite },
+ editor: { currentSandbox },
+ } = useStore();
+
+ const functionDirectory = getFunctionDir(currentSandbox);
+ const functions = functionDirectory
+ ? currentSandbox.modules.filter(
+ ({ directoryShortid }) => directoryShortid === functionDirectory.shortid
+ )
+ : [];
+
+ return (
+
+ Sandbox Site
+
+
+
+
+ {netlifySite.name}
+
+ {!building && Building
}
+
+ {functions.length ? : null}
+
+
+
+ {netlifyLogs ? : null}
+
+
+
+
+ );
+});
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/ViewLogsButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/ViewLogsButton.tsx
new file mode 100644
index 00000000000..ed96f57ef9e
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/ViewLogsButton.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+
+import { useSignals } from 'app/store';
+
+import { Button } from './elements';
+
+export const ViewLogsButton = () => {
+ const { modalOpened } = useSignals();
+
+ return (
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/elements.ts
new file mode 100644
index 00000000000..5556a81373a
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/elements.ts
@@ -0,0 +1,6 @@
+import { Button as BaseButton } from '@codesandbox/common/lib/components/Button';
+import styled from 'styled-components';
+
+export const Button = styled(BaseButton)`
+ margin-top: 20px;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/index.ts
new file mode 100644
index 00000000000..79ae564896b
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/ViewLogsButton/index.ts
@@ -0,0 +1 @@
+export { ViewLogsButton } from './ViewLogsButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/elements.ts
new file mode 100644
index 00000000000..95c5c34e044
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/elements.ts
@@ -0,0 +1,13 @@
+import styled from 'styled-components';
+
+import { WorkspaceSubtitle } from '../../../../elements';
+
+import { DeploysContainer } from '../../elements';
+
+export const SiteInfoWrapper = styled(DeploysContainer)`
+ background-color: #ffffff;
+`;
+
+export const SubTitle = styled(WorkspaceSubtitle)`
+ padding-left: 0;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/index.ts
new file mode 100644
index 00000000000..8d3926e6b18
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/SiteInfo/index.ts
@@ -0,0 +1 @@
+export { SiteInfo } from './SiteInfo';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/index.ts
new file mode 100644
index 00000000000..c10a1d00773
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Netlify/index.ts
@@ -0,0 +1 @@
+export { Netlify } from './Netlify';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit.js b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit.js
deleted file mode 100644
index 5b7f6f14328..00000000000
--- a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit.js
+++ /dev/null
@@ -1,144 +0,0 @@
-import React, { Fragment, Component } from 'react';
-import { inject, observer } from 'mobx-react';
-import TrashIcon from 'react-icons/lib/fa/trash';
-import LinkIcon from 'react-icons/lib/fa/external-link';
-import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
-import NowLogo from 'app/components/NowLogo';
-import DeploymentIntegration from 'app/components/DeploymentIntegration';
-import ZeitIntegration from '../../../../../common/ZeitIntegration';
-import { WorkspaceInputContainer, WorkspaceSubtitle } from '../../elements';
-import {
- Deploys,
- Wrapper,
- Deploy,
- State,
- Name,
- Link,
- Action,
- ButtonContainer,
- DeploysWrapper,
-} from './Elements';
-
-class ZeitDeployment extends Component {
- state = { show: false };
-
- toggleZeit = () =>
- this.setState(state => ({
- show: !state.show,
- }));
-
- render() {
- const {
- signals,
- store: { user, deployment },
- } = this.props;
-
- const { show } = this.state;
- return user.integrations.zeit ? (
-
-
- this.toggleZeit()}
- color="#000000"
- Icon={NowLogo}
- name="Now"
- deploy={() => signals.deployment.deploySandboxClicked()}
- >
- Deploy your sandbox on{' '}
-
- ZEIT Now
-
-
-
- {deployment.sandboxDeploys.length && show ? (
-
- Sandbox Deploys
-
-
- {deployment.sandboxDeploys.map(deploy => (
-
-
- {deploy.name}
- ({distanceInWordsToNow(deploy.created)} ago)
-
-
- {deploy.state.toLowerCase()}
-
- {deploy.alias.length ? (
-
- Aliased to{' '}
- {deploy.alias.map(a => (
-
- {a.alias}
-
- ))}
-
- ) : null}
-
-
- Visit
-
- {
- signals.deployment.setDeploymentToDelete({
- id: deploy.uid,
- });
- signals.modalOpened({
- modal: 'deleteDeployment',
- });
- }}
- >
- {deployment[`${deploy.uid}Deleting`] ? (
- 'Deleting'
- ) : (
-
- Delete
-
- )}
-
- {deployment.hasAlias && deploy.state === 'READY' ? (
- {
- signals.deployment.aliasDeployment({
- id: deploy.uid,
- });
- }}
- >
- {deploy.alias.length ? 'Aliased' : 'Alias'}
-
- ) : null}
-
-
- ))}
-
-
-
- ) : null}
-
- ) : (
-
-
-
- );
- }
-}
-export default inject('signals', 'store')(observer(ZeitDeployment));
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/DeployButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/DeployButton.tsx
new file mode 100644
index 00000000000..6a54b0fbcb5
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/DeployButton.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+
+import { DeploymentIntegration } from 'app/components/DeploymentIntegration';
+import NowLogo from 'app/components/NowLogo';
+import { useSignals } from 'app/store';
+
+import { DeployButtonContainer } from '../../elements';
+
+export const DeployButton = ({ isOpen, toggle }) => {
+ const {
+ deployment: { deploySandboxClicked },
+ } = useSignals();
+
+ return (
+
+
+ Deploy your sandbox on{' '}
+
+ ZEIT Now
+
+
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/index.ts
new file mode 100644
index 00000000000..85f358de062
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/DeployButton/index.ts
@@ -0,0 +1 @@
+export { DeployButton } from './DeployButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/Actions.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/Actions.tsx
new file mode 100644
index 00000000000..c6f8c42a880
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/Actions.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+
+import { useStore } from 'app/store';
+
+import { ButtonContainer } from '../../../elements';
+
+import { AliasDeploymentButton } from './AliasDeploymentButton';
+import { DeleteDeploymentButton } from './DeleteDeploymentButton';
+import { VisitDeploymentButton } from './VisitDeploymentButton';
+
+export const Actions = ({ deploy }) => {
+ const {
+ deployment: { hasAlias },
+ } = useStore();
+
+ return (
+
+
+
+
+
+ {hasAlias && deploy.state === 'READY' ? (
+
+ ) : null}
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/AliasDeploymentButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/AliasDeploymentButton.tsx
new file mode 100644
index 00000000000..265675393e7
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/AliasDeploymentButton.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { useSignals } from 'app/store';
+
+import { Action } from '../../../../elements';
+
+export const AliasDeploymentButton = ({ deploy: { alias, uid: id } }) => {
+ const {
+ deployment: { aliasDeployment },
+ } = useSignals();
+
+ return (
+ 0} onClick={() => aliasDeployment({ id })}>
+ {alias.length > 0 ? 'Aliased' : 'Alias'}
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/index.ts
new file mode 100644
index 00000000000..b58b8870cdc
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/AliasDeploymentButton/index.ts
@@ -0,0 +1 @@
+export { AliasDeploymentButton } from './AliasDeploymentButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/DeleteDeploymentButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/DeleteDeploymentButton.tsx
new file mode 100644
index 00000000000..c6ac383992b
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/DeleteDeploymentButton.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import TrashIcon from 'react-icons/lib/fa/trash';
+
+import { useSignals, useStore } from 'app/store';
+
+import { Action } from '../../../../elements';
+
+export const DeleteDeploymentButton = ({ id }) => {
+ const {
+ deployment: { setDeploymentToDelete },
+ modalOpened,
+ } = useSignals();
+ const { deployment } = useStore();
+
+ return (
+ {
+ setDeploymentToDelete({ id });
+ modalOpened({ modal: 'deleteDeployment' });
+ }}
+ >
+ {deployment[`${id}Deleting`] ? (
+ 'Deleting'
+ ) : (
+ <>
+ Delete
+ >
+ )}
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/index.ts
new file mode 100644
index 00000000000..948b72b8c6d
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/DeleteDeploymentButton/index.ts
@@ -0,0 +1 @@
+export { DeleteDeploymentButton } from './DeleteDeploymentButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/VisitDeploymentButton.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/VisitDeploymentButton.tsx
new file mode 100644
index 00000000000..7c2751ec502
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/VisitDeploymentButton.tsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import LinkIcon from 'react-icons/lib/fa/external-link';
+
+import { Link } from '../../../../elements';
+
+export const VisitDeploymentButton = ({ url }) => (
+
+ Visit
+
+);
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/index.ts
new file mode 100644
index 00000000000..7421962c1f8
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/VisitDeploymentButton/index.ts
@@ -0,0 +1 @@
+export { VisitDeploymentButton } from './VisitDeploymentButton';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/index.ts
new file mode 100644
index 00000000000..ac0eab8d42a
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Actions/index.ts
@@ -0,0 +1 @@
+export { Actions } from './Actions';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/Alias.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/Alias.tsx
new file mode 100644
index 00000000000..d4005af3547
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/Alias.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+export const Alias = ({ alias: aliases }) => (
+
+ Aliased to{' '}
+ {aliases.map(({ alias }) => (
+
+ {alias}
+
+ ))}
+
+);
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/index.ts
new file mode 100644
index 00000000000..b24935ecbb0
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Alias/index.ts
@@ -0,0 +1 @@
+export { Alias } from './Alias';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Deploys.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Deploys.tsx
new file mode 100644
index 00000000000..be79030d2f6
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/Deploys.tsx
@@ -0,0 +1,52 @@
+import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
+import React from 'react';
+
+import { useStore } from 'app/store';
+
+import {
+ WorkspaceInputContainer,
+ WorkspaceSubtitle,
+} from '../../../../elements';
+
+import {
+ Deploy,
+ Deploys as DeploysWrapper,
+ DeploysContainer,
+ Name,
+ State,
+} from '../../elements';
+
+import { Actions } from './Actions';
+import { Alias } from './Alias';
+
+export const Deploys = () => {
+ const {
+ deployment: { sandboxDeploys },
+ } = useStore();
+
+ return (
+
+ Sandbox Deploys
+
+
+
+ {sandboxDeploys.map(deploy => (
+
+
+ {deploy.name}
+
+ {`(${distanceInWordsToNow(deploy.created)} ago)`}
+
+
+ {deploy.state.toLowerCase()}
+
+ {deploy.alias.length > 0 ? : null}
+
+
+
+ ))}
+
+
+
+ );
+};
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/index.ts
new file mode 100644
index 00000000000..9f86e62fc6e
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Deploys/index.ts
@@ -0,0 +1 @@
+export { Deploys } from './Deploys';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Zeit.tsx b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Zeit.tsx
new file mode 100644
index 00000000000..2d82c689301
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/Zeit.tsx
@@ -0,0 +1,35 @@
+import { observer } from 'mobx-react-lite';
+import React, { useState } from 'react';
+
+import ZeitIntegration from 'app/pages/common/ZeitIntegration';
+import { useStore } from 'app/store';
+
+import { Wrapper } from '../elements';
+
+import { DeployButton } from './DeployButton';
+import { Deploys } from './Deploys';
+import { NoIntegrationWrapper } from './elements';
+
+export const Zeit = observer(() => {
+ const {
+ deployment: { deploying, sandboxDeploys },
+ user: { integrations },
+ } = useStore();
+
+ const [isVisible, setVisible] = useState(false);
+
+ return integrations.zeit ? (
+
+ setVisible(show => !show)}
+ />
+
+ {sandboxDeploys.length && isVisible ? : null}
+
+ ) : (
+
+
+
+ );
+});
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/elements.ts
new file mode 100644
index 00000000000..199de976060
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/elements.ts
@@ -0,0 +1,5 @@
+import styled from 'styled-components';
+
+export const NoIntegrationWrapper = styled.div`
+ margin: 1rem;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/index.ts
new file mode 100644
index 00000000000..e7df9fee5dd
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/Zeit/index.ts
@@ -0,0 +1 @@
+export { Zeit } from './Zeit';
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/elements.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/elements.ts
new file mode 100644
index 00000000000..0d1ace783d8
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/elements.ts
@@ -0,0 +1,151 @@
+import styled, { css } from 'styled-components';
+
+import { WorkspaceInputContainer } from '../../elements';
+
+const mapColorToState = (state: string, theme: any) => {
+ const STARTING = ['DEPLOYING', 'BUILDING', 'INITIALIZING'];
+ const ERROR = ['DEPLOYMENT_ERROR', 'BUILD_ERROR', 'ERROR'];
+ const STARTED = ['BOOTED', 'READY'];
+
+ if (STARTING.includes(state)) {
+ return '#FCCB7E';
+ }
+ if (ERROR.includes(state)) {
+ return theme.red;
+ }
+ if (STARTED.includes(state)) {
+ return theme.green;
+ }
+ if (state === 'FROZEN') {
+ return theme.blue;
+ }
+
+ return theme.gray;
+};
+
+export const State = styled.span<{ state: string }>`
+ ${({ state, theme }) => css`
+ align-items: center;
+ display: flex;
+ text-transform: capitalize;
+ margin-bottom: 0.5rem;
+
+ &:before {
+ content: '';
+ display: block;
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ margin-right: 0.5rem;
+ background: ${mapColorToState(state, theme)};
+ }
+ `};
+`;
+
+export const Deploys = styled.ul`
+ list-style: none;
+ padding: 0;
+ flex-direction: column;
+ font-size: 0.875rem;
+ margin: 0 0.25rem;
+`;
+
+export const Deploy = styled.li`
+ display: flex;
+ margin-bottom: 1.5rem;
+ flex-direction: column;
+`;
+
+export const Name = styled.span<{ light?: boolean }>`
+ ${({ light, theme }) => css`
+ font-weight: 600;
+ color: ${theme.light || light
+ ? css`rgba(0, 0, 0, 0.8)`
+ : css`rgba(255, 255, 255, 0.8)`};
+ font-size: 1rem;
+ margin-top: 0;
+ vertical-align: middle;
+
+ span {
+ color: ${theme.light || light
+ ? theme.background3.darken(0.5)
+ : theme.background3.lighten(0.5)};
+ font-size: 12px;
+ margin-left: 0.5rem;
+ }
+ `};
+`;
+
+const BaseLink = styled.a<{ disabled?: boolean }>`
+ padding: 0.25rem 0.4rem;
+ background-color: ${props => props.theme.secondary};
+ text-decoration: none;
+ border: none;
+ font-size: 0.75rem;
+ color: white;
+ border-radius: 2px;
+ font-weight: 600;
+ margin-top: 0.75rem;
+ display: flex;
+ align-items: center;
+ flex-grow: 0;
+ max-width: 50%;
+
+ margin-top: 0;
+
+ svg {
+ margin-right: 10px;
+ }
+
+ ${props =>
+ props.disabled &&
+ css`
+ background: ${props.theme.gray};
+ pointer-events: none;
+ `};
+
+ &:disabled {
+ background: ${props => props.theme.gray};
+ }
+`;
+
+export const Link = styled(BaseLink).attrs({
+ rel: 'noreferrer noopener',
+ target: '_blank',
+})``;
+
+export const Action = BaseLink.withComponent('button');
+
+export const ButtonContainer = styled.section`
+ display: flex;
+
+ > *:not(:last-child) {
+ margin-right: 0.5rem;
+ }
+`;
+
+export const DeploysContainer = styled.div`
+ background-color: #000000;
+ border-radius: 0 0 4px 4px;
+ color: rgba(255, 255, 255, 0.8);
+ font-size: 0.875rem;
+ margin: -4px 0.75rem 0.5rem;
+ padding: 0.75rem 0;
+`;
+
+export const Wrapper = styled.div<{ loading: boolean }>`
+ ${({ loading }) => css`
+ opacity: 1;
+
+ ${loading &&
+ css`
+ opacity: 0.5;
+ pointer-events: none;
+ `};
+ `};
+`;
+
+export const DeployButtonContainer = styled(WorkspaceInputContainer)`
+ margin-bottom: 0;
+ margin-top: 1rem;
+`;
diff --git a/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.ts b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.ts
new file mode 100644
index 00000000000..74dc9ac5cad
--- /dev/null
+++ b/packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Deployment/index.ts
@@ -0,0 +1 @@
+export { Deployment } from './Deployment';
diff --git a/packages/app/src/app/pages/common/NotFound/index.tsx b/packages/app/src/app/pages/common/NotFound/index.tsx
index 1281d2149db..02aedafd356 100644
--- a/packages/app/src/app/pages/common/NotFound/index.tsx
+++ b/packages/app/src/app/pages/common/NotFound/index.tsx
@@ -1,4 +1,5 @@
import React from 'react';
+import { observer } from 'mobx-react-lite';
import { Button } from '@codesandbox/common/lib/components/Button';
import { newSandboxWizard } from '@codesandbox/common/lib/utils/url-generator';
@@ -29,4 +30,4 @@ const NotFound = () => {
);
};
-export default NotFound;
+export default observer(NotFound);
diff --git a/packages/app/src/app/store/modules/deployment/actions.js b/packages/app/src/app/store/modules/deployment/actions.js
index f59273e2bfb..60a4b1ca11c 100644
--- a/packages/app/src/app/store/modules/deployment/actions.js
+++ b/packages/app/src/app/store/modules/deployment/actions.js
@@ -313,8 +313,12 @@ export async function getDeploys({ http, path, state, props }) {
const assignAlias = async d => {
const alias = await deploysByID(d.uid, token, http);
- // eslint-disable-next-line
- d.alias = alias.aliases;
+ if (alias) {
+ // eslint-disable-next-line
+ d.alias = alias.aliases;
+ } else {
+ d.alias = [];
+ }
return d;
};
diff --git a/packages/app/src/app/utils/getNetlifyConfig.js b/packages/app/src/app/utils/getNetlifyConfig.js
index a806da5880e..f82a7456b76 100644
--- a/packages/app/src/app/utils/getNetlifyConfig.js
+++ b/packages/app/src/app/utils/getNetlifyConfig.js
@@ -8,5 +8,6 @@ export default sandbox => {
module.title === 'netlify.toml' && module.directoryShortid == null
)
.map(m => toml(m.code))[0] || { build: {} };
+
return mapKeys(netlifyConfig.build, (v, k) => k.toLowerCase());
};
diff --git a/packages/common/src/sandbox/modules.ts b/packages/common/src/sandbox/modules.ts
index 97f07c3d748..1b40e135e66 100644
--- a/packages/common/src/sandbox/modules.ts
+++ b/packages/common/src/sandbox/modules.ts
@@ -21,7 +21,9 @@ export function resolveDirectory(
directories: Array,
_startdirectoryShortid: string | undefined = undefined
) {
- if (!_path) return throwError('');
+ if (!_path) {
+ return throwError('');
+ }
let path = _path;
let startdirectoryShortid = _startdirectoryShortid;
@@ -40,7 +42,9 @@ export function resolveDirectory(
const foundDirectoryShortid = splitPath.reduce(
(dirId: string | undefined, pathPart: string, i: number) => {
// Meaning this is the last argument, so the directory
- if (i === splitPath.length) return dirId;
+ if (i === splitPath.length) {
+ return dirId;
+ }
if (pathPart === '..') {
// Find the parent
diff --git a/packages/homepage/package.json b/packages/homepage/package.json
index a1da471497b..95809eb7525 100644
--- a/packages/homepage/package.json
+++ b/packages/homepage/package.json
@@ -1,5 +1,5 @@
{
- "name": "codesandbox-homepage",
+ "name": "homepage",
"description": "CodeSandbox Homepage",
"private": true,
"version": "1.0.0",