feat(2033): reorganise token site (#2313)
* chore: make proposals the home page, redirect home to proposals * chore: reorganise the remainder of the routes * chore: small styling bug * fix: nav links highlighted incorrectly * feat: rename title, rename routes to new structure, add redirects * chore: make navbar full width * feat: new navbar bases on trading navbar * chore: revert change to the width of the page * chore: make navbar reactive and support draw * chore: move draw into its' own file * chore: move nav into toolkit * style: lint * chore: trading to use navbar * fix: uppercase navbar title * chore: add test * fix: merge issue * style: lint * test: adjust test URLs * test: more route adjsuting * test: fix route name * test: change URL to be new url * test: more path corrections * test: more path fixes * style: lint * test: minor test fixes * test: more test fixes * test: fix incorrect paths * test: green build plz * chore: adjust name as per PR comments * test: fix path * test: fix incorrect path * test: final test fix * test: plz green
This commit is contained in:
parent
7c15ee6c01
commit
3486244137
@ -52,7 +52,6 @@ context(
|
||||
function () {
|
||||
before('connect wallets and set approval limit', function () {
|
||||
cy.visit('/');
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
cy.wrap(
|
||||
network_parameters['spam.protection.proposal.min.tokens'] /
|
||||
@ -132,7 +131,7 @@ context(
|
||||
cy.wait_for_spinner();
|
||||
cy.connectVegaWallet();
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
});
|
||||
|
||||
@ -207,7 +206,7 @@ context(
|
||||
|
||||
let arrayOfProposals = [];
|
||||
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
cy.get(proposalDetailsTitle)
|
||||
.each((proposalTitleElement) => {
|
||||
@ -223,16 +222,16 @@ context(
|
||||
|
||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated('2');
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', '2');
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
cy.wait_for_spinner();
|
||||
cy.click_on_validator_from_list(0);
|
||||
cy.staking_validator_page_add_stake('2');
|
||||
|
||||
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
|
||||
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50', generateProposalTitle());
|
||||
@ -320,14 +319,14 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
tokensRequiredToAchieveResult
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.get('@submittedProposal').within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
cy.get_proposal_information_from_table('Participation met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
cy.get('@submittedProposal').within(() =>
|
||||
cy.get(voteStatus).should('have.text', 'Participation met')
|
||||
@ -378,7 +377,7 @@ context(
|
||||
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
cy.get_submitted_proposal_from_proposal_list(proposalTitle).within(
|
||||
() => cy.get(viewProposalButton).click()
|
||||
@ -523,7 +522,7 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
tokensRequiredToAchieveResult
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.get('@submittedProposal').within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
@ -611,7 +610,7 @@ context(
|
||||
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
cy.get(rejectProposalsLink).click().wait_for_spinner();
|
||||
cy.get('@rawProposal').then((rawProposal) => {
|
||||
@ -808,7 +807,7 @@ context(
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
|
||||
@ -820,7 +819,7 @@ context(
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.get(proposalDetailsTitle).invoke('text').as('proposalTitle');
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@ context(
|
||||
function () {
|
||||
before('connect wallets and set approval limit', function () {
|
||||
cy.visit('/');
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
});
|
||||
|
||||
@ -50,7 +49,7 @@ context(
|
||||
cy.wait_for_spinner();
|
||||
cy.connectVegaWallet();
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
});
|
||||
|
||||
@ -74,7 +73,7 @@ context(
|
||||
});
|
||||
|
||||
it('Unable to submit network parameter with missing/invalid fields', function () {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.get(inputError).should('have.length', 3);
|
||||
@ -99,7 +98,7 @@ context(
|
||||
});
|
||||
|
||||
it('Unable to submit network parameter proposal with vote deadline above enactment deadline', function () {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER);
|
||||
cy.get(newProposalTitle).type('Test update network parameter proposal');
|
||||
cy.get(newProposalDescription).type('invalid deadlines');
|
||||
|
@ -33,7 +33,6 @@ context(
|
||||
// 2001-STKE-002, 2001-STKE-032
|
||||
before('visit staking tab and connect vega wallet', function () {
|
||||
cy.visit('/');
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
});
|
||||
|
||||
@ -46,7 +45,7 @@ context(
|
||||
cy.connectVegaWallet();
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.vega_wallet_teardown();
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
);
|
||||
@ -95,7 +94,7 @@ context(
|
||||
.contains(2.0, epochTimeout)
|
||||
.should('be.visible');
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%');
|
||||
});
|
||||
@ -142,14 +141,14 @@ context(
|
||||
.contains(2.0, epochTimeout)
|
||||
.should('be.visible');
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%');
|
||||
});
|
||||
|
||||
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
|
||||
cy.staking_page_associate_tokens('3', { type: 'contract' });
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
cy.staking_page_associate_tokens('4', { type: 'wallet' });
|
||||
|
||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
|
||||
@ -202,7 +201,7 @@ context(
|
||||
.contains(6.0, epochTimeout)
|
||||
.should('be.visible');
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '6.00', '100%');
|
||||
});
|
||||
@ -232,7 +231,7 @@ context(
|
||||
.parent()
|
||||
.should('contain', 2.0, txTimeout);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.click_on_validator_from_list(1);
|
||||
|
||||
@ -253,7 +252,7 @@ context(
|
||||
.eq(1)
|
||||
.should('contain', 1.0, txTimeout);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
cy.wait_for_spinner();
|
||||
|
||||
cy.get(`[row-id="${0}"]`).within(() => {
|
||||
@ -310,7 +309,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
// 2001-STKE-040
|
||||
cy.click_on_validator_from_list(0);
|
||||
|
||||
@ -343,7 +342,7 @@ context(
|
||||
cy.get(totalStake, epochTimeout).should('contain.text', '2');
|
||||
cy.get(stakeShare, epochTimeout).should('have.text', '100%');
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%');
|
||||
});
|
||||
@ -370,7 +369,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.click_on_validator_from_list('0');
|
||||
|
||||
@ -399,7 +398,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%');
|
||||
});
|
||||
@ -429,7 +428,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.click_on_validator_from_list(0);
|
||||
|
||||
@ -470,7 +469,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.click_on_validator_from_list(0);
|
||||
|
||||
@ -536,7 +535,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%');
|
||||
});
|
||||
@ -590,7 +589,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '0.00', '0%');
|
||||
});
|
||||
@ -637,7 +636,7 @@ context(
|
||||
.should('contain', 2.0, txTimeout)
|
||||
.and('contain', partValidatorId);
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.validate_validator_list_total_stake_and_share('0', '2.00', '100%');
|
||||
});
|
||||
|
@ -7,11 +7,11 @@ const vegaWalletUnstakedBalance =
|
||||
'[data-testid="vega-wallet-balance-unstaked"]';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
|
||||
const ethWalletAssociateButton = '[href="/staking/associate"]';
|
||||
const ethWalletAssociateButton = '[href="/validators/associate"]';
|
||||
const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]';
|
||||
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
|
||||
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||
const ethWalletDissociateButton = '[href="/staking/disassociate"]';
|
||||
const ethWalletDissociateButton = '[href="/validators/disassociate"]';
|
||||
const vestingContractSection = '[data-testid="vega-in-vesting-contract"]';
|
||||
const vegaInWalletSection = '[data-testid="vega-in-wallet"]';
|
||||
const connectedVegaKey = '[data-testid="connected-vega-key"]';
|
||||
@ -27,7 +27,6 @@ context(
|
||||
function () {
|
||||
before('visit staking tab and connect vega wallet', function () {
|
||||
cy.visit('/');
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
});
|
||||
|
||||
@ -40,7 +39,7 @@ context(
|
||||
cy.connectVegaWallet();
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.vega_wallet_teardown();
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
);
|
||||
@ -257,7 +256,7 @@ context(
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52);
|
||||
});
|
||||
|
||||
cy.navigate_to('staking');
|
||||
cy.navigate_to('validators');
|
||||
|
||||
cy.staking_page_disassociate_tokens('9', { type: 'wallet' });
|
||||
cy.get(vegaInWalletSection).within(() => {
|
||||
|
@ -33,7 +33,7 @@ context(
|
||||
beforeEach('Navigate to withdrawal page', function () {
|
||||
cy.reload();
|
||||
cy.visit('/');
|
||||
cy.navigate_to('withdrawals');
|
||||
cy.navigate_to('withdraw');
|
||||
cy.wait_for_spinner();
|
||||
cy.connectVegaWallet();
|
||||
cy.ethereum_wallet_connect();
|
||||
|
@ -9,12 +9,12 @@ context(
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
before('navigate to governance page', function () {
|
||||
cy.visit('/').navigate_to('governance');
|
||||
cy.visit('/').navigate_to('proposals');
|
||||
});
|
||||
|
||||
describe('with no network change proposals', function () {
|
||||
it('should have governance tab highlighted', function () {
|
||||
cy.verify_tab_highlighted('governance');
|
||||
cy.verify_tab_highlighted('proposals');
|
||||
});
|
||||
|
||||
it('should have GOVERNANCE header visible', function () {
|
||||
@ -49,7 +49,7 @@ context(
|
||||
.should('be.visible')
|
||||
.and('have.text', 'New proposal')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', '/governance/propose');
|
||||
.and('equal', '/proposals/propose');
|
||||
});
|
||||
|
||||
// Skipping this test for now, the new proposal button no longer takes a user directly
|
||||
@ -60,7 +60,7 @@ context(
|
||||
cy.get(connectToVegaWalletButton)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Connect Vega wallet');
|
||||
cy.navigate_to('governance');
|
||||
cy.navigate_to('proposals');
|
||||
cy.wait_for_spinner();
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,10 @@
|
||||
const navSection = 'nav';
|
||||
const navHome = '[href="/"]';
|
||||
const navVesting = '[href="/vesting"]';
|
||||
const navStaking = '[href="/staking"]';
|
||||
const navVesting = '[href="/token/tranches"]';
|
||||
const navToken = '[href="/token"]';
|
||||
const navStaking = '[href="/validators"]';
|
||||
const navRewards = '[href="/rewards"]';
|
||||
const navWithdraw = '[href="/withdrawals"]';
|
||||
const navGovernance = '[href="/governance"]';
|
||||
const navWithdraw = '[href="/token/withdraw"]';
|
||||
const navGovernance = '[href="/proposals"]';
|
||||
|
||||
const tokenDetailsTable = '.token-details';
|
||||
const address = '[data-testid="token-address"]';
|
||||
@ -25,7 +25,7 @@ const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
|
||||
|
||||
context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
cy.visit('/token');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
@ -34,9 +34,9 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
});
|
||||
|
||||
describe('Navigation tabs', function () {
|
||||
it('should have HOME tab', function () {
|
||||
it('should have TOKEN tab', function () {
|
||||
cy.get(navSection).within(() => {
|
||||
cy.get(navHome).should('be.visible');
|
||||
cy.get(navToken).should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have VESTING tab', function () {
|
||||
@ -106,14 +106,14 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
cy.get(tranchesLink)
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', '/tranches');
|
||||
.and('equal', '/token/tranches');
|
||||
});
|
||||
it('should have REDEEM button', function () {
|
||||
cy.get(redeemBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', '/vesting');
|
||||
.and('equal', '/token/redeem');
|
||||
});
|
||||
it('should have GET VEGA WALLET link', function () {
|
||||
cy.get(getVegaWalletLink)
|
||||
@ -125,21 +125,21 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
cy.get(associateVegaLink)
|
||||
.should('be.visible')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', '/staking/associate');
|
||||
.and('equal', '/validators/associate');
|
||||
});
|
||||
it('should have STAKING button', function () {
|
||||
cy.get(stakingBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', '/staking');
|
||||
.and('equal', '/validators');
|
||||
});
|
||||
it('should have GOVERNANCE button', function () {
|
||||
cy.get(governanceBtn)
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.should('have.attr', 'href')
|
||||
.and('equal', '/governance');
|
||||
.and('equal', '/proposals');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -15,13 +15,13 @@ const stakeNumberRegex = /^\d*\.?\d*$/;
|
||||
|
||||
context('Staking Page - verify elements on page', function () {
|
||||
before('navigate to staking page', function () {
|
||||
cy.visit('/').navigate_to('staking');
|
||||
cy.visit('/').navigate_to('validators');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||
describe('description section', function () {
|
||||
it('Should have staking tab highlighted', function () {
|
||||
cy.verify_tab_highlighted('staking');
|
||||
cy.verify_tab_highlighted('validators');
|
||||
});
|
||||
|
||||
it('Should have STAKING ON VEGA header visible', function () {
|
||||
|
@ -5,11 +5,10 @@ context(
|
||||
'Vesting Page - verify elements on page',
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
before('navigate to vesting page', function () {
|
||||
cy.visit('/').navigate_to('vesting');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
before('navigate to vesting page', function () {
|
||||
cy.visit('/').navigate_to('vesting');
|
||||
});
|
||||
it('should have vesting tab highlighted', function () {
|
||||
cy.verify_tab_highlighted('vesting');
|
||||
});
|
||||
@ -32,15 +31,16 @@ context(
|
||||
describe('with eth wallet connected', function () {
|
||||
before('connect eth wallet', function () {
|
||||
cy.ethereum_wallet_connect();
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
// 1005-VEST-001
|
||||
// 1005-VEST-002
|
||||
it('Able to view tranches', function () {
|
||||
cy.get('[href="/tranches"]')
|
||||
.should('have.text', 'all tranches')
|
||||
cy.get('[href="/token/tranches"]')
|
||||
.should('have.text', 'Supply & Vesting')
|
||||
.click();
|
||||
cy.url().should('include', '/tranches');
|
||||
cy.url().should('include', '/token/tranches');
|
||||
cy.get('h1').should('contain.text', 'Vesting tranches');
|
||||
});
|
||||
});
|
||||
|
@ -2,8 +2,8 @@ const walletContainer = '[data-testid="ethereum-wallet"]';
|
||||
const walletHeader = '[data-testid="wallet-header"] h1';
|
||||
const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]';
|
||||
const connectorList = '[data-testid="web3-connector-list"]';
|
||||
const associate = '[href="/staking/associate"]';
|
||||
const disassociate = '[href="/staking/disassociate"]';
|
||||
const associate = '[href="/validators/associate"]';
|
||||
const disassociate = '[href="/validators/disassociate"]';
|
||||
const disconnect = '[data-testid="disconnect-from-eth-wallet-button"]';
|
||||
const accountNo = '[data-testid="ethereum-account-truncated"]';
|
||||
const currencyTitle = '[data-testid="currency-title"]';
|
||||
|
@ -18,8 +18,8 @@ const walletName = '[data-testid="wallet-name"]';
|
||||
const currencyTitle = '[data-testid="currency-title"]';
|
||||
const currencyValue = '[data-testid="currency-value"]';
|
||||
const vegaUnstaked = '[data-testid="vega-wallet-balance-unstaked"] .text-right';
|
||||
const governanceBtn = '[href="/governance"]';
|
||||
const stakingBtn = '[href="/staking"]';
|
||||
const governanceBtn = '[href="/proposals"]';
|
||||
const stakingBtn = '[href="/validators"]';
|
||||
const manageLink = '[data-testid="manage-vega-wallet"]';
|
||||
const dialogVegaKey = '[data-testid="vega-public-key-full"]';
|
||||
const dialogDisconnectBtn = '[data-testid="disconnect"]';
|
||||
|
@ -5,12 +5,12 @@ context(
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
before('navigate to withdrawals page', function () {
|
||||
cy.visit('/').navigate_to('withdrawals');
|
||||
cy.visit('/').navigate_to('withdraw');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
it('should have withdraw tab highlighted', function () {
|
||||
cy.verify_tab_highlighted('withdrawals');
|
||||
cy.verify_tab_highlighted('withdraw');
|
||||
});
|
||||
|
||||
it('should have WITHDRAW header visible', function () {
|
||||
|
@ -8,13 +8,13 @@ Cypress.Commands.add(
|
||||
|
||||
const navigation = {
|
||||
section: 'nav',
|
||||
home: '[href="/"]',
|
||||
vesting: '[href="/vesting"]',
|
||||
staking: '[href="/staking"]',
|
||||
vesting: '[href="/token/redeem"]',
|
||||
validators: '[href="/validators"]',
|
||||
rewards: '[href="/rewards"]',
|
||||
withdrawals: '[href="/withdrawals"]',
|
||||
governance: '[href="/governance"]',
|
||||
withdraw: '[href="/token/withdraw"]',
|
||||
proposals: '[href="/proposals"]',
|
||||
pageSpinner: '[data-testid="splash-loader"]',
|
||||
token: '[href="/token"]',
|
||||
};
|
||||
|
||||
Cypress.Commands.add('navigate_to', (page) => {
|
||||
|
@ -172,9 +172,9 @@ Cypress.Commands.add('get_sort_order_of_supplied_array', (suppliedArray) => {
|
||||
});
|
||||
|
||||
Cypress.Commands.add('go_to_make_new_proposal', (proposalType) => {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.navigate_to_page_if_not_already_loaded('proposals');
|
||||
cy.get(newProposalButton).should('be.visible').click();
|
||||
cy.url().should('include', '/governance/propose');
|
||||
cy.url().should('include', '/proposals/propose');
|
||||
cy.wait_for_spinner();
|
||||
cy.get('li').contains(proposalType).click();
|
||||
});
|
||||
|
@ -3,8 +3,8 @@ const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||
const tokenInputApprove = '[data-testid="token-input-approve-button"]';
|
||||
const addStakeRadioButton = '[data-testid="add-stake-radio"]';
|
||||
const removeStakeRadioButton = '[data-testid="remove-stake-radio"]';
|
||||
const ethWalletAssociateButton = '[href="/staking/associate"]';
|
||||
const ethWalletDissociateButton = '[href="/staking/disassociate"]';
|
||||
const ethWalletAssociateButton = '[href="/validators/associate"]';
|
||||
const ethWalletDissociateButton = '[href="/validators/disassociate"]';
|
||||
const vegaWalletUnstakedBalance =
|
||||
'[data-testid="vega-wallet-balance-unstaked"]';
|
||||
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
|
||||
|
@ -88,7 +88,7 @@ const Web3Container = ({
|
||||
<AppLoader>
|
||||
<BalanceManager>
|
||||
<>
|
||||
<div className="app w-full max-w-[1500px] mx-auto grid grid-rows-[1fr_min-content] min-h-full border-neutral-700 lg:border-l lg:border-r lg:text-body-large">
|
||||
<div className="app w-full max-w-[1500px] mx-auto grid grid-rows-[min-content_1fr_min-content] min-h-full border-neutral-700 lg:border-l lg:border-r lg:text-body-large">
|
||||
<TemplateSidebar sidebar={sideBar}>
|
||||
<AppRouter />
|
||||
</TemplateSidebar>
|
||||
|
@ -164,12 +164,12 @@ const ConnectedKey = () => {
|
||||
)}
|
||||
</section>
|
||||
<WalletCardActions>
|
||||
<Link className="flex-1" to={`${Routes.STAKING}/associate`}>
|
||||
<Link className="flex-1" to={`${Routes.VALIDATORS}/associate`}>
|
||||
<Button size="sm" fill={true}>
|
||||
{t('associate')}
|
||||
</Button>
|
||||
</Link>
|
||||
<Link className="flex-1" to={`${Routes.STAKING}/disassociate`}>
|
||||
<Link className="flex-1" to={`${Routes.VALIDATORS}/disassociate`}>
|
||||
<Button size="sm" fill={true}>
|
||||
{t('disassociate')}
|
||||
</Button>
|
||||
|
124
apps/token/src/components/nav/nav-draw.tsx
Normal file
124
apps/token/src/components/nav/nav-draw.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
import classNames from 'classnames';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import {
|
||||
AppStateActionType,
|
||||
useAppState,
|
||||
} from '../../contexts/app-state/app-state-context';
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
import { EthWallet } from '../eth-wallet';
|
||||
import { VegaWallet } from '../vega-wallet';
|
||||
|
||||
interface Route {
|
||||
name: string;
|
||||
path: string;
|
||||
}
|
||||
|
||||
const DrawerSection = ({ children }: { children: React.ReactNode }) => (
|
||||
<div className="px-4 my-4">{children}</div>
|
||||
);
|
||||
|
||||
const IconLine = ({ inverted }: { inverted: boolean }) => (
|
||||
<span className={`block w-6 h-[2px] ${inverted ? 'bg-black' : 'bg-white'}`} />
|
||||
);
|
||||
|
||||
const DrawerNavLinks = ({
|
||||
isInverted,
|
||||
routes,
|
||||
}: {
|
||||
isInverted?: boolean;
|
||||
routes: Route[];
|
||||
}) => {
|
||||
const { appDispatch } = useAppState();
|
||||
const linkProps = {
|
||||
end: true,
|
||||
onClick: () =>
|
||||
appDispatch({ type: AppStateActionType.SET_DRAWER, isOpen: false }),
|
||||
};
|
||||
const navClasses = classNames('flex flex-col');
|
||||
|
||||
return (
|
||||
<nav className={navClasses}>
|
||||
{routes.map(({ name, path }) => {
|
||||
return (
|
||||
<NavLink
|
||||
{...linkProps}
|
||||
to={{ pathname: path }}
|
||||
className={({ isActive }) =>
|
||||
classNames({
|
||||
'bg-vega-yellow text-black': !isInverted && isActive,
|
||||
'bg-transparent text-white hover:text-vega-yellow':
|
||||
!isInverted && !isActive,
|
||||
'bg-black text-white': isInverted && isActive,
|
||||
'bg-transparent text-black hover:text-white':
|
||||
isInverted && !isActive,
|
||||
'border-t border-white p-4': true,
|
||||
})
|
||||
}
|
||||
>
|
||||
{name}
|
||||
</NavLink>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export const NavDrawer = ({
|
||||
inverted,
|
||||
routes,
|
||||
}: {
|
||||
inverted: boolean;
|
||||
routes: Route[];
|
||||
}) => {
|
||||
const { appState, appDispatch } = useAppState();
|
||||
|
||||
const drawerContentClasses = classNames(
|
||||
'drawer-content', // needed for css animation
|
||||
// Positions the modal in the center of screen
|
||||
'fixed w-[80vw] max-w-[420px] top-0 right-0',
|
||||
'flex flex-col flex-nowrap justify-between h-full bg-banner overflow-y-scroll border-l border-white',
|
||||
'bg-black text-neutral-200'
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() =>
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_DRAWER,
|
||||
isOpen: true,
|
||||
})
|
||||
}
|
||||
className="flex flex-col flex-nowrap gap-1"
|
||||
>
|
||||
<IconLine inverted={inverted} />
|
||||
<IconLine inverted={inverted} />
|
||||
<IconLine inverted={inverted} />
|
||||
</button>
|
||||
|
||||
<Dialog.Root
|
||||
open={appState.drawerOpen}
|
||||
onOpenChange={(isOpen) =>
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_DRAWER,
|
||||
isOpen,
|
||||
})
|
||||
}
|
||||
>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay className="fixed inset-0 bg-white/15" />
|
||||
<Dialog.Content className={drawerContentClasses}>
|
||||
<div>
|
||||
<DrawerSection>
|
||||
<EthWallet />
|
||||
</DrawerSection>
|
||||
<DrawerSection>
|
||||
<VegaWallet />
|
||||
</DrawerSection>
|
||||
</div>
|
||||
<DrawerNavLinks routes={routes} />
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,91 +1,22 @@
|
||||
import './nav.css';
|
||||
|
||||
import classNames from 'classnames';
|
||||
import debounce from 'lodash/debounce';
|
||||
import React from 'react';
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link, NavLink } from 'react-router-dom';
|
||||
import vegaWhite from '../../images/vega_white.png';
|
||||
|
||||
import { Flags } from '../../config';
|
||||
import {
|
||||
AppStateActionType,
|
||||
useAppState,
|
||||
} from '../../contexts/app-state/app-state-context';
|
||||
import { NavLink, Link } from 'react-router-dom';
|
||||
import { NetworkSwitcher } from '@vegaprotocol/environment';
|
||||
import type { HTMLAttributeAnchorTarget } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import Routes from '../../routes/routes';
|
||||
import { EthWallet } from '../eth-wallet';
|
||||
import { VegaWallet } from '../vega-wallet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import vegaWhite from '../../images/vega_white.png';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { NavDrawer } from './nav-draw';
|
||||
import {
|
||||
getNavLinkClassNames,
|
||||
Nav as ToolkitNav,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
const Fish = () => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="33"
|
||||
height="20"
|
||||
viewBox="0 0 200 116"
|
||||
fill="none"
|
||||
data-testid="fairground-icon"
|
||||
>
|
||||
<g clipPath="url(#clip0)">
|
||||
<path
|
||||
d="M70.5918 32.8569L70.5918 22.7932L60.5254 22.7932L60.5254 32.8569L70.5918 32.8569Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M80.6641 83.2006L80.6641 73.1377L70.5977 73.1377L70.5977 83.2006L80.6641 83.2006Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M70.5918 93.2409L70.5918 83.1772L60.5254 83.1772L60.5254 93.2409L70.5918 93.2409Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M100.797 93.2636L100.797 73.1377L90.7305 73.1377L90.7305 93.2636L100.797 93.2636Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M90.7285 103.33L90.7285 93.2671L80.662 93.2671L80.662 103.33L90.7285 103.33Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M90.7285 22.8026L90.7285 12.74L80.662 12.74L80.662 22.8026L90.7285 22.8026Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M110.869 12.6108L110.869 2.54785L100.803 2.54785L100.803 12.6108L110.869 12.6108Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M120.934 103.326L120.934 73.1377L110.867 73.1377L110.867 103.326L120.934 103.326Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M110.869 113.384L110.869 103.321L100.803 103.321L100.803 113.384L110.869 113.384Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M161.328 52.9855L161.328 42.9226L151.262 42.9226L151.262 52.9855L161.328 52.9855Z"
|
||||
fill="black"
|
||||
/>
|
||||
<path
|
||||
d="M20.133 83.187L30.3354 83.187L30.3354 73.124L40.4017 73.124L40.4017 63.0613L50.4681 63.0613L50.4681 73.124L60.5345 73.124L60.5345 63.0613L70.6008 63.0613L80.6672 63.0613L131.135 63.0613L131.135 113.376L161.334 113.376L161.334 103.313L171.4 103.313L171.4 93.25L181.467 93.25L181.467 83.187L191.533 83.187L191.533 63.0613L181.467 63.0613L181.467 73.1241L171.4 73.1241L171.4 83.187L161.334 83.187L161.334 73.1241L171.4 73.1241L171.4 63.0613L161.334 63.0613L151.268 63.0613L141.201 63.0613L141.201 52.9983L141.201 32.8726L161.334 32.8726L171.4 32.8726L171.4 63.0613L181.467 63.0613L181.467 52.9983L191.533 52.9983L191.533 32.8726L181.467 32.8726L181.467 22.8096L171.4 22.8096L171.4 12.7467L161.334 12.7467L161.334 2.54785L141.201 2.54785L131.135 2.54785L131.135 52.9983L120.933 52.9983L120.933 12.7467L110.866 12.7467L110.866 52.9983L100.8 52.9983L100.8 22.8096L90.7336 22.8096L90.7336 52.9983L80.6672 52.9983L80.6672 32.8726L70.6008 32.8726L70.6008 52.9983L60.5345 52.9983L60.5345 42.9354L50.4681 42.9354L50.4681 52.9983L40.4017 52.9983L40.4017 42.9354L30.3354 42.9354L30.3354 32.8726L20.133 32.8726L20.133 22.8096L0.000308081 22.8096L0.000307201 42.9354L10.0666 42.9354L10.0666 52.9983L20.133 52.9983L20.133 63.0613L10.0666 63.0613L10.0666 73.124L0.000305881 73.124L0.000305002 93.25L20.133 93.25L20.133 83.187Z"
|
||||
fill="black"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="200" height="116" fill="none" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
const useDebouncedResize = () => {
|
||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||
|
||||
export const Nav = () => {
|
||||
const [windowWidth, setWindowWidth] = React.useState(window.innerWidth);
|
||||
const isDesktop = windowWidth > 959;
|
||||
const inverted = Flags.FAIRGROUND;
|
||||
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
const handleResizeDebounced = debounce(() => {
|
||||
setWindowWidth(window.innerWidth);
|
||||
}, 300);
|
||||
@ -96,167 +27,116 @@ export const Nav = () => {
|
||||
window.removeEventListener('resize', handleResizeDebounced);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`px-4 py-2 ${
|
||||
inverted
|
||||
? 'bg-clouds bg-no-repeat bg-cover bg-vega-yellow'
|
||||
: 'border-neutral-700 border-b'
|
||||
}`}
|
||||
>
|
||||
{isDesktop && <NavHeader fairground={inverted} />}
|
||||
<div className="flex justify-between items-center mx-auto gap-12 lg:justify-start">
|
||||
{!isDesktop && <NavHeader fairground={inverted} />}
|
||||
<div className="flex gap-12 lg:flex-auto">
|
||||
{isDesktop ? (
|
||||
<NavLinks isDesktop={isDesktop} isInverted={inverted} />
|
||||
) : (
|
||||
<NavDrawer inverted={inverted} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const NavHeader = ({ fairground }: { fairground: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-4">
|
||||
<Link to="/">
|
||||
{fairground ? (
|
||||
<Fish />
|
||||
) : (
|
||||
<img alt="Vega" src={vegaWhite} height={30} width={30} />
|
||||
)}
|
||||
</Link>
|
||||
<h1
|
||||
data-testid="header-title"
|
||||
className={`uppercase md:text-2xl sm:text-lg font-alpha uppercase calt my-0 ${
|
||||
fairground ? 'text-black' : 'text-white'
|
||||
}`}
|
||||
>
|
||||
{fairground ? t('fairgroundTitle') : t('title')}
|
||||
</h1>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DrawerSection = ({ children }: { children: React.ReactNode }) => (
|
||||
<div className="px-4 my-4">{children}</div>
|
||||
);
|
||||
|
||||
const IconLine = ({ inverted }: { inverted: boolean }) => (
|
||||
<span className={`block w-6 h-[2px] ${inverted ? 'bg-black' : 'bg-white'}`} />
|
||||
);
|
||||
|
||||
const NavDrawer = ({ inverted }: { inverted: boolean }) => {
|
||||
const { appState, appDispatch } = useAppState();
|
||||
|
||||
const drawerContentClasses = classNames(
|
||||
'drawer-content', // needed for css animation
|
||||
// Positions the modal in the center of screen
|
||||
'fixed w-[80vw] max-w-[420px] top-0 right-0',
|
||||
'flex flex-col flex-nowrap justify-between h-full bg-banner overflow-y-scroll border-l border-white',
|
||||
'bg-black text-neutral-200'
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
onClick={() =>
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_DRAWER,
|
||||
isOpen: true,
|
||||
})
|
||||
}
|
||||
className="flex flex-col flex-nowrap gap-1"
|
||||
>
|
||||
<IconLine inverted={inverted} />
|
||||
<IconLine inverted={inverted} />
|
||||
<IconLine inverted={inverted} />
|
||||
</button>
|
||||
|
||||
<Dialog.Root
|
||||
open={appState.drawerOpen}
|
||||
onOpenChange={(isOpen) =>
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_DRAWER,
|
||||
isOpen,
|
||||
})
|
||||
}
|
||||
>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay className="fixed inset-0 bg-white/15" />
|
||||
<Dialog.Content className={drawerContentClasses}>
|
||||
<div>
|
||||
<DrawerSection>
|
||||
<EthWallet />
|
||||
</DrawerSection>
|
||||
<DrawerSection>
|
||||
<VegaWallet />
|
||||
</DrawerSection>
|
||||
</div>
|
||||
<NavLinks isDesktop={false} />
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const NavLinks = ({
|
||||
isDesktop,
|
||||
isInverted,
|
||||
}: {
|
||||
isDesktop: boolean;
|
||||
isInverted?: boolean;
|
||||
}) => {
|
||||
const { appDispatch } = useAppState();
|
||||
const { t } = useTranslation();
|
||||
const linkProps = {
|
||||
onClick: () =>
|
||||
appDispatch({ type: AppStateActionType.SET_DRAWER, isOpen: false }),
|
||||
return {
|
||||
windowWidth,
|
||||
};
|
||||
};
|
||||
|
||||
type NavbarTheme = 'inherit' | 'dark' | 'yellow';
|
||||
interface NavbarProps {
|
||||
navbarTheme?: NavbarTheme;
|
||||
}
|
||||
|
||||
export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => {
|
||||
const { windowWidth } = useDebouncedResize();
|
||||
const isDesktop = windowWidth > 995;
|
||||
|
||||
const { t } = useTranslation();
|
||||
const isYellow = navbarTheme === 'yellow';
|
||||
const routes = [
|
||||
{ route: Routes.HOME, text: t('Home') },
|
||||
{ route: Routes.VESTING, text: t('Vesting') },
|
||||
{ route: Routes.STAKING, text: t('Staking') },
|
||||
{ route: Routes.REWARDS, text: t('Rewards') },
|
||||
{ route: Routes.WITHDRAWALS, text: t('Withdraw') },
|
||||
{ route: Routes.GOVERNANCE, text: t('Governance') },
|
||||
{
|
||||
name: t('Proposals'),
|
||||
path: Routes.PROPOSALS,
|
||||
},
|
||||
{
|
||||
name: t('Validators'),
|
||||
path: Routes.VALIDATORS,
|
||||
},
|
||||
{
|
||||
name: t('Rewards'),
|
||||
path: Routes.REWARDS,
|
||||
},
|
||||
{
|
||||
name: t('Token'),
|
||||
path: Routes.TOKEN,
|
||||
},
|
||||
{
|
||||
name: t('Redeem'),
|
||||
path: Routes.REDEEM,
|
||||
},
|
||||
{
|
||||
name: t('Withdraw'),
|
||||
path: Routes.WITHDRAWALS,
|
||||
},
|
||||
{
|
||||
name: t('Supply & Vesting'),
|
||||
path: Routes.TRANCHES,
|
||||
},
|
||||
];
|
||||
const navClasses = classNames('flex', {
|
||||
'flex-row gap-2 mt-4 uppercase': isDesktop,
|
||||
'flex-col': !isDesktop,
|
||||
});
|
||||
|
||||
return (
|
||||
<nav className={navClasses}>
|
||||
{routes.map(({ route, text }) => {
|
||||
return (
|
||||
<NavLink
|
||||
{...linkProps}
|
||||
to={route}
|
||||
key={route}
|
||||
className={({ isActive }) =>
|
||||
classNames({
|
||||
'bg-vega-yellow text-black': !isInverted && isActive,
|
||||
'bg-transparent text-white hover:text-vega-yellow':
|
||||
!isInverted && !isActive,
|
||||
'bg-black text-white': isInverted && isActive,
|
||||
'bg-transparent text-black hover:text-white':
|
||||
isInverted && !isActive,
|
||||
'py-1 px-2': isDesktop,
|
||||
'border-t border-white p-4': !isDesktop,
|
||||
})
|
||||
}
|
||||
>
|
||||
{text}
|
||||
</NavLink>
|
||||
);
|
||||
})}
|
||||
</nav>
|
||||
<ToolkitNav
|
||||
navbarTheme={navbarTheme}
|
||||
icon={
|
||||
<Link to="/">
|
||||
<img alt="Vega" src={vegaWhite} height={30} width={30} />
|
||||
</Link>
|
||||
}
|
||||
title={t('Governance')}
|
||||
titleContent={<NetworkSwitcher />}
|
||||
>
|
||||
{isDesktop ? (
|
||||
<nav className="flex items-center flex-1 px-2">
|
||||
{routes.map((r) => (
|
||||
<AppNavLink {...r} navbarTheme={navbarTheme} />
|
||||
))}
|
||||
</nav>
|
||||
) : (
|
||||
<nav className="flex items-center flex-1 px-2 justify-end">
|
||||
<NavDrawer inverted={isYellow} routes={routes} />
|
||||
</nav>
|
||||
)}
|
||||
</ToolkitNav>
|
||||
);
|
||||
};
|
||||
|
||||
interface AppNavLinkProps {
|
||||
name: string;
|
||||
path: string;
|
||||
navbarTheme: NavbarTheme;
|
||||
testId?: string;
|
||||
alignRight?: boolean;
|
||||
target?: HTMLAttributeAnchorTarget;
|
||||
}
|
||||
|
||||
const AppNavLink = ({
|
||||
name,
|
||||
path,
|
||||
navbarTheme,
|
||||
alignRight,
|
||||
target,
|
||||
testId = name,
|
||||
}: AppNavLinkProps) => {
|
||||
const borderClasses = classNames('absolute h-1 w-full bottom-[-1px] left-0', {
|
||||
'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow',
|
||||
'bg-black': navbarTheme === 'yellow',
|
||||
});
|
||||
return (
|
||||
<NavLink
|
||||
data-testid={testId}
|
||||
to={{ pathname: path }}
|
||||
className={getNavLinkClassNames(navbarTheme, alignRight)}
|
||||
target={target}
|
||||
end={true}
|
||||
>
|
||||
{({ isActive }) => {
|
||||
return (
|
||||
<>
|
||||
{name}
|
||||
{isActive && <span className={borderClasses} />}
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||
import React from 'react';
|
||||
|
||||
import { Nav } from '../nav';
|
||||
@ -8,17 +9,20 @@ export interface TemplateSidebarProps {
|
||||
}
|
||||
|
||||
export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
return (
|
||||
<div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[min-content_1fr] lg:grid-cols-[1fr_450px]">
|
||||
<Nav />
|
||||
<main className="col-start-1 p-4">{children}</main>
|
||||
<aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700">
|
||||
{sidebar.map((Component, i) => (
|
||||
<section className="mb-4 last:mb-0" key={i}>
|
||||
{Component}
|
||||
</section>
|
||||
))}
|
||||
</aside>
|
||||
</div>
|
||||
<>
|
||||
<Nav navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} />
|
||||
<div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[min-content_1fr] lg:grid-cols-[1fr_450px]">
|
||||
<main className="col-start-1 p-4">{children}</main>
|
||||
<aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700">
|
||||
{sidebar.map((Component, i) => (
|
||||
<section className="mb-4 last:mb-0" key={i}>
|
||||
{Component}
|
||||
</section>
|
||||
))}
|
||||
</aside>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -22,20 +22,18 @@ export const VegaWalletContainer = ({ children }: VegaWalletContainerProps) => {
|
||||
|
||||
if (!pubKey) {
|
||||
return (
|
||||
<p>
|
||||
<Button
|
||||
data-testid="connect-to-vega-wallet-btn"
|
||||
onClick={() => {
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
|
||||
isOpen: true,
|
||||
});
|
||||
openVegaWalletDialog();
|
||||
}}
|
||||
>
|
||||
{t('connectVegaWallet')}
|
||||
</Button>
|
||||
</p>
|
||||
<Button
|
||||
data-testid="connect-to-vega-wallet-btn"
|
||||
onClick={() => {
|
||||
appDispatch({
|
||||
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
|
||||
isOpen: true,
|
||||
});
|
||||
openVegaWalletDialog();
|
||||
}}
|
||||
>
|
||||
{t('connectVegaWallet')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
label={`${d.name || truncateMiddle(d.nodeId)} ${
|
||||
d.hasStakePending ? `(${t('thisEpoch')})` : ''
|
||||
}`}
|
||||
link={`${Routes.STAKING}/${d.nodeId}`}
|
||||
link={`${Routes.VALIDATORS}/${d.nodeId}`}
|
||||
value={d.currentEpochStake}
|
||||
/>
|
||||
</div>
|
||||
@ -186,7 +186,7 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
label={`${d.name || truncateMiddle(d.nodeId)} (${t(
|
||||
'nextEpoch'
|
||||
)})`}
|
||||
link={`${Routes.STAKING}/${d.nodeId}`}
|
||||
link={`${Routes.VALIDATORS}/${d.nodeId}`}
|
||||
value={d.nextEpochStake}
|
||||
/>
|
||||
</div>
|
||||
@ -194,12 +194,12 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
</div>
|
||||
))}
|
||||
<WalletCardActions>
|
||||
<Link className="flex-1" to={Routes.GOVERNANCE}>
|
||||
<Link className="flex-1" to={Routes.PROPOSALS}>
|
||||
<Button size="sm" fill={true}>
|
||||
{t('governance')}
|
||||
</Button>
|
||||
</Link>
|
||||
<Link className="flex-1" to={Routes.STAKING}>
|
||||
<Link className="flex-1" to={Routes.VALIDATORS}>
|
||||
<Button size="sm" fill={true}>
|
||||
{t('staking')}
|
||||
</Button>
|
||||
|
@ -472,7 +472,7 @@
|
||||
"transaction": "Transaction",
|
||||
"associated": "Associated",
|
||||
"notAssociated": "Not Associated",
|
||||
"title": "VEGA TOKEN",
|
||||
"title": "Governance",
|
||||
"Use the Ethereum wallet you want to send your tokens to. You'll also need enough Ethereum to pay gas.": "Connect to the Ethereum wallet that holds your $VEGA tokens to see what can be redeemed from vesting tranches. To redeem tokens you will need some ETH to pay gas fees.\n",
|
||||
"Connect to see your stake": "Connect to see your stake",
|
||||
"Staked on Vega validator": "Associated to Vega key",
|
||||
@ -715,5 +715,8 @@
|
||||
"SpamProtectionMin": "Spam protection minimum",
|
||||
"ListAsset": "List Asset",
|
||||
"ListAssetDescription": "This asset needs to be listed on the collateral bridge before it can be used.",
|
||||
"ListAssetAction": "List asset"
|
||||
"ListAssetAction": "List asset",
|
||||
"Proposals": "Proposals",
|
||||
"Validators": "Validators",
|
||||
"Redeem": "Redeem"
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export const Complete = ({
|
||||
</Link>
|
||||
</p>
|
||||
)}
|
||||
<RouteLink to={Routes.VESTING}>
|
||||
<RouteLink to={Routes.REDEEM}>
|
||||
<Button>{t('Check your vesting VEGA tokens')}</Button>
|
||||
</RouteLink>
|
||||
</Callout>
|
||||
|
@ -196,7 +196,7 @@ export const ProposalsListItemDetails = ({
|
||||
)}
|
||||
{proposal.id && (
|
||||
<div className="col-start-2 row-start-2 justify-self-end">
|
||||
<Link to={`${Routes.GOVERNANCE}/${proposal.id}`}>
|
||||
<Link to={`${Routes.PROPOSALS}/${proposal.id}`}>
|
||||
<Button data-testid="view-proposal-btn" size="sm">
|
||||
{t('View')}
|
||||
</Button>
|
||||
|
@ -54,7 +54,7 @@ export const ProposalsList = ({ proposals }: ProposalsListProps) => {
|
||||
<Link
|
||||
className="xs:justify-self-end"
|
||||
data-testid="new-proposal-link"
|
||||
to={`${Routes.GOVERNANCE}/propose`}
|
||||
to={`${Routes.PROPOSALS}/propose`}
|
||||
>
|
||||
<Button variant="primary" size="sm">
|
||||
{t('NewProposal')}
|
||||
|
@ -45,7 +45,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/network-parameter`}
|
||||
to={`${Routes.PROPOSALS}/propose/network-parameter`}
|
||||
>
|
||||
{t('NetworkParameter')}
|
||||
</Link>
|
||||
@ -55,7 +55,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/new-market`}
|
||||
to={`${Routes.PROPOSALS}/propose/new-market`}
|
||||
>
|
||||
{t('NewMarket')}
|
||||
</Link>
|
||||
@ -65,7 +65,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/update-market`}
|
||||
to={`${Routes.PROPOSALS}/propose/update-market`}
|
||||
>
|
||||
{t('UpdateMarket')}
|
||||
</Link>
|
||||
@ -75,7 +75,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/new-asset`}
|
||||
to={`${Routes.PROPOSALS}/propose/new-asset`}
|
||||
>
|
||||
{t('NewAsset')}
|
||||
</Link>
|
||||
@ -85,7 +85,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/update-asset`}
|
||||
to={`${Routes.PROPOSALS}/propose/update-asset`}
|
||||
>
|
||||
{t('UpdateAsset')}
|
||||
</Link>
|
||||
@ -95,7 +95,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/freeform`}
|
||||
to={`${Routes.PROPOSALS}/propose/freeform`}
|
||||
>
|
||||
{t('Freeform')}
|
||||
</Link>
|
||||
@ -105,7 +105,7 @@ export const Propose = () => {
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/raw`}
|
||||
to={`${Routes.PROPOSALS}/propose/raw`}
|
||||
>
|
||||
{t('RawProposal')}
|
||||
</Link>
|
||||
|
@ -57,7 +57,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
'Once unlocked they can be redeemed from the contract so that you can transfer them between wallets.'
|
||||
)}
|
||||
</p>
|
||||
<Link to={Routes.VESTING}>
|
||||
<Link to={Routes.REDEEM}>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="md"
|
||||
@ -93,7 +93,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
<p>
|
||||
<Link
|
||||
data-testid="associate-vega-tokens-link-on-homepage"
|
||||
to={`${Routes.STAKING}/associate`}
|
||||
to={`${Routes.VALIDATORS}/associate`}
|
||||
className="underline text-white"
|
||||
>
|
||||
{t('Associate VEGA tokens')}
|
||||
@ -110,7 +110,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<Link to={Routes.STAKING}>
|
||||
<Link to={Routes.VALIDATORS}>
|
||||
<Button size="md" data-testid="staking-button-on-homepage">
|
||||
{t('Nominate a validator')}
|
||||
</Button>
|
||||
@ -127,7 +127,7 @@ const Home = ({ name }: RouteChildProps) => {
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
<Link to={Routes.GOVERNANCE}>
|
||||
<Link to={Routes.PROPOSALS}>
|
||||
<Button size="md" data-testid="governance-button-on-homepage">
|
||||
{t('View Governance proposals')}
|
||||
</Button>
|
||||
|
@ -10,7 +10,7 @@ import Routes from '../routes';
|
||||
const RedemptionIndex = ({ name }: RouteChildProps) => {
|
||||
useDocumentTitle(name);
|
||||
const { t } = useTranslation();
|
||||
const tranche = useMatch(`${Routes.VESTING}/:id`);
|
||||
const tranche = useMatch(`${Routes.REDEEM}/:id`);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -121,13 +121,13 @@ export const RedeemFromTranche = () => {
|
||||
stakingLink: (
|
||||
<Link
|
||||
className="underline text-white"
|
||||
to={Routes.STAKING}
|
||||
to={Routes.VALIDATORS}
|
||||
/>
|
||||
),
|
||||
governanceLink: (
|
||||
<Link
|
||||
className="underline text-white"
|
||||
to={Routes.GOVERNANCE}
|
||||
to={Routes.PROPOSALS}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
import Home from './home';
|
||||
import NotFound from './not-found';
|
||||
import NotPermitted from './not-permitted';
|
||||
@ -193,61 +193,32 @@ const LazyWithdrawals = React.lazy(
|
||||
)
|
||||
);
|
||||
|
||||
const routerConfig = [
|
||||
const redirects = [
|
||||
{
|
||||
path: Routes.HOME,
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
element: <Home name="Home" />,
|
||||
},
|
||||
{
|
||||
path: Routes.TRANCHES,
|
||||
element: <LazyTranches name="Tranches" />,
|
||||
children: [
|
||||
{ index: true, element: <LazyTranchesTranches /> },
|
||||
{ path: ':trancheId', element: <LazyTranchesTranche /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.CLAIM,
|
||||
element: <LazyClaim name="Claim" />,
|
||||
element: <Navigate to={Routes.PROPOSALS} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.STAKING,
|
||||
element: <LazyStaking name="Staking" />,
|
||||
children: [
|
||||
{ path: 'associate', element: <LazyStakingAssociate /> },
|
||||
{ path: 'disassociate', element: <LazyStakingDisassociate /> },
|
||||
{ path: ':node', element: <LazyStakingNode /> },
|
||||
{
|
||||
index: true,
|
||||
element: <LazyStakingIndex />,
|
||||
},
|
||||
],
|
||||
element: <Navigate to={Routes.VALIDATORS} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.REWARDS,
|
||||
element: <LazyRewards name="Rewards" />,
|
||||
path: '/tranches',
|
||||
element: <Navigate to={Routes.TRANCHES} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.WITHDRAWALS,
|
||||
element: <LazyWithdrawals name="Withdrawals" />,
|
||||
path: '/withdrawals',
|
||||
element: <Navigate to={Routes.WITHDRAWALS} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.VESTING,
|
||||
element: <LazyRedemption name="Vesting" />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <LazyRedemptionIndex />,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
element: <LazyRedemptionTranche />,
|
||||
},
|
||||
],
|
||||
path: '/vesting',
|
||||
element: <Navigate to={Routes.REDEEM} replace />,
|
||||
},
|
||||
];
|
||||
|
||||
const routerConfig = [
|
||||
{
|
||||
path: Routes.GOVERNANCE,
|
||||
path: Routes.PROPOSALS,
|
||||
element: <LazyGovernance name="Governance" />,
|
||||
children: [
|
||||
{ index: true, element: <LazyGovernanceProposals /> },
|
||||
@ -281,6 +252,63 @@ const routerConfig = [
|
||||
{ path: 'rejected', element: <LazyRejectedGovernanceProposals /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
element: <LazyStaking name="Staking" />,
|
||||
children: [
|
||||
{ path: 'associate', element: <LazyStakingAssociate /> },
|
||||
{ path: 'disassociate', element: <LazyStakingDisassociate /> },
|
||||
{ path: ':node', element: <LazyStakingNode /> },
|
||||
{
|
||||
index: true,
|
||||
element: <LazyStakingIndex />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.REWARDS,
|
||||
element: <LazyRewards name="Rewards" />,
|
||||
},
|
||||
{
|
||||
path: Routes.TOKEN,
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
children: [
|
||||
{
|
||||
element: <Home name="Home" />,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
path: Routes.TRANCHES,
|
||||
element: <LazyTranches name="Tranches" />,
|
||||
children: [
|
||||
{ index: true, element: <LazyTranchesTranches /> },
|
||||
{ path: ':trancheId', element: <LazyTranchesTranche /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.WITHDRAWALS,
|
||||
element: <LazyWithdrawals name="Withdrawals" />,
|
||||
},
|
||||
{
|
||||
path: Routes.REDEEM,
|
||||
element: <LazyRedemption name="Vesting" />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <LazyRedemptionIndex />,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
element: <LazyRedemptionTranche />,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.CLAIM,
|
||||
element: <LazyClaim name="Claim" />,
|
||||
},
|
||||
{
|
||||
path: Routes.NOT_PERMITTED,
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
@ -295,6 +323,7 @@ const routerConfig = [
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
element: <NotFound name="NotFound" />,
|
||||
},
|
||||
...redirects,
|
||||
];
|
||||
|
||||
export default routerConfig;
|
||||
|
@ -1,13 +1,16 @@
|
||||
export default {
|
||||
HOME: '/',
|
||||
TRANCHES: '/tranches',
|
||||
CLAIM: '/claim',
|
||||
STAKING: '/staking',
|
||||
VALIDATORS: '/validators',
|
||||
REWARDS: '/rewards',
|
||||
WITHDRAWALS: '/withdrawals',
|
||||
GOVERNANCE: '/governance',
|
||||
VESTING: '/vesting',
|
||||
PROPOSALS: '/proposals',
|
||||
NOT_PERMITTED: '/not-permitted',
|
||||
NOT_FOUND: '/not-found',
|
||||
CONTRACTS: '/contracts',
|
||||
STAKING: '/staking',
|
||||
TOKEN: '/token',
|
||||
REDEEM: '/token/redeem',
|
||||
WITHDRAWALS: '/token/withdraw',
|
||||
TRANCHES: '/token/tranches',
|
||||
ASSOCIATE: '/token/associate',
|
||||
};
|
||||
|
@ -93,7 +93,7 @@ export const AssociateTransaction = ({
|
||||
vegaKey: truncateMiddle(vegaKey),
|
||||
})}
|
||||
completeFooter={
|
||||
<RouteLink to={Routes.STAKING}>
|
||||
<RouteLink to={Routes.VALIDATORS}>
|
||||
<Button>{t('Nominate Stake to Validator Node')}</Button>
|
||||
</RouteLink>
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ export const DisassociateTransaction = ({
|
||||
})
|
||||
}
|
||||
completeFooter={
|
||||
<Link to={Routes.STAKING}>
|
||||
<Link to={Routes.VALIDATORS}>
|
||||
<Button>{t('backToStaking')}</Button>
|
||||
</Link>
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { createDocsLinks, ExternalLinks } from '@vegaprotocol/react-helpers';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import Routes from '../../../routes/routes';
|
||||
|
||||
export const StakingIntro = () => {
|
||||
const { t } = useTranslation();
|
||||
@ -24,7 +25,7 @@ export const StakingIntro = () => {
|
||||
<li>
|
||||
{t('stakingDescription1')}{' '}
|
||||
<Link
|
||||
to="/staking/associate"
|
||||
to={Routes.ASSOCIATE}
|
||||
className="underline"
|
||||
data-testid="staking-associate-link"
|
||||
>
|
||||
|
@ -9,8 +9,8 @@ import type { RouteChildProps } from '..';
|
||||
const StakingRouter = ({ name }: RouteChildProps) => {
|
||||
useDocumentTitle(name);
|
||||
const { t } = useTranslation();
|
||||
const associate = useMatch('/staking/associate');
|
||||
const disassociate = useMatch('/staking/disassociate');
|
||||
const associate = useMatch('/validators/associate');
|
||||
const disassociate = useMatch('/validators/disassociate');
|
||||
|
||||
const title = React.useMemo(() => {
|
||||
if (associate) {
|
||||
|
@ -44,7 +44,7 @@ export const StakeSuccess = ({
|
||||
<div>
|
||||
<p>{message}</p>
|
||||
<p>
|
||||
<Link className="underline" to={Routes.STAKING}>
|
||||
<Link className="underline" to={Routes.VALIDATORS}>
|
||||
{t('backToStaking')}
|
||||
</Link>
|
||||
</p>
|
||||
|
@ -88,7 +88,7 @@ export const VestingChart = () => {
|
||||
stroke={colors.white}
|
||||
strokeWidth={2}
|
||||
label={{
|
||||
position: 'right',
|
||||
position: 'left',
|
||||
value: currentDate,
|
||||
fill: colors.white,
|
||||
}}
|
||||
|
@ -7,8 +7,12 @@ import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
|
||||
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
|
||||
import { Vega } from '../icons/vega';
|
||||
import type { HTMLAttributeAnchorTarget } from 'react';
|
||||
import testnetBg from '../../assets/green-cloud.png';
|
||||
import { Routes } from '../../pages/client-router';
|
||||
import {
|
||||
getNavLinkClassNames,
|
||||
getActiveNavLinkClassNames,
|
||||
Nav,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
type NavbarTheme = 'inherit' | 'dark' | 'yellow';
|
||||
interface NavbarProps {
|
||||
@ -27,61 +31,40 @@ export const Navbar = ({
|
||||
marketId: store.marketId,
|
||||
}));
|
||||
const tradingPath = marketId ? `/markets/${marketId}` : '/markets';
|
||||
|
||||
const themeWrapperClasses = classNames({
|
||||
dark: navbarTheme === 'dark',
|
||||
});
|
||||
|
||||
const isYellow = navbarTheme === 'yellow';
|
||||
const navbarClasses = classNames(
|
||||
'flex items-stretch border-b px-4 border-default',
|
||||
{
|
||||
'dark:bg-black dark:text-white': !isYellow,
|
||||
'bg-vega-yellow text-black bg-right-top bg-no-repeat bg-contain':
|
||||
isYellow,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={themeWrapperClasses}>
|
||||
<div
|
||||
className={navbarClasses}
|
||||
style={{
|
||||
backgroundImage: isYellow ? `url("${testnetBg.src}")` : '',
|
||||
}}
|
||||
>
|
||||
<div className="flex gap-4 items-center">
|
||||
<Link to="/">
|
||||
<Vega className="w-13" />
|
||||
</Link>
|
||||
<NetworkSwitcher />
|
||||
</div>
|
||||
<nav className="flex items-center flex-1 px-2">
|
||||
<AppNavLink
|
||||
name={t('Trading')}
|
||||
path={tradingPath}
|
||||
navbarTheme={navbarTheme}
|
||||
/>
|
||||
<AppNavLink
|
||||
name={t('Portfolio')}
|
||||
path={Routes.PORTFOLIO}
|
||||
navbarTheme={navbarTheme}
|
||||
/>
|
||||
<a
|
||||
href={`${VEGA_TOKEN_URL}/governance`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={getActiveNavLinkClassNames(false, navbarTheme, true)}
|
||||
>
|
||||
{t('Governance')}
|
||||
</a>
|
||||
</nav>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<VegaWalletConnectButton />
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
|
||||
</div>
|
||||
<Nav
|
||||
navbarTheme={navbarTheme}
|
||||
title={t('Console')}
|
||||
titleContent={<NetworkSwitcher />}
|
||||
icon={
|
||||
<Link to="/">
|
||||
<Vega className="w-13" />
|
||||
</Link>
|
||||
}
|
||||
>
|
||||
<AppNavLink
|
||||
name={t('Trading')}
|
||||
path={tradingPath}
|
||||
navbarTheme={navbarTheme}
|
||||
/>
|
||||
<AppNavLink
|
||||
name={t('Portfolio')}
|
||||
path={Routes.PORTFOLIO}
|
||||
navbarTheme={navbarTheme}
|
||||
/>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<a
|
||||
href={`${VEGA_TOKEN_URL}/governance`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={getActiveNavLinkClassNames(false, navbarTheme, true)}
|
||||
>
|
||||
{t('Governance')}
|
||||
</a>
|
||||
<VegaWalletConnectButton />
|
||||
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
|
||||
</div>
|
||||
</div>
|
||||
</Nav>
|
||||
);
|
||||
};
|
||||
|
||||
@ -124,28 +107,3 @@ const AppNavLink = ({
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
|
||||
function getNavLinkClassNames(
|
||||
navbarTheme: string,
|
||||
alignRight = false
|
||||
): (props: { isActive?: boolean }) => string | undefined {
|
||||
return ({ isActive = false }) => {
|
||||
return getActiveNavLinkClassNames(isActive, navbarTheme, alignRight);
|
||||
};
|
||||
}
|
||||
|
||||
const getActiveNavLinkClassNames = (
|
||||
isActive: boolean,
|
||||
navbarTheme: string,
|
||||
alignRight = false
|
||||
): string | undefined => {
|
||||
return classNames('mx-2 py-3 self-end relative', {
|
||||
'cursor-default': isActive,
|
||||
'text-black dark:text-white': isActive && navbarTheme !== 'yellow',
|
||||
'text-neutral-500 dark:text-neutral-400 hover:text-black dark:hover:text-neutral-300':
|
||||
!isActive && navbarTheme !== 'yellow',
|
||||
'ml-auto': alignRight,
|
||||
'text-black': isActive && navbarTheme === 'yellow',
|
||||
'text-black/60 hover:text-black': !isActive && navbarTheme === 'yellow',
|
||||
});
|
||||
};
|
||||
|
@ -18,6 +18,7 @@ export * from './key-value-table';
|
||||
export * from './link';
|
||||
export * from './loader';
|
||||
export * from './lozenge';
|
||||
export * from './nav';
|
||||
export * from './popover';
|
||||
export * from './price-change';
|
||||
export * from './progress-bar';
|
||||
|
1
libs/ui-toolkit/src/components/nav/index.ts
Normal file
1
libs/ui-toolkit/src/components/nav/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './nav';
|
19
libs/ui-toolkit/src/components/nav/nav.spec.tsx
Normal file
19
libs/ui-toolkit/src/components/nav/nav.spec.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
import { Nav } from './nav';
|
||||
|
||||
describe('Nav', () => {
|
||||
it('should render title, title content, icon and children', () => {
|
||||
const { baseElement } = render(
|
||||
<Nav
|
||||
navbarTheme="dark"
|
||||
icon={<div data-testid="icon" />}
|
||||
titleContent={<div data-testid="title-content" />}
|
||||
title={'Some title'}
|
||||
>
|
||||
<div data-testid="link"></div>
|
||||
</Nav>
|
||||
);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
});
|
34
libs/ui-toolkit/src/components/nav/nav.stories.tsx
Normal file
34
libs/ui-toolkit/src/components/nav/nav.stories.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import type { Meta, Story } from '@storybook/react';
|
||||
import { ButtonLink } from '../button';
|
||||
|
||||
import { VegaLogo } from '../vega-logo';
|
||||
import { Nav } from './nav';
|
||||
|
||||
export default {
|
||||
component: Nav,
|
||||
title: 'Nav',
|
||||
} as Meta;
|
||||
|
||||
const Template: Story = ({ icon, title, titleContent }) => (
|
||||
<div className="flex w-full">
|
||||
<Nav icon={icon} title={title} titleContent={titleContent}>
|
||||
<div className="mx-4">
|
||||
<ButtonLink>Some link</ButtonLink>{' '}
|
||||
</div>
|
||||
<div className="mx-4">
|
||||
<ButtonLink>Some other link</ButtonLink>
|
||||
</div>
|
||||
</Nav>
|
||||
</div>
|
||||
);
|
||||
|
||||
const props = {
|
||||
icon: <VegaLogo />,
|
||||
title: 'Title',
|
||||
titleContent: <div>Content next to title</div>,
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
...props,
|
||||
};
|
79
libs/ui-toolkit/src/components/nav/nav.tsx
Normal file
79
libs/ui-toolkit/src/components/nav/nav.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import classNames from 'classnames';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export function getNavLinkClassNames(
|
||||
navbarTheme: string,
|
||||
alignRight = false
|
||||
): (props: { isActive?: boolean }) => string | undefined {
|
||||
return ({ isActive = false }) => {
|
||||
return getActiveNavLinkClassNames(isActive, navbarTheme, alignRight);
|
||||
};
|
||||
}
|
||||
|
||||
export const getActiveNavLinkClassNames = (
|
||||
isActive: boolean,
|
||||
navbarTheme: string,
|
||||
alignRight = false
|
||||
): string | undefined => {
|
||||
return classNames('mx-2 py-3 self-end relative', {
|
||||
'cursor-default': isActive,
|
||||
'text-black dark:text-white': isActive && navbarTheme !== 'yellow',
|
||||
'text-neutral-500 dark:text-neutral-400 hover:text-black dark:hover:text-neutral-300':
|
||||
!isActive && navbarTheme !== 'yellow',
|
||||
'ml-auto': alignRight,
|
||||
'text-black': isActive && navbarTheme === 'yellow',
|
||||
'text-black/60 hover:text-black': !isActive && navbarTheme === 'yellow',
|
||||
});
|
||||
};
|
||||
|
||||
type NavbarTheme = 'inherit' | 'dark' | 'yellow';
|
||||
|
||||
interface NavbarProps {
|
||||
navbarTheme?: NavbarTheme;
|
||||
icon: ReactNode;
|
||||
titleContent: ReactNode;
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const Nav = ({
|
||||
navbarTheme = 'inherit',
|
||||
children,
|
||||
icon,
|
||||
titleContent,
|
||||
title,
|
||||
}: NavbarProps) => {
|
||||
const themeWrapperClasses = classNames('w-full', {
|
||||
dark: navbarTheme === 'dark',
|
||||
});
|
||||
|
||||
const isYellow = navbarTheme === 'yellow';
|
||||
const navbarClasses = classNames(
|
||||
'flex items-stretch border-b px-4 border-default',
|
||||
{
|
||||
'dark:bg-black dark:text-white': !isYellow,
|
||||
'bg-vega-yellow text-black bg-right-top bg-no-repeat bg-contain':
|
||||
isYellow,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={themeWrapperClasses}>
|
||||
<div className={navbarClasses}>
|
||||
<div className="flex gap-4 items-center">
|
||||
{icon}
|
||||
<h1
|
||||
className={classNames(
|
||||
'h-full flex flex-col my-0 justify-center font-alpha calt uppercase',
|
||||
{ 'text-black': isYellow, 'text-white': !isYellow }
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
{titleContent}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue
Block a user