feat: remove unused files

This commit is contained in:
fragosti
2018-12-20 16:32:00 -08:00
parent ba7c8d9244
commit ea781b8850
29 changed files with 1 additions and 2818 deletions

View File

@@ -9,7 +9,7 @@
"scripts": {
"build": "yarn build:dev",
"build:prod": "node --max_old_space_size=8192 ../../node_modules/.bin/webpack --mode production",
"build:dev": "../../node_modules/.bin/webpack --mode development",
"build:dev": "../../node_modules/.bin/webpack --mode development --json",
"clean": "shx rm -f public/bundle*",
"lint": "tslint --format stylish --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
"dev": "webpack-dev-server --mode development --content-base public --https",

View File

@@ -1,46 +0,0 @@
import { colors } from '@0x/react-shared';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import * as React from 'react';
import { constants } from 'ts/utils/constants';
interface U2fNotSupportedDialogProps {
isOpen: boolean;
onToggleDialog: () => void;
}
export const U2fNotSupportedDialog = (props: U2fNotSupportedDialogProps) => {
return (
<Dialog
title="U2F Not Supported"
titleStyle={{ fontWeight: 100 }}
actions={[<FlatButton key="u2fNo" label="Ok" onClick={props.onToggleDialog} />]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
>
<div className="pt2" style={{ color: colors.grey700 }}>
<div>
It looks like your browser does not support U2F connections required for us to communicate with your
hardware wallet. Please use a browser that supports U2F connections and try again.
</div>
<div>
<ul>
<li className="pb1">Chrome version 38 or later</li>
<li className="pb1">Opera version 40 of later</li>
<li>
Firefox with{' '}
<a
href={constants.URL_FIREFOX_U2F_ADDON}
target="_blank"
style={{ textDecoration: 'underline' }}
>
this extension
</a>.
</li>
</ul>
</div>
</div>
</Dialog>
);
};

View File

@@ -1,33 +0,0 @@
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import { colors } from 'material-ui/styles';
import * as React from 'react';
interface WrappedEthSectionNoticeDialogProps {
isOpen: boolean;
onToggleDialog: () => void;
}
export const WrappedEthSectionNoticeDialog = (props: WrappedEthSectionNoticeDialogProps) => {
return (
<Dialog
title="Dedicated Wrapped Ether Section"
titleStyle={{ fontWeight: 100 }}
actions={[
<FlatButton key="acknowledgeWrapEthSection" label="Sounds good" onClick={props.onToggleDialog} />,
]}
open={props.isOpen}
onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
modal={true}
>
<div className="pt2" style={{ color: colors.grey700 }}>
<div>
We have recently updated the Wrapped Ether token (WETH) used by 0x Portal. Don't worry, unwrapping
Ether tied to the old Wrapped Ether token can be done at any time by clicking on the "Wrap ETH"
section in the menu to the left.
</div>
</div>
</Dialog>
);
};

View File

@@ -1,127 +0,0 @@
import { colors } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Input } from 'ts/components/ui/input';
import { Text } from 'ts/components/ui/text';
import { analytics } from 'ts/utils/analytics';
import { backendClient } from 'ts/utils/backend_client';
export interface SubscribeFormProps {}
export enum SubscribeFormStatus {
None,
Error,
Success,
Loading,
Other,
}
export interface SubscribeFormState {
emailText: string;
lastSubmittedEmail: string;
status: SubscribeFormStatus;
}
const FORM_FONT_SIZE = '15px';
// TODO: Translate visible strings. https://app.asana.com/0/628666249318202/697485674422001
export class SubscribeForm extends React.Component<SubscribeFormProps, SubscribeFormState> {
public state = {
emailText: '',
lastSubmittedEmail: '',
status: SubscribeFormStatus.None,
};
public render(): React.ReactNode {
return (
<Container className="flex flex-column items-center justify-between md-mx2 sm-mx2">
<Container marginBottom="15px">
<Text fontFamily="Roboto Mono" fontColor={colors.grey} center={true}>
Subscribe to our newsletter for 0x relayer and dApp updates
</Text>
</Container>
<form onSubmit={this._handleFormSubmitAsync.bind(this)}>
<Container className="flex flex-wrap justify-center items-center">
<Container marginTop="15px">
<Input
placeholder="you@email.com"
value={this.state.emailText}
fontColor={colors.white}
fontSize={FORM_FONT_SIZE}
backgroundColor={colors.projectsGrey}
width="300px"
onChange={this._handleEmailInputChange.bind(this)}
/>
</Container>
<Container marginLeft="15px" marginTop="15px">
<Button
type="submit"
backgroundColor={colors.darkestGrey}
fontColor={colors.white}
fontSize={FORM_FONT_SIZE}
>
Subscribe
</Button>
</Container>
</Container>
</form>
{this._renderMessage()}
</Container>
);
}
private _renderMessage(): React.ReactNode {
let message = null;
switch (this.state.status) {
case SubscribeFormStatus.Error:
message = 'Sorry, something went wrong. Try again later.';
break;
case SubscribeFormStatus.Loading:
message = 'One second...';
break;
case SubscribeFormStatus.Success:
message = `Thanks! ${this.state.lastSubmittedEmail} is now on the mailing list.`;
break;
case SubscribeFormStatus.None:
break;
default:
throw new Error(
'The SubscribeFormStatus switch statement is not exhaustive when choosing an error message.',
);
}
return (
<Container isHidden={!message} marginTop="30px">
<Text center={true} fontFamily="Roboto Mono" fontColor={colors.grey}>
{message || 'spacer text (never shown to user)'}
</Text>
</Container>
);
}
private _handleEmailInputChange(event: React.ChangeEvent<HTMLInputElement>): void {
this.setState({ emailText: event.target.value });
}
private async _handleFormSubmitAsync(event: React.FormEvent<HTMLInputElement>): Promise<void> {
event.preventDefault();
if (_.isUndefined(this.state.emailText) || _.isEmpty(this.state.emailText)) {
return;
}
this.setState({
status: SubscribeFormStatus.Loading,
lastSubmittedEmail: this.state.emailText,
});
try {
const response = await backendClient.subscribeToNewsletterAsync(this.state.emailText);
const status = response.status === 200 ? SubscribeFormStatus.Success : SubscribeFormStatus.Error;
if (status === SubscribeFormStatus.Success) {
analytics.identify(this.state.emailText, 'email');
}
this.setState({ status, emailText: '' });
} catch (error) {
this._setStatus(SubscribeFormStatus.Error);
}
}
private _setStatus(status: SubscribeFormStatus): void {
this.setState({ status });
}
}

View File

@@ -1,177 +0,0 @@
import styled from 'styled-components';
import { getCSSPadding, PADDING_SIZES, PaddingInterface } from 'ts/constants/utilities';
interface WrapWidths {
default: string;
full: string;
medium: string;
narrow: string;
[key: string]: string;
}
interface ColumnWidths {
[key: string]: string;
}
interface SectionProps {
isNoPadding?: boolean;
isPadLarge?: boolean;
isNoMargin?: boolean;
bgColor?: string;
isFullWidth?: boolean;
isRelative?: boolean;
}
interface WrapProps extends PaddingInterface {
width?: 'default' | 'full' | 'medium' | 'narrow';
bgColor?: string;
isWrapped?: boolean;
isCentered?: boolean;
isReversed?: boolean;
}
interface ColumnProps {
colWidth?: '1/4' | '1/3' | '1/2' | '2/3';
isNoPadding?: boolean;
isNoMargin?: boolean;
isPadLarge?: boolean;
isFlexGrow?: boolean;
isMobileCentered?: boolean;
bgColor?: string;
}
interface GetColWidthArgs {
span?: number;
columns: number;
}
export interface WrapStickyInterface {
offsetTop?: string;
}
const _getColumnWidth = (args: GetColWidthArgs): string => {
const { span = 1, columns } = args;
const percentWidth = span / columns * 100;
const gutterDiff = GUTTER * (columns - 1) / columns;
return `calc(${percentWidth}% - ${gutterDiff}px)`;
};
const GUTTER = 30 as number;
const MAX_WIDTH = 1500;
export const BREAKPOINTS = {
mobile: '768px',
};
const WRAPPER_WIDTHS: WrapWidths = {
default: `${MAX_WIDTH}px`, // tbd
full: '100%',
medium: '1136px',
narrow: '930px',
};
const COLUMN_WIDTHS: ColumnWidths = {
'1/4': _getColumnWidth({ columns: 4 }),
'1/3': _getColumnWidth({ columns: 3 }),
'1/2': _getColumnWidth({ columns: 2 }),
'2/3': _getColumnWidth({ span: 2, columns: 3 }),
};
export const Main = styled.main`
max-width: ${MAX_WIDTH}px;
margin: 0 auto;
@media (min-width: ${BREAKPOINTS.mobile}) {
width: calc(100% - 60px);
}
`;
// We can also turn Section into a stateless comp,
// passing a asElement (same patter nas Heading) so we dont have to
// make a const on every route to withComponent-size it.
// just <Section asElement?="div/section/footer/header/whatever" /> ?
export const Section =
styled.section <
SectionProps >
`
width: ${props => (props.isFullWidth ? `calc(100% + ${GUTTER * 2}px)` : '100%')};
padding: ${props => !props.isNoPadding && (props.isPadLarge ? `${PADDING_SIZES.large}` : PADDING_SIZES.default)};
background-color: ${props => props.bgColor};
position: ${props => props.isRelative && 'relative'};
overflow: ${props => props.isRelative && 'hidden'};
margin-bottom: ${props => !props.isNoMargin && `${GUTTER}px`};
@media (min-width: 1560px) {
width: ${props => props.isFullWidth && '100vw'};
margin-left: ${props => props.isFullWidth && `calc(750px - 50vw)`};
}
@media (max-width: ${BREAKPOINTS.mobile}) {
margin-bottom: ${props => !props.isNoMargin && `${GUTTER / 2}px`};
padding: ${props =>
props.isPadLarge ? `${PADDING_SIZES.large} ${PADDING_SIZES.default}` : PADDING_SIZES.default};
}
`;
const WrapBase =
styled.div <
WrapProps >
`
max-width: ${props => WRAPPER_WIDTHS[props.width || 'default']};
padding: ${props => props.padding && getCSSPadding(props.padding)};
background-color: ${props => props.bgColor};
margin: 0 auto;
`;
export const Wrap = styled(WrapBase)`
@media (min-width: ${BREAKPOINTS.mobile}) {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
flex-direction: ${props => props.isReversed && 'row-reverse'};
}
`;
export const WrapCentered = styled(WrapBase)`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
`;
export const WrapSticky =
styled.div <
WrapStickyInterface >
`
position: sticky;
top: ${props => props.offsetTop || '60px'};
`;
export const WrapGrid = styled(WrapBase)`
display: flex;
flex-wrap: ${props => props.isWrapped && `wrap`};
justify-content: ${props => (props.isCentered ? `center` : 'space-between')};
`;
export const Column =
styled.div <
ColumnProps >
`
background-color: ${props => props.bgColor};
flex-grow: ${props => props.isFlexGrow && 1};
@media (min-width: ${BREAKPOINTS.mobile}) {
padding: ${props =>
!props.isNoPadding &&
(props.isPadLarge ? `${PADDING_SIZES.large} ${PADDING_SIZES.default}` : PADDING_SIZES.default)};
width: ${props => (props.colWidth ? COLUMN_WIDTHS[props.colWidth] : '100%')};
}
@media (max-width: ${BREAKPOINTS.mobile}) {
padding: ${props => !props.isNoPadding && (props.isPadLarge ? '40px 30px' : 0)};
margin-bottom: 20px;
text-align: ${props => props.isMobileCentered && 'center'};
}
`;
WrapGrid.defaultProps = {
isCentered: true,
};

View File

@@ -1,9 +0,0 @@
import { constants } from 'ts/utils/constants';
interface RedirectorProps {
location: string;
}
export function Redirector(_props: RedirectorProps): void {
window.location.href = constants.URL_ANGELLIST;
}

View File

@@ -1,7 +0,0 @@
import styled from 'styled-components';
export const Separator = styled.hr`
background: #eaeaea;
height: 1px;
border: 0;
`;

View File

@@ -1,18 +0,0 @@
import * as React from 'react';
export interface FilledImageProps {
src: string;
}
export const FilledImage = (props: FilledImageProps) => (
<div
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
backgroundImage: `url(${props.src})`,
backgroundRepeat: 'no-repeat',
backgroundPosition: 'center',
backgroundSize: 'cover',
}}
/>
);

