Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explore apps statistics component - Closes #4358 #4370

Merged
merged 26 commits into from
Jul 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
["@update", "./src/modules/update"],
["@wallet", "./src/modules/wallet/"],
["@account", "./src/modules/account/"],
["@blockchainApplication", "./src/modules/blockchainApplication/"],
["@legacy", "./src/modules/legacy/"],
["@message", "./src/modules/message/"],
["@auth", "./src/modules/auth/"],
Expand Down
1 change: 1 addition & 0 deletions jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@fixtures/*": ["./tests/fixtures"],
"@theme/*": ["./src/theme/*"],
"@account/*": ["./src/modules/account/*"],
"@blockchainApplication/*": ["./src/modules/blockchainApplication/*"],
"@block/*": ["./src/modules/block/*"],
"@bookmark/*": ["./src/modules/bookmark/*"],
"@search/*": ["./src/modules/search/*"],
Expand Down
2 changes: 1 addition & 1 deletion setup/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const config = {
'@tests': resolve('./tests'),
'@theme': resolve('./src/theme'),
'@account': resolve('./src/modules/account'),
'@blockchainApplication': resolve('./src/modules/blockchainApplication'),
'@block': resolve('./src/modules/block'),
'@bookmark': resolve('./src/modules/bookmark'),
'@search': resolve('./src/modules/search'),
Expand All @@ -25,7 +26,6 @@ const config = {
'@settings': resolve('./packages/settings'),
'@token': resolve('./src/modules/token'),
'@transaction': resolve('./src/modules/transaction'),
'@blockchainApplication': resolve('./src/modules/blockchainApplication'),
'@update': resolve('./src/modules/update'),
'@views': resolve('./packages/views'),
'@packages': resolve('./packages'),
Expand Down
47 changes: 47 additions & 0 deletions setup/react/assets/images/icons/stacked-token.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 86 additions & 0 deletions setup/react/assets/images/icons/total-supply-token.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"Account username": "Account username",
"Account was removed": "Account was removed",
"Accounts": "Accounts",
"Active": "Active",
"Active delegates": "Active delegates",
"Active delegates are select to generate blocks every round.": "Active delegates are select to generate blocks every round.",
"Add": "Add",
Expand All @@ -42,6 +43,7 @@
"Amount": "Amount",
"Amount can't be negative.": "Amount can't be negative.",
"Amount can't be zero.": "Amount can't be zero.",
"Amount of LSK tokens staked by validators and nominators for DPoS governance": "Amount of LSK tokens staked by validators and nominators for DPoS governance",
"Amount of transaction": "Amount of transaction",
"Amount per transaction (LSK)": "Amount per transaction (LSK)",
"Amount range": "Amount range",
Expand Down Expand Up @@ -389,6 +391,7 @@
"Register delegate": "Register delegate",
"Register multisignature account": "Register multisignature account",
"Register multisignature group": "Register multisignature group",
"Registered": "Registered",
"Registered delegates": "Registered delegates",
"Registrant": "Registrant",
"Reject": "Reject",
Expand Down Expand Up @@ -472,14 +475,17 @@
"Slot status": "Slot status",
"Something went wrong. Please try again": "Something went wrong. Please try again",
"Sorry, we couldn’t find the page you were looking for. We suggest that you return to the main dashboard.": "Sorry, we couldn’t find the page you were looking for. We suggest that you return to the main dashboard.",
"Staked": "Staked",
"Standby delegates": "Standby delegates",
"Standby delegates can be chosen at random for one of two slots per round for generating a block.": "Standby delegates can be chosen at random for one of two slots per round for generating a block.",
"Statistics": "Statistics",
"Status": "Status",
"Stay Informed": "Stay Informed",
"Store this document in a safe place.": "Store this document in a safe place.",
"Submitting the transaction": "Submitting the transaction",
"Supply": "Supply",
"Switch account": "Switch account",
"Terminated": "Terminated",
"Terms of Use": "Terms of Use",
"Testnet": "Testnet",
"The aggregated LSK volume transferred over the selected time period.": "The aggregated LSK volume transferred over the selected time period.",
Expand Down Expand Up @@ -530,6 +536,8 @@
"To recover, you can try to reload the page, by clicking the button below. If the problem persists, report the error via email.": "To recover, you can try to reload the page, by clicking the button below. If the problem persists, report the error via email.",
"To verify the integrity of a signed message use the \"Verify message\" tool in the sidebar.": "To verify the integrity of a signed message use the \"Verify message\" tool in the sidebar.",
"Toggle Full Screen": "Toggle Full Screen",
"Total LSK tokens in circulation": "Total LSK tokens in circulation",
"Total Supply": "Total Supply",
"Total burnt": "Total burnt",
"Total fee": "Total fee",
"Total forged": "Total forged",
Expand Down
27 changes: 27 additions & 0 deletions src/modules/blockchainApplication/explore/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* istanbul ignore file */
import http from 'src/utils/api/http';
import { HTTP_PREFIX } from 'src/const/httpCodes';

