Skip to content

Commit

Permalink
Merge pull request #141 from oasisprotocol/mz/blockDetails
Browse files Browse the repository at this point in the history
Design Feedback: Block details #2
  • Loading branch information
buberdds authored Feb 17, 2023
2 parents f02927c + ea1c7a7 commit d92e3a8
Show file tree
Hide file tree
Showing 14 changed files with 170 additions and 105 deletions.
107 changes: 57 additions & 50 deletions src/app/components/Account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { StyledDescriptionList } from '../../components/StyledDescriptionList'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { JazzIcon } from '../../components/JazzIcon'
import { CoinGeckoReferral } from '../../components/CoinGeckoReferral'
import { TextSkeleton } from '../../components/Skeleton'
import { trimLongString } from '../../utils/trimLongString'
import {
type Account as AccountDetailsProps,
Expand All @@ -35,7 +36,8 @@ const StyledBox = styled(Box)(() => ({
}))

type AccountProps = {
account: AccountDetailsProps
account?: AccountDetailsProps
isLoading: boolean
roseFiatValue?: number
}

Expand All @@ -44,65 +46,70 @@ const getChainBalance = (runtime: string, balance?: RuntimeSdkBalance[]) => {
return chainBalance?.balance || '0'
}

export const Account: FC<AccountProps> = ({ account, roseFiatValue }) => {
export const Account: FC<AccountProps> = ({ account, isLoading, roseFiatValue }) => {
const { t } = useTranslation()
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
const balance = getChainBalance(RuntimeName.emerald, account.runtime_sdk_balances)
const balance = account && getChainBalance(RuntimeName.emerald, account.runtime_sdk_balances)

return (
<StyledDescriptionList titleWidth={isMobile ? '100px' : '200px'}>
<dt>
<JazzIcon diameter={isMobile ? 30 : 40} seed={addressToNumber(account.address)} />
</dt>
<dd>
<CopyToClipboard
label={
<Typography component="span" sx={{ color: COLORS.brandDark, fontWeight: 700 }}>
{isMobile ? trimLongString(account.address) : account.address}
</Typography>
}
value={account.address}
/>
</dd>

<dt>{t('account.chain')}</dt>
<dd>{t('common.emerald')}</dd>

<dt>{t('common.balance')}</dt>
<dd>{t('common.valueInRose', { value: balance })}</dd>
{roseFiatValue && (
<>
<dt>{t('common.fiatValue')}</dt>
<>
{isLoading && <TextSkeleton numberOfRows={8} />}
{account && (
<StyledDescriptionList titleWidth={isMobile ? '100px' : '200px'}>
<dt>
<JazzIcon diameter={isMobile ? 30 : 40} seed={addressToNumber(account.address)} />
</dt>
<dd>
<StyledBox>
{t('common.fiatValueInUSD', {
value: parseFloat(balance) * roseFiatValue,
formatParams: {
value: {
currency: 'USD',
} satisfies Intl.NumberFormatOptions,
},
})}
<CoinGeckoReferral />
</StyledBox>
<CopyToClipboard
label={
<Typography component="span" sx={{ color: COLORS.brandDark, fontWeight: 700 }}>
{isMobile ? trimLongString(account.address) : account.address}
</Typography>
}
value={account.address}
/>
</dd>
</>
)}

<dt>{t('common.transactions')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>
<dt>{t('account.chain')}</dt>
<dd>{t('common.emerald')}</dd>

<dt>{t('common.balance')}</dt>
<dd>{t('common.valueInRose', { value: balance })}</dd>
{roseFiatValue && balance && (
<>
<dt>{t('common.fiatValue')}</dt>
<dd>
<StyledBox>
{t('common.fiatValueInUSD', {
value: parseFloat(balance) * roseFiatValue,
formatParams: {
value: {
currency: 'USD',
} satisfies Intl.NumberFormatOptions,
},
})}
<CoinGeckoReferral />
</StyledBox>
</dd>
</>
)}

<dt>{t('account.evmTokens')}</dt>
<dd>
<TokenPills tokens={account.runtime_evm_balances} />
</dd>
<dt>{t('common.transactions')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>

<dt>{t('account.totalReceived')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>
<dt>{t('account.evmTokens')}</dt>
<dd>
<TokenPills tokens={account.runtime_evm_balances} />
</dd>

<dt>{t('account.totalSent')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>
</StyledDescriptionList>
<dt>{t('account.totalReceived')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>

<dt>{t('account.totalSent')}</dt>
<dd>{/* TODO: waiting for API update */}</dd>
</StyledDescriptionList>
)}
</>
)
}
4 changes: 1 addition & 3 deletions src/app/components/Blocks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { VerticalProgressBar } from '../../components/ProgressBar'
import { Table, TableCellAlign, TableColProps } from '../../components/Table'
import { TrimLinkLabel } from '../../components/TrimLinkLabel'
import { RouteUtils } from '../../utils/route-utils'
import { ParaTime } from '../../../config'
import { ParaTime, gasLimit } from '../../../config'
import { TablePaginationProps } from '../Table/TablePagination'

export type TableRuntimeBlock = RuntimeBlock & {
Expand All @@ -26,8 +26,6 @@ type BlocksProps = {
pagination: false | TablePaginationProps
}

const gasLimit = 10000000 // TODO temporary value, 22020096 for consensus

export const Blocks = (props: BlocksProps) => {
const { isLoading, blocks, verbose, pagination, limit } = props
const { t } = useTranslation()
Expand Down
12 changes: 10 additions & 2 deletions src/app/components/CoinGeckoReferral/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ import { Trans, useTranslation } from 'react-i18next'
import Typography from '@mui/material/Typography'
import Link from '@mui/material/Link'
import { referrals } from '../../utils/externalLinks'
import { COLORS } from '../../../styles/theme/colors'

export const CoinGeckoReferral: FC = () => {
const { t } = useTranslation()

return (
<Typography component="span" sx={{ fontSize: '12px' }}>
<Typography component="span" sx={{ fontSize: '12px', color: COLORS.brandExtraDark }}>
<Trans
i18nKey="coinGeckoReferral"
t={t}
components={{
CoinGeckoLink: <Link href={referrals.coinGecko} rel="noopener noreferrer" target="_blank" />,
CoinGeckoLink: (
<Link
href={referrals.coinGecko}
rel="noopener noreferrer"
target="_blank"
sx={{ fontWeight: 400, color: 'inherit', textDecoration: 'underline' }}
/>
),
}}
/>
</Typography>
Expand Down
16 changes: 16 additions & 0 deletions src/app/components/Skeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { FC } from 'react'
import Skeleton from '@mui/material/Skeleton'

type TextSkeletonProps = {
numberOfRows: number
}

export const TextSkeleton: FC<TextSkeletonProps> = ({ numberOfRows }) => {
return (
<>
{[...Array(numberOfRows).keys()].map(i => (
<Skeleton key={i} variant="text" height={30} sx={{ my: 4 }} />
))}
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ exports[`TrimLinkLabel snapshot 1`] = `
-webkit-text-decoration: underline;
text-decoration: underline;
text-decoration-color: rgba(0, 146, 246, 0.4);
color: #000062;
text-decoration-color: #000062;
color: #3333c4;
font-weight: 700;
-webkit-text-decoration: none;
text-decoration: none;
}
.emotion-0-MuiTypography-root-MuiLink-root:hover {
Expand Down
9 changes: 1 addition & 8 deletions src/app/pages/AccountDetailsPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { useHref, useLoaderData } from 'react-router-dom'
import CardContent from '@mui/material/CardContent'
import Skeleton from '@mui/material/Skeleton'
import { PageLayout } from '../../components/PageLayout'
import { SubPageCard } from '../../components/SubPageCard'
import { Account } from '../../components/Account'
Expand All @@ -21,12 +19,7 @@ export const AccountDetailsPage: FC = () => {
return (
<PageLayout>
<SubPageCard featured title={t('account.title')}>
{accountQuery.isLoading && <Skeleton variant="text" height={30} sx={{ my: 4 }} />}
{account && (
<CardContent>
<Account account={account} roseFiatValue={rosePriceQuery.data} />
</CardContent>
)}
<Account account={account} isLoading={accountQuery.isLoading} roseFiatValue={rosePriceQuery.data} />
</SubPageCard>
<RouterTabs
tabs={[
Expand Down
4 changes: 3 additions & 1 deletion src/app/pages/BlockDetailPage/TransactionsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { useGetEmeraldTransactions } from '../../../oasis-indexer/api'
import { Transactions } from '../../components/Transactions'
import { ErrorBoundary } from '../../components/ErrorBoundary'

export const transactionsContainerId = 'transactions'

const TransactionList: FC<{ blockHeight: number }> = ({ blockHeight }) => {
const txsPagination = useSearchParamsPagination('page')
const txsOffset = (txsPagination.selectedPage - 1) * NUMBER_OF_ITEMS_ON_SEPARATE_PAGE
Expand All @@ -36,7 +38,7 @@ const TransactionList: FC<{ blockHeight: number }> = ({ blockHeight }) => {
export const TransactionsCard: FC<{ blockHeight: number }> = ({ blockHeight }) => {
const { t } = useTranslation()
return (
<Card>
<Card id={transactionsContainerId}>
<CardHeader disableTypography component="h3" title={t('common.transactions')} />
<CardContent>
<ErrorBoundary light={true}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { render, screen } from '@testing-library/react'
import { screen } from '@testing-library/react'
import { renderWithProviders } from '../../../utils/renderWithProviders'
import { BlockDetailView } from '../'

describe('BlockDetailView', () => {
Expand All @@ -12,7 +13,7 @@ describe('BlockDetailView', () => {
})

it('should display formatted values', () => {
render(
renderWithProviders(
<BlockDetailView
isLoading={false}
block={{
Expand All @@ -25,7 +26,7 @@ describe('BlockDetailView', () => {
}}
/>,
)
expect(screen.getByText('1158800')).toBeInTheDocument()
expect(screen.getByText('1,158,800')).toBeInTheDocument()
expect(screen.getByText('April 23, 2022 at 12:20 PM UTC (9 months ago)')).toBeInTheDocument()
expect(screen.getByText('6,434 bytes')).toBeInTheDocument()
})
Expand Down
72 changes: 48 additions & 24 deletions src/app/pages/BlockDetailPage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams } from 'react-router-dom'
import { useHref, useParams } from 'react-router-dom'
import Typography from '@mui/material/Typography'
import Skeleton from '@mui/material/Skeleton'
import useMediaQuery from '@mui/material/useMediaQuery'
import { useTheme } from '@mui/material/styles'
import Link from '@mui/material/Link'
import { RuntimeBlock, useGetEmeraldBlocks } from '../../../oasis-indexer/api'
import { StyledDescriptionList } from '../../components/StyledDescriptionList'
import { PageLayout } from '../../components/PageLayout'
import { SubPageCard } from '../../components/SubPageCard'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { TextSkeleton } from '../../components/Skeleton'
import { useFormattedTimestampString } from '../../hooks/useFormattedTimestamp'
import { TransactionsCard } from './TransactionsCard'
import { AppErrors } from '../../../types/errors'
import { trimLongString } from '../../utils/trimLongString'
import { COLORS } from '../../../styles/theme/colors'
import { gasLimit } from '../../../config'
import { transactionsContainerId } from './TransactionsCard'

// TODO: replace with an appropriate API
function useGetEmeraldBlockByHeight(blockHeight: number) {
Expand Down Expand Up @@ -50,21 +53,36 @@ export const BlockDetailView: FC<{
const theme = useTheme()
const isMobile = useMediaQuery(theme.breakpoints.down('sm'))
const formattedTime = useFormattedTimestampString(block?.timestamp)
const transactionsAnchor = `${useHref('')}#${transactionsContainerId}`

return (
<SubPageCard featured title={t('common.block')}>
{isLoading && (
<>
<Skeleton variant="text" height={30} sx={{ my: 4 }} />
<Skeleton variant="text" height={30} sx={{ my: 4 }} />
<Skeleton variant="text" height={30} sx={{ my: 4 }} />
<Skeleton variant="text" height={30} sx={{ my: 4 }} />
<Skeleton variant="text" height={30} sx={{ my: 4 }} />
</>
)}
{isLoading && <TextSkeleton numberOfRows={7} />}
{block && (
<StyledDescriptionList titleWidth={isMobile ? '100px' : '200px'}>
<dt>{t('common.height')}</dt>
<dd>{block.round}</dd>
<dd>
<CopyToClipboard
label={
<Typography component="span" sx={{ color: COLORS.brandDark, fontWeight: 700 }}>
{block.round.toLocaleString()}
</Typography>
}
value={block.round.toString()}
/>
</dd>

<dt>{t('common.hash')}</dt>
<dd>
<CopyToClipboard
label={
<Typography component="span" sx={{ color: COLORS.brandDark, fontWeight: 700 }}>
{isMobile ? trimLongString(block.hash) : block.hash}
</Typography>
}
value={block.hash}
/>
</dd>

<dt>{t('common.timestamp')}</dt>
<dd>{formattedTime}</dd>
Expand All @@ -84,22 +102,28 @@ export const BlockDetailView: FC<{
</dd>

<dt>{t('common.transactions')}</dt>
<dd>{t('common.transactionsNumber', { value: block.num_transactions })}</dd>

<dt>{t('common.hash')}</dt>
<dd>
<CopyToClipboard
label={
<Typography component="span" sx={{ color: COLORS.brandDark, fontWeight: 700 }}>
{isMobile ? trimLongString(block.hash) : block.hash}
</Typography>
}
value={block.hash}
/>
<Link href={transactionsAnchor}>
{t('common.transactionsNumber', { count: block.num_transactions })}
</Link>
</dd>

<dt>{t('common.gasUsed')}</dt>
<dd>{block.gas_used.toLocaleString()}</dd>
<dd>
{t('block.gasUsed', {
value: block.gas_used,
percentage: block.gas_used / gasLimit,
formatParams: {
percentage: {
style: 'percent',
maximumFractionDigits: 2,
} satisfies Intl.NumberFormatOptions,
},
})}
</dd>

<dt>{t('common.gasLimit')}</dt>
<dd>{gasLimit.toLocaleString()}</dd>
</StyledDescriptionList>
)}
</SubPageCard>
Expand Down
Loading

0 comments on commit d92e3a8

Please sign in to comment.