View File

@@ -1,49 +0,0 @@
import { colors } from '@0x/react-shared';
import * as React from 'react';
import { styled } from 'ts/style/theme';
export interface InputProps {
className?: string;
value?: string;
width?: string;
fontSize?: string;
fontColor?: string;
border?: string;
padding?: string;
placeholderColor?: string;
placeholder?: string;
backgroundColor?: string;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
<input className={className} value={value} onChange={onChange} placeholder={placeholder} />
);
export const Input = styled(PlainInput)`
font-size: ${props => props.fontSize};
width: ${props => props.width};
padding: ${props => props.padding};
border-radius: 3px;
box-sizing: border-box;
font-family: 'Roboto Mono';
color: ${props => props.fontColor};
border: ${props => props.border};
outline: none;
background-color: ${props => props.backgroundColor};
&::placeholder {
color: ${props => props.placeholderColor};
}
`;
Input.defaultProps = {
width: 'auto',
backgroundColor: colors.white,
fontColor: colors.darkestGrey,
placeholderColor: colors.darkGrey,
fontSize: '12px',
border: 'none',
padding: '0.8em 1.2em',
};
Input.displayName = 'Input';

View File

@@ -1,17 +0,0 @@
import CircularProgress from 'material-ui/CircularProgress';
import * as React from 'react';
export interface SimpleLoadingProps {
message: string;
}
export const SimpleLoading = (props: SimpleLoadingProps) => {
return (
<div className="mx-auto pt3" style={{ maxWidth: 400, height: 409 }}>
<div className="relative" style={{ top: '50%', transform: 'translateY(-50%)', height: 95 }}>
<CircularProgress />
<div className="pt3 pb3">{props.message}</div>
</div>
</div>
);
};

View File

@@ -1,75 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import Typist from 'react-typist';
import { Text, TextProps } from 'ts/components/ui/text';
import 'react-typist/dist/Typist.css';
export interface TypedTextProps extends TextProps {
textList: string[];
shouldRepeat?: boolean;
wordDelayMs?: number;
avgKeystrokeDelayMs?: number;
stdKeystrokeDelay?: number;
}
export interface TypedTextState {
cycleCount: number;
}
export class TypedText extends React.Component<TypedTextProps, TypedTextState> {
public static defaultProps = {
shouldRepeat: false,
avgKeystrokeDelayMs: 90,
wordDelayMs: 1000,
};
public state = {
cycleCount: 0,
};
public render(): React.ReactNode {
const {
textList,
shouldRepeat,
wordDelayMs,
avgKeystrokeDelayMs,
stdKeystrokeDelay,
// tslint:disable-next-line
...textProps
} = this.props;
const { cycleCount } = this.state;
if (_.isEmpty(textList)) {
return null;
}
const typistChildren: React.ReactNode[] = [];
_.forEach(textList, text => {
typistChildren.push(
<Text key={`text-${text}-${cycleCount}`} {...textProps}>
{text}
</Text>,
);
if (wordDelayMs) {
typistChildren.push(<Typist.Delay key={`delay-${text}-${cycleCount}`} ms={wordDelayMs} />);
}
typistChildren.push(<Typist.Backspace key={`backspace-${text}-${cycleCount}`} count={text.length} />);
});
return (
<Typist
avgTypingDelay={avgKeystrokeDelayMs}
stdTypingDelay={stdKeystrokeDelay}
className="inline"
key={`typist-key-${cycleCount}`}
onTypingDone={this._onTypingDone.bind(this)}
>
{typistChildren}
</Typist>
);
}
private _onTypingDone(): void {
if (this.props.shouldRepeat) {
this.setState({
cycleCount: this.state.cycleCount + 1,
});
}
}
}

View File

@@ -1,25 +0,0 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { About as AboutComponent, AboutProps } from 'ts/pages/about/about';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
}
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, _ownProps: AboutProps): ConnectedState => ({
translate: state.translate,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
export const About: React.ComponentClass<AboutProps> = connect(mapStateToProps, mapDispatchToProps)(AboutComponent);

View File

@@ -1,28 +0,0 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { Jobs as JobsComponent, JobsProps } from 'ts/pages/jobs/jobs';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
screenWidth: ScreenWidths;
}
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, _ownProps: JobsProps): ConnectedState => ({
translate: state.translate,
screenWidth: state.screenWidth,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
export const Jobs: React.ComponentClass<JobsProps> = connect(mapStateToProps, mapDispatchToProps)(JobsComponent);

View File

@@ -1,27 +0,0 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { Landing as LandingComponent, LandingProps } from 'ts/pages/landing/landing';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
}
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, _ownProps: LandingProps): ConnectedState => ({
translate: state.translate,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
export const Landing: React.ComponentClass<LandingProps> = connect(mapStateToProps, mapDispatchToProps)(
LandingComponent,
);

View File

@@ -1,27 +0,0 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { LaunchKit as LaunchKitComponent, LaunchKitProps } from 'ts/pages/launch_kit/launch_kit';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
import { Translate } from 'ts/utils/translate';
interface ConnectedState {
translate: Translate;
}
interface ConnectedDispatch {
dispatcher: Dispatcher;
}
const mapStateToProps = (state: State, _ownProps: LaunchKitProps): ConnectedState => ({
translate: state.translate,
});
const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
dispatcher: new Dispatcher(dispatch),
});
export const LaunchKit: React.ComponentClass<LaunchKitProps> = connect(mapStateToProps, mapDispatchToProps)(
LaunchKitComponent,
);

View File

@@ -1 +0,0 @@
<svg width="22" height="17" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.066 0l-1.068 1.147 6.232 6.557H0v1.592h18.23l-6.232 6.557L13.066 17l8.08-8.5-8.08-8.5z" fill="#CBCBCB"/></svg>

Before

Width:  |  Height:  |  Size: 198 B

View File

