diff options
Diffstat (limited to 'packages/website/ts/pages')
26 files changed, 0 insertions, 4850 deletions
diff --git a/packages/website/ts/pages/about/jobs.tsx b/packages/website/ts/pages/about/jobs.tsx deleted file mode 100644 index 85c25a75f..000000000 --- a/packages/website/ts/pages/about/jobs.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled from 'styled-components'; - -import { AboutPageLayout } from 'ts/components/aboutPageLayout'; -import { Link } from 'ts/components/link'; -import { Column, FlexWrap, Section } from 'ts/components/newLayout'; -import { Heading, Paragraph } from 'ts/components/text'; -import { Container } from 'ts/components/ui/container'; -import { colors } from 'ts/style/colors'; -import { WebsiteBackendJobInfo } from 'ts/types'; -import { backendClient } from 'ts/utils/backend_client'; -import { constants } from 'ts/utils/constants'; - -const OPEN_POSITIONS_HASH = 'positions'; - -interface PositionProps { - title: string; - location: string; - href: string; -} - -interface PositionItemProps { - position: PositionProps; -} - -const Position: React.FunctionComponent<PositionItemProps> = (props: PositionItemProps) => { - const { position } = props; - return ( - <PositionWrap> - <StyledColumn width="50%"> - <Container position="relative" top="-3px" paddingRight="12px"> - <Heading asElement="h3" size="small" fontWeight="400" marginBottom="0"> - <a href={position.href} target="_blank"> - {position.title} - </a> - </Heading> - </Container> - </StyledColumn> - - <StyledColumn width="30%" padding="0 40px 0 0"> - <Paragraph isMuted={true} marginBottom="0"> - {position.location} - </Paragraph> - </StyledColumn> - - <StyledColumn width="20%"> - <Paragraph marginBottom="0" textAlign="right" color={colors.brandDark} fontWeight={400}> - <Link href={position.href} target="_blank"> - Apply - </Link> - </Paragraph> - </StyledColumn> - </PositionWrap> - ); -}; - -export interface NextAboutJobsProps {} -interface NextAboutJobsState { - jobInfos: WebsiteBackendJobInfo[]; -} - -export class NextAboutJobs extends React.Component<NextAboutJobsProps, NextAboutJobsState> { - private _isUnmounted: boolean; - private static _convertJobInfoToPositionProps(jobInfo: WebsiteBackendJobInfo): PositionProps { - return { - title: jobInfo.title, - location: jobInfo.office, - href: jobInfo.url, - }; - } - constructor(props: NextAboutJobsProps) { - super(props); - this.state = { - jobInfos: [], - }; - } - - public componentWillMount(): void { - // tslint:disable-next-line:no-floating-promises - this._fetchJobInfosAsync(); - } - public componentWillUnmount(): void { - this._isUnmounted = true; - } - public render(): React.ReactNode { - const positions = this.state.jobInfos.map(jobInfo => NextAboutJobs._convertJobInfoToPositionProps(jobInfo)); - return ( - <AboutPageLayout - title="Join Us in Our Mission" - description={ - <> - <Paragraph size="medium"> - To create a tokenized world where all value can flow freely. - </Paragraph> - <Paragraph size="medium"> - We are growing an ecosystem of businesses and projects by solving difficult challenges to - make our technology intuitive, flexible, and accessible to all. Join us in building - infrastructure upon which the exchange of all assets will take place. - </Paragraph> - </> - } - linkLabel="Our mission and values" - href={constants.URL_MISSION_AND_VALUES_BLOG_POST} - > - <DocumentTitle title="Jobs at 0x" /> - <Section bgColor="#F3F6F4" isFlex={true} maxWidth="1170px" wrapWidth="100%"> - <Column maxWidth="442px"> - <Heading size="medium" marginBottom="30px"> - Powered by a Diverse, Global Community - </Heading> - - <Paragraph> - 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 worldwide. - We're passionate about open-source software and decentralized technology's potential to act - as an equalizing force in the world. - </Paragraph> - </Column> - - <Column maxWidth="600px"> - <ImageWrap> - <img src="/images/jobs/map@2x.png" height="365" alt="Map of community" /> - </ImageWrap> - </Column> - </Section> - - <Section isFlex={true} maxWidth="1170px" wrapWidth="100%"> - <Column> - <Heading size="medium">Benefits</Heading> - </Column> - - <Column maxWidth="826px"> - <BenefitsList> - <li>Comprehensive Insurance</li> - <li>Unlimited Vacation</li> - <li>Meals and snacks provided daily</li> - <li>Flexible hours and liberal work-from-home-policy</li> - <li>Supportive of remote working</li> - <li>Transportation, phone, and wellness expense</li> - <li>Relocation assistance</li> - <li>Optional team excursions</li> - <li>Competitive salary</li> - <li>Cryptocurrency based compensation</li> - </BenefitsList> - </Column> - </Section> - - <Section id={OPEN_POSITIONS_HASH} isFlex={true} maxWidth="1170px" wrapWidth="100%"> - <Column> - <Heading size="medium"> - Current - <br /> - Openings - </Heading> - </Column> - - <Column maxWidth="826px"> - {_.map(positions, (position, index) => ( - <Position key={`position-${index}`} position={position} /> - ))} - </Column> - </Section> - </AboutPageLayout> - ); - } - private async _fetchJobInfosAsync(): Promise<void> { - try { - if (!this._isUnmounted) { - this.setState({ - jobInfos: [], - }); - } - const jobInfos = await backendClient.getJobInfosAsync(); - if (!this._isUnmounted) { - this.setState({ - jobInfos, - }); - } - } catch (error) { - if (!this._isUnmounted) { - this.setState({ - jobInfos: [], - }); - } - } - } -} - -const BenefitsList = styled.ul` - color: #000; - font-weight: 300; - line-height: 1.444444444; - list-style: disc; - columns: auto 2; - column-gap: 80px; - - li { - margin-bottom: 1em; - } -`; - -const ImageWrap = styled.figure` - @media (min-width: 768px) { - height: 600px; - padding-left: 60px; - display: flex; - align-items: flex-end; - } -`; - -const StyledColumn = styled(Column)` - flex-shrink: 0; - - @media (max-width: 768px) { - & + & { - margin-top: 15px; - } - } -`; - -const PositionWrap = styled(FlexWrap)` - margin-bottom: 40px; - padding-bottom: 30px; - position: relative; - - &:after { - content: ''; - width: 100%; - position: absolute; - bottom: 0; - left: 0; - height: 1px; - background-color: #e3e3e3; - } -`; diff --git a/packages/website/ts/pages/about/mission.tsx b/packages/website/ts/pages/about/mission.tsx deleted file mode 100644 index ab8949fae..000000000 --- a/packages/website/ts/pages/about/mission.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled from 'styled-components'; - -import { AboutPageLayout } from 'ts/components/aboutPageLayout'; -import { Definition } from 'ts/components/definition'; -import { Image } from 'ts/components/image'; -import { Column, Section } from 'ts/components/newLayout'; -import { Heading } from 'ts/components/text'; -import { constants } from 'ts/utils/constants'; - -const values = [ - { - title: 'Do The Right Thing', - description: - 'We acknowledge the broad subjectivity behind doing “the right thing,” and are committed to rigorously exploring its nuance in our decision making. We believe this responsibility drives our decision making above all else, and pledge to act in the best interest of our peers, community, and society as a whole.', - icon: 'right-thing', - }, - { - title: 'Consistently Ship', - description: - 'Achieving our mission requires dedication and diligence. We aspire to be an organization that consistently ships. We set high-impact goals that are rooted in data and pride ourselves in consistently outputting outstanding results across the organization.', - icon: 'consistently-ship', - }, - { - title: 'Focus on Long-term Impact', - description: - 'We anticipate that over time, awareness of the fundamentally disruptive nature of frictionless global exchange will cause some to see this technology as a threat. There will be setbacks, some will claim that this technology is too disruptive, and we will face adversity. Persistence and a healthy long-term focus will see us through these battles.', - icon: 'long-term-impact', - }, -]; - -export const NextAboutMission = () => ( - <AboutPageLayout - title="Creating a tokenized world where all value can flow freely." - description="0x is important infrastructure for the emerging crypto economy and enables markets to be created that couldn't have existed before. As more assets become tokenized, public blockchains provide the opportunity to establish a new financial stack that is more efficient, transparent, and equitable than any system in the past." - linkLabel="Our mission and values" - href={constants.URL_MISSION_AND_VALUES_BLOG_POST} - > - <DocumentTitle title="Our Mission - 0x" /> - <Section isFullWidth={true} isPadded={false}> - <FullWidthImage> - <Image src="/images/about/about-office.png" alt="0x Offices" isCentered={true} /> - </FullWidthImage> - </Section> - - <Section isFlex={true} maxWidth="1170px" wrapWidth="100%"> - <Column> - <Heading size="medium" maxWidth="226px"> - Core Values - </Heading> - </Column> - - <Column width="70%" maxWidth="826px"> - <Column width="100%" maxWidth="800px"> - {_.map(values, (item, index) => ( - <StyledDefinition - icon={item.icon} - title={item.title} - description={item.description} - isInlineIcon={true} - iconSize="large" - /> - ))} - </Column> - </Column> - </Section> - </AboutPageLayout> -); - -const StyledDefinition = styled(Definition)` - & + & { - margin-top: 30px; - padding-top: 30px; - border-top: 1px solid #eaeaea; - } -`; - -const FullWidthImage = styled.figure` - width: 100vw; - margin-left: calc(50% - 50vw); - - img { - width: 100%; - height: 100%; - object-fit: cover; - } - - @media (min-width: 768px) { - height: 500px; - } - - @media (max-width: 768px) { - height: 400px; - } -`; diff --git a/packages/website/ts/pages/about/press.tsx b/packages/website/ts/pages/about/press.tsx deleted file mode 100644 index 03003d656..000000000 --- a/packages/website/ts/pages/about/press.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled from 'styled-components'; - -import { AboutPageLayout } from 'ts/components/aboutPageLayout'; -import { Button } from 'ts/components/button'; -import { Column, FlexWrap } from 'ts/components/newLayout'; -import { Paragraph } from 'ts/components/text'; - -interface HighlightProps { - logo: string; - title?: string; - text: string; - href: string; -} - -interface HighlightItemProps { - highlight: HighlightProps; -} - -const highlights: HighlightProps[] = [ - { - logo: '/images/press/logo-forbes.png', - title: 'Forbes', - text: - '0x Instant is aiming to aid businesses and developers such as news sites, crypto wallets, dApps or price trackers to monetize or add a new revenue stream to their existing pipeline.', - href: - 'https://www.forbes.com/sites/rebeccacampbell1/2018/12/06/0x-launches-instant-delivers-an-easy-and-flexible-way-to-buy-crypto-tokens/#bfb73a843561', - }, - { - logo: '/images/press/logo-venturebeat.png', - title: 'VentureBeat', - text: '0x leads the way for ‘tokenization’ of the world, and collectible game items are next', - href: - 'https://venturebeat.com/2018/09/24/0x-leads-the-way-for-tokenization-of-the-world-and-collectible-game-items-are-next/', - }, - { - logo: '/images/press/logo-fortune.png', - title: 'Fortune', - text: - 'In the future, many traditional investments like real estate and corporate shares will come in the form of digital tokens that are bought and transferred on a blockchain.', - href: 'http://fortune.com/2018/09/06/0x-harbor-blockchain/', - }, - { - logo: '/images/press/logo-techcrunch.png', - title: 'TechCrunch', - text: - '0x allows any developer to quickly build their own decentralized cryptocurrency exchange and decide their own fees.', - href: 'https://techcrunch.com/2018/07/16/0x/', - }, -]; - -export const NextAboutPress = () => ( - <AboutPageLayout - title="Press Highlights" - description={ - <> - <Paragraph size="medium" marginBottom="60px"> - Want to write about 0x? <a href="mailto:team@0xproject.com">Get in touch.</a> - </Paragraph> - - {_.map(highlights, (highlight, index) => ( - <Highlight key={`highlight-${index}`} highlight={highlight} /> - ))} - </> - } - > - <DocumentTitle title="Press Highlights - 0x" /> - </AboutPageLayout> -); - -export const Highlight: React.FunctionComponent<HighlightItemProps> = (props: HighlightItemProps) => { - const { highlight } = props; - return ( - <HighlightWrap> - <Column> - <img src={highlight.logo} alt={highlight.title} /> - </Column> - - <Column width="60%" maxWidth="560px"> - <Paragraph isMuted={false}>{highlight.text}</Paragraph> - <Button href={highlight.href} isWithArrow={true} isNoBorder={true} target="_blank"> - Read Article - </Button> - </Column> - </HighlightWrap> - ); -}; - -const HighlightWrap = styled(FlexWrap)` - border-top: 1px solid #eaeaea; - padding: 30px 0; -`; diff --git a/packages/website/ts/pages/about/team.tsx b/packages/website/ts/pages/about/team.tsx deleted file mode 100644 index 808fea049..000000000 --- a/packages/website/ts/pages/about/team.tsx +++ /dev/null @@ -1,296 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled from 'styled-components'; - -import { colors } from 'ts/style/colors'; - -import { AboutPageLayout } from 'ts/components/aboutPageLayout'; -import { Column, Section } from 'ts/components/newLayout'; -import { Heading, Paragraph } from 'ts/components/text'; -import { WebsitePaths } from 'ts/types'; - -interface TeamMember { - name: string; - title: string; - imageUrl?: string; -} - -const team: TeamMember[] = [ - { - imageUrl: '/images/team/willw.jpg', - name: 'Will Warren', - title: 'co-founder & CEO', - }, - { - imageUrl: '/images/team/amirb.jpg', - name: 'Amir Bandeali', - title: 'Co-founder & CTO', - }, - { - imageUrl: '/images/team/fabiob.jpg', - name: 'Fabio Berger', - title: 'engineering manager', - }, - { - imageUrl: '/images/team/alexv.jpg', - name: 'Alex Xu', - title: 'Director of operations', - }, - { - imageUrl: '/images/team/leonidL.jpg', - name: 'Leonid Logvinov', - title: 'engineer', - }, - { - imageUrl: '/images/team/benb.jpg', - name: 'Ben Burns', - title: 'designer', - }, - { - imageUrl: '/images/team/brandonm.jpg', - name: 'Brandon Millman', - title: 'senior engineer', - }, - { - imageUrl: '/images/team/toms.jpg', - name: 'Tom Schmidt', - title: 'product lead', - }, - { - imageUrl: '/images/team/jacobe.jpg', - name: 'Jacob Evans', - title: 'ecosystem engineer', - }, - { - imageUrl: '/images/team/blake.jpg', - name: 'Blake Henderson', - title: 'ecosystem programs lead', - }, - { - imageUrl: '/images/team/zack.jpg', - name: 'Zack Skelly', - title: 'lead recruiter', - }, - { - imageUrl: '/images/team/greg.jpg', - name: 'Greg Hysen', - title: 'blockchain engineer', - }, - { - imageUrl: '/images/team/remcoB.jpg', - name: 'Remco Bloemen', - title: 'technical fellow', - }, - { - imageUrl: '/images/team/francesco.jpg', - name: 'Francesco Agosti', - title: 'engineer', - }, - { - imageUrl: '/images/team/melo.jpg', - name: 'Mel Oberto', - title: 'people operations associate', - }, - { - imageUrl: '/images/team/alexb.jpg', - name: 'Alex Browne', - title: 'engineer in residence', - }, - { - imageUrl: '/images/team/peterz.jpg', - name: 'Peter Zeitz', - title: 'research fellow', - }, - { - imageUrl: '/images/team/chrisk.jpg', - name: 'Chris Kalani', - title: 'director of design', - }, - { - imageUrl: '/images/team/clayr.jpg', - name: 'Clay Robbins', - title: 'ecosystem development lead', - }, - { - imageUrl: '/images/team/mattt.jpg', - name: 'Matt Taylor', - title: 'marketing lead', - }, - { - imageUrl: '/images/team/eugenea.jpg', - name: 'Eugene Aumson', - title: 'engineer', - }, - { - imageUrl: '/images/team/weijew.jpg', - name: 'Weijie Wu', - title: 'research fellow', - }, - { - imageUrl: '/images/team/rahuls.jpg', - name: 'Rahul Singireddy', - title: 'relayer success manager', - }, - { - imageUrl: '/images/team/jasons.jpg', - name: 'Jason Somensatto', - title: 'strategic legal counsel', - }, - { - imageUrl: '/images/team/steveK.jpg', - name: 'Steve Klebanoff', - title: 'senior engineer', - }, - { - imageUrl: '/images/team/xianny.jpg', - name: 'Xianny Ng', - title: 'engineer', - }, - { - imageUrl: '/images/team/oshirob.png', - name: 'Brent Oshiro', - title: 'community engagement lead', - }, - { - imageUrl: '/images/team/marcs.jpg', - name: 'Marc Savino', - title: 'technical sourcer', - }, -]; - -const advisors: TeamMember[] = [ - { - imageUrl: '/images/team/advisors/frede.jpg', - name: 'Fred Ehrsam', - title: 'Advisor', - }, - { - imageUrl: '/images/team/advisors/olafc.jpg', - name: 'Olaf Carlson-Wee', - title: 'Advisor', - }, - { - imageUrl: '/images/team/advisors/joeyk.jpg', - name: 'Joey Krug', - title: 'Advisor', - }, - { - imageUrl: '/images/team/advisors/lindax.jpg', - name: 'Linda Xie', - title: 'Advisor', - }, - { - imageUrl: '/images/team/advisors/davids.jpg', - name: 'David Sacks', - title: 'Advisor', - }, -]; - -export const NextAboutTeam = () => ( - <AboutPageLayout - title="We are a global, growing team" - description="We are a distributed team with backgrounds in engineering, academic research, business, and design. The 0x Core Team is passionate about accelerating the adoption decentralized technology and believe in its potential to be an equalizing force in the world. Join us and do the most impactful work of your life." - linkLabel="Join the team" - to={WebsitePaths.AboutJobs} - > - <DocumentTitle title="Our Team - 0x" /> - <Section maxWidth="1170px" wrapWidth="100%" isFlex={true} flexBreakpoint="900px"> - <Column> - <Heading size="medium">0x Team</Heading> - </Column> - - <Column width="70%" maxWidth="800px"> - <StyledGrid> - {_.map(team, (info: TeamMember, index: number) => ( - <Member key={`team-${index}`} name={info.name} title={info.title} imageUrl={info.imageUrl} /> - ))} - </StyledGrid> - </Column> - </Section> - - <Section bgColor="#F3F6F4" maxWidth="1170px" wrapWidth="100%" flexBreakpoint="900px" isFlex={true}> - <Column> - <Heading size="medium">Advisors</Heading> - </Column> - - <Column width="70%" maxWidth="800px"> - <StyledGrid> - {_.map(advisors, (info: TeamMember, index: number) => ( - <Member key={`advisor-${index}`} name={info.name} title={info.title} imageUrl={info.imageUrl} /> - ))} - </StyledGrid> - </Column> - </Section> - </AboutPageLayout> -); - -const StyledGrid = styled.div` - &:after { - content: ''; - clear: both; - } -`; - -const Member = ({ name, title, imageUrl }: TeamMember) => ( - <StyledMember> - <img src={imageUrl} alt={name} /> - <Name>{name}</Name> - <MemberTitle isMuted={0.5} size={14} style={{ textTransform: 'capitalize' }}> - {title} - </MemberTitle> - </StyledMember> -); - -const StyledMember = styled.div` - margin-bottom: 10px; - float: left; - width: calc(50% - 15px); - margin-right: 15px; - - @media (max-width: 600px) { - &:nth-child(2n + 1) { - clear: left; - } - } - - img, - svg { - width: 100%; - height: auto; - object-fit: contain; - margin-bottom: 10px; - } - - @media (min-width: 600px) { - width: calc(33.3333% - 30px); - margin-right: 20px; - - &:nth-child(3n + 1) { - clear: left; - } - } - - @media (min-width: 900px) { - width: calc(25% - 30px); - - &:nth-child(3n + 1) { - clear: none; - } - - &:nth-child(4n + 1) { - clear: left; - } - } -`; - -const Name = styled.h3` - color: ${colors.textDarkPrimary}; - font-size: 14px; - line-height: 1; - margin: 0; -`; - -const MemberTitle = styled(Paragraph)` - font-size: 14px; -`; diff --git a/packages/website/ts/pages/community.tsx b/packages/website/ts/pages/community.tsx deleted file mode 100644 index 7c02fed82..000000000 --- a/packages/website/ts/pages/community.tsx +++ /dev/null @@ -1,289 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import styled from 'styled-components'; - -import { colors } from 'ts/style/colors'; - -import { Banner } from 'ts/components/banner'; -import { Button } from 'ts/components/button'; -import { Icon } from 'ts/components/icon'; -import { ModalContact } from 'ts/components/modals/modal_contact'; -import { Column, Section, WrapGrid } from 'ts/components/newLayout'; -import { SiteWrap } from 'ts/components/siteWrap'; -import { Heading, Paragraph } from 'ts/components/text'; - -interface EventProps { - title: string; - date: string; - signupUrl: string; - imageUrl: string; -} - -interface CommunityLinkProps { - bgColor: string; - title?: string; - icon?: string; - url: string; -} - -const events: EventProps[] = [ - { - title: '0x London Meetup', - date: 'October 20th 2018', - imageUrl: '/images/events/london.jpg', - signupUrl: '#', - }, - { - title: '0x Berlin Meetup', - date: 'October 20th 2018', - imageUrl: '/images/events/berlin.jpg', - signupUrl: '#', - }, - { - title: '0x San Francisco Meetup', - date: 'October 20th 2018', - imageUrl: '/images/events/sf.jpg', - signupUrl: '#', - }, -]; -const communityLinks: CommunityLinkProps[] = [ - { - bgColor: '#1DA1F2', - title: 'Twitter', - icon: 'social-twitter', - url: 'https://twitter.com/0xProject', - }, - { - bgColor: '#FF4500', - title: 'Reddit', - icon: 'social-reddit', - url: 'https://twitter.com/0xProject', - }, - { - bgColor: '#7289DA', - title: 'Twitter', - icon: 'social-discord', - url: 'https://twitter.com/0xProject', - }, - { - bgColor: '#3B5998', - title: 'Facebook', - icon: 'social-fb', - url: 'https://twitter.com/0xProject', - }, - { - bgColor: '#181717', - title: 'GitHub', - icon: 'social-github', - url: 'https://twitter.com/0xProject', - }, - { - bgColor: '#003831', - title: 'Newsletter', - icon: 'social-newsletter', - url: 'https://twitter.com/0xProject', - }, -]; - -export class NextCommunity extends React.Component { - public state = { - isContactModalOpen: false, - }; - public render(): React.ReactNode { - return ( - <SiteWrap theme="light"> - <Section isTextCentered={true}> - <Column> - <Heading size="medium" isCentered={true}> - Community - </Heading> - <Paragraph size="medium" isCentered={true} isMuted={true} marginBottom="0"> - The 0x community is a global, passionate group of crypto developers and enthusiasts. The - official channels below provide a great forum for connecting and engaging with the - community. - </Paragraph> - <LinkWrap> - <Button to="#" isWithArrow={true} isAccentColor={true}> - Join the 0x community - </Button> - </LinkWrap> - </Column> - </Section> - - <Section isFullWidth={true}> - <WrapGrid - isTextCentered={true} - isWrapped={true} - isFullWidth={false} - isCentered={false} - maxWidth="1151px" - > - {_.map(communityLinks, (link: CommunityLinkProps, index: number) => ( - <CommunityLink - key={`cl-${index}`} - icon={link.icon} - title={link.title} - bgColor={link.bgColor} - url={link.url} - /> - ))} - </WrapGrid> - </Section> - - <EventsWrapper - bgColor={colors.backgroundLight} - isFullWidth={true} - isCentered={true} - isTextCentered={true} - > - <Column maxWidth="720px"> - <Heading size="medium" asElement="h2" isCentered={true} maxWidth="507px" marginBottom="30px"> - Upcoming Events - </Heading> - <Paragraph size="medium" isCentered={true} isMuted={true}> - 0x meetups happen all over the world on a monthly basis and are hosted by devoted members of - the community. Want to host a meetup in your city? Reach out for help finding a venue, - connecting with local 0x mentors, and promoting your events. - </Paragraph> - <LinkWrap> - <Button to="#" isWithArrow={true} isAccentColor={true}> - Get in Touch - </Button> - <Button to="#" isWithArrow={true} isAccentColor={true}> - Join Newsletter - </Button> - </LinkWrap> - </Column> - <WrapGrid - isTextCentered={true} - isWrapped={true} - isFullWidth={false} - isCentered={false} - maxWidth="1149px" - > - {_.map(events, (ev: EventProps, index: number) => ( - <Event - key={`event-${index}`} - title={ev.title} - date={ev.date} - signupUrl={ev.signupUrl} - imageUrl={ev.imageUrl} - /> - ))} - </WrapGrid> - </EventsWrapper> - - <Banner - heading="Ready to get started?" - subline="Dive into our docs, or contact us if needed" - mainCta={{ text: 'Get Started', href: '/docs' }} - secondaryCta={{ text: 'Get in Touch', onClick: this._onOpenContactModal.bind(this) }} - /> - <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} /> - </SiteWrap> - ); - } - - public _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - public _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; -} - -const Event: React.FunctionComponent<EventProps> = (event: EventProps) => ( - <StyledEvent> - <EventIcon name="logo-mark" size={30} margin={0} /> - <EventImage src={event.imageUrl} alt="" /> - <EventContent> - <Heading color={colors.white} size="small" marginBottom="0"> - {event.title} - </Heading> - <Paragraph color={colors.white} isMuted={0.65}> - {event.date} - </Paragraph> - <Button color={colors.white} href={event.signupUrl} isWithArrow={true}> - Sign Up - </Button> - </EventContent> - </StyledEvent> -); - -const CommunityLink: React.FunctionComponent<CommunityLinkProps> = (props: CommunityLinkProps) => ( - <StyledCommunityLink bgColor={props.bgColor} href={props.url}> - <CommunityIcon name={props.icon} size={44} margin={0} /> - <CommunityTitle color={colors.white} isMuted={false} marginBottom="0"> - {props.title} - </CommunityTitle> - </StyledCommunityLink> -); - -// Events -const EventsWrapper = styled(Section)` - display: flex; - align-items: center; - flex-direction: column; -`; - -// Event -const StyledEvent = styled.div` - background-color: ${colors.brandDark}; - width: calc((100% / 3) - 30px); - text-align: left; - height: 424px; - margin-top: 130px; - position: relative; -`; - -const EventIcon = styled(Icon)` - position: absolute; - top: 30px; - left: 30px; -`; - -const EventImage = styled.img` - width: 100%; - height: 260px; - object-fit: cover; -`; - -const EventContent = styled.div` - padding: 30px 30px; -`; - -interface StyledCommunityLinkProps { - bgColor: string; -} -const StyledCommunityLink = styled.a` - background-color: ${(props: StyledCommunityLinkProps) => props.bgColor}; - color: ${colors.white}; - width: 175px; - height: 175px; - text-align: center; - position: relative; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -`; - -const CommunityTitle = styled(Paragraph)` - font-size: 20px; - font-weight: 400; -`; - -const CommunityIcon = styled(Icon)` - margin-bottom: 20px; -`; - -// Misc -const LinkWrap = styled.div` - display: inline-flex; - margin-top: 60px; - - a + a { - margin-left: 60px; - } -`; diff --git a/packages/website/ts/pages/documentation/developers_page.tsx b/packages/website/ts/pages/documentation/developers_page.tsx deleted file mode 100644 index 0b725c514..000000000 --- a/packages/website/ts/pages/documentation/developers_page.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { colors, constants as sharedConstants, utils as sharedUtils } from '@0x/react-shared'; -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import { Helmet } from 'react-helmet'; -import { DocsLogo } from 'ts/components/documentation/docs_logo'; -import { DocsTopBar } from 'ts/components/documentation/docs_top_bar'; -import { Container } from 'ts/components/ui/container'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { media } from 'ts/style/media'; -import { styled } from 'ts/style/theme'; -import { BrowserType, OperatingSystemType, ScreenWidths } from 'ts/types'; -import { Translate } from 'ts/utils/translate'; -import { utils } from 'ts/utils/utils'; - -const THROTTLE_TIMEOUT = 100; -const TOP_BAR_HEIGHT = 80; -const browserType = utils.getBrowserType(); -let SCROLLBAR_WIDTH; -switch (browserType) { - case BrowserType.Firefox: - // HACK: Firefox doesn't allow styling of their scrollbar's. - // Source: https://stackoverflow.com/questions/6165472/custom-css-scrollbar-for-firefox - const os = utils.getOperatingSystem(); - SCROLLBAR_WIDTH = os === OperatingSystemType.Windows ? 17 : 15; - break; - - case BrowserType.Edge: - // Edge's scrollbar is placed outside of the div content and doesn't - // need to be accounted for - SCROLLBAR_WIDTH = 0; - break; - - default: - SCROLLBAR_WIDTH = 4; -} -const SIDEBAR_PADDING = 22; - -export interface DevelopersPageProps { - location: Location; - translate: Translate; - screenWidth: ScreenWidths; - dispatcher: Dispatcher; - mainContent: React.ReactNode; - sidebar: React.ReactNode; -} - -export interface DevelopersPageState { - isSidebarScrolling: boolean; -} - -const isUserOnMobile = sharedUtils.isUserOnMobile(); - -const scrollableContainerStyles = ` - position: absolute; - top: ${TOP_BAR_HEIGHT}px; - left: 0px; - bottom: 0px; - right: 0px; - overflow-x: hidden; - overflow-y: scroll; - -webkit-overflow-scrolling: touch; - /* Required for hide/show onHover of scrollbar on Microsoft Edge */ - -ms-overflow-style: -ms-autohiding-scrollbar; -`; - -interface SidebarContainerProps { - className?: string; -} - -const SidebarContainer = styled.div<SidebarContainerProps>` - ${scrollableContainerStyles} - padding-top: 27px; - padding-left: ${SIDEBAR_PADDING}px; - padding-right: ${SIDEBAR_PADDING}px; - overflow: hidden; - &:hover { - overflow: auto; - padding-right: ${SIDEBAR_PADDING - SCROLLBAR_WIDTH}px; - } -`; - -interface MainContentContainerProps { - className?: string; -} - -const MainContentContainer = styled.div<MainContentContainerProps>` - ${scrollableContainerStyles} - padding-top: 0px; - padding-left: 50px; - padding-right: 50px; - overflow: ${isUserOnMobile ? 'auto' : 'hidden'}; - &:hover { - padding-right: ${50 - SCROLLBAR_WIDTH}px; - overflow: auto; - } - ${media.small` - padding-left: 20px; - padding-right: 20px; - &:hover { - padding-right: ${20 - SCROLLBAR_WIDTH}px; - overflow: auto; - } - `} -`; - -export class DevelopersPage extends React.Component<DevelopersPageProps, DevelopersPageState> { - private readonly _throttledScreenWidthUpdate: () => void; - private readonly _throttledSidebarScrolling: () => void; - private _sidebarScrollClearingInterval: number; - constructor(props: DevelopersPageProps) { - super(props); - this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); - this._throttledSidebarScrolling = _.throttle(this._onSidebarScroll.bind(this), THROTTLE_TIMEOUT); - this.state = { - isSidebarScrolling: false, - }; - } - public componentDidMount(): void { - window.addEventListener('resize', this._throttledScreenWidthUpdate); - window.scrollTo(0, 0); - this._sidebarScrollClearingInterval = window.setInterval(() => { - this.setState({ - isSidebarScrolling: false, - }); - }, 1000); - } - public componentWillUnmount(): void { - window.removeEventListener('resize', this._throttledScreenWidthUpdate); - window.clearInterval(this._sidebarScrollClearingInterval); - } - public render(): React.ReactNode { - const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; - const mainContentPadding = isSmallScreen ? 20 : 50; - return ( - <Container - className="flex items-center overflow-hidden" - width="100%" - background={`linear-gradient(to right, ${colors.grey100} 0%, ${colors.grey100} 50%, ${ - colors.white - } 50%, ${colors.white} 100%)`} - > - <DocumentTitle title="0x Docs" /> - <Helmet> - <link rel="stylesheet" href="/css/github-gist.css" /> - </Helmet> - <Container className="flex mx-auto" height="100vh"> - <Container - className="sm-hide xs-hide relative" - width={270} - paddingLeft={22} - paddingRight={22} - paddingTop={0} - backgroundColor={colors.grey100} - > - <Container - borderBottom={this.state.isSidebarScrolling ? `1px solid ${colors.grey300}` : 'none'} - paddingBottom="2px" - > - <Container paddingTop="30px" paddingLeft="10px" paddingBottom="8px"> - <DocsLogo /> - </Container> - </Container> - <SidebarContainer onWheel={this._throttledSidebarScrolling}> - <Container paddingBottom="100px"> - {this.props.screenWidth !== ScreenWidths.Sm && this.props.sidebar} - </Container> - </SidebarContainer> - </Container> - <Container - className="relative" - width={isSmallScreen ? '100vw' : 786} - paddingBottom="100px" - backgroundColor={colors.white} - > - <Container paddingLeft={mainContentPadding} paddingRight={mainContentPadding}> - <DocsTopBar - location={this.props.location} - screenWidth={this.props.screenWidth} - translate={this.props.translate} - sidebar={this.props.sidebar} - /> - </Container> - <MainContentContainer id={sharedConstants.SCROLL_CONTAINER_ID}> - {this.props.mainContent} - </MainContentContainer> - </Container> - </Container> - </Container> - ); - } - private _onSidebarScroll(_event: React.FormEvent<HTMLInputElement>): void { - this.setState({ - isSidebarScrolling: true, - }); - } - private _updateScreenWidth(): void { - const newScreenWidth = utils.getScreenWidth(); - this.props.dispatcher.updateScreenWidth(newScreenWidth); - } -} // tslint:disable:max-file-line-count diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx deleted file mode 100644 index 14bad7329..000000000 --- a/packages/website/ts/pages/documentation/doc_page.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { - DocAgnosticFormat, - DocReference, - DocsInfo, - GeneratedDocJson, - SupportedDocJson, - TypeDocUtils, -} from '@0x/react-docs'; -import findVersions from 'find-versions'; -import * as _ from 'lodash'; -import CircularProgress from 'material-ui/CircularProgress'; -import * as React from 'react'; -import semverSort from 'semver-sort'; -import { SidebarHeader } from 'ts/components/documentation/sidebar_header'; -import { NestedSidebarMenu } from 'ts/components/nested_sidebar_menu'; -import { Container } from 'ts/components/ui/container'; -import { DevelopersPage } from 'ts/pages/documentation/developers_page'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { DocPackages, ScreenWidths } from 'ts/types'; -import { constants } from 'ts/utils/constants'; -import { docUtils } from 'ts/utils/doc_utils'; -import { Translate } from 'ts/utils/translate'; -import { utils } from 'ts/utils/utils'; - -const isDevelopmentOrStaging = utils.isDevelopment() || utils.isStaging(); -const ZERO_EX_JS_VERSION_MISSING_TOPLEVEL_PATH = '0.32.4'; - -const docIdToSubpackageName: { [id: string]: string } = { - [DocPackages.ZeroExJs]: '0x.js', - [DocPackages.Connect]: 'connect', - [DocPackages.SmartContracts]: 'contracts', - [DocPackages.Web3Wrapper]: 'web3-wrapper', - [DocPackages.ContractWrappers]: 'contract-wrappers', - [DocPackages.SolCompiler]: 'sol-compiler', - [DocPackages.JSONSchemas]: 'json-schemas', - [DocPackages.SolCoverage]: 'sol-coverage', - [DocPackages.SolProfiler]: 'sol-profiler', - [DocPackages.SolTrace]: 'sol-trace', - [DocPackages.Subproviders]: 'subproviders', - [DocPackages.OrderUtils]: 'order-utils', - [DocPackages.OrderWatcher]: 'order-watcher', - [DocPackages.EthereumTypes]: 'ethereum-types', - [DocPackages.AssetBuyer]: 'asset-buyer', - [DocPackages.Migrations]: 'migrations', -}; - -export interface DocPageProps { - location: Location; - dispatcher: Dispatcher; - docsVersion: string; - availableDocVersions: string[]; - docsInfo: DocsInfo; - translate: Translate; - screenWidth: ScreenWidths; -} - -interface DocPageState { - docAgnosticFormat?: DocAgnosticFormat; -} - -export class DocPage extends React.Component<DocPageProps, DocPageState> { - private _isUnmounted: boolean; - constructor(props: DocPageProps) { - super(props); - this._isUnmounted = false; - this.state = { - docAgnosticFormat: undefined, - }; - } - public componentWillMount(): void { - const pathName = this.props.location.pathname; - const lastSegment = pathName.substr(pathName.lastIndexOf('/') + 1); - const versions = findVersions(lastSegment); - const preferredVersionIfExists = versions.length > 0 ? versions[0] : undefined; - // tslint:disable-next-line:no-floating-promises - this._fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists); - } - public componentWillUnmount(): void { - this._isUnmounted = true; - } - public render(): React.ReactNode { - const sourceUrl = this._getSourceUrl(); - const sectionNameToLinks = _.isUndefined(this.state.docAgnosticFormat) - ? {} - : this.props.docsInfo.getSectionNameToLinks(this.state.docAgnosticFormat); - const mainContent = _.isUndefined(this.state.docAgnosticFormat) ? ( - <div className="flex justify-center">{this._renderLoading()}</div> - ) : ( - <DocReference - selectedVersion={this.props.docsVersion} - availableVersions={this.props.availableDocVersions} - docsInfo={this.props.docsInfo} - docAgnosticFormat={this.state.docAgnosticFormat} - sourceUrl={sourceUrl} - /> - ); - const sidebar = _.isUndefined(this.state.docAgnosticFormat) ? ( - <div /> - ) : ( - <NestedSidebarMenu - sidebarHeader={this._renderSidebarHeader()} - sectionNameToLinks={sectionNameToLinks} - screenWidth={this.props.screenWidth} - /> - ); - return ( - <DevelopersPage - sidebar={sidebar} - mainContent={mainContent} - location={this.props.location} - screenWidth={this.props.screenWidth} - translate={this.props.translate} - dispatcher={this.props.dispatcher} - /> - ); - } - private _renderSidebarHeader(): React.ReactNode { - return ( - <SidebarHeader - screenWidth={this.props.screenWidth} - title={this.props.docsInfo.displayName} - docsVersion={this.props.docsVersion} - availableDocVersions={this.props.availableDocVersions} - onVersionSelected={this._onVersionSelected.bind(this)} - /> - ); - } - private _renderLoading(): React.ReactNode { - return ( - <Container className="pt4"> - <Container className="center pb2"> - <CircularProgress size={40} thickness={5} /> - </Container> - <Container className="center pt2" paddingBottom="11px"> - Loading documentation... - </Container> - </Container> - ); - } - private async _fetchJSONDocsFireAndForgetAsync(preferredVersionIfExists?: string): Promise<void> { - const folderName = docIdToSubpackageName[this.props.docsInfo.id]; - const docBucketRoot = isDevelopmentOrStaging - ? constants.S3_STAGING_DOC_BUCKET_ROOT - : constants.S3_DOC_BUCKET_ROOT; - const versionToFilePath = await docUtils.getVersionToFilePathAsync(docBucketRoot, folderName); - const versions = _.keys(versionToFilePath); - this.props.dispatcher.updateAvailableDocVersions(versions); - const sortedVersions = semverSort.desc(versions); - const latestVersion = sortedVersions[0]; - - let versionToFetch = latestVersion; - if (!_.isUndefined(preferredVersionIfExists)) { - const preferredVersionFileNameIfExists = versionToFilePath[preferredVersionIfExists]; - if (!_.isUndefined(preferredVersionFileNameIfExists)) { - versionToFetch = preferredVersionIfExists; - } - } - this.props.dispatcher.updateCurrentDocsVersion(versionToFetch); - - const versionFilePathToFetch = versionToFilePath[versionToFetch]; - const versionDocObj = await docUtils.getJSONDocFileAsync(versionFilePathToFetch, docBucketRoot); - let docAgnosticFormat; - if (this.props.docsInfo.type === SupportedDocJson.TypeDoc) { - docAgnosticFormat = new TypeDocUtils( - versionDocObj as GeneratedDocJson, - this.props.docsInfo, - ).convertToDocAgnosticFormat(); - } else if (this.props.docsInfo.type === SupportedDocJson.SolDoc) { - // documenting solidity. - docAgnosticFormat = versionDocObj as DocAgnosticFormat; - // HACK: need to modify docsInfo like convertToDocAgnosticFormat() would do - this.props.docsInfo.markdownMenu.Contracts = []; - _.each(docAgnosticFormat, (_docObj, sectionName) => { - this.props.docsInfo.sections[sectionName] = sectionName; - this.props.docsInfo.markdownMenu.Contracts.push(sectionName); - }); - } - - if (!this._isUnmounted) { - this.setState({ - docAgnosticFormat, - }); - } - } - private _getSourceUrl(): string { - const url = this.props.docsInfo.packageUrl; - let pkg = docIdToSubpackageName[this.props.docsInfo.id]; - let tagPrefix = pkg; - const packagesWithNamespace = ['connect']; - if (_.includes(packagesWithNamespace, pkg)) { - tagPrefix = `@0x/${pkg}`; - } - // HACK: The following three lines exist for backward compatibility reasons - // Before exporting types from other packages as part of the 0x.js interface, - // all TypeDoc generated paths omitted the topLevel `0x.js` segment. Now it - // adds it, and for that reason, we need to make sure we don't add it twice in - // the source links we generate. - const semvers = semverSort.desc([this.props.docsVersion, ZERO_EX_JS_VERSION_MISSING_TOPLEVEL_PATH]); - const isVersionAfterTopLevelPathChange = semvers[0] !== ZERO_EX_JS_VERSION_MISSING_TOPLEVEL_PATH; - pkg = this.props.docsInfo.id === DocPackages.ZeroExJs && isVersionAfterTopLevelPathChange ? '' : `/${pkg}`; - - const sourceUrl = `${url}/blob/${tagPrefix}%40${this.props.docsVersion}/packages${pkg}`; - return sourceUrl; - } - private _onVersionSelected(semver: string): void { - let path = window.location.pathname; - const lastChar = path[path.length - 1]; - if (_.isFinite(_.parseInt(lastChar))) { - const pathSections = path.split('/'); - pathSections.pop(); - path = pathSections.join('/'); - } - const baseUrl = utils.getCurrentBaseUrl(); - window.location.href = `${baseUrl}${path}/${semver}${window.location.hash}`; - } -} diff --git a/packages/website/ts/pages/documentation/docs_home.tsx b/packages/website/ts/pages/documentation/docs_home.tsx deleted file mode 100644 index 219903147..000000000 --- a/packages/website/ts/pages/documentation/docs_home.tsx +++ /dev/null @@ -1,498 +0,0 @@ -import { ALink, colors, Link } from '@0x/react-shared'; -import { ObjectMap } from '@0x/types'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { OverviewContent } from 'ts/components/documentation/overview_content'; -import { NestedSidebarMenu } from 'ts/components/nested_sidebar_menu'; -import { Button } from 'ts/components/ui/button'; -import { DevelopersPage } from 'ts/pages/documentation/developers_page'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { Categories, Deco, Key, Package, ScreenWidths, TutorialInfo, WebsitePaths } from 'ts/types'; -import { constants } from 'ts/utils/constants'; -import { Translate } from 'ts/utils/translate'; - -const TUTORIALS: TutorialInfo[] = [ - { - iconUrl: '/images/developers/tutorials/develop_on_ethereum.svg', - description: Key.DevelopOnEthereumDescription, - link: { - title: Key.DevelopOnEthereum, - to: `${WebsitePaths.Wiki}#Ethereum-Development`, - }, - }, - { - iconUrl: '/images/developers/tutorials/build_a_relayer.svg', - description: Key.BuildARelayerDescription, - link: { - title: Key.BuildARelayer, - to: `${WebsitePaths.Wiki}#Build-A-Relayer`, - }, - }, - { - iconUrl: '/images/developers/tutorials/0x_order_basics.svg', - description: Key.OrderBasicsDescription, - link: { - title: Key.OrderBasics, - to: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`, - }, - }, - { - iconUrl: '/images/developers/tutorials/use_shared_liquidity.svg', - description: Key.UseNetworkedLiquidityDescription, - link: { - title: Key.UseNetworkedLiquidity, - to: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`, - }, - }, - { - iconUrl: '/images/developers/tutorials/integrate_0x_instant.svg', - description: Key.Integrate0xInstantDescription, - link: { - title: Key.Integrate0xInstant, - to: `${WebsitePaths.Wiki}#Get-Started-With-Instant`, - }, - }, -]; - -const CATEGORY_TO_PACKAGES: ObjectMap<Package[]> = { - [Categories.ZeroExProtocolTypescript]: [ - { - description: - 'A library for interacting with the 0x protocol. It is a high level package which combines a number of smaller specific-purpose packages such as [order-utils](https://0x.org/docs/order-utils) and [contract-wrappers](https://0x.org/docs/contract-wrappers).', - link: { - title: '0x.js', - to: WebsitePaths.ZeroExJs, - }, - }, - { - description: - 'A Typescript starter project that will walk you through the basics of how to interact with 0x Protocol and trade of an SRA relayer', - link: { - title: '0x starter project', - to: 'https://github.com/0xProject/0x-starter-project', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'Launch a 0x relayer in under a minute with Launch Kit. `0x-launch-kit` is an open-source, free-to-use 0x relayer template that you can use as a starting point for your own project.', - link: { - title: '0x launch kit', - to: 'https://github.com/0xProject/0x-launch-kit', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'Reference documentation for the 0x smart contracts. Helpful for dApp developer wanting to integrate 0x at the smart contract level.', - link: { - title: '0x smart contracts', - to: WebsitePaths.SmartContracts, - }, - }, - { - description: - 'An http & websocket client for interacting with relayers that have implemented the [Standard Relayer API](https://github.com/0xProject/standard-relayer-api)', - link: { - title: '@0x/connect', - to: WebsitePaths.Connect, - }, - }, - { - description: - 'Typescript/Javascript wrappers of the 0x protocol Ethereum smart contracts. Use this library to call methods on the 0x smart contracts, subscribe to contract events and to fetch information stored in contracts.', - link: { - title: '@0x/contract-wrappers', - to: WebsitePaths.ContractWrappers, - }, - }, - { - description: - "A package to deploy the 0x protocol's system of smart contracts to the testnet of your choice", - link: { - title: '@0x/migrations', - to: WebsitePaths.Migrations, - }, - }, - { - description: - 'A collection of 0x-related JSON-schemas (incl. SRA request/response schemas, 0x order message format schema, etc...)', - link: { - title: '@0x/json-schemas', - to: WebsitePaths.JSONSchemas, - }, - }, - { - description: - 'A set of utils for working with 0x orders. It includes utilities for creating, signing, validating 0x orders, encoding/decoding assetData and much more.', - link: { - title: '@0x/order-utils', - to: WebsitePaths.OrderUtils, - }, - }, - { - description: - "A daemon that watches a set of 0x orders and emits events when an order's fillability has changed. Can be used by a relayer to prune their orderbook or by a trader to keep their view of the market up-to-date.", - link: { - title: '@0x/order-watcher', - to: WebsitePaths.OrderWatcher, - }, - }, - { - description: - 'A tiny utility library for getting known deployed contract addresses for a particular network.', - link: { - title: '@0x/contract-addresses', - to: 'https://www.npmjs.com/package/@0x/contract-addresses', - shouldOpenInNewTab: true, - }, - }, - { - description: 'Smart contract compilation artifacts for the latest version of the 0x protocol.', - link: { - title: '@0x/contract-artifacts', - to: 'https://www.npmjs.com/package/@0x/contract-artifacts', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'Contains the Standard Relayer API OpenAPI Spec. The package distributes both a javascript object version and a json version.', - link: { - title: '@0x/sra-spec', - to: 'https://github.com/0xProject/0x-monorepo/tree/development/packages/sra-spec', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'Convenience package for buying assets represented on the Ethereum blockchain using 0x. In its simplest form, the package helps in the usage of the [0x forwarder contract](https://github.com/0xProject/0x-protocol-specification/blob/master/v2/forwarder-specification.md), which allows users to execute [Wrapped Ether](https://weth.io/) based 0x orders without having to set allowances, wrap Ether or own ZRX, meaning they can buy tokens with Ether alone. Given some liquidity (0x signed orders), it helps estimate the Ether cost of buying a certain asset (giving a range) and then buying that asset.', - link: { - title: '@0x/asset-buyer', - to: WebsitePaths.AssetBuyer, - }, - }, - ], - [Categories.ZeroExProtocolPython]: [ - { - description: - "A library for interacting with 0x orders. Generate an orderHash, sign an order, validate it's signature and more.", - link: { - title: '0x-order-utils', - to: 'https://pypi.org/project/0x-order-utils/', - shouldOpenInNewTab: true, - }, - }, - { - description: 'A Standard Relayer API client', - link: { - title: '0x-sra-client', - to: 'https://pypi.org/project/0x-sra-client/', - shouldOpenInNewTab: true, - }, - }, - { - description: 'Package containing the addresses at which the 0x smart contracts have been deployed', - link: { - title: '0x-contract-addresses', - to: 'https://pypi.org/project/0x-contract-addresses/', - shouldOpenInNewTab: true, - }, - }, - { - description: 'Package containing the 0x smart contract compilation artifacts', - link: { - title: '0x-contract-artifacts', - to: 'https://pypi.org/project/0x-contract-artifacts/', - shouldOpenInNewTab: true, - }, - }, - { - description: '0x JSON schemas for those developing on top of 0x protocol', - link: { - title: '0x-json-schemas', - to: 'https://pypi.org/project/0x-json-schemas/', - shouldOpenInNewTab: true, - }, - }, - { - description: 'Demo project showing how to interact with the 0x smart contracts using Python', - link: { - title: '0x-contract-demo', - to: 'https://github.com/0xProject/0x-monorepo/blob/development/python-packages/contract_demo/README.md', - shouldOpenInNewTab: true, - }, - }, - ], - [Categories.Ethereum]: [ - { - description: - "This package allows you to generate TypeScript contract wrappers from ABI files. It's heavily inspired by Geth abigen but takes a different approach. You can write your custom handlebars templates which will allow you to seamlessly integrate the generated code into your existing codebase with existing conventions.", - link: { - title: 'abi-gen', - to: 'https://github.com/0xProject/0x-monorepo/tree/development/packages/abi-gen', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'A collection of Typescript types that are useful when working on an Ethereum-based project (e.g RawLog, Transaction, TxData, SolidityTypes, etc...).', - link: { - title: 'ethereum-types', - to: WebsitePaths.EthereumTypes, - }, - }, - { - description: - 'A wrapper around [solc-js](https://github.com/ethereum/solc-js) that adds smart re-compilation, ability to compile an entire project, Solidity version specific compilation, standard input description support and much more.', - link: { - title: '@0x/sol-compiler', - to: WebsitePaths.SolCompiler, - }, - }, - { - description: - 'A Solidity code coverage tool. Sol-coverage uses transaction traces to figure out which lines of your code has been covered by your tests.', - link: { - title: '@0x/sol-coverage', - to: WebsitePaths.SolCoverage, - }, - }, - { - description: - 'A Solidity profiler. Sol-profiler uses transaction traces to figure out line-by-line gas consumption.', - link: { - title: '@0x/sol-profiler', - to: WebsitePaths.SolProfiler, - }, - }, - { - description: - 'A Solidity revert trace tool. Sol-trace prints human-readable revert trace whenever the revert happens.', - link: { - title: '@0x/sol-trace', - to: WebsitePaths.SolTrace, - }, - }, - { - description: - 'A collection of subproviders to use with [web3-provider-engine](https://www.npmjs.com/package/web3-provider-engine) (e.g subproviders for interfacing with Ledger hardware wallet, Mnemonic wallet, private key wallet, etc...)', - link: { - title: '@0x/subproviders', - to: WebsitePaths.Subproviders, - }, - }, - { - description: - 'A raw Ethereum JSON RPC client to simplify interfacing with Ethereum nodes. Also includes some convenience functions for awaiting transactions to be mined, converting between token units, etc...', - link: { - title: '@0x/web3-wrapper', - to: WebsitePaths.Web3Wrapper, - }, - }, - ], - [Categories.CommunityMaintained]: [ - { - description: - 'Node.js worker originally built for 0x Tracker which extracts 0x fill events from the Ethereum blockchain and persists them to MongoDB. Support for both V1 and V2 of the 0x protocol is included with events tagged against the protocol version they belong to.', - link: { - title: '0x Event Extractor', - to: 'https://github.com/0xTracker/0x-event-extractor', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'Node.js worker built for 0x Tracker which performs various ETL tasks related to the 0x protocol trading data and other information used on 0x Tracker.', - link: { - title: '0x Tracker Worker', - to: 'https://github.com/0xTracker/0x-tracker-worker', - shouldOpenInNewTab: true, - }, - }, - { - description: - "ERCdEX's Javascript SDK for trading on their relayer, as well as other Aquaduct partner relayers", - link: { - title: 'Aquaduct', - to: 'https://www.npmjs.com/package/aqueduct', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'SDKs for automation using Aqueduct & ERC dEX. Aqueduct Server is a lightweight, portable and secure server that runs locally on any workstation. The server exposes a small number of foundational endpoints that enable working with the decentralized Aqueduct liquidity pool from any context or programming language.', - link: { - title: 'Aquaduct Server SDK', - to: 'https://github.com/ERCdEX/aqueduct-server-sdk', - shouldOpenInNewTab: true, - }, - }, - { - description: "The ERCdEX Trade Widget let's any website provide token liquidity to it's users", - link: { - to: 'https://github.com/ERCdEX/widget', - title: 'ERCdEX Widget', - shouldOpenInNewTab: true, - }, - }, - { - description: "ERCdEX's Java SDK for trading on their relayer, as well as other Aquaduct partner relayers", - link: { - to: 'https://github.com/ERCdEX/java', - title: 'ERCdEX Java SDK', - shouldOpenInNewTab: true, - }, - }, - { - description: "ERCdEX's Python SDK for trading on their relayer, as well as other Aquaduct partner relayers", - link: { - to: 'https://github.com/ERCdEX/python', - title: 'ERCdEX Python SDK', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'A set of command-line tools for creating command-line scripts for interacting with the Ethereum blockchain in general, and 0x in particular', - link: { - title: 'Massive', - to: 'https://github.com/NoteGio/massive', - shouldOpenInNewTab: true, - }, - }, - { - description: 'An open-source API-only Relayer written in Go', - link: { - to: 'https://github.com/NoteGio/openrelay', - title: 'OpenRelay', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'A JavaScript Library for Interacting with OpenRelay.xyz and other 0x Standard Relayer API Implementations', - link: { - title: 'OpenRelay.js', - to: 'https://github.com/NoteGio/openrelay.js', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'The Radar Relay SDK is a software development kit that simplifies the interactions with Radar Relay’s APIs', - link: { - title: 'Radar SDK', - to: 'https://github.com/RadarRelay/sdk', - shouldOpenInNewTab: true, - }, - }, - { - description: - 'The Ocean provides a simple REST API, WebSockets API, and JavaScript library to help you integrate decentralized trading into your existing trading strategy.', - link: { - title: 'The Ocean Javascript SDK', - to: 'https://github.com/TheOceanTrade/theoceanx-javascript', - shouldOpenInNewTab: true, - }, - }, - { - description: "Tokenlon SDK provides APIs for developers to trade of imToken's relayer", - link: { - to: 'https://www.npmjs.com/package/tokenlon-sdk', - title: 'Tokenlon Javascript SDK', - shouldOpenInNewTab: true, - }, - }, - { - description: 'A small library that implements the 0x order assetData encoding/decoding in Java', - link: { - to: 'https://github.com/wildnothing/asset-data-decoder', - title: 'AssetData decoder library in Java', - shouldOpenInNewTab: true, - }, - }, - ], -}; - -export interface DocsHomeProps { - location: Location; - translate: Translate; - screenWidth: ScreenWidths; - tutorials: TutorialInfo[]; - categoryToPackages: ObjectMap<Package[]>; - dispatcher: Dispatcher; -} - -export interface DocsHomeState {} - -export class DocsHome extends React.Component<DocsHomeProps, DocsHomeState> { - public render(): React.ReactNode { - const sectionNameToLinks: ObjectMap<ALink[]> = { - 'Starter guides': _.map(TUTORIALS, tutorialInfo => { - return { - ...tutorialInfo.link, - title: this.props.translate.get(tutorialInfo.link.title as Key, Deco.Cap), - }; - }), - [Categories.ZeroExProtocolTypescript]: _.map( - CATEGORY_TO_PACKAGES[Categories.ZeroExProtocolTypescript], - pkg => pkg.link, - ), - [Categories.Ethereum]: _.map(CATEGORY_TO_PACKAGES[Categories.Ethereum], pkg => pkg.link), - [Categories.CommunityMaintained]: _.map( - CATEGORY_TO_PACKAGES[Categories.CommunityMaintained], - pkg => pkg.link, - ), - }; - const mainContent = ( - <OverviewContent - translate={this.props.translate} - tutorials={TUTORIALS} - categoryToPackages={CATEGORY_TO_PACKAGES} - /> - ); - const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; - const sidebar = ( - <NestedSidebarMenu - sidebarHeader={isSmallScreen ? this._renderSidebarHeader() : undefined} - sectionNameToLinks={sectionNameToLinks} - shouldReformatMenuItemNames={false} - screenWidth={this.props.screenWidth} - /> - ); - return ( - <DevelopersPage - mainContent={mainContent} - sidebar={sidebar} - location={this.props.location} - screenWidth={this.props.screenWidth} - translate={this.props.translate} - dispatcher={this.props.dispatcher} - /> - ); - } - private _renderSidebarHeader(): React.ReactNode { - const menuItems = _.map(constants.DEVELOPER_TOPBAR_LINKS, menuItemInfo => { - return ( - <Link - key={`menu-item-${menuItemInfo.title}`} - to={menuItemInfo.to} - shouldOpenInNewTab={menuItemInfo.shouldOpenInNewTab} - > - <Button - borderRadius="4px" - padding="0.4em 0.375em" - width="100%" - fontColor={colors.grey800} - fontSize="14px" - textAlign="left" - > - {this.props.translate.get(menuItemInfo.title as Key, Deco.Cap)} - </Button> - </Link> - ); - }); - return menuItems; - } -} // tslint:disable:max-file-line-count diff --git a/packages/website/ts/pages/ecosystem.tsx b/packages/website/ts/pages/ecosystem.tsx deleted file mode 100644 index 8e367b21f..000000000 --- a/packages/website/ts/pages/ecosystem.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled from 'styled-components'; - -import { colors } from 'ts/style/colors'; - -import { Button } from 'ts/components/button'; -import { Icon } from 'ts/components/icon'; -import { Column, Section, WrapGrid } from 'ts/components/newLayout'; -import { SiteWrap } from 'ts/components/siteWrap'; -import { Heading, Paragraph } from 'ts/components/text'; -import { constants } from 'ts/utils/constants'; - -interface BenefitProps { - title: string; - icon: string; - description: string; -} - -const benefits: BenefitProps[] = [ - { - icon: 'milestoneGrants', - title: 'Milestone Grants', - description: - 'Receive non-dilutive capital ranging from $10,000 to $100,000, with grant sizes awarded based on the quality of your team, vision, execution, and community involvement.', - }, - { - icon: 'vcIntroductions', - title: 'VC Introductions', - description: 'Connect with leading venture capital firms that could participate in your next funding round.', - }, - { - icon: 'techSupport', - title: 'Technical Support', - description: 'Receive ongoing technical assistance from knowledgeable and responsive 0x developers.', - }, - { - icon: 'recruitingSupport', - title: 'Recruiting Assistance', - description: 'Grow your team by accessing an exclusive pool of top engineering and business operations talent.', - }, - { - icon: 'eficientDesign', - title: 'Marketing and Design Help', - description: - 'Get strategic advice on product positioning, customer acquisition, and UI/UX design that can impact the growth of your business.', - }, - { - icon: 'legalResources', - title: 'Legal Resources', - description: 'Access important legal resources that will help you navigate the regulatory landscape.', - }, -]; - -export const NextEcosystem = () => ( - <SiteWrap theme="light"> - <DocumentTitle title="Ecosystem Acceleration Program: Jumpstart your Business on 0x" /> - <Section isTextCentered={true}> - <Column> - <Heading size="medium" isCentered={true}> - Jumpstart your Business on 0x - </Heading> - <Paragraph size="medium" isCentered={true} isMuted={true} marginBottom="0"> - The Ecosystem Acceleration Program gives teams access to a variety of services including funding, - dedicated technical support, and recruiting assistance. We created the Ecosystem Acceleration - Program to bolster the expansion of both infrastructure projects and relayers building on 0x. - </Paragraph> - <LinkWrap> - <Button - href={constants.URL_ECOSYSTEM_APPLY} - isWithArrow={true} - isAccentColor={true} - shouldUseAnchorTag={true} - > - Apply now - </Button> - <Button - href={constants.URL_ECOSYSTEM_BLOG_POST} - isWithArrow={true} - isAccentColor={true} - shouldUseAnchorTag={true} - target="_blank" - > - Learn More - </Button> - </LinkWrap> - </Column> - </Section> - - <Section bgColor={colors.backgroundLight} isFullWidth={true}> - <Column> - <Heading - size={34} - fontWeight="400" - asElement="h2" - isCentered={true} - maxWidth="507px" - marginBottom="70px" - > - Join a vibrant ecosystem of projects in the 0x Network. - </Heading> - </Column> - <WrapGrid isTextCentered={true} isWrapped={true} isFullWidth={true}> - {_.map(benefits, (benefit: BenefitProps, index) => ( - <Column key={`benefit-${index}`} width="33%" padding="0 45px 30px"> - <Icon name={benefit.icon} size="medium" margin={[0, 0, 'small', 0]} /> - <Heading color={colors.textDarkPrimary} size="small" marginBottom="10px" isCentered={true}> - {benefit.title} - </Heading> - <Paragraph isMuted={true} isCentered={true}> - {benefit.description} - </Paragraph> - </Column> - ))} - </WrapGrid> - </Section> - </SiteWrap> -); - -const LinkWrap = styled.div` - display: inline-flex; - margin-top: 60px; - - a + a { - margin-left: 60px; - } -`; diff --git a/packages/website/ts/pages/faq/faq.tsx b/packages/website/ts/pages/faq/faq.tsx deleted file mode 100644 index 548db1d1d..000000000 --- a/packages/website/ts/pages/faq/faq.tsx +++ /dev/null @@ -1,453 +0,0 @@ -import { colors, 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 { Question } from 'ts/pages/faq/question'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { FAQQuestion, FAQSection, WebsitePaths } from 'ts/types'; -import { configs } from 'ts/utils/configs'; -import { constants } from 'ts/utils/constants'; -import { Translate } from 'ts/utils/translate'; - -export interface FAQProps { - source: string; - location: Location; - translate: Translate; - dispatcher: Dispatcher; -} - -interface FAQState {} - -const styles: Styles = { - thin: { - fontWeight: 100, - }, -}; - -const sections: FAQSection[] = [ - { - name: '0x Protocol', - questions: [ - { - prompt: 'What is 0x?', - answer: ( - <div> - At its core, 0x is an open and non-rent seeking protocol that facilitates trustless, low - friction exchange of Ethereum-based assets. Developers can use 0x as a platform to build - exchange applications on top of ( - <a href={`${configs.BASE_URL}${WebsitePaths.ZeroExJs}#introduction`} target="blank"> - 0x.js - </a>{' '} - is a Javascript library for interacting with the 0x protocol). For end users, 0x will be the - infrastructure of a wide variety of user-facing applications i.e.{' '} - <a href={`${configs.BASE_URL}${WebsitePaths.Portal}`} target="blank"> - 0x Portal - </a> - , a decentralized application that facilitates trustless trading of Ethereum-based tokens - between known counterparties. - </div> - ), - }, - { - prompt: 'What problem does 0x solve?', - answer: ( - <div> - In the two years since the Ethereum blockchain’s genesis block, numerous decentralized - applications (dApps) have created Ethereum smart contracts for peer-to-peer exchange. Rapid - iteration and a lack of best practices have left the blockchain scattered with proprietary and - application-specific implementations. As a result, end users are exposed to numerous smart - contracts of varying quality and security, with unique configuration processes and learning - curves, all of which implement the same functionality. This approach imposes unnecessary costs - on the network by fragmenting end users according to the particular dApp each user happens to be - using, eliminating valuable network effects around liquidity. 0x is the solution to this problem - by acting as modular, unopinionated building blocks that may be assembled and reconfigured. - </div> - ), - }, - { - prompt: 'How is 0x different from a centralized exchange like Poloniex or ShapeShift?', - answer: ( - <div> - <ul> - <li>0x is a protocol for exchange, not a user-facing exchange application.</li> - <li> - 0x is decentralized and trustless; there is no central party which can be hacked, run - away with customer funds or be subjected to government regulations. Hacks of Mt. Gox, - Shapeshift and Bitfinex have demonstrated that these types of systemic risks are - palpable. - </li> - <li> - Rather than a proprietary system that exists to extract rent for its owners, 0x is - public infrastructure that is funded by a globally distributed community of - stakeholders. While the protocol is free to use, it enables for-profit user-facing - exchange applications to be built on top of the protocol. - </li> - </ul> - </div> - ), - }, - { - prompt: 'If 0x protocol is free to use, where do transaction fees come in?', - answer: ( - <div> - 0x protocol uses off-chain order books to massively reduce friction costs for market makers and - ensure that the blockchain is only used for trade settlement. Hosting and maintaining an - off-chain order book is a service; to incent “Relayers” to provide this service they must be - able to charge transaction fees on trading activity. Relayers are free to set their transaction - fees to any value they desire. We expect Relayers to be highly competitive and transaction fees - to approach an efficient economic equilibrium over time. - </div> - ), - }, - { - prompt: 'What are the differences between 0x protocol and state channels?', - answer: ( - <div> - <div> - Participants in a state channel pass cryptographically signed messages back and forth, - accumulating intermediate state changes without publishing them to the canonical chain until - the channel is closed. State channels are ideal for “bar tab” applications where numerous - intermediate state changes may be accumulated off-chain before being settled by a final - on-chain transaction (i.e. day trading, poker, turn-based games). - </div> - <ul> - <li> - While state channels drastically reduce the number of on-chain transactions for specific - use cases, numerous on-chain transactions and a security deposit are required to open - and safely close a state channel making them less efficient than 0x for executing - one-time trades. - </li> - <li> - State channels are isolated from the Ethereum blockchain meaning that they cannot - interact with smart contracts. 0x is designed to be integrated directly into smart - contracts so trades can be executed programmatically in a single line of Solidity code. - </li> - </ul> - </div> - ), - }, - { - prompt: 'What types of digital assets are supported by 0x?', - answer: ( - <div> - 0x supports all Ethereum-based assets that adhere to the ERC20 token standard. There are many - ERC20 tokens, worth a combined $2.2B, and more tokens are created each month. We believe that, - by 2020, thousands of assets will be tokenized and moved onto the Ethereum blockchain including - traditional securities such as equities, bonds and derivatives, fiat currencies and scarce - digital goods such as video game items. In the future, cross-blockchain solutions such as{' '} - <a href="https://cosmos.network/" target="_blank"> - Cosmos - </a>{' '} - and{' '} - <a href="http://polkadot.io/" target="_blank"> - Polkadot - </a>{' '} - will allow cryptocurrencies to freely move between blockchains and, naturally, currencies such - as Bitcoin will end up being represented as ERC20 tokens on the Ethereum blockchain. - </div> - ), - }, - { - prompt: '0x is open source: what prevents someone from forking the protocol?', - answer: ( - <div> - Ethereum and Bitcoin are both open source protocols. Each protocol has been forked, but the - resulting clone networks have seen little adoption (as measured by transaction count or market - cap). This is because users have little to no incentive to switch over to a clone network if the - original has initial network effects and a talented developer team behind it. An exception is in - the case that a protocol includes a controversial feature such as a method of rent extraction or - a monetary policy that favors one group of users over another (Zcash developer subsidy - for - better or worse - resulted in Zclassic). Perceived inequality can provide a strong enough - incentive that users will fork the original protocol’s codebase and spin up a new network that - eliminates the controversial feature. In the case of 0x, there is no rent extraction and no - users are given special permissions. 0x protocol is upgradable. Cutting-edge technical - capabilities can be integrated into 0x via decentralized governance (see section below), - eliminating incentives to fork off of the original protocol and sacrifice the network effects - surrounding liquidity that result from the shared protocol and settlement layer. - </div> - ), - }, - ], - }, - { - name: '0x Token (ZRX)', - questions: [ - { - prompt: 'Explain how the 0x protocol token (zrx) works.', - answer: ( - <div> - <div> - 0x protocol token (ZRX) is utilized in two ways: 1) to solve the{' '} - <a href="https://en.wikipedia.org/wiki/Coordination_game" target="_blank"> - coordination problem - </a>{' '} - and drive network effects around liquidity, creating a feedback loop where early adopters of - the protocol benefit from wider adoption and 2) to be used for decentralized governance over - 0x protocol's update mechanism. In more detail: - </div> - <ul> - <li> - ZRX tokens are used by Makers and Takers (market participants that generate and consume - orders, respectively) to pay transaction fees to Relayers (entities that host and - maintain public order books). - </li> - <li> - ZRX tokens are used for decentralized governance over 0x protocol’s update mechanism - which allows its underlying smart contracts to be replaced and improved over time. An - update mechanism is needed because 0x is built upon Ethereum’s rapidly evolving - technology stack, decentralized governance is needed because 0x protocol’s smart - contracts will have access to user funds and numerous dApps will need to plug into 0x - smart contracts. Decentralized governance ensures that this update process is secure and - minimizes disruption to the network. - </li> - </ul> - </div> - ), - }, - { - prompt: 'Why must transaction fees be denominated in 0x token (ZRX) rather than ETH?', - answer: ( - <div> - 0x protocol’s decentralized update mechanism is analogous to proof-of-stake. To maximize the - alignment of stakeholder and end user incentives, the staked asset must provide utility within - the protocol. - </div> - ), - }, - { - prompt: 'How will decentralized governance work?', - answer: ( - <div> - Decentralized governance is an ongoing focus of research; it will involve token voting with ZRX. - Ultimately the solution will maximize security while also maximizing the protocol’s ability to - absorb new innovations. Until the governance structure is formalized and encoded within 0x DAO, - a multi-sig will be used as a placeholder. - </div> - ), - }, - ], - }, - { - name: 'ZRX Token Launch and Fund Use', - questions: [ - { - prompt: 'What is the total supply of ZRX tokens?', - answer: <div>1,000,000,000 ZRX. Fixed supply.</div>, - }, - { - prompt: 'When was the token launch? Was there a pre-sale?', - answer: <div>The token launch was on August 15th, 2017. There was no pre-sale.</div>, - }, - { - prompt: 'What will the token launch proceeds be used for?', - answer: ( - <div> - 100% of the proceeds raised in the token launch will be used to fund the development of free and - open source software, tools and infrastructure that support the protocol and surrounding - ecosystem. Check out our{' '} - <a - href="https://docs.google.com/document/d/1_RVa-_bkU92fWRsC8eNy4vYjcTt-WC8GtqyyjbTd-oY" - target="_blank" - > - development roadmap - </a> - . - </div> - ), - }, - { - prompt: 'What will be the initial distribution of ZRX tokens?', - answer: ( - <div> - <div className="center" style={{ width: '100%' }}> - <img style={{ width: 350 }} src="/images/zrx_pie_chart.png" /> - </div> - <div className="py1"> - <div className="bold pb1">Token Launch (50%)</div> - <div> - ZRX is inherently a governance token that plays a critical role in the process of - upgrading 0x protocol. We are fully committed to formulating a functional and - theoretically sound governance model and we plan to dedicate significant resources to - R&D. - </div> - </div> - <div className="py1"> - <div className="bold pb1">Retained by 0x (15%)</div> - <div> - The 0x core development team will be able to sustain itself for approximately five years - using funds raised through the token launch. If 0x protocol proves to be as foundational - a technology as we believe it to be, the retained ZRX tokens will allow the 0x core - development team to sustain operations beyond the first 5 years. - </div> - </div> - <div className="py1"> - <div className="bold pb1">Developer Fund (15%)</div> - <div> - The Developer Fund will be used to make targeted capital injections into high potential - projects and teams that are attempting to grow the 0x ecosystem, strategic partnerships, - hackathon prizes and community development activities. - </div> - </div> - <div className="py1"> - <div className="bold pb1">Founding Team (10%)</div> - <div> - The founding team’s allocation of ZRX will vest over a traditional 4 year vesting - schedule with a one year cliff. We believe this should be standard practice for any team - that is committed to making their project a long term success. - </div> - </div> - <div className="py1"> - <div className="bold pb1">Early Backers & Advisors (10%)</div> - <div> - Our backers and advisors have provided capital, resources and guidance that have allowed - us to fill out our team, setup a robust legal entity and build a fully functional - product before launching a token. As a result, we have a proven track record and can - offer a token that holds genuine utility. - </div> - </div> - </div> - ), - }, - { - prompt: 'Can I mine ZRX tokens?', - answer: ( - <div> - No, the total supply of ZRX tokens is fixed and there is no continuous issuance model. Users - that facilitate trading over 0x protocol by operating a Relayer earn transaction fees - denominated in ZRX; as more trading activity is generated, more transaction fees are earned. - </div> - ), - }, - { - prompt: 'Will there be a lockup period for ZRX tokens sold in the token launch?', - answer: <div>No, ZRX tokens sold in the token launch will immediately be liquid.</div>, - }, - { - prompt: 'Will there be a lockup period for tokens allocated to the founding team?', - answer: ( - <div> - Yes. ZRX tokens allocated to founders, advisors and staff members will be released over a 4 year - vesting schedule with a 25% cliff upon completion of the initial token launch and 25% released - each subsequent year in monthly installments. Staff members hired after the token launch will - have a 4 year vesting schedule with a one year cliff. - </div> - ), - }, - { - prompt: 'Which cryptocurrencies will be accepted in the token launch?', - answer: <div>ETH.</div>, - }, - { - prompt: 'When will 0x be live?', - answer: ( - <div> - An alpha version of 0x has been live on our private test network since January 2017. Version 1.0 - of 0x protocol will be deployed to the canonical Ethereum blockchain after a round of security - audits and prior to the public token launch. 0x will be using the 0x protocol during our token - launch. - </div> - ), - }, - { - prompt: 'Where can I find a development roadmap?', - answer: ( - <div> - Check it out{' '} - <a - href="https://drive.google.com/open?id=14IP1N8mt3YdsAoqYTyruMnZswpklUs3THyS1VXx71fo" - target="_blank" - > - here - </a> - . - </div> - ), - }, - ], - }, - { - name: 'Team', - questions: [ - { - prompt: 'Where is 0x based?', - answer: <div>0x was founded in SF and is driven by a diverse group of contributors.</div>, - }, - { - prompt: 'How can I get involved?', - answer: ( - <div> - Join our{' '} - <a href={constants.URL_ZEROEX_CHAT} target="_blank"> - Discord - </a> - ! As an open source project, 0x will rely on a worldwide community of passionate developers to - contribute proposals, ideas and code. - </div> - ), - }, - { - prompt: 'Why the name 0x?', - answer: ( - <div> - 0x is the prefix for hexadecimal numeric constants including Ethereum addresses. In a more - abstract context, as the first open protocol for exchange 0x represents the beginning of the end - for the exchange industry’s rent seeking oligopoly: zero exchange. - </div> - ), - }, - { - prompt: 'How do you pronounce 0x?', - answer: <div>We pronounce 0x as “zero-ex,” but you are free to pronounce it however you please.</div>, - }, - ], - }, -]; - -export class FAQ extends React.Component<FAQProps, FAQState> { - public componentDidMount(): void { - window.scrollTo(0, 0); - } - public render(): React.ReactNode { - return ( - <div> - <DocumentTitle title="0x FAQ" /> - <TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} /> - <div id="faq" className="mx-auto max-width-4 pt4" style={{ color: colors.grey800 }}> - <h1 className="center" style={{ ...styles.thin }}> - 0x FAQ - </h1> - <div className="sm-px2 md-px2 lg-px0 pb4">{this._renderSections()}</div> - </div> - <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} /> - </div> - ); - } - private _renderSections(): React.ReactNode { - const renderedSections = _.map(sections, (section: FAQSection, i: number) => { - const isFirstSection = i === 0; - return ( - <div key={section.name}> - <h3>{section.name}</h3> - {this._renderQuestions(section.questions, isFirstSection)} - </div> - ); - }); - return renderedSections; - } - private _renderQuestions(questions: FAQQuestion[], isFirstSection: boolean): React.ReactNode { - const renderedQuestions = _.map(questions, (question: FAQQuestion, i: number) => { - const isFirstQuestion = i === 0; - return ( - <Question - key={question.prompt} - prompt={question.prompt} - answer={question.answer} - shouldDisplayExpanded={isFirstSection && isFirstQuestion} - /> - ); - }); - return renderedQuestions; - } -} diff --git a/packages/website/ts/pages/faq/question.tsx b/packages/website/ts/pages/faq/question.tsx deleted file mode 100644 index 413ffb6ce..000000000 --- a/packages/website/ts/pages/faq/question.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { colors } from '@0x/react-shared'; -import { Card, CardHeader, CardText } from 'material-ui/Card'; -import * as React from 'react'; - -export interface QuestionProps { - prompt: string; - answer: React.ReactNode; - shouldDisplayExpanded: boolean; -} - -interface QuestionState { - isExpanded: boolean; -} - -export class Question extends React.Component<QuestionProps, QuestionState> { - constructor(props: QuestionProps) { - super(props); - this.state = { - isExpanded: props.shouldDisplayExpanded, - }; - } - public render(): React.ReactNode { - return ( - <div className="py1"> - <Card - initiallyExpanded={this.props.shouldDisplayExpanded} - onExpandChange={this._onExchangeChange.bind(this)} - > - <CardHeader - title={this.props.prompt} - style={{ - borderBottom: this.state.isExpanded ? '1px solid rgba(0, 0, 0, 0.19)' : 'none', - }} - titleStyle={{ color: colors.darkerGrey }} - actAsExpander={true} - showExpandableButton={true} - /> - <CardText expandable={true}> - <div style={{ lineHeight: 1.4 }}>{this.props.answer}</div> - </CardText> - </Card> - </div> - ); - } - private _onExchangeChange(): void { - this.setState({ - isExpanded: !this.state.isExpanded, - }); - } -} diff --git a/packages/website/ts/pages/fullscreen_message.tsx b/packages/website/ts/pages/fullscreen_message.tsx deleted file mode 100644 index 675f27a01..000000000 --- a/packages/website/ts/pages/fullscreen_message.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { Styles } from '@0x/react-shared'; -import * as React from 'react'; - -export interface FullscreenMessageProps { - headerText: string; - bodyText: string; -} - -const styles: Styles = { - thin: { - fontWeight: 100, - }, -}; - -export const FullscreenMessage = (props: FullscreenMessageProps) => { - return ( - <div className="mx-auto max-width-4 py4"> - <div className="center py4"> - <div className="py4"> - <div className="py4"> - <h1 style={styles.thin}>{props.headerText}</h1> - <div className="py1"> - <div className="py3">{props.bodyText}</div> - </div> - </div> - </div> - </div> - </div> - ); -}; diff --git a/packages/website/ts/pages/instant.tsx b/packages/website/ts/pages/instant.tsx deleted file mode 100644 index 586665d5b..000000000 --- a/packages/website/ts/pages/instant.tsx +++ /dev/null @@ -1,255 +0,0 @@ -import { utils as sharedUtils } from '@0x/react-shared'; -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import styled, { keyframes } from 'styled-components'; - -import { Banner } from 'ts/components/banner'; -import { Button } from 'ts/components/button'; -import { Definition } from 'ts/components/definition'; -import { Hero } from 'ts/components/hero'; -import { Section, SectionProps } from 'ts/components/newLayout'; -import { SiteWrap } from 'ts/components/siteWrap'; -import { Heading, Paragraph } from 'ts/components/text'; -import { Configurator } from 'ts/pages/instant/configurator'; -import { colors } from 'ts/style/colors'; -import { WebsitePaths } from 'ts/types'; -import { utils } from 'ts/utils/utils'; - -import { ModalContact } from '../components/modals/modal_contact'; - -const CONFIGURATOR_MIN_WIDTH_PX = 1050; - -export const getStartedClick = () => { - if (window.innerWidth < CONFIGURATOR_MIN_WIDTH_PX) { - utils.openUrl(`${WebsitePaths.Wiki}#Get-Started-With-Instant`); - } else { - sharedUtils.setUrlHash('configurator'); - sharedUtils.scrollToHash('configurator', ''); - } -}; - -const featuresData = [ - { - title: 'Support ERC-20 and ERC-721 tokens', - icon: 'supportForAllEthereumStandards-large', - description: - 'Seamlessly integrate token purchasing into your product experience by offering digital assets ranging from in-game items to stablecoins.', - links: [ - { - label: 'Get Started', - onClick: getStartedClick, - shouldUseAnchorTag: true, - }, - { - label: 'Explore the Docs', - url: `${WebsitePaths.Wiki}#Get-Started-With-Instant`, - }, - ], - }, - { - title: 'Generate revenue for your business', - icon: 'generateRevenueForYourBusiness-large', - description: - 'With just a few lines of code, you can earn up to 5% in affiliate fees on every transaction from your crypto wallet or dApp.', - links: [ - { - label: 'Learn about affiliate fees', - url: `${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`, - }, - ], - }, - { - title: 'Easy and flexible integration', - icon: 'flexibleIntegration0xInstant', - description: - 'Use our out-of-the-box design or customize the user interface by integrating via the AssetBuyer engine.. You can also tap into 0x networked liquidity or choose your own liquidity pool.', - links: [ - { - label: 'Explore AssetBuyer', - url: `${WebsitePaths.Docs}/asset-buyer`, - }, - ], - }, -]; - -interface Props { - theme: { - bgColor: string; - textColor: string; - linkColor: string; - }; -} - -export class Next0xInstant extends React.Component<Props> { - public state = { - isContactModalOpen: false, - }; - public render(): React.ReactNode { - return ( - <SiteWrap> - <DocumentTitle title="0x Instant: Quick and secure crypto purchasing" /> - <Hero - title="Introducing 0x Instant" - description="A free and flexible way to offer simple crypto purchasing in any app or website" - actions={<Button onClick={getStartedClick}>Get Started</Button>} - /> - - <Section isFullWidth={true} isPadded={false} padding="30px 0"> - <MarqueeWrap> - <div> - {[...Array(18)].map((item, index) => ( - <Card key={`card-${index}`} index={index}> - <img src={`/images/0x-instant/widget-${(index % 6) + 1}.png`} /> - </Card> - ))} - </div> - </MarqueeWrap> - </Section> - - <Section> - {_.map(featuresData, (item, index) => ( - <Definition - key={`definition-${index}`} - icon={item.icon} - title={item.title} - description={item.description} - isInlineIcon={true} - iconSize={240} - actions={item.links} - /> - ))} - </Section> - - <ConfiguratorSection - id="configurator" - maxWidth="1386px" - padding="0 58px 70px" - bgColor={colors.backgroundDark} - > - <Heading>0x Instant Configurator</Heading> - <Configurator /> - </ConfiguratorSection> - - <Banner - heading="Need more flexibility?" - subline="Dive into our docs, or contact us if needed" - mainCta={{ text: 'Explore the Docs', href: `${WebsitePaths.Wiki}#Get-Started-With-Instant` }} - secondaryCta={{ text: 'Get in Touch', onClick: this._onOpenContactModal.bind(this) }} - /> - <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} /> - - <Section maxWidth="1170px" isPadded={false} padding="60px 0"> - <Paragraph size="small" isMuted={0.5}> - Disclaimer: 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. - </Paragraph> - <Paragraph size="small" isMuted={0.5}> - See the Apache License, Version 2.0 for the specific language governing all applicable - permissions and limitations. - </Paragraph> - </Section> - </SiteWrap> - ); - } - - public _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - public _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; -} - -// scroll animation calc is simply (imageWidth * totalRepetitions) / 2 -// img width is 370px -const scroll = keyframes` - 0% { transform: translate3d(-2220px, 0, 0) } - 100% { transform: translate3d(-4440px, 0, 0) } -`; - -const scrollMobile = keyframes` - 0% { transform: translate3d(0, 0, 0) } - 100% { transform: translate3d(-1800px, 0, 0) } -`; - -const fadeUp = keyframes` - 0% { - opacity: 0; - transform: translateY(50px); - } - 100% { - opacity: 1; - transform: translateY(0px); - } -`; - -const ConfiguratorSection = styled(Section)<SectionProps>` - @media (max-width: ${CONFIGURATOR_MIN_WIDTH_PX}px) { - display: none; - } -`; - -// width = 370 * 12 -// mobile width = 300 -const MarqueeWrap = styled.div` - width: 100vw; - height: 514px; - padding-bottom: 60px; - - @media (max-width: 768px) { - width: calc(100% + 60px); - margin-left: -30px; - overflow: hidden; - } - - > div { - height: auto; - display: flex; - will-change: transform; - transform: translate3d(-2220px, 0, 0); - } - - @media (min-width: 768px) { - > div { - width: 6660px; - animation: ${scroll} 70s linear infinite; - } - } - - @media (max-width: 768px) { - > div { - width: 5400px; - animation: ${scrollMobile} 70s linear infinite; - } - } -`; - -const Card = styled.div<{ index: number }>` - opacity: 0; - flex-shrink: 0; - transform: translateY(10px); - will-change: opacity, transform; - animation: ${fadeUp} 0.75s ${props => `${props.index * 0.05}s`} forwards; - - img { - height: auto; - } - - @media (min-width: 768px) { - img { - width: 370px; - } - } - - @media (max-width: 768px) { - img { - width: 300px; - } - } -`; diff --git a/packages/website/ts/pages/instant/code_demo.tsx b/packages/website/ts/pages/instant/code_demo.tsx deleted file mode 100644 index c59f148b8..000000000 --- a/packages/website/ts/pages/instant/code_demo.tsx +++ /dev/null @@ -1,183 +0,0 @@ -import * as React from 'react'; -import * as CopyToClipboard from 'react-copy-to-clipboard'; -import SyntaxHighlighter from 'react-syntax-highlighter'; - -import { Button } from 'ts/components/button'; -import { Container } from 'ts/components/ui/container'; -import { styled } from 'ts/style/theme'; -import { zIndex } from 'ts/style/z_index'; - -const CustomPre = styled.pre` - margin: 0px; - line-height: 24px; - overflow: scroll; - width: 100%; - height: 100%; - max-height: 800px; - border-radius: 4px; - code { - background-color: inherit !important; - border-radius: 0px; - font-family: 'Roboto Mono', sans-serif; - border: none; - } - code:first-of-type { - background-color: #060d0d !important; - color: #999; - min-height: 100%; - text-align: center; - margin-right: 15px; - line-height: 25px; - padding: 10px 7px !important; - } - code:last-of-type { - position: relative; - top: 10px; - top: 0; - padding-top: 11px; - display: inline-block; - line-height: 25px; - } -`; - -const customStyle = { - 'hljs-comment': { - color: '#7e7887', - }, - 'hljs-quote': { - color: '#7e7887', - }, - 'hljs-variable': { - color: '#be4678', - }, - 'hljs-template-variable': { - color: '#be4678', - }, - 'hljs-attribute': { - color: '#be4678', - }, - 'hljs-regexp': { - color: '#be4678', - }, - 'hljs-link': { - color: '#be4678', - }, - 'hljs-tag': { - color: '#61f5ff', - }, - 'hljs-name': { - color: '#61f5ff', - }, - 'hljs-selector-id': { - color: '#be4678', - }, - 'hljs-selector-class': { - color: '#be4678', - }, - 'hljs-number': { - color: '#c994ff', - }, - 'hljs-meta': { - color: '#61f5ff', - }, - 'hljs-built_in': { - color: '#aa573c', - }, - 'hljs-builtin-name': { - color: '#aa573c', - }, - 'hljs-literal': { - color: '#aa573c', - }, - 'hljs-type': { - color: '#aa573c', - }, - 'hljs-params': { - color: '#aa573c', - }, - 'hljs-string': { - color: '#bcff88', - }, - 'hljs-symbol': { - color: '#2a9292', - }, - 'hljs-bullet': { - color: '#2a9292', - }, - 'hljs-title': { - color: '#576ddb', - }, - 'hljs-section': { - color: '#576ddb', - }, - 'hljs-keyword': { - color: '#955ae7', - }, - 'hljs-selector-tag': { - color: '#955ae7', - }, - 'hljs-deletion': { - color: '#19171c', - display: 'inline-block', - width: '100%', - backgroundColor: '#be4678', - }, - 'hljs-addition': { - color: '#19171c', - display: 'inline-block', - width: '100%', - backgroundColor: '#2a9292', - }, - hljs: { - display: 'block', - overflowX: 'hidden', - background: '#1B2625', - color: 'white', - fontSize: '12px', - }, - 'hljs-emphasis': { - fontStyle: 'italic', - }, - 'hljs-strong': { - fontWeight: 'bold', - }, -}; - -export interface CodeDemoProps { - children: string; -} - -export interface CodeDemoState { - didCopyCode: boolean; -} - -export class CodeDemo extends React.Component<CodeDemoProps, CodeDemoState> { - public state: CodeDemoState = { - didCopyCode: false, - }; - public render(): React.ReactNode { - const copyButtonText = this.state.didCopyCode ? 'Copied!' : 'Copy'; - return ( - <Container position="relative" height="100%"> - <Container position="absolute" top="10px" right="10px" zIndex={zIndex.overlay - 1}> - <CopyToClipboard text={this.props.children} onCopy={this._handleCopyClick}> - <StyledButton>{copyButtonText}</StyledButton> - </CopyToClipboard> - </Container> - <SyntaxHighlighter language="html" style={customStyle} showLineNumbers={true} PreTag={CustomPre}> - {this.props.children} - </SyntaxHighlighter> - </Container> - ); - } - private readonly _handleCopyClick = () => { - this.setState({ didCopyCode: true }); - }; -} - -const StyledButton = styled(Button)` - border-radius: 4px; - font-size: 15px; - font-weight: 400; - padding: 9px 21px 7px; -`; diff --git a/packages/website/ts/pages/instant/config_generator.tsx b/packages/website/ts/pages/instant/config_generator.tsx deleted file mode 100644 index 29fce85db..000000000 --- a/packages/website/ts/pages/instant/config_generator.tsx +++ /dev/null @@ -1,329 +0,0 @@ -import { StandardRelayerAPIOrderProvider } from '@0x/asset-buyer'; -import { getContractAddressesForNetworkOrThrow } from '@0x/contract-addresses'; -import { assetDataUtils } from '@0x/order-utils'; -import { ObjectMap } from '@0x/types'; -import * as _ from 'lodash'; -import * as React from 'react'; -import styled from 'styled-components'; - -import { CheckMark } from 'ts/components/ui/check_mark'; -import { Container } from 'ts/components/ui/container'; -import { MultiSelect } from 'ts/components/ui/multi_select'; -import { Spinner } from 'ts/components/ui/spinner'; -import { Text } from 'ts/components/ui/text'; -import { ConfigGeneratorAddressInput } from 'ts/pages/instant/config_generator_address_input'; -import { FeePercentageSlider } from 'ts/pages/instant/fee_percentage_slider'; -import { colors } from 'ts/style/colors'; -import { WebsitePaths } from 'ts/types'; -import { constants } from 'ts/utils/constants'; - -// New components -import { Heading } from 'ts/components/text'; -import { Select, SelectItemConfig } from 'ts/pages/instant/select'; - -import { assetMetaDataMap } from '../../../../instant/src/data/asset_meta_data_map'; -import { ERC20AssetMetaData, ZeroExInstantBaseConfig } from '../../../../instant/src/types'; - -export interface ConfigGeneratorProps { - value: ZeroExInstantBaseConfig; - onConfigChange: (config: ZeroExInstantBaseConfig) => void; -} - -export interface ConfigGeneratorState { - isLoadingAvailableTokens: boolean; - // Address to token info - availableTokens?: ObjectMap<ERC20AssetMetaData>; -} - -const SRA_ENDPOINTS = ['https://api.radarrelay.com/0x/v2/', 'https://sra.bamboorelay.com/0x/v2/']; - -export class ConfigGenerator extends React.Component<ConfigGeneratorProps, ConfigGeneratorState> { - public state: ConfigGeneratorState = { - isLoadingAvailableTokens: true, - }; - public componentDidMount(): void { - // tslint:disable-next-line:no-floating-promises - this._setAvailableAssetsFromOrderProvider(); - } - public componentDidUpdate(prevProps: ConfigGeneratorProps): void { - if (prevProps.value.orderSource !== this.props.value.orderSource) { - // tslint:disable-next-line:no-floating-promises - this._setAvailableAssetsFromOrderProvider(); - const newConfig: ZeroExInstantBaseConfig = { - ...this.props.value, - availableAssetDatas: undefined, - }; - this.props.onConfigChange(newConfig); - } - } - public render(): React.ReactNode { - const { value } = this.props; - if (!_.isString(value.orderSource)) { - throw new Error('ConfigGenerator component only supports string values as an orderSource.'); - } - return ( - <Container minWidth="350px"> - <ConfigGeneratorSection title="Liquidity Source"> - <Select - shouldIncludeEmpty={false} - id="" - value={value.orderSource} - items={this._generateItems()} - onChange={this._handleSRASelection.bind(this)} - /> - </ConfigGeneratorSection> - <ConfigGeneratorSection {...this._getTokenSelectorProps()}> - {this._renderTokenMultiSelectOrSpinner()} - </ConfigGeneratorSection> - <ConfigGeneratorSection title="Transaction fee ETH address" marginBottom="10px" isOptional={true}> - <ConfigGeneratorAddressInput - value={value.affiliateInfo ? value.affiliateInfo.feeRecipient : ''} - onChange={this._handleAffiliateAddressChange} - /> - </ConfigGeneratorSection> - <ConfigGeneratorSection - title="Fee percentage" - actionText="Learn more" - onActionTextClick={this._handleAffiliatePercentageLearnMoreClick} - > - <FeePercentageSlider - value={value.affiliateInfo.feePercentage} - onChange={this._handleAffiliatePercentageChange} - isDisabled={ - _.isUndefined(value.affiliateInfo) || - _.isUndefined(value.affiliateInfo.feeRecipient) || - _.isEmpty(value.affiliateInfo.feeRecipient) - } - /> - </ConfigGeneratorSection> - </Container> - ); - } - private readonly _getTokenSelectorProps = (): ConfigGeneratorSectionProps => { - if (_.isEmpty(this.state.availableTokens)) { - return { - title: 'What tokens can users buy?', - }; - } - if (_.isUndefined(this.props.value.availableAssetDatas)) { - return { - title: 'What tokens can users buy?', - actionText: 'Unselect All', - onActionTextClick: this._handleUnselectAllClick, - }; - } - return { - title: 'What tokens can users buy?', - actionText: 'Select All', - onActionTextClick: this._handleSelectAllClick, - }; - }; - private readonly _generateItems = (): SelectItemConfig[] => { - return _.map(SRA_ENDPOINTS, endpoint => ({ - label: endpoint, - value: endpoint, - onClick: this._handleSRASelection.bind(this, endpoint), - })); - }; - private readonly _handleAffiliatePercentageLearnMoreClick = (): void => { - window.open(`${WebsitePaths.Wiki}#Learn-About-Affiliate-Fees`, '_blank'); - }; - private readonly _handleSRASelection = (event: React.ChangeEvent<HTMLSelectElement>) => { - const sraEndpoint = event.target.value; - const newConfig: ZeroExInstantBaseConfig = { - ...this.props.value, - orderSource: sraEndpoint, - }; - this.props.onConfigChange(newConfig); - }; - private readonly _handleAffiliateAddressChange = (address: string, isValid: boolean) => { - const oldConfig: ZeroExInstantBaseConfig = this.props.value; - const newConfig: ZeroExInstantBaseConfig = { - ...oldConfig, - affiliateInfo: { - feeRecipient: address, - feePercentage: oldConfig.affiliateInfo.feePercentage, - }, - }; - this.props.onConfigChange(newConfig); - }; - private readonly _handleAffiliatePercentageChange = (value: number) => { - const oldConfig: ZeroExInstantBaseConfig = this.props.value; - const newConfig: ZeroExInstantBaseConfig = { - ...oldConfig, - affiliateInfo: { - feeRecipient: oldConfig.affiliateInfo.feeRecipient, - feePercentage: value, - }, - }; - this.props.onConfigChange(newConfig); - }; - private readonly _handleSelectAllClick = () => { - const newConfig: ZeroExInstantBaseConfig = { - ...this.props.value, - availableAssetDatas: undefined, - }; - this.props.onConfigChange(newConfig); - }; - private readonly _handleUnselectAllClick = () => { - const newConfig: ZeroExInstantBaseConfig = { - ...this.props.value, - availableAssetDatas: [], - }; - this.props.onConfigChange(newConfig); - }; - private readonly _handleTokenClick = (assetData: string) => { - const { value } = this.props; - let newAvailableAssetDatas: string[] = []; - const allKnownAssetDatas = _.keys(this.state.availableTokens); - const availableAssetDatas = value.availableAssetDatas; - if (_.isUndefined(availableAssetDatas)) { - // It being undefined means it's all tokens. - newAvailableAssetDatas = _.pull(allKnownAssetDatas, assetData); - } else if (!_.includes(availableAssetDatas, assetData)) { - // Add it - newAvailableAssetDatas = [...availableAssetDatas, assetData]; - if (newAvailableAssetDatas.length === allKnownAssetDatas.length) { - // If all tokens are manually selected, just show none. - newAvailableAssetDatas = undefined; - } - } else { - // Remove it - newAvailableAssetDatas = _.pull(availableAssetDatas, assetData); - } - const newConfig: ZeroExInstantBaseConfig = { - ...this.props.value, - availableAssetDatas: newAvailableAssetDatas, - }; - this.props.onConfigChange(newConfig); - }; - private readonly _setAvailableAssetsFromOrderProvider = async (): Promise<void> => { - const { value } = this.props; - if (!_.isUndefined(value.orderSource) && _.isString(value.orderSource)) { - this.setState({ isLoadingAvailableTokens: true }); - const networkId = constants.NETWORK_ID_MAINNET; - const sraOrderProvider = new StandardRelayerAPIOrderProvider(value.orderSource, networkId); - const etherTokenAddress = getContractAddressesForNetworkOrThrow(networkId).etherToken; - const etherTokenAssetData = assetDataUtils.encodeERC20AssetData(etherTokenAddress); - const assetDatas = await sraOrderProvider.getAvailableMakerAssetDatasAsync(etherTokenAssetData); - const availableTokens = _.reduce( - assetDatas, - (acc, assetData) => { - const metaDataIfExists = assetMetaDataMap[assetData] as ERC20AssetMetaData; - if (metaDataIfExists) { - acc[assetData] = metaDataIfExists; - } - return acc; - }, - {} as ObjectMap<ERC20AssetMetaData>, - ); - this.setState({ availableTokens, isLoadingAvailableTokens: false }); - } - }; - private readonly _renderTokenMultiSelectOrSpinner = (): React.ReactNode => { - const { value } = this.props; - const { availableTokens, isLoadingAvailableTokens } = this.state; - const multiSelectHeight = '200px'; - if (isLoadingAvailableTokens) { - return ( - <Container - className="flex flex-column items-center justify-center" - height={multiSelectHeight} - backgroundColor={colors.white} - borderRadius="4px" - width="100%" - > - <Container position="relative" left="12px" marginBottom="20px"> - <Spinner /> - </Container> - <Text fontSize="16px">Loading...</Text> - </Container> - ); - } - const availableAssetDatas = _.keys(availableTokens); - if (availableAssetDatas.length === 0) { - return ( - <Container - className="flex flex-column items-center justify-center" - height={multiSelectHeight} - backgroundColor={colors.white} - borderRadius="4px" - width="100%" - > - <Text fontSize="16px">No tokens available. Try another endpoint?</Text> - </Container> - ); - } - const items = _.map(_.keys(availableTokens), assetData => { - const metaData = availableTokens[assetData]; - return { - value: assetData, - renderItemContent: (isSelected: boolean) => ( - <Container className="flex items-center"> - <Container marginRight="10px"> - <CheckMark isChecked={isSelected} color={colors.brandLight} /> - </Container> - <CheckboxText isSelected={isSelected}> - {metaData.symbol.toUpperCase()} — {metaData.name} - </CheckboxText> - </Container> - ), - onClick: this._handleTokenClick.bind(this, assetData), - }; - }); - return <MultiSelect items={items} selectedValues={value.availableAssetDatas} height={multiSelectHeight} />; - }; -} - -export interface ConfigGeneratorSectionProps { - title: string; - actionText?: string; - onActionTextClick?: () => void; - isOptional?: boolean; - marginBottom?: string; -} - -export const ConfigGeneratorSection: React.StatelessComponent<ConfigGeneratorSectionProps> = ({ - title, - actionText, - onActionTextClick, - isOptional, - marginBottom, - children, -}) => ( - <Container marginBottom={marginBottom}> - <Container marginBottom="10px" className="flex justify-between items-center"> - <Heading size="small" marginBottom="0" isFlex={true}> - <span>{title}</span> - {isOptional && <OptionalText> Optional</OptionalText>} - </Heading> - {actionText && <OptionalAction onClick={onActionTextClick}>{actionText}</OptionalAction>} - </Container> - {children} - </Container> -); - -ConfigGeneratorSection.defaultProps = { - marginBottom: '30px', -}; - -const OptionalText = styled.span` - display: inline; - font-size: 14px; - color: #999999; - flex-shrink: 0; -`; - -interface CheckboxTextProps { - isSelected?: boolean; -} - -const CheckboxText = styled.span<CheckboxTextProps>` - font-size: 14px; - line-height: 18px; - color: ${props => (props.isSelected ? colors.brandDark : '#666666')}; -`; - -const OptionalAction = styled(OptionalText)` - cursor: pointer; -`; diff --git a/packages/website/ts/pages/instant/config_generator_address_input.tsx b/packages/website/ts/pages/instant/config_generator_address_input.tsx deleted file mode 100644 index 890e39da6..000000000 --- a/packages/website/ts/pages/instant/config_generator_address_input.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { addressUtils } from '@0x/utils'; -import * as _ from 'lodash'; -import * as React from 'react'; -import styled from 'styled-components'; - -import { colors } from 'ts/style/colors'; - -import { Container } from 'ts/components/ui/container'; - -import { Paragraph } from 'ts/components/text'; - -export interface ConfigGeneratorAddressInputProps { - value?: string; - onChange?: (address: string, isValid: boolean) => void; -} - -export interface ConfigGeneratorAddressInputState { - errMsg: string; -} - -export interface InputProps { - className?: string; - value?: string; - width?: string; - fontSize?: string; - fontColor?: string; - padding?: string; - placeholderColor?: string; - placeholder?: string; - backgroundColor?: string; - onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; -} - -export class ConfigGeneratorAddressInput extends React.Component< - ConfigGeneratorAddressInputProps, - ConfigGeneratorAddressInputState -> { - public state = { - errMsg: '', - }; - public render(): React.ReactNode { - const { errMsg } = this.state; - const hasError = !_.isEmpty(errMsg); - return ( - <Container height="80px"> - <Input value={this.props.value} onChange={this._handleChange} placeholder="0xe99...aa8da4" /> - <Container marginTop="5px" isHidden={!hasError} height="25px"> - <Paragraph size="small" isNoMargin={true}> - {errMsg} - </Paragraph> - </Container> - </Container> - ); - } - - private readonly _handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => { - const address = event.target.value; - const isValidAddress = addressUtils.isAddress(address.toLowerCase()) || address === ''; - const errMsg = isValidAddress ? '' : 'Please enter a valid Ethereum address'; - this.setState({ - errMsg, - }); - this.props.onChange(address, isValidAddress); - }; -} - -const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => ( - <input className={className} value={value} onChange={onChange} placeholder={placeholder} /> -); - -export const Input = styled(PlainInput)` - background-color: ${colors.white}; - color: ${colors.textDarkSecondary}; - font-size: 1rem; - width: 100%; - padding: 16px 20px 18px; - border-radius: 4px; - border: 1px solid transparent; - outline: none; - &::placeholder { - color: #333333; - opacity: 0.5; - } -`; diff --git a/packages/website/ts/pages/instant/configurator.tsx b/packages/website/ts/pages/instant/configurator.tsx deleted file mode 100644 index a63e1752e..000000000 --- a/packages/website/ts/pages/instant/configurator.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import styled from 'styled-components'; - -import { CodeDemo } from 'ts/pages/instant/code_demo'; -import { ConfigGenerator } from 'ts/pages/instant/config_generator'; - -import { Link } from 'ts/components/link'; -import { Column, FlexWrap } from 'ts/components/newLayout'; -import { Heading } from 'ts/components/text'; -import { WebsitePaths } from 'ts/types'; - -import { ZeroExInstantBaseConfig } from '../../../../instant/src/types'; - -export interface ConfiguratorState { - instantConfig: ZeroExInstantBaseConfig; -} - -export class Configurator extends React.Component { - public state: ConfiguratorState = { - instantConfig: { - orderSource: 'https://api.radarrelay.com/0x/v2/', - availableAssetDatas: undefined, - affiliateInfo: { - feeRecipient: '', - feePercentage: 0, - }, - }, - }; - public render(): React.ReactNode { - const codeToDisplay = this._generateCodeDemoCode(); - return ( - <FlexWrap isFlex={true}> - <Column width="442px" padding="0 70px 0 0"> - <ConfigGenerator value={this.state.instantConfig} onConfigChange={this._handleConfigChange} /> - </Column> - <Column width="100%"> - <HeadingWrapper> - <Heading size="small" marginBottom="15px"> - Code Snippet - </Heading> - <Link href={`${WebsitePaths.Wiki}#Get-Started-With-Instant`} isBlock={true} target="_blank"> - Explore the Docs - </Link> - </HeadingWrapper> - <CodeDemo key={codeToDisplay}>{codeToDisplay}</CodeDemo> - </Column> - </FlexWrap> - ); - } - private readonly _handleConfigChange = (config: ZeroExInstantBaseConfig) => { - this.setState({ - instantConfig: config, - }); - }; - private readonly _generateCodeDemoCode = (): string => { - const { instantConfig } = this.state; - return `<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8" /> - <script src="https://instant.0x.org/instant.js"></script> - </head> - <body> - <script> - zeroExInstant.render({ - orderSource: '${instantConfig.orderSource}',${ - !_.isUndefined(instantConfig.affiliateInfo) && instantConfig.affiliateInfo.feeRecipient - ? `\n affiliateInfo: { - feeRecipient: '${instantConfig.affiliateInfo.feeRecipient.toLowerCase()}', - feePercentage: ${instantConfig.affiliateInfo.feePercentage} - },` - : '' - }${ - !_.isUndefined(instantConfig.availableAssetDatas) - ? `\n availableAssetDatas: ${this._renderAvailableAssetDatasString( - instantConfig.availableAssetDatas, - )}` - : '' - } - }, 'body'); - </script> - </body> - </html>`; - }; - private readonly _renderAvailableAssetDatasString = (availableAssetDatas: string[]): string => { - const stringAvailableAssetDatas = availableAssetDatas.map(assetData => `'${assetData}'`); - if (availableAssetDatas.length < 2) { - return `[${stringAvailableAssetDatas.join(', ')}]`; - } - return `[\n ${stringAvailableAssetDatas.join( - ', \n ', - )}\n ]`; - }; -} - -const HeadingWrapper = styled.div` - display: flex; - justify-content: space-between; - - a { - transform: translateY(-8px); - } -`; diff --git a/packages/website/ts/pages/instant/fee_percentage_slider.tsx b/packages/website/ts/pages/instant/fee_percentage_slider.tsx deleted file mode 100644 index c4d9f908f..000000000 --- a/packages/website/ts/pages/instant/fee_percentage_slider.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import Slider from 'rc-slider'; -import * as React from 'react'; -import styled from 'styled-components'; -import 'ts/pages/instant/rc-slider.css'; - -import { colors } from 'ts/style/colors'; - -const SliderWithTooltip = (Slider as any).createSliderWithTooltip(Slider); -// tslint:disable-next-line:no-unused-expression - -export interface FeePercentageSliderProps { - value: number; - isDisabled?: boolean; - onChange: (value: number) => void; -} - -export class FeePercentageSlider extends React.Component<FeePercentageSliderProps> { - public render(): React.ReactNode { - return ( - <StyledSlider - min={0} - max={0.05} - step={0.0025} - value={this.props.value} - disabled={this.props.isDisabled} - onChange={this.props.onChange} - tipFormatter={this._feePercentageSliderFormatter} - tipProps={{ placement: 'bottom', overlayStyle: { backgroundColor: '#fff', borderRadius: '4px' } }} - trackStyle={{ - backgroundColor: colors.brandLight, - }} - railStyle={{ - backgroundColor: 'rgba(255, 255, 255, 0.2)', - }} - handleStyle={{ - border: 'none', - boxShadow: 'none', - }} - activeDotStyle={{ - boxShadow: 'none', - border: 'none', - }} - /> - ); - } - private readonly _feePercentageSliderFormatter = (value: number): React.ReactNode => { - return <Text>{`${(value * 100).toFixed(2)}%`}</Text>; - }; -} - -const StyledSlider = styled(SliderWithTooltip)` - .rc-slider-tooltip__inner { - box-shadow: none !important; - background-color: ${colors.white} !important; - border-radius: 4px !important; - padding: 3px 12px !important; - height: auto !important; - position: relative; - top: 7px; - &:after { - border: solid transparent; - content: ' '; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - border-width: 6px; - bottom: 100%; - left: 100%; - border-bottom-color: ${colors.white}; - margin-left: -60%; - } - } -`; - -const Text = styled.span` - color: #000000; - font-size: 12px; - line-height: 18px; -`; diff --git a/packages/website/ts/pages/instant/rc-slider.css b/packages/website/ts/pages/instant/rc-slider.css deleted file mode 100644 index 63038324e..000000000 --- a/packages/website/ts/pages/instant/rc-slider.css +++ /dev/null @@ -1,295 +0,0 @@ -.rc-slider { - position: relative; - height: 14px; - padding: 5px 0; - width: 100%; - border-radius: 6px; - -ms-touch-action: none; - touch-action: none; - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.rc-slider * { - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.rc-slider-rail { - position: absolute; - width: 100%; - background-color: #e9e9e9; - height: 4px; - border-radius: 6px; -} - -.rc-slider-track { - position: absolute; - left: 0; - height: 4px; - border-radius: 6px; - background-color: #abe2fb; -} - -.rc-slider-handle { - position: absolute; - margin-left: -7px; - margin-top: -5px; - width: 14px; - height: 14px; - cursor: pointer; - cursor: -webkit-grab; - cursor: grab; - border-radius: 50%; - border: solid 2px #96dbfa; - background-color: #fff; - -ms-touch-action: pan-x; - touch-action: pan-x; -} - -.rc-slider-handle:focus { - border-color: #57c5f7; - box-shadow: 0 0 0 5px #96dbfa; - outline: none; -} - -.rc-slider-handle-click-focused:focus { - border-color: #96dbfa; - box-shadow: unset; -} - -.rc-slider-handle:hover { - border-color: #57c5f7; -} - -.rc-slider-handle:active { - border-color: #57c5f7; - box-shadow: 0 0 5px #57c5f7; - cursor: -webkit-grabbing; - cursor: grabbing; -} - -.rc-slider-mark { - position: absolute; - top: 18px; - left: 0; - width: 100%; - font-size: 12px; -} - -.rc-slider-mark-text { - position: absolute; - display: inline-block; - vertical-align: middle; - text-align: center; - cursor: pointer; - color: #999; -} - -.rc-slider-mark-text-active { - color: #666; -} - -.rc-slider-step { - position: absolute; - width: 100%; - height: 4px; - background: transparent; -} - -.rc-slider-dot { - position: absolute; - bottom: -2px; - margin-left: -4px; - width: 8px; - height: 8px; - border: 2px solid #e9e9e9; - background-color: #fff; - cursor: pointer; - border-radius: 50%; - vertical-align: middle; -} - -.rc-slider-dot-active { - border-color: #96dbfa; -} - -.rc-slider-disabled { - opacity: 0.2; -} - -.rc-slider-disabled .rc-slider-track { - background-color: #ccc; -} - -.rc-slider-disabled .rc-slider-handle, -.rc-slider-disabled .rc-slider-dot { - border-color: #ccc; - box-shadow: none; - background-color: #fff; - cursor: not-allowed; -} - -.rc-slider-disabled .rc-slider-mark-text, -.rc-slider-disabled .rc-slider-dot { - cursor: not-allowed !important; -} - -.rc-slider-vertical { - width: 14px; - height: 100%; - padding: 0 5px; -} - -.rc-slider-vertical .rc-slider-rail { - height: 100%; - width: 4px; -} - -.rc-slider-vertical .rc-slider-track { - left: 5px; - bottom: 0; - width: 4px; -} - -.rc-slider-vertical .rc-slider-handle { - margin-left: -5px; - margin-bottom: -7px; - -ms-touch-action: pan-y; - touch-action: pan-y; -} - -.rc-slider-vertical .rc-slider-mark { - top: 0; - left: 18px; - height: 100%; -} - -.rc-slider-vertical .rc-slider-step { - height: 100%; - width: 4px; -} - -.rc-slider-vertical .rc-slider-dot { - left: 2px; - margin-bottom: -4px; -} - -.rc-slider-vertical .rc-slider-dot:first-child { - margin-bottom: -4px; -} - -.rc-slider-vertical .rc-slider-dot:last-child { - margin-bottom: -4px; -} - -.rc-slider-tooltip-zoom-down-enter, -.rc-slider-tooltip-zoom-down-appear { - animation-duration: .3s; - animation-fill-mode: both; - display: block !important; - animation-play-state: paused; -} - -.rc-slider-tooltip-zoom-down-leave { - animation-duration: .3s; - animation-fill-mode: both; - display: block !important; - animation-play-state: paused; -} - -.rc-slider-tooltip-zoom-down-enter.rc-slider-tooltip-zoom-down-enter-active, -.rc-slider-tooltip-zoom-down-appear.rc-slider-tooltip-zoom-down-appear-active { - animation-name: rcSliderTooltipZoomDownIn; - animation-play-state: running; -} - -.rc-slider-tooltip-zoom-down-leave.rc-slider-tooltip-zoom-down-leave-active { - animation-name: rcSliderTooltipZoomDownOut; - animation-play-state: running; -} - -.rc-slider-tooltip-zoom-down-enter, -.rc-slider-tooltip-zoom-down-appear { - transform: scale(0, 0); - animation-timing-function: cubic-bezier(0.23, 1, 0.32, 1); -} - -.rc-slider-tooltip-zoom-down-leave { - animation-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); -} - -@keyframes rcSliderTooltipZoomDownIn { - 0% { - opacity: 0; - transform-origin: 50% 100%; - transform: scale(0, 0); - } - - 100% { - transform-origin: 50% 100%; - transform: scale(1, 1); - } -} - -@keyframes rcSliderTooltipZoomDownOut { - 0% { - transform-origin: 50% 100%; - transform: scale(1, 1); - } - - 100% { - opacity: 0; - transform-origin: 50% 100%; - transform: scale(0, 0); - } -} - -.rc-slider-tooltip { - position: absolute; - left: -9999px; - top: -9999px; - visibility: visible; - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.rc-slider-tooltip * { - box-sizing: border-box; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} - -.rc-slider-tooltip-hidden { - display: none; -} - -.rc-slider-tooltip-placement-top { - padding: 4px 0 8px 0; -} - -.rc-slider-tooltip-inner { - padding: 4px 6px 4px; - min-width: 24px; - height: 24px; - font-size: 12px; - line-height: 1; - color: #000; - text-align: center; - text-decoration: none; -} - -.rc-slider-tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} - -.rc-slider-tooltip-placement-top .rc-slider-tooltip-arrow { - bottom: 4px; - left: 50%; - margin-left: -4px; - border-width: 4px 4px 0; - border-top-color: #6c6c6c; -} diff --git a/packages/website/ts/pages/instant/select.tsx b/packages/website/ts/pages/instant/select.tsx deleted file mode 100644 index d4146cfb0..000000000 --- a/packages/website/ts/pages/instant/select.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import * as React from 'react'; -import styled from 'styled-components'; - -export interface SelectItemConfig { - label: string; - value?: string; - onClick?: () => void; -} - -interface SelectProps { - value?: string; - id: string; - items: SelectItemConfig[]; - emptyText?: string; - onChange?: (ev: React.ChangeEvent<HTMLSelectElement>) => void; - shouldIncludeEmpty: boolean; -} - -export const Select: React.FunctionComponent<SelectProps> = ({ - value, - id, - items, - shouldIncludeEmpty, - emptyText, - onChange, -}) => { - return ( - <Container> - <StyledSelect id={id} onChange={onChange}> - {shouldIncludeEmpty && <option value="">{emptyText}</option>} - {items.map((item, index) => ( - <option - key={`${id}-item-${index}`} - value={item.value} - selected={item.value === value} - onClick={item.onClick} - > - {item.label} - </option> - ))} - </StyledSelect> - <Caret width="12" height="7" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M11 1L6 6 1 1" stroke="#666" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" /> - </Caret> - </Container> - ); -}; - -Select.defaultProps = { - emptyText: 'Select...', - shouldIncludeEmpty: true, -}; - -const Container = styled.div` - background-color: #fff; - border-radius: 4px; - display: flex; - width: 100%; - position: relative; -`; - -const StyledSelect = styled.select` - appearance: none; - border: 0; - font-size: 1rem; - width: 100%; - padding: 20px 20px 20px 20px; -`; - -const Caret = styled.svg` - position: absolute; - right: 20px; - top: calc(50% - 4px); -`; diff --git a/packages/website/ts/pages/landing.tsx b/packages/website/ts/pages/landing.tsx deleted file mode 100644 index b47d34dce..000000000 --- a/packages/website/ts/pages/landing.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; - -import { SectionLandingAbout } from 'ts/components/sections/landing/about'; -import { SectionLandingClients } from 'ts/components/sections/landing/clients'; -import { SectionLandingCta } from 'ts/components/sections/landing/cta'; -import { SectionLandingHero } from 'ts/components/sections/landing/hero'; -import { SiteWrap } from 'ts/components/siteWrap'; - -import { ModalContact } from 'ts/components/modals/modal_contact'; - -interface Props { - theme: { - bgColor: string; - textColor: string; - linkColor: string; - }; -} - -export class NextLanding extends React.Component<Props> { - public state = { - isContactModalOpen: false, - }; - public render(): React.ReactNode { - return ( - <SiteWrap theme="dark"> - <DocumentTitle title="0x: The protocol for trading tokens on Ethereum" /> - <SectionLandingHero /> - <SectionLandingAbout /> - <SectionLandingClients /> - <SectionLandingCta onContactClick={this._onOpenContactModal} /> - <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} /> - </SiteWrap> - ); - } - - public _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - public _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; -} diff --git a/packages/website/ts/pages/launch_kit.tsx b/packages/website/ts/pages/launch_kit.tsx deleted file mode 100644 index dd4de4d99..000000000 --- a/packages/website/ts/pages/launch_kit.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; - -import { Hero } from 'ts/components/hero'; - -import { Banner } from 'ts/components/banner'; -import { Button } from 'ts/components/button'; -import { Definition } from 'ts/components/definition'; -import { Icon } from 'ts/components/icon'; -import { SiteWrap } from 'ts/components/siteWrap'; - -import { Section } from 'ts/components/newLayout'; -import { constants } from 'ts/utils/constants'; - -import { ModalContact } from '../components/modals/modal_contact'; - -const offersData = [ - { - icon: 'supportForAllEthereumStandards', - title: 'Perfect for developers who need a simple drop-in marketplace', - description: ( - <ul> - <li>Quickly launch a market for your project’s token</li> - <li>Seamlessly create an in-game marketplace for digital items and collectables</li> - <li>Easily build a 0x relayer for your local market</li> - </ul> - ), - }, -]; - -export class NextLaunchKit extends React.Component { - public state = { - isContactModalOpen: false, - }; - public render(): React.ReactNode { - return ( - <SiteWrap theme="dark"> - <DocumentTitle title="0x Launch Kit: Launch a relayer in under a minute" /> - <Hero - isLargeTitle={false} - isFullWidth={false} - title="0x Launch Kit" - description="Launch a relayer in under a minute" - figure={<Icon name="launchKit" size="hero" margin={['small', 0, 'small', 0]} />} - actions={<HeroActions />} - /> - - <Section bgColor="dark" isFlex={true} maxWidth="1170px"> - <Definition - title="Networked Liquidity Pool" - titleSize="small" - description="Tap into and share liquidity with other relayers" - icon="networkedLiquidity" - iconSize="medium" - isInline={true} - /> - - <Definition - title="Extensible Code Repo" - titleSize="small" - description="Fork and extend to support modes of exchange" - icon="code-repo" - iconSize="medium" - isInline={true} - /> - - <Definition - title="Exchange Ethereum based Tokens" - titleSize="small" - description="Enable trading for any ERC-20 or ERC-721 asset" - icon="eth-based-tokens" - iconSize="medium" - isInline={true} - /> - </Section> - - <Section> - {_.map(offersData, (item, index) => ( - <Definition - key={`offers-${index}`} - icon={item.icon} - title={item.title} - description={item.description} - isInlineIcon={true} - iconSize={240} - /> - ))} - </Section> - - <Banner - heading="Need more flexibility?" - subline="Dive into our docs, or contact us if needed" - mainCta={{ - text: 'Get Started', - href: `${constants.URL_LAUNCH_KIT}/#table-of-contents`, - shouldOpenInNewTab: true, - }} - secondaryCta={{ text: 'Get in Touch', onClick: this._onOpenContactModal.bind(this) }} - /> - <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} /> - </SiteWrap> - ); - } - - public _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - public _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; -} - -const HeroActions = () => ( - <React.Fragment> - <Button href={constants.URL_LAUNCH_KIT} isInline={true} target="_blank"> - Get Started - </Button> - - <Button href={constants.URL_LAUNCH_KIT_BLOG_POST} isTransparent={true} isInline={true} target="_blank"> - Learn More! - </Button> - </React.Fragment> -); diff --git a/packages/website/ts/pages/market_maker.tsx b/packages/website/ts/pages/market_maker.tsx deleted file mode 100644 index 854870358..000000000 --- a/packages/website/ts/pages/market_maker.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import * as _ from 'lodash'; -import { opacify } from 'polished'; -import * as React from 'react'; - -import { Banner } from 'ts/components/banner'; -import { Button } from 'ts/components/button'; -import { Action, Definition } from 'ts/components/definition'; -import { Hero } from 'ts/components/hero'; -import { ModalContact, ModalContactType } from 'ts/components/modals/modal_contact'; -import { Section } from 'ts/components/newLayout'; -import { SiteWrap } from 'ts/components/siteWrap'; -import { colors } from 'ts/style/colors'; -import { WebsitePaths } from 'ts/types'; - -interface OfferData { - icon: string; - title: string; - description: string; - links?: Action[]; -} -export interface NextMarketMakerProps {} - -export class NextMarketMaker extends React.Component<NextMarketMakerProps> { - public state = { - isContactModalOpen: false, - }; - - private readonly _offersData: OfferData[]; - - constructor(props: NextMarketMakerProps) { - super(props); - this._offersData = [ - { - icon: 'supportForAllEthereumStandards', - title: 'Comprehensive Tutorials', - description: - 'Stay on the bleeding edge of crypto by learning how to market make on decentralized exchanges. The network of 0x relayers provides market makers a first-mover advantage to capture larger spreads, find arbitrage opportunities, and trade on new types of exchanges like prediction markets and non-fungible token marketplaces.', - links: [ - { - label: 'Explore the Docs', - url: `${WebsitePaths.Wiki}#Market-Making-on-0x`, - }, - ], - }, - { - icon: 'generateRevenueForYourBusiness-large', - title: 'Market Making Compensation', - description: 'Accepted applicants can receive up to $15,000 for completing onboarding', - }, - { - icon: 'getInTouch', - title: 'Dedicated Support', - description: - 'The 0x team will provide 1:1 onboarding assistance and promptly answer all your questions. They will walk you through the tutorials so that you know how to read 0x order types, spin up an Ethereum node, and execute trades on the blockchain.', - links: [ - { - label: 'Contact Us', - onClick: this._onOpenContactModal, - shouldUseAnchorTag: true, - }, - ], - }, - ]; - } - - public render(): React.ReactNode { - return ( - <SiteWrap theme="light"> - <Hero - maxWidth="865px" - maxWidthHeading="715px" - isLargeTitle={false} - isFullWidth={false} - isCenteredMobile={false} - title="Bring liquidity to the markets of the future" - description="Market makers (MMs) are important stakeholders in the 0x ecosystem. The Market Making Program provides a set of resources that help onboard MMs to bring liquidity to the 0x network. The Program includes tutorials, monetary incentives, and 1:1 support from the 0x team." - actions={this._renderHeroActions()} - /> - - <Section bgColor="light" isFlex={true} maxWidth="1170px"> - <Definition - title="Secure Trading" - titleSize="small" - description="Take full custody of your assets to eliminate counterparty risk" - icon="secureTrading" - iconSize="medium" - isInline={true} - /> - - <Definition - title="Networked Liquidity Pool" - titleSize="small" - description="Use one pool of capital across multiple relayers to trade against a large group of takers" - icon="networkedLiquidity" - iconSize="medium" - isInline={true} - /> - - <Definition - title="Low Cost" - titleSize="small" - description="Pay no gas fees to make 0x orders" - icon="low-cost" - iconSize="medium" - isInline={true} - /> - </Section> - - <Section> - {_.map(this._offersData, (item, index) => ( - <Definition - key={`offers-${index}`} - icon={item.icon} - title={item.title} - description={item.description} - isInlineIcon={true} - iconSize={240} - fontSize="medium" - actions={item.links} - /> - ))} - </Section> - - <Banner - heading="Start trading today." - subline="Check out our Market Making tutorials to get started" - mainCta={{ text: 'Tutorials', href: `${WebsitePaths.Wiki}#Market-Making-on-0x` }} - secondaryCta={{ text: 'Apply Now', onClick: this._onOpenContactModal }} - /> - <ModalContact - isOpen={this.state.isContactModalOpen} - onDismiss={this._onDismissContactModal} - modalContactType={ModalContactType.MarketMaker} - /> - </SiteWrap> - ); - } - - private readonly _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - private readonly _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; - - private readonly _renderHeroActions = () => ( - <> - <Button href={`${WebsitePaths.Wiki}#Market-Making-on-0x`} bgColor="dark" isInline={true}> - Get Started - </Button> - <Button - onClick={this._onOpenContactModal} - borderColor={opacify(0.4)(colors.brandDark)} - isTransparent={true} - isInline={true} - > - Apply Now - </Button> - </> - ); -} diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx deleted file mode 100644 index 6abd8fc80..000000000 --- a/packages/website/ts/pages/not_found.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { Footer } from 'ts/components/old_footer'; -import { TopBar } from 'ts/components/top_bar/top_bar'; -import { FullscreenMessage } from 'ts/pages/fullscreen_message'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { Translate } from 'ts/utils/translate'; - -export interface NotFoundProps { - location: Location; - translate: Translate; - dispatcher: Dispatcher; -} - -export const NotFound = (props: NotFoundProps) => { - return ( - <div> - <TopBar blockchainIsLoaded={false} location={props.location} translate={props.translate} /> - <FullscreenMessage - headerText={'404 Not Found'} - bodyText={"Hm... looks like we couldn't find what you are looking for."} - /> - <Footer translate={props.translate} dispatcher={props.dispatcher} /> - </div> - ); -}; diff --git a/packages/website/ts/pages/why.tsx b/packages/website/ts/pages/why.tsx deleted file mode 100644 index 48888d10a..000000000 --- a/packages/website/ts/pages/why.tsx +++ /dev/null @@ -1,302 +0,0 @@ -import * as _ from 'lodash'; -import * as React from 'react'; -import DocumentTitle from 'react-document-title'; -import ScrollableAnchor, { configureAnchors } from 'react-scrollable-anchor'; -import styled from 'styled-components'; - -import { Banner } from 'ts/components/banner'; -import { Button } from 'ts/components/button'; -import { Definition } from 'ts/components/definition'; -import { Hero } from 'ts/components/hero'; -import { Column, Section, WrapSticky } from 'ts/components/newLayout'; -import { SiteWrap } from 'ts/components/siteWrap'; -import { Slide, Slider } from 'ts/components/slider/slider'; -import { Heading } from 'ts/components/text'; - -import { ModalContact } from '../components/modals/modal_contact'; - -const offersData = [ - { - icon: 'robustSmartContracts', - title: 'Robust Smart Contracts', - description: `0x Protocol's smart contracts have been put through two rounds of rigorous security audits.`, - }, - { - icon: 'extensibleArchitecture', - title: 'Extensible Architecture', - description: `0x's modular pipeline enables you to plug in your own smart contracts through an extensible API.`, - }, - { - icon: 'eficientDesign', - title: 'Efficient Design', - description: `0x’s off-chain order relay with on-chain settlement is a gas efficient approach to p2p exchange, reducing blockchain bloat.`, - }, -]; - -const functionalityData = [ - { - icon: 'secureTrading', - title: 'Secure Non-custodial Trading', - description: 'Enable tokens to be traded wallet-to-wallet with no deposits or withdrawals.', - }, - { - icon: 'flexibleOrders', - title: 'Flexible Order Types', - description: 'Choose to sell assets at a specific “buy it now” price or allow potential buyers to submit bids.', - }, - { - icon: 'buildBusiness', - title: 'Build a Business', - description: - 'Monetize your product by taking fees on each transaction and join a growing number of relayers in the 0x ecosystem.', - }, -]; - -const useCaseSlides = [ - { - icon: 'gamingAndCollectibles', - title: 'Games & Collectibles', - description: - 'Artists and game makers are tokenizing digital art and in-game items known as non-fungible tokens (NFTs). 0x enables these creators to add exchange functionality by providing the ability to build marketplaces for NFT trading.', - }, - { - icon: 'predictionMarkets', - title: 'Prediction Markets', - description: - 'Decentralized prediction markets and cryptodervivative platforms generate sets of tokens that represent a financial stake in the outcomes of events. 0x allows these tokens to be instantly tradable in liquid markets.', - }, - { - icon: 'orderBooks', - title: 'Order Books', - description: - 'There are thousands of decentralized apps and protocols that have native utility tokens. 0x provides professional exchanges with the ability to host order books and facilitates the exchange of these assets.', - }, - { - icon: 'decentralisedLoans', - title: 'Decentralized Loans', - description: - 'Efficient lending requires liquid markets where investors can buy and re-sell loans. 0x enables an ecosystem of lenders to self-organize and efficiently determine market prices for all outstanding loans.', - }, - { - icon: 'stableTokens', - title: 'Stable Tokens', - description: - 'Novel economic constructs such as stable coins require efficient, liquid markets to succeed. 0x will facilitate the underlying economic mechanisms that allow these tokens to remain stable.', - }, -]; - -configureAnchors({ offset: -60 }); - -export class NextWhy extends React.Component { - public state = { - isContactModalOpen: false, - }; - public render(): React.ReactNode { - const buildAction = ( - <Button href="/docs" isWithArrow={true} isAccentColor={true}> - Build on 0x - </Button> - ); - return ( - <SiteWrap theme="dark"> - <DocumentTitle title="Features & Benefits - 0x" /> - <Hero - title="The exchange layer for the crypto economy" - description="The world's assets are becoming tokenized on public blockchains. 0x Protocol is free, open-source infrastructure that developers and businesses utilize to build products that enable the purchasing and trading of crypto tokens." - actions={buildAction} - /> - - <Section bgColor="dark" isFlex={true} maxWidth="1170px"> - <Definition - title="Support for all Ethereum Standards" - titleSize="small" - description="0x Protocol facilitates the decentralized exchange of a growing number of Ethereum-based tokens, including all ERC-20 and ERC-721 assets." - icon="supportForAllEthereumStandards" - iconSize="large" - isInline={true} - /> - - <Definition - title="Networked Liquidity" - titleSize="small" - description="0x is lowering the barrier to entry by building a layer of networked liquidity that allows businesses to tap into a shared pool of digital assets." - icon="networkedLiquidity" - iconSize="large" - isInline={true} - /> - - <Definition - title="Flexible Integration" - titleSize="small" - description="0x is a modular system that enables businesses and projects, known as relayers, to easily add exchange functionality to any product experience." - icon="flexibleIntegration" - iconSize="large" - isInline={true} - /> - </Section> - - <Section maxWidth="1170px" isFlex={true} isFullWidth={true}> - <Column> - <NavStickyWrap offsetTop="130px"> - <ChapterLink href="#benefits">Benefits</ChapterLink> - <ChapterLink href="#cases">Use Cases</ChapterLink> - <ChapterLink href="#functionality">Features</ChapterLink> - </NavStickyWrap> - </Column> - - <Column width="55%" maxWidth="826px"> - <Column width="100%" maxWidth="560px" padding="0 30px 0 0"> - <ScrollableAnchor id="benefits"> - <SectionWrap> - <SectionTitle size="medium" marginBottom="60px" isNoBorder={true}> - What 0x offers - </SectionTitle> - - {_.map(offersData, (item, index) => ( - <Definition - key={`offers-${index}`} - icon={item.icon} - title={item.title} - titleSize="small" - description={item.description} - isWithMargin={true} - /> - ))} - </SectionWrap> - </ScrollableAnchor> - - <ScrollableAnchor id="cases"> - <SectionWrap isNotRelative={true}> - <SectionTitle size="medium" marginBottom="60px"> - Use Cases - </SectionTitle> - <Slider> - {_.map(useCaseSlides, (item, index) => ( - <Slide - key={`useCaseSlide-${index}`} - heading={item.title} - text={item.description} - icon={item.icon} - /> - ))} - </Slider> - </SectionWrap> - </ScrollableAnchor> - - <ScrollableAnchor id="functionality"> - <SectionWrap> - <SectionTitle size="medium" marginBottom="60px"> - Exchange Functionality - </SectionTitle> - - {_.map(functionalityData, (item, index) => ( - <Definition - key={`functionality-${index}`} - icon={item.icon} - title={item.title} - titleSize="small" - description={item.description} - isWithMargin={true} - /> - ))} - </SectionWrap> - </ScrollableAnchor> - </Column> - </Column> - </Section> - - <Banner - heading="Ready to get started?" - subline="Dive into our docs, or contact us if needed" - mainCta={{ text: 'Get Started', href: '/docs' }} - secondaryCta={{ text: 'Get in Touch', onClick: this._onOpenContactModal.bind(this) }} - /> - <ModalContact isOpen={this.state.isContactModalOpen} onDismiss={this._onDismissContactModal} /> - </SiteWrap> - ); - } - - public _onOpenContactModal = (): void => { - this.setState({ isContactModalOpen: true }); - }; - - public _onDismissContactModal = (): void => { - this.setState({ isContactModalOpen: false }); - }; -} - -interface SectionProps { - isNotRelative?: boolean; -} - -const SectionWrap = styled.div<SectionProps>` - position: ${props => !props.isNotRelative && 'relative'}; - - & + & { - padding-top: 60px; - margin-top: 60px; - } - - @media (min-width: 768px) { - & + &:before { - width: 100vw; - } - } - - @media (max-width: 768px) { - text-align: left; - - & + &:before { - width: 100%; - } - } -`; - -interface SectionTitleProps { - isNoBorder?: boolean; -} -const SectionTitle = styled(Heading)<SectionTitleProps>` - position: relative; - - ${props => - !props.isNoBorder && - ` - &:before { - content: ''; - width: 100vw; - position: absolute; - top: -53px; - left: 0; - height: 1px; - background-color: #3d3d3d; - } - `} - - @media (max-width: 768px) { - &:before { - width: calc(100vw - 60px); - } - } -`; - -const NavStickyWrap = styled(WrapSticky)` - padding-left: 60px; - z-index: 15; - - @media (max-width: 768px) { - display: none; - } -`; - -const ChapterLink = styled.a` - color: ${props => props.theme.textColor}; - font-size: 22px; - margin-bottom: 25px; - display: block; - opacity: 0.8; - - &:hover, - &:active { - opacity: 1; - } -`; diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx deleted file mode 100644 index c3c1600a5..000000000 --- a/packages/website/ts/pages/wiki/wiki.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import { - ALink, - colors, - constants as sharedConstants, - HeaderSizes, - Link, - MarkdownSection, - utils as sharedUtils, -} from '@0x/react-shared'; -import { ObjectMap } from '@0x/types'; -import * as _ from 'lodash'; -import CircularProgress from 'material-ui/CircularProgress'; -import * as React from 'react'; -import { SidebarHeader } from 'ts/components/documentation/sidebar_header'; -import { NestedSidebarMenu } from 'ts/components/nested_sidebar_menu'; -import { Button } from 'ts/components/ui/button'; -import { Container } from 'ts/components/ui/container'; -import { DevelopersPage } from 'ts/pages/documentation/developers_page'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { Article, ArticlesBySection, Deco, Key, ScreenWidths } from 'ts/types'; -import { backendClient } from 'ts/utils/backend_client'; -import { constants } from 'ts/utils/constants'; -import { Translate } from 'ts/utils/translate'; -import { utils } from 'ts/utils/utils'; - -const WIKI_NOT_READY_BACKOUT_TIMEOUT_MS = 5000; - -export interface WikiProps { - source: string; - location: Location; - dispatcher: Dispatcher; - translate: Translate; - screenWidth: ScreenWidths; -} - -interface WikiState { - articlesBySection: ArticlesBySection; - isHoveringSidebar: boolean; -} - -export class Wiki extends React.Component<WikiProps, WikiState> { - private _wikiBackoffTimeoutId: number; - private _isUnmounted: boolean; - constructor(props: WikiProps) { - super(props); - this._isUnmounted = false; - this.state = { - articlesBySection: undefined, - isHoveringSidebar: false, - }; - } - public componentWillMount(): void { - // tslint:disable-next-line:no-floating-promises - this._fetchArticlesBySectionAsync(); - } - public componentWillUnmount(): void { - this._isUnmounted = true; - clearTimeout(this._wikiBackoffTimeoutId); - } - public render(): React.ReactNode { - const sectionNameToLinks = _.isUndefined(this.state.articlesBySection) - ? {} - : this._getSectionNameToLinks(this.state.articlesBySection); - - const mainContent = _.isUndefined(this.state.articlesBySection) ? ( - <div className="flex justify-center">{this._renderLoading()}</div> - ) : ( - <div id="wiki" style={{ paddingRight: 2 }}> - {this._renderWikiArticles()} - </div> - ); - const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; - const sidebar = _.isUndefined(this.state.articlesBySection) ? ( - <div /> - ) : ( - <NestedSidebarMenu - sidebarHeader={isSmallScreen ? this._renderSidebarHeader() : undefined} - sectionNameToLinks={sectionNameToLinks} - screenWidth={this.props.screenWidth} - /> - ); - return ( - <DevelopersPage - sidebar={sidebar} - mainContent={mainContent} - location={this.props.location} - screenWidth={this.props.screenWidth} - translate={this.props.translate} - dispatcher={this.props.dispatcher} - /> - ); - } - private _renderSidebarHeader(): React.ReactNode { - const menuItems = _.map(constants.DEVELOPER_TOPBAR_LINKS, menuItemInfo => { - return ( - <Link - key={`menu-item-${menuItemInfo.title}`} - to={menuItemInfo.to} - shouldOpenInNewTab={menuItemInfo.shouldOpenInNewTab} - > - <Button - borderRadius="4px" - padding="0.4em 0.375em" - width="100%" - fontColor={colors.grey800} - fontSize="14px" - textAlign="left" - > - {this.props.translate.get(menuItemInfo.title as Key, Deco.Cap)} - </Button> - </Link> - ); - }); - const wikiTitle = this.props.translate.get(Key.Wiki, Deco.Cap); - return ( - <Container> - <SidebarHeader screenWidth={this.props.screenWidth} title={wikiTitle} /> - {menuItems} - </Container> - ); - } - private _renderLoading(): React.ReactNode { - return ( - <Container className="pt4"> - <Container className="center pb2"> - <CircularProgress size={40} thickness={5} /> - </Container> - <Container className="center pt2" paddingBottom="11px"> - Loading wiki... - </Container> - </Container> - ); - } - private _renderWikiArticles(): React.ReactNode { - const sectionNames = _.keys(this.state.articlesBySection); - const sections = _.map(sectionNames, sectionName => this._renderSection(sectionName)); - return sections; - } - private _renderSection(sectionName: string): React.ReactNode { - const articles = this.state.articlesBySection[sectionName]; - const renderedArticles = _.map(articles, (article: Article) => { - const githubLink = `${constants.URL_GITHUB_WIKI}/edit/master/${sectionName}/${article.fileName}`; - return ( - <div key={`markdown-section-${article.title}`}> - <MarkdownSection - sectionName={article.title} - markdownContent={article.content} - headerSize={HeaderSizes.H2} - githubLink={githubLink} - /> - </div> - ); - }); - return <div key={`section-${sectionName}`}>{renderedArticles}</div>; - } - private async _fetchArticlesBySectionAsync(): Promise<void> { - try { - const articlesBySection = await backendClient.getWikiArticlesBySectionAsync(); - if (!this._isUnmounted) { - this.setState( - { - articlesBySection, - }, - async () => { - await utils.onPageLoadPromise; - const hash = this.props.location.hash.slice(1); - sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID); - }, - ); - } - } catch (err) { - const errMsg = `${err}`; - if (_.includes(errMsg, `${constants.HTTP_NO_CONTENT_STATUS_CODE}`)) { - // We need to backoff and try fetching again later - this._wikiBackoffTimeoutId = window.setTimeout(() => { - // tslint:disable-next-line:no-floating-promises - this._fetchArticlesBySectionAsync(); - }, WIKI_NOT_READY_BACKOUT_TIMEOUT_MS); - return; - } - } - } - private _getSectionNameToLinks(articlesBySection: ArticlesBySection): ObjectMap<ALink[]> { - const sectionNames = _.keys(articlesBySection); - const sectionNameToLinks: ObjectMap<ALink[]> = {}; - for (const sectionName of sectionNames) { - const articles = articlesBySection[sectionName]; - const articleLinks = _.map(articles, article => { - return { - to: sharedUtils.getIdFromName(article.title), - title: article.title, - }; - }); - sectionNameToLinks[sectionName] = articleLinks; - } - return sectionNameToLinks; - } -} |