|
|
|
import React from 'react';
|
|
|
|
// import dynamic from 'next/dynamic'
|
|
|
|
// import {buildURI} from 'react-csv';
|
|
|
|
// /**
|
|
|
|
// * See https://github.com/react-csv/react-csv/issues/87
|
|
|
|
// */
|
|
|
|
export const isSafari = () => /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
|
|
|
|
|
|
export const isJsons = ((array) => Array.isArray(array) && array.every(
|
|
|
|
row => (typeof row === 'object' && !(row instanceof Array))
|
|
|
|
));
|
|
|
|
|
|
|
|
export const isArrays = ((array) => Array.isArray(array) && array.every(
|
|
|
|
row => Array.isArray(row)
|
|
|
|
));
|
|
|
|
|
|
|
|
export const jsonsHeaders = ((array) => Array.from(
|
|
|
|
array.map(json => Object.keys(json))
|
|
|
|
.reduce((a, b) => new Set([...a, ...b]), [])
|
|
|
|
));
|
|
|
|
|
|
|
|
export const jsons2arrays = (jsons, headers) => {
|
|
|
|
headers = headers || jsonsHeaders(jsons);
|
|
|
|
|
|
|
|
// allow headers to have custom labels, defaulting to having the header data key be the label
|
|
|
|
let headerLabels = headers;
|
|
|
|
let headerKeys = headers;
|
|
|
|
if (isJsons(headers)) {
|
|
|
|
headerLabels = headers.map((header) => header.label);
|
|
|
|
headerKeys = headers.map((header) => header.key);
|
|
|
|
}
|
|
|
|
|
|
|
|
const data = jsons.map((object) => headerKeys.map((header) => getHeaderValue(header, object)));
|
|
|
|
return [headerLabels, ...data];
|
|
|
|
};
|
|
|
|
|
|
|
|
export const getHeaderValue = (property, obj) => {
|
|
|
|
const foundValue = property
|
|
|
|
.replace(/\[([^\]]+)]/g, ".$1")
|
|
|
|
.split(".")
|
|
|
|
.reduce(function (o, p, i, arr) {
|
|
|
|
// if at any point the nested keys passed do not exist, splice the array so it doesnt keep reducing
|
|
|
|
const value = o[p];
|
|
|
|
if (value === undefined || value === null) {
|
|
|
|
arr.splice(1);
|
|
|
|
} else {
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}, obj);
|
|
|
|
// if at any point the nested keys passed do not exist then looks for key `property` in object obj
|
|
|
|
return (foundValue === undefined) ? ((property in obj) ? obj[property] : '') : foundValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
export const elementOrEmpty = (element) =>
|
|
|
|
(typeof element === 'undefined' || element === null) ? '' : element;
|
|
|
|
|
|
|
|
export const joiner = ((data, separator = ',', enclosingCharacter = '"') => {
|
|
|
|
return data
|
|
|
|
.filter(e => e)
|
|
|
|
.map(
|
|
|
|
row => row
|
|
|
|
.map((element) => elementOrEmpty(element))
|
|
|
|
.map(column => `${enclosingCharacter}${column}${enclosingCharacter}`)
|
|
|
|
.join(separator)
|
|
|
|
)
|
|
|
|
.join(`\n`);
|
|
|
|
});
|
|
|
|
|
|
|
|
export const arrays2csv = ((data, headers, separator, enclosingCharacter) =>
|
|
|
|
joiner(headers ? [headers, ...data] : data, separator, enclosingCharacter)
|
|
|
|
);
|
|
|
|
|
|
|
|
export const jsons2csv = ((data, headers, separator, enclosingCharacter) =>
|
|
|
|
joiner(jsons2arrays(data, headers), separator, enclosingCharacter)
|
|
|
|
);
|
|
|
|
|
|
|
|
export const string2csv = ((data, headers, separator) =>
|
|
|
|
(headers) ? `${headers.join(separator)}\n${data}` : data.replace(/"/g, '""')
|
|
|
|
);
|
|
|
|
|
|
|
|
export const toCSV = (data, headers, separator, enclosingCharacter) => {
|
|
|
|
if (isJsons(data)) return jsons2csv(data, headers, separator, enclosingCharacter);
|
|
|
|
if (isArrays(data)) return arrays2csv(data, headers, separator, enclosingCharacter);
|
|
|
|
if (typeof data === 'string') return string2csv(data, headers, separator);
|
|
|
|
throw new TypeError(`Data should be a "String", "Array of arrays" OR "Array of objects" `);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const CSVLink = ({filename, data, children, ...rest}) => {
|
|
|
|
|
|
|
|
const buildURI = ((data, uFEFF, headers, separator, enclosingCharacter) => {
|
|
|
|
const csv = toCSV(data, headers, separator, enclosingCharacter);
|
|
|
|
const type = isSafari() ? 'application/csv' : 'text/csv';
|
|
|
|
const blob = new Blob([uFEFF ? '\uFEFF' : '', csv], {type});
|
|
|
|
const dataURI = `data:${type};charset=utf-8,${uFEFF ? '\uFEFF' : ''}${csv}`;
|
|
|
|
|
|
|
|
const URL = window.URL || window.webkitURL;
|
|
|
|
|
|
|
|
return (typeof URL.createObjectURL === 'undefined')
|
|
|
|
? dataURI
|
|
|
|
: URL.createObjectURL(blob);
|
|
|
|
});
|
|
|
|
|
|
|
|
const isNodeEnvironment = typeof window === 'undefined';
|
|
|
|
const uFEFF = true;
|
|
|
|
const headers = undefined;
|
|
|
|
const separator = ",";
|
|
|
|
const enclosingCharacter = '"';
|
|
|
|
const href = isNodeEnvironment ? '' : buildURI(data, uFEFF, headers, separator, enclosingCharacter)
|
|
|
|
|
|
|
|
return (
|
|
|
|
<a
|
|
|
|
download={filename}
|
|
|
|
target="_blank"
|
|
|
|
{...rest}
|
|
|
|
href={href}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</a>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default CSVLink;
|