-
Notifications
You must be signed in to change notification settings - Fork 465
[instant] Asset buyer errors #1142
Changes from all commits
18c9907
f36352b
db77cd1
1d07949
dfc5d7d
d46b288
187bbc7
32fa1bc
d052342
155858d
2b495a7
ae4f1a0
f2f7598
7b43cd1
6cf8d57
01b98c3
1d38b75
6ea386a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import * as React from 'react'; | ||
|
||
import { keyframes, styled } from '../../style/theme'; | ||
|
||
const slideKeyframeGenerator = (fromY: string, toY: string) => keyframes` | ||
from { | ||
position: relative; | ||
top: ${fromY}; | ||
} | ||
|
||
to { | ||
position: relative; | ||
top: ${toY}; | ||
} | ||
`; | ||
|
||
export interface SlideAnimationProps { | ||
keyframes: string; | ||
animationType: string; | ||
animationDirection?: string; | ||
} | ||
|
||
export const SlideAnimation = | ||
styled.div < | ||
SlideAnimationProps > | ||
` | ||
animation-name: ${props => props.keyframes}; | ||
animation-duration: 0.3s; | ||
animation-timing-function: ${props => props.animationType}; | ||
animation-delay: 0s; | ||
animation-iteration-count: 1; | ||
animation-fill-mode: ${props => props.animationDirection || 'none'}; | ||
position: relative; | ||
`; | ||
|
||
export interface SlideAnimationComponentProps { | ||
downY: string; | ||
} | ||
|
||
export const SlideUpAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => ( | ||
<SlideAnimation animationType="ease-in" keyframes={slideKeyframeGenerator(props.downY, '0px')}> | ||
{props.children} | ||
</SlideAnimation> | ||
); | ||
|
||
export const SlideDownAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => ( | ||
<SlideAnimation | ||
animationDirection="forwards" | ||
animationType="cubic-bezier(0.25, 0.1, 0.25, 1)" | ||
keyframes={slideKeyframeGenerator('0px', props.downY)} | ||
> | ||
{props.children} | ||
</SlideAnimation> | ||
); |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import * as React from 'react'; | |
|
||
import { SelectedAssetAmountInput } from '../containers/selected_asset_amount_input'; | ||
import { ColorOption } from '../style/theme'; | ||
import { AsyncProcessState } from '../types'; | ||
import { format } from '../util/format'; | ||
|
||
import { Container, Flex, Text } from './ui'; | ||
|
@@ -12,20 +13,45 @@ export interface InstantHeadingProps { | |
selectedAssetAmount?: BigNumber; | ||
totalEthBaseAmount?: BigNumber; | ||
ethUsdPrice?: BigNumber; | ||
quoteState: AsyncProcessState; | ||
} | ||
|
||
const displaytotalEthBaseAmount = ({ selectedAssetAmount, totalEthBaseAmount }: InstantHeadingProps): string => { | ||
const Placeholder = () => ( | ||
<Text fontWeight="bold" fontColor={ColorOption.white}> | ||
— | ||
</Text> | ||
); | ||
const displaytotalEthBaseAmount = ({ | ||
selectedAssetAmount, | ||
totalEthBaseAmount, | ||
}: InstantHeadingProps): React.ReactNode => { | ||
if (_.isUndefined(selectedAssetAmount)) { | ||
return '0 ETH'; | ||
} | ||
return format.ethBaseAmount(totalEthBaseAmount, 4, '...loading'); | ||
return format.ethBaseAmount(totalEthBaseAmount, 4, <Placeholder />); | ||
}; | ||
|
||
const displayUsdAmount = ({ totalEthBaseAmount, selectedAssetAmount, ethUsdPrice }: InstantHeadingProps): string => { | ||
const displayUsdAmount = ({ | ||
totalEthBaseAmount, | ||
selectedAssetAmount, | ||
ethUsdPrice, | ||
}: InstantHeadingProps): React.ReactNode => { | ||
if (_.isUndefined(selectedAssetAmount)) { | ||
return '$0.00'; | ||
} | ||
return format.ethBaseAmountInUsd(totalEthBaseAmount, ethUsdPrice, 2, '...loading'); | ||
return format.ethBaseAmountInUsd(totalEthBaseAmount, ethUsdPrice, 2, <Placeholder />); | ||
}; | ||
|
||
const loadingOrAmount = (quoteState: AsyncProcessState, amount: React.ReactNode): React.ReactNode => { | ||
if (quoteState === AsyncProcessState.PENDING) { | ||
return ( | ||
<Text fontWeight="bold" fontColor={ColorOption.white}> | ||
…loading | ||
</Text> | ||
); | ||
} else { | ||
return amount; | ||
} | ||
}; | ||
|
||
export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = props => ( | ||
|
@@ -47,11 +73,11 @@ export const InstantHeading: React.StatelessComponent<InstantHeadingProps> = pro | |
<Flex direction="column" justify="space-between"> | ||
<Container marginBottom="5px"> | ||
<Text fontSize="16px" fontColor={ColorOption.white} fontWeight={500}> | ||
{displaytotalEthBaseAmount(props)} | ||
{loadingOrAmount(props.quoteState, displaytotalEthBaseAmount(props))} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feels kind of weird to have two nested There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call -- yes, will fix |
||
</Text> | ||
</Container> | ||
<Text fontSize="16px" fontColor={ColorOption.white} opacity={0.7}> | ||
{displayUsdAmount(props)} | ||
{loadingOrAmount(props.quoteState, displayUsdAmount(props))} | ||
</Text> | ||
</Flex> | ||
</Flex> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import * as React from 'react'; | ||
|
||
import { LatestBuyQuoteOrderDetails } from '../containers/latest_buy_quote_order_details'; | ||
import { LatestError } from '../containers/latest_error'; | ||
import { SelectedAssetBuyButton } from '../containers/selected_asset_buy_button'; | ||
import { SelectedAssetInstantHeading } from '../containers/selected_asset_instant_heading'; | ||
|
||
|
@@ -12,6 +13,9 @@ export interface ZeroExInstantContainerProps {} | |
|
||
export const ZeroExInstantContainer: React.StatelessComponent<ZeroExInstantContainerProps> = props => ( | ||
<Container width="350px"> | ||
<Container zIndex={1} position="relative"> | ||
<LatestError /> | ||
</Container> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 |
||
<Container | ||
zIndex={2} | ||
position="relative" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import * as React from 'react'; | ||
|
||
import { connect } from 'react-redux'; | ||
|
||
import { SlidingError } from '../components/sliding_error'; | ||
import { LatestErrorDisplay, State } from '../redux/reducer'; | ||
import { errorUtil } from '../util/error'; | ||
|
||
export interface LatestErrorComponentProps { | ||
assetData?: string; | ||
latestError?: any; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per convo w/ @fragosti , we explored two options:
After discussing, I went with option 2 for the drawbacks listed in option 1. Open to feedback though. |
||
slidingDirection: 'down' | 'up'; | ||
} | ||
|
||
export const LatestErrorComponent: React.StatelessComponent<LatestErrorComponentProps> = props => { | ||
if (!props.latestError) { | ||
return <div />; | ||
} | ||
const { icon, message } = errorUtil.errorDescription(props.latestError, props.assetData); | ||
return <SlidingError direction={props.slidingDirection} icon={icon} message={message} />; | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A convention I'm trying to follow is to not have any Component code in these container files, they simply connect a pure presentational component to the redux store and do any state -> prop mapping. Seems like you don't need this component to me?
The only thing is not rendering when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the idea of getting rid of this component, but I think we need the custom "not render when latestError is undefined" logic. Some thoughts:
I may be missing something though, let me know if there is an alternative approach in which we could get rid of this component. If you agree we need to keep the component, I understand the convention and pattern of separating presentational and container components, but in this case it seems overboard IMHO: this component is extremely simple and it's highly unlikely it'd be used anywhere else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could change it so that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per slack convo, decided to leave as-is and address later if needed |
||
|
||
interface ConnectedState { | ||
assetData?: string; | ||
latestError?: any; | ||
slidingDirection: 'down' | 'up'; | ||
} | ||
export interface LatestErrorProps {} | ||
const mapStateToProps = (state: State, _ownProps: LatestErrorProps): ConnectedState => ({ | ||
assetData: state.selectedAssetData, | ||
latestError: state.latestError, | ||
slidingDirection: state.latestErrorDisplay === LatestErrorDisplay.Present ? 'up' : 'down', | ||
}); | ||
|
||
export const LatestError = connect(mapStateToProps)(LatestErrorComponent); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think this should be called
quoteRequestState
.quote
is data, and it doesn't make sense to me for it to have state.