fix: trades grid colors (#2766)

This commit is contained in:
m.ray 2023-01-27 13:55:20 -05:00 committed by GitHub
parent b1280c8285
commit 4b3b5c322a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 79 deletions

View File

@ -3,6 +3,7 @@ fragment TradeFields on Trade {
price price
size size
createdAt createdAt
aggressor
market { market {
id id
} }
@ -35,5 +36,6 @@ subscription TradesUpdate($marketId: ID!) {
size size
createdAt createdAt
marketId marketId
aggressor
} }
} }

View File

@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client'; import * as Apollo from '@apollo/client';
const defaultOptions = {} as const; const defaultOptions = {} as const;
export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } }; export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } };
export type TradesQueryVariables = Types.Exact<{ export type TradesQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID']; marketId: Types.Scalars['ID'];
@ -11,14 +11,14 @@ export type TradesQueryVariables = Types.Exact<{
}>; }>;
export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null }; export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null };
export type TradesUpdateSubscriptionVariables = Types.Exact<{ export type TradesUpdateSubscriptionVariables = Types.Exact<{
marketId: Types.Scalars['ID']; marketId: Types.Scalars['ID'];
}>; }>;
export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string }> | null }; export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side }> | null };
export const TradeFieldsFragmentDoc = gql` export const TradeFieldsFragmentDoc = gql`
fragment TradeFields on Trade { fragment TradeFields on Trade {
@ -26,6 +26,7 @@ export const TradeFieldsFragmentDoc = gql`
price price
size size
createdAt createdAt
aggressor
market { market {
id id
} }
@ -89,6 +90,7 @@ export const TradesUpdateDocument = gql`
size size
createdAt createdAt
marketId marketId
aggressor
} }
} }
`; `;

View File

