clean up dashboard

This commit is contained in:
Ian-Bright
2023-06-06 13:47:45 -06:00
parent 6d603e5861
commit 80fedac3f6
15 changed files with 509 additions and 341 deletions

View File

@@ -15,6 +15,7 @@
"react-dom": "^18.2.0",
"react-jss": "^10.10.0",
"react-scripts": "5.0.1",
"react-virtualized-auto-sizer": "^1.0.20",
"recharts": "^2.6.2",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"

View File

@@ -1,98 +1,155 @@
import Counter from 'components/Counter';
import { CHARTS, COUNTERS } from 'data';
import { CHARTS, COUNTERS, SECTIONS } from 'data';
import { useEffect, useState } from 'react';
import { createUseStyles } from 'react-jss';
import Flex from 'components/Flex';
import ChartWrapper from 'components/Charts/ChartWrapper';
import Typography from 'components/Typography';
import logo from 'assets/images/waxGreenLogo.webp';
const { REACT_APP_API_URL } = process.env;
const useStyles = createUseStyles({
card: {
backgroundColor: '#34383D',
border: '1px solid #74FFCE',
borderRadius: '4px',
color: '#74FFCE',
padding: '20px',
},
container: {
padding: '16px',
padding: '16px 16px 120px 16px',
},
});
type Layout = {
charts: any[];
counters: any[];
description?: string;
title: string;
};
function App() {
const styles = useStyles();
const [layout, setLayout] = useState<Layout>({
charts: [],
counters: [],
});
const [layout, setLayout] = useState<Layout[]>([]);
useEffect(() => {
(async () => {
const res = await fetch(`${REACT_APP_API_URL}/queries`);
const data = await res.json();
const charts = CHARTS.map((chart) => ({
...chart,
data: data[chart.queryId],
}));
const counters = COUNTERS.map((counter) => ({
...counter,
data: data[counter.queryId],
}));
setLayout({ counters, charts });
setLayout(
SECTIONS.map((section) => {
let charts: any[] = [];
let counters: any[] = [];
if (section.charts[0] !== undefined) {
const range = section.charts;
charts = range[1]
? CHARTS.slice(range[0], range[1])
: CHARTS.slice(range[0]);
}
if (section.counters[0] !== undefined) {
const range = section.counters;
counters = range[1]
? COUNTERS.slice(range[0], range[1])
: COUNTERS.slice(range[0]);
}
return {
...section,
charts: charts.map((chart) => ({
...chart,
data: data[chart.queryId],
})),
counters: counters.map((counter) => ({
...counter,
data: data[counter.queryId],
})),
};
})
);
})();
}, []);
return (
<div className={styles.container}>
<Flex justifyContent='flex-end'>
<a href='https://getwax.org' rel='noreferrer' target='_blank'>
<img alt='Logo' src={logo} style={{ height: '40px' }} />
</a>
</Flex>
<Flex
alignItems='center'
justifyContent='center'
mb='32px'
mt='32px'
style={{ color: '#FCFCFC' }}
mt='12px'
style={{ color: '#74FFCE' }}
>
<Typography variant='h4'>BLS Wallet Analytics</Typography>
<Typography variant='h2'>WAX V1 Analytics</Typography>
</Flex>
<Flex childFlex='1 0 calc(25% - 60px)' gap='6px' wrap='wrap'>
{layout.counters.map((counter) => (
<div className={styles.card} style={{ height: '200px' }}>
<Typography style={{ color: '#FCFCFC' }} variant='h6'>
{counter.title}
</Typography>
<Counter
counterKey={counter.counterKey}
data={counter.data}
label={counter.label}
/>
{layout.map((section) => (
<div>
<div className={styles.card} style={{ marginBlock: '32px' }}>
<Typography variant='h4'>{section.title}</Typography>
{section.description && (
<Typography style={{ marginTop: '4px' }} variant='subtitle1'>
<i>{section.description}</i>
</Typography>
)}
</div>
))}
</Flex>
<Flex childFlex='1 0 calc(50% - 60px)' gap='6px' mt='16px' wrap='wrap'>
{layout.charts.map((chart) => (
<div className={styles.card} style={{ height: '350px' }}>
<Typography
style={{ color: '#FCFCFC', marginBottom: '8px' }}
variant='h6'
>
{chart.title}
</Typography>
<ChartWrapper
color={chart.color}
chartType={chart.chartType}
data={chart.data}
stackBy={chart.stackBy}
xAxisTitle={chart.xAxisTitle}
xKey={chart.xKey}
yAxisTitle={chart.yAxisTitle}
yKey={chart.yKey}
/>
</div>
))}
</Flex>
<Flex
childFlex='1 0 calc(25% - 60px)'
gap='6px'
justifyContent='center'
wrap='wrap'
>
{section.counters.map((counter) => (
<div className={styles.card} style={{ height: '200px' }}>
<Typography style={{ color: '#FCFCFC' }} variant='h6'>
{''}
</Typography>
<Counter
counterKey={counter.counterKey}
data={counter.data}
label={counter.label}
showDecimal={counter.showDecimal}
/>
</div>
))}
</Flex>
<Flex
childFlex='1 0 calc(50% - 60px)'
justifyContent='center'
gap='6px'
mt='16px'
wrap='wrap'
>
{section.charts.map((chart) => (
<div
className={styles.card}
style={{ height: '450px', maxWidth: '50%' }}
>
<Typography
style={{ color: '#FCFCFC', marginBottom: '8px' }}
variant='h6'
>
{chart.title}
</Typography>
<ChartWrapper
color={chart.color}
chartType={chart.chartType}
data={chart.data}
showDecimals={chart.showDecimals}
stackBy={chart.stackBy}
xAxisTitle={chart.xAxisTitle}
xKey={chart.xKey}
yAxisTitle={chart.yAxisTitle}
yKey={chart.yKey}
/>
</div>
))}
</Flex>
</div>
))}
</div>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -4,7 +4,6 @@ import {
Area,
AreaChart as RechartsAreaChart,
CartesianGrid,
ResponsiveContainer,
Tooltip as RechartsTooltip,
TooltipProps,
XAxis,
@@ -27,8 +26,11 @@ export default function AreaChart({
color,
data,
grid,
height,
scale,
showDecimals,
stackBy,
width,
xAxisTitle,
xKey,
yAxisTitle,
@@ -39,60 +41,60 @@ export default function AreaChart({
}, [data, stackBy, xKey]);
return (
<ResponsiveContainer>
<RechartsAreaChart
data={stackBy ? data.formattedData : data}
margin={{ bottom: xAxisTitle ? 15 : 0, left: 5 }}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} xKey={xKey} />
)}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Area
activeDot={{ r: 2, strokeWidth: 1 }}
dataKey={key}
fill={PALETTE[index % PALETTE.length]}
fillOpacity={0.75}
key={key}
stackId={'1'}
stroke={PALETTE[index % PALETTE.length]}
type='linear'
/>
))
) : (
<Area
activeDot={{ r: 5, strokeWidth: 0.5 }}
dataKey={yKey}
dot={false}
fill={color}
fillOpacity={0.6}
isAnimationActive={false}
stroke={color}
type='monotone'
/>
<RechartsAreaChart
data={stackBy ? data.formattedData : data}
height={height}
margin={{ bottom: xAxisTitle ? 30 : 0, left: 5 }}
width={width}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} showDecimals={showDecimals} xKey={xKey} />
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle ?? '')}
fontSize={TICKMARK_FONT_SIZE}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Area
activeDot={{ r: 2, strokeWidth: 1 }}
dataKey={key}
fill={PALETTE[index % PALETTE.length]}
fillOpacity={0.75}
key={key}
stackId={'1'}
stroke={PALETTE[index % PALETTE.length]}
type='linear'
/>
))
) : (
<Area
activeDot={{ r: 5, strokeWidth: 0.5 }}
dataKey={yKey}
dot={false}
fill={color}
fillOpacity={0.6}
isAnimationActive={false}
stroke={color}
type='monotone'
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
tickFormatter={(tick) => formatLargeNumber(tick)}
scale={scale}
/>
</RechartsAreaChart>
</ResponsiveContainer>
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle ?? '')}
fontSize={TICKMARK_FONT_SIZE}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
tickFormatter={(tick) => formatLargeNumber(tick)}
scale={scale}
/>
</RechartsAreaChart>
);
}

