Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83115b5e5d | ||
|
|
2123afc4b0 | ||
|
|
ea91fa1723 | ||
|
|
4dcdec7a35 | ||
|
|
196f1914a3 | ||
|
|
ea4c7a4a37 | ||
|
|
c22fec97b4 | ||
|
|
989a0456c0 | ||
|
|
8c79a94a8c | ||
|
|
a7a6a820c0 | ||
|
|
1fa09a690e | ||
|
|
b0a84970f2 | ||
|
|
b2a115f935 |
@@ -2761,7 +2761,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "69212.7941588870528164928",
|
||||
"locked_amount": "68975.3330121062666493861",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -2827,7 +2827,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1435.351483007733",
|
||||
"locked_amount": "1421.61410637973125",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -3215,7 +3215,7 @@
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "2836.415649675",
|
||||
"locked_amount": "34287.34557243708",
|
||||
"locked_amount": "34080.14646639042375",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -3326,7 +3326,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "69149.646192904764493335",
|
||||
"locked_amount": "68912.401699541887736445",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -3392,7 +3392,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "34043.00988077117846",
|
||||
"locked_amount": "33871.4891362252656",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -3585,7 +3585,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2910.871067985794",
|
||||
"locked_amount": "2897.1713280060885",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -3796,7 +3796,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "11051.5629572361427967976",
|
||||
"locked_amount": "10818.8482095714036717828",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -3829,7 +3829,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "98230.390980249184455396",
|
||||
"locked_amount": "15105.57858979342307160273426",
|
||||
"locked_amount": "14787.49770626082669661645614",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -3875,7 +3875,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "4649.201685825244862006",
|
||||
"locked_amount": "4551.302610251424035468",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -3908,7 +3908,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1513.2700339508446292286",
|
||||
"locked_amount": "1481.4048348417078526675",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -3941,7 +3941,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "4720.860935375",
|
||||
"locked_amount": "5656.9413696662315119734",
|
||||
"locked_amount": "5537.8221384325917571011",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -4093,7 +4093,7 @@
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "4373.451408",
|
||||
"locked_amount": "9135.943255064457",
|
||||
"locked_amount": "9011.6237914364655",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -4324,7 +4324,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "560684.945746241749007341",
|
||||
"locked_amount": "555369.642869191387312504",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -7298,10 +7298,15 @@
|
||||
"tranche_id": 10,
|
||||
"tranche_start": "2021-07-15T23:37:11.000Z",
|
||||
"tranche_end": "2021-07-15T23:37:11.000Z",
|
||||
"total_added": "6159302.299000000000000001",
|
||||
"total_removed": "6113483.280000000000000001",
|
||||
"total_added": "6259302.299000000000000001",
|
||||
"total_removed": "6213483.280000000000000001",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0xa4417547c32fb4936e0dd6ee338ba31b2fd622388fe8a3906d9e7020d5e8371b"
|
||||
},
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@@ -7824,6 +7829,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tx": "0xa4417547c32fb4936e0dd6ee338ba31b2fd622388fe8a3906d9e7020d5e8371b"
|
||||
},
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@@ -8289,6 +8299,12 @@
|
||||
{
|
||||
"address": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tranche_id": 10,
|
||||
"tx": "0xa4417547c32fb4936e0dd6ee338ba31b2fd622388fe8a3906d9e7020d5e8371b"
|
||||
},
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@@ -8471,6 +8487,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
"tranche_id": 10,
|
||||
"tx": "0xa4417547c32fb4936e0dd6ee338ba31b2fd622388fe8a3906d9e7020d5e8371b"
|
||||
},
|
||||
{
|
||||
"amount": "100000",
|
||||
"user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f",
|
||||
@@ -8646,8 +8668,8 @@
|
||||
"tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc"
|
||||
}
|
||||
],
|
||||
"total_tokens": "2956651",
|
||||
"withdrawn_tokens": "2956651",
|
||||
"total_tokens": "3056651",
|
||||
"withdrawn_tokens": "3056651",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
@@ -36594,7 +36616,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "592998.0503546212334",
|
||||
"locked_amount": "886078.876576593193858643006",
|
||||
"locked_amount": "877911.01211975962832293262",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -37919,8 +37941,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "567626.84057226362274952",
|
||||
"locked_amount": "8441666.3902799341022910153716735157718303",
|
||||
"total_removed": "570447.40018226362274952",
|
||||
"locked_amount": "8412703.667343023478982687330398519288997",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -38454,6 +38476,11 @@
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tx": "0x4870598253a2a664d9c96af37904f08ac772ee9620b5975560ef7e7fb51c9a7f"
|
||||
},
|
||||
{
|
||||
"amount": "2820.55961",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x039c7d1eb6b18a13c3fb91589403d43710e12b319e7d40936280a576502f80fe"
|
||||
},
|
||||
{
|
||||
"amount": "856.08784586478614",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -41965,6 +41992,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "2820.55961",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x039c7d1eb6b18a13c3fb91589403d43710e12b319e7d40936280a576502f80fe"
|
||||
},
|
||||
{
|
||||
"amount": "1412.763584",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -42165,8 +42198,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200000",
|
||||
"withdrawn_tokens": "90814.016456",
|
||||
"remaining_tokens": "109185.983544"
|
||||
"withdrawn_tokens": "93634.576066",
|
||||
"remaining_tokens": "106365.423934"
|
||||
},
|
||||
{
|
||||
"address": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
|
||||
@@ -43519,7 +43552,7 @@
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "3926967.723059737571037032",
|
||||
"locked_amount": "2071847.284667310624156645942280506",
|
||||
"locked_amount": "2045109.08378068825804623195557898",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -50432,7 +50465,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "2749067.463242913023296295",
|
||||
"locked_amount": "501695.989059927736982047096440314",
|
||||
"locked_amount": "491131.564178330845541202121121822",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -52458,8 +52491,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "33643.6376997992685",
|
||||
"locked_amount": "140404.26303635577567951130086252",
|
||||
"total_removed": "33662.0369387672685",
|
||||
"locked_amount": "139110.018223666781876256383155776",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -59143,6 +59176,11 @@
|
||||
"user": "0x4F4A140E9B4a8403792970C6b5535ed0AA32c8A4",
|
||||
"tx": "0x181a9afe9b3592427f1ee10f205e01f34ae7be383294e8d93e397766092bf6df"
|
||||
},
|
||||
{
|
||||
"amount": "18.399238968",
|
||||
"user": "0xD3ec605d078326B0a636ca90d496Ebb5Eb457a27",
|
||||
"tx": "0xa82e451753cbced76b064af62868d3170dff7afca557680e657c27ebba5c7beb"
|
||||
},
|
||||
{
|
||||
"amount": "13.1116203702",
|
||||
"user": "0x4cBC0C88d8FE503f62823B42f30a4900292C13bE",
|
||||
@@ -67301,6 +67339,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "18.399238968",
|
||||
"user": "0xD3ec605d078326B0a636ca90d496Ebb5Eb457a27",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xa82e451753cbced76b064af62868d3170dff7afca557680e657c27ebba5c7beb"
|
||||
},
|
||||
{
|
||||
"amount": "262.76406646",
|
||||
"user": "0xD3ec605d078326B0a636ca90d496Ebb5Eb457a27",
|
||||
@@ -67309,8 +67353,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "262.76406646",
|
||||
"remaining_tokens": "137.23593354"
|
||||
"withdrawn_tokens": "281.163305428",
|
||||
"remaining_tokens": "118.836694572"
|
||||
},
|
||||
{
|
||||
"address": "0x7f6aba7563Cb5d31980D440337D3d1A6e3dB58F3",
|
||||
|
||||
@@ -63,6 +63,39 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
.and('have.text', 'Browse, vote, and propose');
|
||||
});
|
||||
});
|
||||
it('should show open or enacted proposals with proposal summary', function () {
|
||||
cy.get('body').then(($body) => {
|
||||
if (!$body.find('[data-testid="proposals-list-item"]').length) {
|
||||
cy.createMarket();
|
||||
cy.reload();
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
});
|
||||
cy.getByTestId('proposals-list-item')
|
||||
.should('have.length.at.least', 1)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.getByTestId('proposal-title')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-type')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-description')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-details')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-status')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('vote-details')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('view-proposal-btn').should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have external link for governance', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.getByTestId('external-link')
|
||||
|
||||
+2
-2
@@ -30,11 +30,11 @@ context('Staking Page - verify elements on page', function () {
|
||||
|
||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||
describe('description section', function () {
|
||||
it('Should have staking tab highlighted', function () {
|
||||
it('Should have validators tab highlighted', function () {
|
||||
cy.verify_tab_highlighted('validators');
|
||||
});
|
||||
|
||||
it('Should have STAKING ON VEGA header visible', function () {
|
||||
it('Should have validators ON VEGA header visible', function () {
|
||||
cy.verify_page_header('Validators');
|
||||
});
|
||||
|
||||
@@ -338,8 +338,8 @@ context(
|
||||
.contains(currency.id)
|
||||
.parent()
|
||||
.siblings()
|
||||
.within(() => cy.contains_exactly('10.00').should('be.visible'));
|
||||
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.get(vegaWalletCurrencyTitle)
|
||||
.contains(currency.id)
|
||||
.parent()
|
||||
|
||||
@@ -18,7 +18,7 @@ export const NavDropDown = ({ navbarTheme }: { navbarTheme: NavbarTheme }) => {
|
||||
<AppNavLink
|
||||
name={
|
||||
<NavDropdownMenuTrigger
|
||||
className="w-auto flex items-center"
|
||||
className="w-auto flex items-center -m-3 p-3 cursor-pointer"
|
||||
data-testid="state-trigger"
|
||||
onClick={() => setOpen(!isOpen)}
|
||||
>
|
||||
|
||||
+111
-89
@@ -50,101 +50,117 @@ export const StandbyPendingValidatorsTable = ({
|
||||
const nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
|
||||
return data.map(
|
||||
({
|
||||
id,
|
||||
name,
|
||||
avatarUrl,
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore },
|
||||
pendingStake,
|
||||
}) => {
|
||||
const { rawValidatorScore, performanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
const overstakedAmount = getOverstakedAmount(
|
||||
rawValidatorScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
);
|
||||
let individualStakeNeededForPromotion,
|
||||
individualStakeNeededForPromotionDescription;
|
||||
|
||||
if (stakeNeededForPromotion && performanceScore) {
|
||||
const stakedTotalBigNum = new BigNumber(stakedTotal);
|
||||
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
|
||||
const performanceScoreBigNum = new BigNumber(performanceScore);
|
||||
|
||||
const calc = stakeNeededBigNum
|
||||
.dividedBy(performanceScoreBigNum)
|
||||
.minus(stakedTotalBigNum);
|
||||
|
||||
if (calc.isGreaterThan(0)) {
|
||||
individualStakeNeededForPromotion = calc.toString();
|
||||
individualStakeNeededForPromotionDescription = t(
|
||||
stakeNeededForPromotionDescription,
|
||||
{
|
||||
prefix: formatNumber(calc, 2).toString(),
|
||||
}
|
||||
);
|
||||
} else {
|
||||
individualStakeNeededForPromotion = '0';
|
||||
individualStakeNeededForPromotionDescription = t(
|
||||
stakeNeededForPromotionDescription,
|
||||
{
|
||||
prefix: formatNumber(0, 2).toString(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
return data
|
||||
.sort((a, b) => {
|
||||
const aVotingPower = new BigNumber(a.rankingScore.votingPower);
|
||||
const bVotingPower = new BigNumber(b.rankingScore.votingPower);
|
||||
return bVotingPower.minus(aVotingPower).toNumber();
|
||||
})
|
||||
.map((node, index) => {
|
||||
const votingPowerRanking = index + 1;
|
||||
|
||||
return {
|
||||
...node,
|
||||
votingPowerRanking,
|
||||
};
|
||||
})
|
||||
.map(
|
||||
({
|
||||
id,
|
||||
[ValidatorFields.VALIDATOR]: {
|
||||
avatarUrl,
|
||||
name,
|
||||
},
|
||||
[ValidatorFields.STAKE]: formatNumber(
|
||||
toBigNum(stakedTotal, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
|
||||
individualStakeNeededForPromotion || null,
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
|
||||
individualStakeNeededForPromotionDescription || t('n/a'),
|
||||
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
|
||||
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
|
||||
toBigNum(stakedByDelegates, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKED_BY_OPERATOR]: formatNumber(
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
||||
getPerformancePenalty(performanceScore),
|
||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
overstakedAmount,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
name,
|
||||
avatarUrl,
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore },
|
||||
pendingStake,
|
||||
votingPowerRanking,
|
||||
}) => {
|
||||
const { rawValidatorScore, performanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
const overstakedAmount = getOverstakedAmount(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: formatNumber(
|
||||
toBigNum(pendingStake, decimals),
|
||||
2
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
);
|
||||
let individualStakeNeededForPromotion,
|
||||
individualStakeNeededForPromotionDescription;
|
||||
|
||||
if (stakeNeededForPromotion && performanceScore) {
|
||||
const stakedTotalBigNum = new BigNumber(stakedTotal);
|
||||
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
|
||||
const performanceScoreBigNum = new BigNumber(performanceScore);
|
||||
|
||||
const calc = stakeNeededBigNum
|
||||
.dividedBy(performanceScoreBigNum)
|
||||
.minus(stakedTotalBigNum);
|
||||
|
||||
if (calc.isGreaterThan(0)) {
|
||||
individualStakeNeededForPromotion = calc.toString();
|
||||
individualStakeNeededForPromotionDescription = t(
|
||||
stakeNeededForPromotionDescription,
|
||||
{
|
||||
prefix: formatNumber(calc, 2).toString(),
|
||||
}
|
||||
);
|
||||
} else {
|
||||
individualStakeNeededForPromotion = '0';
|
||||
individualStakeNeededForPromotionDescription = t(
|
||||
stakeNeededForPromotionDescription,
|
||||
{
|
||||
prefix: formatNumber(0, 2).toString(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
[ValidatorFields.RANKING_INDEX]: votingPowerRanking,
|
||||
[ValidatorFields.VALIDATOR]: {
|
||||
avatarUrl,
|
||||
name,
|
||||
},
|
||||
[ValidatorFields.STAKE]: formatNumber(
|
||||
toBigNum(stakedTotal, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
|
||||
individualStakeNeededForPromotion || null,
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
|
||||
individualStakeNeededForPromotionDescription || t('n/a'),
|
||||
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
|
||||
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
|
||||
toBigNum(stakedByDelegates, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKED_BY_OPERATOR]: formatNumber(
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]:
|
||||
getPerformancePenalty(performanceScore),
|
||||
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
overstakedAmount,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: formatNumber(
|
||||
toBigNum(pendingStake, decimals),
|
||||
2
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
}, [
|
||||
data,
|
||||
decimals,
|
||||
@@ -158,6 +174,12 @@ export const StandbyPendingValidatorsTable = ({
|
||||
const StandbyPendingTable = forwardRef<AgGridReact>((_, gridRef) => {
|
||||
const colDefs = useMemo<ColDef[]>(
|
||||
() => [
|
||||
{
|
||||
field: ValidatorFields.RANKING_INDEX,
|
||||
headerName: '#',
|
||||
width: 60,
|
||||
pinned: 'left',
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.VALIDATOR,
|
||||
headerName: t(ValidatorFields.VALIDATOR).toString(),
|
||||
|
||||
@@ -59,11 +59,17 @@ export const getOverstakedAmount = (
|
||||
export const getOverstakingPenalty = (
|
||||
overstakedAmount: BigNumber,
|
||||
stakedOnNode: string
|
||||
) =>
|
||||
formatNumberPercentage(
|
||||
) => {
|
||||
// avoid division by zero
|
||||
if (new BigNumber(stakedOnNode).isZero() || overstakedAmount.isZero()) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
return formatNumberPercentage(
|
||||
overstakedAmount.dividedBy(new BigNumber(stakedOnNode)).times(100),
|
||||
2
|
||||
);
|
||||
};
|
||||
|
||||
export const getTotalPenalties = (
|
||||
rawValidatorScore: string | null | undefined,
|
||||
|
||||
@@ -3,6 +3,8 @@ import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { marketsQuery } from '@vegaprotocol/mock';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const dialogCloseBtn = 'dialog-close';
|
||||
|
||||
describe('markets table', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.clearLocalStorage().then(() => {
|
||||
@@ -147,7 +149,7 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
});
|
||||
cy.visit('#/markets/market-0');
|
||||
cy.url().should('contain', 'market-0');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId(dialogCloseBtn).click();
|
||||
cy.getByTestId('item-value').contains('Opening auction').realHover();
|
||||
cy.getByTestId('opening-auction-sub-status').should(
|
||||
'contain.text',
|
||||
@@ -171,7 +173,8 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
});
|
||||
|
||||
function openMarketDropDown() {
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId(dialogCloseBtn).should('be.visible');
|
||||
cy.getByTestId(dialogCloseBtn).click();
|
||||
cy.getByTestId('popover-trigger').click();
|
||||
cy.contains('Loading market data...').should('not.exist');
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ describe('Desktop view', { tags: '@smoke' }, () => {
|
||||
cy.wrap(element)
|
||||
.get('span.absolute.md\\:h-1.w-full')
|
||||
.should('exist');
|
||||
cy.contains('No market').should('not.exist');
|
||||
cy.location('hash').should('equal', hashes[index]);
|
||||
});
|
||||
});
|
||||
@@ -68,6 +69,7 @@ describe('Mobile view', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('button-menu-drawer').click();
|
||||
cy.getByTestId('menu-drawer').within((el) => {
|
||||
cy.wrap(el).getByTestId('Trading').click();
|
||||
cy.contains('No market').should('not.exist');
|
||||
cy.location('hash').should('equal', '#/markets/market-1');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -96,7 +96,15 @@ export const MarketPage = () => {
|
||||
|
||||
const tradeView = useMemo(() => {
|
||||
if (w > 960) {
|
||||
return <TradeGrid market={data} onSelect={onSelect} />;
|
||||
return (
|
||||
<TradeGrid
|
||||
market={data}
|
||||
onSelect={onSelect}
|
||||
pinnedAsset={
|
||||
data?.tradableInstrument.instrument.product.settlementAsset
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<TradePanels
|
||||
|
||||
@@ -28,6 +28,7 @@ import { NO_MARKET } from './constants';
|
||||
import { LiquidityContainer } from '../liquidity/liquidity';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||
|
||||
type MarketDependantView =
|
||||
| typeof CandlesChartContainer
|
||||
@@ -65,14 +66,17 @@ type TradingView = keyof typeof TradingViews;
|
||||
interface TradeGridProps {
|
||||
market: Market | null;
|
||||
onSelect: (marketId: string) => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
const MainGrid = ({
|
||||
marketId,
|
||||
onSelect,
|
||||
pinnedAsset,
|
||||
}: {
|
||||
marketId: string;
|
||||
onSelect?: (marketId: string) => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const onMarketClick = (marketId: string) => {
|
||||
@@ -175,7 +179,7 @@ const MainGrid = ({
|
||||
</Tab>
|
||||
<Tab id="accounts" name={t('Collateral')}>
|
||||
<VegaWalletContainer>
|
||||
<TradingViews.Collateral />
|
||||
<TradingViews.Collateral pinnedAsset={pinnedAsset} />
|
||||
</VegaWalletContainer>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -186,11 +190,19 @@ const MainGrid = ({
|
||||
};
|
||||
const MainGridWrapped = memo(MainGrid);
|
||||
|
||||
export const TradeGrid = ({ market, onSelect }: TradeGridProps) => {
|
||||
export const TradeGrid = ({
|
||||
market,
|
||||
onSelect,
|
||||
pinnedAsset,
|
||||
}: TradeGridProps) => {
|
||||
return (
|
||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||
<TradeMarketHeader market={market} onSelect={onSelect} />
|
||||
<MainGridWrapped marketId={market?.id || ''} onSelect={onSelect} />
|
||||
<MainGridWrapped
|
||||
marketId={market?.id || ''}
|
||||
onSelect={onSelect}
|
||||
pinnedAsset={pinnedAsset}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -214,12 +226,14 @@ interface TradePanelsProps {
|
||||
onSelect: (marketId: string) => void;
|
||||
onMarketClick?: (marketId: string) => void;
|
||||
onClickCollateral: () => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
export const TradePanels = ({
|
||||
market,
|
||||
onSelect,
|
||||
onClickCollateral,
|
||||
pinnedAsset,
|
||||
}: TradePanelsProps) => {
|
||||
const [view, setView] = useState<TradingView>('Candles');
|
||||
const renderView = () => {
|
||||
@@ -228,6 +242,7 @@ export const TradePanels = ({
|
||||
onSelect: (marketId: string) => void;
|
||||
onMarketClick?: (marketId: string) => void;
|
||||
onClickCollateral: () => void;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}>(TradingViews[view]);
|
||||
|
||||
if (!Component) {
|
||||
@@ -241,6 +256,7 @@ export const TradePanels = ({
|
||||
marketId={market?.id}
|
||||
onSelect={onSelect}
|
||||
onClickCollateral={onClickCollateral}
|
||||
pinnedAsset={pinnedAsset}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
|
||||
export const DepositsContainer = () => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: depositsProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
@@ -27,6 +27,7 @@ export const DepositsContainer = () => {
|
||||
error={error}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
noDataMessage={t('No deposits')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
|
||||
export const WithdrawalsContainer = () => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: withdrawalProvider,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
@@ -33,6 +33,7 @@ export const WithdrawalsContainer = () => {
|
||||
error={error}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
noDataMessage={t('No withdrawals')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,10 +5,15 @@ import { useWithdrawalDialog } from '@vegaprotocol/withdraws';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||
import { AccountManager, useTransferDialog } from '@vegaprotocol/accounts';
|
||||
import { useDepositDialog } from '@vegaprotocol/deposits';
|
||||
|
||||
export const AccountsContainer = () => {
|
||||
export const AccountsContainer = ({
|
||||
pinnedAsset,
|
||||
}: {
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
const openWithdrawalDialog = useWithdrawalDialog((store) => store.open);
|
||||
@@ -39,6 +44,7 @@ export const AccountsContainer = () => {
|
||||
onClickWithdraw={openWithdrawalDialog}
|
||||
onClickDeposit={openDepositDialog}
|
||||
isReadOnly={isReadOnly}
|
||||
pinnedAsset={pinnedAsset}
|
||||
/>
|
||||
</div>
|
||||
{!isReadOnly && (
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useRef, useMemo, memo } from 'react';
|
||||
import type { AccountFields } from './accounts-data-provider';
|
||||
import { aggregatedAccountsDataProvider } from './accounts-data-provider';
|
||||
import type { PinnedAsset } from './accounts-table';
|
||||
import { AccountTable } from './accounts-table';
|
||||
|
||||
interface AccountManagerProps {
|
||||
@@ -12,6 +13,7 @@ interface AccountManagerProps {
|
||||
onClickWithdraw?: (assetId?: string) => void;
|
||||
onClickDeposit?: (assetId?: string) => void;
|
||||
isReadOnly: boolean;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
export const AccountManager = ({
|
||||
@@ -20,11 +22,15 @@ export const AccountManager = ({
|
||||
onClickDeposit,
|
||||
partyId,
|
||||
isReadOnly,
|
||||
pinnedAsset,
|
||||
}: AccountManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
|
||||
const { data, loading, error } = useDataProvider<AccountFields[], never>({
|
||||
const { data, loading, error, reload } = useDataProvider<
|
||||
AccountFields[],
|
||||
never
|
||||
>({
|
||||
dataProvider: aggregatedAccountsDataProvider,
|
||||
variables,
|
||||
});
|
||||
@@ -32,12 +38,13 @@ export const AccountManager = ({
|
||||
<div className="relative h-full">
|
||||
<AccountTable
|
||||
ref={gridRef}
|
||||
rowData={data}
|
||||
rowData={error ? [] : data}
|
||||
onClickAsset={onClickAsset}
|
||||
onClickDeposit={onClickDeposit}
|
||||
onClickWithdraw={onClickWithdraw}
|
||||
isReadOnly={isReadOnly}
|
||||
noRowsOverlayComponent={() => null}
|
||||
pinnedAsset={pinnedAsset}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@@ -45,7 +52,8 @@ export const AccountManager = ({
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
error={error}
|
||||
loading={loading}
|
||||
noDataMessage={t('No accounts')}
|
||||
noDataMessage={pinnedAsset ? ' ' : t('No accounts')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -72,52 +72,74 @@ describe('AccountsTable', () => {
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
});
|
||||
const rows = await screen.findAllByRole('row');
|
||||
expect(rows.length).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
it('should get correct account data', () => {
|
||||
const result = getAccountData([singleRow]);
|
||||
const expected = [
|
||||
{
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
decimals: 5,
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
},
|
||||
available: '0',
|
||||
balance: '0',
|
||||
breakdown: [
|
||||
{
|
||||
__typename: 'AccountBalance',
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
it('should add first asset as pinned', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<AccountTable
|
||||
rowData={singleRowData}
|
||||
onClickAsset={() => null}
|
||||
isReadOnly={false}
|
||||
pinnedAsset={{
|
||||
decimals: 5,
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
},
|
||||
available: '0',
|
||||
balance: '125600000',
|
||||
deposited: '125600000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: 'BTCUSD Monthly (30 Jun 2022)',
|
||||
name: 'tBTC',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const rows = await screen.findAllByRole('row');
|
||||
expect(rows.length).toBe(9);
|
||||
});
|
||||
|
||||
it('should get correct account data', () => {
|
||||
const result = getAccountData([singleRow]);
|
||||
const expected = [
|
||||
{
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
decimals: 5,
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
},
|
||||
available: '0',
|
||||
balance: '0',
|
||||
breakdown: [
|
||||
{
|
||||
__typename: 'AccountBalance',
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
decimals: 5,
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
},
|
||||
available: '0',
|
||||
balance: '125600000',
|
||||
deposited: '125600000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: 'BTCUSD Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
},
|
||||
type: 'ACCOUNT_TYPE_MARGIN',
|
||||
used: '125600000',
|
||||
},
|
||||
type: 'ACCOUNT_TYPE_MARGIN',
|
||||
used: '125600000',
|
||||
},
|
||||
],
|
||||
deposited: '125600000',
|
||||
type: 'ACCOUNT_TYPE_GENERAL',
|
||||
used: '125600000',
|
||||
},
|
||||
];
|
||||
expect(result).toEqual(expected);
|
||||
],
|
||||
deposited: '125600000',
|
||||
type: 'ACCOUNT_TYPE_GENERAL',
|
||||
used: '125600000',
|
||||
},
|
||||
];
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { forwardRef, useState } from 'react';
|
||||
import { forwardRef, useMemo, useState } from 'react';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
isNumeric,
|
||||
@@ -14,6 +14,8 @@ import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
|
||||
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
||||
import BreakdownTable from './breakdown-table';
|
||||
import type { AccountFields } from './accounts-data-provider';
|
||||
import type { Asset } from '@vegaprotocol/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
||||
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
|
||||
@@ -23,6 +25,8 @@ export interface Datasource extends IDatasource {
|
||||
getRows(params: GetRowsParams): void;
|
||||
}
|
||||
|
||||
export type PinnedAsset = Pick<Asset, 'symbol' | 'name' | 'id' | 'decimals'>;
|
||||
|
||||
export interface AccountTableProps extends AgGridReactProps {
|
||||
rowData?: AccountFields[] | null;
|
||||
datasource?: Datasource;
|
||||
@@ -30,12 +34,33 @@ export interface AccountTableProps extends AgGridReactProps {
|
||||
onClickWithdraw?: (assetId: string) => void;
|
||||
onClickDeposit?: (assetId: string) => void;
|
||||
isReadOnly: boolean;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
|
||||
const [openBreakdown, setOpenBreakdown] = useState(false);
|
||||
const [breakdown, setBreakdown] = useState<AccountFields[] | null>(null);
|
||||
const pinnedAssetId = props.pinnedAsset?.id;
|
||||
|
||||
const pinnedAssetRow = useMemo(() => {
|
||||
const currentPinnedAssetRow = props.rowData?.find(
|
||||
(row) => row.asset.id === pinnedAssetId
|
||||
);
|
||||
if (!currentPinnedAssetRow) {
|
||||
if (props.pinnedAsset) {
|
||||
return {
|
||||
asset: props.pinnedAsset,
|
||||
available: '0',
|
||||
used: '0',
|
||||
deposited: '0',
|
||||
balance: '0',
|
||||
};
|
||||
}
|
||||
}
|
||||
return currentPinnedAssetRow;
|
||||
}, [pinnedAssetId, props.pinnedAsset, props.rowData]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AgGrid
|
||||
@@ -51,6 +76,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
sortable: true,
|
||||
}}
|
||||
{...props}
|
||||
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
|
||||
>
|
||||
<AgGridColumn
|
||||
headerName={t('Asset')}
|
||||
@@ -138,37 +164,55 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
cellRenderer={({
|
||||
data,
|
||||
}: VegaICellRendererParams<AccountFields>) => {
|
||||
return data ? (
|
||||
<>
|
||||
<ButtonLink
|
||||
data-testid="breakdown"
|
||||
onClick={() => {
|
||||
setOpenBreakdown(!openBreakdown);
|
||||
setBreakdown(data.breakdown || null);
|
||||
}}
|
||||
>
|
||||
{t('Breakdown')}
|
||||
</ButtonLink>
|
||||
<span className="mx-1" />
|
||||
<ButtonLink
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
{t('Deposit')}
|
||||
</ButtonLink>
|
||||
<span className="mx-1" />
|
||||
<ButtonLink
|
||||
data-testid="withdraw"
|
||||
onClick={() =>
|
||||
onClickWithdraw && onClickWithdraw(data.asset.id)
|
||||
}
|
||||
>
|
||||
{t('Withdraw')}
|
||||
</ButtonLink>
|
||||
</>
|
||||
) : null;
|
||||
if (!data) return null;
|
||||
else {
|
||||
if (
|
||||
data.asset.id === pinnedAssetId &&
|
||||
new BigNumber(data.deposited).isLessThanOrEqualTo(0)
|
||||
) {
|
||||
return (
|
||||
<ButtonLink
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
{t('Deposit to trade')}
|
||||
</ButtonLink>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<ButtonLink
|
||||
data-testid="breakdown"
|
||||
onClick={() => {
|
||||
setOpenBreakdown(!openBreakdown);
|
||||
setBreakdown(data.breakdown || null);
|
||||
}}
|
||||
>
|
||||
{t('Breakdown')}
|
||||
</ButtonLink>
|
||||
<span className="mx-1" />
|
||||
<ButtonLink
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
{t('Deposit')}
|
||||
</ButtonLink>
|
||||
<span className="mx-1" />
|
||||
<ButtonLink
|
||||
data-testid="withdraw"
|
||||
onClick={() =>
|
||||
onClickWithdraw && onClickWithdraw(data.asset.id)
|
||||
}
|
||||
>
|
||||
{t('Withdraw')}
|
||||
</ButtonLink>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -25,6 +25,7 @@ export const DealTicketContainer = ({
|
||||
data: marketData,
|
||||
error: marketDataError,
|
||||
loading: marketDataLoading,
|
||||
reload,
|
||||
} = useThrottledDataProvider(
|
||||
{
|
||||
dataProvider: marketDataProvider,
|
||||
@@ -39,6 +40,7 @@ export const DealTicketContainer = ({
|
||||
data={market && marketData}
|
||||
loading={marketLoading || marketDataLoading}
|
||||
error={marketError || marketDataError}
|
||||
reload={reload}
|
||||
>
|
||||
{market && marketData ? (
|
||||
<DealTicket
|
||||
|
||||
@@ -19,7 +19,7 @@ export const FillsManager = ({
|
||||
}: FillsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const scrolledToTop = useRef(true);
|
||||
const { data, error, loading, addNewRows, getRows } = useFillsList({
|
||||
const { data, error, loading, addNewRows, getRows, reload } = useFillsList({
|
||||
partyId,
|
||||
marketId,
|
||||
gridRef,
|
||||
@@ -55,6 +55,7 @@ export const FillsManager = ({
|
||||
data={data}
|
||||
noDataMessage={t('No fills')}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -78,7 +78,7 @@ export const useFillsList = ({
|
||||
|
||||
const variables = useMemo(() => ({ partyId, marketId }), [partyId, marketId]);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider<
|
||||
const { data, error, loading, load, totalCount, reload } = useDataProvider<
|
||||
(TradeEdge | null)[],
|
||||
Trade[]
|
||||
>({
|
||||
@@ -95,5 +95,5 @@ export const useFillsList = ({
|
||||
load,
|
||||
newRows
|
||||
);
|
||||
return { data, error, loading, addNewRows, getRows };
|
||||
return { data, error, loading, addNewRows, getRows, reload };
|
||||
};
|
||||
|
||||
@@ -29,14 +29,19 @@ export const ProposalsList = () => {
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
};
|
||||
}, []);
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: proposalsListDataProvider,
|
||||
variables,
|
||||
});
|
||||
const filteredData = getNewMarketProposals(data || []);
|
||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={filteredData}>
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={filteredData}
|
||||
reload={reload}
|
||||
>
|
||||
<AgGrid
|
||||
ref={gridRef}
|
||||
domLayout="autoHeight"
|
||||
|
||||
@@ -35,6 +35,7 @@ query LedgerEntries(
|
||||
node {
|
||||
...LedgerEntry
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
startCursor
|
||||
|
||||
+2
-1
@@ -14,7 +14,7 @@ export type LedgerEntriesQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', node: { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, toAccountType?: Types.AccountType | null, toAccountMarketId?: string | null, toAccountPartyId?: string | null, toAccountBalance: string, fromAccountType?: Types.AccountType | null, fromAccountMarketId?: string | null, fromAccountPartyId?: string | null, fromAccountBalance: string } } | null>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
|
||||
export type LedgerEntriesQuery = { __typename?: 'Query', ledgerEntries: { __typename?: 'AggregatedLedgerEntriesConnection', edges: Array<{ __typename?: 'AggregatedLedgerEntriesEdge', cursor: string, node: { __typename?: 'AggregatedLedgerEntry', vegaTime: any, quantity: string, assetId?: string | null, transferType?: Types.TransferType | null, toAccountType?: Types.AccountType | null, toAccountMarketId?: string | null, toAccountPartyId?: string | null, toAccountBalance: string, fromAccountType?: Types.AccountType | null, fromAccountMarketId?: string | null, fromAccountPartyId?: string | null, fromAccountBalance: string } } | null>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
|
||||
|
||||
export const LedgerEntryFragmentDoc = gql`
|
||||
fragment LedgerEntry on AggregatedLedgerEntry {
|
||||
@@ -43,6 +43,7 @@ export const LedgerEntriesDocument = gql`
|
||||
node {
|
||||
...LedgerEntry
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
startCursor
|
||||
|
||||
@@ -128,7 +128,11 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
|
||||
const marketReceiver = markets.find(
|
||||
(market: Market) => market.id === entry.toAccountMarketId
|
||||
);
|
||||
return { node: { ...entry, asset, marketSender, marketReceiver } };
|
||||
const cursor = edge?.cursor;
|
||||
return {
|
||||
node: { ...entry, asset, marketSender, marketReceiver },
|
||||
cursor,
|
||||
};
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -172,14 +176,13 @@ export const useLedgerEntriesDataProvider = ({
|
||||
data: (AggregatedLedgerEntriesEdge | null)[] | null;
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
dataRef.current = data;
|
||||
totalCountRef.current = totalCount;
|
||||
return updateGridData(dataRef, data, gridRef);
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
||||
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||
dataProvider: ledgerEntriesProvider,
|
||||
update,
|
||||
insert,
|
||||
@@ -193,5 +196,5 @@ export const useLedgerEntriesDataProvider = ({
|
||||
totalCountRef,
|
||||
load
|
||||
);
|
||||
return { loading, error, data, getRows };
|
||||
return { loading, error, data, getRows, reload };
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ export const ledgerEntriesQuery = (
|
||||
edges: ledgerEntries.map((node) => ({
|
||||
__typename: 'AggregatedLedgerEntriesEdge',
|
||||
node,
|
||||
cursor: 'cursor-1',
|
||||
})),
|
||||
pageInfo: {
|
||||
startCursor:
|
||||
|
||||
@@ -21,11 +21,12 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [filter, setFilter] = useState<Filter | undefined>();
|
||||
|
||||
const { data, error, loading, getRows } = useLedgerEntriesDataProvider({
|
||||
partyId,
|
||||
filter,
|
||||
gridRef,
|
||||
});
|
||||
const { data, error, loading, getRows, reload } =
|
||||
useLedgerEntriesDataProvider({
|
||||
partyId,
|
||||
filter,
|
||||
gridRef,
|
||||
});
|
||||
|
||||
const onFilterChanged = useCallback(
|
||||
(event: FilterChangedEvent) => {
|
||||
@@ -38,7 +39,11 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
||||
},
|
||||
[filter]
|
||||
);
|
||||
|
||||
const getRowId = useCallback(
|
||||
({ data }: { data: Types.AggregatedLedgerEntry }) =>
|
||||
`${data.vegaTime}-${data.fromAccountPartyId}-${data.toAccountPartyId}`,
|
||||
[]
|
||||
);
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<LedgerTable
|
||||
@@ -46,6 +51,7 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
||||
rowModelType="infinite"
|
||||
datasource={{ getRows }}
|
||||
onFilterChanged={onFilterChanged}
|
||||
getRowId={getRowId}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@@ -54,6 +60,7 @@ export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
||||
data={data}
|
||||
noDataMessage={t('No entries')}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +85,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
||||
[marketId, updateOrderbookData]
|
||||
);
|
||||
|
||||
const { data, error, loading, flush } = useDataProvider({
|
||||
const { data, error, loading, flush, reload } = useDataProvider({
|
||||
dataProvider: marketDepthProvider,
|
||||
update,
|
||||
variables,
|
||||
@@ -156,6 +156,7 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
||||
loading={loading || marketDataLoading || marketLoading}
|
||||
error={error || marketDataError || marketError}
|
||||
data={data}
|
||||
reload={reload}
|
||||
>
|
||||
<Orderbook
|
||||
{...orderbookData}
|
||||
|
||||
@@ -69,14 +69,14 @@ export const MarketInfoContainer = ({
|
||||
[marketId, yTimestamp]
|
||||
);
|
||||
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: marketInfoDataProvider,
|
||||
skipUpdates: true,
|
||||
variables,
|
||||
});
|
||||
|
||||
return (
|
||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
||||
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
||||
{data && data.market ? (
|
||||
<Info market={data.market} onSelect={(id) => onSelect?.(id)} />
|
||||
) : (
|
||||
|
||||
@@ -10,7 +10,7 @@ interface MarketsContainerProps {
|
||||
}
|
||||
|
||||
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
const { data, error, loading } = useDataProvider({
|
||||
const { data, error, loading, reload } = useDataProvider({
|
||||
dataProvider,
|
||||
skipUpdates: true,
|
||||
});
|
||||
@@ -18,7 +18,8 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<MarketListTable
|
||||
rowData={data}
|
||||
rowData={error ? [] : data}
|
||||
noRowsOverlayComponent={() => null}
|
||||
onRowClicked={(rowEvent: RowClickedEvent) => {
|
||||
const { data, event } = rowEvent;
|
||||
// filters out clicks on the symbol column because it should display asset details
|
||||
@@ -36,6 +37,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('No markets')}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -155,6 +155,7 @@ export const ordersProvider = makeDataProvider({
|
||||
append,
|
||||
first: 100,
|
||||
},
|
||||
additionalContext: { isEnlargedTimeout: true },
|
||||
});
|
||||
|
||||
export const ordersWithMarketProvider = makeDerivedDataProvider<
|
||||
|
||||
@@ -83,14 +83,15 @@ export const OrderListManager = ({
|
||||
const create = useVegaTransactionStore((state) => state.create);
|
||||
const hasActiveOrder = useHasActiveOrder(marketId);
|
||||
|
||||
const { data, error, loading, addNewRows, getRows } = useOrderListData({
|
||||
partyId,
|
||||
marketId,
|
||||
sort,
|
||||
filter,
|
||||
gridRef,
|
||||
scrolledToTop,
|
||||
});
|
||||
const { data, error, loading, addNewRows, getRows, reload } =
|
||||
useOrderListData({
|
||||
partyId,
|
||||
marketId,
|
||||
sort,
|
||||
filter,
|
||||
gridRef,
|
||||
scrolledToTop,
|
||||
});
|
||||
|
||||
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
||||
if (event.top === 0) {
|
||||
@@ -128,7 +129,7 @@ export const OrderListManager = ({
|
||||
return (
|
||||
<>
|
||||
<div className="h-full relative grid grid-rows-[1fr,min-content]">
|
||||
<div className="h-full relative">
|
||||
<div className="relative">
|
||||
<OrderListTable
|
||||
ref={gridRef}
|
||||
rowModelType="infinite"
|
||||
@@ -149,6 +150,8 @@ export const OrderListManager = ({
|
||||
setEditOrder={setEditOrder}
|
||||
onMarketClick={onMarketClick}
|
||||
isReadOnly={isReadOnly}
|
||||
hasActiveOrder={hasActiveOrder}
|
||||
blockLoadDebounceMillis={100}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@@ -157,6 +160,7 @@ export const OrderListManager = ({
|
||||
data={data}
|
||||
noDataMessage={t('No orders')}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -119,7 +119,7 @@ export const useOrderListData = ({
|
||||
[gridRef]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
||||
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||
dataProvider: ordersWithMarketProvider,
|
||||
update,
|
||||
insert,
|
||||
@@ -133,5 +133,5 @@ export const useOrderListData = ({
|
||||
load,
|
||||
newRows
|
||||
);
|
||||
return { loading, error, data, addNewRows, getRows };
|
||||
return { loading, error, data, addNewRows, getRows, reload };
|
||||
};
|
||||
|
||||
@@ -33,20 +33,24 @@ export type OrderListTableProps = OrderListProps & {
|
||||
setEditOrder: (order: Order) => void;
|
||||
onMarketClick?: (marketId: string) => void;
|
||||
isReadOnly: boolean;
|
||||
hasActiveOrder?: boolean;
|
||||
};
|
||||
|
||||
export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
|
||||
({ cancel, setEditOrder, onMarketClick, ...props }, ref) => {
|
||||
({ cancel, setEditOrder, onMarketClick, hasActiveOrder, ...props }, ref) => {
|
||||
return (
|
||||
<AgGrid
|
||||
ref={ref}
|
||||
overlayNoRowsTemplate="No orders"
|
||||
overlayNoRowsTemplate={t('No orders')}
|
||||
defaultColDef={{
|
||||
flex: 1,
|
||||
resizable: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
}}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: hasActiveOrder ? 'calc(100% - 46px)' : '100%',
|
||||
}}
|
||||
getRowId={({ data }) => data.id}
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -18,7 +18,11 @@ export const PositionsManager = ({
|
||||
isReadOnly,
|
||||
}: PositionsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { data, error, loading } = usePositionsData(partyId, gridRef, true);
|
||||
const { data, error, loading, reload } = usePositionsData(
|
||||
partyId,
|
||||
gridRef,
|
||||
true
|
||||
);
|
||||
const create = useVegaTransactionStore((store) => store.create);
|
||||
const onClose = ({
|
||||
marketId,
|
||||
@@ -51,7 +55,7 @@ export const PositionsManager = ({
|
||||
return (
|
||||
<div className="h-full relative">
|
||||
<PositionsTable
|
||||
rowData={data}
|
||||
rowData={error ? [] : data}
|
||||
ref={gridRef}
|
||||
onMarketClick={onMarketClick}
|
||||
onClose={onClose}
|
||||
@@ -65,6 +69,7 @@ export const PositionsManager = ({
|
||||
data={data}
|
||||
noDataMessage={t('No positions')}
|
||||
noDataCondition={(data) => !(data && data.length)}
|
||||
reload={reload}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,7 +25,7 @@ export const usePositionsData = (
|
||||
},
|
||||
[gridRef, clientSideModel]
|
||||
);
|
||||
const { data, error, loading } = useDataProvider({
|
||||
const { data, error, loading, reload } = useDataProvider({
|
||||
dataProvider: positionsMetricsProvider,
|
||||
update,
|
||||
variables,
|
||||
@@ -45,5 +45,6 @@ export const usePositionsData = (
|
||||
error,
|
||||
loading,
|
||||
getRows,
|
||||
reload,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -80,6 +80,7 @@ export const useDataProvider = <
|
||||
}
|
||||
}, []);
|
||||
const reload = useCallback((force = false) => {
|
||||
initialized.current = false;
|
||||
if (reloadRef.current) {
|
||||
reloadRef.current(force);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const getLastRow = (
|
||||
lastRow = totalCount;
|
||||
}
|
||||
} else if (blockLength < endRow - startRow) {
|
||||
lastRow = blockLength;
|
||||
lastRow = blockLength + startRow;
|
||||
}
|
||||
return lastRow;
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
[]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
||||
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||
dataProvider: tradesWithMarketProvider,
|
||||
update,
|
||||
insert,
|
||||
@@ -107,7 +107,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<AsyncRenderer loading={loading} error={error} data={data} reload={reload}>
|
||||
<TradesTable
|
||||
ref={gridRef}
|
||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { render, act, screen } from '@testing-library/react';
|
||||
import { AsyncRenderer } from './async-renderer';
|
||||
|
||||
describe('AsyncRenderer', () => {
|
||||
it('timeout error should render button', async () => {
|
||||
const reload = jest.fn();
|
||||
await act(() => {
|
||||
render(
|
||||
<AsyncRenderer
|
||||
reload={reload}
|
||||
error={new Error('Timeout exceeded')}
|
||||
loading={false}
|
||||
data={undefined}
|
||||
/>
|
||||
);
|
||||
});
|
||||
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||
await act(() => {
|
||||
screen.getByRole('button').click();
|
||||
});
|
||||
expect(reload).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Splash } from '../splash';
|
||||
import type { ReactNode } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Button } from '../button';
|
||||
|
||||
interface AsyncRendererProps<T> {
|
||||
loading: boolean;
|
||||
@@ -12,6 +13,7 @@ interface AsyncRendererProps<T> {
|
||||
children?: ReactNode | null;
|
||||
render?: (data: T) => ReactNode;
|
||||
noDataCondition?(data?: T): boolean;
|
||||
reload?: () => void;
|
||||
}
|
||||
|
||||
export function AsyncRenderer<T = object>({
|
||||
@@ -24,15 +26,30 @@ export function AsyncRenderer<T = object>({
|
||||
noDataCondition,
|
||||
children,
|
||||
render,
|
||||
reload,
|
||||
}: AsyncRendererProps<T>) {
|
||||
if (error) {
|
||||
if (!data) {
|
||||
return (
|
||||
<Splash>
|
||||
{errorMessage
|
||||
? errorMessage
|
||||
: t(`Something went wrong: ${error.message}`)}
|
||||
</Splash>
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="h-12 flex flex-col items-center">
|
||||
<Splash>
|
||||
{errorMessage
|
||||
? errorMessage
|
||||
: t(`Something went wrong: ${error.message}`)}
|
||||
</Splash>
|
||||
{reload && error.message === 'Timeout exceeded' && (
|
||||
<Button
|
||||
size="sm"
|
||||
className="pointer-events-auto"
|
||||
type="button"
|
||||
onClick={reload}
|
||||
>
|
||||
{t('Try again')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ export const Checkbox = ({
|
||||
) : (
|
||||
<Icon
|
||||
name="tick"
|
||||
className="relative w-[10px] h-[10px] text-white dark:text-black"
|
||||
size={3}
|
||||
className="relative text-white dark:text-black"
|
||||
/>
|
||||
)}
|
||||
</CheckboxPrimitive.CheckboxIndicator>
|
||||
|
||||
@@ -53,7 +53,7 @@ export const NavDropdownMenuContent = forwardRef<
|
||||
<DropdownMenuPrimitive.Content
|
||||
{...contentProps}
|
||||
ref={forwardedRef}
|
||||
className="bg-vega-dark-100 mt-4 py-4 rounded-xl border border-vega-dark-200 text-white"
|
||||
className="z-10 bg-vega-dark-100 mt-4 py-4 rounded-xl border border-vega-dark-200 text-white"
|
||||
align="start"
|
||||
sideOffset={10}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user