@ -1,13 +1,15 @@
import { act, render, screen } from '@testing-library/react'; import { act, render, screen } from '@testing-library/react';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers'; import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
import { DOWN_CLASS, TradesTable, UP_CLASS } from './trades-table'; import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table';
import type { Trade } from './trades-data-provider'; import type { Trade } from './trades-data-provider';
import { Side } from '@vegaprotocol/types';
const trade: Trade = { const trade: Trade = {
__typename: 'Trade', __typename: 'Trade',
id: 'trade-id', id: 'trade-id',
price: '111122200', price: '111122200',
size: '2000', size: '2000',
aggressor: Side.SIDE_BUY,
createdAt: new Date('2022-04-06T19:00:00').toISOString(), createdAt: new Date('2022-04-06T19:00:00').toISOString(),
market: { market: {
__typename: 'Market', __typename: 'Market',
@ -17,59 +19,58 @@ const trade: Trade = {
} as Trade['market'], } as Trade['market'],
}; };
it('Correct columns are rendered', async () => { describe('TradesTable', () => {
await act(async () => { it('should render correct columns', async () => {
render(<TradesTable rowData={[trade]} />); await act(async () => {
}); render(<TradesTable rowData={[trade]} />);
const expectedHeaders = ['Price', 'Size', 'Created at']; });
const headers = screen.getAllByRole('columnheader'); const expectedHeaders = ['Price', 'Size', 'Created at'];
expect(headers).toHaveLength(expectedHeaders.length); const headers = screen.getAllByRole('columnheader');
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders); expect(headers).toHaveLength(expectedHeaders.length);
}); expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
it('Number and data columns are formatted', async () => {
await act(async () => {
render(<TradesTable rowData={[trade]} />);
}); });
const cells = screen.getAllByRole('gridcell'); it('should format number and data columns', async () => {
const expectedValues = [ await act(async () => {
'1,111,222.00', render(<TradesTable rowData={[trade]} />);
'20.00', });
getDateTimeFormat().format(new Date(trade.createdAt)),
]; const cells = screen.getAllByRole('gridcell');
cells.forEach((cell, i) => { const expectedValues = [
expect(cell).toHaveTextContent(expectedValues[i]); '1,111,222.00',
'20.00',
getDateTimeFormat().format(new Date(trade.createdAt)),
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
});
it('should format price and size columns', async () => {
const trade2 = {
...trade,
id: 'trade-id-2',
price: (Number(trade.price) + 10).toString(),
size: (Number(trade.size) - 10).toString(),
};
await act(async () => {
render(<TradesTable rowData={[trade2, trade]} />);
});
const cells = screen.getAllByRole('gridcell');
const priceCells = cells.filter(
(cell) => cell.getAttribute('col-id') === 'price'
);
const sizeCells = cells.filter(
(cell) => cell.getAttribute('col-id') === 'size'
);
// For first trade price should have green class
// row 1
expect(priceCells[0]).toHaveClass(BUY_CLASS);
expect(priceCells[1]).not.toHaveClass(SELL_CLASS);
expect(sizeCells[1]).not.toHaveClass(SELL_CLASS);
expect(sizeCells[1]).not.toHaveClass(BUY_CLASS);
}); });
}); });
it('Price and size columns are formatted', async () => {
const trade2 = {
...trade,
id: 'trade-id-2',
price: (Number(trade.price) + 10).toString(),
size: (Number(trade.size) - 10).toString(),
};
await act(async () => {
render(<TradesTable rowData={[trade2, trade]} />);
});
const cells = screen.getAllByRole('gridcell');
const priceCells = cells.filter(
(cell) => cell.getAttribute('col-id') === 'price'
);
const sizeCells = cells.filter(
(cell) => cell.getAttribute('col-id') === 'size'
);
// For first trade price should have green class and size should have red class
// row 1
expect(priceCells[0]).toHaveClass(UP_CLASS);
expect(priceCells[1]).not.toHaveClass(DOWN_CLASS);
expect(priceCells[1]).not.toHaveClass(UP_CLASS);
expect(sizeCells[0]).toHaveClass(DOWN_CLASS);
expect(sizeCells[1]).not.toHaveClass(DOWN_CLASS);
expect(sizeCells[1]).not.toHaveClass(UP_CLASS);
});

View File

@ -13,31 +13,22 @@ import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
import type { CellClassParams, ValueFormatterParams } from 'ag-grid-community'; import type { CellClassParams, ValueFormatterParams } from 'ag-grid-community';
import type { AgGridReactProps } from 'ag-grid-react'; import type { AgGridReactProps } from 'ag-grid-react';
import type { Trade } from './trades-data-provider'; import type { Trade } from './trades-data-provider';
import BigNumber from 'bignumber.js'; import { Side } from '@vegaprotocol/types';
export const UP_CLASS = 'text-vega-green dark:text-vega-green'; export const BUY_CLASS = 'text-vega-green dark:text-vega-green';
export const DOWN_CLASS = 'text-vega-pink dark:text-vega-pink'; export const SELL_CLASS = 'text-vega-pink dark:text-vega-pink';
const changeCellClass = const changeCellClass = ({ node }: CellClassParams) => {
(dataKey: string) => let colorClass = '';
({ api, value, node }: CellClassParams) => {
const rowIndex = node?.rowIndex;
let colorClass = '';
if (typeof rowIndex === 'number') { if (node.data?.aggressor === Side.SIDE_BUY) {
const prevRowNode = api.getModel().getRow(rowIndex + 1); colorClass = BUY_CLASS;
const prevValue = prevRowNode?.data && prevRowNode.data[dataKey]; } else if (node.data?.aggressor === Side.SIDE_SELL) {
const valueNum = new BigNumber(value); colorClass = SELL_CLASS;
}
if (valueNum.isGreaterThan(prevValue)) { return ['font-mono text-right', colorClass].join(' ');
colorClass = UP_CLASS; };
} else if (valueNum.isLessThan(prevValue)) {
colorClass = DOWN_CLASS;
}
}
return ['font-mono text-right', colorClass].join(' ');
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> { export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: (Trade | null)[], lastRow?: number): void; successCallback(rowsThisBlock: (Trade | null)[], lastRow?: number): void;
@ -77,7 +68,7 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
field="price" field="price"
type="rightAligned" type="rightAligned"
width={130} width={130}
cellClass={changeCellClass('price')} cellClass={changeCellClass}
valueFormatter={({ valueFormatter={({
value, value,
data, data,
@ -127,7 +118,6 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
} }
return addDecimal(value, data.market.positionDecimalPlaces); return addDecimal(value, data.market.positionDecimalPlaces);
}} }}
cellClass={changeCellClass('size')}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Created at')} headerName={t('Created at')}

View File

@ -1,3 +1,4 @@
import { Side } from '@vegaprotocol/types';
import merge from 'lodash/merge'; import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest'; import type { PartialDeep } from 'type-fest';
import type { import type {
@ -47,6 +48,7 @@ export const tradesUpdateSubscription = (
size: '24', size: '24',
createdAt: '2022-04-06T16:19:42.692598951Z', createdAt: '2022-04-06T16:19:42.692598951Z',
marketId: 'market-0', marketId: 'market-0',
aggressor: Side.SIDE_BUY,
}, },
], ],
}; };
@ -59,6 +61,7 @@ const trades: TradeFieldsFragment[] = [
price: '17116898', price: '17116898',
size: '24', size: '24',
createdAt: '2022-04-06T16:19:42.692598951Z', createdAt: '2022-04-06T16:19:42.692598951Z',
aggressor: Side.SIDE_BUY,
market: { market: {
id: 'market-0', id: 'market-0',
__typename: 'Market', __typename: 'Market',
@ -70,6 +73,7 @@ const trades: TradeFieldsFragment[] = [
price: '17209102', price: '17209102',
size: '7', size: '7',
createdAt: '2022-04-07T06:59:44.835686754Z', createdAt: '2022-04-07T06:59:44.835686754Z',
aggressor: Side.SIDE_SELL,
market: { market: {
id: 'market-0', id: 'market-0',
__typename: 'Market', __typename: 'Market',
@ -81,6 +85,7 @@ const trades: TradeFieldsFragment[] = [
price: '17106734', price: '17106734',
size: '18', size: '18',
createdAt: '2022-04-07T17:56:47.997938583Z', createdAt: '2022-04-07T17:56:47.997938583Z',
aggressor: Side.SIDE_BUY,
market: { market: {
id: 'market-0', id: 'market-0',
__typename: 'Market', __typename: 'Market',