View File

@@ -4,7 +4,6 @@ import {
Bar,
BarChart as RechartsBarChart,
CartesianGrid,
ResponsiveContainer,
Tooltip as RechartsTooltip,
TooltipProps,
XAxis,
@@ -27,8 +26,11 @@ export default function BarChart({
color,
data,
grid,
height,
scale,
showDecimals,
stackBy,
width,
xAxisTitle,
xKey,
yAxisTitle,
@@ -39,52 +41,52 @@ export default function BarChart({
}, [data, stackBy, xKey]);
return (
<ResponsiveContainer>
<RechartsBarChart
data={stackBy ? data.formattedData : data}
margin={{ bottom: xAxisTitle ? 15 : 0, left: 5 }}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} xKey={xKey} />
)}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Bar
dataKey={key}
fill={PALETTE[index % PALETTE.length]}
fillOpacity={1}
isAnimationActive={false}
key={key}
stackId={'1'}
type='monotone'
/>
))
) : (
<Bar dataKey={yKey} fill={color} isAnimationActive={false} />
<RechartsBarChart
data={stackBy ? data.formattedData : data}
height={height}
margin={{ bottom: xAxisTitle ? 30 : 0, left: 5 }}
width={width}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} showDecimals={showDecimals} xKey={xKey} />
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
fontSize={TICKMARK_FONT_SIZE}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle)}
name={xAxisTitle}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
name={yAxisTitle}
scale={scale}
tickFormatter={(tick) => formatLargeNumber(tick)}
/>
</RechartsBarChart>
</ResponsiveContainer>
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Bar
dataKey={key}
fill={PALETTE[index % PALETTE.length]}
fillOpacity={1}
isAnimationActive={false}
key={key}
stackId={'1'}
type='monotone'
/>
))
) : (
<Bar dataKey={yKey} fill={color} isAnimationActive={false} />
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
fontSize={TICKMARK_FONT_SIZE}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle)}
name={xAxisTitle}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
name={yAxisTitle}
scale={scale}
tickFormatter={(tick) => formatLargeNumber(tick)}
/>
</RechartsBarChart>
);
}