@@ -1,421 +0,0 @@
import { colors, Link, Styles } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import { Footer } from 'ts/components/old_footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Profile } from 'ts/pages/about/profile';
import { Dispatcher } from 'ts/redux/dispatcher';
import { ProfileInfo, WebsitePaths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
const teamRow1: ProfileInfo[] = [
{
name: 'Will Warren',
title: 'Co-founder & CEO',
description: `Smart contract R&D. Previously applied physics at Los Alamos \
Nat Lab. Mechanical engineering at UC San Diego. PhD dropout.`,
image: '/images/team/will.jpg',
linkedIn: 'https://www.linkedin.com/in/will-warren-92aab62b/',
github: 'https://github.com/willwarren89',
medium: 'https://medium.com/@willwarren89',
},
{
name: 'Amir Bandeali',
title: 'Co-founder & CTO',
description: `Smart contract R&D. Previously fixed income trader at DRW. \
Finance at University of Illinois, Urbana-Champaign.`,
image: '/images/team/amir.png',
linkedIn: 'https://www.linkedin.com/in/abandeali1/',
github: 'https://github.com/abandeali1',
medium: 'https://medium.com/@abandeali1',
},
{
name: 'Fabio Berger',
title: 'Senior Engineer',
description: `Full-stack blockchain engineer. Previously software engineer \
at Airtable and founder of WealthLift. Computer Science at Duke.`,
image: '/images/team/fabio.jpg',
linkedIn: 'https://www.linkedin.com/in/fabio-berger-03ab261a/',
github: 'https://github.com/fabioberger',
medium: 'https://medium.com/@fabioberger',
},
];
const teamRow2: ProfileInfo[] = [
{
name: 'Alex Xu',
title: 'Director of Operations',
description: `Strategy and operations. Previously digital marketing at Google \
and vendor management at Amazon. Economics at UC San Diego.`,
image: '/images/team/alex.jpg',
linkedIn: 'https://www.linkedin.com/in/alex-xu/',
github: '',
medium: 'https://medium.com/@aqxu',
},
{
name: 'Leonid Logvinov',
title: 'Engineer',
description: `Full-stack blockchain engineer. Previously blockchain engineer \
at Neufund. Computer Science at University of Warsaw.`,
image: '/images/team/leonid.png',
linkedIn: 'https://www.linkedin.com/in/leonidlogvinov/',
github: 'https://github.com/LogvinovLeon',
medium: 'https://medium.com/@Logvinov',
},
{
name: 'Ben Burns',
title: 'Designer',
description: `Product, motion, and graphic designer. Previously designer \
at Airtable and Apple. Digital Design at University of Cincinnati.`,
image: '/images/team/ben.jpg',
linkedIn: 'https://www.linkedin.com/in/ben-burns-30170478/',
github: '',
medium: '',
},
];
const teamRow3: ProfileInfo[] = [
{
name: 'Brandon Millman',
title: 'Senior Engineer',
description: `Full-stack engineer. Previously senior software engineer at \
Twitter. Computer Science and Electrical Engineering at Duke.`,
image: '/images/team/brandon.png',
linkedIn: 'https://www.linkedin.com/in/brandon-millman-b093a022/',
github: 'https://github.com/BMillman19',
medium: 'https://medium.com/@bchillman',
},
{
name: 'Tom Schmidt',
title: 'Product Manager',
description: `Previously engineering at Apple, product management at Facebook and Instagram. Computer Science at Stanford.`,
image: '/images/team/tom.jpg',
linkedIn: 'https://www.linkedin.com/in/tomhschmidt/',
github: 'https://github.com/tomhschmidt',
medium: '',
},
{
name: 'Jacob Evans',
title: 'Ecosystem Engineer',
description: `Previously software engineer at Qantas and RSA Security.`,
image: '/images/team/jacob.jpg',
linkedIn: 'https://www.linkedin.com/in/dekzter/',
github: 'https://github.com/dekz',
medium: '',
},
];
const teamRow4: ProfileInfo[] = [
{
name: 'Blake Henderson',
title: 'Operations Associate',
description: `Operations and Analytics. Previously analytics at LinkedIn. Economics at UC San Diego.`,
image: '/images/team/blake.jpg',
linkedIn: 'https://www.linkedin.com/in/blakerhenderson/',
github: '',
medium: '',
},
{
name: 'Zack Skelly',
title: 'Lead Recruiter',
description: `Talent. Previously first recruiter at Heap, recruiting at Dropbox and Google. English Rhetoric and Composition at Pepperdine.`,
image: '/images/team/zach.png',
linkedIn: 'https://www.linkedin.com/in/zackaryskelly/',
github: '',
medium: '',
},
{
name: 'Greg Hysen',
title: 'Blockchain Engineer',
description: `Smart contract R&D. Previously lead distributed systems engineer at Hivemapper. Computer Science at University of Waterloo.`,
image: '/images/team/greg.jpeg',
linkedIn: 'https://www.linkedin.com/in/gregory-hysen-71741463/',
github: 'https://github.com/hysz',
medium: '',
},
];
const teamRow5: ProfileInfo[] = [
{
name: 'Remco Bloemen',
title: 'Technical Fellow',
description: `Previously cofounder at Neufund and Coblue. Part III at Cambridge. PhD dropout at Twente Business School.`,
image: '/images/team/remco.jpeg',
linkedIn: 'https://www.linkedin.com/in/remcobloemen/',
github: 'http://github.com/recmo',
medium: '',
},
{
name: 'Francesco Agosti',
title: 'Engineer',
description: `Full-stack engineer. Previously senior software engineer at Yelp. Computer Science at Duke.`,
image: 'images/team/fragosti.png',
linkedIn: 'https://www.linkedin.com/in/fragosti/',
github: 'http://github.com/fragosti',
},
{
name: 'Mel Oberto',
title: 'Office Ops / Executive Assistant',
description: `Daily Operations. Previously People Operations Associate at Heap. Marketing and MBA at Sacred Heart University.`,
image: 'images/team/mel.png',
linkedIn: 'https://www.linkedin.com/in/melanieoberto',
},
];
const teamRow6: ProfileInfo[] = [
{
name: 'Alex Browne',
title: 'Engineer in Residence',
description: `Full-stack blockchain engineer. Previously at Plaid. Open source guru and footgun dismantler. Computer Science and Electrical Engineering at Duke.`,
image: 'images/team/alexbrowne.png',
linkedIn: 'https://www.linkedin.com/in/stephenalexbrowne/',
github: 'http://github.com/albrow',
},
{
name: 'Peter Zeitz',
title: 'Research Fellow',
description: `Researching decentralized governance. Previously Assistant Professor of Economics at National University of Singapore Business School. PhD in Economics at UCLA.`,
image: 'images/team/peter.jpg',
linkedIn: 'https://www.linkedin.com/in/peter-z-7b9595163/',
},
{
name: 'Chris Kalani',
title: 'Director of Design',
description: `Previously founded Wake (acquired by InVision). Early Facebook product designer.`,
image: 'images/team/chris.png',
linkedIn: 'https://www.linkedin.com/in/chriskalani/',
github: 'https://github.com/chriskalani',
},
];
const teamRow7: ProfileInfo[] = [
{
name: 'Clay Robbins',
title: 'Ecosystem Development Lead',
description: `Growth & Business Development. Previously product and partnerships at Square. Economics at Dartmouth College.`,
image: 'images/team/clay.png',
linkedIn: 'https://www.linkedin.com/in/robbinsclay/',
},
{
name: 'Matt Taylor',
title: 'Marketing Lead',
description: `Growth & Marketing. Previously marketing at Abra and Square. Economics and Philosophy at Claremont McKenna College.`,
image: 'images/team/matt.jpg',
linkedIn: 'https://www.linkedin.com/in/mattytay/',
},
{
name: 'Eugene Aumson',
title: 'Engineer',
description: `Developer Experience. Previously senior software engineer in foreign exchange applications at Bloomberg LP.`,
image: 'images/team/gene.jpg',
linkedIn: 'https://www.linkedin.com/in/aumson/',
github: 'https://github.com/feuGeneA',
},
];
const teamRow8: ProfileInfo[] = [
{
name: 'Weijie Wu',
title: 'Research Fellow',
description: `Researching decentralized governance. Previously Researcher at Huawei and Assistant Professor at Shanghai Jiao Tong University. PhD in Computer Science at The Chinese University of Hong Kong.`,
image: 'images/team/weijie.png',
linkedIn: 'https://www.linkedin.com/in/weijiewu/',
},
{
name: 'Rahul Singireddy',
title: 'Relayer Success Manager',
description: `Previously community at Zeppelin, growth at Dharma, and cryptocurrency contributor at Forbes. Symbolic Systems at Stanford.`,
image: 'images/team/rahul.png',
linkedIn: 'https://www.linkedin.com/in/rahul-singireddy-3037908a/',
},
{
name: 'Jason Somensatto',
title: 'Strategic Legal Counsel',
description: `Legal. Previously head of blockchain and crypto practice at Orrick. JD from George Washington University and undergrad at UVA.`,
image: 'images/team/jason.png',
linkedIn: 'https://www.linkedin.com/in/jasonsomensatto/',
},
];
const teamRow9: ProfileInfo[] = [
{
name: 'Steve Klebanoff',
title: 'Senior Engineer',
description: ` Full-stack engineer. Previously Staff Software Engineer at AppFolio. Computer Science & Cognitive Psychology at Northeastern University.`,
image: 'images/team/steve.png',
linkedIn: 'https://www.linkedin.com/in/steveklebanoff/',
github: 'https://github.com/steveklebanoff',
},
{
name: 'Xianny Ng',
title: 'Engineer',
description: `Developer Experience. Previously telemetry at Mapbox and platform engineering at Bench Accounting.`,
image: 'images/team/xianny.png',
linkedIn: 'https://www.linkedin.com/in/xianny/',
github: 'https://github.com/xianny',
},
];
const advisors1: ProfileInfo[] = [
{
name: 'Fred Ehrsam',
description: 'Co-founder of Coinbase. Previously FX trader at Goldman Sachs.',
image: '/images/advisors/fred.jpg',
linkedIn: 'https://www.linkedin.com/in/fredehrsam/',
medium: 'https://medium.com/@FEhrsam',
twitter: 'https://twitter.com/FEhrsam',
},
{
name: 'Olaf Carlson-Wee',
image: '/images/advisors/olaf.png',
description: 'Founder of Polychain Capital. First hire at Coinbase. Angel investor.',
linkedIn: 'https://www.linkedin.com/in/olafcw/',
angellist: 'https://angel.co/olafcw',
},
{
name: 'Joey Krug',
description: `Co-CIO at Pantera Capital. Founder of Augur. Thiel 20 Under 20 Fellow.`,
image: '/images/advisors/joey.jpg',
linkedIn: 'https://www.linkedin.com/in/joeykrug/',
github: 'https://github.com/joeykrug',
angellist: 'https://angel.co/joeykrug',
},
];
const advisors2: ProfileInfo[] = [
{
name: 'Linda Xie',
description: 'Co-founder of Scalar Capital. Previously PM at Coinbase.',
image: '/images/advisors/linda.jpg',
linkedIn: 'https://www.linkedin.com/in/lindaxie/',
medium: 'https://medium.com/@linda.xie',
twitter: 'https://twitter.com/ljxie',
},
{
name: 'David Sacks',
description: 'General Partner at Craft Ventures. Original COO of PayPal. Founder of Yammer.',
image: '/images/advisors/david.png',
linkedIn: 'https://www.linkedin.com/in/davidoliversacks/',
medium: 'https://medium.com/@davidsacks',
twitter: 'https://twitter.com/DavidSacks',
},
];
export interface AboutProps {
source: string;
location: Location;
translate: Translate;
dispatcher: Dispatcher;
}
interface AboutState {}
const styles: Styles = {
header: {
fontFamily: 'Roboto Mono',
fontSize: 36,
color: 'black',
paddingTop: 110,
},
weAreHiring: {
fontSize: 30,
color: colors.darkestGrey,
fontFamily: 'Roboto Mono',
letterSpacing: 7.5,
},
};
export class About extends React.Component<AboutProps, AboutState> {
public componentDidMount(): void {
window.scrollTo(0, 0);
}
public render(): React.ReactNode {
return (
<div style={{ backgroundColor: colors.lightestGrey }}>
<DocumentTitle title="0x About Us" />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
style={{ backgroundColor: colors.lightestGrey }}
translate={this.props.translate}
/>
<div id="about" className="mx-auto max-width-4 py4" style={{ color: colors.grey800 }}>
<div className="mx-auto pb4 sm-px3" style={{ maxWidth: 435 }}>
<div style={styles.header}>About us:</div>
<div
className="pt3"
style={{
fontSize: 17,
color: colors.darkestGrey,
lineHeight: 1.5,
}}
>
Our team is a globally distributed group with backgrounds in engineering, research, business
and design. We are passionate about decentralized technology and its potential to act as an
equalizing force in the world.
</div>
</div>
<div className="pt3 md-px4 lg-px0">
<div className="clearfix pb3">{this._renderProfiles(teamRow1)}</div>
<div className="clearfix">{this._renderProfiles(teamRow2)}</div>
<div className="clearfix">{this._renderProfiles(teamRow3)}</div>
<div className="clearfix">{this._renderProfiles(teamRow4)}</div>
<div className="clearfix">{this._renderProfiles(teamRow5)}</div>
<div className="clearfix">{this._renderProfiles(teamRow6)}</div>
<div className="clearfix">{this._renderProfiles(teamRow7)}</div>
<div className="clearfix">{this._renderProfiles(teamRow8)}</div>
<div className="clearfix">{this._renderProfiles(teamRow9)}</div>
</div>
<div className="pt3 pb2">
<div
className="pt2 pb3 sm-center md-pl4 lg-pl0 md-ml3"
style={{
color: colors.grey,
fontSize: 24,
fontFamily: 'Roboto Mono',
}}
>
Advisors:
</div>
<div className="clearfix">{this._renderProfiles(advisors1)}</div>
<div className="clearfix">{this._renderProfiles(advisors2)}</div>
</div>
<div className="mx-auto py4 sm-px3" style={{ maxWidth: 308 }}>
<div className="pb2" style={styles.weAreHiring}>
WE'RE HIRING
</div>
<div
className="pb4 mb4"
style={{
fontSize: 16,
color: colors.darkestGrey,
lineHeight: 1.5,
letterSpacing: '0.5px',
}}
>
We are seeking outstanding candidates to{' '}
<Link to={WebsitePaths.Careers} textDecoration="underline" fontColor="black">
join our team
</Link>
. We value passion, diversity and unique perspectives.
</div>
</div>
</div>
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
</div>
);
}
private _renderProfiles(profiles: ProfileInfo[]): React.ReactNode {
const numIndiv = profiles.length;
const colSize = utils.getColSize(numIndiv);
return _.map(profiles, profile => {
return (
<div key={`profile-${profile.name}`}>
<Profile colSize={colSize} profileInfo={profile} />
</div>
);
});
}
}

View File

@@ -1,80 +0,0 @@
import { colors, Styles } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import { ProfileInfo } from 'ts/types';
const IMAGE_DIMENSION = 149;
const styles: Styles = {
subheader: {
textTransform: 'uppercase',
fontSize: 32,
margin: 0,
},
imageContainer: {
width: IMAGE_DIMENSION,
height: IMAGE_DIMENSION,
boxShadow: 'rgba(0, 0, 0, 0.19) 2px 5px 10px',
},
};
interface ProfileProps {
colSize: number;
profileInfo: ProfileInfo;
}
export const Profile = (props: ProfileProps) => {
return (
<div className={`lg-col md-col lg-col-${props.colSize} md-col-6`}>
<div style={{ maxWidth: 300 }} className="mx-auto lg-px3 md-px3 sm-px4 sm-pb3">
<div className="circle overflow-hidden mx-auto" style={styles.imageContainer}>
<img width={IMAGE_DIMENSION} src={props.profileInfo.image} />
</div>
<div className="center" style={{ fontSize: 18, fontWeight: 'bold', paddingTop: 20 }}>
{props.profileInfo.name}
</div>
{!_.isUndefined(props.profileInfo.title) && (
<div
className="pt1 center"
style={{
fontSize: 14,
fontFamily: 'Roboto Mono',
color: colors.darkGrey,
whiteSpace: 'nowrap',
}}
>
{props.profileInfo.title.toUpperCase()}
</div>
)}
<div style={{ minHeight: 60, lineHeight: 1.4 }} className="pt1 pb2 mx-auto lg-h6 md-h6 sm-h5 sm-center">
{props.profileInfo.description}
</div>
<div className="flex pb3 sm-hide xs-hide" style={{ width: 280, opacity: 0.5 }}>
{renderSocialMediaIcons(props.profileInfo)}
</div>
</div>
</div>
);
};
function renderSocialMediaIcons(profileInfo: ProfileInfo): React.ReactNode {
const icons = [
renderSocialMediaIcon('zmdi-github-box', profileInfo.github),
renderSocialMediaIcon('zmdi-linkedin-box', profileInfo.linkedIn),
renderSocialMediaIcon('zmdi-twitter-box', profileInfo.twitter),
];
return icons;
}
function renderSocialMediaIcon(iconName: string, url: string): React.ReactNode {
if (_.isEmpty(url)) {
return null;
}
return (
<div key={url} className="pr1">
<a href={url} style={{ color: 'inherit' }} target="_blank" className="text-decoration-none">
<i className={`zmdi ${iconName}`} style={{ ...styles.socalIcon }} />
</a>
</div>
);
}

View File

@@ -1,57 +0,0 @@
import * as React from 'react';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { ScreenWidths } from 'ts/types';
export interface Introducing0xInstantProps {
screenWidth: ScreenWidths;
onCTAClick: () => void;
}
export const Introducing0xInstant = (props: Introducing0xInstantProps) => {
const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
const zero = (
<Text fontColor={colors.white} fontSize="42px" fontWeight="600" fontFamily="Roboto Mono" Tag="span">
0
</Text>
);
const title = isSmallScreen ? (
<div>
Introducing<br />
{zero}x Instant
</div>
) : (
<div>Introducing {zero}x Instant</div>
);
return (
<div className="clearfix center lg-pt4 md-pt4" style={{ backgroundColor: colors.instantPrimaryBackground }}>
<div className="mx-auto inline-block align-middle py4" style={{ lineHeight: '44px', textAlign: 'center' }}>
<Container className="sm-center sm-pt3">
<Text fontColor={colors.white} fontSize="42px" lineHeight="52px" fontWeight="600">
{title}
</Text>
</Container>
<Container className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 sm-center" maxWidth="600px">
<Text fontColor={colors.grey500} fontSize="20px" lineHeight="32px" fontFamily="Roboto Mono">
A free and flexible way to offer simple crypto
<br /> purchasing in any app or website.
</Text>
</Container>
<div className="py3">
<Button
type="button"
backgroundColor={colors.mediumBlue}
fontColor={colors.white}
fontSize="18px"
onClick={props.onCTAClick}
>
Get Started
</Button>
</div>
</div>
</div>
);
};

View File

@@ -1,62 +0,0 @@
import * as React from 'react';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { utils } from 'ts/utils/utils';
export interface NeedMoreProps {
screenWidth: ScreenWidths;
}
export const NeedMore = (props: NeedMoreProps) => {
const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
const backgroundColor = isSmallScreen ? colors.instantTertiaryBackground : colors.instantSecondaryBackground;
const className = isSmallScreen ? 'flex flex-column items-center' : 'flex';
const marginRight = isSmallScreen ? undefined : '200px';
return (
<Container className="flex flex-column items-center py4 px3" backgroundColor={backgroundColor}>
<Container className={className}>
<Container className="sm-center" marginRight={marginRight}>
<Text fontColor={colors.white} fontSize="32px" lineHeight="45px">
Need more flexibility?
</Text>
<Text fontColor={colors.grey500} fontSize="18px" lineHeight="27px">
View our full documentation or reach out if you have any questions.
</Text>
</Container>
<Container className="py3 flex">
<Container marginRight="20px">
<Button
type="button"
backgroundColor={colors.white}
fontColor={backgroundColor}
fontSize="18px"
onClick={onGetInTouchClick}
>
Get in Touch
</Button>
</Container>
<Button
type="button"
backgroundColor={colors.mediumBlue}
fontColor={colors.white}
fontSize="18px"
onClick={onDocsClick}
>
Explore the Docs
</Button>
</Container>
</Container>
</Container>
);
};
const onGetInTouchClick = () => {
utils.openUrl(constants.URL_ZEROEX_CHAT);
};
const onDocsClick = () => {
utils.openUrl(`${WebsitePaths.Wiki}#Get-Started-With-Instant`);
};

View File

@@ -1,35 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { colors } from 'ts/style/colors';
import { ScreenWidths } from 'ts/types';
export interface ScreenshotsProps {
screenWidth: ScreenWidths;
}
export const Screenshots = (props: ScreenshotsProps) => {
const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
const images = isSmallScreen
? [
'images/instant/rep_screenshot.png',
'images/instant/dai_screenshot.png',
'images/instant/gods_screenshot.png',
]
: [
'images/instant/nmr_screenshot.png',
'images/instant/kitty_screenshot.png',
'images/instant/rep_screenshot.png',
'images/instant/dai_screenshot.png',
'images/instant/gods_screenshot.png',
'images/instant/gnt_screenshot.png',
];
return (
<Container backgroundColor={colors.instantPrimaryBackground} className="py3 flex justify-center">
{_.map(images, image => {
return <img className="px1 flex-none" width="300px" height="420px" src={image} key={image} />;
})}
</Container>
);
};

View File

@@ -1,158 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { Circle } from 'ts/components/ui/circle';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { styled } from 'ts/style/theme';
import { ScreenWidths } from 'ts/types';
import { constants } from 'ts/utils/constants';
const BENEFITS = [
'Comprehensive insurance (medical, dental, and vision)',
'Unlimited vacation (three weeks per year minimum)',
'Meals and snacks provided in-office daily',
'Flexible hours and liberal work-from-home-policy',
'Supportive remote working environment',
'Transportation, phone, and wellness expense',
'Relocation assistance',
'Optional team excursions (fully paid, often international)',
'Competitive salary and cryptocurrency-based compensation',
];
interface Value {
iconSrc: string;
text: string;
}
const VALUES: Value[] = [
{
iconSrc: 'images/jobs/heart-icon.svg',
text: 'Do the right thing',
},
{
iconSrc: 'images/jobs/ship-icon.svg',
text: 'Consistently ship',
},
{
iconSrc: 'images/jobs/calendar-icon.svg',
text: 'Focus on long term impact',
},
];
export interface BenefitsProps {
screenWidth: ScreenWidths;
}
export const Benefits = (props: BenefitsProps) => {
const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
return (
<Container className="flex flex-column items-center py4 px3" backgroundColor={colors.white}>
{!isSmallScreen ? (
<Container className="flex" maxWidth="1200px">
<BenefitsList />
<Container marginLeft="120px">
<ValuesList />
</Container>
</Container>
) : (
<Container className="flex-column">
<BenefitsList />
<Container marginTop="50px">
<ValuesList />
</Container>
</Container>
)}
</Container>
);
};
const Header: React.StatelessComponent = ({ children }) => (
<Container marginBottom="30px">
<Text fontFamily="Roboto Mono" fontSize="24px" fontColor={colors.black}>
{children}
</Text>
</Container>
);
interface BenefitsListProps {
className?: string;
}
const PlainBenefitsList: React.StatelessComponent<BenefitsListProps> = ({ className }) => {
return (
<Container className={className}>
<Header>Benefits</Header>
{_.map(BENEFITS, benefit => <BenefitItem key={benefit} description={benefit} />)}
</Container>
);
};
const BenefitsList = styled(PlainBenefitsList)`
transform: translateY(30px);
`;
interface BenefitItemProps {
description: string;
}
const BenefitItem: React.StatelessComponent<BenefitItemProps> = ({ description }) => (
<Container marginBottom="15px">
<div className="flex">
<Circle className="flex-none pr2 pt1" diameter={8} fillColor={colors.black} />
<div className="flex-auto">
<Text fontSize="14px" lineHeight="24px">
{description}
</Text>
</div>
</div>
</Container>
);
interface ValuesListProps {
className?: string;
}
const PlainValuesList: React.StatelessComponent<ValuesListProps> = ({ className }) => {
return (
<Container className={className} maxWidth="270px">
<Header>Our Values</Header>
{_.map(VALUES, value => <ValueItem key={value.text} {...value} />)}
<Text fontSize="14px" lineHeight="26px">
We care deeply about our culture and values, and encourage you to{' '}
<a
style={{ color: colors.mediumBlue, textDecoration: 'none' }}
target="_blank"
href={constants.URL_MISSION_AND_VALUES_BLOG_POST}
>
read more on our blog
</a>.
</Text>
</Container>
);
};
const ValuesList = styled(PlainValuesList)`
border-color: ${colors.beigeWhite};
border-radius: 7px;
border-width: 1px;
border-style: solid;
padding-left: 38px;
padding-right: 38px;
padding-top: 28px;
padding-bottom: 28px;
`;
type ValueItemProps = Value;
const ValueItem: React.StatelessComponent<ValueItemProps> = ({ iconSrc, text }) => {
return (
<Container marginBottom="25px">
<div className="flex items-center">
<Image className="flex-none pr2" width="20px" src={iconSrc} />
<div className="flex-auto">
<Text fontSize="14px" lineHeight="24px" fontWeight="bold">
{text}
</Text>
</div>
</div>
</Container>
);
};

View File

@@ -1,71 +0,0 @@
import { colors, utils as sharedUtils } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
import { MetaTags } from 'ts/components/meta_tags';
import { Footer } from 'ts/components/old_footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Container } from 'ts/components/ui/container';
import { Benefits } from 'ts/pages/jobs/benefits';
import { Join0x } from 'ts/pages/jobs/join_0x';
import { Mission } from 'ts/pages/jobs/mission';
import { OpenPositions } from 'ts/pages/jobs/open_positions';
import { Dispatcher } from 'ts/redux/dispatcher';
import { ScreenWidths } from 'ts/types';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
const OPEN_POSITIONS_HASH = 'positions';
const THROTTLE_TIMEOUT = 100;
const DOCUMENT_TITLE = 'Careers at 0x';
const DOCUMENT_DESCRIPTION = 'Join 0x in creating a tokenized world where all value can flow freely';
export interface JobsProps {
location: Location;
translate: Translate;
dispatcher: Dispatcher;
screenWidth: ScreenWidths;
}
export interface JobsState {}
export class Jobs extends React.Component<JobsProps, JobsState> {
// TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well)
private readonly _throttledScreenWidthUpdate: () => void;
public constructor(props: JobsProps) {
super(props);
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
}
public componentDidMount(): void {
window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public render(): React.ReactNode {
return (
<Container overflowX="hidden">
<MetaTags title={DOCUMENT_TITLE} description={DOCUMENT_DESCRIPTION} />
<DocumentTitle title={DOCUMENT_TITLE} />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
style={{ backgroundColor: colors.white, position: 'relative' }}
translate={this.props.translate}
/>
<Join0x onCallToActionClick={this._onJoin0xCallToActionClick.bind(this)} />
<Mission screenWidth={this.props.screenWidth} />
<Benefits screenWidth={this.props.screenWidth} />
<OpenPositions hash={OPEN_POSITIONS_HASH} screenWidth={this.props.screenWidth} />
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
</Container>
);
}
private _onJoin0xCallToActionClick(): void {
sharedUtils.setUrlHash(OPEN_POSITIONS_HASH);
sharedUtils.scrollToHash(OPEN_POSITIONS_HASH, '');
}
private _updateScreenWidth(): void {
const newScreenWidth = utils.getScreenWidth();
this.props.dispatcher.updateScreenWidth(newScreenWidth);
}
}

View File

@@ -1,64 +0,0 @@
import { colors } from '@0x/react-shared';
import * as React from 'react';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { constants } from 'ts/utils/constants';
const BUTTON_TEXT = 'View open positions';
export interface Join0xProps {
onCallToActionClick: () => void;
}
export const Join0x = (props: Join0xProps) => (
<div className="clearfix center lg-py4 md-py4" style={{ backgroundColor: colors.white, color: colors.black }}>
<div
className="mx-auto inline-block align-middle py4"
style={{ lineHeight: '44px', textAlign: 'center', position: 'relative' }}
>
<Container className="sm-hide xs-hide" position="absolute" left="100%" marginLeft="80px">
<Image src="images/jobs/hero-dots-right.svg" width="400px" />
</Container>
<Container className="sm-hide xs-hide" position="absolute" right="100%" marginRight="80px">
<Image src="images/jobs/hero-dots-left.svg" width="400px" />
</Container>
<div className="h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
Join Us in Our Mission
</div>
<Container className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 sm-center" maxWidth="537px">
<Text fontSize="14px" lineHeight="30px">
At 0x, our mission is to create a tokenized world where all value can flow freely.
<br />
<br />We are powering a growing ecosystem of decentralized applications and solving novel challenges
to make our technology intuitive, flexible, and accessible to all.{' '}
<a
style={{ color: colors.mediumBlue, textDecoration: 'none' }}
target="_blank"
href={constants.URL_MISSION_AND_VALUES_BLOG_POST}
>
Read more
</a>{' '}
about our mission, and join us in building financial infrastructure upon which the exchange of
anything of value will take place.
</Text>
</Container>
<div className="py3">
<Button
type="button"
backgroundColor={colors.black}
width="290px"
fontColor={colors.white}
fontSize="18px"
fontFamily="Roboto Mono"
onClick={props.onCallToActionClick}
>
{BUTTON_TEXT}
</Button>
</div>
</div>
</div>
);

View File

@@ -1,47 +0,0 @@
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { ScreenWidths } from 'ts/types';
export interface MissionProps {
screenWidth: ScreenWidths;
}
export const Mission = (props: MissionProps) => {
const shouldShowImage = props.screenWidth === ScreenWidths.Lg;
const image = <Image src="/images/jobs/world-map.svg" maxWidth="500px" maxHeight="280px" />;
const missionStatementClassName = !shouldShowImage ? 'center' : undefined;
const missionStatement = (
<Container className={missionStatementClassName} maxWidth="388px">
<Text fontFamily="Roboto Mono" fontSize="22px" lineHeight="31px">
Powered by a Diverse<br />Worldwide Community
</Text>
<Container marginTop="32px">
<Text fontSize="14px" lineHeight="2em">
We're a highly technical team with varied backgrounds in engineering, science, business, finance,
and research. While the core team is headquartered in San Francisco, there are 30+ teams building on
0x and hundreds of thousands of participants behind our efforts globally. We're passionate about
open-source software and decentralized technology's potential to act as an equalizing force in the
world.
</Text>
</Container>
</Container>
);
return (
<div
className="flex flex-column items-center py4 px3"
style={{ backgroundColor: colors.jobsPageBackground, color: colors.black }}
>
{shouldShowImage ? (
<Container className="flex items-center" maxWidth="1200px">
{image}
<Container marginLeft="115px">{missionStatement}</Container>
</Container>
) : (
<Container className="flex flex-column items-center">{missionStatement}</Container>
)}
</div>
);
};

View File

@@ -1,179 +0,0 @@
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
import * as React from 'react';
import { Container } from 'ts/components/ui/container';
import { Retry } from 'ts/components/ui/retry';
import { Text } from 'ts/components/ui/text';
import { colors } from 'ts/style/colors';
import { styled } from 'ts/style/theme';
import { ScreenWidths, WebsiteBackendJobInfo } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
import { constants } from 'ts/utils/constants';
import { utils } from 'ts/utils/utils';
const TABLE_ROW_MIN_HEIGHT = 100;
export interface OpenPositionsProps {
hash: string;
screenWidth: ScreenWidths;
}
export interface OpenPositionsState {
jobInfos?: WebsiteBackendJobInfo[];
error?: Error;
}
export class OpenPositions extends React.Component<OpenPositionsProps, OpenPositionsState> {
private _isUnmounted: boolean;
constructor(props: OpenPositionsProps) {
super(props);
this._isUnmounted = false;
this.state = {
jobInfos: undefined,
error: undefined,
};
}
public componentWillMount(): void {
// tslint:disable-next-line:no-floating-promises
this._fetchJobInfosAsync();
}
public componentWillUnmount(): void {
this._isUnmounted = true;
}
public render(): React.ReactNode {
const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.jobInfos);
const isSmallScreen = utils.isMobileWidth(this.props.screenWidth);
return (
<Container id={this.props.hash} className="mx-auto pb4 px3 max-width-4">
{!isSmallScreen && (
<hr style={{ border: 0, borderTop: 1, borderStyle: 'solid', borderColor: colors.beigeWhite }} />
)}
<Container marginTop="64px" marginBottom="50px">
<Text fontFamily="Roboto Mono" fontSize="24px" fontColor={colors.black}>
Open Positions
</Text>
</Container>
{isReadyToRender ? this._renderTable() : this._renderLoading()}
</Container>
);
}
private _renderLoading(): React.ReactNode {
return (
// TODO: consolidate this loading component with the one in portal and RelayerIndex
// TODO: possibly refactor into a generic loading container with spinner and retry UI
<div className="center">
{_.isUndefined(this.state.error) ? (
<CircularProgress size={40} thickness={5} />
) : (
<Retry onRetry={this._fetchJobInfosAsync.bind(this)} />
)}
</div>
);
}
private _renderTable(): React.ReactNode {
return (
<Container width="100%">
<div>
{_.map(this.state.jobInfos, jobInfo => {
return (
<JobInfoTableRow
key={jobInfo.id}
screenWidth={this.props.screenWidth}
jobInfo={jobInfo}
onClick={this._openJobInfoUrl.bind(this, jobInfo)}
/>
);
})}
</div>
<Container className="center" marginTop="70px">
<Text fontStyle="italic" fontSize="14px">
Interested in telling us why you'd be a valuable addition to the team outside of the positions
listed above?{' '}
<a
style={{ color: colors.mediumBlue, textDecoration: 'none' }}
href={`mailto:${constants.EMAIL_JOBS}`}
>
Email us!
</a>
</Text>
</Container>
</Container>
);
}
private async _fetchJobInfosAsync(): Promise<void> {
try {
if (!this._isUnmounted) {
this.setState({
jobInfos: undefined,
error: undefined,
});
}
const jobInfos = await backendClient.getJobInfosAsync();
if (!this._isUnmounted) {
this.setState({
jobInfos,
});
}
} catch (error) {
if (!this._isUnmounted) {
this.setState({
error,
});
}
}
}
private _openJobInfoUrl(jobInfo: WebsiteBackendJobInfo): void {
const url = jobInfo.url;
utils.openUrl(url);
}
}
export interface JobInfoTableRowProps {
className?: string;
screenWidth: ScreenWidths;
jobInfo: WebsiteBackendJobInfo;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
}
const PlainJobInfoTableRow: React.StatelessComponent<JobInfoTableRowProps> = ({
className,
screenWidth,
jobInfo,
onClick,
}) => {
const isSmallScreen = screenWidth === ScreenWidths.Sm;
const titleClassName = isSmallScreen ? 'col col-12 center' : 'col col-5';
const paddingLeft = isSmallScreen ? undefined : '30px';
return (
<Container className={className} onClick={onClick} marginBottom="30px" paddingLeft={paddingLeft}>
<Container className="flex items-center" minHeight={TABLE_ROW_MIN_HEIGHT} width="100%">
<Container className="clearfix container" width="100%">
<Container className={titleClassName}>
<Text fontSize="16px" fontWeight="bold" fontColor={colors.mediumBlue}>
{jobInfo.title}
</Text>
</Container>
{!isSmallScreen && (
<Container className="col col-3">
<Text fontSize="16px">{jobInfo.department}</Text>
</Container>
)}
{!isSmallScreen && (
<Container className="col col-4 center">
<Text fontSize="16px">{jobInfo.office}</Text>
</Container>
)}
</Container>
</Container>
</Container>
);
};
export const JobInfoTableRow = styled(PlainJobInfoTableRow)`
cursor: pointer;
background-color: ${colors.grey100};
border-radius: 7px;
&:hover {
opacity: 0.5;
}
`;

View File

@@ -1,22 +0,0 @@
import * as _ from 'lodash';
import * as React from 'react';
import { FilledImage } from 'ts/components/ui/filled_image';
export interface PhotoRailProps {
images: string[];
}
export const PhotoRail = (props: PhotoRailProps) => {
return (
<div className="clearfix" style={{ height: 490 }}>
{_.map(props.images, (image: string) => {
return (
<div key={image} className="col lg-col-4 md-col-4 col-12 center" style={{ height: '100%' }}>
<FilledImage src={image} />
</div>
);
})}
</div>
);
};

View File

@@ -1,620 +0,0 @@
import { colors, Link } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import DocumentTitle from 'react-document-title';
import { SubscribeForm } from 'ts/components/forms/subscribe_form';
import { Footer } from 'ts/components/old_footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { CallToAction } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { TypedText } from 'ts/components/ui/typed_text';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
interface BoxContent {
title: string;
description: string;
imageUrl: string;
classNames: string;
maxWidth: number;
}
interface UseCase {
imageUrl: string;
type: string;
description: string;
classNames: string;
style?: React.CSSProperties;
}
interface Project {
logoFileName: string;
projectUrl: string;
}
const THROTTLE_TIMEOUT = 100;
const WHATS_NEW_TITLE = 'Introducing 0x Instant';
const WHATS_NEW_URL = WebsitePaths.Instant;
const TITLE_STYLE: React.CSSProperties = {
fontFamily: 'Roboto Mono',
color: colors.grey,
fontWeight: 300,
letterSpacing: 3,
};
const ROTATING_LIST = [
'tokens',
'game items',
'digital art',
'futures',
'stocks',
'derivatives',
'loans',
'cats',
'everything',
];
const relayerProjects: Project[] = [
{
logoFileName: 'ethfinex.png',
projectUrl: constants.PROJECT_URL_ETHFINEX,
},
{
logoFileName: 'radar_relay.png',
projectUrl: constants.PROJECT_URL_RADAR_RELAY,
},
{
logoFileName: 'paradex.png',
projectUrl: constants.PROJECT_URL_PARADEX,
},
{
logoFileName: 'the_ocean.png',
projectUrl: constants.PROJECT_URL_0CEAN,
},
{
logoFileName: 'amadeus.png',
projectUrl: constants.PROJECT_URL_AMADEUS,
},
{
logoFileName: 'ddex.png',
projectUrl: constants.PROJECT_URL_DDEX,
},
{
logoFileName: 'decent_ex.png',
projectUrl: constants.PROJECT_URL_DECENT_EX,
},
{
logoFileName: 'dextroid.png',
projectUrl: constants.PROJECT_URL_DEXTROID,
},
{
logoFileName: 'ercdex.png',
projectUrl: constants.PROJECT_URL_ERC_DEX,
},
{
logoFileName: 'open_relay.png',
projectUrl: constants.PROJECT_URL_OPEN_RELAY,
},
{
logoFileName: 'idt.png',
projectUrl: constants.PROJECT_URL_IDT,
},
{
logoFileName: 'imtoken.png',
projectUrl: constants.PROJECT_URL_IMTOKEN,
},
];
export interface LandingProps {
location: Location;
translate: Translate;
dispatcher: Dispatcher;
}
interface LandingState {
screenWidth: ScreenWidths;
}
export class Landing extends React.Component<LandingProps, LandingState> {
private readonly _throttledScreenWidthUpdate: () => void;
constructor(props: LandingProps) {
super(props);
this.state = {
screenWidth: utils.getScreenWidth(),
};
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
}
public componentDidMount(): void {
window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public componentWillUnmount(): void {
window.removeEventListener('resize', this._throttledScreenWidthUpdate);
}
public render(): React.ReactNode {
return (
<div id="landing" className="clearfix" style={{ color: colors.grey500 }}>
<DocumentTitle title="0x Protocol" />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
isNightVersion={true}
style={{ backgroundColor: colors.heroGrey, position: 'relative' }}
translate={this.props.translate}
/>
{this._renderHero()}
{this._renderProjects(
relayerProjects,
this.props.translate.get(Key.RelayersHeader, Deco.Upper),
colors.projectsGrey,
true,
)}
{this._renderInfoBoxes()}
{this._renderTokenizationSection()}
{this._renderUseCases()}
{this._renderCallToAction()}
<Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
</div>
);
}
private _renderHero(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const left = 'col lg-col-6 md-col-6 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
const flexClassName = isSmallScreen
? 'flex items-center flex-column justify-center'
: 'flex items-center justify-center';
return (
<div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 clearfix">
{this._renderWhatsNew()}
<div className={`${flexClassName} lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4`}>
<Container marginTop="30px" marginBottom="30px" marginLeft="15px" marginRight="15px">
<Image src="/images/landing/0x_homepage.svg" maxWidth="100%" height="auto" />
</Container>
<div className={left} style={{ color: colors.white, height: 390, lineHeight: '390px' }}>
<div
className="inline-block lg-align-middle md-align-middle sm-align-top"
style={{
paddingLeft: isSmallScreen ? 0 : 12,
lineHeight: '36px',
}}
>
<Text
className="sm-pb2"
fontFamily="Roboto"
display="inline-block"
fontColor={colors.grey300}
fontWeight={500}
lineHeight="1.3em"
fontSize={isSmallScreen ? '28px' : '36px'}
>
{this.props.translate.get(Key.TopHeader, Deco.Cap)}
{this.props.translate.getLanguage() === Language.English && (
<React.Fragment>
{' '}
for{' '}
<TypedText
fontFamily="Roboto"
display="inline-block"
fontColor={colors.white}
fontWeight={700}
lineHeight="1.3em"
fontSize={isSmallScreen ? '28px' : '36px'}
textList={ROTATING_LIST}
shouldRepeat={true}
/>
</React.Fragment>
)}
</Text>
<Container
className={`pt3 flex clearfix sm-mx-auto ${isSmallScreen ? 'justify-center' : ''}`}
>
<Container paddingRight="20px">
<Link to={WebsitePaths.Docs}>
<CallToAction type="light">
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
</CallToAction>
</Link>
</Container>
<div>
<Link to={WebsitePaths.Portal}>
<CallToAction>
{this.props.translate.get(Key.TradeCallToAction, Deco.Cap)}
</CallToAction>
</Link>
</div>
</Container>
</div>
</div>
</div>
</div>
{this.props.translate.getLanguage() === Language.English && <SubscribeForm />}
</div>
);
}
private _renderWhatsNew(): React.ReactNode {
return (
<div className="sm-center sm-px1">
<a href={WHATS_NEW_URL} className="inline-block text-decoration-none">
<div className="flex items-center sm-pl0 md-pl2 lg-pl0">
<Container
paddingTop="3px"
paddingLeft="8px"
paddingBottom="3px"
paddingRight="8px"
backgroundColor={colors.white}
borderRadius={6}
>
<Text fontSize="14px" fontWeight={500} fontColor={colors.heroGrey}>
New
</Text>
</Container>
<Container marginLeft="12px">
<Text fontSize="16px" fontWeight={500} fontColor={colors.grey300}>
{WHATS_NEW_TITLE}
</Text>
</Container>
</div>
</a>
</div>
);
}
private _renderProjects(
projects: Project[],
title: string,
backgroundColor: string,
isTitleCenter: boolean,
): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const projectList = _.map(projects, (project: Project, i: number) => {
const isRelayersOnly = projects.length === 12;
let colWidth: number;
switch (this.state.screenWidth) {
case ScreenWidths.Sm:
colWidth = 4;
break;
case ScreenWidths.Md:
colWidth = 3;
break;
case ScreenWidths.Lg:
colWidth = isRelayersOnly ? 2 : 2 - i % 2;
break;
default:
throw new Error(`Encountered unknown ScreenWidths value: ${this.state.screenWidth}`);
}
return (
<div key={`project-${project.logoFileName}`} className={`col col-${colWidth} center`}>
<div>
<a href={project.projectUrl} target="_blank" className="text-decoration-none">
<img
src={`/images/landing/project_logos/${project.logoFileName}`}
height={isSmallScreen ? 60 : 92}
/>
</a>
</div>
</div>
);
});
return (
<div className={`clearfix py4 ${isTitleCenter && 'center'}`} style={{ backgroundColor }}>
<div className="mx-auto max-width-4 clearfix sm-px3">
<div className="h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}>
{title}
</div>
<div className="clearfix">{projectList}</div>
<div
className="pt3 mx-auto center"
style={{
color: colors.landingLinkGrey,
fontFamily: 'Roboto Mono',
maxWidth: 300,
fontSize: 14,
}}
>
{this.props.translate.get(Key.FullListPrompt)}{' '}
<Link to={WebsitePaths.Portal} textDecoration="underline" fontColor={colors.landingLinkGrey}>
{this.props.translate.get(Key.FullListLink)}
</Link>
</div>
</div>
</div>
);
}
private _renderTokenizationSection(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
<div className="clearfix lg-py4 md-py4 sm-pb4 sm-pt2" style={{ backgroundColor: colors.grey100 }}>
<div className="mx-auto max-width-4 py4 clearfix">
{isSmallScreen && this._renderTokenCloud()}
<div
className="col lg-col-6 md-col-6 col-12 center"
style={{ color: colors.darkestGrey, height: 364, lineHeight: '364px' }}
>
<div
className="mx-auto inline-block lg-align-middle md-align-middle sm-align-top"
style={{ maxWidth: 385, lineHeight: '44px', textAlign: 'left' }}
>
<div className="lg-h1 md-h1 sm-h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
{this.props.translate.get(Key.TokenizedSectionHeader, Deco.Cap)}
</div>
<div
className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h5 sm-center"
style={{ fontFamily: 'Roboto Mono', lineHeight: 1.7, maxWidth: 370 }}
>
{this.props.translate.get(Key.TokenizedSectionDescription, Deco.Cap)}
</div>
<div className="flex pt1 sm-px3">{this._renderMissionAndValuesButton()}</div>
</div>
</div>
{!isSmallScreen && this._renderTokenCloud()}
</div>
</div>
);
}
private _renderTokenCloud(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
return (
<div className="col lg-col-6 md-col-6 col-12 center">
<img src="/images/landing/tokenized_world.png" height={isSmallScreen ? 280 : 364.5} />
</div>
);
}
private _renderMissionAndValuesButton(): React.ReactNode {
return (
<a
href={constants.URL_MISSION_AND_VALUES_BLOG_POST}
target="_blank"
className="inline-block text-decoration-none"
>
<CallToAction>{this.props.translate.get(Key.OurMissionAndValues, Deco.CapWords)}</CallToAction>
</a>
);
}
private _renderInfoBoxes(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const boxStyle: React.CSSProperties = {
maxWidth: 253,
height: 402,
backgroundColor: colors.grey50,
borderRadius: 5,
padding: '10px 24px 24px',
};
const boxContents: BoxContent[] = [
{
title: this.props.translate.get(Key.BenefitOneTitle, Deco.Cap),
description: this.props.translate.get(Key.BenefitOneDescription, Deco.Cap),
imageUrl: '/images/landing/distributed_network.png',
classNames: '',
maxWidth: 160,
},
{
title: this.props.translate.get(Key.BenefitTwoTitle, Deco.Cap),
description: this.props.translate.get(Key.BenefitTwoDescription, Deco.Cap),
imageUrl: '/images/landing/liquidity.png',
classNames: 'mx-auto',
maxWidth: 160,
},
{
title: this.props.translate.get(Key.BenefitThreeTitle, Deco.Cap),
description: this.props.translate.get(Key.BenefitThreeDescription, Deco.Cap),
imageUrl: '/images/landing/exchange_everywhere.png',
classNames: 'right',
maxWidth: 130,
},
];
const boxes = _.map(boxContents, (boxContent: BoxContent) => {
return (
<div key={`box-${boxContent.title}`} className="col lg-col-4 md-col-4 col-12 sm-pb4">
<div className={`center sm-mx-auto ${!isSmallScreen && boxContent.classNames}`} style={boxStyle}>
<Container className="flex items-center" height="210px">
<img
className="mx-auto"
src={boxContent.imageUrl}
style={{ height: 'auto', maxWidth: boxContent.maxWidth }}
/>
</Container>
<div className="h3" style={{ color: 'black', fontFamily: 'Roboto Mono' }}>
{boxContent.title}
</div>
<div className="pt2 pb2" style={{ fontFamily: 'Roboto Mono', fontSize: 14 }}>
{boxContent.description}
</div>
</div>
</div>
);
});
return (
<div className="clearfix" style={{ backgroundColor: colors.heroGrey }}>
<div className="center pb3 pt4" style={TITLE_STYLE}>
{this.props.translate.get(Key.BenefitsHeader, Deco.Upper)}
</div>
<div className="mx-auto pb4 sm-mt2 clearfix" style={{ maxWidth: '60em' }}>
{boxes}
</div>
</div>
);
}
private _getUseCases(): UseCase[] {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const isEnglish = this.props.translate.getLanguage() === Language.English;
if (isEnglish) {
return [
{
imageUrl: '/images/landing/governance_icon.png',
type: this.props.translate.get(Key.GamingAndCollectables, Deco.Upper),
description: this.props.translate.get(Key.GamingAndCollectablesDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/prediction_market_icon.png',
type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper),
description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/fund_management_icon.png',
type: this.props.translate.get(Key.OrderBooks, Deco.Upper),
description: this.props.translate.get(Key.OrderBooksDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/loans_icon.png',
type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper),
description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap),
classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
style: {
width: 291,
float: 'right',
marginTop: !isSmallScreen ? 38 : 0,
},
},
{
imageUrl: '/images/landing/stable_tokens_icon.png',
type: this.props.translate.get(Key.StableTokens, Deco.Upper),
description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap),
classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
},
];
} else {
return [
{
imageUrl: '/images/landing/governance_icon.png',
type: this.props.translate.get(Key.DecentralizedGovernance, Deco.Upper),
description: this.props.translate.get(Key.DecentralizedGovernanceDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/prediction_market_icon.png',
type: this.props.translate.get(Key.PredictionMarkets, Deco.Upper),
description: this.props.translate.get(Key.PredictionMarketsDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/stable_tokens_icon.png',
type: this.props.translate.get(Key.StableTokens, Deco.Upper),
description: this.props.translate.get(Key.StableTokensDescription, Deco.Cap),
classNames: 'lg-px2 md-px2',
},
{
imageUrl: '/images/landing/loans_icon.png',
type: this.props.translate.get(Key.DecentralizedLoans, Deco.Upper),
description: this.props.translate.get(Key.DecentralizedLoansDescription, Deco.Cap),
classNames: 'lg-pr2 md-pr2 lg-col-6 md-col-6',
style: {
width: 291,
float: 'right',
marginTop: !isSmallScreen ? 38 : 0,
},
},
{
imageUrl: '/images/landing/fund_management_icon.png',
type: this.props.translate.get(Key.FundManagement, Deco.Upper),
description: this.props.translate.get(Key.FundManagementDescription, Deco.Cap),
classNames: 'lg-pl2 md-pl2 lg-col-6 md-col-6',
style: { width: 291, marginTop: !isSmallScreen ? 38 : 0 },
},
];
}
}
private _renderUseCases(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const useCases = this._getUseCases();
const cases = _.map(useCases, (useCase: UseCase) => {
const style = _.isUndefined(useCase.style) || isSmallScreen ? {} : useCase.style;
const useCaseBoxStyle = {
color: colors.grey,
border: `1px solid ${colors.grey750}`,
borderRadius: 4,
maxWidth: isSmallScreen ? 375 : 'none',
...style,
};
const typeStyle: React.CSSProperties = {
color: colors.lightGrey,
fontSize: 13,
textTransform: 'uppercase',
fontFamily: 'Roboto Mono',
fontWeight: 300,
};
return (
<div
key={`useCase-${useCase.type}`}
className={`col lg-col-4 md-col-4 col-12 sm-pt3 sm-px3 sm-pb3 ${useCase.classNames}`}
>
<div className="relative p2 pb2 sm-mx-auto" style={useCaseBoxStyle}>
<div className="absolute center" style={{ top: -35, width: 'calc(100% - 32px)' }}>
<img src={useCase.imageUrl} style={{ height: 50 }} />
</div>
<div className="pt2 center" style={typeStyle}>
{useCase.type}
</div>
<div
className="pt2"
style={{
lineHeight: 1.5,
fontSize: 14,
overflow: 'hidden',
height: 124,
}}
>
{useCase.description}
</div>
</div>
</div>
);
});
return (
<div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
<div className="center h4 pb3 lg-pl0 md-pl3 sm-pl2" style={TITLE_STYLE}>
{this.props.translate.get(Key.UseCasesHeader, Deco.Upper)}
</div>
<div className="mx-auto pb4 pt3 mt1 sm-mt2 clearfix" style={{ maxWidth: '67em' }}>
{cases}
</div>
</div>
);
}
private _renderCallToAction(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const callToActionClassNames =
'lg-pr3 md-pr3 lg-right-align md-right-align sm-center sm-px3 h4 lg-table-cell md-table-cell';
return (
<div className="clearfix pb4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 pb4 mb3 clearfix center">
<div className="center inline-block" style={{ textAlign: 'left' }}>
<div
className={callToActionClassNames}
style={{
fontFamily: 'Roboto Mono',
color: colors.white,
lineHeight: isSmallScreen ? 1.7 : 3,
}}
>
{this.props.translate.get(Key.FinalCallToAction, Deco.Cap)}
</div>
<div className="sm-center sm-pt2 lg-table-cell md-table-cell">
<Link to={WebsitePaths.Docs}>
<CallToAction fontSize="15px">
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
</CallToAction>
</Link>
</div>
</div>
</div>
</div>
);
}
private _updateScreenWidth(): void {
const newScreenWidth = utils.getScreenWidth();
if (newScreenWidth !== this.state.screenWidth) {
this.setState({
screenWidth: newScreenWidth,
});
}
}
} // tslint:disable:max-file-line-count

