From b55ba3a31823699fa2460fad6fd22b913c38c946 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 1 Nov 2018 13:10:51 -0700 Subject: feat: add states to the erc20 input for no assets or only 1 asset --- packages/instant/public/index.html | 6 ++-- .../src/components/erc20_asset_amount_input.tsx | 32 ++++++++++++++++++---- .../src/components/erc20_token_selector.tsx | 4 ++- .../instant/src/components/zero_ex_instant.tsx | 6 +++- .../containers/available_erc20_token_selector.ts | 2 +- .../selected_erc20_asset_amount_input.ts | 20 +++++++------- packages/instant/src/redux/reducer.ts | 4 +-- 7 files changed, 50 insertions(+), 24 deletions(-) diff --git a/packages/instant/public/index.html b/packages/instant/public/index.html index 74975678a..1c08aa5a1 100644 --- a/packages/instant/public/index.html +++ b/packages/instant/public/index.html @@ -59,13 +59,13 @@ assetData: '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498', } const orderSourceOverride = queryParams.getQueryParamValue('orderSource'); + const availableAssetDatasString = queryParams.getQueryParamValue('availableAssetDatas'); const renderOptionsOverrides = { orderSource: orderSourceOverride === 'provided' ? [providedOrder] : orderSourceOverride, - assetData: queryParams.getQueryParamValue('assetData'), networkId: +queryParams.getQueryParamValue('networkId') || undefined, defaultAssetBuyAmount: +queryParams.getQueryParamValue('defaultAssetBuyAmount') || undefined, - availableAssetIdentifiers: JSON.parse(queryParams.getQueryParamValue('availableAssetIdentifiers') || '[]'), - defaultSelectedAssetIdentifier: queryParams.getQueryParamValue('defaultSelectedAssetIdentifier'), + availableAssetDatas: availableAssetDatasString ? JSON.parse(availableAssetDatasString) : undefined, + defaultSelectedAssetData: queryParams.getQueryParamValue('defaultSelectedAssetData'), } const renderOptions = Object.assign({}, renderOptionsDefaults, removeUndefined(renderOptionsOverrides)); zeroExInstant.render(renderOptions); diff --git a/packages/instant/src/components/erc20_asset_amount_input.tsx b/packages/instant/src/components/erc20_asset_amount_input.tsx index b1fec6405..e222bc576 100644 --- a/packages/instant/src/components/erc20_asset_amount_input.tsx +++ b/packages/instant/src/components/erc20_asset_amount_input.tsx @@ -19,6 +19,7 @@ export interface ERC20AssetAmountInputProps { startingFontSizePx: number; fontColor?: ColorOption; isDisabled: boolean; + numberOfAssetsAvailable?: number; } export interface ERC20AssetAmountInputState { @@ -47,6 +48,7 @@ export class ERC20AssetAmountInput extends React.Component { const { onChange, ...rest } = this.props; const amountBorderBottom = this.props.isDisabled ? '' : `1px solid ${transparentWhite}`; + const onSymbolClick = this._generateSelectAssetClick(); return ( @@ -59,7 +61,6 @@ export class ERC20AssetAmountInput extends React.Component {assetUtils.formattedSymbolForAsset(asset)} @@ -80,6 +81,13 @@ export class ERC20AssetAmountInput extends React.Component { + const { numberOfAssetsAvailable } = this.props; + let text = 'Select Token'; + if (_.isUndefined(numberOfAssetsAvailable)) { + text = '...Loading'; + } else if (numberOfAssetsAvailable === 0) { + text = 'Assets Unavailable'; + } return ( - Select Token + {text} {this._renderChevronIcon()} ); }; private readonly _renderChevronIcon = (): React.ReactNode => { + const { numberOfAssetsAvailable } = this.props; + if (_.isUndefined(numberOfAssetsAvailable) || numberOfAssetsAvailable <= 1) { + return null; + } return ( - + ); @@ -110,7 +122,15 @@ export class ERC20AssetAmountInput extends React.Component { + // We don't want to allow opening the token selection panel if there are no assets. + private readonly _generateSelectAssetClick = (): (() => void) | undefined => { + const { numberOfAssetsAvailable } = this.props; + if (_.isUndefined(numberOfAssetsAvailable) || numberOfAssetsAvailable <= 1) { + return undefined; + } + return this._handleSelectAssetClick; + }; + private readonly _handleSelectAssetClick = () => { if (this.props.onSelectAssetClick) { this.props.onSelectAssetClick(this.props.asset); } diff --git a/packages/instant/src/components/erc20_token_selector.tsx b/packages/instant/src/components/erc20_token_selector.tsx index a98176e9b..12051b382 100644 --- a/packages/instant/src/components/erc20_token_selector.tsx +++ b/packages/instant/src/components/erc20_token_selector.tsx @@ -11,7 +11,9 @@ export interface ERC20TokenSelectorProps { } export const ERC20TokenSelector: React.StatelessComponent = ({ tokens, onTokenSelect }) => ( - {_.map(tokens, token => )} + + {_.map(tokens, token => )} + ); interface TokenSelectorRowProps { diff --git a/packages/instant/src/components/zero_ex_instant.tsx b/packages/instant/src/components/zero_ex_instant.tsx index ab6350010..e49001d12 100644 --- a/packages/instant/src/components/zero_ex_instant.tsx +++ b/packages/instant/src/components/zero_ex_instant.tsx @@ -37,6 +37,7 @@ export interface ZeroExInstantOptionalProps { export class ZeroExInstant extends React.Component { private readonly _store: Store; + // TODO(fragosti): Write tests for this beast once we inject a provider. private static _mergeInitialStateWithProps(props: ZeroExInstantProps, state: State = INITIAL_STATE): State { const networkId = props.networkId || state.network; // TODO: Provider needs to not be hard-coded to injected web3. @@ -72,6 +73,9 @@ export class ZeroExInstant extends React.Component { selectedAssetAmount: _.isUndefined(props.defaultAssetBuyAmount) ? state.selectedAssetAmount : new BigNumberInput(props.defaultAssetBuyAmount), + availableAssets: _.isUndefined(props.availableAssetDatas) + ? undefined + : assetUtils.createAssetsFromAssetDatas(props.availableAssetDatas, completeAssetMetaDataMap, networkId), assetMetaDataMap: completeAssetMetaDataMap, }; return storeStateFromProps; @@ -87,7 +91,7 @@ export class ZeroExInstant extends React.Component { // tslint:disable-next-line:no-floating-promises asyncData.fetchEthPriceAndDispatchToStore(this._store); // fetch available assets if none are specified - if (_.isEmpty(state.availableAssets)) { + if (_.isUndefined(state.availableAssets)) { // tslint:disable-next-line:no-floating-promises asyncData.fetchAvailableAssetDatasAndDispatchToStore(this._store); } diff --git a/packages/instant/src/containers/available_erc20_token_selector.ts b/packages/instant/src/containers/available_erc20_token_selector.ts index 6b5ecb6ac..e8bacdba0 100644 --- a/packages/instant/src/containers/available_erc20_token_selector.ts +++ b/packages/instant/src/containers/available_erc20_token_selector.ts @@ -20,7 +20,7 @@ interface ConnectedDispatch { } const mapStateToProps = (state: State, _ownProps: AvailableERC20TokenSelectorProps): ConnectedState => ({ - tokens: assetUtils.getERC20AssetsFromAssets(state.availableAssets), + tokens: assetUtils.getERC20AssetsFromAssets(state.availableAssets || []), }); const mapDispatchToProps = ( diff --git a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts index 217d603d2..64b6f4b3b 100644 --- a/packages/instant/src/containers/selected_erc20_asset_amount_input.ts +++ b/packages/instant/src/containers/selected_erc20_asset_amount_input.ts @@ -27,6 +27,7 @@ interface ConnectedState { value?: BigNumberInput; asset?: ERC20Asset; isDisabled: boolean; + numberOfAssetsAvailable?: number; } interface ConnectedDispatch { @@ -38,6 +39,7 @@ interface ConnectedProps { asset?: ERC20Asset; onChange: (value?: BigNumberInput, asset?: ERC20Asset) => void; isDisabled: boolean; + numberOfAssetsAvailable?: number; } type FinalProps = ConnectedProps & SelectedERC20AssetAmountInputProps; @@ -46,20 +48,17 @@ const mapStateToProps = (state: State, _ownProps: SelectedERC20AssetAmountInputP const processState = state.buyOrderState.processState; const isEnabled = processState === OrderProcessState.NONE || processState === OrderProcessState.FAILURE; const isDisabled = !isEnabled; - - const selectedAsset = state.selectedAsset; - if (_.isUndefined(selectedAsset) || selectedAsset.metaData.assetProxyId !== AssetProxyId.ERC20) { - return { - value: state.selectedAssetAmount, - isDisabled, - }; - } - + const selectedAsset = + !_.isUndefined(state.selectedAsset) && state.selectedAsset.metaData.assetProxyId === AssetProxyId.ERC20 + ? (state.selectedAsset as ERC20Asset) + : undefined; + const numberOfAssetsAvailable = _.isUndefined(state.availableAssets) ? undefined : state.availableAssets.length; return { assetBuyer: state.assetBuyer, value: state.selectedAssetAmount, - asset: selectedAsset as ERC20Asset, + asset: selectedAsset, isDisabled, + numberOfAssetsAvailable, }; }; @@ -138,6 +137,7 @@ const mergeProps = ( connectedDispatch.updateBuyQuote(connectedState.assetBuyer, value, asset); }, isDisabled: connectedState.isDisabled, + numberOfAssetsAvailable: connectedState.numberOfAssetsAvailable, }; }; diff --git a/packages/instant/src/redux/reducer.ts b/packages/instant/src/redux/reducer.ts index 57d95167a..20d927561 100644 --- a/packages/instant/src/redux/reducer.ts +++ b/packages/instant/src/redux/reducer.ts @@ -23,7 +23,7 @@ export interface State { assetBuyer?: AssetBuyer; assetMetaDataMap: ObjectMap; selectedAsset?: Asset; - availableAssets: Asset[]; + availableAssets?: Asset[]; selectedAssetAmount?: BigNumberInput; buyOrderState: OrderState; ethUsdPrice?: BigNumber; @@ -36,7 +36,7 @@ export interface State { export const INITIAL_STATE: State = { network: Network.Mainnet, selectedAssetAmount: undefined, - availableAssets: [], + availableAssets: undefined, assetMetaDataMap, buyOrderState: { processState: OrderProcessState.NONE }, ethUsdPrice: undefined, -- cgit v1.2.3