View File

@@ -6,6 +6,7 @@ import { useMemo } from 'react';
import { ChartScale, ChartType, StackBy } from 'utils/constants';
import PieChart from '../PieChart';
import { generateStackData } from 'utils';
import AutoSizer from 'react-virtualized-auto-sizer';
type ChartWrapperProps = {
chartType: string;
@@ -13,8 +14,9 @@ type ChartWrapperProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any[];
grid?: boolean;
stackBy?: StackBy;
scale?: ChartScale;
showDecimals?: boolean;
stackBy?: StackBy;
xAxisTitle: string;
xKey: string;
yAxisTitle: string;
@@ -27,6 +29,7 @@ export default function ChartWrapper({
data,
grid,
scale = ChartScale.Linear,
showDecimals,
stackBy,
xAxisTitle,
xKey,
@@ -67,48 +70,82 @@ export default function ChartWrapper({
if (chartType === ChartType.Area) {
return (
<AreaChart
color={color}
data={sortedData}
grid={!!grid}
scale={scale}
stackBy={stackBy}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
<AutoSizer>
{({ height, width }: { height: number; width: number }) => (
<AreaChart
color={color}
data={sortedData}
grid={!!grid}
height={height}
scale={scale}
showDecimals={showDecimals}
stackBy={stackBy}
width={width}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
)}
</AutoSizer>
);
} else if (chartType === ChartType.Bar) {
return (
<BarChart
color={color}
data={sortedData}
grid={!!grid}
scale={scale}
stackBy={stackBy}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
<AutoSizer>
{({ height, width }: { height: number; width: number }) => (
<BarChart
color={color}
data={sortedData}
grid={!!grid}
height={height}
scale={scale}
showDecimals={showDecimals}
stackBy={stackBy}
width={width}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
)}
</AutoSizer>
);
} else if (chartType === ChartType.Line) {
return (
<LineChart
color={color}
curveType='basis'
data={sortedData}
grid={!!grid}
scale={scale}
stackBy={stackBy}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
<AutoSizer>
{({ height, width }: { height: number; width: number }) => (
<LineChart
color={color}
curveType='basis'
data={sortedData}
grid={!!grid}
height={height}
scale={scale}
showDecimals={showDecimals}
stackBy={stackBy}
width={width}
xAxisTitle={xAxisTitle}
xKey={xKey || 'x'}
yAxisTitle={yAxisTitle}
yKey={yKey || 'y'}
/>
)}
</AutoSizer>
);
} else {
return <PieChart data={data} dataKey={yKey || 'y'} nameKey={xKey || 'x'} />;
return (
<AutoSizer>
{({ height, width }: { height: number; width: number }) => (
<PieChart
data={data}
dataKey={yKey || 'y'}
height={height}
nameKey={xKey || 'x'}
showDecimals={showDecimals}
width={width}
/>
)}
</AutoSizer>
);
}
}

View File

@@ -4,7 +4,6 @@ import {
CartesianGrid,
Line,
LineChart as RechartsLineChart,
ResponsiveContainer,
Tooltip as RechartsTooltip,
TooltipProps,
XAxis,
@@ -25,11 +24,13 @@ type LineChartProps = AxisChartProps;
export default function LineChart({
color,
curveType,
data,
grid,
height,
scale,
showDecimals,
stackBy,
width,
xAxisTitle,
xKey,
yAxisTitle,
@@ -39,59 +40,59 @@ export default function LineChart({
return determineTimeframe(stackBy ? data.formattedData : data, xKey);
}, [data, stackBy, xKey]);
return (
<ResponsiveContainer>
<RechartsLineChart
data={stackBy ? data.formattedData : data}
margin={{ bottom: xAxisTitle ? 15 : 0, left: 5 }}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} xKey={xKey} />
)}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Line
activeDot={{ strokeWidth: 1 }}
dataKey={key}
dot={false}
fill={PALETTE[index % PALETTE.length]}
key={key}
stroke={PALETTE[index % PALETTE.length]}
strokeWidth={2}
/>
))
) : (
<Line
activeDot={{ r: 5, strokeWidth: 0.5 }}
isAnimationActive={false}
dataKey={yKey}
dot={false}
stroke={color}
type='monotone'
/>
<RechartsLineChart
data={stackBy ? data.formattedData : data}
height={height}
margin={{ bottom: xAxisTitle ? 30 : 0, left: 5 }}
width={width}
>
{grid && <CartesianGrid strokeDasharray='3 3' />}
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} showDecimals={showDecimals} xKey={xKey} />
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
fontSize={TICKMARK_FONT_SIZE}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle)}
name={xAxisTitle}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
{stackBy ? (
data.keys?.map((key: string, index: number) => (
<Line
activeDot={{ strokeWidth: 1 }}
dataKey={key}
dot={false}
fill={PALETTE[index % PALETTE.length]}
key={key}
stroke={PALETTE[index % PALETTE.length]}
strokeWidth={2}
/>
))
) : (
<Line
activeDot={{ r: 5, strokeWidth: 0.5 }}
isAnimationActive={false}
dataKey={yKey}
dot={false}
stroke={color}
type='monotone'
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
scale={scale}
name={yAxisTitle}
tickFormatter={(tick) => formatLargeNumber(tick)}
/>
</RechartsLineChart>
</ResponsiveContainer>
)}
<XAxis
dataKey={(x) => handleXKey(x, xKey)}
fontSize={TICKMARK_FONT_SIZE}
label={X_AXIS_LABEL_INSTRUCTIONS(xAxisTitle)}
name={xAxisTitle}
tickFormatter={(tick) =>
timeframe ? moment(tick).format(timeframe) : tick
}
/>
<YAxis
dataKey={stackBy ? '' : yKey}
domain={[0, 'auto']}
fontSize={TICKMARK_FONT_SIZE}
label={Y_AXIS_LABEL_INSTRUCTIONS(yAxisTitle ?? '')}
scale={scale}
name={yAxisTitle}
tickFormatter={(tick) => formatLargeNumber(tick)}
/>
</RechartsLineChart>
);
}

