diff options
Diffstat (limited to 'packages/website')
7 files changed, 40 insertions, 224 deletions
diff --git a/packages/website/ts/components/inputs/allowance_state_toggle.tsx b/packages/website/ts/components/inputs/allowance_state_toggle.tsx index 495efd806..ce439e147 100644 --- a/packages/website/ts/components/inputs/allowance_state_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_state_toggle.tsx @@ -24,7 +24,7 @@ export interface AllowanceStateToggleProps { export interface AllowanceStateToggleState { allowanceState: AllowanceState; - prevAllowance: BigNumber; + prevTokenState: TokenState; } const DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); @@ -33,21 +33,21 @@ export class AllowanceStateToggle extends React.Component<AllowanceStateTogglePr public static defaultProps = { onErrorOccurred: _.noop.bind(_), }; - private static _getAllowanceStateFromAllowance(allowance?: BigNumber): AllowanceState { - if (_.isUndefined(allowance)) { + private static _getAllowanceState(tokenState: TokenState): AllowanceState { + if (!tokenState.isLoaded) { return AllowanceState.Loading; } - if (allowance.gt(0)) { + if (tokenState.allowance.gt(0)) { return AllowanceState.Unlocked; } return AllowanceState.Locked; } constructor(props: AllowanceStateToggleProps) { super(props); - const allowance = props.tokenState.allowance; + const tokenState = props.tokenState; this.state = { - allowanceState: AllowanceState.Loading, - prevAllowance: allowance, + allowanceState: AllowanceStateToggle._getAllowanceState(tokenState), + prevTokenState: tokenState, }; } @@ -69,11 +69,17 @@ export class AllowanceStateToggle extends React.Component<AllowanceStateTogglePr ); } public componentWillReceiveProps(nextProps: AllowanceStateToggleProps): void { - if (!nextProps.tokenState.allowance.eq(this.state.prevAllowance)) { - const allowance = nextProps.tokenState.allowance; + const nextTokenState = nextProps.tokenState; + const prevTokenState = this.state.prevTokenState; + if ( + !nextTokenState.allowance.eq(prevTokenState.allowance) || + nextTokenState.isLoaded !== prevTokenState.isLoaded + ) { + const tokenState = nextProps.tokenState; + const allowance = tokenState.allowance; this.setState({ - prevAllowance: allowance, - allowanceState: AllowanceStateToggle._getAllowanceStateFromAllowance(allowance), + prevTokenState: tokenState, + allowanceState: AllowanceStateToggle._getAllowanceState(nextTokenState), }); } } @@ -124,7 +130,7 @@ export class AllowanceStateToggle extends React.Component<AllowanceStateTogglePr } catch (err) { analytics.track('Set Allowance Failure', logData); this.setState({ - allowanceState: AllowanceStateToggle._getAllowanceStateFromAllowance(this.state.prevAllowance), + allowanceState: AllowanceStateToggle._getAllowanceState(this.state.prevTokenState), }); const errMsg = `${err}`; if (utils.didUserDenyWeb3Request(errMsg)) { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx deleted file mode 100644 index 05dce134a..000000000 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { Styles } from '@0xproject/react-shared'; -import { BigNumber, logUtils } from '@0xproject/utils'; -import * as _ from 'lodash'; -import Toggle from 'material-ui/Toggle'; -import * as React from 'react'; -import { Blockchain } from 'ts/blockchain'; -import { Dispatcher } from 'ts/redux/dispatcher'; -import { colors } from 'ts/style/colors'; -import { BalanceErrs, Token, TokenState } from 'ts/types'; -import { analytics } from 'ts/utils/analytics'; -import { errorReporter } from 'ts/utils/error_reporter'; -import { utils } from 'ts/utils/utils'; - -const DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS = new BigNumber(2).pow(256).minus(1); - -interface AllowanceToggleProps { - networkId: number; - blockchain: Blockchain; - dispatcher: Dispatcher; - token: Token; - tokenState: TokenState; - userAddress: string; - isDisabled?: boolean; - onErrorOccurred?: (errType: BalanceErrs) => void; - refetchTokenStateAsync: () => Promise<void>; -} - -interface AllowanceToggleState { - isSpinnerVisible: boolean; - prevAllowance: BigNumber; -} - -const styles: Styles = { - baseThumbStyle: { - height: 10, - width: 10, - top: 6, - backgroundColor: colors.white, - boxShadow: `0px 0px 0px ${colors.allowanceToggleShadow}`, - }, - offThumbStyle: { - left: 4, - }, - onThumbStyle: { - left: 25, - }, - baseTrackStyle: { - width: 25, - }, - offTrackStyle: { - backgroundColor: colors.grey300, - }, - onTrackStyle: { - backgroundColor: colors.mediumBlue, - }, -}; - -export class AllowanceToggle extends React.Component<AllowanceToggleProps, AllowanceToggleState> { - public static defaultProps = { - onErrorOccurred: _.noop.bind(_), - isDisabled: false, - }; - constructor(props: AllowanceToggleProps) { - super(props); - this.state = { - isSpinnerVisible: false, - prevAllowance: props.tokenState.allowance, - }; - } - public componentWillReceiveProps(nextProps: AllowanceToggleProps): void { - if (!nextProps.tokenState.allowance.eq(this.state.prevAllowance)) { - this.setState({ - isSpinnerVisible: false, - prevAllowance: nextProps.tokenState.allowance, - }); - } - } - public render(): React.ReactNode { - return ( - <div className="flex"> - <div> - <Toggle - disabled={this.state.isSpinnerVisible || this.props.isDisabled} - toggled={this._isAllowanceSet()} - onToggle={this._onToggleAllowanceAsync.bind(this)} - thumbStyle={{ ...styles.baseThumbStyle, ...styles.offThumbStyle }} - thumbSwitchedStyle={{ ...styles.baseThumbStyle, ...styles.onThumbStyle }} - trackStyle={{ ...styles.baseTrackStyle, ...styles.offTrackStyle }} - trackSwitchedStyle={{ ...styles.baseTrackStyle, ...styles.onTrackStyle }} - /> - </div> - {this.state.isSpinnerVisible && ( - <div className="pl1" style={{ paddingTop: 3 }}> - <i className="zmdi zmdi-spinner zmdi-hc-spin" /> - </div> - )} - </div> - ); - } - private async _onToggleAllowanceAsync(): Promise<void> { - if (this.props.userAddress === '') { - this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen(true); - return; - } - - this.setState({ - isSpinnerVisible: true, - }); - - let newAllowanceAmountInBaseUnits = new BigNumber(0); - if (!this._isAllowanceSet()) { - newAllowanceAmountInBaseUnits = DEFAULT_ALLOWANCE_AMOUNT_IN_BASE_UNITS; - } - const logData = { - tokenSymbol: this.props.token.symbol, - newAllowance: newAllowanceAmountInBaseUnits.toNumber(), - }; - try { - await this.props.blockchain.setProxyAllowanceAsync(this.props.token, newAllowanceAmountInBaseUnits); - analytics.track('Set Allowances Success', logData); - await this.props.refetchTokenStateAsync(); - } catch (err) { - analytics.track('Set Allowance Failure', logData); - this.setState({ - isSpinnerVisible: false, - }); - const errMsg = `${err}`; - if (utils.didUserDenyWeb3Request(errMsg)) { - return; - } - logUtils.log(`Unexpected error encountered: ${err}`); - logUtils.log(err.stack); - this.props.onErrorOccurred(BalanceErrs.allowanceSettingFailed); - errorReporter.report(err); - } - } - private _isAllowanceSet(): boolean { - return !this.props.tokenState.allowance.eq(0); - } -} diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index f395674a1..522687758 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -21,7 +21,7 @@ import { WrapEthOnboardingStep2, WrapEthOnboardingStep3, } from 'ts/components/onboarding/wrap_eth_onboarding_step'; -import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle'; +import { AllowanceStateToggle } from 'ts/containers/inputs/allowance_state_toggle'; import { BrowserType, ProviderType, ScreenWidths, Token, TokenByAddress, TokenStateByAddress } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { utils } from 'ts/utils/utils'; @@ -149,8 +149,8 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp title: 'Step 3: Unlock Tokens', content: ( <SetAllowancesOnboardingStep - zrxAllowanceToggle={this._renderZrxAllowanceToggle()} - ethAllowanceToggle={this._renderEthAllowanceToggle()} + zrxAllowanceToggle={this._renderZrxAllowanceStateToggle()} + ethAllowanceToggle={this._renderEthAllowanceStateToggle()} doesUserHaveAllowancesForWethAndZrx={this._doesUserHaveAllowancesForWethAndZrx()} /> ), @@ -243,15 +243,15 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp stepIndex: this.props.stepIndex, }); } - private _renderZrxAllowanceToggle(): React.ReactNode { + private _renderZrxAllowanceStateToggle(): React.ReactNode { const zrxToken = utils.getZrxToken(this.props.tokenByAddress); - return this._renderAllowanceToggle(zrxToken); + return this._renderAllowanceStateToggle(zrxToken); } - private _renderEthAllowanceToggle(): React.ReactNode { + private _renderEthAllowanceStateToggle(): React.ReactNode { const ethToken = utils.getEthToken(this.props.tokenByAddress); - return this._renderAllowanceToggle(ethToken); + return this._renderAllowanceStateToggle(ethToken); } - private _renderAllowanceToggle(token: Token): React.ReactNode { + private _renderAllowanceStateToggle(token: Token): React.ReactNode { if (!token) { return null; } @@ -260,10 +260,9 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp return null; } return ( - <AllowanceToggle + <AllowanceStateToggle token={token} tokenState={tokenStateIfExists} - isDisabled={!tokenStateIfExists.isLoaded} blockchain={this.props.blockchain} // tslint:disable-next-line:jsx-no-lambda refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(token.address)} diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index c8d80702b..cfade8f13 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -24,7 +24,7 @@ import { SendButton } from 'ts/components/send_button'; import { HelpTooltip } from 'ts/components/ui/help_tooltip'; import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button'; import { TokenIcon } from 'ts/components/ui/token_icon'; -import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle'; +import { AllowanceStateToggle } from 'ts/containers/inputs/allowance_state_toggle'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; import { @@ -361,12 +361,11 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala )} </TableRowColumn> <TableRowColumn> - <AllowanceToggle + <AllowanceStateToggle blockchain={this.props.blockchain} token={token} tokenState={tokenState} onErrorOccurred={this._onErrorOccurred.bind(this)} - isDisabled={!tokenState.isLoaded} refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this, token.address)} /> </TableRowColumn> diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 2cba993c4..02b403220 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -74,14 +74,14 @@ interface WalletState { isHoveringSidebar: boolean; } -interface AllowanceToggleConfig { +interface AllowanceStateToggleConfig { token: Token; tokenState: TokenState; } interface AccessoryItemConfig { wrappedEtherDirection?: Side; - allowanceToggleConfig?: AllowanceToggleConfig; + allowanceStateToggleConfig?: AllowanceStateToggleConfig; } const ETHER_ICON_PATH = '/images/ether.png'; @@ -89,7 +89,8 @@ const ICON_DIMENSION = 28; const BODY_ITEM_KEY = 'BODY'; const HEADER_ITEM_KEY = 'HEADER'; const ETHER_ITEM_KEY = 'ETHER'; -const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56; +const WRAP_ROW_ALLOWANCE_TOGGLE_WIDTH = 67; +const ALLOWANCE_TOGGLE_WIDTH = 56; const PLACEHOLDER_COLOR = colors.grey300; const LOADING_ROWS_COUNT = 6; @@ -338,7 +339,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { ); const accessoryItemConfig: AccessoryItemConfig = { wrappedEtherDirection, - allowanceToggleConfig: { + allowanceStateToggleConfig: { token, tokenState, }, @@ -393,12 +394,14 @@ export class Wallet extends React.Component<WalletProps, WalletState> { } private _renderAccessoryItems(config: AccessoryItemConfig): React.ReactElement<{}> { const shouldShowWrappedEtherAction = !_.isUndefined(config.wrappedEtherDirection); - const shouldShowToggle = !_.isUndefined(config.allowanceToggleConfig); + const shouldShowToggle = !_.isUndefined(config.allowanceStateToggleConfig); // if we don't have a toggle, we still want some space to the right of the "wrap" button so that it aligns with // the "unwrap" button in the row below + const isWrapEtherRow = shouldShowWrappedEtherAction && config.wrappedEtherDirection === Side.Deposit; + const width = isWrapEtherRow ? WRAP_ROW_ALLOWANCE_TOGGLE_WIDTH : ALLOWANCE_TOGGLE_WIDTH; const toggle = ( - <Container className="flex justify-center" width={NO_ALLOWANCE_TOGGLE_SPACE_WIDTH}> - {shouldShowToggle && this._renderAllowanceToggle(config.allowanceToggleConfig)} + <Container className="flex justify-center" width={width}> + {shouldShowToggle && this._renderAllowanceToggle(config.allowanceStateToggleConfig)} </Container> ); return ( @@ -410,17 +413,8 @@ export class Wallet extends React.Component<WalletProps, WalletState> { </div> ); } - private _renderAllowanceToggle(config: AllowanceToggleConfig): React.ReactNode { + private _renderAllowanceToggle(config: AllowanceStateToggleConfig): React.ReactNode { // TODO: Error handling - // return ( - // <AllowanceToggle - // blockchain={this.props.blockchain} - // token={config.token} - // tokenState={config.tokenState} - // isDisabled={!config.tokenState.isLoaded} - // refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(config.token.address)} - // /> - // ); return ( <AllowanceStateToggle blockchain={this.props.blockchain} diff --git a/packages/website/ts/containers/inputs/allowance_state_toggle.ts b/packages/website/ts/containers/inputs/allowance_state_toggle.ts index d6ff11f84..2a099b557 100644 --- a/packages/website/ts/containers/inputs/allowance_state_toggle.ts +++ b/packages/website/ts/containers/inputs/allowance_state_toggle.ts @@ -13,7 +13,6 @@ interface AllowanceStateToggleProps { onErrorOccurred?: (errType: BalanceErrs) => void; token: Token; tokenState: TokenState; - isDisabled?: boolean; refetchTokenStateAsync: () => Promise<void>; } diff --git a/packages/website/ts/containers/inputs/allowance_toggle.ts b/packages/website/ts/containers/inputs/allowance_toggle.ts deleted file mode 100644 index 545708f92..000000000 --- a/packages/website/ts/containers/inputs/allowance_toggle.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as React from 'react'; -import { connect } from 'react-redux'; -import { Dispatch } from 'redux'; -import { Blockchain } from 'ts/blockchain'; -import { State } from 'ts/redux/reducer'; -import { BalanceErrs, Token, TokenState } from 'ts/types'; - -import { AllowanceToggle as AllowanceToggleComponent } from 'ts/components/inputs/allowance_toggle'; -import { Dispatcher } from 'ts/redux/dispatcher'; - -interface AllowanceToggleProps { - blockchain: Blockchain; - onErrorOccurred?: (errType: BalanceErrs) => void; - token: Token; - tokenState: TokenState; - isDisabled?: boolean; - refetchTokenStateAsync: () => Promise<void>; -} - -interface ConnectedState { - networkId: number; - userAddress: string; -} - -interface ConnectedDispatch { - dispatcher: Dispatcher; -} - -const mapStateToProps = (state: State, _ownProps: AllowanceToggleProps): ConnectedState => ({ - networkId: state.networkId, - userAddress: state.userAddress, -}); - -const mapDispatchTopProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({ - dispatcher: new Dispatcher(dispatch), -}); - -export const AllowanceToggle: React.ComponentClass<AllowanceToggleProps> = connect( - mapStateToProps, - mapDispatchTopProps, -)(AllowanceToggleComponent); |