From e89b818e4c7f6be27a31c5d429c4c68f730bbe43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20G=C5=82ownia?= Date: Thu, 6 Jul 2023 17:57:29 +0200 Subject: [PATCH] feat(orders): reduce number of columns in orders table (#4238) --- .../src/integration/trading-orders.cy.ts | 23 ++--- .../order-data-provider.spec.ts | 50 ---------- .../order-data-provider.ts | 35 ------- .../components/order-list/order-list.spec.tsx | 23 ++--- .../lib/components/order-list/order-list.tsx | 93 ++++++++----------- 5 files changed, 63 insertions(+), 161 deletions(-) diff --git a/apps/trading-e2e/src/integration/trading-orders.cy.ts b/apps/trading-e2e/src/integration/trading-orders.cy.ts index e096b5b04..1070ef804 100644 --- a/apps/trading-e2e/src/integration/trading-orders.cy.ts +++ b/apps/trading-e2e/src/integration/trading-orders.cy.ts @@ -16,7 +16,7 @@ const orderStatus = 'status'; const orderRemaining = 'remaining'; const orderPrice = 'price'; const orderTimeInForce = 'timeInForce'; -const orderCreatedAt = 'createdAt'; +const orderUpdatedAt = 'updatedAt'; const cancelOrderBtn = 'cancel'; const cancelAllOrdersBtn = 'cancelAll'; const editOrderBtn = 'edit'; @@ -46,6 +46,10 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => { 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.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.get(`[col-id='${orderRemaining}']`).each(($remaining) => { - cy.wrap($remaining).invoke('text').should('not.be.empty'); - }); - cy.get(`[col-id='${orderPrice}']`).each(($price) => { 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.get(`[col-id='${orderCreatedAt}']`).each(($dateTime) => { + cy.get(`[col-id='${orderUpdatedAt}']`).each(($dateTime) => { cy.wrap($dateTime).invoke('text').should('not.be.empty'); }); }); @@ -96,7 +96,8 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => { 'have.text', '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(editOrderBtn).should('not.exist'); }); @@ -219,7 +220,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => { cy.getByTestId(`order-status-${orderId}`) .parentsUntil(`.ag-row`) .siblings(`[col-id=${orderRemaining}]`) - .should('have.text', '4/5'); + .should('have.text', '4'); }); it('must see a filled order', () => { @@ -267,7 +268,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => { status: Schema.OrderStatus.STATUS_ACTIVE, }); cy.get(`[row-id=${orderId}]`) - .find('[col-id="size"]') + .find(`[col-id="${orderSize}"]`) .should('have.text', '-15'); }); @@ -281,7 +282,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => { status: Schema.OrderStatus.STATUS_ACTIVE, }); cy.get(`[row-id=${orderId}]`) - .find('[col-id="size"]') + .find(`[col-id="${orderSize}"]`) .should('have.text', '+5'); }); @@ -364,7 +365,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => { }); cy.get(`[row-id=${orderId}]`) .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 ', () => { diff --git a/libs/orders/src/lib/components/order-data-provider/order-data-provider.spec.ts b/libs/orders/src/lib/components/order-data-provider/order-data-provider.spec.ts index b47cb5a1e..923fd52cc 100644 --- a/libs/orders/src/lib/components/order-data-provider/order-data-provider.spec.ts +++ b/libs/orders/src/lib/components/order-data-provider/order-data-provider.spec.ts @@ -76,54 +76,4 @@ describe('order data provider', () => { )?.length ).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); - }); }); diff --git a/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts b/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts index 97b379323..cb907869d 100644 --- a/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts +++ b/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts @@ -39,13 +39,6 @@ const orderMatchFilters = ( return true; } - if ( - variables?.filter?.status && - !(order.status && variables.filter.status.includes(order.status)) - ) { - return false; - } - if ( variables?.filter?.liveOnly && !(order.status && liveOnlyOrderStatuses.includes(order.status)) @@ -53,34 +46,6 @@ const orderMatchFilters = ( 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; }; diff --git a/libs/orders/src/lib/components/order-list/order-list.spec.tsx b/libs/orders/src/lib/components/order-list/order-list.spec.tsx index 6af806a86..63e3a2ab6 100644 --- a/libs/orders/src/lib/components/order-list/order-list.spec.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.spec.tsx @@ -50,13 +50,12 @@ describe('OrderListTable', () => { }); const expectedHeaders = [ 'Market', + 'Filled', 'Size', 'Type', 'Status', - 'Filled', 'Price', 'Time In Force', - 'Created At', 'Updated At', '', // no cell header for edit/cancel ]; @@ -73,14 +72,13 @@ describe('OrderListTable', () => { const cells = screen.getAllByRole('gridcell'); const expectedValues: string[] = [ marketOrder.market?.tradableInstrument.instrument.code || '', - '+0.10', + '0.05', + '0.10', Schema.OrderTypeMapping[marketOrder.type as Schema.OrderType] || '', Schema.OrderStatusMapping[marketOrder.status], - '5', '-', - Schema.OrderTimeInForceMapping[marketOrder.timeInForce], + Schema.OrderTimeInForceCode[marketOrder.timeInForce], getDateTimeFormat().format(new Date(marketOrder.createdAt)), - '-', 'Edit', ]; expectedValues.forEach((expectedValue, i) => @@ -96,16 +94,15 @@ describe('OrderListTable', () => { const expectedValues: string[] = [ limitOrder.market?.tradableInstrument.instrument.code || '', - '+0.10', + '0.05', + '0.10', Schema.OrderTypeMapping[limitOrder.type || Schema.OrderType.TYPE_LIMIT], Schema.OrderStatusMapping[limitOrder.status], - '5', '-', `${ - Schema.OrderTimeInForceMapping[limitOrder.timeInForce] + Schema.OrderTimeInForceCode[limitOrder.timeInForce] }: ${getDateTimeFormat().format(new Date(limitOrder.expiresAt ?? ''))}`, getDateTimeFormat().format(new Date(limitOrder.createdAt)), - '-', 'Edit', ]; expectedValues.forEach((expectedValue, i) => @@ -124,7 +121,7 @@ describe('OrderListTable', () => { render(generateJsx({ rowData: [rejectedOrder] })); }); const cells = screen.getAllByRole('gridcell'); - expect(cells[3]).toHaveTextContent( + expect(cells[4]).toHaveTextContent( `${Schema.OrderStatusMapping[rejectedOrder.status]}: ${ Schema.OrderRejectionReasonMapping[rejectedOrder.rejectionReason] }` @@ -193,7 +190,7 @@ describe('OrderListTable', () => { }); const amendCell = getAmendCell(); - const typeCell = screen.getAllByRole('gridcell')[2]; + const typeCell = screen.getAllByRole('gridcell')[3]; expect(typeCell).toHaveTextContent('Liquidity provision'); expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument(); expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument(); @@ -215,7 +212,7 @@ describe('OrderListTable', () => { }); const amendCell = getAmendCell(); - const typeCell = screen.getAllByRole('gridcell')[2]; + const typeCell = screen.getAllByRole('gridcell')[3]; expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit'); expect(amendCell.queryByTestId('edit')).toBeInTheDocument(); expect(amendCell.queryByTestId('cancel')).toBeInTheDocument(); diff --git a/libs/orders/src/lib/components/order-list/order-list.tsx b/libs/orders/src/lib/components/order-list/order-list.tsx index b5a1aba40..b92bee2d0 100644 --- a/libs/orders/src/lib/components/order-list/order-list.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.tsx @@ -63,6 +63,38 @@ export const OrderListTable = memo< cellRendererParams: { idPath: 'market.id', onMarketClick }, minWidth: 150, }, + { + headerName: t('Filled'), + field: 'remaining', + cellClass: 'font-mono text-right', + type: 'rightAligned', + valueGetter: ({ data }: VegaValueGetterParams) => { + return data?.size && data.market + ? toBigNum( + (BigInt(data.size) - BigInt(data.remaining)).toString(), + data.market.positionDecimalPlaces ?? 0 + ).toNumber() + : undefined; + }, + valueFormatter: ({ + data, + value, + }: VegaValueFormatterParams): 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'), field: 'size', @@ -103,7 +135,9 @@ export const OrderListTable = memo< ) ); }, - minWidth: 80, + minWidth: 50, + width: 80, + flex: 0, }, { field: 'type', @@ -150,38 +184,6 @@ export const OrderListTable = memo< ), minWidth: 100, }, - { - headerName: t('Filled'), - field: 'remaining', - cellClass: 'font-mono text-right', - type: 'rightAligned', - valueGetter: ({ data }: VegaValueGetterParams) => { - return data?.size && data.market - ? toBigNum( - (BigInt(data.size) - BigInt(data.remaining)).toString(), - data.market.positionDecimalPlaces ?? 0 - ).toNumber() - : undefined; - }, - valueFormatter: ({ - data, - value, - }: VegaValueFormatterParams): 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', type: 'rightAligned', @@ -221,12 +223,10 @@ export const OrderListTable = memo< const expiry = getDateTimeFormat().format( new Date(data.expiresAt) ); - return `${Schema.OrderTimeInForceMapping[value]}: ${expiry}`; + return `${Schema.OrderTimeInForceCode[value]}: ${expiry}`; } - const tifLabel = value - ? Schema.OrderTimeInForceMapping[value] - : ''; + const tifLabel = value ? Schema.OrderTimeInForceCode[value] : ''; const label = `${tifLabel}${ data?.postOnly ? t('. Post Only') : '' }${data?.reduceOnly ? t('. Reduce only') : ''}`; @@ -235,29 +235,18 @@ export const OrderListTable = memo< }, minWidth: 150, }, - { - field: 'createdAt', - filter: DateRangeFilter, - cellRenderer: ({ - value, - }: VegaICellRendererParams) => { - return ( - - {value ? getDateTimeFormat().format(new Date(value)) : value} - - ); - }, - minWidth: 150, - }, { field: 'updatedAt', + filter: DateRangeFilter, + valueGetter: ({ data }: VegaValueGetterParams) => + data?.updatedAt || data?.createdAt, cellRenderer: ({ data, - value, }: VegaICellRendererParams) => { if (!data) { return undefined; } + const value = data.updatedAt || data.createdAt; return ( {value ? getDateTimeFormat().format(new Date(value)) : '-'}