View File

@@ -3,7 +3,6 @@ import {
Cell,
Pie,
PieChart as RechartsPieChart,
ResponsiveContainer,
Sector,
Tooltip as RechartsTooltip,
TooltipProps,
@@ -16,13 +15,19 @@ type PieChartProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any[];
dataKey: string;
height: number;
nameKey: string;
showDecimals?: boolean;
width: number;
};
export default function PieChart({
data,
dataKey,
height,
nameKey,
showDecimals,
width,
}: PieChartProps): JSX.Element {
const [activeIndex, setActiveIndex] = useState(-1);
@@ -49,34 +54,34 @@ export default function PieChart({
};
return (
<ResponsiveContainer>
<RechartsPieChart>
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip {...props} xKey={nameKey} />
)}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
<Pie
activeIndex={activeIndex}
activeShape={activeShape}
cx='50%'
cy='50%'
data={data}
dataKey={dataKey}
labelLine={false}
nameKey={nameKey}
onMouseEnter={onPieEnter}
onMouseLeave={() => setActiveIndex(-1)}
>
{data.map((_, index) => (
<Cell
key={`cell-${index}`}
fill={PALETTE[index % PALETTE.length]}
/>
))}
</Pie>
</RechartsPieChart>
</ResponsiveContainer>
<RechartsPieChart height={height * 0.9} width={width}>
<RechartsTooltip
content={(props: TooltipProps<number, string>) => (
<Tooltip
{...props}
isPie={true}
showDecimals={showDecimals}
xKey={nameKey}
/>
)}
wrapperStyle={{ outline: 'none', zIndex: 100 }}
/>
<Pie
activeIndex={activeIndex}
activeShape={activeShape}
cx='50%'
cy='50%'
data={data}
dataKey={dataKey}
labelLine={false}
nameKey={nameKey}
onMouseEnter={onPieEnter}
onMouseLeave={() => setActiveIndex(-1)}
>
{data.map((_, index) => (
<Cell key={`cell-${index}`} fill={PALETTE[index % PALETTE.length]} />
))}
</Pie>
</RechartsPieChart>
);
}

