Skip to content

Commit

Permalink
Merge pull request #691 from oasisprotocol/csillag/token-dashboard-lo…
Browse files Browse the repository at this point in the history
…ading-state

Improve token dashboard
  • Loading branch information
csillag authored Jul 10, 2023
2 parents 11c84f2 + f6a78f8 commit 60de008
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 73 deletions.
1 change: 1 addition & 0 deletions .changelog/691.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Token dashboard: make sure all cards have loading state
6 changes: 4 additions & 2 deletions src/app/components/Table/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ type TableProps = {
rows?: TableRowProps[]
rowsNumber?: number
stickyColumn?: boolean
extraHorizontalSpaceOnMobile?: boolean
extraHorizontalSpaceOnMobile?: boolean | undefined
alwaysWaitWhileLoading?: boolean | undefined
}

const stickyColumnStyles = {
Expand All @@ -97,6 +98,7 @@ export const Table: FC<TableProps> = ({
rowsNumber = 5,
stickyColumn = false,
extraHorizontalSpaceOnMobile = false,
alwaysWaitWhileLoading = false,
}) => {
const { isMobile } = useScreenSize()

Expand Down Expand Up @@ -125,7 +127,7 @@ export const Table: FC<TableProps> = ({
</TableRow>
</TableHead>
<TableBody>
{!rows && isLoading && (
{(alwaysWaitWhileLoading || !rows) && isLoading && (
<SkeletonTableRows rowsNumber={rowsNumber} columnsNumber={columns.length} />
)}
{rows?.map(row => (
Expand Down
1 change: 1 addition & 0 deletions src/app/components/Tokens/TokenTransfers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ export const TokenTransfers: FC<TokenTransfersProps> = ({
isLoading={isLoading}
pagination={pagination}
extraHorizontalSpaceOnMobile
alwaysWaitWhileLoading
/>
)
}
2 changes: 1 addition & 1 deletion src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const TokenDetailsCard: FC = () => {
<Card>
<CardContent>
{isLoading && <TextSkeleton numberOfRows={7} />}
{account && token && (
{!isLoading && account && token && (
<StyledDescriptionList titleWidth={isMobile ? '100px' : '200px'}>
<dt>{t('common.token')}</dt>
<dd>{token.name}</dd>
Expand Down
11 changes: 7 additions & 4 deletions src/app/pages/TokenDashboardPage/TokenHoldersCountCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ import { COLORS } from '../../../styles/theme/colors'
import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useTokenInfo } from './hook'
import { useLoaderData } from 'react-router-dom'
import Skeleton from '@mui/material/Skeleton'

export const TokenHoldersCountCard: FC = () => {
const { t } = useTranslation()
const scope = useRequiredScopeParam()

const address = useLoaderData() as string

const { token, isFetched } = useTokenInfo(scope, address)
const { isLoading, token, isFetched } = useTokenInfo(scope, address)

const title = t('tokens.holders')
return (
<SnapshotCard title={title} withConstantHeight>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
{isFetched && (
<>
{isLoading ? (
<Skeleton variant="text" sx={{ width: '50%' }} />
) : (
isFetched && (
<Typography
component="span"
sx={{
Expand All @@ -32,7 +35,7 @@ export const TokenHoldersCountCard: FC = () => {
>
{t('tokens.holdersValue', { value: token?.num_holders })}
</Typography>
</>
)
)}
</Box>
</SnapshotCard>
Expand Down
26 changes: 17 additions & 9 deletions src/app/pages/TokenDashboardPage/TokenSupplyCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,42 @@ import { COLORS } from '../../../styles/theme/colors'
import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useTokenInfo } from './hook'
import { useLoaderData } from 'react-router-dom'
import Skeleton from '@mui/material/Skeleton'

export const TokenSupplyCard: FC = () => {
const { t } = useTranslation()
const scope = useRequiredScopeParam()

const address = useLoaderData() as string

const { token, isFetched } = useTokenInfo(scope, address)

const title = t('tokens.totalSupply')
const supplyString = token?.total_supply
const { isLoading, token, isFetched } = useTokenInfo(scope, address)

return (
<SnapshotCard title={title} label={token?.symbol}>
<SnapshotCard
title={t('tokens.totalSupply')}
label={isLoading ? <Skeleton variant="text" sx={{ width: '4em' }} /> : token?.symbol}
>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
{isFetched && (
<>
{isLoading ? (
<Skeleton variant="text" sx={{ width: '50%' }} />
) : (
isFetched &&
token && (
<Typography
component="span"
sx={{
fontSize: '48px',
fontWeight: 700,
color: COLORS.brandDark,
textAlign: 'center',
width: '100%',
}}
>
{!supplyString ? t('common.missing') : t('tokens.totalSupplyValue', { value: supplyString })}
{token.total_supply
? t('tokens.totalSupplyValue', { value: token.total_supply })
: t('common.undefined')}
</Typography>
</>
)
)}
</Box>
</SnapshotCard>
Expand Down
90 changes: 47 additions & 43 deletions src/app/pages/TokenDashboardPage/TokenTitleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,72 +11,76 @@ import { DelayedContractVerificationIcon } from '../../components/ContractVerifi
import { AccountLink } from '../../components/Account/AccountLink'
import Box from '@mui/material/Box'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { useTranslation } from 'react-i18next'

const TitleSkeleton: FC = () => <Skeleton variant="text" sx={{ display: 'inline-block', width: '100%' }} />

export const TokenTitleCard: FC = () => {
const { t } = useTranslation()
const scope = useRequiredScopeParam()
const address = useLoaderData() as string

const { isLoading, token } = useTokenInfo(scope, address)

const title = isLoading ? <TitleSkeleton /> : token?.name
const subTitle = isLoading ? null : ` (${token?.symbol})` || null

return (
<Card>
<CardContent>
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
{isLoading ? (
<TitleSkeleton />
) : (
<Box
sx={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<Typography
variant="h2"
sx={{
fontWeight: 700,
}}
>
{title}
</Typography>
&nbsp;
<Typography
variant="h2"
sx={{
color: COLORS.grayMedium,
fontWeight: 700,
}}
>
{subTitle}
</Typography>
</Box>

{token && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '50%',
}}
>
<DelayedContractVerificationIcon
scope={token}
contractOasisAddress={token.contract_addr}
noLink
/>
<AccountLink scope={token} address={token.eth_contract_addr || token.contract_addr} />
<CopyToClipboard value={token.eth_contract_addr || token.contract_addr} />
<Typography
variant="h2"
sx={{
fontWeight: 700,
}}
>
{token?.name ?? t('common.missing')}
</Typography>
&nbsp;
<Typography
variant="h2"
sx={{
color: COLORS.grayMedium,
fontWeight: 700,
}}
>
{token?.symbol ?? t('common.missing')}
</Typography>
</Box>
)}
</Box>

{token && (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<DelayedContractVerificationIcon
scope={token}
contractOasisAddress={token.contract_addr}
noLink
/>
<AccountLink scope={token} address={token.eth_contract_addr || token.contract_addr} />
<CopyToClipboard value={token.eth_contract_addr || token.contract_addr} />
</Box>
)}
</Box>
)}
</CardContent>
</Card>
)
Expand Down
15 changes: 11 additions & 4 deletions src/app/pages/TokenDashboardPage/TokenTotalTransactionsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,28 @@ import { COLORS } from '../../../styles/theme/colors'
import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useLoaderData } from 'react-router-dom'
import { useAccount } from '../AccountDetailsPage/hook'
import Skeleton from '@mui/material/Skeleton'
import { useTokenInfo } from './hook'

export const TokenTotalTransactionsCard: FC = () => {
const { t } = useTranslation()
const scope = useRequiredScopeParam()

const address = useLoaderData() as string

const { isFetched, account } = useAccount(scope, address)
const { isLoading: isAccountLoading, isFetched, account } = useAccount(scope, address)
const { isLoading: isTokenLoading } = useTokenInfo(scope, address)
const value = account?.stats.num_txns

const isLoading = isAccountLoading || isTokenLoading

return (
<SnapshotCard title={t('totalTransactions.header')} withConstantHeight>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
{isFetched && (
<>
{isLoading ? (
<Skeleton variant="text" sx={{ width: '50%' }} />
) : (
isFetched && (
<Typography
component="span"
sx={{
Expand All @@ -32,7 +39,7 @@ export const TokenTotalTransactionsCard: FC = () => {
>
{t('totalTransactions.value', { value })}
</Typography>
</>
)
)}
</Box>
</SnapshotCard>
Expand Down
20 changes: 14 additions & 6 deletions src/app/pages/TokenDashboardPage/TokenTransfersCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useLoaderData } from 'react-router-dom'
import { TokenTransfers } from '../../components/Tokens/TokenTransfers'
import { CardEmptyState } from '../AccountDetailsPage/CardEmptyState'
import { useAccount } from '../AccountDetailsPage/hook'
import { useTokenTransfers } from './hook'
import { useTokenInfo, useTokenTransfers } from './hook'

export const tokenTransfersContainerId = 'transfers'

Expand All @@ -19,12 +19,20 @@ export const TokenTransfersCard: FC = () => {
const scope = useRequiredScopeParam()
const address = useLoaderData() as string

const { isLoading, isFetched, transfers, pagination, totalCount, isTotalCountClipped } = useTokenTransfers(
scope,
address,
)
const {
isLoading: areTransfersLoading,
isFetched,
transfers,
pagination,
totalCount,
isTotalCountClipped,
} = useTokenTransfers(scope, address)

const { isLoading: isTokenLoading } = useTokenInfo(scope, address)

const { isLoading: isAccountLoading, account } = useAccount(scope, address)

const { account } = useAccount(scope, address)
const isLoading = isTokenLoading || isAccountLoading || areTransfersLoading

return (
<Card>
Expand Down
11 changes: 7 additions & 4 deletions src/app/pages/TokenDashboardPage/TokenTypeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,23 @@ import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useTokenInfo } from './hook'
import { useLoaderData } from 'react-router-dom'
import { getTokenTypeName } from '../../../types/tokens'
import Skeleton from '@mui/material/Skeleton'

export const TokenTypeCard: FC = () => {
const { t } = useTranslation()
const scope = useRequiredScopeParam()

const address = useLoaderData() as string

const { token, isFetched } = useTokenInfo(scope, address)
const { isLoading, token, isFetched } = useTokenInfo(scope, address)

return (
<SnapshotCard title={t('common.type')} withConstantHeight>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100%' }}>
{isFetched && (
<>
{isLoading ? (
<Skeleton variant="text" sx={{ width: '50%' }} />
) : (
isFetched && (
<Typography
component="span"
sx={{
Expand All @@ -32,7 +35,7 @@ export const TokenTypeCard: FC = () => {
>
{token?.type ? getTokenTypeName(t, token.type) : '-'}
</Typography>
</>
)
)}
</Box>
</SnapshotCard>
Expand Down
1 change: 1 addition & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"txnFee": "Txn Fee",
"type": "Type",
"quantity": "Quantity",
"undefined": "Undefined",
"unknown": "Unknown",
"value": "Value",
"valueInToken": "{{value}} {{ticker}}",
Expand Down

0 comments on commit 60de008

Please sign in to comment.