aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website/ts/components
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2017-12-20 06:36:37 +0800
committerGitHub <noreply@github.com>2017-12-20 06:36:37 +0800
commitd1c36f50d5849e70e16b785f5fff8f58435536d7 (patch)
tree713c69e926fefa4953fa80fa98bc903ba94f6da3 /packages/website/ts/components
parentc39ac903a972930d538f8fa3292c658201b1c5e5 (diff)
parent484312e677d1f1f1b280cdada92acddf5effd525 (diff)
downloaddexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar.gz
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar.bz2
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar.lz
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar.xz
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.tar.zst
dexon-sol-tools-d1c36f50d5849e70e16b785f5fff8f58435536d7.zip
Merge pull request #283 from 0xProject/createWethPage
Merge WETH page improvements into development
Diffstat (limited to 'packages/website/ts/components')
-rw-r--r--packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx16
-rw-r--r--packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx4
-rw-r--r--packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx38
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx106
-rw-r--r--packages/website/ts/components/portal.tsx50
-rw-r--r--packages/website/ts/components/send_button.tsx2
6 files changed, 171 insertions, 45 deletions
diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
index 44c23e4b0..700255163 100644
--- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
+++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
@@ -108,7 +108,16 @@ export class EthWethConversionDialog extends
className="pt1"
style={{fontSize: 12}}
>
- 1 ETH = 1 WETH
+ <div className="left">1 ETH = 1 WETH</div>
+ {this.props.direction === Side.Receive &&
+ <div
+ className="right"
+ onClick={this.onMaxClick.bind(this)}
+ style={{color: colors.darkBlue, textDecoration: 'underline', cursor: 'pointer'}}
+ >
+ Max
+ </div>
+ }
</div>
</div>
</div>
@@ -136,6 +145,11 @@ export class EthWethConversionDialog extends
</div>
);
}
+ private onMaxClick() {
+ this.setState({
+ value: this.props.tokenState.balance,
+ });
+ }
private onValueChange(isValid: boolean, amount?: BigNumber) {
this.setState({
value: amount,
diff --git a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
index 2f824ab44..ffe55794f 100644
--- a/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
+++ b/packages/website/ts/components/dialogs/portal_disclaimer_dialog.tsx
@@ -17,11 +17,11 @@ export function PortalDisclaimerDialog(props: PortalDisclaimerDialogProps) {
<FlatButton
key="portalAgree"
label="I Agree"
- onTouchTap={props.onToggleDialog.bind(this)}
+ onTouchTap={props.onToggleDialog}
/>,
]}
open={props.isOpen}
- onRequestClose={props.onToggleDialog.bind(this)}
+ onRequestClose={props.onToggleDialog}
autoScrollBodyContent={true}
modal={true}
>
diff --git a/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
new file mode 100644
index 000000000..3f485ce4f
--- /dev/null
+++ b/packages/website/ts/components/dialogs/wrapped_eth_section_notice_dialog.tsx
@@ -0,0 +1,38 @@
+import Dialog from 'material-ui/Dialog';
+import FlatButton from 'material-ui/FlatButton';
+import {colors} from 'material-ui/styles';
+import * as React from 'react';
+
+interface WrappedEthSectionNoticeDialogProps {
+ isOpen: boolean;
+ onToggleDialog: () => void;
+}
+
+export function WrappedEthSectionNoticeDialog(props: WrappedEthSectionNoticeDialogProps) {
+ return (
+ <Dialog
+ title="Dedicated Wrapped Ether Section"
+ titleStyle={{fontWeight: 100}}
+ actions={[
+ <FlatButton
+ key="acknowledgeWrapEthSection"
+ label="Sounds good"
+ onTouchTap={props.onToggleDialog}
+ />,
+ ]}
+ open={props.isOpen}
+ onRequestClose={props.onToggleDialog}
+ autoScrollBodyContent={true}
+ modal={true}
+ >
+ <div className="pt2" style={{color: colors.grey700}}>
+ <div>
+ We have recently updated the Wrapped Ether token (WETH) used by 0x Portal.
+ Don't worry, unwrapping Ether tied to the old Wrapped Ether token can
+ be done at any time by clicking on the "Wrap ETH" section in the menu
+ to the left.
+ </div>
+ </div>
+ </Dialog>
+ );
+}
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index 59353d18c..bdd4664e8 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -12,10 +12,12 @@ import {
} from 'material-ui/Table';
import * as moment from 'moment';
import * as React from 'react';
+import ReactTooltip = require('react-tooltip');
import {Blockchain} from 'ts/blockchain';
import {EthWethConversionButton} from 'ts/components/eth_weth_conversion_button';
import {Dispatcher} from 'ts/redux/dispatcher';
import {
+ EtherscanLinkSuffixes,
OutdatedWrappedEtherByNetworkId,
Side,
Token,
@@ -26,6 +28,7 @@ import {
import {colors} from 'ts/utils/colors';
import {configs} from 'ts/utils/configs';
import {constants} from 'ts/utils/constants';
+import {utils} from 'ts/utils/utils';
const PRECISION = 5;
const DATE_FORMAT = 'D/M/YY';
@@ -84,6 +87,10 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
const etherTokenState = this.props.tokenStateByAddress[etherToken.address];
const wethBalance = ZeroEx.toUnitAmount(etherTokenState.balance, constants.DECIMAL_PLACES_ETH);
const isBidirectional = true;
+ const etherscanUrl = utils.getEtherScanLinkIfExists(
+ etherToken.address, this.props.networkId, EtherscanLinkSuffixes.Address,
+ );
+ const tokenLabel = this.renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
return (
<div className="clearfix lg-px4 md-px4 sm-px2" style={{minHeight: 600}}>
<div className="relative">
@@ -91,7 +98,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<div className="absolute" style={{top: 0, right: 0}}>
<a
target="_blank"
- href="https://weth.io/"
+ href={constants.URL_WETH_IO}
style={{color: colors.grey}}
>
<div className="flex">
@@ -130,8 +137,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
src={ETHER_ICON_PATH}
/>
- <div className="mt2 ml2 sm-hide xs-hide">
- Ether
+ <div
+ className="ml2 sm-hide xs-hide"
+ style={{marginTop: 12}}
+ >
+ ETH
</div>
</div>
</TableRowColumn>
@@ -152,15 +162,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</TableRow>
<TableRow key="WETH">
<TableRowColumn className="py1">
- <div className="flex">
- <img
- style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
- src={configs.ICON_URL_BY_SYMBOL.WETH}
- />
- <div className="mt2 ml2 sm-hide xs-hide">
- Wrapped Ether
- </div>
- </div>
+ {this.renderTokenLink(tokenLabel, etherscanUrl)}
</TableRowColumn>
<TableRowColumn>
{wethBalance.toFixed(PRECISION)} WETH
@@ -243,8 +245,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
private renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState) {
const rows = _.map(configs.OUTDATED_WRAPPED_ETHERS,
(outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
- const outdatedWETH = outdatedWETHByNetworkId[this.props.networkId];
- const timestampMsRange = outdatedWETH.timestampMsRange;
+ const outdatedWETHIfExists = outdatedWETHByNetworkId[this.props.networkId];
+ if (_.isUndefined(outdatedWETHIfExists)) {
+ return null; // noop
+ }
+ const timestampMsRange = outdatedWETHIfExists.timestampMsRange;
let dateRange: string;
if (!_.isUndefined(timestampMsRange)) {
const startMoment = moment(timestampMsRange.startTimestampMs);
@@ -255,28 +260,26 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
}
const outdatedEtherToken = {
...etherToken,
- address: outdatedWETH.address,
+ address: outdatedWETHIfExists.address,
};
- const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETH.address];
- const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETH.address];
+ const isStateLoaded = this.state.outdatedWETHAddressToIsStateLoaded[outdatedWETHIfExists.address];
+ const outdatedEtherTokenState = this.state.outdatedWETHStateByAddress[outdatedWETHIfExists.address];
const balanceInEthIfExists = isStateLoaded ?
ZeroEx.toUnitAmount(
outdatedEtherTokenState.balance, constants.DECIMAL_PLACES_ETH,
).toFixed(PRECISION) :
undefined;
- const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(this, outdatedWETH.address);
+ const onConversionSuccessful = this.onOutdatedConversionSuccessfulAsync.bind(
+ this, outdatedWETHIfExists.address,
+ );
+ const etherscanUrl = utils.getEtherScanLinkIfExists(
+ outdatedWETHIfExists.address, this.props.networkId, EtherscanLinkSuffixes.Address,
+ );
+ const tokenLabel = this.renderToken(dateRange, outdatedEtherToken.address, OUTDATED_WETH_ICON_PATH);
return (
- <TableRow key={`weth-${outdatedWETH.address}`}>
+ <TableRow key={`weth-${outdatedWETHIfExists.address}`}>
<TableRowColumn className="py1">
- <div className="flex">
- <img
- style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
- src={OUTDATED_WETH_ICON_PATH}
- />
- <div className="mt2 ml2 sm-hide xs-hide">
- {dateRange}
- </div>
- </div>
+ {this.renderTokenLink(tokenLabel, etherscanUrl)}
</TableRowColumn>
<TableRowColumn>
{isStateLoaded ?
@@ -302,6 +305,41 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
});
return rows;
}
+ private renderTokenLink(tokenLabel: React.ReactNode, etherscanUrl: string) {
+ return (
+ <span>
+ {_.isUndefined(etherscanUrl) ?
+ tokenLabel :
+ <a href={etherscanUrl} target="_blank" style={{textDecoration: 'none'}}>
+ {tokenLabel}
+ </a>
+ }
+ </span>
+ );
+ }
+ private renderToken(name: string, address: string, imgPath: string) {
+ const tooltipId = `tooltip-${address}`;
+ return (
+ <div className="flex">
+ <img
+ style={{width: ICON_DIMENSION, height: ICON_DIMENSION}}
+ src={imgPath}
+ />
+ <div
+ className="ml2 sm-hide xs-hide"
+ style={{marginTop: 12}}
+ >
+ <span
+ data-tip={true}
+ data-for={tooltipId}
+ >
+ {name}
+ </span>
+ <ReactTooltip id={tooltipId}>{address}</ReactTooltip>
+ </div>
+ </div>
+ );
+ }
private async onOutdatedConversionSuccessfulAsync(outdatedWETHAddress: string) {
this.setState({
outdatedWETHAddressToIsStateLoaded: {
@@ -346,9 +384,15 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
});
}
private getOutdatedWETHAddresses(): string[] {
- const outdatedWETHAddresses = _.map(configs.OUTDATED_WRAPPED_ETHERS, outdatedWrappedEther => {
- return outdatedWrappedEther[this.props.networkId].address;
- });
+ const outdatedWETHAddresses = _.compact(_.map(configs.OUTDATED_WRAPPED_ETHERS,
+ outdatedWrappedEtherByNetwork => {
+ const outdatedWrappedEtherIfExists = outdatedWrappedEtherByNetwork[this.props.networkId];
+ if (_.isUndefined(outdatedWrappedEtherIfExists)) {
+ return undefined;
+ }
+ const address = outdatedWrappedEtherIfExists.address;
+ return address;
+ }));
return outdatedWETHAddresses;
}
} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/components/portal.tsx b/packages/website/ts/components/portal.tsx
index 2f6f9912a..939dae6f7 100644
--- a/packages/website/ts/components/portal.tsx
+++ b/packages/website/ts/components/portal.tsx
@@ -7,6 +7,7 @@ import {Route, Switch} from 'react-router-dom';
import {Blockchain} from 'ts/blockchain';
import {BlockchainErrDialog} from 'ts/components/dialogs/blockchain_err_dialog';
import {PortalDisclaimerDialog} from 'ts/components/dialogs/portal_disclaimer_dialog';
+import {WrappedEthSectionNoticeDialog} from 'ts/components/dialogs/wrapped_eth_section_notice_dialog';
import {EthWrappers} from 'ts/components/eth_wrappers';
import {FillOrder} from 'ts/components/fill_order';
import {Footer} from 'ts/components/footer';
@@ -63,22 +64,39 @@ interface PortalAllState {
prevNetworkId: number;
prevNodeVersion: string;
prevUserAddress: string;
- hasAcceptedDisclaimer: boolean;
+ prevPathname: string;
+ isDisclaimerDialogOpen: boolean;
+ isWethNoticeDialogOpen: boolean;
}
export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private blockchain: Blockchain;
private sharedOrderIfExists: Order;
private throttledScreenWidthUpdate: () => void;
+ public static hasAlreadyDismissedWethNotice() {
+ const didDismissWethNotice = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE);
+ const hasAlreadyDismissedWethNotice = !_.isUndefined(didDismissWethNotice) &&
+ !_.isEmpty(didDismissWethNotice);
+ return hasAlreadyDismissedWethNotice;
+ }
constructor(props: PortalAllProps) {
super(props);
this.sharedOrderIfExists = this.getSharedOrderIfExists();
this.throttledScreenWidthUpdate = _.throttle(this.updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+
+ const isViewingBalances = _.includes(props.location.pathname, `${WebsitePaths.Portal}/balances`);
+ const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
+
+ const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
+ const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
+ !_.isEmpty(didAcceptPortalDisclaimer);
this.state = {
prevNetworkId: this.props.networkId,
prevNodeVersion: this.props.nodeVersion,
prevUserAddress: this.props.userAddress,
- hasAcceptedDisclaimer: false,
+ prevPathname: this.props.location.pathname,
+ isDisclaimerDialogOpen: !hasAcceptedDisclaimer,
+ isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
};
}
public componentDidMount() {
@@ -87,12 +105,6 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
}
public componentWillMount() {
this.blockchain = new Blockchain(this.props.dispatcher);
- const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER);
- const hasAcceptedDisclaimer = !_.isUndefined(didAcceptPortalDisclaimer) &&
- !_.isEmpty(didAcceptPortalDisclaimer);
- this.setState({
- hasAcceptedDisclaimer,
- });
}
public componentWillUnmount() {
this.blockchain.destroy();
@@ -128,6 +140,14 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
// tslint:disable-next-line:no-floating-promises
this.blockchain.nodeVersionUpdatedFireAndForgetAsync(nextProps.nodeVersion);
}
+ if (nextProps.location.pathname !== this.state.prevPathname) {
+ const isViewingBalances = _.includes(nextProps.location.pathname, `${WebsitePaths.Portal}/balances`);
+ const hasAlreadyDismissedWethNotice = Portal.hasAlreadyDismissedWethNotice();
+ this.setState({
+ prevPathname: nextProps.location.pathname,
+ isWethNoticeDialogOpen: !hasAlreadyDismissedWethNotice && isViewingBalances,
+ });
+ }
}
public render() {
const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher
@@ -220,8 +240,12 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId}
/>
+ <WrappedEthSectionNoticeDialog
+ isOpen={this.state.isWethNoticeDialogOpen}
+ onToggleDialog={this.onWethNoticeAccepted.bind(this)}
+ />
<PortalDisclaimerDialog
- isOpen={!this.state.hasAcceptedDisclaimer}
+ isOpen={this.state.isDisclaimerDialogOpen}
onToggleDialog={this.onPortalDisclaimerAccepted.bind(this)}
/>
<FlashMessage
@@ -302,7 +326,13 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
private onPortalDisclaimerAccepted() {
localStorage.setItem(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER, 'set');
this.setState({
- hasAcceptedDisclaimer: true,
+ isDisclaimerDialogOpen: false,
+ });
+ }
+ private onWethNoticeAccepted() {
+ localStorage.setItem(constants.LOCAL_STORAGE_KEY_DISMISS_WETH_NOTICE, 'set');
+ this.setState({
+ isWethNoticeDialogOpen: false,
});
}
private getSharedOrderIfExists(): Order {
diff --git a/packages/website/ts/components/send_button.tsx b/packages/website/ts/components/send_button.tsx
index 1fc300964..23e61e77e 100644
--- a/packages/website/ts/components/send_button.tsx
+++ b/packages/website/ts/components/send_button.tsx
@@ -76,8 +76,8 @@ export class SendButton extends React.Component<SendButtonProps, SendButtonState
} else if (!_.includes(errMsg, 'User denied transaction')) {
utils.consoleLog(`Unexpected error encountered: ${err}`);
utils.consoleLog(err.stack);
- await errorReporter.reportAsync(err);
this.props.onError();
+ await errorReporter.reportAsync(err);
}
}
this.setState({