View File

@@ -14,28 +14,53 @@ const useStyles = createUseStyles({
},
});
type TooltipProps = { xKey: string } & RechartsTooltipProps<number, string>;
type TooltipProps = {
isPie?: boolean;
showDecimals?: boolean;
xKey: string;
} & RechartsTooltipProps<number, string>;
export default function Tooltip(props: TooltipProps): JSX.Element {
const { label, payload, xKey } = props;
const { isPie, label, payload, showDecimals, xKey } = props;
const styles = useStyles();
if (!payload) return <></>;
if (!payload || payload[0] === undefined) return <></>;
return (
<div className={styles.container}>
<Flex key={xKey} gap='12px' style={{ color: '#FCFCFC' }}>
<div>{xKey}:</div>
<div>
{isDateOrTimestamp(label)
? moment(label).format('MMM Do, YYYY')
: label}
</div>
</Flex>
{payload.map(({ color, name, payload: { fill }, value }) => (
<Flex key={name} gap='12px' style={{ color: color ?? fill }}>
<div>{name}:</div>
<div>{formatNumber(value ?? 0, 0)}</div>
</Flex>
))}
{isPie ? (
<>
<Flex key={xKey} gap='12px' style={{ color: '#FCFCFC' }}>
<div>{xKey}:</div>
<div>
{isDateOrTimestamp(payload[0].name)
? moment(payload[0].name).format('MMM Do, YYYY')
: payload[0].name}
</div>
</Flex>
<Flex gap='12px' style={{ color: payload[0].payload.fill }}>
<div>{payload[0].dataKey}:</div>
<div>
{formatNumber(payload[0].value ?? 0, showDecimals ? 2 : 0)}
</div>
</Flex>
</>
) : (
<>
<Flex key={xKey} gap='12px' style={{ color: '#FCFCFC' }}>
<div>{xKey}:</div>
<div>
{isDateOrTimestamp(label)
? moment(label).format('MMM Do, YYYY')
: label}
</div>
</Flex>
{payload.map(({ color, name, payload: { fill }, value }) => (
<Flex key={name} gap='12px' style={{ color: color ?? fill }}>
<div>{name}:</div>
<div>{formatNumber(value ?? 0, showDecimals ? 2 : 0)}</div>
</Flex>
))}
</>
)}
</div>
);
}

View File

