Improve charts page UI, add mobile view

pull/219/head
artemkolodko 2 years ago
parent 700af0f39a
commit 1102bb0358
  1. 14
      src/pages/ChartsPage/ActiveAddresses.tsx
  2. 49
      src/pages/ChartsPage/AverageBlockSize.tsx
  3. 14
      src/pages/ChartsPage/AverageFee.tsx
  4. 4
      src/pages/ChartsPage/DailyChartPage.tsx
  5. 14
      src/pages/ChartsPage/DailyTransactions.tsx
  6. 28
      src/pages/ChartsPage/index.tsx
  7. BIN
      src/pages/ChartsPage/thumbnails/daily_blocksize.png
  8. 19
      src/pages/ChartsPage/utils.ts
  9. 1
      src/types/api.ts

@ -15,18 +15,8 @@ export const ActiveAddresses = () => {
const loadData = async () => {
try {
setIsLoading(true)
const limit = 1000
let data: MetricsDailyItem[] = []
for(let i = 0; i < 2; i++) {
const res = await getMetricsByType(MetricsType.walletsCount, i * limit, limit)
data = [...data, ...res]
if(res.length < limit) {
break;
}
}
const cachedData = enrichResponse(data)
setItems(cachedData)
const data = await getMetricsByType(MetricsType.walletsCount, 0, 2000)
setItems(enrichResponse(data))
} catch (e) {
console.error('Error on loading metrics:', e)
setLoadingError('Loading error')

@ -0,0 +1,49 @@
import React, {useEffect, useState} from 'react'
import {getMetricsByType} from "../../api/client";
import {MetricsDailyItem, MetricsType} from "../../types";
import {
enrichResponse,
} from './utils'
import {DailyChartPage} from "./DailyChartPage";
export const AverageBlockSize = () => {
const [items, setItems] = useState<MetricsDailyItem[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const [loadingError, setLoadingError] = useState('')
useEffect(() => {
const loadData = async () => {
try {
setIsLoading(true)
const data = await getMetricsByType(MetricsType.blockSize, 0, 2000)
setItems(enrichResponse(data))
} catch (e) {
console.error('Error on loading metrics:', e)
setLoadingError('Loading error')
} finally {
setIsLoading(false);
}
}
loadData()
}, [])
const dailyPageProps = {
title: 'Harmony Average Block Size',
unitLabel: 'blocksize',
items,
isLoading,
loadingError,
chart: {
yAxisLabel: 'Block Size in Bytes',
tooltipLabel: 'Block Size (Bytes)'
},
renderMaxValue: (value: string, date: string) => {
return `Largest size of ${value} bytes on ${date}`
},
renderMinValue: (value: string, date: string) => {
return `Smallest size of ${value} bytes on ${date}`
}
}
return <DailyChartPage {...dailyPageProps} />
}

@ -15,18 +15,8 @@ export const AverageFee = () => {
const loadData = async () => {
try {
setIsLoading(true)
const limit = 1000
let data: MetricsDailyItem[] = []
for(let i = 0; i < 2; i++) {
const res = await getMetricsByType(MetricsType.averageFee, i * limit, limit)
data = [...data, ...res]
if(res.length < limit) {
break;
}
}
const cachedData = enrichResponse(data)
setItems(cachedData)
const data = await getMetricsByType(MetricsType.averageFee, 0, 2000)
setItems(enrichResponse(data))
} catch (e) {
console.error('Error on loading metrics:', e)
setLoadingError('Loading error')

@ -15,6 +15,7 @@ import styled from "styled-components";
import dayjs from "dayjs";
import {Alert, Info} from "grommet-icons";
import {Link} from "react-router-dom";
import {useMediaQuery} from "react-responsive";
const ChartModalContainer = styled(Box)`
position: absolute;
@ -95,7 +96,8 @@ export const DailyChartPage = (props: DailyChartPageProps) => {
}
}, [props.items])
const chartOptions = getDetailedChartOptions(themeMode, items, { yAxisLabel: props.chart.yAxisLabel })
const isMobile = useMediaQuery({ query: '(max-width: 868px)' })
const chartOptions = getDetailedChartOptions(themeMode, items, { isMobile, yAxisLabel: props.chart.yAxisLabel })
const chartData = getChartData(themeMode, items, props.chart.tooltipLabel)
return <BaseContainer pad={{ horizontal: "0" }}>

@ -15,18 +15,8 @@ export const DailyTransactions = () => {
const loadData = async () => {
try {
setIsLoading(true)
const limit = 1000
let data: MetricsDailyItem[] = []
for(let i = 0; i < 2; i++) {
const res = await getMetricsByType(MetricsType.transactionsCount, i * limit, limit)
data = [...data, ...res]
if(res.length < limit) {
break;
}
}
const cachedData = enrichResponse(data)
setItems(cachedData)
const data = await getMetricsByType(MetricsType.transactionsCount, 0, 2000)
setItems(enrichResponse(data))
} catch (e) {
console.error('Error on loading metrics:', e)
setLoadingError('Loading error')

@ -5,20 +5,30 @@ import {useHistory, useLocation} from "react-router-dom";
import {ActiveAddresses} from "./ActiveAddresses";
import {DailyTransactions} from "./DailyTransactions";
import {AverageFee} from "./AverageFee";
import {AverageBlockSize} from "./AverageBlockSize";
import styled from "styled-components";
enum ChartType {
tx = 'tx',
addresses = 'addresses',
fee = 'fee'
fee = 'fee',
blockSize = 'blocksize'
}
const PreviewContainer = styled(Box)`
flex: 1 1 250px;
transition: transform 250ms;
flex: 0 0 calc(25% - 16px);
margin-left: 8px;
margin-right: 8px;
&:hover {
transform: scale(1.025);
@media (max-width: 1024px) {
flex: 0 0 calc(50% - 16px);
margin-bottom: 0.75rem;
}
@media (max-width: 768px) {
flex: 0 0 calc(100% - 16px);
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
`
@ -30,12 +40,13 @@ const PreviewCard = (props: { type: ChartType, title: string }) => {
return <PreviewContainer border={{ size: '1px' }} onClick={onClick} round={'8px'} overflow={'hidden'}>
<Box pad={'8px'} background={'backgroundDropdownItem'}>
<Text color={'brand'}>{title}</Text>
<Text size={'small'} color={'brand'}>{title}</Text>
</Box>
<Box style={{ filter: 'grayscale(0.8)' }} pad={'8px'} border={{ side: 'top' }}>
{type === ChartType.tx && <img src={require("./thumbnails/daily_txs.png").default} alt={type} />}
{type === ChartType.addresses && <img src={require("./thumbnails/daily_addresses.png").default} alt={type} />}
{type === ChartType.fee && <img src={require("./thumbnails/daily_fee.png").default} alt={type} />}
{type === ChartType.blockSize && <img src={require("./thumbnails/daily_blocksize.png").default} alt={type} />}
</Box>
</PreviewContainer>
}
@ -50,6 +61,8 @@ export function ChartsPage() {
return <ActiveAddresses />
} else if(route === ChartType.fee) {
return <AverageFee />
} else if(route === ChartType.blockSize) {
return <AverageBlockSize />
}
return (
@ -61,10 +74,11 @@ export function ChartsPage() {
<Box border={{ side: 'bottom' }} pad={"small"}>
<Text weight={'bold'}>Blockchain Data</Text>
</Box>
<Box wrap direction={'row'} pad={"small"} gap={'16px'} justify={'center'} align={'center'}>
<Box wrap direction={'row'} pad={"small"} justify={'center'} align={'center'}>
<PreviewCard type={ChartType.tx} title={'Daily Transactions Chart'} />
<PreviewCard type={ChartType.addresses} title={'Daily Active Addresses'} />
<PreviewCard type={ChartType.fee} title={'Average Transaction Fee'} />
<PreviewCard type={ChartType.blockSize} title={'Average Block Size'} />
</Box>
</BasePage>
</BaseContainer>

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

@ -25,6 +25,7 @@ export const getChartData = (themeMode: string, items: MetricsDailyItem[], label
}
export interface OptionsConfig {
isMobile?: boolean
yAxisLabel?: string
}
@ -96,19 +97,27 @@ export const getDetailedChartOptions = (themeMode: 'light' | 'dark', points: any
callback: function(value: string, index: any, ticks: any) {
const item = points[index]
const nextItem = points[index + 1]
// Month change
if(nextItem) {
if(dayjs(item.timestamp).month() !== dayjs(nextItem.timestamp).month()) {
console.log('dayjs(nextItem.timestamp).month()', dayjs(nextItem.timestamp).month())
}
// Show January and July
if (dayjs(item.timestamp).month() !== dayjs(nextItem.timestamp).month() &&
([0, 6].includes(dayjs(item.timestamp).month()))) {
([6, 0].includes(dayjs(nextItem.timestamp).month()))) {
return dayjs(nextItem.timestamp).format("MMM 'YY")
}
if(ticks.length <= 365) {
if (dayjs(item.timestamp).month() !== dayjs(nextItem.timestamp).month()) {
return dayjs(nextItem.timestamp).format("MMM 'YY")
// too many labels for mobile screen
if(!config.isMobile) {
// show each month
if(ticks.length <= 365) {
if (dayjs(item.timestamp).month() !== dayjs(nextItem.timestamp).month()) {
return dayjs(nextItem.timestamp).format("MMM 'YY")
}
}
}
if(ticks.length <= 30) {
// show each day
if (dayjs(item.timestamp).day() !== dayjs(nextItem.timestamp).day() &&
[1].includes(dayjs(item.timestamp).day())) {
return dayjs(nextItem.timestamp).format("D MMM")

@ -55,4 +55,5 @@ export enum MetricsType {
transactionsCount = 'transactions_count',
walletsCount = 'wallets_count',
averageFee = 'average_fee',
blockSize = 'block_size'
}

Loading…
Cancel
Save