From 478c4f83bba374fc411023310ed144efcd26bf57 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 14 Aug 2023 12:20:53 +0100 Subject: [PATCH 1/5] chore(trading): remove markets test (#4545) --- .../trading-e2e/src/integration/markets.cy.ts | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 apps/trading-e2e/src/integration/markets.cy.ts diff --git a/apps/trading-e2e/src/integration/markets.cy.ts b/apps/trading-e2e/src/integration/markets.cy.ts deleted file mode 100644 index 2783c78b8..000000000 --- a/apps/trading-e2e/src/integration/markets.cy.ts +++ /dev/null @@ -1,73 +0,0 @@ -import * as Schema from '@vegaprotocol/types'; -import { aliasGQLQuery } from '@vegaprotocol/cypress'; -import { marketsQuery } from '@vegaprotocol/mock'; -import { getDateTimeFormat } from '@vegaprotocol/utils'; - -describe('markets table', { tags: '@smoke' }, () => { - beforeEach(() => { - cy.clearLocalStorage().then(() => { - cy.mockTradingPage( - Schema.MarketState.STATE_ACTIVE, - Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION, - Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET - ); - cy.mockSubscription(); - cy.setOnBoardingViewed(); - cy.visit('/#/markets/all'); - }); - }); - - it('opening auction subsets should be properly displayed', () => { - cy.mockTradingPage( - Schema.MarketState.STATE_ACTIVE, - Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION - ); - cy.mockGQL((req) => { - const override = { - marketsConnection: { - edges: [ - { - node: { - tradableInstrument: { - instrument: { - name: `opening auction MARKET`, - }, - }, - state: Schema.MarketState.STATE_ACTIVE, - tradingMode: - Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION, - }, - }, - ], - }, - }; - // @ts-ignore partial deep check failing - const market = marketsQuery(override); - aliasGQLQuery(req, 'Market', market); - aliasGQLQuery(req, 'ProposalOfMarket', { - proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } }, - }); - }); - cy.visit('#/markets/market-0'); - cy.url().should('contain', 'market-0'); - cy.getByTestId('item-value').contains('Opening auction').realHover(); - cy.getByTestId('opening-auction-sub-status').should( - 'contain.text', - 'Opening auction: Not enough liquidity to open' - ); - - const now = new Date(Date.parse('2023-01-30 12:00:01')).getTime(); - cy.clock(now, ['Date']); // Set "now" to BEFORE reservation - cy.reload(); - cy.getByTestId('item-value').contains('Opening auction').realHover(); - cy.getByTestId('opening-auction-sub-status').should( - 'contain.text', - `Opening auction: Closing on ${getDateTimeFormat().format( - new Date('2023-01-31 12:00:01') - )}` - ); - cy.clock().then((clock) => { - clock.restore(); - }); - }); -}); From 30735388e84711bc5d4e2ec9435ca5b2e0af1892 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 14 Aug 2023 15:35:24 +0100 Subject: [PATCH 2/5] chore(trading): remove asset tests (#4548) --- apps/trading-e2e/src/integration/assets.cy.ts | 177 ------------------ 1 file changed, 177 deletions(-) delete mode 100644 apps/trading-e2e/src/integration/assets.cy.ts diff --git a/apps/trading-e2e/src/integration/assets.cy.ts b/apps/trading-e2e/src/integration/assets.cy.ts deleted file mode 100644 index e02c451e9..000000000 --- a/apps/trading-e2e/src/integration/assets.cy.ts +++ /dev/null @@ -1,177 +0,0 @@ -// #region consts -const assetColId = '[col-id="asset.symbol"]'; -const assetDetailsDialog = 'dialog-content'; -const assetRow = 'key-value-table-row'; -const contractAddress = '7_value'; -const dialogCloseBtn = 'close-asset-details-dialog'; -const dialogCloseX = 'dialog-close'; -const dialogTitle = 'dialog-title'; - -const indicesWithLabelTooltips = [4, 5, 6, 7, 8, 9, 11, 12, 13, 14]; -const indicesWithValueTooltips = [1, 6]; - -const labelValueToolTipPairs = [ - { - label: 'ID', - value: 'asset-id', - }, - { - label: 'Type', - value: 'ERC20', - valueToolTip: 'An asset originated from an Ethereum ERC20 Token', - }, - { - label: 'Name', - value: 'Euro', - }, - { - label: 'Symbol', - value: 'tEURO', - }, - { - label: 'Decimals', - value: '5', - labelTooltip: 'Number of decimal / precision handled by this asset', - }, - { - label: 'Quantum', - value: '0.00001', - labelTooltip: 'The minimum economically meaningful amount of the asset', - }, - { - label: 'Status', - value: 'Enabled', - labelTooltip: 'The status of the asset in the Vega network', - valueToolTip: 'Asset can be used on the Vega network', - }, - { - label: 'Contract address', - value: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4 ', - labelTooltip: - 'The address of the contract for the token, on the ethereum network', - }, - { - label: 'Withdrawal threshold', - value: '0.0005', - labelTooltip: - "The maximum you can withdraw instantly. There's no limit on the size of a withdrawal, but all withdrawals over the threshold will have a delay time added to them", - }, - { - label: 'Lifetime limit', - value: '1,230.00', - labelTooltip: - 'The lifetime deposit limit per address. Note: this is a temporary measure that can be changed or removed through governance', - }, - { label: '', value: '' }, - { - label: 'Infrastructure fee account balance', - value: '0.00001', - labelTooltip: 'The infrastructure fee account in this asset', - }, - { - label: 'Global reward pool account balance', - value: '0.00002', - labelTooltip: 'The global rewards acquired in this asset', - }, - { - label: 'Maker paid fees account balance', - value: '0.00003', - labelTooltip: - 'The rewards acquired based on the fees paid to makers in this asset', - }, - { - label: 'Maker received fees account balance', - value: '0.00004', - labelTooltip: - 'The rewards acquired based on fees received for being a maker on trades', - }, - { - label: 'Liquidity provision fee reward account balance', - value: '0.00005', - labelTooltip: - 'The rewards acquired based on the liquidity provision fees in this asset', - }, - { - label: 'Market proposer reward account balance', - value: '0.00006', - labelTooltip: - 'The rewards acquired based on the market proposer reward in this asset', - }, -]; -//endregion - -beforeEach(() => { - cy.mockTradingPage(); - cy.mockSubscription(); - cy.setVegaWallet(); -}); - -const visitPortfolioAndClickAsset = (assetName: string) => { - cy.visit('/#/portfolio'); - cy.get(assetColId).contains(assetName).click(); -}; - -const testTooltip = (index: number, testId: string, tooltip: string) => { - cy.getByTestId(`${index}_${testId}`).realHover(); - cy.get('[role="tooltip"]').find('div').should('have.text', tooltip); - cy.getByTestId(dialogTitle).click(); -}; - -describe('assets', { tags: '@smoke', testIsolation: true }, () => { - it('asset details', () => { - visitPortfolioAndClickAsset('tBTC'); - - cy.getByTestId(assetRow).each((element, index) => { - if (index === 10) { - return; - } - const { label, value, labelTooltip, valueToolTip } = - labelValueToolTipPairs[index]; - // 6501-ASSE-001 - // 6501-ASSE-002 - // 6501-ASSE-003 - // 6501-ASSE-004 - // 6501-ASSE-005 - // 6501-ASSE-006 - // 6501-ASSE-007 - // 6501-ASSE-008 - // 6501-ASSE-009 - // 6501-ASSE-010 - // 6501-ASSE-011 - cy.getByTestId(`${index}_label`).should('have.text', label); - cy.getByTestId(`${index}_value`).should('have.text', value); - - // 6501-ASSE-012 - if (indicesWithLabelTooltips.includes(index)) { - if (labelTooltip) { - testTooltip(index, 'label', labelTooltip); - } - } - if (indicesWithValueTooltips.includes(index)) { - if (valueToolTip) { - testTooltip(index, 'value', valueToolTip); - } - } - }); - // 6501-ASSE-013 - cy.getByTestId(dialogCloseX).click(); - cy.document().then((doc) => { - expect(doc.querySelector(assetDetailsDialog)).to.not.exist; - }); - }); - - it('ERC20 Contract address', () => { - visitPortfolioAndClickAsset('tBTC'); - cy.getByTestId(contractAddress).within(() => { - // 6501-ASSE-014 - cy.getByTestId('external-link') - .should('have.attr', 'target', '_blank') - .should('have.text', '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4'); - }); - // 6501-ASSE-013 - cy.getByTestId(dialogCloseBtn).click(); - cy.document().then((doc) => { - expect(doc.querySelector(assetDetailsDialog)).to.not.exist; - }); - }); -}); From cd3acf8ff9b96f9fb964fb25d404cfd9e758f64d Mon Sep 17 00:00:00 2001 From: Joe Tsang <30622993+jtsang586@users.noreply.github.com> Date: Mon, 14 Aug 2023 16:17:29 +0100 Subject: [PATCH 3/5] test(explorer): successor market explorer (#4544) --- .../explorer-e2e/src/integration/market.cy.js | 56 +++++++- .../src/integration/proposal.cy.js | 39 +++--- .../src/support/common.functions.js | 7 + .../src/support/governance.functions.js | 130 ++++++++++++++++++ .../integration/flow/proposal-details.cy.ts | 2 +- .../integration/flow/proposal-enacted.cy.ts | 1 + .../src/integration/flow/proposal-flow.cy.ts | 1 + .../src/integration/flow/proposal-forms.cy.ts | 1 + .../src/integration/flow/proposal-list.cy.ts | 1 + .../src/integration/flow/rewards-flow.cy.ts | 1 + .../src/integration/flow/staking-flow.cy.ts | 11 +- .../flow/token-association-flow.cy.ts | 1 + .../integration/flow/withdrawal-flow.cy.ts | 11 +- libs/cypress/src/index.ts | 2 + .../cypress/src/lib/commands/mock-chain-id.ts | 22 +++ 15 files changed, 241 insertions(+), 45 deletions(-) create mode 100644 apps/explorer-e2e/src/support/governance.functions.js create mode 100644 libs/cypress/src/lib/commands/mock-chain-id.ts diff --git a/apps/explorer-e2e/src/integration/market.cy.js b/apps/explorer-e2e/src/integration/market.cy.js index f72b49df4..559df3faa 100644 --- a/apps/explorer-e2e/src/integration/market.cy.js +++ b/apps/explorer-e2e/src/integration/market.cy.js @@ -1,8 +1,8 @@ +import { createSuccessorMarketProposal } from '../support/governance.functions'; + context('Market page', { tags: '@regression' }, function () { describe('Verify elements on page', function () { const marketHeaders = 'markets-heading'; - const createdMarketId = - '2eab0e66545a789047561bc5a2e5cbc3b19eb708da41104e3cac2474ee36c4d4'; before('Create market', function () { cy.visit('/'); @@ -11,7 +11,7 @@ context('Market page', { tags: '@regression' }, function () { beforeEach('Get market id', function () { cy.navigate_to('markets'); - cy.get('[col-id="id"]').eq(1).invoke('text').as('createdMarketId'); + cy.get('[col-id="id"]').last().invoke('text').as('createdMarketId'); }); it('Market displayed on market page', function () { @@ -106,6 +106,7 @@ context('Market page', { tags: '@regression' }, function () { // Able to view Json cy.contains('View JSON').click(); cy.get('.language-json').should('exist'); + cy.getByTestId('icon-cross').click(); }); // Skipping due to resize observer loop limit error @@ -113,17 +114,60 @@ context('Market page', { tags: '@regression' }, function () { cy.common_switch_to_mobile_and_click_toggle(); cy.navigate_to('markets', true); cy.getByTestId(marketHeaders).should('be.visible'); - cy.get(`[row-id="${createdMarketId}"]`) + cy.get(`[row-id="${this.createdMarketId}"]`) .should('be.visible') .within(() => { cy.get_element_by_col_id('code').should('have.text', 'TEST.24h'); cy.get_element_by_col_id('name').should('have.text', 'Test market 1'); cy.get_element_by_col_id('state').should('have.text', 'Pending'); cy.get_element_by_col_id('asset').should('have.text', 'fUSDC'); - cy.get_element_by_col_id('id').should('have.text', createdMarketId); + cy.get_element_by_col_id('id').should( + 'have.text', + this.createdMarketId + ); cy.get_element_by_col_id('actions') .find('a') - .should('have.attr', 'href', `/markets/${createdMarketId}`); + .should('have.attr', 'href', `/markets/${this.createdMarketId}`); + }); + }); + + it('Able to go to market details page for successor market', function () { + const successionLineItem = 'succession-line-item'; + const successionLineMarketId = 'succession-line-item-market-id'; + + createSuccessorMarketProposal(this.createdMarketId); + cy.navigate_to('markets'); + cy.reload(); + cy.contains('Token test market', { timeout: 8000 }).should('be.visible'); + cy.get('[row-index="0"]') + .invoke('attr', 'row-id') + .as('successorMarketId'); + cy.contains('Token test market').click(); + cy.getByTestId(marketHeaders).should('have.text', 'Token test market'); + cy.validate_proposal_change_type('Triggering Ratio', 'Added'); + cy.validate_element_from_table('Triggering Ratio', '0.7'); + cy.validate_proposal_change_type('Time Window', 'Added'); + cy.validate_element_from_table('Time Window', '3,600'); + cy.validate_proposal_change_type('Scaling Factor', 'Added'); + cy.validate_element_from_table('Scaling Factor', '10'); + + cy.getByTestId(successionLineItem) + .first() + .within(() => { + cy.contains('Test market 1'); + cy.getByTestId(successionLineMarketId).should( + 'have.text', + this.createdMarketId + ); + }); + cy.getByTestId(successionLineItem) + .eq(1) + .within(() => { + cy.contains('Token test market'); + cy.getByTestId(successionLineMarketId).should( + 'have.text', + this.successorMarketId + ); }); }); }); diff --git a/apps/explorer-e2e/src/integration/proposal.cy.js b/apps/explorer-e2e/src/integration/proposal.cy.js index 46225c5da..1c6615d90 100644 --- a/apps/explorer-e2e/src/integration/proposal.cy.js +++ b/apps/explorer-e2e/src/integration/proposal.cy.js @@ -13,28 +13,31 @@ context('Proposal page', { tags: '@smoke' }, function () { it('Able to view proposal', function () { cy.navigate_to('governanceProposals'); cy.getByTestId(proposalHeading).should('be.visible'); - // get first proposal in list - cy.get('[row-index="0"]').within(() => { - cy.get_element_by_col_id('title').should('have.text', proposalTitle); - cy.get_element_by_col_id('type').should('have.text', 'NewMarket'); - cy.get_element_by_col_id('state').should('have.text', 'Enacted'); - cy.getByTestId('vote-progress').should('be.visible'); - cy.get('[col-id="cDate"]') - .invoke('text') - .should('match', dateTimeRegex); - cy.get('[col-id="eDate"]') - .invoke('text') - .should('match', dateTimeRegex); - cy.getByTestId('external-link') - .should('have.attr', 'href') - .and('contains', 'https://governance.fairground.wtf/proposals/'); - cy.contains('View terms').should('exist').click(); - }); + cy.contains(proposalTitle) + .parent() + .parent() + .parent() + .within(() => { + cy.get_element_by_col_id('title').should('have.text', proposalTitle); + cy.get_element_by_col_id('type').should('have.text', 'NewMarket'); + cy.get_element_by_col_id('state').should('have.text', 'Enacted'); + cy.getByTestId('vote-progress').should('be.visible'); + cy.get('[col-id="cDate"]') + .invoke('text') + .should('match', dateTimeRegex); + cy.get('[col-id="eDate"]') + .invoke('text') + .should('match', dateTimeRegex); + cy.getByTestId('external-link') + .should('have.attr', 'href') + .and('contains', 'https://governance.fairground.wtf/proposals/'); + cy.contains('View terms').should('exist').click(); + }); cy.getByTestId('dialog-title').should('have.text', proposalTitle); cy.get('.language-json').should('exist'); }); - it('Proposal page displayed on mobile', function () { + it.skip('Proposal page displayed on mobile', function () { cy.common_switch_to_mobile_and_click_toggle(); cy.navigate_to('governanceProposals', true); cy.getByTestId(proposalHeading).should('be.visible'); diff --git a/apps/explorer-e2e/src/support/common.functions.js b/apps/explorer-e2e/src/support/common.functions.js index 6ef2860f1..50cbc1ec2 100644 --- a/apps/explorer-e2e/src/support/common.functions.js +++ b/apps/explorer-e2e/src/support/common.functions.js @@ -127,3 +127,10 @@ Cypress.Commands.add( .should('have.text', tableRowValue); } ); + +Cypress.Commands.add( + 'validate_proposal_change_type', + (tableRowName, changeType) => { + cy.contains(tableRowName).siblings().should('have.text', changeType); + } +); diff --git a/apps/explorer-e2e/src/support/governance.functions.js b/apps/explorer-e2e/src/support/governance.functions.js new file mode 100644 index 000000000..a509fa40d --- /dev/null +++ b/apps/explorer-e2e/src/support/governance.functions.js @@ -0,0 +1,130 @@ +export function createSuccessorMarketProposal(parentMarketId) { + cy.VegaWalletSubmitProposal(getSuccessorTxBody(parentMarketId)); +} + +function getSuccessorTxBody(parentMarketId) { + return { + proposalSubmission: { + rationale: { + title: 'Test successor market proposal details', + description: 'E2E test for successor market', + }, + terms: { + newMarket: { + changes: { + decimalPlaces: '5', + positionDecimalPlaces: '5', + linearSlippageFactor: '0.001', + quadraticSlippageFactor: '0', + lpPriceRange: '10', + instrument: { + name: 'Token test market', + code: 'TEST.24h', + future: { + settlementAsset: + '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc', + quoteName: 'fUSDC', + dataSourceSpecForSettlementData: { + external: { + oracle: { + signers: [ + { + pubKey: { + key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680', + }, + }, + ], + filters: [ + { + key: { + name: 'prices.BTC.value', + type: 'TYPE_INTEGER', + numberDecimalPlaces: '0', + }, + conditions: [ + { + operator: 'OPERATOR_GREATER_THAN', + value: '0', + }, + ], + }, + ], + }, + }, + }, + dataSourceSpecForTradingTermination: { + external: { + oracle: { + signers: [ + { + pubKey: { + key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680', + }, + }, + ], + filters: [ + { + key: { + name: 'trading.terminated.ETH5', + type: 'TYPE_BOOLEAN', + }, + conditions: [ + { + operator: 'OPERATOR_EQUALS', + value: 'true', + }, + ], + }, + ], + }, + }, + }, + dataSourceSpecBinding: { + settlementDataProperty: 'prices.BTC.value', + tradingTerminationProperty: 'trading.terminated.ETH5', + }, + }, + }, + metadata: [ + 'sector:food', + 'sector:materials', + 'source:docs.vega.xyz', + ], + priceMonitoringParameters: { + triggers: [ + { + horizon: '43200', + probability: '0.9999999', + auctionExtension: '600', + }, + ], + }, + liquidityMonitoringParameters: { + targetStakeParameters: { + timeWindow: '3600', + scalingFactor: 10, + }, + triggeringRatio: '0.7', + auctionExtension: '1', + }, + logNormal: { + tau: 0.0001140771161, + riskAversionParameter: 0.01, + params: { + mu: 0, + r: 0.016, + sigma: 0.5, + }, + }, + successor: { + parentMarketId: parentMarketId, + insurancePoolFraction: '0.75', + }, + }, + }, + closingTimestamp: 1695666618, + enactmentTimestamp: 1695666618, + }, + }, + }; +} diff --git a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts index ca8a61e33..a8defbc08 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts @@ -55,12 +55,12 @@ describe( before('connect wallets and set approval limit', function () { cy.visit('/'); ethereumWalletConnect(); - // cy.associateTokensToVegaWallet('1'); }); beforeEach('visit proposals tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.reload(); waitForSpinner(); cy.connectVegaWallet(); diff --git a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts index f65adf490..435e429d3 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts @@ -42,6 +42,7 @@ context( beforeEach('visit proposals', function () { cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.reload(); waitForSpinner(); cy.connectVegaWallet(); diff --git a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts index c5f72c211..6b15e7f81 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts @@ -82,6 +82,7 @@ context( cy.clearLocalStorage(); turnTelemetryOff(); cy.reload(); + cy.mockChainId(); waitForSpinner(); cy.connectVegaWallet(); ethereumWalletConnect(); diff --git a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts index a506de724..f78a688e3 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts @@ -74,6 +74,7 @@ context( beforeEach('visit governance tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.reload(); waitForSpinner(); cy.connectVegaWallet(); diff --git a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts index f3c21bc98..6bd4093ea 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts @@ -42,6 +42,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { cy.clearLocalStorage(); turnTelemetryOff(); cy.reload(); + cy.mockChainId(); waitForSpinner(); cy.connectVegaWallet(); ethereumWalletConnect(); diff --git a/apps/governance-e2e/src/integration/flow/rewards-flow.cy.ts b/apps/governance-e2e/src/integration/flow/rewards-flow.cy.ts index 59c0db832..c207d160a 100644 --- a/apps/governance-e2e/src/integration/flow/rewards-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/rewards-flow.cy.ts @@ -26,6 +26,7 @@ context('rewards - flow', { tags: '@slow' }, function () { before('set up environment to allow rewards', function () { cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.visit('/'); waitForSpinner(); ethereumWalletConnect(); diff --git a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts index d3fd39507..c5e67fd51 100644 --- a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts @@ -25,8 +25,6 @@ import { vegaWalletSetSpecifiedApprovalAmount, vegaWalletTeardown, } from '../../support/wallet-functions'; -import { aliasGQLQuery } from '@vegaprotocol/cypress'; -import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock'; const stakeValidatorListTotalStake = 'total-stake'; const stakeValidatorListTotalShare = 'total-stake-share'; @@ -58,10 +56,6 @@ context( function () { // 1002-STKE-002, 1002-STKE-032 before('visit staking tab and connect vega wallet', function () { - cy.mockGQL((req) => { - aliasGQLQuery(req, 'ChainId', chainIdQuery()); - aliasGQLQuery(req, 'Statistics', statisticsQuery()); - }); cy.visit('/'); ethereumWalletConnect(); cy.connectVegaWallet(); @@ -72,12 +66,9 @@ context( beforeEach( 'teardown wallet & drill into a specific validator', function () { - cy.mockGQL((req) => { - aliasGQLQuery(req, 'ChainId', chainIdQuery()); - aliasGQLQuery(req, 'Statistics', statisticsQuery()); - }); cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); // Go to homepage to allow wallet teardown without epoch timer refreshing page navigateTo(navigation.home); vegaWalletTeardown(); diff --git a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts index 2bddc0758..540dc87fb 100644 --- a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts @@ -56,6 +56,7 @@ context( function () { cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.reload(); waitForSpinner(); cy.connectVegaWallet(); diff --git a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts index 946311c28..eba299c4b 100644 --- a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts @@ -6,8 +6,6 @@ import { } from '../../support/common.functions'; import { ethereumWalletConnect } from '../../support/wallet-eth.functions'; import { depositAsset } from '../../support/wallet-functions'; -import { aliasGQLQuery } from '@vegaprotocol/cypress'; -import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock'; const withdraw = 'withdraw'; const withdrawalForm = 'withdraw-form'; @@ -44,22 +42,15 @@ context( { tags: '@slow' }, function () { before('visit withdrawals and connect vega wallet', function () { - cy.mockGQL((req) => { - aliasGQLQuery(req, 'ChainId', chainIdQuery()); - aliasGQLQuery(req, 'Statistics', statisticsQuery()); - }); cy.visit('/'); ethereumWalletConnect(); depositAsset(usdcEthAddress, '1000', 5); }); beforeEach('Navigate to withdrawal page', function () { - cy.mockGQL((req) => { - aliasGQLQuery(req, 'ChainId', chainIdQuery()); - aliasGQLQuery(req, 'Statistics', statisticsQuery()); - }); cy.clearLocalStorage(); turnTelemetryOff(); + cy.mockChainId(); cy.reload(); waitForSpinner(); navigateTo(navigation.withdraw); diff --git a/libs/cypress/src/index.ts b/libs/cypress/src/index.ts index 906083983..b2a77bdff 100644 --- a/libs/cypress/src/index.ts +++ b/libs/cypress/src/index.ts @@ -24,6 +24,7 @@ import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-walle import { addImportNodeWallets } from './lib/commands/import-node-wallets'; import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up-rewards-pool'; import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet'; +import { addMockChainId } from './lib/commands/mock-chain-id'; addGetTestIdcommand(); addMockGQLCommand(); @@ -49,6 +50,7 @@ addVegaWalletSubmitLiquidityProvision(); addImportNodeWallets(); addVegaWalletTopUpRewardsPool(); addAssociateTokensToVegaWallet(); +addMockChainId(); export { mockConnectWallet, diff --git a/libs/cypress/src/lib/commands/mock-chain-id.ts b/libs/cypress/src/lib/commands/mock-chain-id.ts new file mode 100644 index 000000000..541c05c80 --- /dev/null +++ b/libs/cypress/src/lib/commands/mock-chain-id.ts @@ -0,0 +1,22 @@ +import { aliasGQLQuery } from '../mock-gql'; +// eslint-disable-next-line @nx/enforce-module-boundaries +import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock'; + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Cypress { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + interface Chainable { + mockChainId(): void; + } + } +} + +export function addMockChainId() { + Cypress.Commands.add('mockChainId', () => { + cy.mockGQL((req) => { + aliasGQLQuery(req, 'ChainId', chainIdQuery()); + aliasGQLQuery(req, 'Statistics', statisticsQuery()); + }); + }); +} From 20cbcb830287c46d68c2902f0d7fb85c91ef6ff5 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 14 Aug 2023 18:06:36 +0100 Subject: [PATCH 4/5] chore(trading): remove home tests (#4551) --- apps/trading-e2e/src/integration/home.cy.ts | 207 -------------------- 1 file changed, 207 deletions(-) delete mode 100644 apps/trading-e2e/src/integration/home.cy.ts diff --git a/apps/trading-e2e/src/integration/home.cy.ts b/apps/trading-e2e/src/integration/home.cy.ts deleted file mode 100644 index 88081b42c..000000000 --- a/apps/trading-e2e/src/integration/home.cy.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { aliasGQLQuery } from '@vegaprotocol/cypress'; -import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals'; -import * as Schema from '@vegaprotocol/types'; - -const dialogContent = 'welcome-dialog'; - -const generateProposal = (code: string): ProposalListFieldsFragment => ({ - __typename: 'Proposal', - reference: '', - state: Schema.ProposalState.STATE_OPEN, - datetime: '', - votes: { - __typename: undefined, - yes: { - __typename: undefined, - totalTokens: '', - totalNumber: '', - totalWeight: '', - }, - no: { - __typename: undefined, - totalTokens: '', - totalNumber: '', - totalWeight: '', - }, - }, - requiredMajority: '', - party: { - __typename: 'Party', - id: '', - }, - rationale: { - __typename: 'ProposalRationale', - description: '', - title: '', - }, - requiredParticipation: '', - errorDetails: '', - rejectionReason: null, - requiredLpMajority: '', - requiredLpParticipation: '', - terms: { - __typename: 'ProposalTerms', - closingDatetime: '', - enactmentDatetime: undefined, - change: { - __typename: 'NewMarket', - decimalPlaces: 1, - lpPriceRange: '', - riskParameters: { - __typename: 'SimpleRiskModel', - params: { - __typename: 'SimpleRiskModelParams', - factorLong: 0, - factorShort: 1, - }, - }, - metadata: [], - instrument: { - __typename: 'InstrumentConfiguration', - code: code, - name: code, - futureProduct: { - __typename: 'FutureProduct', - settlementAsset: { - __typename: 'Asset', - id: 'A', - name: 'A', - symbol: 'A', - decimals: 1, - quantum: '', - }, - quoteName: '', - dataSourceSpecBinding: { - __typename: 'DataSourceSpecToFutureBinding', - settlementDataProperty: '', - tradingTerminationProperty: '', - }, - dataSourceSpecForSettlementData: { - __typename: 'DataSourceDefinition', - sourceType: { - __typename: 'DataSourceDefinitionInternal', - }, - }, - dataSourceSpecForTradingTermination: { - __typename: 'DataSourceDefinition', - sourceType: { - __typename: 'DataSourceDefinitionInternal', - }, - }, - }, - }, - }, - }, -}); - -describe('home', { tags: '@regression' }, () => { - beforeEach(() => { - cy.clearLocalStorage(); - cy.mockTradingPage(); - cy.mockSubscription(); - }); - - describe('default market found', () => { - it('redirects to a default market with the landing dialog open', () => { - cy.visit('/'); - cy.wait('@Markets'); - - cy.get('[data-testid^="pathname-/markets/"]'); - - // the choose market overlay is no longer showing - cy.contains('Loading...').should('not.exist'); - cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0'); - }); - }); - - describe('no markets found', () => { - beforeEach(() => { - cy.mockGQL((req) => { - const data = { - marketsConnection: { - __typename: 'MarketConnection', - edges: [], - }, - }; - const proposalA: ProposalListFieldsFragment = - generateProposal('AAAZZZ'); - - aliasGQLQuery(req, 'Markets', data); - aliasGQLQuery(req, 'MarketsData', data); - aliasGQLQuery(req, 'ProposalsList', { - proposalsConnection: { - __typename: 'ProposalsConnection', - edges: [{ __typename: 'ProposalEdge', node: proposalA }], - }, - }); - }); - cy.visit('/'); - cy.wait('@Markets'); - cy.wait('@MarketsData'); - }); - - it('close welcome dialog should redirect to market/all', () => { - cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`); - cy.getByTestId('welcome-dialog').should('be.visible'); - cy.getByTestId('welcome-title').should('contain.text', 'Console CUSTOM'); - cy.getByTestId('browse-markets-button').should('not.be.disabled'); - cy.getByTestId('get-started-banner').should('be.visible'); - cy.getByTestId('get-started-button').should('not.be.disabled'); - cy.getByTestId('dialog-close').click(); - cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`); - cy.window().then((window) => { - expect(window.localStorage.getItem('vega_onboarding_viewed')).to.equal( - 'true' - ); - }); - }); - - it('click browse markets button should redirect to market/all', () => { - cy.getByTestId('welcome-dialog').should('be.visible'); - cy.getByTestId('browse-markets-button').click(); - cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`); - cy.window().then((window) => { - expect(window.localStorage.getItem('vega_onboarding_viewed')).to.equal( - 'true' - ); - }); - }); - - it('click get started button should open connect dialog', () => { - cy.getByTestId('welcome-dialog').should('be.visible'); - cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`); - cy.window().then((window) => { - // @ts-ignore stub it out just for test case - window.vega = {}; - cy.getByTestId('get-started-button').click(); - cy.getByTestId('wallet-dialog-title').should('contain.text', 'Connect'); - }); - }); - }); - - describe('redirect should take last visited market into consideration', () => { - it('marketId comes from existing market', () => { - cy.window().then((window) => { - window.localStorage.setItem('marketId', 'market-1'); - cy.visit('/'); - cy.getByTestId('dialog-close').click(); - cy.location('hash').should('equal', '#/markets/market-1'); - cy.getByTestId(dialogContent).should('not.exist'); - }); - }); - - it('marketId comes from not-existing market', () => { - cy.window().then((window) => { - window.localStorage.setItem('marketId', 'market-not-existing'); - cy.mockGQL((req) => { - aliasGQLQuery(req, 'Market', null); - }); - cy.visit('/'); - cy.wait('@Markets'); - cy.getByTestId('dialog-close').click(); - cy.location('hash').should('equal', '#/markets/market-not-existing'); - cy.getByTestId(dialogContent).should('not.exist'); - }); - }); - }); -}); From e4eedf5ccdece0d1a766ee6b6bfa2053ea7a73d8 Mon Sep 17 00:00:00 2001 From: Matthew Russell Date: Tue, 15 Aug 2023 12:26:13 +0100 Subject: [PATCH 5/5] feat(trading,datagrid): datagrid improvements (#4524) --- .github/workflows/ci-cd-trigger.yml | 2 +- apps/explorer-e2e/cypress.config.js | 1 + apps/governance-e2e/cypress.config.js | 1 + .../integration/flow/withdrawal-flow.cy.ts | 3 +- .../src/integration/view/proposal.cy.ts | 2 +- apps/trading-e2e/cypress.config.js | 1 + .../src/integration/trading-positions.cy.ts | 5 +- .../src/integration/trading-trades.cy.ts | 4 +- .../client-pages/market/trade-views.tsx | 2 +- apps/trading/client-pages/markets/closed.tsx | 6 -- .../positions-container.tsx | 4 +- .../components/trades-container/index.ts | 1 + .../trades-container/trades-container.tsx | 24 +++++ apps/trading/pages/styles.css | 10 +++ libs/accounts/src/lib/accounts-table.tsx | 14 +-- libs/accounts/src/lib/breakdown-table.tsx | 14 ++- .../src/lib/ag-grid/ag-grid-lazy-themed.tsx | 33 ++++--- .../src/lib/cells/market-name-cell.tsx | 6 +- libs/datagrid/src/lib/column-definitions.ts | 4 +- .../src/lib/use-datagrid-events.spec.tsx | 52 ++--------- libs/datagrid/src/lib/use-datagrid-events.ts | 90 ++++++++++++++----- libs/deposits/src/lib/deposits-table.tsx | 10 +-- libs/fills/src/lib/fills-table.tsx | 2 - libs/ledger/src/lib/ledger-table.tsx | 22 ++--- libs/liquidity/src/lib/liquidity-table.tsx | 15 ++-- .../markets-container/market-list-table.tsx | 3 - .../markets-container/use-column-defs.tsx | 1 - .../order-list-manager/order-list-manager.tsx | 1 - .../lib/components/order-list/order-list.tsx | 32 ++----- .../stop-orders-table/stop-orders-table.tsx | 25 ++---- libs/positions/src/lib/positions-manager.tsx | 24 +++-- .../src/lib/positions-table.spec.tsx | 11 ++- libs/positions/src/lib/positions-table.tsx | 56 ++++-------- .../proposals-list/proposals-list.tsx | 1 - .../proposals-list/use-column-defs.tsx | 5 -- libs/trades/src/index.ts | 2 +- ...rades-container.tsx => trades-manager.tsx} | 8 +- libs/trades/src/lib/trades-table.spec.tsx | 4 +- libs/trades/src/lib/trades-table.tsx | 13 +-- .../trading-dropdown/actions-dropdown.tsx | 5 +- libs/withdraws/src/lib/withdrawals-table.tsx | 3 - 41 files changed, 243 insertions(+), 279 deletions(-) create mode 100644 apps/trading/components/trades-container/index.ts create mode 100644 apps/trading/components/trades-container/trades-container.tsx rename libs/trades/src/lib/{trades-container.tsx => trades-manager.tsx} (76%) diff --git a/.github/workflows/ci-cd-trigger.yml b/.github/workflows/ci-cd-trigger.yml index ab5d07641..592d2112c 100644 --- a/.github/workflows/ci-cd-trigger.yml +++ b/.github/workflows/ci-cd-trigger.yml @@ -137,7 +137,7 @@ jobs: secrets: inherit with: projects: ${{ needs.lint-test-build.outputs.projects-e2e }} - tags: '@smoke @regression' + tags: '@smoke' publish-dist: needs: lint-test-build diff --git a/apps/explorer-e2e/cypress.config.js b/apps/explorer-e2e/cypress.config.js index 2ce3326ce..bb90e37e6 100644 --- a/apps/explorer-e2e/cypress.config.js +++ b/apps/explorer-e2e/cypress.config.js @@ -23,6 +23,7 @@ module.exports = defineConfig({ viewportWidth: 1440, viewportHeight: 900, testIsolation: false, + experimentalMemoryManagement: true, }, env: { environment: 'CUSTOM', diff --git a/apps/governance-e2e/cypress.config.js b/apps/governance-e2e/cypress.config.js index fa4caa50a..9ae1de52c 100644 --- a/apps/governance-e2e/cypress.config.js +++ b/apps/governance-e2e/cypress.config.js @@ -28,6 +28,7 @@ module.exports = defineConfig({ numTestsKeptInMemory: 5, downloadsFolder: 'cypress/downloads', testIsolation: false, + experimentalMemoryManagement: true, }, env: { ethProviderUrl: 'http://localhost:8545/', diff --git a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts index eba299c4b..30c480d5c 100644 --- a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts @@ -97,7 +97,8 @@ context( }); }); - it( + // eslint-disable-next-line + it.skip( 'Able to withdraw asset: -eth wallet connected -withdraw funds button', { tags: '@smoke' }, function () { diff --git a/apps/governance-e2e/src/integration/view/proposal.cy.ts b/apps/governance-e2e/src/integration/view/proposal.cy.ts index 02f282e5a..28395cdbf 100644 --- a/apps/governance-e2e/src/integration/view/proposal.cy.ts +++ b/apps/governance-e2e/src/integration/view/proposal.cy.ts @@ -231,7 +231,7 @@ context( }); // 3009-NTWU-001 3009-NTWU-002 3009-NTWU-006 3009-NTWU-009 - it('should display network upgrade banner with estimate', function () { + it.skip('should display network upgrade banner with estimate', function () { mockNetworkUpgradeProposal(); cy.visit('/'); cy.getByTestId('banners').within(() => { diff --git a/apps/trading-e2e/cypress.config.js b/apps/trading-e2e/cypress.config.js index 853f95f92..b74c9d4fd 100644 --- a/apps/trading-e2e/cypress.config.js +++ b/apps/trading-e2e/cypress.config.js @@ -26,6 +26,7 @@ module.exports = defineConfig({ requestTimeout: 20000, retries: 1, testIsolation: false, + experimentalMemoryManagement: true, }, env: { ETHERSCAN_URL: 'https://sepolia.etherscan.io', diff --git a/apps/trading-e2e/src/integration/trading-positions.cy.ts b/apps/trading-e2e/src/integration/trading-positions.cy.ts index b13928075..d1497801d 100644 --- a/apps/trading-e2e/src/integration/trading-positions.cy.ts +++ b/apps/trading-e2e/src/integration/trading-positions.cy.ts @@ -27,7 +27,8 @@ describe('positions', { tags: '@smoke', testIsolation: true }, () => { validatePositionsDisplayed(); }); - it('renders positions on portfolio page', () => { + // TODO: move this to sim, its flakey + it.skip('renders positions on portfolio page', () => { cy.mockGQL((req) => { const positions = positionsQuery(); if (positions.positions?.edges) { @@ -230,7 +231,7 @@ describe('positions', { tags: '@regression', testIsolation: true }, () => { deltaX: 500, }); // 7004-POSI-004 - cy.get('[col-id="updatedAt"]').should('be.visible'); + cy.get('[col-id="unrealisedPNL"]').should('be.visible'); }); it('Drag and drop columns', () => { diff --git a/apps/trading-e2e/src/integration/trading-trades.cy.ts b/apps/trading-e2e/src/integration/trading-trades.cy.ts index 016abd48a..50ad89f99 100644 --- a/apps/trading-e2e/src/integration/trading-trades.cy.ts +++ b/apps/trading-e2e/src/integration/trading-trades.cy.ts @@ -59,8 +59,7 @@ describe('trades', { tags: '@smoke' }, () => { cy.getByTestId(tradesTable) // order table shares identical col id .find(`${colIdCreatedAt} ${colHeader}`) .should('have.text', 'Created at'); - const dateTimeRegex = - /(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm; + const dateTimeRegex = /(\d{1,2}):(\d{1,2}):(\d{1,2})/gm; cy.getByTestId(tradesTable) .get(`.ag-center-cols-container ${colIdCreatedAt}`) .each(($tradeDateTime) => { @@ -87,6 +86,7 @@ describe('trades', { tags: '@smoke' }, () => { }); it('copy price to deal ticket form', () => { + cy.getByTestId('Order').click(); // 6005-THIS-007 cy.get(colIdPrice).last().should('be.visible').click(); cy.getByTestId('order-price').should('have.value', '171.16898'); diff --git a/apps/trading/client-pages/market/trade-views.tsx b/apps/trading/client-pages/market/trade-views.tsx index 7d81da733..900f4226c 100644 --- a/apps/trading/client-pages/market/trade-views.tsx +++ b/apps/trading/client-pages/market/trade-views.tsx @@ -1,6 +1,5 @@ import type { ComponentProps } from 'react'; import { Splash } from '@vegaprotocol/ui-toolkit'; -import { TradesContainer } from '@vegaprotocol/trades'; import { DepthChartContainer } from '@vegaprotocol/market-depth'; import { CandlesChartContainer, @@ -8,6 +7,7 @@ import { } from '@vegaprotocol/candles-chart'; import { Filter, OpenOrdersMenu } from '@vegaprotocol/orders'; import { NO_MARKET } from './constants'; +import { TradesContainer } from '../../components/trades-container'; import { OrderbookContainer } from '../../components/orderbook-container'; import { FillsContainer } from '../../components/fills-container'; import { PositionsContainer } from '../../components/positions-container'; diff --git a/apps/trading/client-pages/markets/closed.tsx b/apps/trading/client-pages/markets/closed.tsx index 2b0603dea..f01d68b69 100644 --- a/apps/trading/client-pages/markets/closed.tsx +++ b/apps/trading/client-pages/markets/closed.tsx @@ -276,15 +276,9 @@ const ClosedMarketsDataGrid = ({ return ( data.id} - defaultColDef={{ - resizable: true, - minWidth: 100, - flex: 1, - }} components={{ SuccessorMarketRenderer }} overlayNoRowsTemplate={error ? error.message : t('No markets')} /> diff --git a/apps/trading/components/positions-container/positions-container.tsx b/apps/trading/components/positions-container/positions-container.tsx index 34d864e75..518f7c2d6 100644 --- a/apps/trading/components/positions-container/positions-container.tsx +++ b/apps/trading/components/positions-container/positions-container.tsx @@ -15,9 +15,7 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => { const gridStore = usePositionsStore((store) => store.gridStore); const updateGridStore = usePositionsStore((store) => store.updateGridStore); - const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => { - updateGridStore(colState); - }); + const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore); if (!pubKey) { return ( diff --git a/apps/trading/components/trades-container/index.ts b/apps/trading/components/trades-container/index.ts new file mode 100644 index 000000000..bdd817b39 --- /dev/null +++ b/apps/trading/components/trades-container/index.ts @@ -0,0 +1 @@ +export * from './trades-container'; diff --git a/apps/trading/components/trades-container/trades-container.tsx b/apps/trading/components/trades-container/trades-container.tsx new file mode 100644 index 000000000..b6c932491 --- /dev/null +++ b/apps/trading/components/trades-container/trades-container.tsx @@ -0,0 +1,24 @@ +import { TradesManager } from '@vegaprotocol/trades'; +import type { DataGridSlice } from '../../stores/datagrid-store-slice'; +import { createDataGridSlice } from '../../stores/datagrid-store-slice'; +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; +import { useDataGridEvents } from '@vegaprotocol/datagrid'; + +interface TradesContainerProps { + marketId: string; +} + +export const TradesContainer = ({ marketId }: TradesContainerProps) => { + const gridStore = useTradesStore((store) => store.gridStore); + const updateGridStore = useTradesStore((store) => store.updateGridStore); + const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore); + + return ; +}; + +const useTradesStore = create()( + persist(createDataGridSlice, { + name: 'vega_trades_store', + }) +); diff --git a/apps/trading/pages/styles.css b/apps/trading/pages/styles.css index 71120bf70..86e8eb7a3 100644 --- a/apps/trading/pages/styles.css +++ b/apps/trading/pages/styles.css @@ -142,12 +142,19 @@ html [data-theme='dark'] { border-width: 0; } +.vega-ag-grid .ag-cell .ag-cell-wrapper { + height: 100%; +} + .vega-ag-grid .ag-header-row { @apply font-alpha font-normal; } /* Light variables */ .ag-theme-balham { + --ag-grid-size: 2px; /* Used for compactness */ + --ag-row-height: 36px; + --ag-header-height: 36px; --ag-background-color: theme(colors.white); --ag-border-color: theme(colors.vega.clight.600); --ag-header-background-color: theme(colors.vega.clight.700); @@ -160,6 +167,9 @@ html [data-theme='dark'] { /* Dark variables */ .ag-theme-balham-dark { + --ag-grid-size: 2px; /* Used for compactness */ + --ag-row-height: 36px; + --ag-header-height: 36px; --ag-background-color: theme(colors.vega.cdark.900); --ag-border-color: theme(colors.vega.cdark.600); --ag-header-background-color: theme(colors.vega.cdark.700); diff --git a/libs/accounts/src/lib/accounts-table.tsx b/libs/accounts/src/lib/accounts-table.tsx index 5d616bed6..847868230 100644 --- a/libs/accounts/src/lib/accounts-table.tsx +++ b/libs/accounts/src/lib/accounts-table.tsx @@ -58,6 +58,12 @@ export const accountValuesComparator = ( return valueA > valueB ? 1 : -1; }; +const defaultColDef = { + resizable: true, + sortable: true, + tooltipComponent: TooltipCellComponent, + comparator: accountValuesComparator, +}; export interface GetRowsParams extends Omit { successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void; } @@ -306,16 +312,10 @@ export const AccountTable = ({ return ( data.asset.id} tooltipShowDelay={500} rowData={data} - defaultColDef={{ - resizable: true, - tooltipComponent: TooltipCellComponent, - sortable: true, - comparator: accountValuesComparator, - }} + defaultColDef={defaultColDef} columnDefs={colDefs} getRowHeight={getPinnedAssetRowHeight} pinnedTopRowData={pinnedRow ? [pinnedRow] : undefined} diff --git a/libs/accounts/src/lib/breakdown-table.tsx b/libs/accounts/src/lib/breakdown-table.tsx index 1eb0e9f19..e3546f296 100644 --- a/libs/accounts/src/lib/breakdown-table.tsx +++ b/libs/accounts/src/lib/breakdown-table.tsx @@ -20,6 +20,10 @@ import { MarginHealthChart } from './margin-health-chart'; import { MarketNameCell } from '@vegaprotocol/datagrid'; import { AccountType } from '@vegaprotocol/types'; +const defaultColDef = { + resizable: true, + sortable: true, +}; interface BreakdownTableProps extends AgGridReactProps { data: AccountFields[] | null; onMarketClick?: (marketId: string, metaKey?: boolean) => void; @@ -41,7 +45,6 @@ const BreakdownTable = forwardRef( if (!value) return 'None'; return value; }, - minWidth: 200, }, { headerName: t('Account type'), @@ -58,7 +61,6 @@ const BreakdownTable = forwardRef( { headerName: t('Balance'), field: 'used', - flex: 2, maxWidth: 500, type: 'rightAligned', tooltipComponent: TooltipCellComponent, @@ -97,7 +99,6 @@ const BreakdownTable = forwardRef( { headerName: t('Margin health'), field: 'market.id', - flex: 2, maxWidth: 500, sortable: false, cellRenderer: ({ @@ -118,7 +119,6 @@ const BreakdownTable = forwardRef( return ( @@ -128,11 +128,7 @@ const BreakdownTable = forwardRef( rowHeight={34} components={{ PriceCell, MarketNameCell, ProgressBarCell }} tooltipShowDelay={500} - defaultColDef={{ - flex: 1, - resizable: true, - sortable: true, - }} + defaultColDef={defaultColDef} columnDefs={coldefs} /> ); diff --git a/libs/datagrid/src/lib/ag-grid/ag-grid-lazy-themed.tsx b/libs/datagrid/src/lib/ag-grid/ag-grid-lazy-themed.tsx index 641e20fcf..269aa1c99 100644 --- a/libs/datagrid/src/lib/ag-grid/ag-grid-lazy-themed.tsx +++ b/libs/datagrid/src/lib/ag-grid/ag-grid-lazy-themed.tsx @@ -3,6 +3,20 @@ import { AgGridReact } from 'ag-grid-react'; import { useThemeSwitcher } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/i18n'; import classNames from 'classnames'; +import type { ColDef } from 'ag-grid-community'; + +const defaultProps: AgGridReactProps = { + enableCellTextSelection: true, + overlayLoadingTemplate: t('Loading...'), + overlayNoRowsTemplate: t('No data'), + suppressCellFocus: true, + suppressColumnMoveAnimation: true, +}; + +const defaultColDef: ColDef = { + resizable: true, + sortable: true, +}; export const AgGridThemed = ({ style, @@ -13,23 +27,20 @@ export const AgGridThemed = ({ gridRef?: React.ForwardedRef; }) => { const { theme } = useThemeSwitcher(); - const defaultProps = { - rowHeight: 22, - headerHeight: 22, - enableCellTextSelection: true, - overlayLoadingTemplate: t('Loading...'), - overlayNoRowsTemplate: t('No data'), - suppressCellFocus: true, - }; - const wrapperClasses = classNames('vega-ag-grid', { + const wrapperClasses = classNames('vega-ag-grid', 'w-full h-full', { 'ag-theme-balham': theme === 'light', 'ag-theme-balham-dark': theme === 'dark', }); return ( -
- +
+
); }; diff --git a/libs/datagrid/src/lib/cells/market-name-cell.tsx b/libs/datagrid/src/lib/cells/market-name-cell.tsx index e88c47275..1c2bc2b43 100644 --- a/libs/datagrid/src/lib/cells/market-name-cell.tsx +++ b/libs/datagrid/src/lib/cells/market-name-cell.tsx @@ -29,7 +29,11 @@ export const MarketNameCell = ({ ); if (!value || !data) return null; return onMarketClick ? ( - ) : ( diff --git a/libs/datagrid/src/lib/column-definitions.ts b/libs/datagrid/src/lib/column-definitions.ts index 038adcc59..216efc3d6 100644 --- a/libs/datagrid/src/lib/column-definitions.ts +++ b/libs/datagrid/src/lib/column-definitions.ts @@ -4,8 +4,8 @@ export const COL_DEFS = { sortable: false, resizable: false, filter: false, - minWidth: 45, - maxWidth: 45, + minWidth: 30, + maxWidth: 30, type: 'rightAligned', pinned: 'right' as const, }, diff --git a/libs/datagrid/src/lib/use-datagrid-events.spec.tsx b/libs/datagrid/src/lib/use-datagrid-events.spec.tsx index 073fc00f6..02504be2f 100644 --- a/libs/datagrid/src/lib/use-datagrid-events.spec.tsx +++ b/libs/datagrid/src/lib/use-datagrid-events.spec.tsx @@ -14,7 +14,6 @@ const gridProps = { { field: 'id', width: 100, - resizable: true, filter: 'agNumberColumnFilter', }, ], @@ -50,7 +49,7 @@ describe('useDataGridEvents', () => { console.warn = originalWarn; }); - it('default state is set and callback is called on column or filter event', async () => { + it('default state is set and callback is called on filter event', async () => { const callback = jest.fn(); const initialState = { filterModel: undefined, @@ -67,45 +66,6 @@ describe('useDataGridEvents', () => { // no filters set expect(result.current.api.getFilterModel()).toEqual({}); - const newWidth = 400; - - // Set col width - await act(async () => { - result.current.columnApi.setColumnWidth('id', newWidth); - }); - - act(() => { - jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME); - }); - - expect(callback).toHaveBeenCalledWith({ - columnState: [expect.objectContaining({ colId: 'id', width: newWidth })], - filterModel: {}, - }); - callback.mockClear(); - expect(result.current.columnApi.getColumnState()[0].width).toEqual( - newWidth - ); - - // Set filter - await act(async () => { - result.current.columnApi.applyColumnState({ - state: [{ colId: 'id', sort: 'asc' }], - applyOrder: true, - }); - }); - - act(() => { - jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME); - }); - - expect(callback).toHaveBeenCalledWith({ - columnState: [expect.objectContaining({ colId: 'id', sort: 'asc' })], - filterModel: {}, - }); - callback.mockClear(); - expect(result.current.columnApi.getColumnState()[0].sort).toEqual('asc'); - // Set filter const idFilter = { filter: 1, @@ -123,7 +83,7 @@ describe('useDataGridEvents', () => { }); expect(callback).toHaveBeenCalledWith({ - columnState: expect.any(Object), + columnState: undefined, filterModel: { id: idFilter, }, @@ -138,7 +98,7 @@ describe('useDataGridEvents', () => { filterType: 'number', type: 'equals', }; - const colState = { colId: 'id', width: 300, sort: 'desc' as const }; + const colState = { colId: 'id', sort: 'desc' as const }; const initialState = { filterModel: { id: idFilter, @@ -156,7 +116,7 @@ describe('useDataGridEvents', () => { }); }); - it('debounces events', async () => { + it('ignores events that were not made via the UI', async () => { const callback = jest.fn(); const initialState = { filterModel: undefined, @@ -170,8 +130,6 @@ describe('useDataGridEvents', () => { // Set col width multiple times await act(async () => { result.current.columnApi.setColumnWidth('id', newWidth); - result.current.columnApi.setColumnWidth('id', newWidth); - result.current.columnApi.setColumnWidth('id', newWidth); }); expect(callback).not.toHaveBeenCalled(); @@ -180,6 +138,6 @@ describe('useDataGridEvents', () => { jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME); }); - expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledTimes(0); }); }); diff --git a/libs/datagrid/src/lib/use-datagrid-events.ts b/libs/datagrid/src/lib/use-datagrid-events.ts index 305ab703b..23aaf68e1 100644 --- a/libs/datagrid/src/lib/use-datagrid-events.ts +++ b/libs/datagrid/src/lib/use-datagrid-events.ts @@ -1,12 +1,13 @@ -import debounce from 'lodash/debounce'; import type { + ColumnMovedEvent, ColumnResizedEvent, ColumnState, + ColumnVisibleEvent, FilterChangedEvent, - GridReadyEvent, + FirstDataRenderedEvent, SortChangedEvent, } from 'ag-grid-community'; -import { useCallback, useMemo } from 'react'; +import { useCallback } from 'react'; type State = { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -14,30 +15,70 @@ type State = { columnState?: ColumnState[]; }; -type Event = ColumnResizedEvent | FilterChangedEvent | SortChangedEvent; - -export const GRID_EVENT_DEBOUNCE_TIME = 300; - export const useDataGridEvents = ( state: State, callback: (data: State) => void ) => { - // This function can be called very frequently by the onColumnResized - // grid callback, so its memoized to only update after resizing is finished - const onGridChange = useMemo( - () => - debounce(({ api, columnApi }: Event) => { - if (!api || !columnApi) return; - const columnState = columnApi.getColumnState(); - const filterModel = api.getFilterModel(); - callback({ columnState, filterModel }); - }, GRID_EVENT_DEBOUNCE_TIME), + /** + * Callback for filter events + */ + const onFilterChanged = useCallback( + ({ api }: FilterChangedEvent) => { + if (!api) return; + const filterModel = api.getFilterModel(); + callback({ filterModel }); + }, [callback] ); - // check if we have stored column states or filter models and apply if we do + /** + * Callback for column resized and column moved events, which can be + * triggered in quick succession. Uses the finished flag to not call the + * store callback unnecessarily + */ + const onDebouncedColumnChange = useCallback( + ({ + columnApi, + source, + finished, + }: ColumnResizedEvent | ColumnMovedEvent) => { + if (!finished) return; + + // only call back on user interactions, and not events triggered from the api + const permittedEvents = [ + 'uiColumnResized', + 'uiColumnDragged', + 'uiColumnMoved', + ]; + + if (!permittedEvents.includes(source)) { + return; + } + + const columnState = columnApi.getColumnState(); + + callback({ columnState }); + }, + [callback] + ); + + /** + * Callback for sort and visible events + */ + const onColumnChange = useCallback( + ({ columnApi }: SortChangedEvent | ColumnVisibleEvent) => { + const columnState = columnApi.getColumnState(); + callback({ columnState }); + }, + [callback] + ); + + /** + * Callback for grid startup to apply stored column and filter states. + * State only applied if found, otherwise columns sized to fit available space + */ const onGridReady = useCallback( - ({ api, columnApi }: GridReadyEvent) => { + ({ api, columnApi }: FirstDataRenderedEvent) => { if (!api || !columnApi) return; if (state.columnState) { @@ -46,7 +87,6 @@ export const useDataGridEvents = ( applyOrder: true, }); } else { - // ensure columns fit available space if no widths are set api.sizeColumnsToFit(); } @@ -59,8 +99,12 @@ export const useDataGridEvents = ( return { onGridReady, - onColumnResized: onGridChange, - onFilterChanged: onGridChange, - onSortChanged: onGridChange, + // these events don't use the 'finished' flag + onFilterChanged, + onSortChanged: onColumnChange, + onColumnVisible: onColumnChange, + // these trigger a lot so this callback uses the 'finished' flag + onColumnMoved: onDebouncedColumnChange, + onColumnResized: onDebouncedColumnChange, }; }; diff --git a/libs/deposits/src/lib/deposits-table.tsx b/libs/deposits/src/lib/deposits-table.tsx index 43820a479..e7f77df02 100644 --- a/libs/deposits/src/lib/deposits-table.tsx +++ b/libs/deposits/src/lib/deposits-table.tsx @@ -70,17 +70,9 @@ export const DepositsTable = ( ); }, - flex: 1, }, ], [] ); - return ( - - ); + return ; }; diff --git a/libs/fills/src/lib/fills-table.tsx b/libs/fills/src/lib/fills-table.tsx index 9e48a1f51..65351ae48 100644 --- a/libs/fills/src/lib/fills-table.tsx +++ b/libs/fills/src/lib/fills-table.tsx @@ -124,8 +124,6 @@ export const FillsTable = forwardRef( ref={ref} columnDefs={columnDefs} overlayNoRowsTemplate={t('No fills')} - defaultColDef={{ resizable: true }} - style={{ width: '100%', height: '100%' }} getRowId={({ data }) => data?.id} tooltipShowDelay={0} tooltipHideDelay={2000} diff --git a/libs/ledger/src/lib/ledger-table.tsx b/libs/ledger/src/lib/ledger-table.tsx index 8628256e1..fbcd43532 100644 --- a/libs/ledger/src/lib/ledger-table.tsx +++ b/libs/ledger/src/lib/ledger-table.tsx @@ -42,6 +42,16 @@ const dateRangeFilterParams = { maxNextDays: 0, defaultValue, }; +const defaultColDef = { + resizable: true, + sortable: true, + tooltipComponent: TransferTooltipCellComponent, + filterParams: { + ...dateRangeFilterParams, + buttons: ['reset'], + }, +}; + type LedgerEntryProps = TypedDataAgGrid; export const LedgerTable = (props: LedgerEntryProps) => { @@ -177,24 +187,14 @@ export const LedgerTable = (props: LedgerEntryProps) => { value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-', filterParams: dateRangeFilterParams, filter: DateRangeFilter, - flex: 1, }, ], [] ); return ( diff --git a/libs/liquidity/src/lib/liquidity-table.tsx b/libs/liquidity/src/lib/liquidity-table.tsx index 1fa870d39..cd594ba0f 100644 --- a/libs/liquidity/src/lib/liquidity-table.tsx +++ b/libs/liquidity/src/lib/liquidity-table.tsx @@ -31,6 +31,12 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => { return getDateTimeFormat().format(new Date(value)); }; +const defaultColDef = { + resizable: true, + sortable: true, + tooltipComponent: TooltipCellComponent, +}; + export interface LiquidityTableProps extends TypedDataAgGrid { symbol?: string; @@ -124,7 +130,6 @@ export const LiquidityTable = ({ headerTooltip: t( 'The valuation of the market at the time the liquidity commitment was made. Commitments made at a lower valuation earlier in the lifetime of the market would be expected to have a higher equity-like share if the market has grown. If a commitment is amended, value will reflect the average of the market valuations across the lifetime of the commitment.' ), - minWidth: 160, valueFormatter: assetDecimalsQuantumFormatter, tooltipValueGetter: assetDecimalsFormatter, }, @@ -183,16 +188,10 @@ export const LiquidityTable = ({ return ( data.id || ''} tooltipShowDelay={500} - defaultColDef={{ - resizable: true, - minWidth: 100, - tooltipComponent: TooltipCellComponent, - sortable: true, - }} + defaultColDef={defaultColDef} {...props} columnDefs={colDefs} /> diff --git a/libs/markets/src/lib/components/markets-container/market-list-table.tsx b/libs/markets/src/lib/components/markets-container/market-list-table.tsx index 51d24e2bd..a16613077 100644 --- a/libs/markets/src/lib/components/markets-container/market-list-table.tsx +++ b/libs/markets/src/lib/components/markets-container/market-list-table.tsx @@ -35,11 +35,9 @@ const MarketName = (props: MarketNameCellProps) => ( ); const defaultColDef = { - resizable: true, sortable: true, filter: true, filterParams: { buttons: ['reset'] }, - minWidth: 100, }; type Props = TypedDataAgGrid & { onMarketClick: (marketId: string, metaKey?: boolean) => void; @@ -58,7 +56,6 @@ export const MarketListTable = ({ }; return ( { { headerName: t('Trading mode'), field: 'tradingMode', - minWidth: 170, valueFormatter: ({ data, }: VegaValueFormatterParams) => { diff --git a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx index 0a2600542..cf9a612ec 100644 --- a/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx +++ b/libs/orders/src/lib/components/order-list-manager/order-list-manager.tsx @@ -84,7 +84,6 @@ export const OrderListManager = ({ onMarketClick={onMarketClick} onOrderTypeClick={onOrderTypeClick} isReadOnly={isReadOnly} - suppressAutoSize overlayNoRowsTemplate={error ? error.message : t('No orders')} {...gridProps} /> 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 bc4bc4b8a..9786fefa5 100644 --- a/libs/orders/src/lib/components/order-list/order-list.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.tsx @@ -37,6 +37,12 @@ import type { Order } from '../order-data-provider'; import { Filter } from '../order-list-manager'; import type { ColDef } from 'ag-grid-community'; +const defaultColDef = { + resizable: true, + sortable: true, + filterParams: { buttons: ['reset'] }, +}; + export type OrderListTableProps = TypedDataAgGrid & { marketId?: string; onCancel: (order: Order) => void; @@ -76,7 +82,6 @@ export const OrderListTable = memo< field: 'market.tradableInstrument.instrument.code', cellRenderer: 'MarketNameCell', cellRendererParams: { idPath: 'market.id', onMarketClick }, - minWidth: 150, }, { headerName: t('Filled'), @@ -110,9 +115,6 @@ export const OrderListTable = memo< data.market.positionDecimalPlaces ?? 0 ); }, - minWidth: 50, - width: 90, - flex: 0, }, { headerName: t('Size'), @@ -154,9 +156,6 @@ export const OrderListTable = memo< ) ); }, - minWidth: 50, - width: 80, - flex: 0, }, { field: 'type', @@ -168,7 +167,6 @@ export const OrderListTable = memo< cellRendererParams: { onClick: onOrderTypeClick, }, - minWidth: 80, }, { field: 'status', @@ -201,7 +199,6 @@ export const OrderListTable = memo< {valueFormatted} ), - minWidth: 100, }, { field: 'price', @@ -223,7 +220,6 @@ export const OrderListTable = memo< } return addDecimalsFormatNumber(value, data.market.decimalPlaces); }, - minWidth: 100, }, { field: 'timeInForce', @@ -252,7 +248,6 @@ export const OrderListTable = memo< return label; }, - minWidth: 150, }, { field: 'updatedAt', @@ -272,13 +267,12 @@ export const OrderListTable = memo< ); }, - minWidth: 150, }, { colId: 'amend', ...COL_DEFS.actions, - minWidth: showAllActions ? 120 : COL_DEFS.actions.minWidth, - maxWidth: showAllActions ? 120 : COL_DEFS.actions.minWidth, + minWidth: showAllActions ? 110 : COL_DEFS.actions.minWidth, + maxWidth: showAllActions ? 110 : COL_DEFS.actions.minWidth, cellRenderer: ({ data }: { data?: Order }) => { if (!data) return null; @@ -336,16 +330,8 @@ export const OrderListTable = memo< return ( data.id} components={{ MarketNameCell, OrderTypeCell }} {...props} diff --git a/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx b/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx index 0b59cdba6..35698c16b 100644 --- a/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx +++ b/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx @@ -29,6 +29,12 @@ import type { AgGridReact } from 'ag-grid-react'; import type { StopOrder } from '../order-data-provider/stop-orders-data-provider'; import type { ColDef } from 'ag-grid-community'; +const defaultColDef = { + resizable: true, + sortable: true, + filterParams: { buttons: ['reset'] }, +}; + export type StopOrdersTableProps = TypedDataAgGrid & { onCancel: (order: StopOrder) => void; onMarketClick?: (marketId: string, metaKey?: boolean) => void; @@ -46,7 +52,6 @@ export const StopOrdersTable = memo< field: 'market.tradableInstrument.instrument.code', cellRenderer: 'MarketNameCell', cellRendererParams: { idPath: 'market.id', onMarketClick }, - minWidth: 150, }, { headerName: t('Trigger'), @@ -58,7 +63,6 @@ export const StopOrdersTable = memo< data, }: VegaValueFormatterParams): string => data ? formatTrigger(data, data.market.decimalPlaces) : '', - minWidth: 100, }, { field: 'expiresAt', @@ -82,7 +86,6 @@ export const StopOrdersTable = memo< } return ''; }, - minWidth: 150, }, { headerName: t('Size'), @@ -129,7 +132,6 @@ export const StopOrdersTable = memo< ) ); }, - minWidth: 80, }, { field: 'submission.type', @@ -141,7 +143,6 @@ export const StopOrdersTable = memo< value, }: VegaICellRendererParams) => value ? Schema.OrderTypeMapping[value] : '', - minWidth: 80, }, { field: 'status', @@ -163,7 +164,6 @@ export const StopOrdersTable = memo< }) => ( {valueFormatted} ), - minWidth: 100, }, { field: 'submission.price', @@ -185,7 +185,6 @@ export const StopOrdersTable = memo< } return addDecimalsFormatNumber(value, data.market.decimalPlaces); }, - minWidth: 100, }, { field: 'submission.timeInForce', @@ -198,7 +197,6 @@ export const StopOrdersTable = memo< }: VegaValueFormatterParams) => { return value ? Schema.OrderTimeInForceCode[value] : ''; }, - minWidth: 150, }, { field: 'updatedAt', @@ -218,7 +216,6 @@ export const StopOrdersTable = memo< ); }, - minWidth: 150, }, { colId: 'actions', @@ -249,16 +246,8 @@ export const StopOrdersTable = memo< return ( data.id} components={{ MarketNameCell }} {...props} diff --git a/libs/positions/src/lib/positions-manager.tsx b/libs/positions/src/lib/positions-manager.tsx index c0e5c5336..45c17f173 100644 --- a/libs/positions/src/lib/positions-manager.tsx +++ b/libs/positions/src/lib/positions-manager.tsx @@ -65,18 +65,16 @@ export const PositionsManager = ({ }); return ( -
- 1} - overlayNoRowsTemplate={error ? error.message : t('No positions')} - {...gridProps} - /> -
+ 1} + overlayNoRowsTemplate={error ? error.message : t('No positions')} + {...gridProps} + /> ); }; diff --git a/libs/positions/src/lib/positions-table.spec.tsx b/libs/positions/src/lib/positions-table.spec.tsx index 8234ea8d5..4bb657fd9 100644 --- a/libs/positions/src/lib/positions-table.spec.tsx +++ b/libs/positions/src/lib/positions-table.spec.tsx @@ -57,7 +57,7 @@ describe('Positions', () => { }); const headers = screen.getAllByRole('columnheader'); - expect(headers).toHaveLength(12); + expect(headers).toHaveLength(11); expect( headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim()) ).toEqual([ @@ -66,13 +66,12 @@ describe('Positions', () => { 'Open volume', 'Mark price', 'Liquidation price', - 'Settlement asset', + 'Asset', 'Entry price', 'Leverage', - 'Margin allocated', + 'Margin', 'Realised PNL', 'Unrealised PNL', - 'Updated', ]); }); @@ -212,7 +211,7 @@ describe('Positions', () => { ); }); const cells = screen.getAllByRole('gridcell'); - expect(cells[12].textContent).toEqual('Close'); + expect(cells[11].textContent).toEqual('Close'); }); it('do not display close button if openVolume is zero', async () => { @@ -228,7 +227,7 @@ describe('Positions', () => { ); }); const cells = screen.getAllByRole('gridcell'); - expect(cells[12].textContent).toEqual(''); + expect(cells[11].textContent).toEqual(''); }); describe('PNLCell', () => { diff --git a/libs/positions/src/lib/positions-table.tsx b/libs/positions/src/lib/positions-table.tsx index 28e80e2e6..d9da7a083 100644 --- a/libs/positions/src/lib/positions-table.tsx +++ b/libs/positions/src/lib/positions-table.tsx @@ -12,7 +12,6 @@ import { COL_DEFS } from '@vegaprotocol/datagrid'; import { ProgressBarCell } from '@vegaprotocol/datagrid'; import { AgGridLazy as AgGrid, - DateRangeFilter, PriceFlashCell, signedNumberCssClass, signedNumberCssClassRules, @@ -29,7 +28,6 @@ import { volumePrefix, toBigNum, formatNumber, - getDateTimeFormat, addDecimalsFormatNumber, } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; @@ -86,6 +84,14 @@ AmountCell.displayName = 'AmountCell'; export const getRowId = ({ data }: { data: Position }) => `${data.partyId}-${data.marketId}`; +const defaultColDef = { + sortable: true, + filter: true, + filterParams: { buttons: ['reset'] }, + tooltipComponent: TooltipCellComponent, + resizable: true, +}; + export const PositionsTable = ({ onClose, onMarketClick, @@ -98,24 +104,16 @@ export const PositionsTable = ({ const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore(); return ( (() => { const columnDefs: (ColDef | null)[] = [ multipleKeys @@ -128,7 +126,6 @@ export const PositionsTable = ({ pubKeys.find((key) => key.publicKey === data.partyId) ?.name) || data?.partyId, - minWidth: 190, } : null, { @@ -136,7 +133,6 @@ export const PositionsTable = ({ field: 'marketName', cellRenderer: 'MarketNameCell', cellRendererParams: { idPath: 'marketId', onMarketClick }, - minWidth: 190, }, { headerName: t('Notional'), @@ -160,7 +156,6 @@ export const PositionsTable = ({ data.marketDecimalPlaces ); }, - minWidth: 80, }, { headerName: t('Open volume'), @@ -190,7 +185,6 @@ export const PositionsTable = ({ ); }, cellRenderer: OpenVolumeCell, - minWidth: 100, }, { headerName: t('Mark price'), @@ -224,12 +218,12 @@ export const PositionsTable = ({ data.marketDecimalPlaces ); }, - minWidth: 100, }, { headerName: t('Liquidation price'), colId: 'liquidationPrice', type: 'rightAligned', + cellClass: 'font-mono text-right', cellRenderer: ({ data }: VegaICellRendererParams) => { if (!data) return null; return ( @@ -244,10 +238,9 @@ export const PositionsTable = ({ }, }, { - headerName: t('Settlement asset'), + headerName: t('Asset'), field: 'assetSymbol', colId: 'asset', - minWidth: 100, cellRenderer: ({ data }: VegaICellRendererParams) => { if (!data) return null; return ( @@ -293,7 +286,6 @@ export const PositionsTable = ({ data.marketDecimalPlaces ); }, - minWidth: 100, }, multipleKeys ? null @@ -307,12 +299,11 @@ export const PositionsTable = ({ value, }: VegaValueFormatterParams) => value === undefined ? '' : formatNumber(value.toString(), 1), - minWidth: 100, }, multipleKeys ? null : { - headerName: t('Margin allocated'), + headerName: t('Margin'), field: 'marginAccountBalance', type: 'rightAligned', filter: 'agNumberColumnFilter', @@ -339,7 +330,6 @@ export const PositionsTable = ({ data.decimals ); }, - minWidth: 100, }, { headerName: t('Realised PNL'), @@ -364,7 +354,6 @@ export const PositionsTable = ({ 'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.' ), cellRenderer: PNLCell, - minWidth: 100, }, { headerName: t('Unrealised PNL'), @@ -388,22 +377,6 @@ export const PositionsTable = ({ 'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.' ), cellRenderer: PNLCell, - minWidth: 100, - }, - { - headerName: t('Updated'), - field: 'updatedAt', - type: 'rightAligned', - filter: DateRangeFilter, - valueFormatter: ({ - value, - }: VegaValueFormatterParams) => { - if (!value) { - return ''; - } - return getDateTimeFormat().format(new Date(value)); - }, - minWidth: 150, }, onClose && !isReadOnly ? { @@ -427,8 +400,8 @@ export const PositionsTable = ({
); }, - minWidth: 90, - maxWidth: 90, + minWidth: 75, + maxWidth: 75, } : null, ]; @@ -444,6 +417,7 @@ export const PositionsTable = ({ pubKey, pubKeys, ])} + {...props} /> ); }; diff --git a/libs/proposals/src/components/proposals-list/proposals-list.tsx b/libs/proposals/src/components/proposals-list/proposals-list.tsx index fec75c5b4..0d1c9bc2c 100644 --- a/libs/proposals/src/components/proposals-list/proposals-list.tsx +++ b/libs/proposals/src/components/proposals-list/proposals-list.tsx @@ -42,7 +42,6 @@ export const ProposalsList = ({ rowData={filteredData} defaultColDef={defaultColDef} getRowId={({ data }) => data.id} - style={{ width: '100%', height: '100%' }} overlayNoRowsTemplate={t('No markets')} components={{ SuccessorMarketRenderer }} /> diff --git a/libs/proposals/src/components/proposals-list/use-column-defs.tsx b/libs/proposals/src/components/proposals-list/use-column-defs.tsx index c04eb5e50..620b03ac0 100644 --- a/libs/proposals/src/components/proposals-list/use-column-defs.tsx +++ b/libs/proposals/src/components/proposals-list/use-column-defs.tsx @@ -42,7 +42,6 @@ export const useColumnDefs = () => { colId: 'market', headerName: t('Market'), field: 'terms.change.instrument.code', - minWidth: 150, cellStyle: { lineHeight: '14px' }, cellRenderer: ({ data, @@ -144,7 +143,6 @@ export const useColumnDefs = () => { 'terms.enactmentDatetime' >) => (value ? getDateTimeFormat().format(new Date(value)) : '-'), filter: DateRangeFilter, - flex: 1, }, { colId: 'proposal-actions', @@ -155,7 +153,6 @@ export const useColumnDefs = () => { if (!data?.id) return null; return ; }, - flex: 1, }, ]); }, [VEGA_TOKEN_URL, requiredMajorityPercentage]); @@ -163,10 +160,8 @@ export const useColumnDefs = () => { const defaultColDef: ColDef = useMemo(() => { return { sortable: true, - resizable: true, filter: true, filterParams: { buttons: ['reset'] }, - minWidth: 100, }; }, []); diff --git a/libs/trades/src/index.ts b/libs/trades/src/index.ts index f0dcfa278..01643bdff 100644 --- a/libs/trades/src/index.ts +++ b/libs/trades/src/index.ts @@ -1,2 +1,2 @@ -export * from './lib/trades-container'; +export * from './lib/trades-manager'; export * from './lib/__generated__/Trades'; diff --git a/libs/trades/src/lib/trades-container.tsx b/libs/trades/src/lib/trades-manager.tsx similarity index 76% rename from libs/trades/src/lib/trades-container.tsx rename to libs/trades/src/lib/trades-manager.tsx index be6599727..2509d8045 100644 --- a/libs/trades/src/lib/trades-container.tsx +++ b/libs/trades/src/lib/trades-manager.tsx @@ -3,12 +3,17 @@ import { tradesWithMarketProvider } from './trades-data-provider'; import { TradesTable } from './trades-table'; import { useDealTicketFormValues } from '@vegaprotocol/deal-ticket'; import { t } from '@vegaprotocol/i18n'; +import type { useDataGridEvents } from '@vegaprotocol/datagrid'; interface TradesContainerProps { marketId: string; + gridProps?: ReturnType; } -export const TradesContainer = ({ marketId }: TradesContainerProps) => { +export const TradesManager = ({ + marketId, + gridProps, +}: TradesContainerProps) => { const update = useDealTicketFormValues((state) => state.updateAll); const { data, error } = useDataProvider({ @@ -23,6 +28,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => { update(marketId, { price }); }} overlayNoRowsTemplate={error ? error.message : t('No trades')} + {...gridProps} /> ); }; diff --git a/libs/trades/src/lib/trades-table.spec.tsx b/libs/trades/src/lib/trades-table.spec.tsx index 60380db6a..0f67491d6 100644 --- a/libs/trades/src/lib/trades-table.spec.tsx +++ b/libs/trades/src/lib/trades-table.spec.tsx @@ -1,5 +1,5 @@ import { act, render, screen } from '@testing-library/react'; -import { getDateTimeFormat } from '@vegaprotocol/utils'; +import { getTimeFormat } from '@vegaprotocol/utils'; import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table'; import type { Trade } from './trades-data-provider'; import { Side } from '@vegaprotocol/types'; @@ -39,7 +39,7 @@ describe('TradesTable', () => { const expectedValues = [ '1,111,222.00', '20.00', - getDateTimeFormat().format(new Date(trade.createdAt)), + getTimeFormat().format(new Date(trade.createdAt)), ]; cells.forEach((cell, i) => { expect(cell).toHaveTextContent(expectedValues[i]); diff --git a/libs/trades/src/lib/trades-table.tsx b/libs/trades/src/lib/trades-table.tsx index 67e965a4a..66c271738 100644 --- a/libs/trades/src/lib/trades-table.tsx +++ b/libs/trades/src/lib/trades-table.tsx @@ -8,7 +8,7 @@ import { AgGridLazy as AgGrid, NumericCell } from '@vegaprotocol/datagrid'; import { addDecimal, addDecimalsFormatNumber, - getDateTimeFormat, + getTimeFormat, } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import type { IDatasource, IGetRowsParams } from 'ag-grid-community'; @@ -53,7 +53,6 @@ export const TradesTable = ({ onClick, ...props }: Props) => { headerName: t('Price'), field: 'price', type: 'rightAligned', - width: 130, cellClass: changeCellClass, valueFormatter: ({ value, @@ -87,7 +86,6 @@ export const TradesTable = ({ onClick, ...props }: Props) => { { headerName: t('Size'), field: 'size', - width: 125, type: 'rightAligned', valueFormatter: ({ value, @@ -107,12 +105,12 @@ export const TradesTable = ({ onClick, ...props }: Props) => { headerName: t('Created at'), field: 'createdAt', type: 'rightAligned', - width: 170, cellClass: 'text-right', + flex: 1, // make created at always fill remaining space valueFormatter: ({ value, }: VegaValueFormatterParams) => { - return value && getDateTimeFormat().format(new Date(value)); + return value && getTimeFormat().format(new Date(value)); }, }, ], @@ -120,12 +118,9 @@ export const TradesTable = ({ onClick, ...props }: Props) => { ); return ( data.id} - defaultColDef={{ - flex: 1, - }} columnDefs={columnDefs} + rowHeight={22} {...props} /> ); diff --git a/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx b/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx index 474ed8526..fd73c6e38 100644 --- a/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx +++ b/libs/ui-toolkit/src/components/trading-dropdown/actions-dropdown.tsx @@ -7,10 +7,7 @@ import { export const ActionsDropdownTrigger = () => { return ( - + diff --git a/libs/withdraws/src/lib/withdrawals-table.tsx b/libs/withdraws/src/lib/withdrawals-table.tsx index 8b22e6164..e4992c9b4 100644 --- a/libs/withdraws/src/lib/withdrawals-table.tsx +++ b/libs/withdraws/src/lib/withdrawals-table.tsx @@ -115,7 +115,6 @@ export const WithdrawalsTable = ({ { headerName: t('Transaction'), field: 'txHash', - flex: 2, type: 'rightAligned', cellRendererParams: { complete: (withdrawal: WithdrawalFieldsFragment) => { @@ -135,8 +134,6 @@ export const WithdrawalsTable = ({