Commit fa291707 authored by tom goriunov's avatar tom goriunov Committed by GitHub

Merge branch 'main' into client-api-calls

parents 28b59628 3ae3b14c
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 3c0-.184.15-.333.333-.333h4.334v2c0 .368.298.666.666.666h2v1.334h1.334v-.92c0-.441-.176-.865-.489-1.178L9.431 1.822a1.667 1.667 0 0 0-1.179-.489H4.333c-.92 0-1.666.747-1.666 1.667v3.667H4V3Zm0 10v-1H2.667v1c0 .92.746 1.667 1.666 1.667H11c.92 0 1.667-.746 1.667-1.667v-1h-1.334v1a.333.333 0 0 1-.333.333H4.333A.333.333 0 0 1 4 13Zm1.167-5.833H4.75c-.575 0-1.042.466-1.042 1.041v2.084c0 .575.466 1.041 1.042 1.041h.417a1.04 1.04 0 0 0 1.041-1.041v-.209a.418.418 0 0 0-.416-.416.418.418 0 0 0-.417.416v.209a.209.209 0 0 1-.208.208H4.75a.209.209 0 0 1-.208-.208V8.208c0-.114.093-.208.208-.208h.417a.21.21 0 0 1 .208.208v.209a.417.417 0 0 0 .833 0v-.209a1.04 1.04 0 0 0-1.041-1.041Zm2.666 0a1.21 1.21 0 0 0-.599 2.258l.662.377a.375.375 0 0 1-.188.7h-.666a.418.418 0 0 0-.417.417c0 .23.188.417.417.417h.666a1.21 1.21 0 0 0 .6-2.258l-.662-.377a.375.375 0 0 1 .188-.7h.458a.418.418 0 0 0 0-.833h-.459Zm2.125.416v.823c0 .6.144 1.188.417 1.719a3.737 3.737 0 0 0 .417-1.719v-.823a.417.417 0 0 1 .833 0v.823a4.58 4.58 0 0 1-.77 2.542l-.134.2a.415.415 0 0 1-.692 0l-.133-.2a4.58 4.58 0 0 1-.771-2.542v-.823a.417.417 0 0 1 .833 0Z" fill="currentColor"/>
</svg>
import { unparse } from 'papaparse';
export default function saveAsCSV(headerRows: Array<string>, dataRows: Array<Array<string>>, filename: string) {
const csv = unparse([
headerRows,
...dataRows,
]);
const blob = new Blob([ csv ], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.click();
link.remove();
URL.revokeObjectURL(url);
}
......@@ -5,9 +5,12 @@ import React, { useRef, useCallback, useState } from 'react';
import type { TimeChartItem } from './types';
import imageIcon from 'icons/image.svg';
import repeatArrow from 'icons/repeat_arrow.svg';
import repeatArrowIcon from 'icons/repeat_arrow.svg';
import scopeIcon from 'icons/scope.svg';
import svgFileIcon from 'icons/svg_file.svg';
import dotsIcon from 'icons/vertical_dots.svg';
import dayjs from 'lib/date/dayjs';
import saveAsCSV from 'lib/saveAsCSV';
import ChartWidgetGraph from './ChartWidgetGraph';
import ChartWidgetSkeleton from './ChartWidgetSkeleton';
......@@ -40,18 +43,10 @@ const ChartWidget = ({ items, title, description, isLoading, chartHeight }: Prop
const showChartFullscreen = useCallback(() => {
setIsFullscreen(true);
if (!document.fullscreenElement && document.documentElement.requestFullscreen) {
document.documentElement.requestFullscreen();
}
}, []);
const clearFullscreenChart = useCallback(() => {
setIsFullscreen(false);
if (document.fullscreenElement) {
document.exitFullscreen();
}
}, []);
const handleFileSaveClick = useCallback(() => {
......@@ -78,6 +73,19 @@ const ChartWidget = ({ items, title, description, isLoading, chartHeight }: Prop
}
}, [ title ]);
const handleSVGSavingClick = useCallback(() => {
if (items) {
const headerRows = [
'Date', 'Value',
];
const dataRows = items.map((item) => [
dayjs(item.date).format('YYYY-MM-DD'), String(item.value),
]);
saveAsCSV(headerRows, dataRows, `${ title } (Blockscout stats)`);
}
}, [ items, title ]);
if (isLoading) {
return <ChartWidgetSkeleton hasDescription={ Boolean(description) } chartHeight={ chartHeight }/>;
}
......@@ -132,7 +140,7 @@ const ChartWidget = ({ items, title, description, isLoading, chartHeight }: Prop
size="sm"
variant="outline"
onClick={ handleZoomResetClick }
icon={ <Icon as={ repeatArrow } w={ 4 } h={ 4 }/> }
icon={ <Icon as={ repeatArrowIcon } w={ 4 } h={ 4 }/> }
/>
</Tooltip>
......@@ -161,6 +169,7 @@ const ChartWidget = ({ items, title, description, isLoading, chartHeight }: Prop
<Icon as={ scopeIcon } boxSize={ 4 } mr={ 3 }/>
View fullscreen
</MenuItem>
<MenuItem
display="flex"
alignItems="center"
......@@ -169,6 +178,15 @@ const ChartWidget = ({ items, title, description, isLoading, chartHeight }: Prop
<Icon as={ imageIcon } boxSize={ 4 } mr={ 3 }/>
Save as PNG
</MenuItem>
<MenuItem
display="flex"
alignItems="center"
onClick={ handleSVGSavingClick }
>
<Icon as={ svgFileIcon } boxSize={ 4 } mr={ 3 }/>
Save as CSV
</MenuItem>
</MenuList>
</Menu>
</Grid>
......
......@@ -46,19 +46,10 @@ const StatsFilters = ({
templateAreas={{
base: `"input input"
"section interval"`,
lg: `"input section interval"`,
lg: `"section interval input"`,
}}
gridTemplateColumns={{ base: 'repeat(2, minmax(0, 1fr))', lg: '1fr auto auto' }}
gridTemplateColumns={{ base: 'repeat(2, minmax(0, 1fr))', lg: 'auto auto 1fr' }}
>
<GridItem
w="100%"
area="input"
>
<FilterInput
onChange={ onFilterInputChange }
placeholder="Find chart, metric..."/>
</GridItem>
<GridItem
w={{ base: '100%', lg: 'auto' }}
area="section"
......@@ -80,6 +71,15 @@ const StatsFilters = ({
onSelect={ onIntervalChange }
/>
</GridItem>
<GridItem
w="100%"
area="input"
>
<FilterInput
onChange={ onFilterInputChange }
placeholder="Find chart, metric..."/>
</GridItem>
</Grid>
);
};
......
......@@ -3588,6 +3588,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.36.tgz#c0d5f2fe76b47b63e0e0efc3d2049a9970d68794"
integrity sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==
"@types/papaparse@^5.3.5":
version "5.3.5"
resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-5.3.5.tgz#e5ad94b1fe98e2a8ea0b03284b83d2cb252bbf39"
integrity sha512-R1icl/hrJPFRpuYj9PVG03WBAlghJj4JW9Py5QdR8FFSxaLmZRyu7xYDCCBZIJNfUv3MYaeBbhBoX958mUTAaw==
dependencies:
"@types/node" "*"
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
......@@ -7708,6 +7715,11 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
papaparse@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.3.2.tgz#d1abed498a0ee299f103130a6109720404fbd467"
integrity sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment