Feat/300 network parameters table (#333)
* network parameters table with key value rows and syntax blobs only for json values * inline row not for syntax * add unit test for network param table * add cypress test to verify if values are non-empty * remove some comments * rename formatNumber method to addDecimalsFormatNumber and simplify formatNumber * remove duplicate expect line * use AsyncRenderer and sort params asc * refactor and add extra tests to check ordering and loading cases * format big number params with addDecimals formatNumber * Update apps/explorer/src/app/routes/network-parameters/network-parameters.tsx Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com> * capitalize and refactor tests * missing ; caused formatting to fail Co-authored-by: madalinaraicu <“madalina@raygroup.uk”> Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>
This commit is contained in:
parent
431ea1bc80
commit
d03e4cf785
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -3,6 +3,7 @@
|
|||||||
"nrwl.angular-console",
|
"nrwl.angular-console",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"firsttris.vscode-jest-runner",
|
"firsttris.vscode-jest-runner",
|
||||||
"dbaeumer.vscode-eslint"
|
"dbaeumer.vscode-eslint",
|
||||||
|
"stevejpurves.cucumber"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,15 @@ Feature: Network parameters Page
|
|||||||
Given I am on mobile and open the toggle menu
|
Given I am on mobile and open the toggle menu
|
||||||
When I navigate to network parameters page
|
When I navigate to network parameters page
|
||||||
Then network parameters page is correctly displayed
|
Then network parameters page is correctly displayed
|
||||||
|
|
||||||
|
Scenario: Navigate to network parameters page and check each value is non-empty
|
||||||
|
Given I am on the homepage
|
||||||
|
When I navigate to network parameters page
|
||||||
|
Then network parameters page is correctly displayed
|
||||||
|
And each value is non-empty
|
||||||
|
|
||||||
|
Scenario: Navigate to network parameters page and check each value using mobile
|
||||||
|
Given I am on mobile and open the toggle menu
|
||||||
|
When I navigate to network parameters page
|
||||||
|
Then network parameters page is correctly displayed
|
||||||
|
And each value is non-empty
|
||||||
|
@ -11,4 +11,12 @@ export default class NetworkParametersPage extends BasePage {
|
|||||||
);
|
);
|
||||||
cy.getByTestId(this.parameters).should('not.be.empty');
|
cy.getByTestId(this.parameters).should('not.be.empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eachValueIsNonEmpty() {
|
||||||
|
cy.getByTestId(this.parameters).then(($parameters) => {
|
||||||
|
$parameters.each((_index, element) => {
|
||||||
|
cy.wrap(element).should('not.be.empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,3 +9,7 @@ When('I navigate to network parameters page', () => {
|
|||||||
Then('network parameters page is correctly displayed', () => {
|
Then('network parameters page is correctly displayed', () => {
|
||||||
networkPage.verifyNetworkParametersDisplayed();
|
networkPage.verifyNetworkParametersDisplayed();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Then('each value is non-empty', () => {
|
||||||
|
networkPage.eachValueIsNonEmpty();
|
||||||
|
});
|
||||||
|
@ -1,28 +1 @@
|
|||||||
import { gql, useQuery } from '@apollo/client';
|
export * from './network-parameters';
|
||||||
import { RouteTitle } from '../../components/route-title';
|
|
||||||
import type { NetworkParametersQuery } from './__generated__/NetworkParametersQuery';
|
|
||||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
|
||||||
|
|
||||||
export const NETWORK_PARAMETERS_QUERY = gql`
|
|
||||||
query NetworkParametersQuery {
|
|
||||||
networkParameters {
|
|
||||||
key
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const NetworkParameters = () => {
|
|
||||||
const { data } = useQuery<NetworkParametersQuery>(NETWORK_PARAMETERS_QUERY);
|
|
||||||
return (
|
|
||||||
<section>
|
|
||||||
<RouteTitle data-testid="network-param-header">
|
|
||||||
{t('Network Parameters')}
|
|
||||||
</RouteTitle>
|
|
||||||
{data ? <SyntaxHighlighter data={data} /> : null}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default NetworkParameters;
|
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { NetworkParametersTable } from './network-parameters';
|
||||||
|
import type { NetworkParametersQuery } from './__generated__/NetworkParametersQuery';
|
||||||
|
|
||||||
|
describe('NetworkParametersTable', () => {
|
||||||
|
it('renders correctly when it has network params', () => {
|
||||||
|
const data: NetworkParametersQuery = {
|
||||||
|
networkParameters: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.liquidityProvision.minLpStakeQuantumMultiple',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.fee.factors.infrastructureFee',
|
||||||
|
value: '0.0005',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
render(<NetworkParametersTable data={data} loading={false} />);
|
||||||
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
|
'Network Parameters'
|
||||||
|
);
|
||||||
|
const rows = screen.getAllByTestId('key-value-table-row');
|
||||||
|
expect(rows[0].children[0]).toHaveTextContent(
|
||||||
|
'market.fee.factors.infrastructureFee'
|
||||||
|
);
|
||||||
|
expect(rows[1].children[0]).toHaveTextContent(
|
||||||
|
'market.liquidityProvision.minLpStakeQuantumMultiple'
|
||||||
|
);
|
||||||
|
expect(rows[0].children[1]).toHaveTextContent('0.0005');
|
||||||
|
expect(rows[1].children[1]).toHaveTextContent('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders the rows in ascending order', () => {
|
||||||
|
const data: NetworkParametersQuery = {
|
||||||
|
networkParameters: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.fee.factors.infrastructureFee',
|
||||||
|
value: '0.0005',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.liquidityProvision.minLpStakeQuantumMultiple',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
render(<NetworkParametersTable data={data} loading={false} />);
|
||||||
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
|
'Network Parameters'
|
||||||
|
);
|
||||||
|
const rows = screen.getAllByTestId('key-value-table-row');
|
||||||
|
expect(rows[0].children[0]).toHaveTextContent(
|
||||||
|
'market.fee.factors.infrastructureFee'
|
||||||
|
);
|
||||||
|
expect(rows[1].children[0]).toHaveTextContent(
|
||||||
|
'market.liquidityProvision.minLpStakeQuantumMultiple'
|
||||||
|
);
|
||||||
|
expect(rows[0].children[1]).toHaveTextContent('0.0005');
|
||||||
|
expect(rows[1].children[1]).toHaveTextContent('1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render rows when is loading', () => {
|
||||||
|
render(<NetworkParametersTable data={undefined} loading={true} />);
|
||||||
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
|
'Network Parameters'
|
||||||
|
);
|
||||||
|
expect(screen.queryByTestId('key-value-table-row')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,118 @@
|
|||||||
|
import { gql, useQuery } from '@apollo/client';
|
||||||
|
import {
|
||||||
|
AsyncRenderer,
|
||||||
|
KeyValueTable,
|
||||||
|
KeyValueTableRow,
|
||||||
|
SyntaxHighlighter,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
formatNumber,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
import { RouteTitle } from '../../components/route-title';
|
||||||
|
import type {
|
||||||
|
NetworkParametersQuery,
|
||||||
|
NetworkParametersQuery_networkParameters,
|
||||||
|
} from './__generated__/NetworkParametersQuery';
|
||||||
|
import orderBy from 'lodash/orderBy';
|
||||||
|
|
||||||
|
const BIG_NUMBER_PARAMS = [
|
||||||
|
'spam.protection.delegation.min.tokens',
|
||||||
|
'validators.delegation.minAmount',
|
||||||
|
'reward.staking.delegation.minimumValidatorStake',
|
||||||
|
'reward.staking.delegation.maxPayoutPerParticipant',
|
||||||
|
'reward.staking.delegation.maxPayoutPerEpoch',
|
||||||
|
'spam.protection.voting.min.tokens',
|
||||||
|
'governance.proposal.freeform.minProposerBalance',
|
||||||
|
'governance.proposal.updateNetParam.minVoterBalance',
|
||||||
|
'governance.proposal.updateMarket.minVoterBalance',
|
||||||
|
'governance.proposal.asset.minVoterBalance',
|
||||||
|
'governance.proposal.updateNetParam.minProposerBalance',
|
||||||
|
'governance.proposal.freeform.minVoterBalance',
|
||||||
|
'spam.protection.proposal.min.tokens',
|
||||||
|
'governance.proposal.updateMarket.minProposerBalance',
|
||||||
|
'governance.proposal.asset.minProposerBalance',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const renderRow = ({
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
}: NetworkParametersQuery_networkParameters) => {
|
||||||
|
const isSyntaxRow = isJsonObject(value);
|
||||||
|
return (
|
||||||
|
<KeyValueTableRow key={key} inline={!isSyntaxRow}>
|
||||||
|
{key}
|
||||||
|
{isSyntaxRow ? (
|
||||||
|
<SyntaxHighlighter data={JSON.parse(value)} />
|
||||||
|
) : isNaN(Number(value)) ? (
|
||||||
|
value
|
||||||
|
) : BIG_NUMBER_PARAMS.includes(key) ? (
|
||||||
|
addDecimalsFormatNumber(Number(value), 4)
|
||||||
|
) : (
|
||||||
|
formatNumber(Number(value), 4)
|
||||||
|
)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isJsonObject = (str: string) => {
|
||||||
|
try {
|
||||||
|
return JSON.parse(str) && Object.keys(JSON.parse(str)).length > 0;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const NETWORK_PARAMETERS_QUERY = gql`
|
||||||
|
query NetworkParametersQuery {
|
||||||
|
networkParameters {
|
||||||
|
key
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export interface NetworkParametersTableProps
|
||||||
|
extends React.HTMLAttributes<HTMLTableElement> {
|
||||||
|
data?: NetworkParametersQuery;
|
||||||
|
error?: Error;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const NetworkParametersTable = ({
|
||||||
|
data,
|
||||||
|
error,
|
||||||
|
loading,
|
||||||
|
}: NetworkParametersTableProps) => (
|
||||||
|
<section>
|
||||||
|
<RouteTitle data-testid="network-param-header">
|
||||||
|
{t('Network Parameters')}
|
||||||
|
</RouteTitle>
|
||||||
|
|
||||||
|
<AsyncRenderer
|
||||||
|
data={data}
|
||||||
|
loading={loading}
|
||||||
|
error={error}
|
||||||
|
render={(data) => {
|
||||||
|
const ascParams = orderBy(
|
||||||
|
data.networkParameters || [],
|
||||||
|
(param) => param.key,
|
||||||
|
'asc'
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<KeyValueTable data-testid="parameters">
|
||||||
|
{(ascParams || []).map((row) => renderRow(row))}
|
||||||
|
</KeyValueTable>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NetworkParameters = () => {
|
||||||
|
const { data, loading, error } = useQuery<NetworkParametersQuery>(
|
||||||
|
NETWORK_PARAMETERS_QUERY
|
||||||
|
);
|
||||||
|
return <NetworkParametersTable data={data} error={error} loading={loading} />;
|
||||||
|
};
|
@ -9,7 +9,6 @@ import { Party as PartySingle } from './parties/id';
|
|||||||
import Txs from './txs';
|
import Txs from './txs';
|
||||||
import Validators from './validators';
|
import Validators from './validators';
|
||||||
import Genesis from './genesis';
|
import Genesis from './genesis';
|
||||||
import NetworkParameters from './network-parameters';
|
|
||||||
import { Block } from './blocks/id';
|
import { Block } from './blocks/id';
|
||||||
import { Blocks } from './blocks/home';
|
import { Blocks } from './blocks/home';
|
||||||
import { Tx } from './txs/id';
|
import { Tx } from './txs/id';
|
||||||
@ -18,6 +17,7 @@ import { PendingTxs } from './pending';
|
|||||||
import flags from '../lib/flags';
|
import flags from '../lib/flags';
|
||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t } from '@vegaprotocol/react-helpers';
|
||||||
import { Routes } from './route-names';
|
import { Routes } from './route-names';
|
||||||
|
import { NetworkParameters } from './network-parameters';
|
||||||
|
|
||||||
const partiesRoutes = flags.parties
|
const partiesRoutes = flags.parties
|
||||||
? [
|
? [
|
||||||
|
@ -2,7 +2,7 @@ import { forwardRef } from 'react';
|
|||||||
import type { ColumnApi, ValueFormatterParams } from 'ag-grid-community';
|
import type { ColumnApi, ValueFormatterParams } from 'ag-grid-community';
|
||||||
import {
|
import {
|
||||||
PriceCell,
|
PriceCell,
|
||||||
formatNumber,
|
addDecimalsFormatNumber,
|
||||||
t,
|
t,
|
||||||
addSummaryRows,
|
addSummaryRows,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
@ -136,7 +136,7 @@ export const AccountsTable = forwardRef<AgGridReact, AccountsTableProps>(
|
|||||||
value,
|
value,
|
||||||
data,
|
data,
|
||||||
}: AccountsTableValueFormatterParams) =>
|
}: AccountsTableValueFormatterParams) =>
|
||||||
formatNumber(value, data.asset.decimals)
|
addDecimalsFormatNumber(value, data.asset.decimals)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</AgGrid>
|
</AgGrid>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import type { OrderEvent_busEvents_event_Order } from './__generated__/OrderEvent';
|
import type { OrderEvent_busEvents_event_Order } from './__generated__/OrderEvent';
|
||||||
import { formatNumber, t } from '@vegaprotocol/react-helpers';
|
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||||
import type { VegaTxState } from '@vegaprotocol/wallet';
|
import type { VegaTxState } from '@vegaprotocol/wallet';
|
||||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ export const OrderDialog = ({
|
|||||||
{finalizedOrder.type === 'Limit' && finalizedOrder.market && (
|
{finalizedOrder.type === 'Limit' && finalizedOrder.market && (
|
||||||
<p>
|
<p>
|
||||||
{t(
|
{t(
|
||||||
`Price: ${formatNumber(
|
`Price: ${addDecimalsFormatNumber(
|
||||||
finalizedOrder.price,
|
finalizedOrder.price,
|
||||||
finalizedOrder.market.decimalPlaces
|
finalizedOrder.market.decimalPlaces
|
||||||
)}`
|
)}`
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
PriceCell,
|
PriceCell,
|
||||||
Vol,
|
Vol,
|
||||||
CumulativeVol,
|
CumulativeVol,
|
||||||
formatNumber,
|
addDecimalsFormatNumber,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
interface OrderbookRowProps {
|
interface OrderbookRowProps {
|
||||||
@ -33,7 +33,7 @@ export const OrderbookRow = React.memo(
|
|||||||
<Vol value={bid} relativeValue={relativeBidVol} type="bid" />
|
<Vol value={bid} relativeValue={relativeBidVol} type="bid" />
|
||||||
<PriceCell
|
<PriceCell
|
||||||
value={BigInt(price)}
|
value={BigInt(price)}
|
||||||
valueFormatted={formatNumber(price, decimalPlaces)}
|
valueFormatted={addDecimalsFormatNumber(price, decimalPlaces)}
|
||||||
/>
|
/>
|
||||||
<Vol value={ask} relativeValue={relativeAskVol} type="ask" />
|
<Vol value={ask} relativeValue={relativeAskVol} type="ask" />
|
||||||
<CumulativeVol
|
<CumulativeVol
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
import type { ValueFormatterParams } from 'ag-grid-community';
|
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||||
import { PriceFlashCell, formatNumber, t } from '@vegaprotocol/react-helpers';
|
import {
|
||||||
|
PriceFlashCell,
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
t,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
import type {
|
import type {
|
||||||
Markets_markets,
|
Markets_markets,
|
||||||
@ -60,7 +64,7 @@ export const MarketListTable = forwardRef<AgGridReact, MarketListTableProps>(
|
|||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
cellRenderer="PriceFlashCell"
|
cellRenderer="PriceFlashCell"
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
formatNumber(value, data.decimalPlaces)
|
addDecimalsFormatNumber(value, data.decimalPlaces)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
@ -68,7 +72,7 @@ export const MarketListTable = forwardRef<AgGridReact, MarketListTableProps>(
|
|||||||
field="data.bestOfferPrice"
|
field="data.bestOfferPrice"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
formatNumber(value, data.decimalPlaces)
|
addDecimalsFormatNumber(value, data.decimalPlaces)
|
||||||
}
|
}
|
||||||
cellRenderer="PriceFlashCell"
|
cellRenderer="PriceFlashCell"
|
||||||
/>
|
/>
|
||||||
@ -78,7 +82,7 @@ export const MarketListTable = forwardRef<AgGridReact, MarketListTableProps>(
|
|||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
cellRenderer="PriceFlashCell"
|
cellRenderer="PriceFlashCell"
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
valueFormatter={({ value, data }: ValueFormatterParams) =>
|
||||||
formatNumber(value, data.decimalPlaces)
|
addDecimalsFormatNumber(value, data.decimalPlaces)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn headerName={t('Description')} field="name" />
|
<AgGridColumn headerName={t('Description')} field="name" />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { formatNumber, t } from '@vegaprotocol/react-helpers';
|
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||||
import type { Stats as IStats, StatFields as IStatFields } from './types';
|
import type { Stats as IStats, StatFields as IStatFields } from './types';
|
||||||
|
|
||||||
// Stats fields config. Keys will correspond to graphql queries when used, and values
|
// Stats fields config. Keys will correspond to graphql queries when used, and values
|
||||||
@ -60,7 +60,7 @@ export const statsFields: { [key in keyof IStats]: IStatFields[] } = {
|
|||||||
{
|
{
|
||||||
title: t('Total staked'),
|
title: t('Total staked'),
|
||||||
formatter: (total: string) => {
|
formatter: (total: string) => {
|
||||||
return formatNumber(total, 18, 2);
|
return addDecimalsFormatNumber(total, 18, 2);
|
||||||
},
|
},
|
||||||
description: t('Sum of VEGA associated with a Vega key'),
|
description: t('Sum of VEGA associated with a Vega key'),
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@ import { forwardRef } from 'react';
|
|||||||
import type { ValueFormatterParams } from 'ag-grid-community';
|
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||||
import {
|
import {
|
||||||
PriceFlashCell,
|
PriceFlashCell,
|
||||||
formatNumber,
|
addDecimalsFormatNumber,
|
||||||
volumePrefix,
|
volumePrefix,
|
||||||
addDecimal,
|
addDecimal,
|
||||||
t,
|
t,
|
||||||
@ -100,7 +100,7 @@ export const PositionsTable = forwardRef<AgGridReact, PositionsTableProps>(
|
|||||||
value,
|
value,
|
||||||
data,
|
data,
|
||||||
}: PositionsTableValueFormatterParams) =>
|
}: PositionsTableValueFormatterParams) =>
|
||||||
formatNumber(value, data.market.decimalPlaces)
|
addDecimalsFormatNumber(value, data.market.decimalPlaces)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
@ -27,12 +27,16 @@ export const getNumberFormat = memoize(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export const formatNumber = (
|
export const formatNumber = (rawValue: string | number, formatDecimals = 0) => {
|
||||||
|
return getNumberFormat(formatDecimals).format(Number(rawValue));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const addDecimalsFormatNumber = (
|
||||||
rawValue: string | number,
|
rawValue: string | number,
|
||||||
decimalPlaces: number,
|
decimalPlaces: number,
|
||||||
formatDecimals: number = decimalPlaces
|
formatDecimals: number = decimalPlaces
|
||||||
) => {
|
) => {
|
||||||
const x = addDecimal(rawValue, decimalPlaces);
|
const x = addDecimal(rawValue, decimalPlaces);
|
||||||
|
|
||||||
return getNumberFormat(formatDecimals).format(Number(x));
|
return formatNumber(x, formatDecimals);
|
||||||
};
|
};
|
||||||
|
@ -4,7 +4,7 @@ import { forwardRef, useMemo } from 'react';
|
|||||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { TradeFields } from './__generated__/TradeFields';
|
import type { TradeFields } from './__generated__/TradeFields';
|
||||||
import {
|
import {
|
||||||
formatNumber,
|
addDecimalsFormatNumber,
|
||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
t,
|
t,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
@ -67,7 +67,7 @@ export const TradesTable = forwardRef<AgGridReact, TradesTableProps>(
|
|||||||
field="price"
|
field="price"
|
||||||
cellClass={changeCellClass('price')}
|
cellClass={changeCellClass('price')}
|
||||||
valueFormatter={({ value, data }: ValueFormatterParams) => {
|
valueFormatter={({ value, data }: ValueFormatterParams) => {
|
||||||
return formatNumber(value, data.market.decimalPlaces);
|
return addDecimalsFormatNumber(value, data.market.decimalPlaces);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
|
@ -12,7 +12,7 @@ const props: KeyValueTableProps = {
|
|||||||
it('Renders the correct elements', () => {
|
it('Renders the correct elements', () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<KeyValueTable {...props}>
|
<KeyValueTable {...props}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow inline={true}>
|
||||||
<span>My label</span>
|
<span>My label</span>
|
||||||
<span>My value</span>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
@ -38,10 +38,10 @@ it('Renders the correct elements', () => {
|
|||||||
expect(rows[1].children[1]).toHaveTextContent('My value 2');
|
expect(rows[1].children[1]).toHaveTextContent('My value 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Applies numeric class if prop is passed', () => {
|
it('Applies numeric class if prop is passed row not inline', () => {
|
||||||
render(
|
render(
|
||||||
<KeyValueTable {...props} numerical={true}>
|
<KeyValueTable {...props} numerical={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow inline={false}>
|
||||||
<span>My label</span>
|
<span>My label</span>
|
||||||
<span>My value</span>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
@ -51,12 +51,35 @@ it('Applies numeric class if prop is passed', () => {
|
|||||||
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
||||||
'w-full border-collapse mb-8 [border-spacing:0] break-all'
|
'w-full border-collapse mb-8 [border-spacing:0] break-all'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('key-value-table-row')).toHaveClass(
|
||||||
|
' flex gap-1 flex-wrap justify-between border-b first:border-t border-black dark:border-white flex-col items-start'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Applies numeric class if prop is passed row inline', () => {
|
||||||
|
render(
|
||||||
|
<KeyValueTable {...props} numerical={true}>
|
||||||
|
<KeyValueTableRow inline={true}>
|
||||||
|
<span>My label</span>
|
||||||
|
<span>My value</span>
|
||||||
|
</KeyValueTableRow>
|
||||||
|
</KeyValueTable>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('key-value-table')).toHaveClass(
|
||||||
|
'w-full border-collapse mb-8 [border-spacing:0] break-all'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('key-value-table-row')).toHaveClass(
|
||||||
|
'flex gap-1 flex-wrap justify-between border-b first:border-t border-black dark:border-white flex-row items-center'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Applies muted class if prop is passed', () => {
|
it('Applies muted class if prop is passed', () => {
|
||||||
render(
|
render(
|
||||||
<KeyValueTable {...props} muted={true}>
|
<KeyValueTable {...props} muted={true}>
|
||||||
<KeyValueTableRow>
|
<KeyValueTableRow inline={false}>
|
||||||
<span>My label</span>
|
<span>My label</span>
|
||||||
<span>My value</span>
|
<span>My value</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
|
@ -62,6 +62,7 @@ export interface KeyValueTableRowProps
|
|||||||
className?: string;
|
className?: string;
|
||||||
numerical?: boolean; // makes all values monospace
|
numerical?: boolean; // makes all values monospace
|
||||||
muted?: boolean;
|
muted?: boolean;
|
||||||
|
inline?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const KeyValueTableRow = ({
|
export const KeyValueTableRow = ({
|
||||||
@ -69,25 +70,28 @@ export const KeyValueTableRow = ({
|
|||||||
className,
|
className,
|
||||||
muted,
|
muted,
|
||||||
numerical,
|
numerical,
|
||||||
|
inline = true,
|
||||||
}: KeyValueTableRowProps) => {
|
}: KeyValueTableRowProps) => {
|
||||||
const dlClassName = classNames(
|
const dlClassName = classNames(
|
||||||
'flex flex-wrap justify-between items-center border-b first:border-t border-black dark:border-white',
|
'flex gap-1 flex-wrap justify-between border-b first:border-t border-black dark:border-white',
|
||||||
|
{ 'flex-col items-start': !inline },
|
||||||
|
{ 'flex-row items-center': inline },
|
||||||
{
|
{
|
||||||
'border-black/60 dark:border-white/60 first:[border-top:none] last:[border-bottom:none]':
|
'border-black/60 dark:border-white/60 first:[border-top:none] last:[border-bottom:none]':
|
||||||
muted,
|
muted,
|
||||||
},
|
},
|
||||||
className
|
className
|
||||||
);
|
);
|
||||||
const dtClassName = `break-normal font-medium uppercase align-top p-4`;
|
const dtClassName = `break-words font-medium uppercase align-top p-4 capitalize`;
|
||||||
const ddClassName = classNames(
|
const ddClassName = classNames(
|
||||||
'align-top p-4 text-black/60 dark:text-white/60 break-normal',
|
'align-top p-4 text-black/60 dark:text-white/60 break-words',
|
||||||
{
|
{
|
||||||
'font-mono': numerical,
|
'font-mono': numerical,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<dl className={dlClassName}>
|
<dl className={dlClassName} data-testid="key-value-table-row">
|
||||||
<dt className={dtClassName}>{children[0]}</dt>
|
<dt className={dtClassName}>{children[0]}</dt>
|
||||||
<dd className={ddClassName}>{children[1]}</dd>
|
<dd className={ddClassName}>{children[1]}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
Loading…
Reference in New Issue
Block a user