Commit b8255d03 authored by Yuri Mikhin's avatar Yuri Mikhin Committed by Yuri Mikhin

Add "Save to PNG" option to charts.

parent 3fda7486
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m12.18 3.765-1.944-1.944a1.674 1.674 0 0 0-1.179-.488H4.333c-.92 0-1.666.746-1.666 1.667v10c0 .92.746 1.667 1.667 1.667H11c.917 0 1.667-.75 1.667-1.667V4.943c0-.44-.175-.865-.487-1.178ZM11.417 13c0 .23-.187.417-.417.417H4.334A.417.417 0 0 1 3.917 13V3.003c0-.23.186-.416.416-.416H8.5v2.08c0 .46.373.833.833.833h2.06V13h.024ZM8.273 8.938a.365.365 0 0 0-.303.162l-1.032 1.55-.305-.456a.363.363 0 0 0-.606-.001l-1.215 1.823a.364.364 0 0 0-.018.374c.063.12.186.192.297.192h5.104a.365.365 0 0 0 .304-.566L8.554 9.1c-.044-.103-.158-.162-.28-.162ZM6 8.833a.833.833 0 1 0 0-1.666.833.833 0 0 0 0 1.666Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.667 2A.667.667 0 0 0 2 2.667V6a.667.667 0 0 0 1.333 0V3.333H6A.667.667 0 1 0 6 2H2.667Zm0 12A.667.667 0 0 1 2 13.333V10a.667.667 0 0 1 1.333 0v2.667H6A.667.667 0 1 1 6 14H2.667ZM14 2.667A.667.667 0 0 0 13.333 2H10a.667.667 0 0 0 0 1.333h2.667V6A.667.667 0 1 0 14 6V2.667ZM13.333 14a.667.667 0 0 0 .667-.667V10a.667.667 0 0 0-1.333 0v2.667H10A.667.667 0 1 0 10 14h3.333Z" fill="currentColor"/>
</svg>
import { Box, Grid, Icon, IconButton, Menu, MenuButton, MenuItem, MenuList, Text, Tooltip, useColorModeValue, VisuallyHidden } from '@chakra-ui/react';
import React, { useCallback, useState } from 'react';
import domToImage from 'dom-to-image';
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 scopeIcon from 'icons/scope.svg';
import dotsIcon from 'icons/vertical_dots.svg';
import ChartWidgetGraph from './ChartWidgetGraph';
......@@ -17,7 +20,10 @@ type Props = {
isLoading: boolean;
}
const DOWNLOAD_IMAGE_SCALE = 5;
const ChartWidget = ({ items, title, description, isLoading }: Props) => {
const ref = useRef<HTMLDivElement>(null);
const [ isFullscreen, setIsFullscreen ] = useState(false);
const [ isZoomResetInitial, setIsZoomResetInitial ] = React.useState(true);
......@@ -47,6 +53,30 @@ const ChartWidget = ({ items, title, description, isLoading }: Props) => {
}
}, []);
const handleFileSaveClick = useCallback(() => {
if (ref.current) {
domToImage.toPng(ref.current,
{
quality: 100,
bgcolor: 'white',
width: ref.current.offsetWidth * DOWNLOAD_IMAGE_SCALE,
height: ref.current.offsetHeight * DOWNLOAD_IMAGE_SCALE,
filter: (node) => node.nodeName !== 'BUTTON',
style: {
transform: `scale(${ DOWNLOAD_IMAGE_SCALE })`,
'transform-origin': 'top left',
},
})
.then((dataUrl) => {
const link = document.createElement('a');
link.download = `${ title } (Blockscout chart).png`;
link.href = dataUrl;
link.click();
link.remove();
});
}
}, [ title ]);
if (isLoading) {
return <ChartWidgetSkeleton/>;
}
......@@ -55,6 +85,7 @@ const ChartWidget = ({ items, title, description, isLoading }: Props) => {
return (
<>
<Box
ref={ ref }
padding={{ base: 3, lg: 4 }}
borderRadius="md"
border="1px"
......@@ -119,7 +150,22 @@ const ChartWidget = ({ items, title, description, isLoading }: Props) => {
</VisuallyHidden>
</MenuButton>
<MenuList>
<MenuItem onClick={ showChartFullscreen }>View fullscreen</MenuItem>
<MenuItem
display="flex"
alignItems="center"
onClick={ showChartFullscreen }
>
<Icon as={ scopeIcon } boxSize={ 4 } mr={ 3 }/>
View fullscreen
</MenuItem>
<MenuItem
display="flex"
alignItems="center"
onClick={ handleFileSaveClick }
>
<Icon as={ imageIcon } boxSize={ 4 } mr={ 3 }/>
Save as PNG
</MenuItem>
</MenuList>
</Menu>
</Grid>
......
......@@ -3476,6 +3476,11 @@
"@types/d3-transition" "*"
"@types/d3-zoom" "*"
"@types/dom-to-image@^2.6.4":
version "2.6.4"
resolved "https://registry.yarnpkg.com/@types/dom-to-image/-/dom-to-image-2.6.4.tgz#008411e23903cb0ee9e51a42ab8358c609541ee8"
integrity sha512-UddUdGF1qulrSDulkz3K2Ypq527MR6ixlgAzqLbxSiQ0icx0XDlIV+h4+edmjq/1dqn0KgN0xGSe1kI9t+vGuw==
"@types/estree@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
......@@ -5050,6 +5055,11 @@ dom-serializer@^1.0.1:
domhandler "^4.2.0"
entities "^2.0.0"
dom-to-image@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867"
integrity sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==
domelementtype@^2.0.1, domelementtype@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
......
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