Feat/258 move key value table into monorepo (#320)
* move key-value-table to ui-toolkit and use tailwind * add key-value-table to storybook * override border width 1px from the styles of the app, remove td and th from children * clone muted and numerical props to children elements * proposal change table remove empty lines * add Roboto mono to font-mono tailwind config * remove labels and labelfor * revert change on token-details-circulating * export the whole components directory rather than explicitly individual components * add classNames, add formatNumberPercentage, remove spans, add span in token details circulating * data-testid=governance-proposal-enactmentDate and use span instead of div * use custom spacing defined in tailwind & another README.md update for running cypress in watch mode * update divs to span within the vesting table * Update README.md Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * borders and text visible on both dark and light themes * add headingLevel and use dl instead of tables * update styling for dl inline * remove added grey from tailwind * ignore md files Co-authored-by: madalinaraicu <“madalina@raygroup.uk”> Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>
This commit is contained in:
parent
3af4e354cd
commit
bd3268adf0
@ -3,3 +3,4 @@
|
|||||||
/dist
|
/dist
|
||||||
/coverage
|
/coverage
|
||||||
__generated__
|
__generated__
|
||||||
|
*.md
|
||||||
|
14
README.md
14
README.md
@ -19,6 +19,7 @@ The trading interface built based on a component toolkit. It will provide a way
|
|||||||
### [UI toolkit](https://github.com/vegaprotocol/frontend-monorepo/tree/master/libs/ui-toolkit)
|
### [UI toolkit](https://github.com/vegaprotocol/frontend-monorepo/tree/master/libs/ui-toolkit)
|
||||||
|
|
||||||
The UI toolkit contains a set of components used to build interfaces that can interact with the Vega protocol, and follow the design style of the project.
|
The UI toolkit contains a set of components used to build interfaces that can interact with the Vega protocol, and follow the design style of the project.
|
||||||
|
It contains a storybook that can be served with `yarn nx run ui-toolkit:storybook`.
|
||||||
|
|
||||||
### [Tailwind CSS config](https://github.com/vegaprotocol/frontend-monorepo/tree/master/libs/tailwindcss-config)
|
### [Tailwind CSS config](https://github.com/vegaprotocol/frontend-monorepo/tree/master/libs/tailwindcss-config)
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ The Tailwind CSS config contains theme that align default config with Vega desig
|
|||||||
|
|
||||||
Check you have the correct version of Node. You can [install NVM to switch between node versions](https://github.com/nvm-sh/nvm#installing-and-updating). Then `NVM install`.
|
Check you have the correct version of Node. You can [install NVM to switch between node versions](https://github.com/nvm-sh/nvm#installing-and-updating). Then `NVM install`.
|
||||||
Before you build you will need to `yarn install` in the root directory.
|
Before you build you will need to `yarn install` in the root directory.
|
||||||
The repository includes a number of template .env files for different networks. Copy from these to the .env file before `serve` to lauch app with different network.
|
The repository includes a number of template .env files for different networks. Copy from these to the .env file before `serve` to launch app with different network. You can serve any application with `yarn nx run <name-of-app>:serve`.
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
@ -40,7 +41,9 @@ Run `nx serve my-app` for a dev server. Navigate to http://localhost:4200/. The
|
|||||||
|
|
||||||
### Running tests
|
### Running tests
|
||||||
|
|
||||||
Run `nx test my-app` to execute the unit tests with [Jest](https://jestjs.io), or `nx affected:test` to execute just unit tests affected by a change.
|
Run `yarn nx run <my-app>-e2e:e2e` to execute the e2e tests with [cypress](https://docs.cypress.io/). You can use the `--watch` flag to open the cypress tests UI in watch mode, see [cypress executor](https://nx.dev/packages/cypress/executors/cypress) for all CLI flags.
|
||||||
|
|
||||||
|
Run `nx test my-app` to execute the unit tests with [Jest](https://jestjs.io), or `nx affected:test` to execute just unit tests affected by a change. You can also use `--watch` with these test to run jest in watch mode, see [Jest executor](https://nx.dev/packages/jest/executors/jest) for all CLI flags.
|
||||||
|
|
||||||
Similarly `nx e2e my-app` will execute the end-to-end tests with [Cypress](https://www.cypress.io)., and `nx affected:e2e` will execute just the end-to-end tests affected by a change.
|
Similarly `nx e2e my-app` will execute the end-to-end tests with [Cypress](https://www.cypress.io)., and `nx affected:e2e` will execute just the end-to-end tests affected by a change.
|
||||||
|
|
||||||
@ -59,6 +62,13 @@ Follow the following steps to start using a local network with the Vega Explorer
|
|||||||
1. Start the explorer frontend application with the `.env.vegacapsule` env file
|
1. Start the explorer frontend application with the `.env.vegacapsule` env file
|
||||||
1. Go to [http://localhost:3000](http://localhost:3000) in your browser
|
1. Go to [http://localhost:3000](http://localhost:3000) in your browser
|
||||||
|
|
||||||
|
If you simply want to run Explorer locally, without using a local network:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd apps/explorer && cp .env.testnet .env.local
|
||||||
|
yarn nx run explorer:serve
|
||||||
|
```
|
||||||
|
|
||||||
# 📑 License
|
# 📑 License
|
||||||
|
|
||||||
[MIT](./LICENSE)
|
[MIT](./LICENSE)
|
||||||
|
@ -1 +0,0 @@
|
|||||||
export { KeyValueTable, KeyValueTableRow } from './key-value-table';
|
|
@ -1,85 +0,0 @@
|
|||||||
@import '../../styles/colors';
|
|
||||||
@import '../../styles/fonts';
|
|
||||||
|
|
||||||
$ns: 'key-value-table';
|
|
||||||
|
|
||||||
.#{$ns}__header,
|
|
||||||
.#{$ns}__footer {
|
|
||||||
margin: 10px 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$ns}__header {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$ns}__row {
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.#{$ns} {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-spacing: 0;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
word-break: break-all;
|
|
||||||
|
|
||||||
tr {
|
|
||||||
border-bottom: 1px solid $white;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-top: 1px solid $white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
word-break: break-word;
|
|
||||||
text-align: left;
|
|
||||||
font-weight: 500;
|
|
||||||
color: $white;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
vertical-align: top;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
color: $text-color;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bp3-tag {
|
|
||||||
margin: 0 5px 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.#{$ns}--numerical {
|
|
||||||
td {
|
|
||||||
font-family: $font-mono;
|
|
||||||
|
|
||||||
& button {
|
|
||||||
font-family: $font-main;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.#{$ns}--muted {
|
|
||||||
tr {
|
|
||||||
border-color: $gray1;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
border-top: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
import './key-value-table.scss';
|
|
||||||
|
|
||||||
import * as React from 'react';
|
|
||||||
|
|
||||||
export interface KeyValueTableProps
|
|
||||||
extends React.HTMLAttributes<HTMLTableElement> {
|
|
||||||
title?: string;
|
|
||||||
numerical?: boolean; // makes all values monospace
|
|
||||||
children: React.ReactNode;
|
|
||||||
muted?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const KeyValueTable = ({
|
|
||||||
title,
|
|
||||||
numerical,
|
|
||||||
children,
|
|
||||||
muted,
|
|
||||||
className,
|
|
||||||
...rest
|
|
||||||
}: KeyValueTableProps) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{title && <h3 className="key-value-table__header">{title}</h3>}
|
|
||||||
<table
|
|
||||||
data-testid="key-value-table"
|
|
||||||
{...rest}
|
|
||||||
className={`key-value-table ${className ? className : ''} ${
|
|
||||||
numerical ? 'key-value-table--numerical' : ''
|
|
||||||
}
|
|
||||||
${muted ? 'key-value-table--muted' : ''}`}
|
|
||||||
>
|
|
||||||
<tbody>{children}</tbody>
|
|
||||||
</table>
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface KeyValueTableRowProps
|
|
||||||
extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
||||||
children: [React.ReactNode, React.ReactNode];
|
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const KeyValueTableRow = ({
|
|
||||||
children,
|
|
||||||
className,
|
|
||||||
...rest
|
|
||||||
}: KeyValueTableRowProps) => {
|
|
||||||
return (
|
|
||||||
<tr
|
|
||||||
{...rest}
|
|
||||||
className={`key-value-table__row ${className ? className : ''}`}
|
|
||||||
>
|
|
||||||
{children[0]}
|
|
||||||
{children[1]}
|
|
||||||
</tr>
|
|
||||||
);
|
|
||||||
};
|
|
@ -5,3 +5,9 @@ export const formatNumber = (value: BigNumber, decimals?: number) => {
|
|||||||
typeof decimals === 'undefined' ? Math.max(value.dp(), 2) : decimals;
|
typeof decimals === 'undefined' ? Math.max(value.dp(), 2) : decimals;
|
||||||
return value.dp(decimalPlaces).toFormat(decimalPlaces);
|
return value.dp(decimalPlaces).toFormat(decimalPlaces);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatNumberPercentage = (value: BigNumber, decimals?: number) => {
|
||||||
|
const decimalPlaces =
|
||||||
|
typeof decimals === 'undefined' ? Math.max(value.dp(), 2) : decimals;
|
||||||
|
return `${value.dp(decimalPlaces).toFormat(decimalPlaces)}%`;
|
||||||
|
};
|
||||||
|
@ -8,10 +8,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import type { Tranche } from '@vegaprotocol/smart-contracts-sdk';
|
import type { Tranche } from '@vegaprotocol/smart-contracts-sdk';
|
||||||
|
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../components/key-value-table';
|
|
||||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||||
import { DATE_FORMAT_LONG } from '../../lib/date-formats';
|
import { DATE_FORMAT_LONG } from '../../lib/date-formats';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
@ -159,37 +156,34 @@ export const ClaimFlow = ({
|
|||||||
<div>
|
<div>
|
||||||
<KeyValueTable>
|
<KeyValueTable>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Connected Ethereum address')}</th>
|
{t('Connected Ethereum address')}
|
||||||
<td>{truncateMiddle(address)}</td>
|
{truncateMiddle(address)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Amount of VEGA')}</th>
|
{t('Amount of VEGA')}
|
||||||
<td>
|
|
||||||
{state.claimData
|
{state.claimData
|
||||||
? formatNumber(state.claimData.claim.amount)
|
? formatNumber(state.claimData.claim.amount)
|
||||||
: 'None'}
|
: 'None'}
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Claim expires')}</th>
|
{t('Claim expires')}
|
||||||
<td>
|
|
||||||
{state.claimData?.claim.expiry
|
{state.claimData?.claim.expiry
|
||||||
? format(
|
? format(
|
||||||
state.claimData?.claim.expiry * 1000,
|
state.claimData?.claim.expiry * 1000,
|
||||||
DATE_FORMAT_LONG
|
DATE_FORMAT_LONG
|
||||||
)
|
)
|
||||||
: 'No expiry'}
|
: 'No expiry'}
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Starts unlocking')}</th>
|
{t('Starts unlocking')}
|
||||||
<td>
|
|
||||||
{format(currentTranche.tranche_start, DATE_FORMAT_LONG)}
|
{format(currentTranche.tranche_start, DATE_FORMAT_LONG)}
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Fully unlocked')}</th>
|
{t('Fully unlocked')}
|
||||||
<td>{format(currentTranche.tranche_end, DATE_FORMAT_LONG)}</td>
|
{format(currentTranche.tranche_end, DATE_FORMAT_LONG)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { format, isFuture } from 'date-fns';
|
import { format, isFuture } from 'date-fns';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../../../components/key-value-table';
|
|
||||||
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
||||||
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
||||||
import { CurrentProposalState } from '../current-proposal-state';
|
import { CurrentProposalState } from '../current-proposal-state';
|
||||||
@ -19,60 +16,50 @@ export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {
|
|||||||
const terms = proposal.terms;
|
const terms = proposal.terms;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<KeyValueTable muted={true} data-testid="proposal-change-table">
|
<KeyValueTable data-testid="proposal-change-table" muted={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('id')}</th>
|
{t('id')}
|
||||||
<td>{proposal.id}</td>
|
{proposal.id}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('state')}</th>
|
{t('state')}
|
||||||
<td>
|
<CurrentProposalState proposal={proposal} />
|
||||||
<CurrentProposalState proposal={proposal} />
|
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>
|
{isFuture(new Date(terms.closingDatetime))
|
||||||
{isFuture(new Date(terms.closingDatetime))
|
? t('closesOn')
|
||||||
? t('closesOn')
|
: t('closedOn')}
|
||||||
: t('closedOn')}
|
{format(new Date(terms.closingDatetime), DATE_FORMAT_DETAILED)}
|
||||||
</th>
|
|
||||||
<td>{format(new Date(terms.closingDatetime), DATE_FORMAT_DETAILED)}</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>
|
{isFuture(new Date(terms.enactmentDatetime))
|
||||||
{isFuture(new Date(terms.enactmentDatetime))
|
? t('proposedEnactment')
|
||||||
? t('proposedEnactment')
|
: t('enactedOn')}
|
||||||
: t('enactedOn')}
|
{format(new Date(terms.enactmentDatetime), DATE_FORMAT_DETAILED)}
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
{format(new Date(terms.enactmentDatetime), DATE_FORMAT_DETAILED)}
|
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('proposedBy')}</th>
|
{t('proposedBy')}
|
||||||
<td>
|
<span style={{ wordBreak: 'break-word' }}>{proposal.party.id}</span>
|
||||||
<span style={{ wordBreak: 'break-word' }}>{proposal.party.id}</span>
|
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('proposedOn')}</th>
|
{t('proposedOn')}
|
||||||
<td>{format(new Date(proposal.datetime), DATE_FORMAT_DETAILED)}</td>
|
{format(new Date(proposal.datetime), DATE_FORMAT_DETAILED)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
{proposal.rejectionReason ? (
|
{proposal.rejectionReason ? (
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('rejectionReason')}</th>
|
{t('rejectionReason')}
|
||||||
<td>{proposal.rejectionReason}</td>
|
{proposal.rejectionReason}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
) : null}
|
) : null}
|
||||||
{proposal.errorDetails ? (
|
{proposal.errorDetails ? (
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('errorDetails')}</th>
|
{t('errorDetails')}
|
||||||
<td>{proposal.errorDetails}</td>
|
{proposal.errorDetails}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
) : null}
|
) : null}
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('type')}</th>
|
{t('type')}
|
||||||
<td>{proposal.terms.change.__typename}</td>
|
{proposal.terms.change.__typename}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
KeyValueTable,
|
formatNumber,
|
||||||
KeyValueTableRow,
|
formatNumberPercentage,
|
||||||
} from '../../../../components/key-value-table';
|
} from '../../../../lib/format-number';
|
||||||
import { formatNumber } from '../../../../lib/format-number';
|
|
||||||
import { useVoteInformation } from '../../hooks';
|
import { useVoteInformation } from '../../hooks';
|
||||||
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
||||||
|
|
||||||
@ -34,65 +34,65 @@ export const ProposalVotesTable = ({ proposal }: ProposalVotesTableProps) => {
|
|||||||
return (
|
return (
|
||||||
<KeyValueTable
|
<KeyValueTable
|
||||||
title={t('voteBreakdown')}
|
title={t('voteBreakdown')}
|
||||||
numerical={true}
|
|
||||||
muted={true}
|
|
||||||
data-testid="proposal-votes-table"
|
data-testid="proposal-votes-table"
|
||||||
|
muted={true}
|
||||||
|
numerical={true}
|
||||||
>
|
>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('willPass')}</th>
|
{t('willPass')}
|
||||||
<td>{willPass ? '👍' : '👎'}</td>
|
{willPass ? '👍' : '👎'}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('majorityMet')}</th>
|
{t('majorityMet')}
|
||||||
<td>{majorityMet ? '👍' : '👎'}</td>
|
{majorityMet ? '👍' : '👎'}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('participationMet')}</th>
|
{t('participationMet')}
|
||||||
<td>{participationMet ? '👍' : '👎'}</td>
|
{participationMet ? '👍' : '👎'}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('tokenForProposal')}</th>
|
{t('tokenForProposal')}
|
||||||
<td>{formatNumber(yesTokens, 2)}</td>
|
{formatNumber(yesTokens, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('tokensAgainstProposal')}</th>
|
{t('tokensAgainstProposal')}
|
||||||
<td>{formatNumber(noTokens, 2)}</td>
|
{formatNumber(noTokens, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('participationRequired')}</th>
|
{t('participationRequired')}
|
||||||
<td>{formatNumber(requiredParticipation)}%</td>
|
{formatNumberPercentage(requiredParticipation)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('majorityRequired')}</th>
|
{t('majorityRequired')}
|
||||||
<td>{formatNumber(requiredMajorityPercentage)}%</td>
|
{formatNumberPercentage(requiredMajorityPercentage)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('numberOfVotingParties')}</th>
|
{t('numberOfVotingParties')}
|
||||||
<td>{formatNumber(totalVotes, 0)}</td>
|
{formatNumber(totalVotes, 0)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('totalTokensVotes')}</th>
|
{t('totalTokensVotes')}
|
||||||
<td>{formatNumber(totalTokensVoted, 2)}</td>
|
{formatNumber(totalTokensVoted, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('totalTokenVotedPercentage')}</th>
|
{t('totalTokenVotedPercentage')}
|
||||||
<td>{formatNumber(totalTokensPercentage, 2)}%</td>
|
{formatNumberPercentage(totalTokensPercentage, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('numberOfForVotes')}</th>
|
{t('numberOfForVotes')}
|
||||||
<td>{formatNumber(yesVotes, 0)}</td>
|
{formatNumber(yesVotes, 0)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('numberOfAgainstVotes')}</th>
|
{t('numberOfAgainstVotes')}
|
||||||
<td>{formatNumber(noVotes, 0)}</td>
|
{formatNumber(noVotes, 0)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('yesPercentage')}</th>
|
{t('yesPercentage')}
|
||||||
<td>{formatNumber(yesPercentage, 2)}%</td>
|
{formatNumberPercentage(yesPercentage, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('noPercentage')}</th>
|
{t('noPercentage')}
|
||||||
<td>{formatNumber(noPercentage, 2)}%</td>
|
{formatNumberPercentage(noPercentage, 2)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
@ -4,10 +4,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { Heading } from '../../../../components/heading';
|
import { Heading } from '../../../../components/heading';
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../../../components/key-value-table';
|
|
||||||
import { getProposalName } from '../../../../lib/type-policies/proposal';
|
import { getProposalName } from '../../../../lib/type-policies/proposal';
|
||||||
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
import type { Proposals_proposals } from '../../proposals/__generated__/Proposals';
|
||||||
import { CurrentProposalState } from '../current-proposal-state';
|
import { CurrentProposalState } from '../current-proposal-state';
|
||||||
@ -33,36 +30,34 @@ export const ProposalsList = ({ proposals }: ProposalsListProps) => {
|
|||||||
</Link>
|
</Link>
|
||||||
<KeyValueTable muted={true}>
|
<KeyValueTable muted={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('state')}</th>
|
{t('state')}
|
||||||
<td data-testid="governance-proposal-state">
|
<span data-testid="governance-proposal-state">
|
||||||
<CurrentProposalState proposal={proposal} />
|
<CurrentProposalState proposal={proposal} />
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>
|
{isFuture(new Date(proposal.terms.closingDatetime))
|
||||||
{isFuture(new Date(proposal.terms.closingDatetime))
|
? t('closesOn')
|
||||||
? t('closesOn')
|
: t('closedOn')}
|
||||||
: t('closedOn')}
|
|
||||||
</th>
|
<span data-testid="governance-proposal-closingDate">
|
||||||
<td data-testid="governance-proposal-closingDate">
|
|
||||||
{format(
|
{format(
|
||||||
new Date(proposal.terms.closingDatetime),
|
new Date(proposal.terms.closingDatetime),
|
||||||
DATE_FORMAT_DETAILED
|
DATE_FORMAT_DETAILED
|
||||||
)}
|
)}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>
|
{isFuture(new Date(proposal.terms.enactmentDatetime))
|
||||||
{isFuture(new Date(proposal.terms.enactmentDatetime))
|
? t('proposedEnactment')
|
||||||
? t('proposedEnactment')
|
: t('enactedOn')}
|
||||||
: t('enactedOn')}
|
|
||||||
</th>
|
<span data-testid="governance-proposal-enactmentDate">
|
||||||
<td data-testid="governance-proposal-enactmentDate">
|
|
||||||
{format(
|
{format(
|
||||||
new Date(proposal.terms.enactmentDatetime),
|
new Date(proposal.terms.enactmentDatetime),
|
||||||
DATE_FORMAT_DETAILED
|
DATE_FORMAT_DETAILED
|
||||||
)}
|
)}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
</li>
|
</li>
|
||||||
|
@ -37,8 +37,8 @@ export const TokenDetailsCirculating = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const totalCirculating = sumCirculatingTokens(tranches);
|
const totalCirculating = sumCirculatingTokens(tranches);
|
||||||
return (
|
return (
|
||||||
<td data-testid="circulating-supply">
|
<span data-testid="circulating-supply">
|
||||||
{formatNumber(totalCirculating, 2)}
|
{formatNumber(totalCirculating, 2)}
|
||||||
</td>
|
</span>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,10 +3,7 @@ import './token-details.scss';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../../components/key-value-table';
|
|
||||||
import { ADDRESSES } from '../../../config';
|
import { ADDRESSES } from '../../../config';
|
||||||
import { useTranches } from '../../../hooks/use-tranches';
|
import { useTranches } from '../../../hooks/use-tranches';
|
||||||
import type { BigNumber } from '../../../lib/bignumber';
|
import type { BigNumber } from '../../../lib/bignumber';
|
||||||
@ -26,36 +23,34 @@ export const TokenDetails = ({
|
|||||||
return (
|
return (
|
||||||
<KeyValueTable className={'token-details'}>
|
<KeyValueTable className={'token-details'}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Token address')}</th>
|
{t('Token address')}
|
||||||
<td data-testid="token-address">
|
<EtherscanLink
|
||||||
<EtherscanLink
|
data-testid="token-address"
|
||||||
address={ADDRESSES.vegaTokenAddress}
|
address={ADDRESSES.vegaTokenAddress}
|
||||||
text={ADDRESSES.vegaTokenAddress}
|
text={ADDRESSES.vegaTokenAddress}
|
||||||
className="font-mono"
|
className="font-mono"
|
||||||
/>
|
/>
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Vesting contract')}</th>
|
{t('Vesting contract')}
|
||||||
<td data-testid="token-contract">
|
<EtherscanLink
|
||||||
<EtherscanLink
|
data-testid="token-contract"
|
||||||
address={ADDRESSES.vestingAddress}
|
address={ADDRESSES.vestingAddress}
|
||||||
text={ADDRESSES.vestingAddress}
|
text={ADDRESSES.vestingAddress}
|
||||||
className="font-mono"
|
className="font-mono"
|
||||||
/>
|
/>
|
||||||
</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Total supply')}</th>
|
{t('Total supply')}
|
||||||
<td data-testid="total-supply">{formatNumber(totalSupply, 2)}</td>
|
<span data-testid="total-supply">{formatNumber(totalSupply, 2)}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Circulating supply')}</th>
|
{t('Circulating supply')}
|
||||||
<TokenDetailsCirculating tranches={tranches} />
|
<TokenDetailsCirculating tranches={tranches} />
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Staked on Vega validator')}</th>
|
{t('Staked on Vega validator')}
|
||||||
<td data-testid="staked">{formatNumber(totalStaked, 2)}</td>
|
<span data-testid="staked">{formatNumber(totalStaked, 2)}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
@ -3,10 +3,7 @@ import './vesting-table.scss';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../../components/key-value-table';
|
|
||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { formatNumber } from '../../../lib/format-number';
|
import { formatNumber } from '../../../lib/format-number';
|
||||||
|
|
||||||
@ -42,29 +39,29 @@ export const VestingTable = ({
|
|||||||
data-testid="vesting-table-total"
|
data-testid="vesting-table-total"
|
||||||
className="vesting-table__top-solid-border"
|
className="vesting-table__top-solid-border"
|
||||||
>
|
>
|
||||||
<th>{t('Vesting VEGA')}</th>
|
<span>{t('Vesting VEGA')}</span>
|
||||||
<td>{formatNumber(total)}</td>
|
{formatNumber(total)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow data-testid="vesting-table-locked">
|
<KeyValueTableRow data-testid="vesting-table-locked">
|
||||||
<th>
|
<span>
|
||||||
<div className="vesting-table__indicator-square vesting-table__indicator-square--locked"></div>
|
<span className="vesting-table__indicator-square vesting-table__indicator-square--locked"></span>
|
||||||
{t('Locked')}
|
{t('Locked')}
|
||||||
</th>
|
</span>
|
||||||
<td>{formatNumber(locked)}</td>
|
{formatNumber(locked)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow data-testid="vesting-table-unlocked">
|
<KeyValueTableRow data-testid="vesting-table-unlocked">
|
||||||
<th>
|
<span>
|
||||||
<div className="vesting-table__indicator-square vesting-table__indicator-square--unlocked"></div>
|
<span className="vesting-table__indicator-square vesting-table__indicator-square--unlocked"></span>
|
||||||
{t('Unlocked')}
|
{t('Unlocked')}
|
||||||
</th>
|
</span>
|
||||||
<td>{formatNumber(vested)}</td>
|
{formatNumber(vested)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow data-testid="vesting-table-staked">
|
<KeyValueTableRow data-testid="vesting-table-staked">
|
||||||
<th>
|
<span>
|
||||||
<div className="vesting-table__indicator-square vesting-table__indicator-square--staked"></div>
|
<span className="vesting-table__indicator-square vesting-table__indicator-square--staked"></span>
|
||||||
{t('Associated')}
|
{t('Associated')}
|
||||||
</th>
|
</span>
|
||||||
<td>{formatNumber(associated)}</td>
|
{formatNumber(associated)}
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
<div className="vesting-table__progress-bar">
|
<div className="vesting-table__progress-bar">
|
||||||
|
@ -4,10 +4,7 @@ import React from 'react';
|
|||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../components/key-value-table';
|
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
import { Routes } from '../router-config';
|
import { Routes } from '../router-config';
|
||||||
@ -41,16 +38,15 @@ export const Tranche0Table = ({
|
|||||||
<>
|
<>
|
||||||
<KeyValueTable numerical={true}>
|
<KeyValueTable numerical={true}>
|
||||||
<KeyValueTableRow data-testid="tranche-table-total">
|
<KeyValueTableRow data-testid="tranche-table-total">
|
||||||
<th>
|
<span className="tranche-table__label">
|
||||||
<span className="tranche-table__label">
|
{t('Tranche')} {trancheId}
|
||||||
{t('Tranche')} {trancheId}
|
</span>
|
||||||
</span>
|
|
||||||
</th>
|
<span>{formatNumber(total)}</span>
|
||||||
<td>{formatNumber(total)}</td>
|
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow data-testid="tranche-table-locked">
|
<KeyValueTableRow data-testid="tranche-table-locked">
|
||||||
<th>{t('Locked')}</th>
|
{t('Locked')}
|
||||||
<td>{formatNumber(total)}</td>
|
<span>{formatNumber(total)}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
<div className="tranche-table__footer" data-testid="tranche-table-footer">
|
<div className="tranche-table__footer" data-testid="tranche-table-footer">
|
||||||
|
@ -5,10 +5,7 @@ import { format } from 'date-fns';
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../../components/key-value-table';
|
|
||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { DATE_FORMAT_DETAILED } from '../../../lib/date-formats';
|
import { DATE_FORMAT_DETAILED } from '../../../lib/date-formats';
|
||||||
import type {
|
import type {
|
||||||
@ -122,26 +119,30 @@ export const RewardTable = ({ reward, delegations }: RewardTableProps) => {
|
|||||||
</h3>
|
</h3>
|
||||||
<KeyValueTable>
|
<KeyValueTable>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('rewardType')}</th>
|
{t('rewardType')}
|
||||||
<td>{DEFAULT_REWARD_TYPE}</td>
|
<span>{DEFAULT_REWARD_TYPE}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('yourStake')}</th>
|
{t('yourStake')}
|
||||||
<td>{stakeForEpoch.toString()}</td>
|
<span>{stakeForEpoch.toString()}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('reward')}</th>
|
{t('reward')}
|
||||||
<td>
|
<span>
|
||||||
{reward.amountFormatted} {t('VEGA')}
|
{reward.amountFormatted} {t('VEGA')}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('shareOfReward')}</th>
|
{t('shareOfReward')}
|
||||||
<td>{new BigNumber(reward.percentageOfTotal).dp(2).toString()}%</td>
|
<span>
|
||||||
|
{new BigNumber(reward.percentageOfTotal).dp(2).toString()}%
|
||||||
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('received')}</th>
|
{t('received')}
|
||||||
<td>{format(new Date(reward.receivedAt), DATE_FORMAT_DETAILED)}</td>
|
<span>
|
||||||
|
{format(new Date(reward.receivedAt), DATE_FORMAT_DETAILED)}
|
||||||
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,10 +4,7 @@ import React from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../components/key-value-table';
|
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
import type { Staking_nodes } from './__generated__/Staking';
|
import type { Staking_nodes } from './__generated__/Staking';
|
||||||
@ -37,59 +34,59 @@ export const ValidatorTable = ({
|
|||||||
return (
|
return (
|
||||||
<KeyValueTable data-testid="validator-table">
|
<KeyValueTable data-testid="validator-table">
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('id')}:</th>
|
<span>{t('id')}:</span>
|
||||||
<td className="validator-table__cell">{node.id}</td>
|
<span className="validator-table__cell">{node.id}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('VEGA ADDRESS / PUBLIC KEY')}</th>
|
<span>{t('VEGA ADDRESS / PUBLIC KEY')}</span>
|
||||||
<td className="validator-table__cell">{node.pubkey}</td>
|
<span className="validator-table__cell">{node.pubkey}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('ABOUT THIS VALIDATOR')}</th>
|
<span>{t('ABOUT THIS VALIDATOR')}</span>
|
||||||
<td>
|
<span>
|
||||||
<a href={node.infoUrl}>{node.infoUrl}</a>
|
<a href={node.infoUrl}>{node.infoUrl}</a>
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('IP ADDRESS')}</th>
|
<span>{t('IP ADDRESS')}</span>
|
||||||
<td>{node.location}</td>
|
<span>{node.location}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('ETHEREUM ADDRESS')}</th>
|
<span>{t('ETHEREUM ADDRESS')}</span>
|
||||||
<td>
|
<span>
|
||||||
<EtherscanLink
|
<EtherscanLink
|
||||||
text={node.ethereumAdddress}
|
text={node.ethereumAdddress}
|
||||||
address={node.ethereumAdddress}
|
address={node.ethereumAdddress}
|
||||||
/>
|
/>
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('TOTAL STAKE')}</th>
|
<span>{t('TOTAL STAKE')}</span>
|
||||||
<td>{node.stakedTotalFormatted}</td>
|
<span>{node.stakedTotalFormatted}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('PENDING STAKE')}</th>
|
<span>{t('PENDING STAKE')}</span>
|
||||||
<td>{node.pendingStakeFormatted}</td>
|
<span>{node.pendingStakeFormatted}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('STAKED BY OPERATOR')}</th>
|
<span>{t('STAKED BY OPERATOR')}</span>
|
||||||
<td>{node.stakedByOperatorFormatted}</td>
|
<span>{node.stakedByOperatorFormatted}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('STAKED BY DELEGATES')}</th>
|
<span>{t('STAKED BY DELEGATES')}</span>
|
||||||
<td>{node.stakedByDelegatesFormatted}</td>
|
<span>{node.stakedByDelegatesFormatted}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('STAKE SHARE')}</th>
|
<span>{t('STAKE SHARE')}</span>
|
||||||
<td>{stakePercentage}</td>
|
<span>{stakePercentage}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('OWN STAKE (THIS EPOCH)')}</th>
|
<span>{t('OWN STAKE (THIS EPOCH)')}</span>
|
||||||
<td>{formatNumber(stakeThisEpoch)}</td>
|
<span>{formatNumber(stakeThisEpoch)}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('NOMINATED (THIS EPOCH)')}</th>
|
<span>{t('NOMINATED (THIS EPOCH)')}</span>
|
||||||
<td>{node.stakedByDelegatesFormatted}</td>
|
<span>{node.stakedByDelegatesFormatted}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../components/key-value-table';
|
|
||||||
import { formatNumber } from '../../lib/format-number';
|
import { formatNumber } from '../../lib/format-number';
|
||||||
import type { BigNumber } from '../../lib/bignumber';
|
import type { BigNumber } from '../../lib/bignumber';
|
||||||
|
|
||||||
@ -23,12 +20,16 @@ export const YourStake = ({
|
|||||||
<h2>{t('Your stake')}</h2>
|
<h2>{t('Your stake')}</h2>
|
||||||
<KeyValueTable>
|
<KeyValueTable>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Your Stake On Node (This Epoch)')}</th>
|
{t('Your Stake On Node (This Epoch)')}
|
||||||
<td data-testid="stake-this-epoch">{formatNumber(stakeThisEpoch)}</td>
|
<span data-testid="stake-this-epoch">
|
||||||
|
{formatNumber(stakeThisEpoch)}
|
||||||
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Your Stake On Node (Next Epoch)')}</th>
|
{t('Your Stake On Node (Next Epoch)')}
|
||||||
<td data-testid="stake-next-epoch">{formatNumber(stakeNextEpoch)}</td>
|
<span data-testid="stake-next-epoch">
|
||||||
|
{formatNumber(stakeNextEpoch)}
|
||||||
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,10 +10,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
import { EtherscanLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { Heading } from '../../components/heading';
|
import { Heading } from '../../components/heading';
|
||||||
import {
|
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||||
KeyValueTable,
|
|
||||||
KeyValueTableRow,
|
|
||||||
} from '../../components/key-value-table';
|
|
||||||
import { SplashLoader } from '../../components/splash-loader';
|
import { SplashLoader } from '../../components/splash-loader';
|
||||||
import { TransactionButton } from '../../components/transaction-button';
|
import { TransactionButton } from '../../components/transaction-button';
|
||||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||||
@ -197,46 +194,46 @@ export const Withdrawal = ({
|
|||||||
<div>
|
<div>
|
||||||
<KeyValueTable>
|
<KeyValueTable>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Withdraw')}</th>
|
{t('Withdraw')}
|
||||||
<td>
|
<span>
|
||||||
{addDecimal(
|
{addDecimal(
|
||||||
new BigNumber(withdrawal.amount),
|
new BigNumber(withdrawal.amount),
|
||||||
withdrawal.asset.decimals
|
withdrawal.asset.decimals
|
||||||
)}{' '}
|
)}{' '}
|
||||||
{withdrawal.asset.symbol}
|
{withdrawal.asset.symbol}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('from')}</th>
|
{t('from')}
|
||||||
<td>{truncateMiddle(withdrawal.party.id)}</td>
|
<span>{truncateMiddle(withdrawal.party.id)}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('toEthereum')}</th>
|
{t('toEthereum')}
|
||||||
<td>
|
<span>
|
||||||
<EtherscanLink
|
<EtherscanLink
|
||||||
address={withdrawal.details?.receiverAddress as string}
|
address={withdrawal.details?.receiverAddress as string}
|
||||||
text={truncateMiddle(
|
text={truncateMiddle(
|
||||||
withdrawal.details?.receiverAddress as string
|
withdrawal.details?.receiverAddress as string
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('created')}</th>
|
{t('created')}
|
||||||
<td>
|
<span>
|
||||||
{format(
|
{format(
|
||||||
new Date(withdrawal.createdTimestamp),
|
new Date(withdrawal.createdTimestamp),
|
||||||
DATE_FORMAT_DETAILED
|
DATE_FORMAT_DETAILED
|
||||||
)}
|
)}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<th>{t('Signature')}</th>
|
{t('Signature')}
|
||||||
<td title={erc20Approval?.signatures}>
|
<span title={erc20Approval?.signatures}>
|
||||||
{!erc20Approval?.signatures
|
{!erc20Approval?.signatures
|
||||||
? t('Loading')
|
? t('Loading')
|
||||||
: truncateMiddle(erc20Approval.signatures)}
|
: truncateMiddle(erc20Approval.signatures)}
|
||||||
</td>
|
</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
<TransactionButton
|
<TransactionButton
|
||||||
|
@ -107,7 +107,7 @@ module.exports = {
|
|||||||
full: '9999px',
|
full: '9999px',
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
mono: defaultTheme.fontFamily.mono,
|
mono: ['Roboto Mono', ...defaultTheme.fontFamily.mono],
|
||||||
serif: defaultTheme.fontFamily.serif,
|
serif: defaultTheme.fontFamily.serif,
|
||||||
sans: [
|
sans: [
|
||||||
'"Helvetica Neue"',
|
'"Helvetica Neue"',
|
||||||
|
24
libs/ui-toolkit/src/components/index.ts
Normal file
24
libs/ui-toolkit/src/components/index.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
export * from './ag-grid';
|
||||||
|
export * from './async-renderer';
|
||||||
|
export * from './button';
|
||||||
|
export * from './callout';
|
||||||
|
export * from './card';
|
||||||
|
export * from './copy-with-tooltip';
|
||||||
|
export * from './dialog';
|
||||||
|
export * from './etherscan-link';
|
||||||
|
export * from './form-group';
|
||||||
|
export * from './icon';
|
||||||
|
export * from './indicator';
|
||||||
|
export * from './input';
|
||||||
|
export * from './input-error';
|
||||||
|
export * from './key-value-table';
|
||||||
|
export * from './loader';
|
||||||
|
export * from './lozenge';
|
||||||
|
export * from './select';
|
||||||
|
export * from './splash';
|
||||||
|
export * from './text-area';
|
||||||
|
export * from './theme-switcher';
|
||||||
|
export * from './toggle';
|
||||||
|
export * from './tooltip';
|
||||||
|
export * from './vega-logo';
|
||||||
|
export * from './syntax-highlighter';
|
1
libs/ui-toolkit/src/components/key-value-table/index.ts
Normal file
1
libs/ui-toolkit/src/components/key-value-table/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './key-value-table';
|
@ -0,0 +1,48 @@
|
|||||||
|
import type { Story, Meta } from '@storybook/react';
|
||||||
|
import { KeyValueTable, KeyValueTableRow } from './key-value-table';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
component: KeyValueTable,
|
||||||
|
title: 'KeyValueTable',
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: Story = (args) => (
|
||||||
|
<KeyValueTable {...args}>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{'Token address'}
|
||||||
|
{'0x888'}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{'Value'}
|
||||||
|
{888}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{'Token address'}
|
||||||
|
{'0x888'}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
</KeyValueTable>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Muted = Template.bind({});
|
||||||
|
Muted.args = {
|
||||||
|
title: 'Muted table',
|
||||||
|
muted: true,
|
||||||
|
numerical: false,
|
||||||
|
headingLevel: 5, // h5
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Numerical = Template.bind({});
|
||||||
|
Numerical.args = {
|
||||||
|
title: 'Numerical table',
|
||||||
|
muted: false,
|
||||||
|
numerical: true,
|
||||||
|
headingLevel: 5, // h5
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Normal = Template.bind({});
|
||||||
|
Normal.args = {
|
||||||
|
headingLevel: 5, // h5
|
||||||
|
title: 'Normal table',
|
||||||
|
muted: false,
|
||||||
|
numerical: false,
|
||||||
|
};
|
@ -1,31 +1,34 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
|
||||||
|
import type { KeyValueTableProps } from './key-value-table';
|
||||||
import { KeyValueTable, KeyValueTableRow } from './key-value-table';
|
import { KeyValueTable, KeyValueTableRow } from './key-value-table';
|
||||||
|
|
||||||
const props = {
|
const props: KeyValueTableProps = {
|
||||||
title: 'Title',
|
title: 'Title',
|
||||||
|
headingLevel: 3,
|
||||||
|
children: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
it('Renders the correct elements', () => {
|
it('Renders the correct elements', () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<KeyValueTable {...props}>
|
<KeyValueTable {...props}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<td>My label</td>
|
<span>My label</span>
|
||||||
<td>My value</td>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<td>My label 2</td>
|
<span>My label 2</span>
|
||||||
<td>My value 2</td>
|
<span>My value 2</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText(props.title)).toBeInTheDocument();
|
expect(screen.getByText(props.title || '')).toBeInTheDocument();
|
||||||
|
|
||||||
expect(container.querySelector('.key-value-table')).toBeInTheDocument();
|
expect(screen.getByTestId('key-value-table')).toBeInTheDocument();
|
||||||
expect(container.querySelectorAll('.key-value-table__row')).toHaveLength(2);
|
expect(container.getElementsByTagName('dl')).toHaveLength(2);
|
||||||
|
|
||||||
const rows = container.querySelectorAll('.key-value-table__row');
|
const rows = container.getElementsByTagName('dl');
|
||||||
// Row 1
|
// Row 1
|
||||||
expect(rows[0].firstChild).toHaveTextContent('My label');
|
expect(rows[0].firstChild).toHaveTextContent('My label');
|
||||||
expect(rows[0].children[1]).toHaveTextContent('My value');
|
expect(rows[0].children[1]).toHaveTextContent('My value');
|
||||||
@ -37,30 +40,30 @@ it('Renders the correct elements', () => {
|
|||||||
|
|
||||||
it('Applies numeric class if prop is passed', () => {
|
it('Applies numeric class if prop is passed', () => {
|
||||||
render(
|
render(
|
||||||
<KeyValueTable numerical={true} {...props}>
|
<KeyValueTable {...props} numerical={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<td>My label</td>
|
<span>My label</span>
|
||||||
<td>My value</td>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
||||||
'key-value-table--numerical'
|
'w-full border-collapse mb-8 [border-spacing:0] break-all'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Applies muted class if prop is passed', () => {
|
it('Applies muted class if prop is passed', () => {
|
||||||
render(
|
render(
|
||||||
<KeyValueTable muted={true} {...props}>
|
<KeyValueTable {...props} muted={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow>
|
||||||
<td>My label</td>
|
<span>My label</span>
|
||||||
<td>My value</td>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
||||||
'key-value-table--muted'
|
'w-full border-collapse mb-8 [border-spacing:0] break-all'
|
||||||
);
|
);
|
||||||
});
|
});
|
@ -0,0 +1,95 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
export interface KeyValueTableProps
|
||||||
|
extends React.HTMLAttributes<HTMLTableElement> {
|
||||||
|
title?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
|
||||||
|
muted?: boolean;
|
||||||
|
numerical?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const KeyValueTable = ({
|
||||||
|
title,
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
muted,
|
||||||
|
numerical,
|
||||||
|
headingLevel,
|
||||||
|
...rest
|
||||||
|
}: KeyValueTableProps) => {
|
||||||
|
const TitleTag: keyof JSX.IntrinsicElements = headingLevel
|
||||||
|
? `h${headingLevel}`
|
||||||
|
: 'div';
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{title && (
|
||||||
|
<TitleTag className={`text-h${headingLevel} mt-8 mb-4`}>
|
||||||
|
{title}
|
||||||
|
</TitleTag>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
data-testid="key-value-table"
|
||||||
|
{...rest}
|
||||||
|
className={`w-full border-collapse mb-8 [border-spacing:0] break-all ${
|
||||||
|
className ? className : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{children &&
|
||||||
|
React.Children.map(
|
||||||
|
children,
|
||||||
|
(child) =>
|
||||||
|
child &&
|
||||||
|
React.cloneElement(
|
||||||
|
child as React.ReactElement<KeyValueTableRowProps>,
|
||||||
|
{
|
||||||
|
muted,
|
||||||
|
numerical,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface KeyValueTableRowProps
|
||||||
|
extends React.HTMLAttributes<HTMLTableRowElement> {
|
||||||
|
children: [React.ReactNode, React.ReactNode];
|
||||||
|
className?: string;
|
||||||
|
numerical?: boolean; // makes all values monospace
|
||||||
|
muted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const KeyValueTableRow = ({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
muted,
|
||||||
|
numerical,
|
||||||
|
}: KeyValueTableRowProps) => {
|
||||||
|
const dlClassName = classNames(
|
||||||
|
'flex flex-wrap justify-between items-center border-b first:border-t border-black dark:border-white',
|
||||||
|
{
|
||||||
|
'border-black/60 dark:border-white/60 first:[border-top:none] last:[border-bottom:none]':
|
||||||
|
muted,
|
||||||
|
},
|
||||||
|
className
|
||||||
|
);
|
||||||
|
const dtClassName = `break-normal font-medium uppercase align-top p-4`;
|
||||||
|
const ddClassName = classNames(
|
||||||
|
'align-top p-4 text-black/60 dark:text-white/60 break-normal',
|
||||||
|
{
|
||||||
|
'font-mono': numerical,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<dl className={dlClassName}>
|
||||||
|
<dt className={dtClassName}>{children[0]}</dt>
|
||||||
|
<dd className={ddClassName}>{children[1]}</dd>
|
||||||
|
</dl>
|
||||||
|
);
|
||||||
|
};
|
@ -1,27 +1,5 @@
|
|||||||
// Components
|
// Components
|
||||||
export { AgGridLazy, AgGridDynamic } from './components/ag-grid';
|
export * from './components';
|
||||||
export { AsyncRenderer } from './components/async-renderer';
|
|
||||||
export { Button, AnchorButton } from './components/button';
|
|
||||||
export { Callout } from './components/callout';
|
|
||||||
export { CopyWithTooltip } from './components/copy-with-tooltip';
|
|
||||||
export { EtherscanLink } from './components/etherscan-link';
|
|
||||||
export { FormGroup } from './components/form-group';
|
|
||||||
export { Icon } from './components/icon';
|
|
||||||
export { Input } from './components/input';
|
|
||||||
export { InputError } from './components/input-error';
|
|
||||||
export { Lozenge } from './components/lozenge';
|
|
||||||
export { Loader } from './components/loader';
|
|
||||||
export { Select } from './components/select';
|
|
||||||
export { Splash } from './components/splash';
|
|
||||||
export { TextArea } from './components/text-area';
|
|
||||||
export { ThemeSwitcher } from './components/theme-switcher';
|
|
||||||
export { Toggle } from './components/toggle';
|
|
||||||
export { Dialog } from './components/dialog/dialog';
|
|
||||||
export { VegaLogo } from './components/vega-logo';
|
|
||||||
export { Tooltip } from './components/tooltip';
|
|
||||||
export { Indicator } from './components/indicator';
|
|
||||||
export { Card } from './components/card';
|
|
||||||
export { SyntaxHighlighter } from './components/syntax-highlighter';
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
export * from './utils/intent';
|
export * from './utils/intent';
|
||||||
|
Loading…
Reference in New Issue
Block a user