Skip to content
Snippets Groups Projects
Commit 40514713 authored by Bjarke Madsen's avatar Bjarke Madsen
Browse files

Style download buttons differently and add image dropdown download box

parent 925a219e
No related branches found
No related tags found
No related merge requests found
import React from 'react';
import * as XLSX from "xlsx";
import {ExportType} from "../helpers/constants";
import { ExportType } from "../helpers/constants";
import { FaDownload } from 'react-icons/fa';
interface DownloadProps {
......@@ -44,7 +45,7 @@ function convertToExcel(jsonData: any[], sheetName = "Sheet1"): Blob {
const ws = XLSX.utils.json_to_sheet(jsonData);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, sheetName);
const wbout = XLSX.write(wb, {bookType: 'xlsx', type: 'binary'});
const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'binary' });
const buffer = new ArrayBuffer(wbout.length);
const view = new Uint8Array(buffer);
......@@ -53,15 +54,15 @@ function convertToExcel(jsonData: any[], sheetName = "Sheet1"): Blob {
view[i] = wbout.charCodeAt(i) & 0xFF;
}
return new Blob([buffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8'});
return new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8' });
}
const DownloadDataButton: React.FC<DownloadProps> = ({data, filename, exportType}) => {
const DownloadDataButton: React.FC<DownloadProps> = ({ data, filename, exportType }) => {
const downloadData = () => {
let convertedData;
let fileType;
let contentType ;
let contentType;
switch (exportType) {
case ExportType.EXCEL: {
......@@ -79,7 +80,7 @@ const DownloadDataButton: React.FC<DownloadProps> = ({data, filename, exportType
}
}
const blob = new Blob([convertedData], {type: contentType});
const blob = new Blob([convertedData], { type: contentType });
filename = filename.endsWith(fileType) ? filename : `${filename}.${fileType}`;
const link = document.createElement('a');
......@@ -90,9 +91,17 @@ const DownloadDataButton: React.FC<DownloadProps> = ({data, filename, exportType
document.body.removeChild(link);
}
let classname = 'downloadbutton';
if (exportType === ExportType.CSV) {
classname += ' downloadcsv';
}
else if (exportType === ExportType.EXCEL) {
classname += ' downloadexcel';
}
return (
<>
<button onClick={downloadData}>Download {exportType}</button>
<button className={classname} onClick={downloadData}>{exportType} <FaDownload /></button>
</>
);
}
......
import React, { useContext, useState } from 'react';
import React, { useContext, useState, useRef, useEffect } from 'react';
import domtoimage from 'dom-to-image';
import { ImageType } from "../helpers/constants";
import { ChartContainerContext } from "../helpers/ChartContainerProvider";
import { FaDownload } from 'react-icons/fa';
interface DownloadImageChartProps {
filename: string;
......@@ -9,10 +10,12 @@ interface DownloadImageChartProps {
const DownloadImageChartButton: React.FC<DownloadImageChartProps> = ({ filename }) => {
const chartContainerRef = useContext(ChartContainerContext);
const [exportType, setExportType] = useState<ImageType>(ImageType.PNG);
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);
const downloadChartAsImage = async () => {
const downloadChartAsImage = async (exportType) => {
if (chartContainerRef?.current) {
setIsOpen(false);
const scale = 1;
const commonStyle = {
......@@ -37,7 +40,7 @@ const DownloadImageChartButton: React.FC<DownloadImageChartProps> = ({ filename
case ImageType.PNG:
default:
dataUrl = await domtoimage.toPng(chartContainerRef.current, {
style: commonStyle
style: commonStyle
});
break;
}
......@@ -52,15 +55,42 @@ const DownloadImageChartButton: React.FC<DownloadImageChartProps> = ({ filename
}
}
const toggleDropdown = () => {
setIsOpen(!isOpen);
};
const handleClickOutside = (event) => {
if (dropdownRef.current && !(dropdownRef.current as HTMLElement).contains(event.target)) {
setIsOpen(false);
}
};
useEffect(() => {
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
return (
<>
<select value={exportType} onChange={(e) => setExportType(e.target.value as ImageType)}>
<option value={ImageType.PNG}>PNG</option>
<option value={ImageType.JPEG}>JPEG</option>
<option value={ImageType.SVG}>SVG</option>
</select>
<button onClick={downloadChartAsImage}>Download Chart</button>
</>
<div className={`image-dropdown`} ref={dropdownRef}>
<button className={`downloadbutton downloadimage`} onClick={toggleDropdown}>
IMAGE <FaDownload />
</button>
<div className={`image-options ${isOpen ? 'open' : ''}`}>
<div className={`imageoption downloadpng`} onClick={() => downloadChartAsImage(ImageType.PNG)}>
<span>PNG</span>
</div>
<div className={`imageoption downloadjpeg`} onClick={() => downloadChartAsImage(ImageType.JPEG)}>
<span>JPEG</span>
</div>
<div className={`imageoption downloadsvg`} onClick={() => downloadChartAsImage(ImageType.SVG)}>
<span>SVG</span>
</div>
</div>
</div>
);
}
......
......@@ -94,4 +94,66 @@
background-color: pink;
text-align: center;
padding: 2em;
}
.downloadbutton {
width: 6rem;
height: 2.8rem;
color: white;
font-weight: bold;
border: none;
}
.downloadbutton svg {
margin-bottom: 0.25rem;
margin-left: 0.1rem;
}
.downloadimage {
background-color: deepskyblue;
width: 100%;
}
.downloadcsv {
background-color: #071ddf;
}
.downloadexcel {
background-color: #33c481
}
.image-dropdown {
width: 10rem;
}
.image-options.open {
display: flex;
}
.image-options {
background-color: white;
position: absolute;
width: 8.5rem;
display: none;
flex-direction: column;
border: deepskyblue 1px solid;
z-index: 10; // make sure it's on top of everything else
}
.imageoption {
padding: 0.5rem;
cursor: pointer;
color: $dark-teal;
font-weight: bold;
}
// add margin left to text within imageoption
.imageoption > span {
margin-left: 0.25rem;
}
.imageoption::after {
// have a line under each option
content: "";
display: block;
border-bottom: grey 1px solid;
}
\ No newline at end of file
......@@ -6,7 +6,7 @@ import { createBudgetDataset } from "../helpers/dataconversion";
import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter";
import LineGraph from "../components/graphing/LineGraph";
import {ExportType, Sections} from '../helpers/constants';
import { ExportType, Sections } from '../helpers/constants';
import DownloadDataButton from "../components/DownloadDataButton";
import { FilterSelectionContext } from '../helpers/FilterSelectionProvider';
import DownloadImageChartButton from "../components/DownloadImageChartButton";
......@@ -15,8 +15,8 @@ import { useData } from '../helpers/useData';
function BudgetPage(): ReactElement {
const {filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
const {data: budgetResponse, nrens} = useData<Budget>('/api/budget/', setFilterSelection);
const { filterSelection, setFilterSelection } = useContext(FilterSelectionContext);
const { data: budgetResponse, nrens } = useData<Budget>('/api/budget/', setFilterSelection);
const budgetData = createBudgetDataset(budgetResponse);
......@@ -31,20 +31,21 @@ function BudgetPage(): ReactElement {
/>
return (
<DataPage title="Budget of NRENs per Year"
description='The graph shows the NRENs budget capita (in Million €) per year .
<DataPage title="Budget of NRENs per Year"
description='The graph shows the NRENs budget capita (in Million €) per year .
On hovering over the graphs data points will give NRENs budget share in that year. This graph can be used to compare, selecting multiple NRENs to see the
fluctuation of budget over years and with other NRENs.' category={Sections.Organisation} filter={filterNode}>
<>
<Row>
<DownloadDataButton data={budgetResponse} filename="budget_data.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={budgetResponse} filename="budget_data.csv" exportType={ExportType.CSV} />
<DownloadDataButton data={budgetResponse} filename="budget_data.xlsx"
exportType={ExportType.EXCEL}/>
exportType={ExportType.EXCEL} />
<DownloadImageChartButton filename="budget_data" />
</Row>
<Row>
<DownloadImageChartButton filename="budget_data"/>
<ChartContainer>
<LineGraph data={budgetData}/>
<LineGraph data={budgetData} />
</ChartContainer>
</Row>
</>
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment