diff options
Diffstat (limited to 'packages/website/ts/components')
12 files changed, 124 insertions, 133 deletions
diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx index b968a3147..c8e10303f 100644 --- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx +++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx @@ -4,7 +4,6 @@ import FlatButton from 'material-ui/FlatButton'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { BlockchainErrs } from 'ts/types'; -import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; interface BlockchainErrDialogProps { @@ -125,8 +124,7 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp Parity Signer Chrome extension </a>{' '} lets you connect to a locally running Parity node. Make sure you have started your local Parity node - with {configs.IS_MAINNET_ENABLED && '`parity ui` or'} `parity --chain kovan ui` in order to connect - to {configs.IS_MAINNET_ENABLED ? 'mainnet or Kovan respectively.' : 'Kovan.'} + with `parity ui` or `parity --chain kovan ui` in order to connect to mainnet or Kovan respectively. </div> <div className="pt2"> <span className="bold">Note:</span> If you have done one of the above steps and are still seeing @@ -142,10 +140,8 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp <div> The 0x smart contracts are not deployed on the Ethereum network you are currently connected to (network Id: {this.props.networkId}). In order to use the 0x portal dApp, please connect to the{' '} - {Networks.Kovan} testnet (network Id: {constants.NETWORK_ID_KOVAN}) - {configs.IS_MAINNET_ENABLED - ? ` or ${constants.MAINNET_NAME} (network Id: ${constants.NETWORK_ID_MAINNET}).` - : `.`} + {Networks.Kovan} testnet (network Id: {constants.NETWORK_ID_KOVAN}) or ${constants.MAINNET_NAME}{' '} + (network Id: ${constants.NETWORK_ID_MAINNET}). </div> <h4>Metamask</h4> <div> @@ -159,11 +155,8 @@ export class BlockchainErrDialog extends React.Component<BlockchainErrDialogProp If using the{' '} <a href={constants.URL_PARITY_CHROME_STORE} target="_blank"> Parity Signer Chrome extension - </a>, make sure to start your local Parity node with{' '} - {configs.IS_MAINNET_ENABLED - ? '`parity ui` or `parity --chain Kovan ui` in order to connect to mainnet \ - or Kovan respectively.' - : '`parity --chain kovan ui` in order to connect to Kovan.'} + </a>, make sure to start your local Parity node with `parity ui` or `parity --chain Kovan ui` in + order to connect to mainnet \ or Kovan respectively. </div> </div> ); diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx index c9727b553..38e4732a4 100644 --- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx +++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx @@ -282,6 +282,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps, if (didSucceed) { this.setState({ stepIndex: LedgerSteps.SELECT_ADDRESS, + connectionErrMsg: '', }); } return didSucceed; diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx index f6594b9d5..3751ce06f 100644 --- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx +++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx @@ -1,5 +1,6 @@ import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; +import * as moment from 'moment'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { TrackTokenConfirmation } from 'ts/components/track_token_confirmation'; @@ -73,12 +74,13 @@ export class TrackTokenConfirmationDialog extends React.Component< this.setState({ isAddingTokenToTracked: true, }); + const currentTimestamp = moment().unix(); for (const token of this.props.tokens) { const newTokenEntry = { ...token, + trackedTimestamp: currentTimestamp, }; - newTokenEntry.isTracked = true; trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); this.props.dispatcher.updateTokenByAddress([newTokenEntry]); } diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx index f3ea44286..03ba1183d 100644 --- a/packages/website/ts/components/fill_order.tsx +++ b/packages/website/ts/components/fill_order.tsx @@ -373,26 +373,26 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> { const tokensToTrack: Token[] = []; const isUnseenMakerToken = _.isUndefined(makerTokenIfExists); - const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && makerTokenIfExists.isTracked; + const isMakerTokenTracked = !_.isUndefined(makerTokenIfExists) && utils.isTokenTracked(makerTokenIfExists); if (isUnseenMakerToken) { tokensToTrack.push({ ...this.state.parsedOrder.metadata.makerToken, address: this.state.parsedOrder.signedOrder.makerTokenAddress, iconUrl: undefined, - isTracked: false, + trackedTimestamp: undefined, isRegistered: false, }); } else if (!isMakerTokenTracked) { tokensToTrack.push(makerTokenIfExists); } const isUnseenTakerToken = _.isUndefined(takerTokenIfExists); - const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && takerTokenIfExists.isTracked; + const isTakerTokenTracked = !_.isUndefined(takerTokenIfExists) && utils.isTokenTracked(takerTokenIfExists); if (isUnseenTakerToken) { tokensToTrack.push({ ...this.state.parsedOrder.metadata.takerToken, address: this.state.parsedOrder.signedOrder.takerTokenAddress, iconUrl: undefined, - isTracked: false, + trackedTimestamp: undefined, isRegistered: false, }); } else if (!isTakerTokenTracked) { diff --git a/packages/website/ts/components/generate_order/asset_picker.tsx b/packages/website/ts/components/generate_order/asset_picker.tsx index 0f569e1ad..3d53a9e7d 100644 --- a/packages/website/ts/components/generate_order/asset_picker.tsx +++ b/packages/website/ts/components/generate_order/asset_picker.tsx @@ -1,6 +1,7 @@ import * as _ from 'lodash'; import Dialog from 'material-ui/Dialog'; import FlatButton from 'material-ui/FlatButton'; +import * as moment from 'moment'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { NewTokenForm } from 'ts/components/generate_order/new_token_form'; @@ -10,6 +11,7 @@ import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; import { DialogConfigs, Token, TokenByAddress, TokenVisibility } from 'ts/types'; import { constants } from 'ts/utils/constants'; +import { utils } from 'ts/utils/utils'; const TOKEN_ICON_DIMENSION = 100; const TILE_DIMENSION = 146; @@ -134,8 +136,8 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt let tileStyles; const gridTiles = _.map(this.props.tokenByAddress, (token: Token, address: string) => { if ( - (this.props.tokenVisibility === TokenVisibility.TRACKED && !token.isTracked) || - (this.props.tokenVisibility === TokenVisibility.UNTRACKED && token.isTracked) || + (this.props.tokenVisibility === TokenVisibility.TRACKED && !utils.isTokenTracked(token)) || + (this.props.tokenVisibility === TokenVisibility.UNTRACKED && utils.isTokenTracked(token)) || token.symbol === constants.ZRX_TOKEN_SYMBOL || token.symbol === constants.ETHER_TOKEN_SYMBOL ) { @@ -212,7 +214,7 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt } private _onChooseToken(tokenAddress: string): void { const token = this.props.tokenByAddress[tokenAddress]; - if (token.isTracked) { + if (utils.isTokenTracked(token)) { this.props.onTokenChosen(tokenAddress); } else { this.setState({ @@ -257,9 +259,8 @@ export class AssetPicker extends React.Component<AssetPickerProps, AssetPickerSt } const newTokenEntry = { ...token, + trackedTimestamp: moment().unix(), }; - - newTokenEntry.isTracked = true; trackedTokenStorage.addTrackedTokenToUser(this.props.userAddress, this.props.networkId, newTokenEntry); this.props.dispatcher.updateTokenByAddress([newTokenEntry]); diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx index 176a0807b..3d7eda84c 100644 --- a/packages/website/ts/components/generate_order/new_token_form.tsx +++ b/packages/website/ts/components/generate_order/new_token_form.tsx @@ -1,6 +1,7 @@ import { colors } from '@0xproject/react-shared'; import * as _ from 'lodash'; import TextField from 'material-ui/TextField'; +import * as moment from 'moment'; import * as React from 'react'; import { Blockchain } from 'ts/blockchain'; import { AddressInput } from 'ts/components/inputs/address_input'; @@ -147,7 +148,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor iconUrl: undefined, name: this.state.name, symbol: this.state.symbol.toUpperCase(), - isTracked: true, + trackedTimestamp: moment().unix(), isRegistered: false, }; this.props.onNewTokenSubmitted(newToken); diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx index b4a174a03..c85d97207 100644 --- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx +++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx @@ -23,7 +23,6 @@ import { GenerateOrderForm } from 'ts/containers/generate_order_form'; import { localStorage } from 'ts/local_storage/local_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, WebsitePaths } from 'ts/types'; -import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { orderParser } from 'ts/utils/order_parser'; import { Translate } from 'ts/utils/translate'; @@ -170,67 +169,53 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta /> <div id="portal" className="mx-auto max-width-4" style={{ width: '100%' }}> <Paper className="mb3 mt2"> - {!configs.IS_MAINNET_ENABLED && this.props.networkId === constants.NETWORK_ID_MAINNET ? ( - <div className="p3 center"> - <div className="h2 py2">Mainnet unavailable</div> - <div className="mx-auto pb2 pt2"> - <img src="/images/zrx_token.png" style={{ width: 150 }} /> - </div> - <div> - 0x portal is currently unavailable on the Ethereum mainnet. - <div>To try it out, switch to the Kovan test network (networkId: 42).</div> - <div className="py2">Check back soon!</div> - </div> + <div className="mx-auto flex"> + <div className="col col-2 pr2 pt1 sm-hide xs-hide" style={portalMenuContainerStyle}> + <LegacyPortalMenu menuItemStyle={{ color: colors.white }} /> </div> - ) : ( - <div className="mx-auto flex"> - <div className="col col-2 pr2 pt1 sm-hide xs-hide" style={portalMenuContainerStyle}> - <LegacyPortalMenu menuItemStyle={{ color: colors.white }} /> - </div> - <div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12"> - <div className="py2" style={{ backgroundColor: colors.grey50 }}> - {this.props.blockchainIsLoaded ? ( - <Switch> - <Route - path={`${WebsitePaths.Portal}/weth`} - render={this._renderEthWrapper.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/fill`} - render={this._renderFillOrder.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/balances`} - render={this._renderTokenBalances.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/trades`} - render={this._renderTradeHistory.bind(this)} - /> - <Route - path={`${WebsitePaths.Home}`} - render={this._renderGenerateOrderForm.bind(this)} - /> - </Switch> - ) : ( - <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}> - <div - className="relative sm-px2 sm-pt2 sm-m1" - style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }} - > - <div className="center pb2"> - <CircularProgress size={40} thickness={5} /> - </div> - <div className="center pt2" style={{ paddingBottom: 11 }}> - Loading Portal... - </div> + <div className="col col-12 lg-col-10 md-col-10 sm-col sm-col-12"> + <div className="py2" style={{ backgroundColor: colors.grey50 }}> + {this.props.blockchainIsLoaded ? ( + <Switch> + <Route + path={`${WebsitePaths.Portal}/weth`} + render={this._renderEthWrapper.bind(this)} + /> + <Route + path={`${WebsitePaths.Portal}/fill`} + render={this._renderFillOrder.bind(this)} + /> + <Route + path={`${WebsitePaths.Portal}/balances`} + render={this._renderTokenBalances.bind(this)} + /> + <Route + path={`${WebsitePaths.Portal}/trades`} + render={this._renderTradeHistory.bind(this)} + /> + <Route + path={`${WebsitePaths.Home}`} + render={this._renderGenerateOrderForm.bind(this)} + /> + </Switch> + ) : ( + <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}> + <div + className="relative sm-px2 sm-pt2 sm-m1" + style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }} + > + <div className="center pb2"> + <CircularProgress size={40} thickness={5} /> + </div> + <div className="center pt2" style={{ paddingBottom: 11 }}> + Loading Portal... </div> </div> - )} - </div> + </div> + )} </div> </div> - )} + </div> </Paper> <BlockchainErrDialog blockchain={this._blockchain} @@ -249,16 +234,14 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)} /> <FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} /> - {this.props.blockchainIsLoaded && ( - <LedgerConfigDialog - providerType={this.props.providerType} - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - toggleDialogFn={this.onToggleLedgerDialog.bind(this)} - isOpen={this.state.isLedgerDialogOpen} - /> - )} + <LedgerConfigDialog + providerType={this.props.providerType} + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + toggleDialogFn={this.onToggleLedgerDialog.bind(this)} + isOpen={this.state.isLedgerDialogOpen} + /> </div> <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} /> </div> @@ -292,8 +275,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta ); } private _renderTokenBalances(): React.ReactNode { - const allTokens = _.values(this.props.tokenByAddress); - const trackedTokens = _.filter(allTokens, t => t.isTracked); + const trackedTokens = utils.getTrackedTokens(this.props.tokenByAddress); return ( <TokenBalances blockchain={this._blockchain} diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 6486bafcb..1850a0966 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -186,9 +186,11 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp const ethToken = utils.getEthToken(this.props.tokenByAddress); const zrxToken = utils.getZrxToken(this.props.tokenByAddress); if (ethToken && zrxToken) { - const ethTokenAllowance = this.props.trackedTokenStateByAddress[ethToken.address].allowance; - const zrxTokenAllowance = this.props.trackedTokenStateByAddress[zrxToken.address].allowance; - return ethTokenAllowance > new BigNumber(0) && zrxTokenAllowance > new BigNumber(0); + const ethTokenState = this.props.trackedTokenStateByAddress[ethToken.address]; + const zrxTokenState = this.props.trackedTokenStateByAddress[zrxToken.address]; + if (ethTokenState && zrxTokenState) { + return ethTokenState.allowance.gt(0) && zrxTokenState.allowance.gt(0); + } } return false; } @@ -251,12 +253,15 @@ class PlainPortalOnboardingFlow extends React.Component<PortalOnboardingFlowProp if (!token) { return null; } - const tokenState = this.props.trackedTokenStateByAddress[token.address]; + const tokenStateIfExists = this.props.trackedTokenStateByAddress[token.address]; + if (_.isUndefined(tokenStateIfExists)) { + return null; + } return ( <AllowanceToggle token={token} - tokenState={tokenState} - isDisabled={!tokenState.isLoaded} + 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/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 4166fde53..438c7b52f 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -152,9 +152,8 @@ export class Portal extends React.Component<PortalProps, PortalState> { } public componentDidUpdate(prevProps: PortalProps): void { if (!prevProps.blockchainIsLoaded && this.props.blockchainIsLoaded) { - const trackedTokenAddresses = _.keys(this.state.trackedTokenStateByAddress); // tslint:disable-next-line:no-floating-promises - this._fetchBalancesAndAllowancesAsync(trackedTokenAddresses); + this._fetchBalancesAndAllowancesAsync(this._getCurrentTrackedTokensAddresses()); } } public componentWillReceiveProps(nextProps: PortalProps): void { @@ -182,17 +181,17 @@ export class Portal extends React.Component<PortalProps, PortalState> { prevPathname: nextProps.location.pathname, }); } + + // If the address changed, but the network did not, we can just refetch the currently tracked tokens. if ( - nextProps.userAddress !== this.props.userAddress || - nextProps.networkId !== this.props.networkId || + (nextProps.userAddress !== this.props.userAddress && nextProps.networkId === this.props.networkId) || nextProps.lastForceTokenStateRefetch !== this.props.lastForceTokenStateRefetch ) { - const trackedTokenAddresses = _.keys(this.state.trackedTokenStateByAddress); // tslint:disable-next-line:no-floating-promises - this._fetchBalancesAndAllowancesAsync(trackedTokenAddresses); + this._fetchBalancesAndAllowancesAsync(this._getCurrentTrackedTokensAddresses()); } - const nextTrackedTokens = this._getTrackedTokens(nextProps.tokenByAddress); + const nextTrackedTokens = utils.getTrackedTokens(nextProps.tokenByAddress); const trackedTokens = this._getCurrentTrackedTokens(); if (!_.isEqual(nextTrackedTokens, trackedTokens)) { @@ -200,7 +199,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const newTokenAddresses = _.map(newTokens, token => token.address); // Add placeholder entry for this token to the state, since fetching the // balance/allowance is asynchronous - const trackedTokenStateByAddress = this.state.trackedTokenStateByAddress; + const trackedTokenStateByAddress = { ...this.state.trackedTokenStateByAddress }; for (const tokenAddress of newTokenAddresses) { trackedTokenStateByAddress[tokenAddress] = { balance: new BigNumber(0), @@ -265,16 +264,16 @@ export class Portal extends React.Component<PortalProps, PortalState> { networkId={this.props.networkId} /> <FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} /> - {this.props.blockchainIsLoaded && ( - <LedgerConfigDialog - providerType={this.props.providerType} - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - toggleDialogFn={this._onToggleLedgerDialog.bind(this)} - isOpen={this.state.isLedgerDialogOpen} - /> - )} + + <LedgerConfigDialog + providerType={this.props.providerType} + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + toggleDialogFn={this._onToggleLedgerDialog.bind(this)} + isOpen={this.state.isLedgerDialogOpen} + /> + <AssetPicker userAddress={this.props.userAddress} networkId={this.props.networkId} @@ -563,9 +562,9 @@ export class Portal extends React.Component<PortalProps, PortalState> { if (this.state.tokenManagementState === TokenManagementState.Remove && !isDefaultTrackedToken) { if (token.isRegistered) { // Remove the token from tracked tokens - const newToken = { + const newToken: Token = { ...token, - isTracked: false, + trackedTimestamp: undefined, }; this.props.dispatcher.updateTokenByAddress([newToken]); } else { @@ -608,17 +607,12 @@ export class Portal extends React.Component<PortalProps, PortalState> { const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm; return isSmallScreen; } - private _getCurrentTrackedTokens(): Token[] { - return this._getTrackedTokens(this.props.tokenByAddress); + return utils.getTrackedTokens(this.props.tokenByAddress); } - - private _getTrackedTokens(tokenByAddress: TokenByAddress): Token[] { - const allTokens = _.values(tokenByAddress); - const trackedTokens = _.filter(allTokens, t => t.isTracked); - return trackedTokens; + private _getCurrentTrackedTokensAddresses(): string[] { + return _.map(this._getCurrentTrackedTokens(), token => token.address); } - private _getInitialTrackedTokenStateByAddress(trackedTokens: Token[]): TokenStateByAddress { const trackedTokenStateByAddress: TokenStateByAddress = {}; _.each(trackedTokens, token => { diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index 7af80745c..3fae83c00 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -308,7 +308,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala const trackedTokensStartingWithEtherToken = trackedTokens.sort( firstBy((t: Token) => t.symbol !== ETHER_TOKEN_SYMBOL) .thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL) - .thenBy('address'), + .thenBy('trackedTimestamp'), ); const tableRows = _.map( trackedTokensStartingWithEtherToken, @@ -424,9 +424,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala if (!this.state.isAddingToken && !isDefaultTrackedToken) { if (token.isRegistered) { // Remove the token from tracked tokens - const newToken = { + const newToken: Token = { ...token, - isTracked: false, + trackedTimestamp: undefined, }; this.props.dispatcher.updateTokenByAddress([newToken]); } else { diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index 537edc7bb..fac6c131f 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -13,7 +13,6 @@ import { ProviderDisplay } from 'ts/components/top_bar/provider_display'; import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item'; import { DropDown } from 'ts/components/ui/drop_down'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { zIndex } from 'ts/style/z_index'; import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; @@ -58,7 +57,6 @@ const styles: Styles = { width: '100%', position: 'relative', top: 0, - zIndex: zIndex.topBar, paddingBottom: 1, }, bottomBar: { diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 5dde0f4e7..e1a2d4ce7 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -156,6 +156,20 @@ export class Wallet extends React.Component<WalletProps, WalletState> { isHoveringSidebar: false, }; } + public componentDidUpdate(prevProps: WalletProps): void { + const currentTrackedTokens = this.props.trackedTokens; + const differentTrackedTokens = _.difference(currentTrackedTokens, prevProps.trackedTokens); + const firstDifferentTrackedToken = _.head(differentTrackedTokens); + // check if there is only one different token, and if that token is a member of the current tracked tokens + // this means that the token was added, not removed + if ( + !_.isUndefined(firstDifferentTrackedToken) && + _.size(differentTrackedTokens) === 1 && + _.includes(currentTrackedTokens, firstDifferentTrackedToken) + ) { + document.getElementById(firstDifferentTrackedToken.address).scrollIntoView(); + } + } public render(): React.ReactNode { const isBlockchainLoaded = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError; return ( @@ -318,7 +332,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const trackedTokensStartingWithEtherToken = trackedTokens.sort( firstBy((t: Token) => t.symbol !== constants.ETHER_TOKEN_SYMBOL) .thenBy((t: Token) => t.symbol !== constants.ZRX_TOKEN_SYMBOL) - .thenBy('address'), + .thenBy('trackedTimestamp'), ); return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this)); } @@ -375,7 +389,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const style = { ...styles.tokenItem, ...additionalStyle }; const etherToken = this._getEthToken(); return ( - <div key={key} className={`flex flex-column ${className || ''}`}> + <div id={key} key={key} className={`flex flex-column ${className || ''}`}> <StandardIconRow icon={icon} main={ |