feat(orders): reduce number of columns in orders table (#4238)

This commit is contained in:
Bartłomiej Głownia 2023-07-06 17:57:29 +02:00 committed by GitHub
parent 0665ac85db
commit e89b818e4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 161 deletions

View File

@ -16,7 +16,7 @@ const orderStatus = 'status';
const orderRemaining = 'remaining'; const orderRemaining = 'remaining';
const orderPrice = 'price'; const orderPrice = 'price';
const orderTimeInForce = 'timeInForce'; const orderTimeInForce = 'timeInForce';
const orderCreatedAt = 'createdAt'; const orderUpdatedAt = 'updatedAt';
const cancelOrderBtn = 'cancel'; const cancelOrderBtn = 'cancel';
const cancelAllOrdersBtn = 'cancelAll'; const cancelAllOrdersBtn = 'cancelAll';
const editOrderBtn = 'edit'; const editOrderBtn = 'edit';
@ -46,6 +46,10 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($symbol).invoke('text').should('not.be.empty'); cy.wrap($symbol).invoke('text').should('not.be.empty');
}); });
cy.get(`[col-id='${orderRemaining}']`).each(($remaining) => {
cy.wrap($remaining).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderSize}']`).each(($size) => { cy.get(`[col-id='${orderSize}']`).each(($size) => {
cy.wrap($size).invoke('text').should('not.be.empty'); cy.wrap($size).invoke('text').should('not.be.empty');
}); });
@ -58,10 +62,6 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($status).invoke('text').should('not.be.empty'); cy.wrap($status).invoke('text').should('not.be.empty');
}); });
cy.get(`[col-id='${orderRemaining}']`).each(($remaining) => {
cy.wrap($remaining).invoke('text').should('not.be.empty');
});
cy.get(`[col-id='${orderPrice}']`).each(($price) => { cy.get(`[col-id='${orderPrice}']`).each(($price) => {
cy.wrap($price).invoke('text').should('not.be.empty'); cy.wrap($price).invoke('text').should('not.be.empty');
}); });
@ -70,7 +70,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.wrap($timeInForce).invoke('text').should('not.be.empty'); cy.wrap($timeInForce).invoke('text').should('not.be.empty');
}); });
cy.get(`[col-id='${orderCreatedAt}']`).each(($dateTime) => { cy.get(`[col-id='${orderUpdatedAt}']`).each(($dateTime) => {
cy.wrap($dateTime).invoke('text').should('not.be.empty'); cy.wrap($dateTime).invoke('text').should('not.be.empty');
}); });
}); });
@ -96,7 +96,8 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
'have.text', 'have.text',
'Partially Filled' 'Partially Filled'
); );
cy.get(`[col-id='${orderRemaining}']`).should('have.text', '7/10'); cy.get(`[col-id='${orderRemaining}']`).should('have.text', '7');
cy.get(`[col-id='${orderSize}']`).should('have.text', '-10');
cy.getByTestId(cancelOrderBtn).should('not.exist'); cy.getByTestId(cancelOrderBtn).should('not.exist');
cy.getByTestId(editOrderBtn).should('not.exist'); cy.getByTestId(editOrderBtn).should('not.exist');
}); });
@ -219,7 +220,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
cy.getByTestId(`order-status-${orderId}`) cy.getByTestId(`order-status-${orderId}`)
.parentsUntil(`.ag-row`) .parentsUntil(`.ag-row`)
.siblings(`[col-id=${orderRemaining}]`) .siblings(`[col-id=${orderRemaining}]`)
.should('have.text', '4/5'); .should('have.text', '4');
}); });
it('must see a filled order', () => { it('must see a filled order', () => {
@ -267,7 +268,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
status: Schema.OrderStatus.STATUS_ACTIVE, status: Schema.OrderStatus.STATUS_ACTIVE,
}); });
cy.get(`[row-id=${orderId}]`) cy.get(`[row-id=${orderId}]`)
.find('[col-id="size"]') .find(`[col-id="${orderSize}"]`)
.should('have.text', '-15'); .should('have.text', '-15');
}); });
@ -281,7 +282,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
status: Schema.OrderStatus.STATUS_ACTIVE, status: Schema.OrderStatus.STATUS_ACTIVE,
}); });
cy.get(`[row-id=${orderId}]`) cy.get(`[row-id=${orderId}]`)
.find('[col-id="size"]') .find(`[col-id="${orderSize}"]`)
.should('have.text', '+5'); .should('have.text', '+5');
}); });
@ -364,7 +365,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
}); });
cy.get(`[row-id=${orderId}]`) cy.get(`[row-id=${orderId}]`)
.find(`[col-id='${orderTimeInForce}']`) .find(`[col-id='${orderTimeInForce}']`)
.should('have.text', "Good 'til Cancelled (GTC)"); .should('have.text', 'GTC');
}); });
it('for Active order when is part of a liquidity or peg shape, must not see an option to amend the individual order ', () => { it('for Active order when is part of a liquidity or peg shape, must not see an option to amend the individual order ', () => {

View File

@ -76,54 +76,4 @@ describe('order data provider', () => {
)?.length )?.length
).toEqual(5); ).toEqual(5);
}); });
it('add only data matching date range filter', () => {
const data = [
{
id: '1',
createdAt: new Date('2022-01-29').toISOString(),
},
{
id: '2',
createdAt: new Date('2022-01-30').toISOString(),
},
] as OrderFieldsFragment[];
const delta = [
// this one should be ignored because it does not match date range
{
id: '0',
createdAt: new Date('2022-02-02').toISOString(),
},
// this one should be updated
{
id: '2',
updatedAt: new Date('2022-01-31').toISOString(),
createdAt: new Date('2022-01-30').toISOString(),
},
// this should be added
{
id: '4',
createdAt: new Date('2022-01-31').toISOString(),
},
] as OrderUpdateFieldsFragment[];
const updatedData = update(
data,
filterOrderUpdates(delta),
{
partyId: '0x123',
filter: {
dateRange: { end: new Date('2022-02-01').toISOString() },
},
},
mapOrderUpdateToOrder
);
expect(updatedData?.findIndex((node) => node.id === delta[0].id)).toEqual(
-1
);
expect(updatedData && updatedData[0].id).toEqual(delta[2].id);
expect(updatedData && updatedData[0].updatedAt).toEqual(delta[2].updatedAt);
expect(updatedData && updatedData[2].id).toEqual(delta[1].id);
expect(updatedData && updatedData[2].updatedAt).toEqual(delta[1].updatedAt);
});
}); });