@@ -7,12 +7,14 @@ type CounterProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
label: string;
showDecimal?: boolean;
};
export default function Counter({
counterKey,
data,
label,
showDecimal,
}: CounterProps): JSX.Element {
return (
<>
@@ -23,9 +25,9 @@ export default function Counter({
style={{ color: '#FCFCFC' }}
>
<Flex direction='column' alignItems='center'>
<Typography variant='subtitle1'>{label}</Typography>
<Typography variant='h6'>{label}</Typography>
<Typography variant='h4'>
{formatNumber(data[0][counterKey], 0)}
{formatNumber(data[0][counterKey], showDecimal ? 2 : 0)}
</Typography>
</Flex>
</Flex>

View File

@@ -3,13 +3,13 @@ import { ChartType } from "utils/constants";
export const COUNTERS = [
{
counterKey: 'Num_Wallets_Created',
label: 'Wallets Created',
label: 'BLS Wallets Created',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Wallets'
},
{
counterKey: 'Num_Wallets_Recovered',
label: 'Wallets Recovered',
label: 'BLS Wallets Recovered',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Wallets'
},
@@ -19,6 +19,12 @@ export const COUNTERS = [
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Tx Groups'
},
{
counterKey: 'Num_Operations_Submitted',
label: 'Operations Submitted',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Tx Groups'
},
{
counterKey: 'Num_Operations_Failed',
label: 'Operations Failed',
@@ -31,28 +37,25 @@ export const COUNTERS = [
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Tx Groups'
},
{
counterKey: 'Num_Operations_Submitted',
label: 'Operations Submitted',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
title: 'Tx Groups'
},
{
counterKey: 'Avg_Operations_Per_Bundle',
label: 'Operations/Bundle',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
showDecimal: true,
title: 'Averages'
},
{
counterKey: 'Avg_Actions_Per_Bundle',
label: 'Actions/Bundle',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
showDecimal: true,
title: 'Averages'
},
{
counterKey: 'Avg_Actions_Per_Operation',
label: 'Actions/Operations',
queryId: 'aa55c0623a28438eac9aecfb7b767726',
showDecimal: true,
title: 'Averages'
},
{
@@ -76,20 +79,6 @@ export const COUNTERS = [
];
export const CHARTS = [
{
chartType: ChartType.Pie,
queryId: '7ad7fb1828094272880202e903af4239',
title: 'Action Method Ids Called',
xKey: 'actionMethodId',
yKey: 'action_count'
},
{
chartType: ChartType.Pie,
queryId: '2578dd88f123458183e0fe077d285243',
title: 'Action Recipients',
xKey: 'actionsRecipient',
yKey: 'action_count'
},
{
chartType: ChartType.Bar,
color: '#B8B7D0',
@@ -113,6 +102,7 @@ export const CHARTS = [
{
chartType: ChartType.Bar,
color: '#CE83D9',
description: 'Number of bundles (a group of operations containing actions) submitted on-chain',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
title: 'Number of Bundles Submitted per Day',
xAxisTitle: 'Day',
@@ -123,6 +113,7 @@ export const CHARTS = [
{
chartType: ChartType.Bar,
color: '#8784D8',
description: 'Number of Actions (function calls coming from a signed operation) submitted on-chain',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
title: 'Number of Actions Submitted per Day',
xAxisTitle: 'Day',
@@ -133,6 +124,7 @@ export const CHARTS = [
{
chartType: ChartType.Bar,
color: '#C6C5CF',
description: 'Number of Operations (a group of actions) submitted on-chain',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
title: 'Number of Operations Submitted per Day',
xAxisTitle: 'Day',
@@ -154,6 +146,7 @@ export const CHARTS = [
chartType: ChartType.Bar,
color: '#84D9CC',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
showDecimals: true,
title: 'Average Operations per Bundle per day',
xAxisTitle: 'Day',
xKey: 'day',
@@ -164,6 +157,7 @@ export const CHARTS = [
chartType: ChartType.Bar,
color: '#8784D8',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
showDecimals: true,
title: 'Average Actions per Bundle Per Dayy',
xAxisTitle: 'Day',
xKey: 'day',
@@ -174,6 +168,7 @@ export const CHARTS = [
chartType: ChartType.Bar,
color: '#B6B6BF',
queryId: 'ab1a30af5991425b8b4abd7c37f859fa',
showDecimals: true,
title: 'Average Actions per Operation per Day',
xAxisTitle: 'Day',
xKey: 'day',
@@ -210,6 +205,20 @@ export const CHARTS = [
yAxisTitle: 'Average Gas per Transaction',
yKey: 'avgGas'
},
{
chartType: ChartType.Pie,
queryId: '7ad7fb1828094272880202e903af4239',
title: 'Action Method Ids Called',
xKey: 'actionMethodId',
yKey: 'action_count'
},
{
chartType: ChartType.Pie,
queryId: '2578dd88f123458183e0fe077d285243',
title: 'Action Recipients',
xKey: 'actionsRecipient',
yKey: 'action_count'
},
{
chartType: ChartType.Bar,
queryId: '74a8783fd397441ca0dd9cbc96423e81',
@@ -236,16 +245,35 @@ export const CHARTS = [
},
];
// type ChartWrapperProps = {
// chartType: string;
// color: string;
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
// data: any[];
// grid?: boolean;
// stackBy?: StackBy;
// scale?: ChartScale;
// xAxisTitle: string;
// xKey: string;
// yAxisTitle: string;
// yKey: string;
// };
export const SECTIONS = [
{
charts: [0, 2],
counters: [0, 2],
description: 'BLS smart-contract wallets for use with WAX',
title: 'Wallets',
},
{
charts: [2, 6],
counters: [2, 6],
description: 'Bundles, submitted on-chain, encompass Operations that carry Actions - the actual function calls.',
title: 'Bundle Composition'
},
{
charts: [6, 9],
counters: [6, 9],
description: 'Bundle, Operations, & Actions Relationship',
title: 'Averages',
},
{
charts: [9, 12],
counters: [9, 12],
description: 'The gas expenses for each bundle submission.',
title: 'Gas',
},
{
charts: [12],
counters: [],
description: 'Metrics related to the contracts called and method IDs invoked within BLS Wallet actions.',
title: 'Actions'
}
];

View File

@@ -18,7 +18,7 @@
}
body {
background-color: #262726;
background-color: #090213;
margin: 0;
font-family: 'Heebo', 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',

View File

@@ -2,6 +2,7 @@ import { CSSProperties } from 'react';
export type TypographyVariant =
| 'caption'
| 'h2'
| 'h4'
| 'h5'
| 'h6'
@@ -21,6 +22,13 @@ export const typography: TypographyVariantMap = {
fontWeight: 400,
lineHeight: '14px',
},
h2: {
fontFamily: 'Heebo',
fontSize: '48px',
fontWeight: 500,
letterSpacing: '0.5px',
lineHeight: 'g6px',
},
h4: {
fontFamily: 'Heebo',
fontSize: '34px',

View File

@@ -8,6 +8,7 @@ export type AxisChartProps = {
grid: boolean;
height?: number;
scale: ChartScale;
showDecimals?: boolean;
stackBy?: StackBy;
width?: number;
xAxisTitle: string;
@@ -35,18 +36,12 @@ export const MS_PER_MONTH = 30.44 * MS_PER_DAY; // Milleseconds per month
export const MS_PER_YEAR = 365.25 * MS_PER_DAY; // Millesconds per year
export const PALETTE = [
'#a6cee3',
'#1f78b4',
'#b2df8a',
'#33a02c',
'#fb9a99',
'#e31a1c',
'#fdbf6f',
'#ff7f00',
'#cab2d6',
'#6a3d9a',
'#ffff99',
'#b15928',
'#84ACCE',
'#74FFCE',
'#E040FB',
'#3F51B5',
'#F18F01'
];
export type StackBy = {

View File

@@ -8087,6 +8087,11 @@ react-transition-group@2.9.0:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
react-virtualized-auto-sizer@^1.0.20:
version "1.0.20"
resolved "https://registry.yarnpkg.com/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.20.tgz#d9a907253a7c221c52fa57dc775a6ef40c182645"
integrity sha512-OdIyHwj4S4wyhbKHOKM1wLSj/UDXm839Z3Cvfg2a9j+He6yDa6i5p0qQvEiCnyQlGO/HyfSnigQwuxvYalaAXA==
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"