Skip to content

Commit

Permalink
stats fixes after test part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Sep 25, 2024
1 parent ab22a7a commit e22db69
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 107 deletions.
2 changes: 1 addition & 1 deletion lib/hooks/useNavItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ export default function useNavItems(): ReturnType {
text: 'Charts & stats',
nextRoute: { pathname: '/stats' as const },
icon: 'stats',
isActive: pathname === '/stats',
isActive: pathname.startsWith('/stats'),
} : null,
apiNavItems.length > 0 && {
text: 'API',
Expand Down
62 changes: 27 additions & 35 deletions ui/pages/Chart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Flex, IconButton, Text } from '@chakra-ui/react';
import { Button, Flex, IconButton, Link, Text } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import React from 'react';

Expand All @@ -19,7 +19,7 @@ import ChartMenu from 'ui/shared/chart/ChartMenu';
import ChartResolutionSelect from 'ui/shared/chart/ChartResolutionSelect';
import ChartWidgetContent from 'ui/shared/chart/ChartWidgetContent';
import useChartQuery from 'ui/shared/chart/useChartQuery';
import useZoomReset from 'ui/shared/chart/useZoomReset';
import useZoom from 'ui/shared/chart/useZoom';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import IconSvg from 'ui/shared/IconSvg';
import PageTitle from 'ui/shared/Page/PageTitle';
Expand All @@ -46,7 +46,7 @@ const Chart = () => {
const id = getQueryParamString(router.query.id);
const [ intervalState, setIntervalState ] = React.useState<StatsIntervalIds | undefined>();
const [ resolution, setResolution ] = React.useState<Resolution>(DEFAULT_RESOLUTION);
const { isZoomResetInitial, handleZoom, handleZoomReset } = useZoomReset();
const { zoomRange, handleZoom, handleZoomReset } = useZoom();

const interval = intervalState || getIntervalByResolution(resolution);

Expand Down Expand Up @@ -155,6 +155,10 @@ const Chart = () => {
title={ info?.title || '' }
isLoading={ lineQuery.isPlaceholderData }
chartRef={ ref }
resolution={ resolution }
zoomRange={ zoomRange }
handleZoom={ handleZoom }
handleZoomReset={ handleZoomReset }
/>
) }
</Flex>
Expand All @@ -172,44 +176,31 @@ const Chart = () => {
withTextAd
/>
<Flex alignItems="center" justifyContent="space-between">
<Flex alignItems="center" gap={ 3 } maxW="100%" overflow="hidden">
<Text>Period</Text>
<ChartIntervalSelect interval={ interval } onIntervalChange={ setIntervalState }/>
<Flex alignItems="center" gap={{ base: 3, lg: 6 }} maxW="100%" overflow="hidden">
<Flex alignItems="center" gap={ 3 }>
<Text>Period</Text>
<ChartIntervalSelect interval={ interval } onIntervalChange={ setIntervalState }/>
</Flex>
{ lineQuery.data?.info?.resolutions && lineQuery.data?.info?.resolutions.length > 1 && (
<>
<Text ml={{ base: 0, lg: 3 }}>{ isMobile ? 'Res.' : 'Resolution' }</Text>
<Flex alignItems="center" gap={ 3 }>
<Text>{ isMobile ? 'Res.' : 'Resolution' }</Text>
<ChartResolutionSelect
resolution={ resolution }
onResolutionChange={ setResolution }
resolutions={ lineQuery.data?.info?.resolutions || [] }
/>
</>
</Flex>
) }
{ (!isZoomResetInitial || resolution !== DEFAULT_RESOLUTION) && (
isMobile ? (
<IconButton
aria-label="Reset"
variant="ghost"
size="sm"
icon={ <IconSvg name="repeat" boxSize={ 5 }/> }
onClick={ handleReset }
/>
) : (
<Button
leftIcon={ <IconSvg name="repeat" w={ 4 } h={ 4 }/> }
colorScheme="blue"
gridColumn={ 2 }
justifySelf="end"
alignSelf="top"
gridRow="1/3"
size="sm"
variant="outline"
onClick={ handleReset }
ml={ 6 }
>
Reset
</Button>
)
{ (Boolean(zoomRange)) && (
<Link
onClick={ handleReset }
display="flex"
alignItems="center"
gap={ 2 }
>
<IconSvg name="repeat" w={ 5 } h={ 5 }/>
{ !isMobile && 'Reset' }
</Link>
) }
</Flex>
{ !isMobile && shareAndMenu }
Expand All @@ -228,9 +219,10 @@ const Chart = () => {
units={ info?.units || undefined }
isEnlarged
isLoading={ lineQuery.isPlaceholderData }
isZoomResetInitial={ isZoomResetInitial }
zoomRange={ zoomRange }
handleZoom={ handleZoom }
emptyText="No data for the selected resolution & interval."
resolution={ resolution }
/>
</Flex>
</>
Expand Down
23 changes: 22 additions & 1 deletion ui/shared/chart/ChartMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import domToImage from 'dom-to-image';
import React from 'react';

import type { TimeChartItem } from './types';
import type { Resolution } from '@blockscout/stats-types';

import type { Route } from 'nextjs-routes';
import { route } from 'nextjs-routes';
Expand All @@ -33,11 +34,27 @@ export type Props = {
isLoading: boolean;
chartRef: React.RefObject<HTMLDivElement>;
href?: Route;
resolution?: Resolution;
zoomRange?: [ Date, Date ];
handleZoom: (range: [ Date, Date ]) => void;
handleZoomReset: () => void;
}

const DOWNLOAD_IMAGE_SCALE = 5;

const ChartMenu = ({ items, title, description, units, isLoading, chartRef, href }: Props) => {
const ChartMenu = ({
items,
title,
description,
units,
isLoading,
chartRef,
href,
resolution,
zoomRange,
handleZoom,
handleZoomReset,
}: Props) => {
const pngBackgroundColor = useColorModeValue('white', 'black');
const [ isFullscreen, setIsFullscreen ] = React.useState(false);

Expand Down Expand Up @@ -172,6 +189,10 @@ const ChartMenu = ({ items, title, description, units, isLoading, chartRef, href
description={ description }
onClose={ clearFullscreenChart }
units={ units }
resolution={ resolution }
zoomRange={ zoomRange }
handleZoom={ handleZoom }
handleZoomReset={ handleZoomReset }
/>
) }
</>
Expand Down
32 changes: 29 additions & 3 deletions ui/shared/chart/ChartTooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as d3 from 'd3';
import React from 'react';

import { Resolution } from '@blockscout/stats-types';
import type { TimeChartData } from 'ui/shared/chart/types';

import ChartTooltipBackdrop, { useRenderBackdrop } from './tooltip/ChartTooltipBackdrop';
Expand All @@ -21,9 +22,21 @@ interface Props {
yScale: d3.ScaleLinear<number, number>;
anchorEl: SVGRectElement | null;
noAnimation?: boolean;
resolution?: Resolution;
}

const ChartTooltip = ({ xScale, yScale, width, tooltipWidth = 200, height, data, anchorEl, noAnimation, ...props }: Props) => {
const ChartTooltip = ({
xScale,
yScale,
width,
tooltipWidth = 200,
height,
data,
anchorEl,
noAnimation,
resolution,
...props
}: Props) => {
const ref = React.useRef<SVGGElement>(null);
const trackerId = React.useRef<number>();
const isVisible = React.useRef(false);
Expand Down Expand Up @@ -150,12 +163,25 @@ const ChartTooltip = ({ xScale, yScale, width, tooltipWidth = 200, height, data,
{ data.map(({ name }) => <ChartTooltipPoint key={ name }/>) }
<ChartTooltipContent>
<ChartTooltipBackdrop/>
<ChartTooltipTitle/>
<ChartTooltipRow label="Date" lineNum={ 1 }/>
<ChartTooltipTitle resolution={ resolution }/>
<ChartTooltipRow label={ getDateLabel(resolution) } lineNum={ 1 }/>
{ data.map(({ name }, index) => <ChartTooltipRow key={ name } label={ name } lineNum={ index + 1 }/>) }
</ChartTooltipContent>
</g>
);
};

export default React.memo(ChartTooltip);

function getDateLabel(resolution?: Resolution): string {
switch (resolution) {
case Resolution.WEEK:
return 'Dates';
case Resolution.MONTH:
return 'Month';
case Resolution.YEAR:
return 'Year';
default:
return 'Date';
}
}
11 changes: 7 additions & 4 deletions ui/shared/chart/ChartWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import IconSvg from 'ui/shared/IconSvg';

import ChartMenu from './ChartMenu';
import ChartWidgetContent from './ChartWidgetContent';
import useZoomReset from './useZoomReset';
import useZoom from './useZoom';

export type Props = {
items?: Array<TimeChartItem>;
Expand Down Expand Up @@ -45,7 +45,7 @@ const ChartWidget = ({
href,
}: Props) => {
const ref = useRef<HTMLDivElement>(null);
const { isZoomResetInitial, handleZoom, handleZoomReset } = useZoomReset();
const { zoomRange, handleZoom, handleZoomReset } = useZoom();

const borderColor = useColorModeValue('gray.200', 'gray.600');

Expand All @@ -60,7 +60,7 @@ const ChartWidget = ({
title={ title }
emptyText={ emptyText }
handleZoom={ handleZoom }
isZoomResetInitial={ isZoomResetInitial }
zoomRange={ zoomRange }
noAnimation={ noAnimation }
/>
);
Expand Down Expand Up @@ -116,7 +116,7 @@ const ChartWidget = ({
<Flex ml="auto" columnGap={ 2 }>
<Tooltip label="Reset zoom">
<IconButton
hidden={ isZoomResetInitial }
hidden={ !zoomRange }
aria-label="Reset zoom"
colorScheme="blue"
w={ 9 }
Expand All @@ -137,6 +137,9 @@ const ChartWidget = ({
isLoading={ isLoading }
chartRef={ ref }
units={ units }
handleZoom={ handleZoom }
handleZoomReset={ handleZoomReset }
zoomRange={ zoomRange }
/>
) }
</Flex>
Expand Down
12 changes: 8 additions & 4 deletions ui/shared/chart/ChartWidgetContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Box, Center, Flex, Link, Skeleton, Text } from '@chakra-ui/react';
import React from 'react';

import type { TimeChartItem } from './types';
import type { Resolution } from '@blockscout/stats-types';

import { apos } from 'lib/html-entities';

Expand All @@ -15,10 +16,11 @@ export type Props = {
isLoading?: boolean;
isError?: boolean;
emptyText?: string;
handleZoom: () => void;
isZoomResetInitial: boolean;
zoomRange?: [ Date, Date ];
handleZoom: (range: [ Date, Date ]) => void;
isEnlarged?: boolean;
noAnimation?: boolean;
resolution?: Resolution;
}

const ChartWidgetContent = ({
Expand All @@ -28,10 +30,11 @@ const ChartWidgetContent = ({
isError,
units,
emptyText,
zoomRange,
handleZoom,
isZoomResetInitial,
isEnlarged,
noAnimation,
resolution,
}: Props) => {
const hasItems = items && items.length > 2;

Expand Down Expand Up @@ -71,12 +74,13 @@ const ChartWidgetContent = ({
<Box flexGrow={ 1 } maxW="100%" position="relative" h="100%">
<ChartWidgetGraph
items={ items }
zoomRange={ zoomRange }
onZoom={ handleZoom }
isZoomResetInitial={ isZoomResetInitial }
title={ title }
units={ units }
isEnlarged={ isEnlarged }
noAnimation={ noAnimation }
resolution={ resolution }
/>
<WatermarkIcon w="162px" h="15%"/>
</Box>
Expand Down
Loading

0 comments on commit e22db69

Please sign in to comment.