const httpPaths = {
blockchainAppsStatistics: `${HTTP_PREFIX}/blockchain/apps/statistics`,
};

/**
* Retrieves sidechains statistics information
*
* @param {Object} data
* @param {Object} data.network The network config from the Redux store
*
* @returns {Promise}
*/
// eslint-disable-next-line import/prefer-default-export
export const getStatistics = ({
network,
params = {},
baseUrl,
}) => http({
path: httpPaths.blockchainAppsStatistics,
network,
params,
baseUrl,
});
Comment on lines +1 to +27
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs a unit test

35 changes: 35 additions & 0 deletions src/modules/blockchainApplication/explore/api/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { getState } from '@fixtures/transactions';
import http from 'src/utils/api/http';
import { getStatistics } from '.';

jest.mock('src/utils/api/http', () =>
jest.fn().mockImplementation(() => Promise.resolve({
data: {
registered: 2503,
active: 2328,
terminated: 35,
totalSupplyLSK: '5000000',
stakedLSK: '3000000',
inflationRate: '4.50',
},
})));

const baseUrl = 'http://custom-base-url.com/';
const { network } = getState();

describe('get blockchain application statistics', () => {
it('Should call http with given params', () => {
getStatistics({
network,
baseUrl,
params: { },
});

expect(http).toHaveBeenCalledWith({
path: '/api/v2/blockchain/apps/statistics',
params: { },
network,
baseUrl,
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@import '../../../../../../setup/react/app/mixins.css';

.container {
max-width: 350px;

& > header {
padding-bottom: 22px;
}

& > div {
margin-bottom: 16px;
}
}

.chartBox {
padding: 16px 0px !important;
}

.statsBox {
flex-direction: row !important;
justify-content: space-between !important;

& > div {
&:first-child {
flex-basis: 70%;
}

&:last-child {
flex-basis: 30%;
display: flex;
justify-content: center;
}
}
}

.statsInfoTitle {
@mixin contentLarge;

color: var(--color-blue-gray);
}

.statsInfo {
@mixin headingNormalIntermediate;

color: var(--color-maastricht-blue);
margin: 8px 0 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { mount } from 'enzyme';
import BlockchainApplicationStatistics from './index';

describe('BlockchainApplicationStatistics', () => {
const props = {
statistics: {
data: {
registered: 101,
active: 53,
terminated: 9,
totalSupplyLSK: '5000000',
stakedLSK: '3000000',
},
},
};

it('should properly', () => {
const wrapper = mount(<BlockchainApplicationStatistics {...props} />);

expect(wrapper.find('.statsInfoTitle').at(0)).toHaveText('Total Supply');
expect(wrapper.find('.statsInfoTitle').at(1)).toHaveText('Staked');
expect(wrapper.find('TokenAmount').at(0)).toHaveText('5,000,000');
expect(wrapper.find('TokenAmount').at(1)).toHaveText('3,000,000');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { toRawLsk } from '@token/fungible/utils/lsk';
import Box from 'src/theme/box';
import BoxHeader from 'src/theme/box/header';
import BoxContent from 'src/theme/box/content';
import { DoughnutChart } from 'src/modules/common/components/charts';
import TokenAmount from '@token/fungible/components/tokenAmount';
import Tooltip from 'src/theme/Tooltip';
import Icon from 'src/theme/Icon';
import { useTheme } from 'src/theme/Theme';
import { getColorPalette } from 'src/modules/common/components/charts/chartOptions';
import prepareChartDataAndOptions from '../../utils/prepareChartDataAndOptions';
import styles from './blockchainApplicationStatistics.css';

const BlockchainApplicationStatistics = ({ statistics }) => {
const { t } = useTranslation();
const colorPalette = getColorPalette(useTheme());
const {
doughnutChartData, doughnutChartOptions,
} = prepareChartDataAndOptions(statistics.data, colorPalette, t);
const cardsMap = [
{
title: t('Total Supply'), description: t('Total LSK tokens in circulation'), amount: toRawLsk(statistics.data.totalSupplyLSK), icon: 'totalSupplyToken',
},
{
title: t('Staked'), description: t('Amount of LSK tokens staked by validators and nominators for DPoS governance'), amount: toRawLsk(statistics.data.stakedLSK), icon: 'stackedToken',
},
];

return (
<Box className={styles.container}>
<BoxHeader>
<h1>{t('Statistics')}</h1>
</BoxHeader>
<BoxContent className={styles.chartBox}>
<DoughnutChart
data={doughnutChartData}
options={doughnutChartOptions}
/>
</BoxContent>
{cardsMap.map(({
title, description, amount, icon,
}) => (
<BoxContent
key={`app-stats-card-${icon}`}
className={styles.statsBox}
>
<div>
<div>
<span className={styles.statsInfoTitle}>{title}</span>
<Tooltip size="m" position="bottom">
<p>{description}</p>
</Tooltip>
</div>
<p className={styles.statsInfo}>
<TokenAmount val={amount} />
</p>
</div>
<div>
<Icon name={icon} />
</div>
</BoxContent>
))}
</Box>
);
};

export default BlockchainApplicationStatistics;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const prepareChartDataAndOptions = (statistics, colorPalette, t) => {
const doughnutChartData = {
labels: [
t('Registered'),
t('Active'),
t('Terminated'),
],
datasets: [
{
backgroundColor: [colorPalette[1], colorPalette[0], colorPalette[2]],
data: [statistics.registered, statistics.active, statistics.terminated],
},
],
};

const doughnutChartOptions = {
cutoutPercentage: 70,
legend: {
display: true,
position: 'left',
align: 'start',
labels: {
padding: 20,
},
},
layout: {
padding: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
},
};

return { doughnutChartData, doughnutChartOptions };
};

export default prepareChartDataAndOptions;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import prepareChartDataAndOptions from './prepareChartDataAndOptions';

describe('BlockchainApplication explore utils', () => {
it('Should return correct data when calling prepareChartDataAndOptions', () => {
const statistics = {
registered: 101,
active: 53,
terminated: 9,
totalSupplyLSK: '5000000',
stakedLSK: '3000000',
};
const colorPalette = ['green', 'blue', 'grey'];
const t = (l) => l;
const {
doughnutChartData, doughnutChartOptions,
} = prepareChartDataAndOptions(statistics, colorPalette, t);

expect(doughnutChartData).toEqual({
labels: ['Registered', 'Active', 'Terminated'],
datasets: [
{
backgroundColor: ['blue', 'green', 'grey'],
data: [statistics.registered, statistics.active, statistics.terminated],
},
],
});
expect(doughnutChartOptions).toEqual({
cutoutPercentage: 70,
legend: {
display: true,
position: 'left',
align: 'start',
labels: {
padding: 20,
},
},
layout: {
padding: {
left: 0,
right: 0,
bottom: 0,
top: 0,
},
},
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* istanbul ignore file */
import React from 'react';
import BlockchainApplicationStatistics from '../../../explore/components/BlockchainApplicationStatistics';

const ManageBlockchainAppications = ({ apps, statistics }) => (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please improve naming apps is so general, also it dosnt need it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How I should rename it?

<BlockchainApplicationStatistics apps={apps} statistics={statistics} />
);

export default ManageBlockchainAppications;
Loading