From 00515eb6f96c44387575fbae6f527c3661e84f43 Mon Sep 17 00:00:00 2001 From: Brandon Millman 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 ( +
+ +
+
+ +
+
+
{props.labelText}
+
+
+ +
+ ); +}; 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 = (props: MenuProps) => { + return ( +
+ {_.map(menuItemEntries, entry => { + const selected = entry.to === props.selectedPath; + return ( + + + + ); + })} +
+ ); +}; + +interface MenuItemLabelProps { + title: string; + iconName: string; + selected: boolean; +} +const MenuItemLabel: React.StatelessComponent = (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 ( +
+
+ +
+
+ {props.title} +
+
+ ); +}; 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 { @@ -261,36 +248,38 @@ export class Portal extends React.Component { } private _renderMenu(routeComponentProps: RouteComponentProps): React.ReactNode { return ( -
- - -
+
} + body={} + /> ); } private _renderWallet(): React.ReactNode { 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> + <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