Skip to content
This repository has been archived by the owner on Jun 17, 2021. It is now read-only.

[WIP] Export to Codesandbox #324

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
]
},
"dependencies": {
"codesandbox": "^1.3.5",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I've missed to pin the version. I'll change that in my next commit.

"create-react-app": "1.5.2",
"electron-debug": "2.0.0",
"electron-devtools-installer": "2.2.4",
Expand Down
31 changes: 31 additions & 0 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,18 @@ export const SHOW_PROJECT_SETTINGS = 'SHOW_PROJECT_SETTINGS';
export const SAVE_PROJECT_SETTINGS_START = 'SAVE_PROJECT_SETTINGS_START';
export const SAVE_PROJECT_SETTINGS_ERROR = 'SAVE_PROJECT_SETTINGS_ERROR';
export const SAVE_PROJECT_SETTINGS_FINISH = 'SAVE_PROJECT_SETTINGS_FINISH';
export const SET_CODESANDBOX_URL = 'SET_CODESANDBOX_URL';

// app settings
export const SHOW_APP_SETTINGS = 'SHOW_APP_SETTINGS';
export const SAVE_APP_SETTINGS_START = 'SAVE_APP_SETTINGS_START';
export const CHANGE_DEFAULT_PROJECT_PATH = 'CHANGE_DEFAULT_PROJECT_PATH';
export const UPDATE_CODESANDBOX_TOKEN = 'UPDATE_CODESANDBOX_TOKEN';

// export to codesandbox
export const EXPORT_TO_CODESANDBOX = 'EXPORT_TO_CODESANDBOX';
export const CODESANDBOX_LOGOUT = 'CODESANDBOX_LOGOUT';

//
//
// Action Creators
Expand Down Expand Up @@ -379,6 +386,20 @@ export const changeDefaultProjectPath = (defaultProjectPath: string) => ({
defaultProjectPath,
});

export const updateCodesandboxToken = (codesandboxToken: string) => ({
type: UPDATE_CODESANDBOX_TOKEN,
codesandboxToken,
});

export const setCodesandboxUrl = (
projectId: string,
codesandboxUrl: string
) => ({
type: SET_CODESANDBOX_URL,
projectId,
codesandboxUrl,
});

// project settings related actions
export const saveProjectSettingsStart = (
name: string,
Expand Down Expand Up @@ -418,3 +439,13 @@ export const showResetStatePrompt = () => ({
});

export const resetAllState = () => ({ type: RESET_ALL_STATE });

export const exportToCodesandbox = (projectPath: string) => ({
type: EXPORT_TO_CODESANDBOX,
projectPath,
});

export const logoutCodesandbox = (projectPath: string) => ({
type: CODESANDBOX_LOGOUT,
projectPath,
});
46 changes: 46 additions & 0 deletions src/assets/images/codesandbox-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/components/DisabledText/DisabledText.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// @flow
import styled from 'styled-components';
import { COLORS } from '../../constants';

export default styled.div`
padding-top: 16px;
color: ${COLORS.gray[500]};
`;
2 changes: 2 additions & 0 deletions src/components/DisabledText/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @flow
export { default } from './DisabledText';
160 changes: 160 additions & 0 deletions src/components/ExportToCodesandbox/ExportToCodesandbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// @flow
import React, { Fragment, PureComponent } from 'react';
import styled from 'styled-components';
import { connect } from 'react-redux';

import * as actions from '../../actions';
import { COLORS } from '../../constants';

import { getSelectedProject } from '../../reducers/projects.reducer';
import { getCodesandboxToken } from '../../reducers/app-settings.reducer';

import ExternalLink from '../ExternalLink';
import FormField from '../FormField';
import TokenInput from '../TokenInput';
import StrokeButton from '../Button/StrokeButton';
import DisabledText from '../DisabledText';
import Spacer from '../Spacer';

import type { Project } from '../../types';
import type { Dispatch } from '../../actions/types';

type State = {
focusTokenInput: boolean,
};

type Props = {
codesandboxToken: string,
isFocused: boolean,
project: Project,
updateCodesandboxToken: Dispatch<typeof actions.updateCodesandboxToken>,
setCodesandboxUrl: Dispatch<typeof actions.setCodesandboxUrl>,
onFocus: () => void,
onBlur: () => void,
};

class ExportToCodesandbox extends PureComponent<Props, State> {
// todo: rename as export is a reserved keyword!
export = (evt: any) => {
const { export: exportSandbox, project } = this.props;
evt.preventDefault();

exportSandbox(project.path);
};

logout = (evt: any) => {
evt.preventDefault();
const { logout, project } = this.props;

logout(project.path);
};
// todo: Change flow:
// 1. Token always available before running the code - so no need to opne codesandbox page
// 2. After export click display External link to created sandbox & store link in project
render() {
const {
codesandboxToken,
project,
isFocused,
onFocus,
onBlur,
} = this.props;
const { codesandboxUrl } = project;

return (
<ExportToCodesandboxWrapper>
<FormField size="small" label="Export to Codesandbox.io">
<InfoText>
Goto Codesandbox website by clicking the link and copy the token.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Goto Codesandbox website by clicking the link and copy the token.
Go to the Codesandbox website by clicking the link and copy the token.

Then paste the token in the token field.{' '}
</InfoText>
<ExternalLink href="https://codesandbox.io/cli/login">
Get new token
</ExternalLink>
</FormField>
<Wrapper>
<FormField label="Codesandbox token">
<TokenRow>
<TokenInput
token={codesandboxToken}
onChange={this.props.updateToken}
onFocus={onFocus}
onBlur={onBlur}
focused={isFocused}
disabled={codesandboxToken !== ''}
/>
{codesandboxToken && (
<Fragment>
<Spacer size={10} />
<StrokeButton size="small" onClick={this.logout}>
Logout
</StrokeButton>
</Fragment>
)}
</TokenRow>
</FormField>
<Action>
<StrokeButton
onClick={this.export}
size="small"
strokeColors={[COLORS.green[700], COLORS.lightGreen[500]]}
disabled={!codesandboxToken}
>
Export to Codesandbox
</StrokeButton>
{!codesandboxToken && (
<DisabledText>
Export disabled because token is missing.
</DisabledText>
)}
<Spacer size={5} />
<InfoText>
{codesandboxUrl && (
<div>
Codesandbox created <strong>{codesandboxUrl}</strong>
<ExternalLink href={codesandboxUrl}>
Open sandbox
</ExternalLink>
</div>
)}
</InfoText>
</Action>
</Wrapper>
</ExportToCodesandboxWrapper>
);
}
}

const Wrapper = styled.div`
display: grid;
grid-template-columns: 1fr 1fr;
`;

const ExportToCodesandboxWrapper = styled.div`
margin-top: 16px;
`;

const Action = styled.div``;

const InfoText = styled.div``;

const TokenRow = styled.div`
display: flex;
align-items: center;
`;

const mapStateToProps = state => ({
project: getSelectedProject(state),
codesandboxToken: getCodesandboxToken(state),
});

const mapDispatchToProps = {
export: actions.exportToCodesandbox,
logout: actions.logoutCodesandbox,
updateToken: actions.updateCodesandboxToken,
};

export default connect(
mapStateToProps,
mapDispatchToProps
)(ExportToCodesandbox);
2 changes: 2 additions & 0 deletions src/components/ExportToCodesandbox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// @flow
export { default } from './ExportToCodesandbox';
1 change: 0 additions & 1 deletion src/components/Modal/Modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ class Modal extends PureComponent<Props, State> {
{({ interpolatedTranslateY, opacity }) => (
<Wrapper opacity={opacity} clickable={!inTransit}>
<Backdrop onClick={onDismiss} />

<PaneWrapper
width={width}
height={height}
Expand Down
Loading