From 8134613ddb8d91c7505e701bb06790d7cd0de817 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Thu, 15 Feb 2024 15:42:30 +0100 Subject: [PATCH 01/13] Create BalanceDistribution card for Consensus account details --- .changelog/1261.trivial.md | 1 + .../BalanceDistribution.tsx | 86 +++++++++++++++++++ .../ConsensusAccountDetailsPage/index.tsx | 8 ++ src/locales/en/translation.json | 4 +- 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 .changelog/1261.trivial.md create mode 100644 src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx diff --git a/.changelog/1261.trivial.md b/.changelog/1261.trivial.md new file mode 100644 index 000000000..820062fff --- /dev/null +++ b/.changelog/1261.trivial.md @@ -0,0 +1 @@ +Add secondary cards to Consensus account details page diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx new file mode 100644 index 000000000..a3b69086c --- /dev/null +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -0,0 +1,86 @@ +import { FC } from 'react' +import { useTranslation } from 'react-i18next' +import Box from '@mui/material/Box' +import Card from '@mui/material/Card' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import Skeleton from '@mui/material/Skeleton' +import Typography from '@mui/material/Typography' +import { Account } from '../../../oasis-nexus/api' +import { PieChart } from '../../components/charts/PieChart' +import { useScreenSize } from '../../hooks/useScreensize' +import { getPreciseNumberFormat } from 'locales/getPreciseNumberFormat' +import { COLORS } from '../../../styles/theme/colors' + +type BalanceDistributionProps = { + account: Account | undefined + isLoading: boolean +} + +export const BalanceDistribution: FC = ({ account, isLoading }) => { + const { t } = useTranslation() + + return ( + + + + {isLoading && } + {account && } + + + ) +} + +type BalanceDistributionContentProps = { + account: Account +} + +const BalanceDistributionContent: FC = ({ account }) => { + const { t } = useTranslation() + const { isMobile } = useScreenSize() + const totalValue = t('common.valueInToken', { + ...getPreciseNumberFormat(account.total), + ticker: account.ticker, + }) + const data = [ + { + label: t('account.available'), + value: Number(account.available), + }, + { + label: t('account.staking'), + value: Number(account.delegations_balance), + }, + { + label: t('account.debonding'), + value: Number(account.debonding_delegations_balance), + }, + ] + + return ( + <> + {!isMobile && ( + + {t('account.totalValue', { + value: totalValue, + })} + + )} + + + t('common.valueInToken', { + ...getPreciseNumberFormat(value.toString()), + ticker: account.ticker, + }), + label: (label: string) => label, + }} + /> + + + ) +} diff --git a/src/app/pages/ConsensusAccountDetailsPage/index.tsx b/src/app/pages/ConsensusAccountDetailsPage/index.tsx index 8e218b761..baf2dfe2a 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/index.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/index.tsx @@ -1,6 +1,7 @@ import { FC } from 'react' import { useTranslation } from 'react-i18next' import { useHref, useLoaderData } from 'react-router-dom' +import Grid from '@mui/material/Grid' import { Account, useGetConsensusAccountsAddress } from '../../../oasis-nexus/api' import { useScreenSize } from '../../hooks/useScreensize' import { StyledDescriptionList } from '../../components/StyledDescriptionList' @@ -13,6 +14,7 @@ import { AddressLoaderData } from '../../utils/route-utils' import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { ConsensusAccountDetailsCard } from './ConsensusAccountDetailsCard' import { RouterTabs } from '../../components/RouterTabs' +import { BalanceDistribution } from './BalanceDistribution' import { ConsensusAccountDetailsContext } from './hooks' export const ConsensusAccountDetailsPage: FC = () => { @@ -29,6 +31,12 @@ export const ConsensusAccountDetailsPage: FC = () => { return ( + + + + + + ) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 5b9106258..191dbd174 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -1,6 +1,7 @@ { "account": { "available": "Available", + "balanceDistribution": "Balance Distribution", "birth": "Birth", "cantLoadDetails": "Unfortunately we couldn't load the account details at this time. Please try again later.", "debonding": "Debonding", @@ -21,7 +22,8 @@ "transactionsListTitle": "Account Transactions", "totalBalance": "Total Balance", "totalReceived": "Total Received", - "totalSent": "Total Sent" + "totalSent": "Total Sent", + "totalValue": "Total {{value}}" }, "activeAccounts": { "title": "Active Accounts", From 9dad0db67e020fb9f134f91281c5595475e7a7c7 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 16 Feb 2024 13:19:27 +0100 Subject: [PATCH 02/13] Prepare API layer for Consensus account delegations --- src/oasis-nexus/api.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/oasis-nexus/api.ts b/src/oasis-nexus/api.ts index dfa9fb3f9..e5da8f9fa 100644 --- a/src/oasis-nexus/api.ts +++ b/src/oasis-nexus/api.ts @@ -90,6 +90,12 @@ declare module './generated/api' { network: Network layer: typeof Layer.consensus } + + export interface Delegation { + network: Network + layer: typeof Layer.consensus + ticker: Ticker + } } export const isAccountEmpty = (account: RuntimeAccount) => { @@ -949,3 +955,34 @@ export const useGetConsensusAccounts: typeof generated.useGetConsensusAccounts = }, }) } + +export const useGetConsensusAccountsAddressDelegations: typeof generated.useGetConsensusAccountsAddressDelegations = + (network, address, params?, options?) => { + const ticker = getTokensForScope({ network, layer: Layer.consensus })[0].ticker + return generated.useGetConsensusAccountsAddressDelegations(network, address, params, { + ...options, + request: { + ...options?.request, + transformResponse: [ + ...arrayify(axios.defaults.transformResponse), + (data: generated.DelegationList, headers, status) => { + if (status !== 200) return data + return { + ...data, + delegations: data.delegations.map(delegation => { + return { + ...delegation, + shares: fromBaseUnits(delegation.shares, consensusDecimals), + amount: fromBaseUnits(delegation.amount, consensusDecimals), + layer: Layer.consensus, + network, + ticker, + } + }), + } + }, + ...arrayify(options?.request?.transformResponse), + ], + }, + }) + } From 50c7ecfb11af72f5cd108d3fdd389c8eb4a0c462 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 16 Feb 2024 13:28:23 +0100 Subject: [PATCH 03/13] Create Delegations list component --- src/app/components/Delegations/index.tsx | 56 ++++++++++++++++++++++++ src/locales/en/translation.json | 2 + 2 files changed, 58 insertions(+) create mode 100644 src/app/components/Delegations/index.tsx diff --git a/src/app/components/Delegations/index.tsx b/src/app/components/Delegations/index.tsx new file mode 100644 index 000000000..5f74b412c --- /dev/null +++ b/src/app/components/Delegations/index.tsx @@ -0,0 +1,56 @@ +import { FC } from 'react' +import { useTranslation } from 'react-i18next' +import { Table, TableCellAlign, TableColProps } from '../../components/Table' +import { Delegation } from '../../../oasis-nexus/api' +import { TablePaginationProps } from '../Table/TablePagination' +import { RoundedBalance } from '../RoundedBalance' + +type DelegationsProps = { + delegations?: Delegation[] + isLoading: boolean + limit: number + pagination: false | TablePaginationProps +} + +export const Delegations: FC = ({ delegations, isLoading, limit, pagination }) => { + const { t } = useTranslation() + + const tableColumns: TableColProps[] = [ + { key: 'name', content: t('validator.title') }, + { align: TableCellAlign.Right, key: 'shares', content: t('validator.shares') }, + { align: TableCellAlign.Right, key: 'staked', content: t('validator.staked') }, + ] + const tableRows = delegations?.map(delegation => ({ + key: delegation.validator, + data: [ + { + // TODO: Enable link with trimmed label when validator details page #1232 is merged + // TODO: Use trimmed name when API is updated + content: <>{delegation.validator}, + key: 'name', + }, + { + align: TableCellAlign.Right, + content: , + key: 'shares', + }, + { + align: TableCellAlign.Right, + + content: , + key: 'staked', + }, + ], + })) + + return ( + + ) +} diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 191dbd174..dd7a8511b 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -611,9 +611,11 @@ "signedBlocksDescription": "Last 100 blocks", "proposedBlocks": "Proposed Blocks", "snapshot": "Validator Snapshot", + "shares": "Shares", "staked": "Staked", "stakingTrend": "Staking Trend", "startDate": "Start Date", + "staking": "Staking", "title": "Validator", "totalShare": "Total Share", "uptime": "Uptime", From 537879c0c5b45f405808791e183233c352d9048a Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 16 Feb 2024 13:36:21 +0100 Subject: [PATCH 04/13] Add Staking card to Consensus account details page --- src/app/components/AccountList/index.tsx | 2 +- src/app/components/Delegations/index.tsx | 4 +- src/app/components/Validators/index.tsx | 2 +- .../BalanceDistribution.tsx | 2 +- .../ConsensusAccountDetailsCard.tsx | 2 +- .../ConsensusAccountDetailsPage/Staking.tsx | 90 +++++++++++++++++++ .../ConsensusAccountDetailsPage/index.tsx | 7 +- .../ConsensusDashboardPage/SnapshotStaked.tsx | 2 +- src/app/pages/ValidatorDetailsPage/index.tsx | 2 +- src/app/utils/externalLinks.ts | 1 + src/locales/en/translation.json | 6 +- 11 files changed, 107 insertions(+), 13 deletions(-) create mode 100644 src/app/pages/ConsensusAccountDetailsPage/Staking.tsx diff --git a/src/app/components/AccountList/index.tsx b/src/app/components/AccountList/index.tsx index 89050ff45..2a6450348 100644 --- a/src/app/components/AccountList/index.tsx +++ b/src/app/components/AccountList/index.tsx @@ -23,7 +23,7 @@ export const AccountList: FC = ({ isLoading, limit, pagination { key: 'address', content: t('common.address') }, ...(verbose ? [{ key: 'creationDate', content: t('account.birth') }] : []), { align: TableCellAlign.Right, key: 'available', content: t('account.available') }, - { align: TableCellAlign.Right, key: 'staked', content: t('account.staked') }, + { align: TableCellAlign.Right, key: 'staked', content: t('common.staked') }, { align: TableCellAlign.Right, key: 'debonding', content: t('account.debonding') }, { align: TableCellAlign.Right, key: 'total', content: {t('account.totalBalance')} }, ] diff --git a/src/app/components/Delegations/index.tsx b/src/app/components/Delegations/index.tsx index 5f74b412c..d11e9739c 100644 --- a/src/app/components/Delegations/index.tsx +++ b/src/app/components/Delegations/index.tsx @@ -18,7 +18,7 @@ export const Delegations: FC = ({ delegations, isLoading, limi const tableColumns: TableColProps[] = [ { key: 'name', content: t('validator.title') }, { align: TableCellAlign.Right, key: 'shares', content: t('validator.shares') }, - { align: TableCellAlign.Right, key: 'staked', content: t('validator.staked') }, + { align: TableCellAlign.Right, key: 'staked', content: t('common.staked') }, ] const tableRows = delegations?.map(delegation => ({ key: delegation.validator, @@ -48,7 +48,7 @@ export const Delegations: FC = ({ delegations, isLoading, limi columns={tableColumns} rows={tableRows} rowsNumber={limit} - name={t('validator.staking')} + name={t('common.staking')} isLoading={isLoading} pagination={pagination} /> diff --git a/src/app/components/Validators/index.tsx b/src/app/components/Validators/index.tsx index 7f92fc2ed..26825be41 100644 --- a/src/app/components/Validators/index.tsx +++ b/src/app/components/Validators/index.tsx @@ -28,7 +28,7 @@ export const Validators: FC = ({ isLoading, limit, pagination, { key: 'name', content: t('validator.title') }, { align: TableCellAlign.Right, key: 'cumulativeVoting', content: t('validator.cumulativeVoting') }, { align: TableCellAlign.Right, key: 'voting', content: t('validator.voting') }, - { align: TableCellAlign.Right, key: 'staked', content: t('validator.staked') }, + { align: TableCellAlign.Right, key: 'staked', content: t('common.staked') }, { align: TableCellAlign.Right, key: 'change', content: t('validator.change') }, { align: TableCellAlign.Right, key: 'delegators', content: t('validator.delegators') }, { align: TableCellAlign.Right, key: 'commission', content: t('validator.commission') }, diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx index a3b69086c..050430d77 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -48,7 +48,7 @@ const BalanceDistributionContent: FC = ({ accou value: Number(account.available), }, { - label: t('account.staking'), + label: t('common.staking'), value: Number(account.delegations_balance), }, { diff --git a/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountDetailsCard.tsx b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountDetailsCard.tsx index d7fd06453..bc42b7620 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountDetailsCard.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountDetailsCard.tsx @@ -76,7 +76,7 @@ const ConsensusAccountDetails: FC = ({ account ticker: account.ticker, })} - {t('account.staking')} + {t('common.staking')}
{t('common.valueInToken', { ...getPreciseNumberFormat(account.delegations_balance!), diff --git a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx new file mode 100644 index 000000000..e0c8183e3 --- /dev/null +++ b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx @@ -0,0 +1,90 @@ +import { FC } from 'react' +import { useTranslation } from 'react-i18next' +import Card from '@mui/material/Card' +import CardHeader from '@mui/material/CardHeader' +import CardContent from '@mui/material/CardContent' +import Link from '@mui/material/Link' +import Skeleton from '@mui/material/Skeleton' +import { COLORS } from '../../../styles/theme/colors' +import { Account, useGetConsensusAccountsAddressDelegations } from '../../../oasis-nexus/api' +import { useRequiredScopeParam } from '../../../app/hooks/useScopeParam' +import { AppErrors } from '../../../types/errors' +import { NUMBER_OF_ITEMS_ON_DASHBOARD as PAGE_SIZE } from '../../config' +import { useSearchParamsPagination } from '../../components/Table/useSearchParamsPagination' +import { Delegations } from '../..//components/Delegations' +import { docs } from '../../utils/externalLinks' + +type StakingProps = { + account: Account | undefined + isLoading: boolean +} + +export const Staking: FC = ({ account, isLoading }) => { + const { t } = useTranslation() + + return ( + + + {t('validator.sharesDocs')} + + } + disableTypography + component="h3" + title={t('common.staking')} + /> + + {isLoading && } + {account && } + + + ) +} + +type StakingContentProps = { + address: string +} + +const StakingContent: FC = ({ address }) => { + const pagination = useSearchParamsPagination('page') + const offset = (pagination.selectedPage - 1) * PAGE_SIZE + const scope = useRequiredScopeParam() + const { network } = scope + const delegationsQuery = useGetConsensusAccountsAddressDelegations( + network, + address, + {}, + { + query: { + cacheTime: 0, + }, + }, + ) + const { isLoading, isFetched, data } = delegationsQuery + if (isFetched && offset && !delegationsQuery.data?.data?.delegations?.length) { + throw AppErrors.PageDoesNotExist + } + + return ( + <> + + + ) +} diff --git a/src/app/pages/ConsensusAccountDetailsPage/index.tsx b/src/app/pages/ConsensusAccountDetailsPage/index.tsx index baf2dfe2a..4d1e5b823 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/index.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/index.tsx @@ -15,6 +15,7 @@ import { useRequiredScopeParam } from '../../hooks/useScopeParam' import { ConsensusAccountDetailsCard } from './ConsensusAccountDetailsCard' import { RouterTabs } from '../../components/RouterTabs' import { BalanceDistribution } from './BalanceDistribution' +import { Staking } from './Staking' import { ConsensusAccountDetailsContext } from './hooks' export const ConsensusAccountDetailsPage: FC = () => { @@ -35,7 +36,9 @@ export const ConsensusAccountDetailsPage: FC = () => { - + + + @@ -72,7 +75,7 @@ export const ConsensusAccountDetailsView: FC<{
-
{t('account.staked')}
+
{t('common.staked')}
<>-
diff --git a/src/app/pages/ConsensusDashboardPage/SnapshotStaked.tsx b/src/app/pages/ConsensusDashboardPage/SnapshotStaked.tsx index 676ccb55a..5791dca22 100644 --- a/src/app/pages/ConsensusDashboardPage/SnapshotStaked.tsx +++ b/src/app/pages/ConsensusDashboardPage/SnapshotStaked.tsx @@ -14,7 +14,7 @@ export const SnapshotStaked: FC = () => { return ( diff --git a/src/app/pages/ValidatorDetailsPage/index.tsx b/src/app/pages/ValidatorDetailsPage/index.tsx index 4fb637c30..74fafc4aa 100644 --- a/src/app/pages/ValidatorDetailsPage/index.tsx +++ b/src/app/pages/ValidatorDetailsPage/index.tsx @@ -160,7 +160,7 @@ export const ValidatorDetailsView: FC<{
{t('validator.voting')}
-
-
{t('validator.staked')}
+
{t('common.staked')}
-
{t('validator.change')}
-
diff --git a/src/app/utils/externalLinks.ts b/src/app/utils/externalLinks.ts index 11cef4df3..dfc2b4502 100644 --- a/src/app/utils/externalLinks.ts +++ b/src/app/utils/externalLinks.ts @@ -18,6 +18,7 @@ export const docs = { consensus: 'https://docs.oasis.io/core/consensus/', consensusTransactions: `https://docs.oasis.io/core/consensus/transactions/`, consensusServices: `https://docs.oasis.io/core/consensus/services/`, + consensusStaking: `https://docs.oasis.io/core/consensus/services/staking/`, consensusGenesis: `https://docs.oasis.io/core/consensus/genesis/`, consensusVectors: `https://docs.oasis.io/core/consensus/test-vectors/`, consensusComet: `https://docs.oasis.io/core/consensus/#cometbft`, diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index dd7a8511b..0a116e214 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -16,8 +16,6 @@ "noTokens": "This account holds no tokens", "showMore": "+ {{counter}} more", "sizeTooltip": "This account is indicated as an {{size}} account based on sum of assets they own.", - "staked": "Staked", - "staking": "Staking", "title": "Account", "transactionsListTitle": "Account Transactions", "totalBalance": "Total Balance", @@ -103,6 +101,8 @@ "show": "Show", "smartContract": "Smart Contract", "smartContract_short": "Contract", + "staked": "Staked", + "staking": "Staking", "submitter": "Submitter", "success": "Success", "status": "Status", @@ -612,10 +612,10 @@ "proposedBlocks": "Proposed Blocks", "snapshot": "Validator Snapshot", "shares": "Shares", + "sharesDocs": "How shares are calculated", "staked": "Staked", "stakingTrend": "Staking Trend", "startDate": "Start Date", - "staking": "Staking", "title": "Validator", "totalShare": "Total Share", "uptime": "Uptime", From 9f0a40541cbd7e161473b9f22d4253306259e7da Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 16 Feb 2024 13:37:58 +0100 Subject: [PATCH 05/13] Force grid cards to have the same height --- .../pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx | 2 +- src/app/pages/ConsensusAccountDetailsPage/Staking.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx index 050430d77..fcb98d988 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -21,7 +21,7 @@ export const BalanceDistribution: FC = ({ account, isL const { t } = useTranslation() return ( - + {isLoading && } diff --git a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx index e0c8183e3..2c89aae38 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx @@ -23,7 +23,7 @@ export const Staking: FC = ({ account, isLoading }) => { const { t } = useTranslation() return ( - + Date: Fri, 16 Feb 2024 16:12:48 +0100 Subject: [PATCH 06/13] Add staking empty state --- .../ConsensusAccountDetailsPage/Staking.tsx | 73 +++++++++++++++---- src/app/utils/externalLinks.ts | 4 + src/locales/en/translation.json | 2 + 3 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx index 2c89aae38..c87e141f0 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx @@ -1,10 +1,14 @@ import { FC } from 'react' import { useTranslation } from 'react-i18next' +import Box from '@mui/material/Box' import Card from '@mui/material/Card' import CardHeader from '@mui/material/CardHeader' import CardContent from '@mui/material/CardContent' import Link from '@mui/material/Link' import Skeleton from '@mui/material/Skeleton' +import Typography from '@mui/material/Typography' +import { styled } from '@mui/material/styles' +import StackedBarChartIcon from '@mui/icons-material/StackedBarChart' import { COLORS } from '../../../styles/theme/colors' import { Account, useGetConsensusAccountsAddressDelegations } from '../../../oasis-nexus/api' import { useRequiredScopeParam } from '../../../app/hooks/useScopeParam' @@ -12,7 +16,7 @@ import { AppErrors } from '../../../types/errors' import { NUMBER_OF_ITEMS_ON_DASHBOARD as PAGE_SIZE } from '../../config' import { useSearchParamsPagination } from '../../components/Table/useSearchParamsPagination' import { Delegations } from '../..//components/Delegations' -import { docs } from '../../utils/externalLinks' +import { docs, wallet } from '../../utils/externalLinks' type StakingProps = { account: Account | undefined @@ -71,20 +75,63 @@ const StakingContent: FC = ({ address }) => { throw AppErrors.PageDoesNotExist } + if (isFetched && !delegationsQuery.data?.data.delegations.length) { + return + } + return ( <> - + {isFetched && ( + + )} ) } + +const StyledBox = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + [theme.breakpoints.down('sm')]: { + paddingTop: theme.spacing(3), + }, + [theme.breakpoints.up('sm')]: { + paddingTop: theme.spacing(6), + }, +})) + +const StakingEmptyState: FC = () => { + const { t } = useTranslation() + + return ( + + + + {t('account.notStaking')} + + + {t('account.startStaking')} + + + ) +} diff --git a/src/app/utils/externalLinks.ts b/src/app/utils/externalLinks.ts index dfc2b4502..9df40f331 100644 --- a/src/app/utils/externalLinks.ts +++ b/src/app/utils/externalLinks.ts @@ -61,3 +61,7 @@ export const api = { export const ipfs = { proxyPrefix: 'https://ipfs.io/ipfs/', } + +export const wallet = { + homepage: 'https://wallet.oasis.io/', +} diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 0a116e214..9a8a59131 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -14,8 +14,10 @@ "lastNonce": "Last Nonce", "listTitle": "Accounts", "noTokens": "This account holds no tokens", + "notStaking": "This account is currently not staking.", "showMore": "+ {{counter}} more", "sizeTooltip": "This account is indicated as an {{size}} account based on sum of assets they own.", + "startStaking": "Start staking now", "title": "Account", "transactionsListTitle": "Account Transactions", "totalBalance": "Total Balance", From 6e73c7ddb9fcc2e0d5a3ee37452b9ef87435aef4 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 16 Feb 2024 16:20:35 +0100 Subject: [PATCH 07/13] Add workaround for an account with no balance --- .../pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx index fcb98d988..18973eb18 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -42,6 +42,10 @@ const BalanceDistributionContent: FC = ({ accou ...getPreciseNumberFormat(account.total), ticker: account.ticker, }) + if (Number(account.total) === 0) { + return <>{/* TODO: we need designs for this case */} + } + const data = [ { label: t('account.available'), From 450c72039cc4f2fe0d2a3503eb6229d5eb4425e7 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Mon, 19 Feb 2024 10:19:07 +0100 Subject: [PATCH 08/13] Enable delegator link in Staking card --- src/app/components/Delegations/index.tsx | 4 ++-- .../components/Validators/ValidatorLink.tsx | 22 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/app/components/Delegations/index.tsx b/src/app/components/Delegations/index.tsx index d11e9739c..b1f39a20c 100644 --- a/src/app/components/Delegations/index.tsx +++ b/src/app/components/Delegations/index.tsx @@ -4,6 +4,7 @@ import { Table, TableCellAlign, TableColProps } from '../../components/Table' import { Delegation } from '../../../oasis-nexus/api' import { TablePaginationProps } from '../Table/TablePagination' import { RoundedBalance } from '../RoundedBalance' +import { ValidatorLink } from '../Validators/ValidatorLink' type DelegationsProps = { delegations?: Delegation[] @@ -24,9 +25,8 @@ export const Delegations: FC = ({ delegations, isLoading, limi key: delegation.validator, data: [ { - // TODO: Enable link with trimmed label when validator details page #1232 is merged // TODO: Use trimmed name when API is updated - content: <>{delegation.validator}, + content: , key: 'name', }, { diff --git a/src/app/components/Validators/ValidatorLink.tsx b/src/app/components/Validators/ValidatorLink.tsx index defa5ddec..afdb9b3f1 100644 --- a/src/app/components/Validators/ValidatorLink.tsx +++ b/src/app/components/Validators/ValidatorLink.tsx @@ -12,9 +12,10 @@ type ValidatorLinkProps = { address: string name?: string network: Network + alwaysTrim?: boolean } -export const ValidatorLink: FC = ({ address, name, network }) => { +export const ValidatorLink: FC = ({ address, name, network, alwaysTrim }) => { const { isTablet } = useScreenSize() const to = RouteUtils.getValidatorRoute(network, address) return ( @@ -22,9 +23,7 @@ export const ValidatorLink: FC = ({ address, name, network } {isTablet ? ( ) : ( - - {name || address} - + )} ) @@ -51,3 +50,18 @@ const TabletValidatorLink: FC = ({ address, name, to } } return } + +type DesktopValidatorLinkProps = TabletValidatorLinkProps & { + alwaysTrim?: boolean +} + +const DesktopValidatorLink: FC = ({ address, name, to, alwaysTrim }) => { + if (alwaysTrim) { + return + } + return ( + + {name || address} + + ) +} From b8334ebf909c05a57305bdca7fac0831dc57cb53 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Mon, 19 Feb 2024 10:51:47 +0100 Subject: [PATCH 09/13] Extract account details card empty state --- .../ConsensusAccountCardEmptyState.tsx | 47 +++++++++++++++++ .../ConsensusAccountDetailsPage/Staking.tsx | 51 ++++--------------- 2 files changed, 56 insertions(+), 42 deletions(-) create mode 100644 src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx diff --git a/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx new file mode 100644 index 000000000..e7b0a7669 --- /dev/null +++ b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx @@ -0,0 +1,47 @@ +import { FC, ReactNode } from 'react' +import Box from '@mui/material/Box' +import Typography from '@mui/material/Typography' +import { styled } from '@mui/material/styles' +import StackedBarChartIcon from '@mui/icons-material/StackedBarChart' +import { COLORS } from '../../../styles/theme/colors' + +const StyledBox = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + [theme.breakpoints.down('sm')]: { + paddingTop: theme.spacing(3), + }, + [theme.breakpoints.up('sm')]: { + paddingTop: theme.spacing(6), + }, +})) + +type ConsensusAccountCardEmptyStateProps = { + children?: ReactNode + label: string +} + +export const ConsensusAccountCardEmptyState: FC = ({ + children, + label, +}) => { + return ( + + + + {label} + + {children} + + ) +} diff --git a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx index c87e141f0..425a3a178 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx @@ -1,14 +1,10 @@ import { FC } from 'react' import { useTranslation } from 'react-i18next' -import Box from '@mui/material/Box' import Card from '@mui/material/Card' import CardHeader from '@mui/material/CardHeader' import CardContent from '@mui/material/CardContent' import Link from '@mui/material/Link' import Skeleton from '@mui/material/Skeleton' -import Typography from '@mui/material/Typography' -import { styled } from '@mui/material/styles' -import StackedBarChartIcon from '@mui/icons-material/StackedBarChart' import { COLORS } from '../../../styles/theme/colors' import { Account, useGetConsensusAccountsAddressDelegations } from '../../../oasis-nexus/api' import { useRequiredScopeParam } from '../../../app/hooks/useScopeParam' @@ -17,6 +13,8 @@ import { NUMBER_OF_ITEMS_ON_DASHBOARD as PAGE_SIZE } from '../../config' import { useSearchParamsPagination } from '../../components/Table/useSearchParamsPagination' import { Delegations } from '../..//components/Delegations' import { docs, wallet } from '../../utils/externalLinks' +import { t } from 'i18next' +import { ConsensusAccountCardEmptyState } from './ConsensusAccountCardEmptyState' type StakingProps = { account: Account | undefined @@ -76,7 +74,13 @@ const StakingContent: FC = ({ address }) => { } if (isFetched && !delegationsQuery.data?.data.delegations.length) { - return + return ( + + + {t('account.startStaking')} + + + ) } return ( @@ -98,40 +102,3 @@ const StakingContent: FC = ({ address }) => { ) } - -const StyledBox = styled(Box)(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', - [theme.breakpoints.down('sm')]: { - paddingTop: theme.spacing(3), - }, - [theme.breakpoints.up('sm')]: { - paddingTop: theme.spacing(6), - }, -})) - -const StakingEmptyState: FC = () => { - const { t } = useTranslation() - - return ( - - - - {t('account.notStaking')} - - - {t('account.startStaking')} - - - ) -} From d1262a812bcbe16b356f0b6ade9d869f8180b7c7 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Mon, 19 Feb 2024 10:47:26 +0100 Subject: [PATCH 10/13] Add empty state to BalanceDistribution component --- .../ConsensusAccountDetailsPage/BalanceDistribution.tsx | 6 ++++-- .../ConsensusAccountCardEmptyState.tsx | 2 ++ src/locales/en/translation.json | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx index 18973eb18..661524dfa 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -11,6 +11,7 @@ import { PieChart } from '../../components/charts/PieChart' import { useScreenSize } from '../../hooks/useScreensize' import { getPreciseNumberFormat } from 'locales/getPreciseNumberFormat' import { COLORS } from '../../../styles/theme/colors' +import { ConsensusAccountCardEmptyState } from './ConsensusAccountCardEmptyState' type BalanceDistributionProps = { account: Account | undefined @@ -42,8 +43,9 @@ const BalanceDistributionContent: FC = ({ accou ...getPreciseNumberFormat(account.total), ticker: account.ticker, }) - if (Number(account.total) === 0) { - return <>{/* TODO: we need designs for this case */} + + if (account.total === '0') { + return } const data = [ diff --git a/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx index e7b0a7669..56a81bb3e 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/ConsensusAccountCardEmptyState.tsx @@ -11,9 +11,11 @@ const StyledBox = styled(Box)(({ theme }) => ({ justifyContent: 'center', alignItems: 'center', [theme.breakpoints.down('sm')]: { + minHeight: '150px', paddingTop: theme.spacing(3), }, [theme.breakpoints.up('sm')]: { + minHeight: '200px', paddingTop: theme.spacing(6), }, })) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 9a8a59131..407899356 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -14,6 +14,7 @@ "lastNonce": "Last Nonce", "listTitle": "Accounts", "noTokens": "This account holds no tokens", + "noBalances": "This account currently has no balances.", "notStaking": "This account is currently not staking.", "showMore": "+ {{counter}} more", "sizeTooltip": "This account is indicated as an {{size}} account based on sum of assets they own.", From 223bddaf29006206958c961bf8ce7912c0e54a71 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Mon, 19 Feb 2024 11:03:10 +0100 Subject: [PATCH 11/13] Adjust BalanceDistribution header with design changes --- .../BalanceDistribution.tsx | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx index 661524dfa..f8276eb0c 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/BalanceDistribution.tsx @@ -65,13 +65,18 @@ const BalanceDistributionContent: FC = ({ accou return ( <> - {!isMobile && ( - - {t('account.totalValue', { - value: totalValue, - })} - - )} + + {t('account.totalValue', { + value: totalValue, + })} + Date: Tue, 5 Mar 2024 15:23:46 +0100 Subject: [PATCH 12/13] Add more spacing between cards and tabs --- src/app/pages/ConsensusAccountDetailsPage/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/index.tsx b/src/app/pages/ConsensusAccountDetailsPage/index.tsx index 4d1e5b823..4f20ba366 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/index.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/index.tsx @@ -20,6 +20,7 @@ import { ConsensusAccountDetailsContext } from './hooks' export const ConsensusAccountDetailsPage: FC = () => { const { t } = useTranslation() + const { isMobile } = useScreenSize() const scope = useRequiredScopeParam() const { network } = scope const { address } = useLoaderData() as AddressLoaderData @@ -32,7 +33,7 @@ export const ConsensusAccountDetailsPage: FC = () => { return ( - + From b81651ac5f3a72d8061df1c4349376020ce46640 Mon Sep 17 00:00:00 2001 From: Michal Zielenkiewicz Date: Fri, 8 Mar 2024 09:49:42 +0100 Subject: [PATCH 13/13] Clear usage of cacheTime in queries --- .../ConsensusAccountDetailsPage/Staking.tsx | 11 +---------- src/app/pages/ConsensusAccountsPage/index.tsx | 16 ++++------------ .../SnapshotValidators.tsx | 10 +--------- .../pages/ConsensusDashboardPage/Validators.tsx | 10 +--------- src/app/pages/ProposalsPage/index.tsx | 16 ++++------------ src/app/pages/ValidatorsPage/index.tsx | 16 ++++------------ 6 files changed, 15 insertions(+), 64 deletions(-) diff --git a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx index 425a3a178..44fb4875d 100644 --- a/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx +++ b/src/app/pages/ConsensusAccountDetailsPage/Staking.tsx @@ -58,16 +58,7 @@ const StakingContent: FC = ({ address }) => { const offset = (pagination.selectedPage - 1) * PAGE_SIZE const scope = useRequiredScopeParam() const { network } = scope - const delegationsQuery = useGetConsensusAccountsAddressDelegations( - network, - address, - {}, - { - query: { - cacheTime: 0, - }, - }, - ) + const delegationsQuery = useGetConsensusAccountsAddressDelegations(network, address) const { isLoading, isFetched, data } = delegationsQuery if (isFetched && offset && !delegationsQuery.data?.data?.delegations?.length) { throw AppErrors.PageDoesNotExist diff --git a/src/app/pages/ConsensusAccountsPage/index.tsx b/src/app/pages/ConsensusAccountsPage/index.tsx index a5320a682..7ea6ead67 100644 --- a/src/app/pages/ConsensusAccountsPage/index.tsx +++ b/src/app/pages/ConsensusAccountsPage/index.tsx @@ -31,18 +31,10 @@ export const ConsensusAccountsPage: FC = () => { } }, [isMobile, setTableView]) - const accountsQuery = useGetConsensusAccounts( - network, - { - limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, - offset: tableView === TableLayout.Vertical ? 0 : offset, - }, - { - query: { - cacheTime: 0, - }, - }, - ) + const accountsQuery = useGetConsensusAccounts(network, { + limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, + offset: tableView === TableLayout.Vertical ? 0 : offset, + }) const { isLoading, isFetched, data } = accountsQuery const accountsData = data?.data if (isFetched && offset && !accountsData?.accounts?.length) { diff --git a/src/app/pages/ConsensusDashboardPage/SnapshotValidators.tsx b/src/app/pages/ConsensusDashboardPage/SnapshotValidators.tsx index 6c761225f..36fbd596c 100644 --- a/src/app/pages/ConsensusDashboardPage/SnapshotValidators.tsx +++ b/src/app/pages/ConsensusDashboardPage/SnapshotValidators.tsx @@ -26,15 +26,7 @@ export const SnapshotValidators: FC<{ scope: SearchScope }> = ({ scope }) => { const { t } = useTranslation() const { network } = scope - const validatorsQuery = useGetConsensusValidators( - network, - { limit: API_MAX_TOTAL_COUNT }, - { - query: { - cacheTime: 0, - }, - }, - ) + const validatorsQuery = useGetConsensusValidators(network, { limit: API_MAX_TOTAL_COUNT }) const validators = validatorsQuery.data?.data.validators return ( diff --git a/src/app/pages/ConsensusDashboardPage/Validators.tsx b/src/app/pages/ConsensusDashboardPage/Validators.tsx index a0bd7f680..3655b6154 100644 --- a/src/app/pages/ConsensusDashboardPage/Validators.tsx +++ b/src/app/pages/ConsensusDashboardPage/Validators.tsx @@ -19,15 +19,7 @@ export const ValidatorsCard: FC<{ scope: SearchScope }> = ({ scope }) => { const { t } = useTranslation() const { network } = scope - const validatorsQuery = useGetConsensusValidators( - network, - { limit }, - { - query: { - cacheTime: 0, - }, - }, - ) + const validatorsQuery = useGetConsensusValidators(network, { limit }) const validators = validatorsQuery.data?.data return ( diff --git a/src/app/pages/ProposalsPage/index.tsx b/src/app/pages/ProposalsPage/index.tsx index afc4377e5..d6bdf8c42 100644 --- a/src/app/pages/ProposalsPage/index.tsx +++ b/src/app/pages/ProposalsPage/index.tsx @@ -32,18 +32,10 @@ export const ProposalsPage: FC = () => { } }, [isMobile, setTableView]) - const proposalsQuery = useGetConsensusProposals( - network, - { - limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, - offset: tableView === TableLayout.Vertical ? 0 : offset, - }, - { - query: { - cacheTime: 0, - }, - }, - ) + const proposalsQuery = useGetConsensusProposals(network, { + limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, + offset: tableView === TableLayout.Vertical ? 0 : offset, + }) const { isLoading, isFetched, data } = proposalsQuery const proposalsData = data?.data if (isFetched && offset && !proposalsData?.proposals?.length) { diff --git a/src/app/pages/ValidatorsPage/index.tsx b/src/app/pages/ValidatorsPage/index.tsx index 0ce21b8ee..b3ea5780c 100644 --- a/src/app/pages/ValidatorsPage/index.tsx +++ b/src/app/pages/ValidatorsPage/index.tsx @@ -31,18 +31,10 @@ export const ValidatorsPage: FC = () => { } }, [isMobile, setTableView]) - const validatorsQuery = useGetConsensusValidators( - network, - { - limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, - offset: tableView === TableLayout.Vertical ? 0 : offset, - }, - { - query: { - cacheTime: 0, - }, - }, - ) + const validatorsQuery = useGetConsensusValidators(network, { + limit: tableView === TableLayout.Vertical ? offset + PAGE_SIZE : PAGE_SIZE, + offset: tableView === TableLayout.Vertical ? 0 : offset, + }) const { isLoading, isFetched, data } = validatorsQuery const validatorsData = data?.data if (isFetched && offset && !validatorsData?.validators?.length) {