View File

@ -39,13 +39,6 @@ const orderMatchFilters = (
return true; return true;
} }
if (
variables?.filter?.status &&
!(order.status && variables.filter.status.includes(order.status))
) {
return false;
}
if ( if (
variables?.filter?.liveOnly && variables?.filter?.liveOnly &&
!(order.status && liveOnlyOrderStatuses.includes(order.status)) !(order.status && liveOnlyOrderStatuses.includes(order.status))
@ -53,34 +46,6 @@ const orderMatchFilters = (
return false; return false;
} }
if (
variables?.filter?.types &&
!(order.type && variables.filter.types.includes(order.type))
) {
return false;
}
if (
variables?.filter?.timeInForce &&
!variables.filter.timeInForce.includes(order.timeInForce)
) {
return false;
}
if (variables?.filter?.excludeLiquidity && order.liquidityProvisionId) {
return false;
}
if (
variables?.filter?.dateRange?.start &&
!(order.createdAt && variables.filter.dateRange.start < order.createdAt)
) {
return false;
}
if (
variables?.filter?.dateRange?.end &&
!(order.createdAt && variables.filter.dateRange.end > order.createdAt)
) {
return false;
}
return true; return true;
}; };

View File

@ -50,13 +50,12 @@ describe('OrderListTable', () => {
}); });
const expectedHeaders = [ const expectedHeaders = [
'Market', 'Market',
'Filled',
'Size', 'Size',
'Type', 'Type',
'Status', 'Status',
'Filled',
'Price', 'Price',
'Time In Force', 'Time In Force',
'Created At',
'Updated At', 'Updated At',
'', // no cell header for edit/cancel '', // no cell header for edit/cancel
]; ];
@ -73,14 +72,13 @@ describe('OrderListTable', () => {
const cells = screen.getAllByRole('gridcell'); const cells = screen.getAllByRole('gridcell');
const expectedValues: string[] = [ const expectedValues: string[] = [
marketOrder.market?.tradableInstrument.instrument.code || '', marketOrder.market?.tradableInstrument.instrument.code || '',
'+0.10', '0.05',
'0.10',
Schema.OrderTypeMapping[marketOrder.type as Schema.OrderType] || '', Schema.OrderTypeMapping[marketOrder.type as Schema.OrderType] || '',
Schema.OrderStatusMapping[marketOrder.status], Schema.OrderStatusMapping[marketOrder.status],
'5',
'-', '-',
Schema.OrderTimeInForceMapping[marketOrder.timeInForce], Schema.OrderTimeInForceCode[marketOrder.timeInForce],
getDateTimeFormat().format(new Date(marketOrder.createdAt)), getDateTimeFormat().format(new Date(marketOrder.createdAt)),
'-',
'Edit', 'Edit',
]; ];
expectedValues.forEach((expectedValue, i) => expectedValues.forEach((expectedValue, i) =>
@ -96,16 +94,15 @@ describe('OrderListTable', () => {
const expectedValues: string[] = [ const expectedValues: string[] = [
limitOrder.market?.tradableInstrument.instrument.code || '', limitOrder.market?.tradableInstrument.instrument.code || '',
'+0.10', '0.05',
'0.10',
Schema.OrderTypeMapping[limitOrder.type || Schema.OrderType.TYPE_LIMIT], Schema.OrderTypeMapping[limitOrder.type || Schema.OrderType.TYPE_LIMIT],
Schema.OrderStatusMapping[limitOrder.status], Schema.OrderStatusMapping[limitOrder.status],
'5',
'-', '-',
`${ `${
Schema.OrderTimeInForceMapping[limitOrder.timeInForce] Schema.OrderTimeInForceCode[limitOrder.timeInForce]
}: ${getDateTimeFormat().format(new Date(limitOrder.expiresAt ?? ''))}`, }: ${getDateTimeFormat().format(new Date(limitOrder.expiresAt ?? ''))}`,
getDateTimeFormat().format(new Date(limitOrder.createdAt)), getDateTimeFormat().format(new Date(limitOrder.createdAt)),
'-',
'Edit', 'Edit',
]; ];
expectedValues.forEach((expectedValue, i) => expectedValues.forEach((expectedValue, i) =>
@ -124,7 +121,7 @@ describe('OrderListTable', () => {
render(generateJsx({ rowData: [rejectedOrder] })); render(generateJsx({ rowData: [rejectedOrder] }));
}); });
const cells = screen.getAllByRole('gridcell'); const cells = screen.getAllByRole('gridcell');
expect(cells[3]).toHaveTextContent( expect(cells[4]).toHaveTextContent(
`${Schema.OrderStatusMapping[rejectedOrder.status]}: ${ `${Schema.OrderStatusMapping[rejectedOrder.status]}: ${
Schema.OrderRejectionReasonMapping[rejectedOrder.rejectionReason] Schema.OrderRejectionReasonMapping[rejectedOrder.rejectionReason]
}` }`
@ -193,7 +190,7 @@ describe('OrderListTable', () => {
}); });
const amendCell = getAmendCell(); const amendCell = getAmendCell();
const typeCell = screen.getAllByRole('gridcell')[2]; const typeCell = screen.getAllByRole('gridcell')[3];
expect(typeCell).toHaveTextContent('Liquidity provision'); expect(typeCell).toHaveTextContent('Liquidity provision');
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument(); expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument(); expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
@ -215,7 +212,7 @@ describe('OrderListTable', () => {
}); });
const amendCell = getAmendCell(); const amendCell = getAmendCell();
const typeCell = screen.getAllByRole('gridcell')[2]; const typeCell = screen.getAllByRole('gridcell')[3];
expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit'); expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit');
expect(amendCell.queryByTestId('edit')).toBeInTheDocument(); expect(amendCell.queryByTestId('edit')).toBeInTheDocument();
expect(amendCell.queryByTestId('cancel')).toBeInTheDocument(); expect(amendCell.queryByTestId('cancel')).toBeInTheDocument();

View File

@ -63,6 +63,38 @@ export const OrderListTable = memo<
cellRendererParams: { idPath: 'market.id', onMarketClick }, cellRendererParams: { idPath: 'market.id', onMarketClick },
minWidth: 150, minWidth: 150,
}, },
{
headerName: t('Filled'),
field: 'remaining',
cellClass: 'font-mono text-right',
type: 'rightAligned',
valueGetter: ({ data }: VegaValueGetterParams<Order>) => {
return data?.size && data.market
? toBigNum(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
},
valueFormatter: ({
data,
value,
}: VegaValueFormatterParams<Order, 'remaining'>): string => {
if (!data) {
return '';
}
if (!data?.market || !isNumeric(value) || !isNumeric(data.size)) {
return '-';
}
return addDecimalsFormatNumber(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces
);
},
minWidth: 50,
width: 90,
flex: 0,
},
{ {
headerName: t('Size'), headerName: t('Size'),
field: 'size', field: 'size',
@ -103,7 +135,9 @@ export const OrderListTable = memo<
) )
); );
}, },
minWidth: 80, minWidth: 50,
width: 80,
flex: 0,
}, },
{ {
field: 'type', field: 'type',
@ -150,38 +184,6 @@ export const OrderListTable = memo<
), ),
minWidth: 100, minWidth: 100,
}, },
{
headerName: t('Filled'),
field: 'remaining',
cellClass: 'font-mono text-right',
type: 'rightAligned',
valueGetter: ({ data }: VegaValueGetterParams<Order>) => {
return data?.size && data.market
? toBigNum(
(BigInt(data.size) - BigInt(data.remaining)).toString(),
data.market.positionDecimalPlaces ?? 0
).toNumber()
: undefined;
},
valueFormatter: ({
data,
value,
}: VegaValueFormatterParams<Order, 'remaining'>): string => {
if (!data) {
return '';
}
if (!data?.market || !isNumeric(value) || !isNumeric(data.size)) {
return '-';
}
const { positionDecimalPlaces } = data.market;
const filled = BigInt(data.size) - BigInt(data.remaining);
return `${addDecimalsFormatNumber(
filled.toString(),
positionDecimalPlaces
)}/${addDecimalsFormatNumber(data.size, positionDecimalPlaces)}`;
},
minWidth: 100,
},
{ {
field: 'price', field: 'price',
type: 'rightAligned', type: 'rightAligned',
@ -221,12 +223,10 @@ export const OrderListTable = memo<
const expiry = getDateTimeFormat().format( const expiry = getDateTimeFormat().format(
new Date(data.expiresAt) new Date(data.expiresAt)
); );
return `${Schema.OrderTimeInForceMapping[value]}: ${expiry}`; return `${Schema.OrderTimeInForceCode[value]}: ${expiry}`;
} }
const tifLabel = value const tifLabel = value ? Schema.OrderTimeInForceCode[value] : '';
? Schema.OrderTimeInForceMapping[value]
: '';
const label = `${tifLabel}${ const label = `${tifLabel}${
data?.postOnly ? t('. Post Only') : '' data?.postOnly ? t('. Post Only') : ''
}${data?.reduceOnly ? t('. Reduce only') : ''}`; }${data?.reduceOnly ? t('. Reduce only') : ''}`;
@ -235,29 +235,18 @@ export const OrderListTable = memo<
}, },
minWidth: 150, minWidth: 150,
}, },
{
field: 'createdAt',
filter: DateRangeFilter,
cellRenderer: ({
value,
}: VegaICellRendererParams<Order, 'createdAt'>) => {
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : value}
</span>
);
},
minWidth: 150,
},
{ {
field: 'updatedAt', field: 'updatedAt',
filter: DateRangeFilter,
valueGetter: ({ data }: VegaValueGetterParams<Order>) =>
data?.updatedAt || data?.createdAt,
cellRenderer: ({ cellRenderer: ({
data, data,
value,
}: VegaICellRendererParams<Order, 'updatedAt'>) => { }: VegaICellRendererParams<Order, 'updatedAt'>) => {
if (!data) { if (!data) {
return undefined; return undefined;
} }
const value = data.updatedAt || data.createdAt;
return ( return (
<span data-value={value}> <span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : '-'} {value ? getDateTimeFormat().format(new Date(value)) : '-'}