diff options
Diffstat (limited to 'packages/website/ts')
7 files changed, 121 insertions, 47 deletions
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 524587358..4066babaf 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -2,7 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Placement, Popper, PopperChildrenProps } from 'react-popper'; -import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; +import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { Container } from 'ts/components/ui/container'; import { Overlay } from 'ts/components/ui/overlay'; import { zIndex } from 'ts/utils/style'; @@ -13,6 +13,8 @@ export interface Step { content: React.ReactNode; placement?: Placement; hideBackButton?: boolean; + hideNextButton?: boolean; + continueButtonDisplay?: ContinueButtonDisplay; } export interface OnboardingFlowProps { @@ -60,9 +62,11 @@ export class OnboardingFlow extends React.Component<OnboardingFlowProps> { content={step.content} isLastStep={isLastStep} hideBackButton={step.hideBackButton} + hideNextButton={step.hideNextButton} onClose={this.props.onClose} onClickNext={this._goToNextStep.bind(this)} onClickBack={this._goToPrevStep.bind(this)} + continueButtonDisplay={step.continueButtonDisplay} /> </Container> ); diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 41925a672..eb34a87f2 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -4,6 +4,8 @@ import { colors } from '@0xproject/react-shared'; import { Container } from 'ts/components/ui/container'; import { Island } from 'ts/components/ui/island'; +export type ContinueButtonDisplay = 'enabled' | 'disabled'; + export interface OnboardingTooltipProps { title?: string; content: React.ReactNode; @@ -11,19 +13,44 @@ export interface OnboardingTooltipProps { onClose: () => void; onClickNext: () => void; onClickBack: () => void; + continueButtonDisplay?: ContinueButtonDisplay; hideBackButton?: boolean; + hideNextButton?: boolean; +} + +// TODO: Make this more general button. +export interface ContinueButtonProps { + display: ContinueButtonDisplay; + children?: string; + onClick: () => void; } +export const ContinueButton: React.StatelessComponent<ContinueButtonProps> = (props: ContinueButtonProps) => { + const isDisabled = props.display === 'disabled'; + return ( + <button disabled={isDisabled} onClick={isDisabled ? undefined : props.onClick}> + {props.children} + </button> + ); +}; + export const OnboardingTooltip: React.StatelessComponent<OnboardingTooltipProps> = (props: OnboardingTooltipProps) => ( <Island> <Container paddingRight="30px" paddingLeft="30px" maxWidth={350} paddingTop="15px" paddingBottom="15px"> <div className="flex flex-column"> {props.title} {props.content} + {props.continueButtonDisplay && ( + <ContinueButton onClick={props.onClickNext} display={props.continueButtonDisplay}> + Continue + </ContinueButton> + )} {!props.hideBackButton && <button onClick={props.onClickBack}>Back</button>} - <button onClick={props.onClickNext}>Skip</button> + {!props.hideNextButton && <button onClick={props.onClickNext}>Skip</button>} <button onClick={props.onClose}>Close</button> </div> </Container> </Island> ); + +OnboardingTooltip.displayName = 'OnboardingTooltip'; diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 8bcb4c749..edaeb3736 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -1,49 +1,25 @@ import * as _ from 'lodash'; import * as React from 'react'; -import { black } from 'material-ui/styles/colors'; +import { BigNumber } from '@0xproject/utils'; import { OnboardingFlow, Step } from 'ts/components/onboarding/onboarding_flow'; -import { ProviderType } from 'ts/types'; +import { ProviderType, TokenByAddress } from 'ts/types'; import { utils } from 'ts/utils/utils'; export interface PortalOnboardingFlowProps { stepIndex: number; isRunning: boolean; userAddress: string; + hasBeenSeen: boolean; providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - hasBeenSeen: boolean; + userEthBalanceInWei: BigNumber; + tokenByAddress: TokenByAddress; updateIsRunning: (isRunning: boolean) => void; updateOnboardingStep: (stepIndex: number) => void; } -const steps: Step[] = [ - { - target: '.wallet', - content: - 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', - placement: 'right', - }, - { - target: '.wallet', - content: 'Unlock your metamask extension to begin', - placement: 'right', - }, - { - target: '.wallet', - content: - 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', - placement: 'right', - hideBackButton: true, - }, - { - target: '.wallet', - content: 'Before you begin you will need to send some ETH to your metamask wallet', - placement: 'right', - }, -]; - export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowProps> { public componentDidMount(): void { this._overrideOnboardingStateIfShould(); @@ -54,7 +30,7 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr public render(): React.ReactNode { return ( <OnboardingFlow - steps={steps} + steps={this._getSteps()} stepIndex={this.props.stepIndex} isRunning={this.props.isRunning} onClose={this.props.updateIsRunning.bind(this, false)} @@ -63,10 +39,60 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr ); } + private _getSteps(): Step[] { + const steps: Step[] = [ + { + target: '.wallet', + content: + 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', + placement: 'right', + hideBackButton: true, + hideNextButton: true, + }, + { + target: '.wallet', + content: 'Unlock your metamask extension to begin', + placement: 'right', + hideBackButton: true, + hideNextButton: true, + }, + { + target: '.wallet', + content: + 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', + placement: 'right', + hideBackButton: true, + continueButtonDisplay: 'enabled', + }, + { + target: '.eth-row', + content: 'Before you begin you will need to send some ETH to your metamask wallet', + placement: 'right', + continueButtonDisplay: this._userHasEth() ? 'enabled' : 'disabled', + }, + { + target: '.weth-row', + content: 'You need to convert some of your ETH into tradeable Wrapped ETH (WETH)', + placement: 'right', + continueButtonDisplay: this._userHasWeth() ? 'enabled' : 'disabled', + }, + ]; + return steps; + } + private _isAddressAvailable(): boolean { return !_.isEmpty(this.props.userAddress); } + private _userHasEth(): boolean { + return this.props.userEthBalanceInWei > new BigNumber(0); + } + + private _userHasWeth(): boolean { + // TODO: https://app.asana.com/0/681385331277907/690722374136933 + return false; + } + private _overrideOnboardingStateIfShould(): void { this._autoStartOnboardingIfShould(); this._adjustStepIfShould(); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 524dc1952..d72c5458f 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -131,9 +131,6 @@ const styles: Styles = { }; const ETHER_ICON_PATH = '/images/ether.png'; -const ETHER_TOKEN_SYMBOL = 'WETH'; -const ZRX_TOKEN_SYMBOL = 'ZRX'; -const ETHER_SYMBOL = 'ETH'; const ICON_DIMENSION = 24; const TOKEN_AMOUNT_DISPLAY_PRECISION = 3; const BODY_ITEM_KEY = 'BODY'; @@ -319,7 +316,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const primaryText = this._renderAmount( this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH, - ETHER_SYMBOL, + constants.ETHER_SYMBOL, ); const etherToken = this._getEthToken(); const etherPrice = this.state.trackedTokenStateByAddress[etherToken.address].price; @@ -338,13 +335,13 @@ export class Wallet extends React.Component<WalletProps, WalletState> { ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; const key = ETHER_ITEM_KEY; - return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); + return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig, 'eth-row'); } private _renderTokenRows(): React.ReactNode { const trackedTokens = this.props.trackedTokens; const trackedTokensStartingWithEtherToken = trackedTokens.sort( - firstBy((t: Token) => t.symbol !== ETHER_TOKEN_SYMBOL) - .thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL) + firstBy((t: Token) => t.symbol !== constants.ETHER_TOKEN_SYMBOL) + .thenBy((t: Token) => t.symbol !== constants.ZRX_TOKEN_SYMBOL) .thenBy('address'), ); return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this)); @@ -359,7 +356,8 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const icon = <TokenIcon token={token} diameter={ICON_DIMENSION} link={tokenLink} />; const primaryText = this._renderAmount(tokenState.balance, token.decimals, token.symbol); const secondaryText = this._renderValue(tokenState.balance, token.decimals, tokenState.price); - const wrappedEtherDirection = token.symbol === ETHER_TOKEN_SYMBOL ? Side.Receive : undefined; + const isWeth = token.symbol === constants.ETHER_TOKEN_SYMBOL; + const wrappedEtherDirection = isWeth ? Side.Receive : undefined; const accessoryItemConfig: AccessoryItemConfig = { wrappedEtherDirection, allowanceToggleConfig: { @@ -368,7 +366,14 @@ export class Wallet extends React.Component<WalletProps, WalletState> { }, }; const key = token.address; - return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); + return this._renderBalanceRow( + key, + icon, + primaryText, + secondaryText, + accessoryItemConfig, + isWeth ? 'weth-row' : undefined, + ); } private _renderBalanceRow( key: string, @@ -376,6 +381,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { primaryText: React.ReactNode, secondaryText: React.ReactNode, accessoryItemConfig: AccessoryItemConfig, + className?: string, ): React.ReactNode { const shouldShowWrapEtherItem = !_.isUndefined(this.state.wrappedEtherDirection) && @@ -385,7 +391,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; const etherToken = this._getEthToken(); return ( - <div key={key} className="flex flex-column"> + <div key={key} className={`flex flex-column ${className || ''}`}> <div className="flex items-center" style={style}> <div className="px2">{icon}</div> <div className="flex-none pr2 pt2 pb2"> @@ -575,8 +581,6 @@ export class Wallet extends React.Component<WalletProps, WalletState> { }); } private _getEthToken(): Token { - const tokens = _.values(this.props.tokenByAddress); - const etherToken = _.find(tokens, { symbol: ETHER_TOKEN_SYMBOL }); - return etherToken; + return utils.getEthToken(this.props.tokenByAddress); } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts index 56a1db553..84739192f 100644 --- a/packages/website/ts/containers/portal_onboarding_flow.ts +++ b/packages/website/ts/containers/portal_onboarding_flow.ts @@ -1,7 +1,8 @@ +import { BigNumber } from '@0xproject/utils'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionTypes, ProviderType } from 'ts/types'; +import { ActionTypes, ProviderType, TokenByAddress } from 'ts/types'; import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow'; import { State } from 'ts/redux/reducer'; @@ -12,10 +13,12 @@ interface ConnectedState { stepIndex: number; isRunning: boolean; userAddress: string; + hasBeenSeen: boolean; providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - hasBeenSeen: boolean; + userEthBalanceInWei: BigNumber; + tokenByAddress: TokenByAddress; } interface ConnectedDispatch { @@ -30,6 +33,8 @@ const mapStateToProps = (state: State): ConnectedState => ({ providerType: state.providerType, injectedProviderName: state.injectedProviderName, blockchainIsLoaded: state.blockchainIsLoaded, + userEthBalanceInWei: state.userEtherBalanceInWei, + tokenByAddress: state.tokenByAddress, hasBeenSeen: state.hasPortalOnboardingBeenSeen, }); diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index f8710b349..9dc1d492c 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -4,6 +4,9 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { DECIMAL_PLACES_ETH: 18, DECIMAL_PLACES_ZRX: 18, + ETHER_TOKEN_SYMBOL: 'WETH', + ZRX_TOKEN_SYMBOL: 'ZRX', + ETHER_SYMBOL: 'ETH', GENESIS_ORDER_BLOCK_BY_NETWORK_ID: { 1: 4145578, 42: 3117574, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index c0d055070..b9d962b75 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -321,4 +321,9 @@ export const utils = { shouldShowPortalV2(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); }, + getEthToken(tokenByAddress: TokenByAddress): Token { + const tokens = _.values(tokenByAddress); + const etherToken = _.find(tokens, { symbol: constants.ETHER_TOKEN_SYMBOL }); + return etherToken; + }, }; |