View File

@@ -1,335 +0,0 @@
import { colors, Link } from '@0x/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import DocumentTitle from 'react-document-title';
import { Footer } from 'ts/components/old_footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Button } from 'ts/components/ui/button';
import { Container } from 'ts/components/ui/container';
import { Image } from 'ts/components/ui/image';
import { Text } from 'ts/components/ui/text';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, ScreenWidths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
export interface LaunchKitProps {
location: Location;
translate: Translate;
dispatcher: Dispatcher;
}
interface LaunchKitState {
screenWidth: ScreenWidths;
}
const THROTTLE_TIMEOUT = 100;
const lighterBackgroundColor = '#222222';
const darkerBackgroundColor = '#1B1B1B';
const grayText = '#999999';
interface Benefit {
icon: string;
description: string;
}
export class LaunchKit extends React.Component<LaunchKitProps, LaunchKitState> {
private readonly _throttledScreenWidthUpdate: () => void;
constructor(props: LaunchKitProps) {
super(props);
this.state = {
screenWidth: utils.getScreenWidth(),
};
this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
}
public componentDidMount(): void {
window.addEventListener('resize', this._throttledScreenWidthUpdate);
window.scrollTo(0, 0);
}
public componentWillUnmount(): void {
window.removeEventListener('resize', this._throttledScreenWidthUpdate);
}
public render(): React.ReactNode {
return (
<div id="launchKit" className="clearfix" style={{ color: colors.grey500 }}>
<DocumentTitle title="0x Launch Kit" />
<TopBar
blockchainIsLoaded={false}
location={this.props.location}
isNightVersion={true}
style={{ backgroundColor: lighterBackgroundColor, position: 'relative' }}
translate={this.props.translate}
/>
{this._renderHero()}
{this._renderSection()}
{this._renderCallToAction()}
{this._renderDisclaimer()}
<Footer
backgroundColor={darkerBackgroundColor}
translate={this.props.translate}
dispatcher={this.props.dispatcher}
/>
</div>
);
}
private _renderHero(): React.ReactNode {
const BENEFITS_1: Benefit[] = [
{
icon: '/images/launch_kit/shared_liquidity.svg',
description: this.props.translate.get(Key.TapIntoAndShare, Deco.Cap),
},
{
icon: '/images/launch_kit/fork.svg',
description: this.props.translate.get(Key.ForkAndExtend, Deco.Cap),
},
{
icon: '/images/launch_kit/enable_trading.svg',
description: this.props.translate.get(Key.EnableTrading, Deco.Cap),
},
];
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const smallButtonPadding = '12px 30px 12px 30px';
const largeButtonPadding = '14px 60px 14px 60px';
const left = 'col lg-col-6 md-col-6 col-12 lg-pl2 md-pl2 sm-pl0 sm-px3 sm-center';
const flexClassName = isSmallScreen
? 'flex items-center flex-column justify-center'
: 'flex items-center justify-center';
return (
<div className="clearfix pt4" style={{ backgroundColor: lighterBackgroundColor }}>
<div className="mx-auto max-width-4 clearfix">
<div className={`${flexClassName} lg-pb4 md-pb4 sm-mb4`}>
<div className={left} style={{ color: colors.white }}>
<div
className="inline-block lg-align-middle md-align-middle sm-align-top"
style={{
paddingLeft: isSmallScreen ? 0 : 12,
lineHeight: '36px',
}}
>
<Text
className="sm-pb2"
fontFamily="Roboto"
display="inline-block"
fontColor={colors.white}
fontWeight="bold"
lineHeight="1.3em"
letterSpacing="1px"
fontSize={isSmallScreen ? '38px' : '46px'}
>
{this.props.translate.get(Key.LaunchKit, Deco.CapWords)}
</Text>
<Container paddingTop="18px">
<Text fontColor={colors.linkSectionGrey} fontSize="18px">
{this.props.translate.get(Key.LaunchKitPitch, Deco.Cap)}
</Text>
</Container>
<Container
paddingTop="54px"
className={`flex clearfix sm-mx-auto ${isSmallScreen ? 'justify-center' : ''}`}
>
<Container paddingRight="20px">
<Link to={constants.URL_LAUNCH_KIT} shouldOpenInNewTab={true}>
<Button
padding={isSmallScreen ? smallButtonPadding : largeButtonPadding}
borderRadius="4px"
borderColor={colors.white}
>
<Text fontSize="16px" fontWeight="bold">
{this.props.translate.get(Key.GetStarted, Deco.Cap)}
</Text>
</Button>
</Link>
</Container>
<div>
<Link to={constants.URL_LAUNCH_KIT_BLOG_POST} shouldOpenInNewTab={true}>
<Button
backgroundColor={lighterBackgroundColor}
borderColor={colors.white}
fontColor={colors.white}
padding={isSmallScreen ? smallButtonPadding : largeButtonPadding}
borderRadius="4px"
>
<Text fontSize="16px" fontWeight="bold" fontColor={colors.white}>
{this.props.translate.get(Key.LearnMore, Deco.Cap)}
</Text>
</Button>
</Link>
</div>
</Container>
</div>
</div>
<Container
marginTop={isSmallScreen ? '60px' : '30px'}
marginBottom="30px"
marginLeft="15px"
marginRight="15px"
>
<Image
src="/images/launch_kit/0x_cupboard.svg"
maxWidth={isSmallScreen ? '75%' : '100%'}
height="auto"
/>
</Container>
</div>
</div>
{this._renderBenefits(BENEFITS_1)}
</div>
);
}
private _renderSection(): React.ReactNode {
const BENEFITS_2: Benefit[] = [
{
icon: '/images/launch_kit/secondary_market.svg',
description: this.props.translate.get(Key.QuicklyLaunch, Deco.Cap),
},
{
icon: '/images/launch_kit/in_game_marketplace.svg',
description: this.props.translate.get(Key.SeemlesslyCreate, Deco.Cap),
},
{
icon: '/images/launch_kit/local_market.svg',
description: this.props.translate.get(Key.LocalMarket, Deco.Cap),
},
];
return (
<div className="clearfix pb4" style={{ backgroundColor: darkerBackgroundColor }}>
<Container
className="mx-auto"
textAlign="center"
paddingTop="89px"
paddingBottom="89px"
maxWidth="421px"
paddingLeft="10px"
paddingRight="10px"
>
<Text fontSize="26px" lineHeight="37px" fontWeight="medium" fontColor={colors.white}>
{this.props.translate.get(Key.PerfectForDevelopers, Deco.Cap)}
</Text>
</Container>
{this._renderBenefits(BENEFITS_2)}
</div>
);
}
private _renderCallToAction(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
const smallButtonPadding = '8px 14px 8px 14px';
const largeButtonPadding = '8px 14px 8px 14px';
return (
<Container
className="clearfix"
backgroundColor={lighterBackgroundColor}
paddingTop="90px"
paddingBottom="90px"
>
<Container className="clearfix mx-auto" maxWidth="850px">
<Container className="lg-left md-left sm-mx-auto sm-pb3" width="348px">
<Text fontColor={colors.white} fontSize="18px">
View our comprehensive documentation to start building today.
</Text>
</Container>
<Container
className={`lg-right md-right flex clearfix sm-mx-auto ${
isSmallScreen ? 'justify-center' : ''
}`}
paddingTop="5px"
>
<Container paddingRight="20px">
<Link to={`${constants.URL_LAUNCH_KIT}/#table-of-contents`} shouldOpenInNewTab={true}>
<Button
padding={isSmallScreen ? smallButtonPadding : largeButtonPadding}
borderRadius="4px"
backgroundColor={lighterBackgroundColor}
borderColor={colors.white}
>
<Text fontSize="16px" fontWeight="bold" fontColor={colors.white}>
{this.props.translate.get(Key.ExploreTheDocs, Deco.Cap)}
</Text>
</Button>
</Link>
</Container>
<div>
<Link to={constants.URL_ZEROEX_CHAT} shouldOpenInNewTab={true}>
<Button
padding={isSmallScreen ? smallButtonPadding : largeButtonPadding}
borderRadius="4px"
>
<Text fontSize="16px" fontWeight="bold">
{this.props.translate.get(Key.GetInTouch, Deco.Cap)}
</Text>
</Button>
</Link>
</div>
</Container>
</Container>
</Container>
);
}
private _renderBenefits(benefits: Benefit[]): React.ReactNode {
return (
<Container className="lg-flex md-flex justify-between mx-auto pb4" maxWidth="890px">
{_.map(benefits, benefit => {
return (
<Container className="mx-auto sm-pb4" width="240px">
<Container textAlign="center">
<img src={benefit.icon} />
</Container>
<Container paddingTop="26px">
<Text
fontSize="18px"
lineHeight="28px"
textAlign="center"
fontColor={colors.linkSectionGrey}
>
{benefit.description}
</Text>
</Container>
</Container>
);
})}
</Container>
);
}
private _renderDisclaimer(): React.ReactNode {
return (
<Container
className="clearfix"
backgroundColor={darkerBackgroundColor}
paddingTop="70px"
paddingBottom="70px"
>
<Container className="mx-auto" maxWidth="850px" paddingLeft="20px" paddingRight="20px">
<Text fontColor={grayText} fontSize="10px">
<b>Disclaimer:</b> The laws and regulations applicable to the use and exchange of digital assets
and blockchain-native tokens, including through any software developed using the licensed work
created by ZeroEx Intl. (the Work), vary by jurisdiction. As set forth in the Apache License,
Version 2.0 applicable to the Work, developers are solely responsible for determining the
appropriateness of using or redistributing the Work, which includes responsibility for ensuring
compliance with any such applicable laws and regulations.
</Text>
<Container paddingTop="15px">
<Text fontColor={grayText} fontSize="10px">
See the{' '}
<Link
to={constants.URL_APACHE_LICENSE}
shouldOpenInNewTab={true}
textDecoration="underline"
>
Apache License, Version 2.0
</Link>{' '}
for the specific language governing all applicable permissions and limitations.
</Text>
</Container>
</Container>
</Container>
);
}
private _updateScreenWidth(): void {
const newScreenWidth = utils.getScreenWidth();
if (newScreenWidth !== this.state.screenWidth) {
this.setState({
screenWidth: newScreenWidth,
});
}
}
}