Skip to content
Snippets Groups Projects
Commit 9d95b6e6 authored by Mohammad Torkashvand's avatar Mohammad Torkashvand
Browse files

added excel download button to the pages

parent 9f5b9a45
No related branches found
No related tags found
No related merge requests found
This diff is collapsed.
...@@ -54,7 +54,8 @@ ...@@ -54,7 +54,8 @@
"react-chartjs-2": "^5.1.0", "react-chartjs-2": "^5.1.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-icons": "4.8.0", "react-icons": "4.8.0",
"react-router-dom": "^6.5.0" "react-router-dom": "^6.5.0",
"xlsx": "^0.18.5"
}, },
"description": "## development environment", "description": "## development environment",
"main": "index.js", "main": "index.js",
......
import React from 'react'; import React from 'react';
import * as XLSX from "xlsx";
import {ExportType} from "../helpers/constants";
interface DownloadCSVProps { interface DownloadCSVProps {
data: any[]; data: any[];
filename?: string; filename: string;
exportType: ExportType;
} }
...@@ -36,12 +40,48 @@ function convertToCSV(jsonData: any[]): string { ...@@ -36,12 +40,48 @@ function convertToCSV(jsonData: any[]): string {
return [header.join(','), ...rows].join('\r\n'); return [header.join(','), ...rows].join('\r\n');
} }
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 buffer = new ArrayBuffer(wbout.length);
const view = new Uint8Array(buffer);
for (let i = 0; i < wbout.length; i++) {
// Convert each character of the binary workbook string to an 8-bit integer and store in the Uint8Array 'view' for blob creation.
view[i] = wbout.charCodeAt(i) & 0xFF;
}
return new Blob([buffer], {type: 'application/octet-stream'});
}
const DownloadDataButton: React.FC<DownloadCSVProps> = ({data, filename, exportType}) => {
const downloadData = () => {
let convertedData;
let fileType;
let contentType ;
switch (exportType) {
case ExportType.EXCEL: {
convertedData = convertToExcel(data);
fileType = 'xlsx';
contentType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8';
break;
}
case ExportType.CSV:
default: {
convertedData = convertToCSV(data);
fileType = 'csv';
contentType = 'text/csv;charset=UTF-8';
break;
}
}
const DownloadCSVButton: React.FC<DownloadCSVProps> = ({ data, filename = 'data.csv' }) => { const blob = new Blob([convertedData], {type: contentType});
filename = filename.endsWith(fileType) ? filename : `${filename}.${fileType}`;
const downloadCSV = () => {
const csv = convertToCSV(data);
const blob = new Blob([csv], { type: 'text/csv' });
const link = document.createElement('a'); const link = document.createElement('a');
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
link.download = filename; link.download = filename;
...@@ -52,9 +92,9 @@ const DownloadCSVButton: React.FC<DownloadCSVProps> = ({ data, filename = 'data. ...@@ -52,9 +92,9 @@ const DownloadCSVButton: React.FC<DownloadCSVProps> = ({ data, filename = 'data.
return ( return (
<> <>
<button onClick={downloadCSV}>Download CSV</button> <button onClick={downloadData}>Download {exportType}</button>
</> </>
); );
} }
export default DownloadCSVButton; export default DownloadDataButton;
...@@ -4,4 +4,9 @@ export enum Sections { ...@@ -4,4 +4,9 @@ export enum Sections {
ConnectedUsers = 'CONNECTED USERS', ConnectedUsers = 'CONNECTED USERS',
Network = 'NETWORK', Network = 'NETWORK',
Services = 'SERVICES', Services = 'SERVICES',
}
export enum ExportType {
CSV = "CSV",
EXCEL = "EXCEL",
} }
\ No newline at end of file
...@@ -6,8 +6,8 @@ import { createBudgetDataset, getYearsAndNrens, loadDataWithFilterNrenSelectionF ...@@ -6,8 +6,8 @@ import { createBudgetDataset, getYearsAndNrens, loadDataWithFilterNrenSelectionF
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter"; import Filter from "../components/graphing/Filter";
import LineGraph from "../components/graphing/LineGraph"; import LineGraph from "../components/graphing/LineGraph";
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
interface inputProps { interface inputProps {
filterSelection: FilterSelection filterSelection: FilterSelection
...@@ -46,7 +46,8 @@ function BudgetPage({ filterSelection, setFilterSelection }: inputProps): ReactE ...@@ -46,7 +46,8 @@ function BudgetPage({ filterSelection, setFilterSelection }: inputProps): ReactE
fluctuation of budget over years and with other NRENs.' category={Sections.Organisation} filter={filterNode}> fluctuation of budget over years and with other NRENs.' category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={budgetResponse} filename="budget_data.csv"/> <DownloadDataButton data={budgetResponse} filename="budget_data.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={budgetResponse} filename="budget_data.xlsx" exportType={ExportType.EXCEL}/>
</Row> </Row>
<Row> <Row>
<LineGraph data={budgetData} /> <LineGraph data={budgetData} />
......
...@@ -7,8 +7,8 @@ import { createChargingStructureDataLookup, getYearsAndNrens, loadDataWithFilter ...@@ -7,8 +7,8 @@ import { createChargingStructureDataLookup, getYearsAndNrens, loadDataWithFilter
import ColorPill from "../components/ColorPill"; import ColorPill from "../components/ColorPill";
import DataPage from "../components/DataPage"; import DataPage from "../components/DataPage";
import Filter from "../components/graphing/Filter"; import Filter from "../components/graphing/Filter";
import { Sections } from "../helpers/constants"; import {ExportType, Sections} from "../helpers/constants";
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
ChartJS.register( ChartJS.register(
...@@ -58,7 +58,8 @@ function ChargingStructurePage({ filterSelection, setFilterSelection }: inputPro ...@@ -58,7 +58,8 @@ function ChargingStructurePage({ filterSelection, setFilterSelection }: inputPro
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={chargingStructureData} filename="charging_mechanism_of_nrens_per_year.csv"/> <DownloadDataButton data={chargingStructureData} filename="charging_mechanism_of_nrens_per_year.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={chargingStructureData} filename="charging_mechanism_of_nrens_per_year.xlsx" exportType={ExportType.EXCEL} />
</Row> </Row>
<Table className="charging-struct-table" striped bordered responsive> <Table className="charging-struct-table" striped bordered responsive>
<colgroup> <colgroup>
......
...@@ -5,8 +5,8 @@ import { ECProject, FilterSelection } from "../Schema"; ...@@ -5,8 +5,8 @@ import { ECProject, FilterSelection } from "../Schema";
import { createECProjectsDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from '../helpers/dataconversion'; import { createECProjectsDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from '../helpers/dataconversion';
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter" import Filter from "../components/graphing/Filter"
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
interface inputProps { interface inputProps {
...@@ -62,7 +62,8 @@ function ECProjects({ filterSelection, setFilterSelection }: inputProps) { ...@@ -62,7 +62,8 @@ function ECProjects({ filterSelection, setFilterSelection }: inputProps) {
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={projectData} filename="nren_involvement_in_european_commission_projects.csv"/> <DownloadDataButton data={projectData} filename="nren_involvement_in_european_commission_projects.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={projectData} filename="nren_involvement_in_european_commission_projects.xlsx" exportType={ExportType.EXCEL}/>
</Row> </Row>
<Table borderless className='compendium-table'> <Table borderless className='compendium-table'>
<thead> <thead>
......
...@@ -8,9 +8,9 @@ import { FundingSource, FilterSelection } from "../Schema"; ...@@ -8,9 +8,9 @@ import { FundingSource, FilterSelection } from "../Schema";
import { createFundingSourceDataset, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion"; import { createFundingSourceDataset, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion";
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter" import Filter from "../components/graphing/Filter"
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import ColorBadge from '../components/ColorBadge'; import ColorBadge from '../components/ColorBadge';
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
export const chartOptions = { export const chartOptions = {
maintainAspectRatio: false, maintainAspectRatio: false,
...@@ -157,7 +157,8 @@ function FundingSourcePage({ filterSelection, setFilterSelection }: inputProps) ...@@ -157,7 +157,8 @@ function FundingSourcePage({ filterSelection, setFilterSelection }: inputProps)
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={fundingSourceData} filename="income_source_of_nren_per_year.csv"/> <DownloadDataButton data={fundingSourceData} filename="income_source_of_nren_per_year.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={fundingSourceData} filename="income_source_of_nren_per_year.xlsx" exportType={ExportType.EXCEL}/>
</Row> </Row>
<div> <div>
<FundingSourceLegend/> <FundingSourceLegend/>
......
import React, { useEffect, useMemo, useState } from 'react'; import React, {useEffect, useMemo, useState} from 'react';
import {Row, Table} from "react-bootstrap"; import {Row, Table} from "react-bootstrap";
import { Organisation, FilterSelection } from "../Schema"; import { Organisation, FilterSelection } from "../Schema";
import { createOrganisationDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion"; import { createOrganisationDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion";
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter" import Filter from "../components/graphing/Filter"
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
function getJSXFromMap(data: Map<string, Map<number, Organisation[]>>) { function getJSXFromMap(data: Map<string, Map<number, Organisation[]>>) {
...@@ -57,7 +57,8 @@ function ParentOrganisation({ filterSelection, setFilterSelection }: inputProps) ...@@ -57,7 +57,8 @@ function ParentOrganisation({ filterSelection, setFilterSelection }: inputProps)
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={organisationData} filename="nren_parent_organisations.csv"/> <DownloadDataButton data={organisationData} filename="nren_parent_organisations.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={organisationData} filename="nren_parent_organisations.xlsx" exportType={ExportType.EXCEL}/>
</Row> </Row>
<Table borderless className='compendium-table'> <Table borderless className='compendium-table'>
<thead> <thead>
......
...@@ -6,11 +6,11 @@ import { NrenStaff, FilterSelection } from "../Schema"; ...@@ -6,11 +6,11 @@ import { NrenStaff, FilterSelection } from "../Schema";
import { createNRENStaffDataset, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion"; import { createNRENStaffDataset, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion";
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter" import Filter from "../components/graphing/Filter"
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import WithLegend from '../components/WithLegend'; import WithLegend from '../components/WithLegend';
import htmlLegendPlugin from '../plugins/HTMLLegendPlugin'; import htmlLegendPlugin from '../plugins/HTMLLegendPlugin';
import {Row} from "react-bootstrap"; import {Row} from "react-bootstrap";
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
ChartJS.register( ChartJS.register(
CategoryScale, CategoryScale,
...@@ -153,14 +153,15 @@ function StaffGraph({ filterSelection, setFilterSelection, roles = false }: inpu ...@@ -153,14 +153,15 @@ function StaffGraph({ filterSelection, setFilterSelection, roles = false }: inpu
? "The graph shows the roles of NREN employees. On hovering over the graph will give the percentage of employees in that role. This graph can be used to compare, selecting multiple NRENs to see the fluctuation of roles over selected year and with other NRENs." ? "The graph shows the roles of NREN employees. On hovering over the graph will give the percentage of employees in that role. This graph can be used to compare, selecting multiple NRENs to see the fluctuation of roles over selected year and with other NRENs."
: "The graph shows the types of employment for NREN employees. On hovering over the graphs will give the percentage of employees in that type of employment. This graph can be used to compare, selecting multiple NRENs to see the fluctuation of types of employment over selected year and with other NRENs."; : "The graph shows the types of employment for NREN employees. On hovering over the graphs will give the percentage of employees in that type of employment. This graph can be used to compare, selecting multiple NRENs to see the fluctuation of types of employment over selected year and with other NRENs.";
const filename = roles ? "roles_of_nren_employees.csv" : "types_of_employment_for_nren.csv"; const filename = roles ? "roles_of_nren_employees" : "types_of_employment_for_nrens";
return ( return (
<DataPage title={title} <DataPage title={title}
description={description} description={description}
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={staffData} filename={filename}/> <DownloadDataButton data={staffData} filename={filename} exportType={ExportType.CSV}/>
<DownloadDataButton data={staffData} filename={filename} exportType={ExportType.EXCEL}/>
</Row> </Row>
<WithLegend> <WithLegend>
<div className="chart-container" style={{'height': `${height}rem`}}> <div className="chart-container" style={{'height': `${height}rem`}}>
......
...@@ -5,8 +5,8 @@ import { Organisation, FilterSelection } from "../Schema"; ...@@ -5,8 +5,8 @@ import { Organisation, FilterSelection } from "../Schema";
import { createOrganisationDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion"; import { createOrganisationDataLookup, getYearsAndNrens, loadDataWithFilterSelectionFallback } from "../helpers/dataconversion";
import DataPage from '../components/DataPage'; import DataPage from '../components/DataPage';
import Filter from "../components/graphing/Filter" import Filter from "../components/graphing/Filter"
import { Sections } from '../helpers/constants'; import {ExportType, Sections} from '../helpers/constants';
import DownloadCSVButton from "../components/DownloadCSVButton"; import DownloadDataButton from "../components/DownloadDataButton";
function getJSXFromMap(data: Map<string, Map<number, Organisation[]>>) { function getJSXFromMap(data: Map<string, Map<number, Organisation[]>>) {
...@@ -62,7 +62,8 @@ function SubOrganisation({ filterSelection, setFilterSelection }: inputProps) { ...@@ -62,7 +62,8 @@ function SubOrganisation({ filterSelection, setFilterSelection }: inputProps) {
category={Sections.Organisation} filter={filterNode}> category={Sections.Organisation} filter={filterNode}>
<> <>
<Row> <Row>
<DownloadCSVButton data={organisationData} filename="nren_suborganisations.csv"/> <DownloadDataButton data={organisationData} filename="nren_suborganisations.csv" exportType={ExportType.CSV}/>
<DownloadDataButton data={organisationData} filename="nren_suborganisations.xlsx" exportType={ExportType.EXCEL}/>
</Row> </Row>
<Table borderless className='compendium-table'> <Table borderless className='compendium-table'>
<thead> <thead>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment