From d53915e7e34e3c6de865342ee2e5063fe959ce5d Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 10 May 2018 14:25:56 -0700 Subject: Add routes --- packages/website/ts/components/portal/portal.tsx | 107 ++++++++++++++++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index e572b7911..d227678d6 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -3,20 +3,35 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; +import { Route, Switch } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog'; import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog'; import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog'; +import { EthWrappers } from 'ts/components/eth_wrappers'; +import { FillOrder } from 'ts/components/fill_order'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; import { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; +import { TokenBalances } from 'ts/components/token_balances'; import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar'; +import { TradeHistory } from 'ts/components/trade_history/trade_history'; import { FlashMessage } from 'ts/components/ui/flash_message'; import { Wallet } from 'ts/components/wallet/wallet'; +import { GenerateOrderForm } from 'ts/containers/generate_order_form'; import { localStorage } from 'ts/local_storage/local_storage'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { Dispatcher } from 'ts/redux/dispatcher'; -import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, TokenVisibility } from 'ts/types'; +import { + BlockchainErrs, + HashData, + Order, + ProviderType, + ScreenWidths, + TokenByAddress, + TokenVisibility, + WebsitePaths, +} from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; import { Translate } from 'ts/utils/translate'; @@ -85,6 +100,7 @@ const styles: Styles = { export class Portal extends React.Component { private _blockchain: Blockchain; + private _sharedOrderIfExists: Order; private _throttledScreenWidthUpdate: () => void; constructor(props: PortalProps) { super(props); @@ -200,7 +216,22 @@ export class Portal extends React.Component {
Explore 0x Ecosystem
- + + + + + + + { ); } + private _renderEthWrapper() { + return ( + + ); + } + private _renderTradeHistory() { + return ( + + ); + } + private _renderTokenBalances() { + const allTokens = _.values(this.props.tokenByAddress); + const trackedTokens = _.filter(allTokens, t => t.isTracked); + return ( + + ); + } + private _renderFillOrder(match: any, location: Location, history: History) { + const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) + ? this.props.userSuppliedOrderCache + : this._sharedOrderIfExists; + return ( + + ); + } + private _renderGenerateOrderForm(match: any, location: Location, history: History) { + return ( + + ); + } + private _renderRelayerIndex() { + return ; + } private _onTokenChosen(tokenAddress: string): void { if (_.isEmpty(tokenAddress)) { this.setState({ -- cgit v1.2.3 From 9e76d2ca63090e28379688505e5e179ec642d3b1 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Thu, 10 May 2018 15:11:49 -0700 Subject: Add menu --- packages/website/ts/components/portal/portal.tsx | 59 ++++++++++++++++-------- packages/website/ts/components/wallet/wallet.tsx | 2 +- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index d227678d6..e6a92d9a8 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -12,6 +12,7 @@ import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_ import { EthWrappers } from 'ts/components/eth_wrappers'; import { FillOrder } from 'ts/components/fill_order'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; +import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu'; import { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; import { TokenBalances } from 'ts/components/token_balances'; import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar'; @@ -164,8 +165,6 @@ export class Portal extends React.Component { const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind( this.props.dispatcher, ); - const allTokens = _.values(this.props.tokenByAddress); - const trackedTokens = _.filter(allTokens, t => t.isTracked); const isAssetPickerDialogOpen = this.state.tokenManagementState !== TokenManagementState.None; const tokenVisibility = this.state.tokenManagementState === TokenManagementState.Add @@ -194,23 +193,19 @@ export class Portal extends React.Component {
Your Account
- +
+ + + + +
@@ -272,6 +267,32 @@ export class Portal extends React.Component {
); } + private _renderMenu() { + return ; + } + private _renderWallet() { + const allTokens = _.values(this.props.tokenByAddress); + const trackedTokens = _.filter(allTokens, t => t.isTracked); + return ( + + ); + } private _renderEthWrapper() { return ( Date: Thu, 10 May 2018 16:29:10 -0700 Subject: Implement new menu styling --- packages/website/ts/components/portal/portal.tsx | 8 +- .../website/ts/components/portal/portal_menu.tsx | 91 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 packages/website/ts/components/portal/portal_menu.tsx diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index e6a92d9a8..d6bc82587 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -3,7 +3,7 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; -import { Route, Switch } from 'react-router-dom'; +import { Route, RouteComponentProps, Switch } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog'; @@ -12,7 +12,7 @@ import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_ import { EthWrappers } from 'ts/components/eth_wrappers'; import { FillOrder } from 'ts/components/fill_order'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; -import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu'; +import { PortalMenu } from 'ts/components/portal/portal_menu'; import { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; import { TokenBalances } from 'ts/components/token_balances'; import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar'; @@ -267,8 +267,8 @@ export class Portal extends React.Component {
); } - private _renderMenu() { - return ; + private _renderMenu(routeComponentProps: RouteComponentProps) { + return ; } private _renderWallet() { const allTokens = _.values(this.props.tokenByAddress); diff --git a/packages/website/ts/components/portal/portal_menu.tsx b/packages/website/ts/components/portal/portal_menu.tsx new file mode 100644 index 000000000..33835fd98 --- /dev/null +++ b/packages/website/ts/components/portal/portal_menu.tsx @@ -0,0 +1,91 @@ +import { colors, Styles } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import { MenuItem } from 'ts/components/ui/menu_item'; +import { Environments, WebsitePaths } from 'ts/types'; +import { configs } from 'ts/utils/configs'; + +export interface PortalMenuProps { + selectedPath?: string; +} + +interface MenuItemEntry { + to: string; + labelText: string; + iconName: string; +} + +const menuItemEntries: MenuItemEntry[] = [ + { + to: `${WebsitePaths.Portal}`, + labelText: 'Generate order', + iconName: 'zmdi-arrow-right-top', + }, + { + to: `${WebsitePaths.Portal}/fill`, + labelText: 'Fill order', + iconName: 'zmdi-arrow-left-bottom', + }, + { + to: `${WebsitePaths.Portal}/balances`, + labelText: 'Balances', + iconName: 'zmdi-balance-wallet', + }, + { + to: `${WebsitePaths.Portal}/trades`, + labelText: 'Trade History', + iconName: 'zmdi-format-list-bulleted', + }, + { + to: `${WebsitePaths.Portal}/weth`, + labelText: 'Wrap ETH', + iconName: 'zmdi-circle-o', + }, +]; + +const DEFAULT_LABEL_COLOR = colors.darkerGrey; +const DEFAULT_ICON_COLOR = colors.darkerGrey; +const SELECTED_ICON_COLOR = colors.yellow800; + +export const PortalMenu: React.StatelessComponent = (props: PortalMenuProps) => { + return ( +
+ {_.map(menuItemEntries, entry => { + const selected = entry.to === props.selectedPath; + return ( + + + + ); + })} +
+ ); +}; + +interface PortalMenuItemLabelProps { + title: string; + iconName: string; + selected: boolean; +} +const PortalMenuItemLabel: React.StatelessComponent = (props: PortalMenuItemLabelProps) => { + const styles: Styles = { + iconStyle: { + color: props.selected ? SELECTED_ICON_COLOR : DEFAULT_ICON_COLOR, + fontSize: 20, + }, + textStyle: { + color: DEFAULT_LABEL_COLOR, + fontWeight: props.selected ? 'bold' : 'normal', + }, + }; + return ( +
+
+ +
+
+ {props.title} +
+
+ ); +}; -- cgit v1.2.3 From ef1e9743465d40cb3a2c3a1479155437694951b9 Mon Sep 17 00:00:00 2001 From: Brandon Millman Date: Fri, 11 May 2018 14:17:40 -0700 Subject: Back button and title components --- packages/website/ts/components/portal/portal.tsx | 129 ++++++++++++++------- .../website/ts/components/portal/portal_menu.tsx | 29 ++--- packages/website/ts/components/wallet/wallet.tsx | 18 +-- 3 files changed, 112 insertions(+), 64 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index d6bc82587..70c99921c 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -3,7 +3,7 @@ import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; -import { Route, RouteComponentProps, Switch } from 'react-router-dom'; +import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom'; import { Blockchain } from 'ts/blockchain'; import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog'; @@ -78,6 +78,7 @@ enum TokenManagementState { const THROTTLE_TIMEOUT = 100; const TOP_BAR_HEIGHT = TopBar.heightForDisplayType(TopBarDisplayType.Expanded); +const BACK_BUTTON_HEIGHT = 28; const styles: Styles = { root: { @@ -97,6 +98,16 @@ const styles: Styles = { fontWeight: 'bold', fontSize: 20, }, + backButton: { + height: BACK_BUTTON_HEIGHT, + backgroundColor: colors.white, + borderRadius: BACK_BUTTON_HEIGHT, + boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, + }, + backButtonIcon: { + color: colors.mediumBlue, + fontSize: 20, + }, }; export class Portal extends React.Component { @@ -190,9 +201,6 @@ export class Portal extends React.Component {
-
- Your Account -
{
-
- Explore 0x Ecosystem -
{ /> { ); } private _renderMenu(routeComponentProps: RouteComponentProps) { - return ; + return ( +
+ + +
+ ); } private _renderWallet() { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( - +
+ + <Wallet + userAddress={this.props.userAddress} + networkId={this.props.networkId} + blockchain={this._blockchain} + blockchainIsLoaded={this.props.blockchainIsLoaded} + blockchainErr={this.props.blockchainErr} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + injectedProviderName={this.props.injectedProviderName} + providerType={this.props.providerType} + onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} + onAddToken={this._onAddToken.bind(this)} + onRemoveToken={this._onRemoveToken.bind(this)} + /> + </div> ); } private _renderEthWrapper() { @@ -319,19 +332,22 @@ export class Portal extends React.Component<PortalProps, PortalState> { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( - <TokenBalances - blockchain={this._blockchain} - blockchainErr={this.props.blockchainErr} - blockchainIsLoaded={this.props.blockchainIsLoaded} - dispatcher={this.props.dispatcher} - screenWidth={this.props.screenWidth} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={trackedTokens} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - networkId={this.props.networkId} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> + <div> + <Title titleText={'Your Account'} /> + <TokenBalances + blockchain={this._blockchain} + blockchainErr={this.props.blockchainErr} + blockchainIsLoaded={this.props.blockchainIsLoaded} + dispatcher={this.props.dispatcher} + screenWidth={this.props.screenWidth} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + networkId={this.props.networkId} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + </div> ); } private _renderFillOrder(match: any, location: Location, history: History) { @@ -363,7 +379,12 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); } private _renderRelayerIndex() { - return <RelayerIndex networkId={this.props.networkId} />; + return ( + <div> + <Title titleText={'Explore 0x Relayers'} /> + <RelayerIndex networkId={this.props.networkId} /> + </div> + ); } private _onTokenChosen(tokenAddress: string): void { if (_.isEmpty(tokenAddress)) { @@ -419,3 +440,31 @@ export class Portal extends React.Component<PortalProps, PortalState> { this.props.dispatcher.updateScreenWidth(newScreenWidth); } } + +interface TitleProps { + titleText: string; +} +const Title = (props: TitleProps) => { + return ( + <div className="py3" style={styles.title}> + {props.titleText} + </div> + ); +}; + +const BackButton = () => { + return ( + <div style={{ height: 65, paddingTop: 25 }}> + <Link to={`${WebsitePaths.Portal}`} style={{ textDecoration: 'none' }}> + <div className="flex right" style={{ ...styles.backButton, paddingTop: 10 }}> + <div style={{ marginLeft: 12 }}> + <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> + </div> + <div style={{ marginLeft: 12, marginRight: 12 }}> + <div style={{ fontSize: 16, color: colors.lightGrey }}>back to Relayers</div> + </div> + </div> + </Link> + </div> + ); +}; diff --git a/packages/website/ts/components/portal/portal_menu.tsx b/packages/website/ts/components/portal/portal_menu.tsx index 33835fd98..e073596e2 100644 --- a/packages/website/ts/components/portal/portal_menu.tsx +++ b/packages/website/ts/components/portal/portal_menu.tsx @@ -17,39 +17,34 @@ interface MenuItemEntry { const menuItemEntries: MenuItemEntry[] = [ { - to: `${WebsitePaths.Portal}`, - labelText: 'Generate order', - iconName: 'zmdi-arrow-right-top', - }, - { - to: `${WebsitePaths.Portal}/fill`, - labelText: 'Fill order', - iconName: 'zmdi-arrow-left-bottom', - }, - { - to: `${WebsitePaths.Portal}/balances`, - labelText: 'Balances', + to: `${WebsitePaths.Portal}/account`, + labelText: 'Account Overview', iconName: 'zmdi-balance-wallet', }, { to: `${WebsitePaths.Portal}/trades`, - labelText: 'Trade History', + labelText: 'Trade history', iconName: 'zmdi-format-list-bulleted', }, { to: `${WebsitePaths.Portal}/weth`, - labelText: 'Wrap ETH', + labelText: 'Wrapped ETH', iconName: 'zmdi-circle-o', }, + { + to: `${WebsitePaths.Portal}/direct`, + labelText: 'Trade direct', + iconName: 'zmdi-swap', + }, ]; const DEFAULT_LABEL_COLOR = colors.darkerGrey; const DEFAULT_ICON_COLOR = colors.darkerGrey; -const SELECTED_ICON_COLOR = colors.yellow800; +const SELECTED_ICON_COLOR = colors.yellow900; export const PortalMenu: React.StatelessComponent<PortalMenuProps> = (props: PortalMenuProps) => { return ( - <div> + <div style={{ paddingLeft: 185 }}> {_.map(menuItemEntries, entry => { const selected = entry.to === props.selectedPath; return ( @@ -80,7 +75,7 @@ const PortalMenuItemLabel: React.StatelessComponent<PortalMenuItemLabelProps> = }; return ( <div className="flex"> - <div className="pr1 pl2"> + <div className="pr1"> <i style={styles.iconStyle} className={`zmdi ${props.iconName}`} /> </div> <div className="pl1" style={styles.textStyle}> diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index d9c97e34a..ac79d5a21 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -18,6 +18,7 @@ import NavigationArrowDownward from 'material-ui/svg-icons/navigation/arrow-down import NavigationArrowUpward from 'material-ui/svg-icons/navigation/arrow-upward'; import Close from 'material-ui/svg-icons/navigation/close'; import * as React from 'react'; +import { Link } from 'react-router-dom'; import ReactTooltip = require('react-tooltip'); import firstBy = require('thenby'); @@ -38,6 +39,7 @@ import { TokenByAddress, TokenState, TokenStateByAddress, + WebsitePaths, } from 'ts/types'; import { backendClient } from 'ts/utils/backend_client'; import { constants } from 'ts/utils/constants'; @@ -237,13 +239,15 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const userAddress = this.props.userAddress; const primaryText = utils.getAddressBeginAndEnd(userAddress); return ( - <ListItem - key={HEADER_ITEM_KEY} - primaryText={primaryText} - leftIcon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />} - style={{ ...styles.paddedItem, ...styles.borderedItem }} - innerDivStyle={styles.headerItemInnerDiv} - /> + <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> + <ListItem + key={HEADER_ITEM_KEY} + primaryText={primaryText} + leftIcon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />} + style={{ ...styles.paddedItem, ...styles.borderedItem }} + innerDivStyle={styles.headerItemInnerDiv} + /> + </Link> ); } private _renderBody(): React.ReactElement<{}> { -- cgit v1.2.3 From 807250510ac5be9ef7cd291aa16db64a5eff1418 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Fri, 11 May 2018 14:21:56 -0700 Subject: Add props to back button --- packages/website/ts/components/portal/portal.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 70c99921c..fb047a28a 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -275,7 +275,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderMenu(routeComponentProps: RouteComponentProps<any>) { return ( <div> - <BackButton /> + <BackButton to={`${WebsitePaths.Portal}`} labelText={'back to Relayers'} /> <PortalMenu selectedPath={routeComponentProps.location.pathname} /> </div> ); @@ -285,7 +285,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( <div> - <Title titleText={'Your Account'} /> + <Title labelText={'Your Account'} /> <Wallet userAddress={this.props.userAddress} networkId={this.props.networkId} @@ -333,7 +333,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( <div> - <Title titleText={'Your Account'} /> + <Title labelText={'Your Account'} /> <TokenBalances blockchain={this._blockchain} blockchainErr={this.props.blockchainErr} @@ -381,7 +381,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderRelayerIndex() { return ( <div> - <Title titleText={'Explore 0x Relayers'} /> + <Title labelText={'Explore 0x Relayers'} /> <RelayerIndex networkId={this.props.networkId} /> </div> ); @@ -442,26 +442,30 @@ export class Portal extends React.Component<PortalProps, PortalState> { } interface TitleProps { - titleText: string; + labelText: string; } const Title = (props: TitleProps) => { return ( <div className="py3" style={styles.title}> - {props.titleText} + {props.labelText} </div> ); }; -const BackButton = () => { +interface BackButtonProps { + to: string; + labelText: string; +} +const BackButton = (props: BackButtonProps) => { return ( <div style={{ height: 65, paddingTop: 25 }}> - <Link to={`${WebsitePaths.Portal}`} style={{ textDecoration: 'none' }}> + <Link to={props.to} style={{ textDecoration: 'none' }}> <div className="flex right" style={{ ...styles.backButton, paddingTop: 10 }}> <div style={{ marginLeft: 12 }}> <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> </div> <div style={{ marginLeft: 12, marginRight: 12 }}> - <div style={{ fontSize: 16, color: colors.lightGrey }}>back to Relayers</div> + <div style={{ fontSize: 16, color: colors.lightGrey }}>{props.labelText}</div> </div> </div> </Link> -- cgit v1.2.3 From d6e321e97ff374b4f46356179bc1e280e4a00260 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Fri, 11 May 2018 15:25:04 -0700 Subject: Add manage you wallet footer --- packages/website/ts/components/wallet/wallet.tsx | 65 +++++++++++++++--------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index ac79d5a21..ff7127604 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -279,31 +279,48 @@ export class Wallet extends React.Component<WalletProps, WalletState> { } private _renderFooterRows(): React.ReactElement<{}> { return ( - <ListItem - key={FOOTER_ITEM_KEY} - primaryText={ - <div className="flex"> - <FloatingActionButton mini={true} zDepth={0} onClick={this.props.onAddToken}> - <ContentAdd /> - </FloatingActionButton> - <FloatingActionButton mini={true} zDepth={0} className="px1" onClick={this.props.onRemoveToken}> - <ContentRemove /> - </FloatingActionButton> - <div - style={{ - paddingLeft: 10, - position: 'relative', - top: '50%', - transform: 'translateY(33%)', - }} - > - add/remove tokens + <div key={FOOTER_ITEM_KEY}> + <ListItem + primaryText={ + <div className="flex"> + <FloatingActionButton mini={true} zDepth={0} onClick={this.props.onAddToken}> + <ContentAdd /> + </FloatingActionButton> + <FloatingActionButton + mini={true} + zDepth={0} + className="px1" + onClick={this.props.onRemoveToken} + > + <ContentRemove /> + </FloatingActionButton> + <div + style={{ + paddingLeft: 10, + position: 'relative', + top: '50%', + transform: 'translateY(33%)', + }} + > + add/remove tokens + </div> </div> - </div> - } - disabled={true} - innerDivStyle={styles.footerItemInnerDiv} - /> + } + disabled={true} + innerDivStyle={styles.footerItemInnerDiv} + style={styles.borderedItem} + /> + <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> + <ListItem + primaryText={ + <div className="flex right" style={{ color: colors.mediumBlue, fontWeight: 'bold' }}> + {'manage your wallet'} + </div> + } + style={{ ...styles.paddedItem, ...styles.borderedItem }} + /> + </Link> + </div> ); } private _renderEthRows(): React.ReactNode { -- cgit v1.2.3 From ea948ac2c885c395f1e07b285c65232264c58b7b Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Fri, 11 May 2018 16:09:22 -0700 Subject: Trade direct route --- packages/website/ts/components/portal/portal.tsx | 79 ++++++++++------------ .../website/ts/components/portal/portal_menu.tsx | 2 +- 2 files changed, 37 insertions(+), 44 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index fb047a28a..09f2ba10a 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -221,7 +221,6 @@ export class Portal extends React.Component<PortalProps, PortalState> { path={`${WebsitePaths.Portal}/weth`} render={this._renderEthWrapper.bind(this)} /> - <Route path={`${WebsitePaths.Portal}/fill`} render={this._renderFillOrder.bind(this)} /> <Route path={`${WebsitePaths.Portal}/account`} render={this._renderTokenBalances.bind(this)} @@ -230,6 +229,10 @@ export class Portal extends React.Component<PortalProps, PortalState> { path={`${WebsitePaths.Portal}/trades`} component={this._renderTradeHistory.bind(this)} /> + <Route + path={`${WebsitePaths.Portal}/direct`} + component={this._renderTradeDirect.bind(this)} + /> <Route path={`${WebsitePaths.Home}`} component={this._renderRelayerIndex.bind(this)} /> </Switch> </div> @@ -308,24 +311,42 @@ export class Portal extends React.Component<PortalProps, PortalState> { } private _renderEthWrapper() { return ( - <EthWrappers - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> + <div> + <Title labelText={'Wrapped ETH'} /> + <EthWrappers + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + </div> ); } private _renderTradeHistory() { return ( - <TradeHistory - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - /> + <div> + <Title labelText={'Trade History'} /> + <TradeHistory + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + networkId={this.props.networkId} + /> + </div> + ); + } + private _renderTradeDirect(match: any, location: Location, history: History) { + return ( + <div> + <Title labelText={'Trade Direct'} /> + <GenerateOrderForm + blockchain={this._blockchain} + hashData={this.props.hashData} + dispatcher={this.props.dispatcher} + /> + </div> ); } private _renderTokenBalances() { @@ -350,34 +371,6 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderFillOrder(match: any, location: Location, history: History) { - const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) - ? this.props.userSuppliedOrderCache - : this._sharedOrderIfExists; - return ( - <FillOrder - blockchain={this._blockchain} - blockchainErr={this.props.blockchainErr} - initialOrder={initialFillOrder} - isOrderInUrl={!_.isUndefined(this._sharedOrderIfExists)} - orderFillAmount={this.props.orderFillAmount} - networkId={this.props.networkId} - userAddress={this.props.userAddress} - tokenByAddress={this.props.tokenByAddress} - dispatcher={this.props.dispatcher} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> - ); - } - private _renderGenerateOrderForm(match: any, location: Location, history: History) { - return ( - <GenerateOrderForm - blockchain={this._blockchain} - hashData={this.props.hashData} - dispatcher={this.props.dispatcher} - /> - ); - } private _renderRelayerIndex() { return ( <div> diff --git a/packages/website/ts/components/portal/portal_menu.tsx b/packages/website/ts/components/portal/portal_menu.tsx index e073596e2..c8e2dacfa 100644 --- a/packages/website/ts/components/portal/portal_menu.tsx +++ b/packages/website/ts/components/portal/portal_menu.tsx @@ -18,7 +18,7 @@ interface MenuItemEntry { const menuItemEntries: MenuItemEntry[] = [ { to: `${WebsitePaths.Portal}/account`, - labelText: 'Account Overview', + labelText: 'Account overview', iconName: 'zmdi-balance-wallet', }, { -- cgit v1.2.3 From c787dc735695be351b23e1e91b792da44e01fc11 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Mon, 14 May 2018 14:19:39 -0700 Subject: Fix linter errors and relayer index reloading --- .../ts/components/legacy_portal/legacy_portal.tsx | 2 +- packages/website/ts/components/portal/portal.tsx | 26 +++++++++++++--------- packages/website/ts/components/wallet/wallet.tsx | 3 +-- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx index 002b258fb..a5ea95629 100644 --- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx +++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx @@ -217,7 +217,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta /> <Route path={`${WebsitePaths.Portal}/trades`} - component={this._renderTradeHistory.bind(this)} + render={this._renderTradeHistory.bind(this)} /> <Route path={`${WebsitePaths.Home}`} diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 09f2ba10a..f3b0cc721 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -210,7 +210,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Route exact={true} path={`${WebsitePaths.Portal}`} - component={this._renderWallet.bind(this)} + render={this._renderWallet.bind(this)} /> </Switch> </div> @@ -227,13 +227,17 @@ export class Portal extends React.Component<PortalProps, PortalState> { /> <Route path={`${WebsitePaths.Portal}/trades`} - component={this._renderTradeHistory.bind(this)} + render={this._renderTradeHistory.bind(this)} /> <Route path={`${WebsitePaths.Portal}/direct`} - component={this._renderTradeDirect.bind(this)} + render={this._renderTradeDirect.bind(this)} + /> + <Route + exact={true} + path={`${WebsitePaths.Portal}/`} + render={this._renderRelayerIndex.bind(this)} /> - <Route path={`${WebsitePaths.Home}`} component={this._renderRelayerIndex.bind(this)} /> </Switch> </div> </div> @@ -275,7 +279,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderMenu(routeComponentProps: RouteComponentProps<any>) { + private _renderMenu(routeComponentProps: RouteComponentProps<any>): React.ReactNode { return ( <div> <BackButton to={`${WebsitePaths.Portal}`} labelText={'back to Relayers'} /> @@ -283,7 +287,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderWallet() { + private _renderWallet(): React.ReactNode { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( @@ -309,7 +313,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderEthWrapper() { + private _renderEthWrapper(): React.ReactNode { return ( <div> <Title labelText={'Wrapped ETH'} /> @@ -325,7 +329,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderTradeHistory() { + private _renderTradeHistory(): React.ReactNode { return ( <div> <Title labelText={'Trade History'} /> @@ -337,7 +341,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderTradeDirect(match: any, location: Location, history: History) { + private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode { return ( <div> <Title labelText={'Trade Direct'} /> @@ -349,7 +353,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderTokenBalances() { + private _renderTokenBalances(): React.ReactNode { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( @@ -371,7 +375,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } - private _renderRelayerIndex() { + private _renderRelayerIndex(): React.ReactNode { return ( <div> <Title labelText={'Explore 0x Relayers'} /> diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index ff7127604..b7c3d5229 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -239,9 +239,8 @@ export class Wallet extends React.Component<WalletProps, WalletState> { const userAddress = this.props.userAddress; const primaryText = utils.getAddressBeginAndEnd(userAddress); return ( - <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> + <Link key={HEADER_ITEM_KEY} to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> <ListItem - key={HEADER_ITEM_KEY} primaryText={primaryText} leftIcon={<Identicon address={userAddress} diameter={ICON_DIMENSION} />} style={{ ...styles.paddedItem, ...styles.borderedItem }} -- cgit v1.2.3 From e0482f5400261bcaced8ea2263b1032939d25b92 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Mon, 14 May 2018 22:11:12 -0700 Subject: Wait for blockchain to display the account management routes --- packages/website/ts/components/portal/portal.tsx | 48 +++++++++++++++------- .../ts/components/relayer_index/relayer_index.tsx | 4 +- packages/website/ts/pages/fullscreen_message.tsx | 30 ++++++++++++++ packages/website/ts/pages/not_found.tsx | 43 ++++++------------- 4 files changed, 78 insertions(+), 47 deletions(-) create mode 100644 packages/website/ts/pages/fullscreen_message.tsx diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index f3b0cc721..bdaf9b18e 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -1,6 +1,7 @@ import { colors, Styles } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; +import CircularProgress from 'material-ui/CircularProgress'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom'; @@ -22,6 +23,7 @@ import { Wallet } from 'ts/components/wallet/wallet'; import { GenerateOrderForm } from 'ts/containers/generate_order_form'; import { localStorage } from 'ts/local_storage/local_storage'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; +import { FullscreenMessage } from 'ts/pages/fullscreen_message'; import { Dispatcher } from 'ts/redux/dispatcher'; import { BlockchainErrs, @@ -218,20 +220,8 @@ export class Portal extends React.Component<PortalProps, PortalState> { <div className="flex-auto px3" style={styles.scrollContainer}> <Switch> <Route - path={`${WebsitePaths.Portal}/weth`} - render={this._renderEthWrapper.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/account`} - render={this._renderTokenBalances.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/trades`} - render={this._renderTradeHistory.bind(this)} - /> - <Route - path={`${WebsitePaths.Portal}/direct`} - render={this._renderTradeDirect.bind(this)} + path={`${WebsitePaths.Portal}/:route`} + render={this._renderAccountManagement.bind(this)} /> <Route exact={true} @@ -313,6 +303,28 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } + private _renderAccountManagement(): React.ReactNode { + return this.props.blockchainIsLoaded ? ( + <Switch> + <Route path={`${WebsitePaths.Portal}/weth`} render={this._renderEthWrapper.bind(this)} /> + <Route path={`${WebsitePaths.Portal}/account`} render={this._renderTokenBalances.bind(this)} /> + <Route path={`${WebsitePaths.Portal}/trades`} render={this._renderTradeHistory.bind(this)} /> + <Route path={`${WebsitePaths.Portal}/direct`} render={this._renderTradeDirect.bind(this)} /> + <Route render={this._renderNotFoundMessage.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> + </div> + ); + } private _renderEthWrapper(): React.ReactNode { return ( <div> @@ -383,6 +395,14 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } + private _renderNotFoundMessage(): React.ReactNode { + return ( + <FullscreenMessage + headerText={'404 Not Found'} + bodyText={"Hm... looks like we couldn't find what you are looking for."} + /> + ); + } private _onTokenChosen(tokenAddress: string): void { if (_.isEmpty(tokenAddress)) { this.setState({ diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index d4fd6aeaf..9eaf9fe03 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -59,10 +59,10 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde const readyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); if (!readyToRender) { return ( - <div className="col col-12" style={{ ...styles.root, height: '100%' }}> + <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: '33%', transform: 'translateY(-50%)' }} + style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }} > <div className="center pb2"> {_.isUndefined(this.state.error) ? ( diff --git a/packages/website/ts/pages/fullscreen_message.tsx b/packages/website/ts/pages/fullscreen_message.tsx new file mode 100644 index 000000000..141fb38a4 --- /dev/null +++ b/packages/website/ts/pages/fullscreen_message.tsx @@ -0,0 +1,30 @@ +import { Styles } from '@0xproject/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/not_found.tsx b/packages/website/ts/pages/not_found.tsx index 96c73d4ec..674271636 100644 --- a/packages/website/ts/pages/not_found.tsx +++ b/packages/website/ts/pages/not_found.tsx @@ -3,6 +3,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Footer } from 'ts/components/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'; @@ -12,35 +13,15 @@ export interface NotFoundProps { dispatcher: Dispatcher; } -interface NotFoundState {} - -const styles: Styles = { - thin: { - fontWeight: 100, - }, +export const NotFound = (props: NotFoundProps) => { + return ( + <div> + <TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} /> + <FullscreenMessage + headerText={'404 Not Found'} + bodyText={"Hm... looks like we couldn't find what you are looking for."} + /> + <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} /> + </div> + ); }; - -export class NotFound extends React.Component<NotFoundProps, NotFoundState> { - public render(): React.ReactNode { - return ( - <div> - <TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} /> - <div className="mx-auto max-width-4 py4"> - <div className="center py4"> - <div className="py4"> - <div className="py4"> - <h1 style={{ ...styles.thin }}>404 Not Found</h1> - <div className="py1"> - <div className="py3"> - Hm... looks like we couldn't find what you are looking for. - </div> - </div> - </div> - </div> - </div> - </div> - <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} /> - </div> - ); - } -} -- cgit v1.2.3 From 09692dc70e914a62c18bf33bfee4d01fcb55713e Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Tue, 15 May 2018 11:44:05 -0700 Subject: Fix comments --- packages/website/ts/components/portal/portal.tsx | 9 ++++++--- packages/website/ts/components/portal/portal_menu.tsx | 4 +++- packages/website/ts/components/relayer_index/relayer_index.tsx | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index bdaf9b18e..cb4e24654 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -11,7 +11,6 @@ import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog'; import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog'; import { EthWrappers } from 'ts/components/eth_wrappers'; -import { FillOrder } from 'ts/components/fill_order'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; import { PortalMenu } from 'ts/components/portal/portal_menu'; import { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; @@ -81,6 +80,7 @@ enum TokenManagementState { const THROTTLE_TIMEOUT = 100; const TOP_BAR_HEIGHT = TopBar.heightForDisplayType(TopBarDisplayType.Expanded); const BACK_BUTTON_HEIGHT = 28; +const LEFT_COLUMN_WIDTH = 346; const styles: Styles = { root: { @@ -91,6 +91,9 @@ const styles: Styles = { body: { height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, }, + leftColumn: { + width: LEFT_COLUMN_WIDTH, + }, scrollContainer: { height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, WebkitOverflowScrolling: 'touch', @@ -114,7 +117,6 @@ const styles: Styles = { export class Portal extends React.Component<PortalProps, PortalState> { private _blockchain: Blockchain; - private _sharedOrderIfExists: Order; private _throttledScreenWidthUpdate: () => void; constructor(props: PortalProps) { super(props); @@ -203,7 +205,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { <div id="portal" style={styles.body}> <div className="sm-flex flex-center"> <div className="flex-last px3"> - <div style={{ width: 346 }}> + <div style={styles.leftColumn}> <Switch> <Route path={`${WebsitePaths.Portal}/:route`} @@ -313,6 +315,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Route render={this._renderNotFoundMessage.bind(this)} /> </Switch> ) : ( + // TODO: consolidate this loading component with the one in relayer_index <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}> <div className="relative sm-px2 sm-pt2 sm-m1" diff --git a/packages/website/ts/components/portal/portal_menu.tsx b/packages/website/ts/components/portal/portal_menu.tsx index c8e2dacfa..dc8f01d41 100644 --- a/packages/website/ts/components/portal/portal_menu.tsx +++ b/packages/website/ts/components/portal/portal_menu.tsx @@ -42,9 +42,11 @@ const DEFAULT_LABEL_COLOR = colors.darkerGrey; const DEFAULT_ICON_COLOR = colors.darkerGrey; const SELECTED_ICON_COLOR = colors.yellow900; +const LEFT_PADDING = 185; + export const PortalMenu: React.StatelessComponent<PortalMenuProps> = (props: PortalMenuProps) => { return ( - <div style={{ paddingLeft: 185 }}> + <div style={{ paddingLeft: LEFT_PADDING }}> {_.map(menuItemEntries, entry => { const selected = entry.to === props.selectedPath; return ( diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index 9eaf9fe03..5ab2e8c17 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -59,6 +59,7 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde const readyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos); if (!readyToRender) { return ( + // TODO: consolidate this loading component with the one in portal <div className="pt4 sm-px2 sm-pt2 sm-m1" style={{ height: 500 }}> <div className="relative sm-px2 sm-pt2 sm-m1" -- cgit v1.2.3 From 6a0cda7396573ac900d948d2427f93a740ca48a0 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Tue, 15 May 2018 11:45:02 -0700 Subject: Fix lint error --- packages/website/ts/components/wallet/wallet.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index b7c3d5229..818cff05b 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -314,8 +314,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> { primaryText={ <div className="flex right" style={{ color: colors.mediumBlue, fontWeight: 'bold' }}> {'manage your wallet'} - </div> - } + </div>} style={{ ...styles.paddedItem, ...styles.borderedItem }} /> </Link> -- cgit v1.2.3 From b6776f53ab3031a60eaaabffefc73d1e6d6f3d7c Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 12:10:36 -0700 Subject: Get rid of extra curly brackets --- packages/website/ts/components/portal/portal.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index cb4e24654..aa4392935 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -274,7 +274,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderMenu(routeComponentProps: RouteComponentProps<any>): React.ReactNode { return ( <div> - <BackButton to={`${WebsitePaths.Portal}`} labelText={'back to Relayers'} /> + <BackButton to={`${WebsitePaths.Portal}`} labelText="back to Relayers" /> <PortalMenu selectedPath={routeComponentProps.location.pathname} /> </div> ); @@ -284,7 +284,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( <div> - <Title labelText={'Your Account'} /> + <Title labelText="Your Account" /> <Wallet userAddress={this.props.userAddress} networkId={this.props.networkId} @@ -331,7 +331,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderEthWrapper(): React.ReactNode { return ( <div> - <Title labelText={'Wrapped ETH'} /> + <Title labelText="Wrapped ETH" /> <EthWrappers networkId={this.props.networkId} blockchain={this._blockchain} @@ -347,7 +347,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderTradeHistory(): React.ReactNode { return ( <div> - <Title labelText={'Trade History'} /> + <Title labelText="Trade History" /> <TradeHistory tokenByAddress={this.props.tokenByAddress} userAddress={this.props.userAddress} @@ -359,7 +359,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode { return ( <div> - <Title labelText={'Trade Direct'} /> + <Title labelText="Trade Direct" /> <GenerateOrderForm blockchain={this._blockchain} hashData={this.props.hashData} @@ -373,7 +373,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( <div> - <Title labelText={'Your Account'} /> + <Title labelText="Your Account" /> <TokenBalances blockchain={this._blockchain} blockchainErr={this.props.blockchainErr} @@ -393,7 +393,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderRelayerIndex(): React.ReactNode { return ( <div> - <Title labelText={'Explore 0x Relayers'} /> + <Title labelText="Explore 0x Relayers" /> <RelayerIndex networkId={this.props.networkId} /> </div> ); @@ -401,8 +401,8 @@ export class Portal extends React.Component<PortalProps, PortalState> { private _renderNotFoundMessage(): React.ReactNode { return ( <FullscreenMessage - headerText={'404 Not Found'} - bodyText={"Hm... looks like we couldn't find what you are looking for."} + headerText="404 Not Found" + bodyText="Hm... looks like we couldn't find what you are looking for." /> ); } -- cgit v1.2.3 From 63e7391981fca437efba221ff4babdb9d6fdac5b Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 13:47:50 -0700 Subject: Add portal layout component --- packages/website/ts/components/portal/portal.tsx | 67 +++++++++++++----------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index aa4392935..ce7911e10 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -105,6 +105,7 @@ const styles: Styles = { }, backButton: { height: BACK_BUTTON_HEIGHT, + paddingTop: 10, backgroundColor: colors.white, borderRadius: BACK_BUTTON_HEIGHT, boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, @@ -203,36 +204,17 @@ export class Portal extends React.Component<PortalProps, PortalState> { style={{ backgroundColor: colors.lightestGrey }} /> <div id="portal" style={styles.body}> - <div className="sm-flex flex-center"> - <div className="flex-last px3"> - <div style={styles.leftColumn}> - <Switch> - <Route - path={`${WebsitePaths.Portal}/:route`} - render={this._renderMenu.bind(this)} - /> - <Route - exact={true} - path={`${WebsitePaths.Portal}`} - render={this._renderWallet.bind(this)} - /> - </Switch> - </div> - </div> - <div className="flex-auto px3" style={styles.scrollContainer}> - <Switch> - <Route - path={`${WebsitePaths.Portal}/:route`} - render={this._renderAccountManagement.bind(this)} - /> - <Route - exact={true} - path={`${WebsitePaths.Portal}/`} - render={this._renderRelayerIndex.bind(this)} - /> - </Switch> - </div> - </div> + <Switch> + <Route + path={`${WebsitePaths.Portal}/:route`} + render={this._renderMenuAndAccountManagement.bind(this)} + /> + <Route + exact={true} + path={`${WebsitePaths.Portal}/`} + render={this._renderWalletAndRelayerIndex.bind(this)} + /> + </Switch> <BlockchainErrDialog blockchain={this._blockchain} blockchainErr={this.props.blockchainErr} @@ -271,6 +253,12 @@ export class Portal extends React.Component<PortalProps, PortalState> { </div> ); } + private _renderWalletAndRelayerIndex(): React.ReactNode { + return <PortalLayout left={this._renderWallet()} right={this._renderRelayerIndex()} />; + } + private _renderMenuAndAccountManagement(routeComponentProps: RouteComponentProps<any>): React.ReactNode { + return <PortalLayout left={this._renderMenu(routeComponentProps)} right={this._renderAccountManagement()} />; + } private _renderMenu(routeComponentProps: RouteComponentProps<any>): React.ReactNode { return ( <div> @@ -480,7 +468,7 @@ const BackButton = (props: BackButtonProps) => { return ( <div style={{ height: 65, paddingTop: 25 }}> <Link to={props.to} style={{ textDecoration: 'none' }}> - <div className="flex right" style={{ ...styles.backButton, paddingTop: 10 }}> + <div className="flex right" style={styles.backButton}> <div style={{ marginLeft: 12 }}> <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> </div> @@ -492,3 +480,20 @@ const BackButton = (props: BackButtonProps) => { </div> ); }; + +interface PortalLayoutProps { + left: React.ReactNode; + right: React.ReactNode; +} +const PortalLayout = (props: PortalLayoutProps) => { + return ( + <div className="sm-flex flex-center"> + <div className="flex-last px3"> + <div style={styles.leftColumn}>{props.left}</div> + </div> + <div className="flex-auto px3" style={styles.scrollContainer}> + {props.right} + </div> + </div> + ); +}; -- cgit v1.2.3 From 00515eb6f96c44387575fbae6f527c3661e84f43 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 16:47:04 -0700 Subject: Refactor a bunch of layouts into their own files --- .../website/ts/components/portal/back_button.tsx | 41 ++++ packages/website/ts/components/portal/menu.tsx | 88 +++++++++ packages/website/ts/components/portal/portal.tsx | 209 +++++++++------------ .../website/ts/components/portal/portal_menu.tsx | 88 --------- packages/website/ts/components/portal/section.tsx | 15 ++ .../website/ts/components/portal/text_header.tsx | 21 +++ .../ts/components/relayer_index/relayer_index.tsx | 19 +- 7 files changed, 259 insertions(+), 222 deletions(-) create mode 100644 packages/website/ts/components/portal/back_button.tsx create mode 100644 packages/website/ts/components/portal/menu.tsx delete mode 100644 packages/website/ts/components/portal/portal_menu.tsx create mode 100644 packages/website/ts/components/portal/section.tsx create mode 100644 packages/website/ts/components/portal/text_header.tsx diff --git a/packages/website/ts/components/portal/back_button.tsx b/packages/website/ts/components/portal/back_button.tsx new file mode 100644 index 000000000..68934f88e --- /dev/null +++ b/packages/website/ts/components/portal/back_button.tsx @@ -0,0 +1,41 @@ +import { colors, Styles } from '@0xproject/react-shared'; +import * as React from 'react'; +import { Link } from 'react-router-dom'; + +export interface BackButtonProps { + to: string; + labelText: string; +} + +const BACK_BUTTON_HEIGHT = 28; + +const styles: Styles = { + backButton: { + height: BACK_BUTTON_HEIGHT, + paddingTop: 10, + backgroundColor: colors.white, + borderRadius: BACK_BUTTON_HEIGHT, + boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, + }, + backButtonIcon: { + color: colors.mediumBlue, + fontSize: 20, + }, +}; + +export const BackButton = (props: BackButtonProps) => { + return ( + <div style={{ height: 65, paddingTop: 25 }}> + <Link to={props.to} style={{ textDecoration: 'none' }}> + <div className="flex right" style={styles.backButton}> + <div style={{ marginLeft: 12 }}> + <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> + </div> + <div style={{ marginLeft: 12, marginRight: 12 }}> + <div style={{ fontSize: 16, color: colors.lightGrey }}>{props.labelText}</div> + </div> + </div> + </Link> + </div> + ); +}; diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx new file mode 100644 index 000000000..9014d8d42 --- /dev/null +++ b/packages/website/ts/components/portal/menu.tsx @@ -0,0 +1,88 @@ +import { colors, Styles } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; +import { MenuItem } from 'ts/components/ui/menu_item'; +import { Environments, WebsitePaths } from 'ts/types'; +import { configs } from 'ts/utils/configs'; + +export interface MenuProps { + selectedPath?: string; +} + +interface MenuItemEntry { + to: string; + labelText: string; + iconName: string; +} + +const menuItemEntries: MenuItemEntry[] = [ + { + to: `${WebsitePaths.Portal}/account`, + labelText: 'Account overview', + iconName: 'zmdi-balance-wallet', + }, + { + to: `${WebsitePaths.Portal}/trades`, + labelText: 'Trade history', + iconName: 'zmdi-format-list-bulleted', + }, + { + to: `${WebsitePaths.Portal}/weth`, + labelText: 'Wrapped ETH', + iconName: 'zmdi-circle-o', + }, + { + to: `${WebsitePaths.Portal}/direct`, + labelText: 'Trade direct', + iconName: 'zmdi-swap', + }, +]; + +const DEFAULT_LABEL_COLOR = colors.darkerGrey; +const DEFAULT_ICON_COLOR = colors.darkerGrey; +const SELECTED_ICON_COLOR = colors.yellow900; + +const LEFT_PADDING = 185; + +export const Menu: React.StatelessComponent<MenuProps> = (props: MenuProps) => { + return ( + <div style={{ paddingLeft: LEFT_PADDING }}> + {_.map(menuItemEntries, entry => { + const selected = entry.to === props.selectedPath; + return ( + <MenuItem key={entry.to} className="py2" to={entry.to}> + <MenuItemLabel title={entry.labelText} iconName={entry.iconName} selected={selected} /> + </MenuItem> + ); + })} + </div> + ); +}; + +interface MenuItemLabelProps { + title: string; + iconName: string; + selected: boolean; +} +const MenuItemLabel: React.StatelessComponent<MenuItemLabelProps> = (props: MenuItemLabelProps) => { + const styles: Styles = { + iconStyle: { + color: props.selected ? SELECTED_ICON_COLOR : DEFAULT_ICON_COLOR, + fontSize: 20, + }, + textStyle: { + color: DEFAULT_LABEL_COLOR, + fontWeight: props.selected ? 'bold' : 'normal', + }, + }; + return ( + <div className="flex"> + <div className="pr1"> + <i style={styles.iconStyle} className={`zmdi ${props.iconName}`} /> + </div> + <div className="pl1" style={styles.textStyle}> + {props.title} + </div> + </div> + ); +}; diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index ce7911e10..81afe57e5 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -12,7 +12,10 @@ import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog'; import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog'; import { EthWrappers } from 'ts/components/eth_wrappers'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; -import { PortalMenu } from 'ts/components/portal/portal_menu'; +import { BackButton } from 'ts/components/portal/back_button'; +import { Menu } from 'ts/components/portal/menu'; +import { Section } from 'ts/components/portal/section'; +import { TextHeader } from 'ts/components/portal/text_header'; import { RelayerIndex } from 'ts/components/relayer_index/relayer_index'; import { TokenBalances } from 'ts/components/token_balances'; import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar'; @@ -79,7 +82,6 @@ enum TokenManagementState { const THROTTLE_TIMEOUT = 100; const TOP_BAR_HEIGHT = TopBar.heightForDisplayType(TopBarDisplayType.Expanded); -const BACK_BUTTON_HEIGHT = 28; const LEFT_COLUMN_WIDTH = 346; const styles: Styles = { @@ -99,21 +101,6 @@ const styles: Styles = { WebkitOverflowScrolling: 'touch', overflow: 'auto', }, - title: { - fontWeight: 'bold', - fontSize: 20, - }, - backButton: { - height: BACK_BUTTON_HEIGHT, - paddingTop: 10, - backgroundColor: colors.white, - borderRadius: BACK_BUTTON_HEIGHT, - boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, - }, - backButtonIcon: { - color: colors.mediumBlue, - fontSize: 20, - }, }; export class Portal extends React.Component<PortalProps, PortalState> { @@ -261,36 +248,38 @@ export class Portal extends React.Component<PortalProps, PortalState> { } private _renderMenu(routeComponentProps: RouteComponentProps<any>): React.ReactNode { return ( - <div> - <BackButton to={`${WebsitePaths.Portal}`} labelText="back to Relayers" /> - <PortalMenu selectedPath={routeComponentProps.location.pathname} /> - </div> + <Section + header={<BackButton to={`${WebsitePaths.Portal}`} labelText="back to Relayers" />} + body={<Menu selectedPath={routeComponentProps.location.pathname} />} + /> ); } private _renderWallet(): React.ReactNode { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( - <div> - <Title labelText="Your Account" /> - <Wallet - userAddress={this.props.userAddress} - networkId={this.props.networkId} - blockchain={this._blockchain} - blockchainIsLoaded={this.props.blockchainIsLoaded} - blockchainErr={this.props.blockchainErr} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={trackedTokens} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - injectedProviderName={this.props.injectedProviderName} - providerType={this.props.providerType} - onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} - onAddToken={this._onAddToken.bind(this)} - onRemoveToken={this._onRemoveToken.bind(this)} - /> - </div> + <Section + header={<TextHeader labelText="Your Account" />} + body={ + <Wallet + userAddress={this.props.userAddress} + networkId={this.props.networkId} + blockchain={this._blockchain} + blockchainIsLoaded={this.props.blockchainIsLoaded} + blockchainErr={this.props.blockchainErr} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + injectedProviderName={this.props.injectedProviderName} + providerType={this.props.providerType} + onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)} + onAddToken={this._onAddToken.bind(this)} + onRemoveToken={this._onRemoveToken.bind(this)} + /> + } + /> ); } private _renderAccountManagement(): React.ReactNode { @@ -318,72 +307,80 @@ export class Portal extends React.Component<PortalProps, PortalState> { } private _renderEthWrapper(): React.ReactNode { return ( - <div> - <Title labelText="Wrapped ETH" /> - <EthWrappers - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> - </div> + <Section + header={<TextHeader labelText="Wrapped ETH" />} + body={ + <EthWrappers + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + } + /> ); } private _renderTradeHistory(): React.ReactNode { return ( - <div> - <Title labelText="Trade History" /> - <TradeHistory - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - /> - </div> + <Section + header={<TextHeader labelText="Trade History" />} + body={ + <TradeHistory + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + networkId={this.props.networkId} + /> + } + /> ); } private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode { return ( - <div> - <Title labelText="Trade Direct" /> - <GenerateOrderForm - blockchain={this._blockchain} - hashData={this.props.hashData} - dispatcher={this.props.dispatcher} - /> - </div> + <Section + header={<TextHeader labelText="Trade Direct" />} + body={ + <GenerateOrderForm + blockchain={this._blockchain} + hashData={this.props.hashData} + dispatcher={this.props.dispatcher} + /> + } + /> ); } private _renderTokenBalances(): React.ReactNode { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( - <div> - <Title labelText="Your Account" /> - <TokenBalances - blockchain={this._blockchain} - blockchainErr={this.props.blockchainErr} - blockchainIsLoaded={this.props.blockchainIsLoaded} - dispatcher={this.props.dispatcher} - screenWidth={this.props.screenWidth} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={trackedTokens} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - networkId={this.props.networkId} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> - </div> + <Section + header={<TextHeader labelText="Your Account" />} + body={ + <TokenBalances + blockchain={this._blockchain} + blockchainErr={this.props.blockchainErr} + blockchainIsLoaded={this.props.blockchainIsLoaded} + dispatcher={this.props.dispatcher} + screenWidth={this.props.screenWidth} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + networkId={this.props.networkId} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + } + /> ); } private _renderRelayerIndex(): React.ReactNode { return ( - <div> - <Title labelText="Explore 0x Relayers" /> - <RelayerIndex networkId={this.props.networkId} /> - </div> + <Section + header={<TextHeader labelText="Explore 0x Relayers" />} + body={<RelayerIndex networkId={this.props.networkId} />} + /> ); } private _renderNotFoundMessage(): React.ReactNode { @@ -449,38 +446,6 @@ export class Portal extends React.Component<PortalProps, PortalState> { } } -interface TitleProps { - labelText: string; -} -const Title = (props: TitleProps) => { - return ( - <div className="py3" style={styles.title}> - {props.labelText} - </div> - ); -}; - -interface BackButtonProps { - to: string; - labelText: string; -} -const BackButton = (props: BackButtonProps) => { - return ( - <div style={{ height: 65, paddingTop: 25 }}> - <Link to={props.to} style={{ textDecoration: 'none' }}> - <div className="flex right" style={styles.backButton}> - <div style={{ marginLeft: 12 }}> - <i style={styles.backButtonIcon} className={`zmdi zmdi-arrow-left`} /> - </div> - <div style={{ marginLeft: 12, marginRight: 12 }}> - <div style={{ fontSize: 16, color: colors.lightGrey }}>{props.labelText}</div> - </div> - </div> - </Link> - </div> - ); -}; - interface PortalLayoutProps { left: React.ReactNode; right: React.ReactNode; @@ -496,4 +461,4 @@ const PortalLayout = (props: PortalLayoutProps) => { </div> </div> ); -}; +}; // tslint:disable:max-file-line-count diff --git a/packages/website/ts/components/portal/portal_menu.tsx b/packages/website/ts/components/portal/portal_menu.tsx deleted file mode 100644 index dc8f01d41..000000000 --- a/packages/website/ts/components/portal/portal_menu.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import { colors, Styles } from '@0xproject/react-shared'; -import * as _ from 'lodash'; -import * as React from 'react'; -import { MenuItem } from 'ts/components/ui/menu_item'; -import { Environments, WebsitePaths } from 'ts/types'; -import { configs } from 'ts/utils/configs'; - -export interface PortalMenuProps { - selectedPath?: string; -} - -interface MenuItemEntry { - to: string; - labelText: string; - iconName: string; -} - -const menuItemEntries: MenuItemEntry[] = [ - { - to: `${WebsitePaths.Portal}/account`, - labelText: 'Account overview', - iconName: 'zmdi-balance-wallet', - }, - { - to: `${WebsitePaths.Portal}/trades`, - labelText: 'Trade history', - iconName: 'zmdi-format-list-bulleted', - }, - { - to: `${WebsitePaths.Portal}/weth`, - labelText: 'Wrapped ETH', - iconName: 'zmdi-circle-o', - }, - { - to: `${WebsitePaths.Portal}/direct`, - labelText: 'Trade direct', - iconName: 'zmdi-swap', - }, -]; - -const DEFAULT_LABEL_COLOR = colors.darkerGrey; -const DEFAULT_ICON_COLOR = colors.darkerGrey; -const SELECTED_ICON_COLOR = colors.yellow900; - -const LEFT_PADDING = 185; - -export const PortalMenu: React.StatelessComponent<PortalMenuProps> = (props: PortalMenuProps) => { - return ( - <div style={{ paddingLeft: LEFT_PADDING }}> - {_.map(menuItemEntries, entry => { - const selected = entry.to === props.selectedPath; - return ( - <MenuItem key={entry.to} className="py2" to={entry.to}> - <PortalMenuItemLabel title={entry.labelText} iconName={entry.iconName} selected={selected} /> - </MenuItem> - ); - })} - </div> - ); -}; - -interface PortalMenuItemLabelProps { - title: string; - iconName: string; - selected: boolean; -} -const PortalMenuItemLabel: React.StatelessComponent<PortalMenuItemLabelProps> = (props: PortalMenuItemLabelProps) => { - const styles: Styles = { - iconStyle: { - color: props.selected ? SELECTED_ICON_COLOR : DEFAULT_ICON_COLOR, - fontSize: 20, - }, - textStyle: { - color: DEFAULT_LABEL_COLOR, - fontWeight: props.selected ? 'bold' : 'normal', - }, - }; - return ( - <div className="flex"> - <div className="pr1"> - <i style={styles.iconStyle} className={`zmdi ${props.iconName}`} /> - </div> - <div className="pl1" style={styles.textStyle}> - {props.title} - </div> - </div> - ); -}; diff --git a/packages/website/ts/components/portal/section.tsx b/packages/website/ts/components/portal/section.tsx new file mode 100644 index 000000000..9b172aae0 --- /dev/null +++ b/packages/website/ts/components/portal/section.tsx @@ -0,0 +1,15 @@ +import { Styles } from '@0xproject/react-shared'; +import * as React from 'react'; + +export interface SectionProps { + header: React.ReactNode; + body: React.ReactNode; +} +export const Section = (props: SectionProps) => { + return ( + <div className="flex flex-column" style={{ height: '100%' }}> + {props.header} + <div className="flex-auto">{props.body}</div> + </div> + ); +}; diff --git a/packages/website/ts/components/portal/text_header.tsx b/packages/website/ts/components/portal/text_header.tsx new file mode 100644 index 000000000..4aabd47d0 --- /dev/null +++ b/packages/website/ts/components/portal/text_header.tsx @@ -0,0 +1,21 @@ +import { Styles } from '@0xproject/react-shared'; +import * as React from 'react'; + +export interface TextHeaderProps { + labelText: string; +} + +const styles: Styles = { + title: { + fontWeight: 'bold', + fontSize: 20, + }, +}; + +export const TextHeader = (props: TextHeaderProps) => { + return ( + <div className="py3" style={styles.title}> + {props.labelText} + </div> + ); +}; diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index 5ab2e8c17..d8b06010b 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -60,18 +60,13 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde if (!readyToRender) { return ( // TODO: consolidate this loading component with the one in portal - <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"> - {_.isUndefined(this.state.error) ? ( - <CircularProgress size={40} thickness={5} /> - ) : ( - <Retry onRetry={this._fetchRelayerInfosAsync.bind(this)} /> - )} - </div> + <div style={styles.root}> + <div className="center"> + {_.isUndefined(this.state.error) ? ( + <CircularProgress size={40} thickness={5} /> + ) : ( + <Retry onRetry={this._fetchRelayerInfosAsync.bind(this)} /> + )} </div> </div> ); -- cgit v1.2.3 From 48b0b5481982b378277e517380cdd343773c7c64 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 17:23:39 -0700 Subject: Add loading component --- packages/website/ts/components/portal/loading.tsx | 21 +++++ packages/website/ts/components/portal/portal.tsx | 92 ++++++++++++---------- .../ts/components/relayer_index/relayer_index.tsx | 14 ++-- 3 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 packages/website/ts/components/portal/loading.tsx diff --git a/packages/website/ts/components/portal/loading.tsx b/packages/website/ts/components/portal/loading.tsx new file mode 100644 index 000000000..d804dd1b8 --- /dev/null +++ b/packages/website/ts/components/portal/loading.tsx @@ -0,0 +1,21 @@ +import CircularProgress from 'material-ui/CircularProgress'; +import * as React from 'react'; + +const CIRCULAR_PROGRESS_SIZE = 40; +const CIRCULAR_PROGRESS_THICKNESS = 5; + +export interface LoadingProps { + isLoading: boolean; + content: React.ReactNode; +} +export const Loading = (props: LoadingProps) => { + if (props.isLoading) { + return ( + <div className="center"> + <CircularProgress size={CIRCULAR_PROGRESS_SIZE} thickness={CIRCULAR_PROGRESS_THICKNESS} /> + </div> + ); + } else { + return <div>{props.content}</div>; + } +}; diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index 81afe57e5..bcb8e60ef 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -1,7 +1,6 @@ import { colors, Styles } from '@0xproject/react-shared'; import { BigNumber } from '@0xproject/utils'; import * as _ from 'lodash'; -import CircularProgress from 'material-ui/CircularProgress'; import * as React from 'react'; import * as DocumentTitle from 'react-document-title'; import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom'; @@ -13,6 +12,7 @@ import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_ import { EthWrappers } from 'ts/components/eth_wrappers'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; import { BackButton } from 'ts/components/portal/back_button'; +import { Loading } from 'ts/components/portal/loading'; import { Menu } from 'ts/components/portal/menu'; import { Section } from 'ts/components/portal/section'; import { TextHeader } from 'ts/components/portal/text_header'; @@ -283,7 +283,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); } private _renderAccountManagement(): React.ReactNode { - return this.props.blockchainIsLoaded ? ( + return ( <Switch> <Route path={`${WebsitePaths.Portal}/weth`} render={this._renderEthWrapper.bind(this)} /> <Route path={`${WebsitePaths.Portal}/account`} render={this._renderTokenBalances.bind(this)} /> @@ -291,18 +291,6 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Route path={`${WebsitePaths.Portal}/direct`} render={this._renderTradeDirect.bind(this)} /> <Route render={this._renderNotFoundMessage.bind(this)} /> </Switch> - ) : ( - // TODO: consolidate this loading component with the one in relayer_index - <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> - </div> ); } private _renderEthWrapper(): React.ReactNode { @@ -310,14 +298,19 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Section header={<TextHeader labelText="Wrapped ETH" />} body={ - <EthWrappers - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + <Loading + isLoading={!this.props.blockchainIsLoaded} + content={ + <EthWrappers + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + } /> } /> @@ -328,10 +321,15 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Section header={<TextHeader labelText="Trade History" />} body={ - <TradeHistory - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - networkId={this.props.networkId} + <Loading + isLoading={!this.props.blockchainIsLoaded} + content={ + <TradeHistory + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + networkId={this.props.networkId} + /> + } /> } /> @@ -342,10 +340,15 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Section header={<TextHeader labelText="Trade Direct" />} body={ - <GenerateOrderForm - blockchain={this._blockchain} - hashData={this.props.hashData} - dispatcher={this.props.dispatcher} + <Loading + isLoading={!this.props.blockchainIsLoaded} + content={ + <GenerateOrderForm + blockchain={this._blockchain} + hashData={this.props.hashData} + dispatcher={this.props.dispatcher} + /> + } /> } /> @@ -358,18 +361,23 @@ export class Portal extends React.Component<PortalProps, PortalState> { <Section header={<TextHeader labelText="Your Account" />} body={ - <TokenBalances - blockchain={this._blockchain} - blockchainErr={this.props.blockchainErr} - blockchainIsLoaded={this.props.blockchainIsLoaded} - dispatcher={this.props.dispatcher} - screenWidth={this.props.screenWidth} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={trackedTokens} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - networkId={this.props.networkId} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + <Loading + isLoading={!this.props.blockchainIsLoaded} + content={ + <TokenBalances + blockchain={this._blockchain} + blockchainErr={this.props.blockchainErr} + blockchainIsLoaded={this.props.blockchainIsLoaded} + dispatcher={this.props.dispatcher} + screenWidth={this.props.screenWidth} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + networkId={this.props.networkId} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} + /> + } /> } /> diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx index d8b06010b..b327c9817 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -60,14 +60,12 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde if (!readyToRender) { return ( // TODO: consolidate this loading component with the one in portal - <div style={styles.root}> - <div className="center"> - {_.isUndefined(this.state.error) ? ( - <CircularProgress size={40} thickness={5} /> - ) : ( - <Retry onRetry={this._fetchRelayerInfosAsync.bind(this)} /> - )} - </div> + <div className="center"> + {_.isUndefined(this.state.error) ? ( + <CircularProgress size={40} thickness={5} /> + ) : ( + <Retry onRetry={this._fetchRelayerInfosAsync.bind(this)} /> + )} </div> ); } else { -- cgit v1.2.3 From 3d4e03f2cd4cb2db3df535a2c95dd2e500fb6f6e Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 17:44:10 -0700 Subject: Refactor account management itmes --- packages/website/ts/components/portal/portal.tsx | 144 +++++++++++------------ 1 file changed, 70 insertions(+), 74 deletions(-) diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index bcb8e60ef..d9d50c5ab 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -74,6 +74,12 @@ interface PortalState { tokenManagementState: TokenManagementState; } +interface AccountManagementItem { + pathName: string; + headerText: string; + render: () => React.ReactNode; +} + enum TokenManagementState { Add = 'Add', Remove = 'Remove', @@ -95,6 +101,7 @@ const styles: Styles = { }, leftColumn: { width: LEFT_COLUMN_WIDTH, + height: '100%', }, scrollContainer: { height: `calc(100vh - ${TOP_BAR_HEIGHT}px)`, @@ -241,7 +248,7 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); } private _renderWalletAndRelayerIndex(): React.ReactNode { - return <PortalLayout left={this._renderWallet()} right={this._renderRelayerIndex()} />; + return <PortalLayout left={this._renderWallet()} right={this._renderRelayerIndexSection()} />; } private _renderMenuAndAccountManagement(routeComponentProps: RouteComponentProps<any>): React.ReactNode { return <PortalLayout left={this._renderMenu(routeComponentProps)} right={this._renderAccountManagement()} />; @@ -283,74 +290,73 @@ export class Portal extends React.Component<PortalProps, PortalState> { ); } private _renderAccountManagement(): React.ReactNode { + const accountManagementItems: AccountManagementItem[] = [ + { + pathName: `${WebsitePaths.Portal}/weth`, + headerText: 'Wrapped ETH', + render: this._renderEthWrapper.bind(this), + }, + { + pathName: `${WebsitePaths.Portal}/account`, + headerText: 'Your Account', + render: this._renderTokenBalances.bind(this), + }, + { + pathName: `${WebsitePaths.Portal}/trades`, + headerText: 'Trade History', + render: this._renderTradeHistory.bind(this), + }, + { + pathName: `${WebsitePaths.Portal}/direct`, + headerText: 'Trade Direct', + render: this._renderTradeDirect.bind(this), + }, + ]; return ( <Switch> - <Route path={`${WebsitePaths.Portal}/weth`} render={this._renderEthWrapper.bind(this)} /> - <Route path={`${WebsitePaths.Portal}/account`} render={this._renderTokenBalances.bind(this)} /> - <Route path={`${WebsitePaths.Portal}/trades`} render={this._renderTradeHistory.bind(this)} /> - <Route path={`${WebsitePaths.Portal}/direct`} render={this._renderTradeDirect.bind(this)} /> + {_.map(accountManagementItems, item => { + return <Route path={item.pathName} render={this._renderAccountManagementItem.bind(this, item)} />; + })}} <Route render={this._renderNotFoundMessage.bind(this)} /> </Switch> ); } - private _renderEthWrapper(): React.ReactNode { + private _renderAccountManagementItem(item: AccountManagementItem): React.ReactNode { return ( <Section - header={<TextHeader labelText="Wrapped ETH" />} - body={ - <Loading - isLoading={!this.props.blockchainIsLoaded} - content={ - <EthWrappers - networkId={this.props.networkId} - blockchain={this._blockchain} - dispatcher={this.props.dispatcher} - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> - } - /> - } + header={<TextHeader labelText={item.headerText} />} + body={<Loading isLoading={!this.props.blockchainIsLoaded} content={item.render()} />} + /> + ); + } + private _renderEthWrapper(): React.ReactNode { + return ( + <EthWrappers + networkId={this.props.networkId} + blockchain={this._blockchain} + dispatcher={this.props.dispatcher} + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> ); } private _renderTradeHistory(): React.ReactNode { return ( - <Section - header={<TextHeader labelText="Trade History" />} - body={ - <Loading - isLoading={!this.props.blockchainIsLoaded} - content={ - <TradeHistory - tokenByAddress={this.props.tokenByAddress} - userAddress={this.props.userAddress} - networkId={this.props.networkId} - /> - } - /> - } + <TradeHistory + tokenByAddress={this.props.tokenByAddress} + userAddress={this.props.userAddress} + networkId={this.props.networkId} /> ); } private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode { return ( - <Section - header={<TextHeader labelText="Trade Direct" />} - body={ - <Loading - isLoading={!this.props.blockchainIsLoaded} - content={ - <GenerateOrderForm - blockchain={this._blockchain} - hashData={this.props.hashData} - dispatcher={this.props.dispatcher} - /> - } - /> - } + <GenerateOrderForm + blockchain={this._blockchain} + hashData={this.props.hashData} + dispatcher={this.props.dispatcher} /> ); } @@ -358,32 +364,22 @@ export class Portal extends React.Component<PortalProps, PortalState> { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); return ( - <Section - header={<TextHeader labelText="Your Account" />} - body={ - <Loading - isLoading={!this.props.blockchainIsLoaded} - content={ - <TokenBalances - blockchain={this._blockchain} - blockchainErr={this.props.blockchainErr} - blockchainIsLoaded={this.props.blockchainIsLoaded} - dispatcher={this.props.dispatcher} - screenWidth={this.props.screenWidth} - tokenByAddress={this.props.tokenByAddress} - trackedTokens={trackedTokens} - userAddress={this.props.userAddress} - userEtherBalanceInWei={this.props.userEtherBalanceInWei} - networkId={this.props.networkId} - lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} - /> - } - /> - } + <TokenBalances + blockchain={this._blockchain} + blockchainErr={this.props.blockchainErr} + blockchainIsLoaded={this.props.blockchainIsLoaded} + dispatcher={this.props.dispatcher} + screenWidth={this.props.screenWidth} + tokenByAddress={this.props.tokenByAddress} + trackedTokens={trackedTokens} + userAddress={this.props.userAddress} + userEtherBalanceInWei={this.props.userEtherBalanceInWei} + networkId={this.props.networkId} + lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch} /> ); } - private _renderRelayerIndex(): React.ReactNode { + private _renderRelayerIndexSection(): React.ReactNode { return ( <Section header={<TextHeader labelText="Explore 0x Relayers" />} -- cgit v1.2.3 From 6b1a91160476205b6c2f0462d3a9d64ddcf20098 Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Wed, 16 May 2018 18:16:27 -0700 Subject: Fix spread --- packages/website/ts/pages/fullscreen_message.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/website/ts/pages/fullscreen_message.tsx b/packages/website/ts/pages/fullscreen_message.tsx index 141fb38a4..6fcf7b32c 100644 --- a/packages/website/ts/pages/fullscreen_message.tsx +++ b/packages/website/ts/pages/fullscreen_message.tsx @@ -18,7 +18,7 @@ export const FullscreenMessage = (props: FullscreenMessageProps) => { <div className="center py4"> <div className="py4"> <div className="py4"> - <h1 style={{ ...styles.thin }}>{props.headerText}</h1> + <h1 style={styles.thin}>{props.headerText}</h1> <div className="py1"> <div className="py3">{props.bodyText}</div> </div> -- cgit v1.2.3 From 943b7d39c685345b00b38ed8a50b7adcffc24f9e Mon Sep 17 00:00:00 2001 From: Brandon Millman <brandon.millman@gmail.com> Date: Thu, 17 May 2018 10:57:03 -0700 Subject: Fix tslint false positive --- packages/website/ts/components/wallet/wallet.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 818cff05b..75dbd12e9 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -136,6 +136,10 @@ const styles: Styles = { overflow: 'auto', WebkitOverflowScrolling: 'touch', }, + manageYourWalletText: { + color: colors.mediumBlue, + fontWeight: 'bold', + }, }; const ETHER_ICON_PATH = '/images/ether.png'; @@ -312,9 +316,12 @@ export class Wallet extends React.Component<WalletProps, WalletState> { <Link to={`${WebsitePaths.Portal}/account`} style={{ textDecoration: 'none' }}> <ListItem primaryText={ - <div className="flex right" style={{ color: colors.mediumBlue, fontWeight: 'bold' }}> + <div className="flex right" style={styles.manageYourWalletText}> {'manage your wallet'} - </div>} + </div> + // https://github.com/palantir/tslint-react/issues/140 + // tslint:disable-next-line:jsx-curly-spacing + } style={{ ...styles.paddedItem, ...styles.borderedItem }} /> </Link> -- cgit v1.2.3