@seasketch/geoprocessing
Version:
Geoprocessing and reporting framework for SeaSketch 2.0
83 lines • 3.83 kB
JavaScript
import React, { useEffect, useState } from "react";
import Dropdown from "./Dropdown.js";
import { SimpleButtonStyled } from "./SimpleButton.js";
import { styled } from "styled-components";
import { Parser, transforms } from "json2csv";
import useSketchProperties from "../hooks/useSketchProperties.js";
import { ThreeDotsVertical } from "@styled-icons/bootstrap/ThreeDotsVertical/ThreeDotsVertical.esm.js";
import { CloudArrowDown } from "@styled-icons/bootstrap/CloudArrowDown/CloudArrowDown.esm.js";
import { useTranslation } from "react-i18next";
// Strictly limit format and data types accepted
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const SUPPORTED_FORMATS = ["json", "csv"];
const DownloadButtonStyled = styled(SimpleButtonStyled) `
font-size: 12px;
`;
/**
* Dropdown menu for transforming data to CSV/JSON format and initiating a browser download
* Defaults to CSV and JSON, and filename will include sketch name from ReportContext (if available)
* and current timestamp
*/
export const DataDownload = ({ filename = "export", data, formats = ["csv", "json"], addSketchName = true, addTimestamp = true, ...dropdownProps }) => {
const { t } = useTranslation();
const formatConfigs = [
{
label: t("DataDownload - export CSV format label", "Export CSV"),
extension: "csv",
contentType: "application/csv",
url: "",
},
{
label: t("DataDownload - export JSON format label", "Export JSON"),
extension: "json",
contentType: "application/json",
url: "",
},
];
const defaultState = formatConfigs.filter((c) => formats.includes(c.extension));
const [objectUrls, setObjectUrls] = useState(defaultState);
const name = (() => {
try {
const [{ name }] = useSketchProperties();
return name;
}
catch {
return "";
}
})();
const sketchSegment = addSketchName && name ? `__${name.replaceAll(/\s/g, "_")}` : "";
const timeSegment = addTimestamp
? `__${new Date().toISOString().split(".")[0]}Z`
: "";
const fullFilename = `${filename}${sketchSegment}${timeSegment}`;
useEffect(() => {
if (!data || data.length === 0)
return;
const formatters = {
csv: () => new Parser({
transforms: [transforms.flatten({ arrays: true })], // Flatten nested objects AND arrays
}).parse(data),
json: () => JSON.stringify(data, null, 2),
};
const dObjects = objectUrls.map((dOption) => {
const blob = new Blob([formatters[dOption.extension]()], {
type: dOption.contentType,
});
if (dOption.url != "")
window.URL.revokeObjectURL(dOption.url); // clean up last first
return { ...dOption, url: window.URL.createObjectURL(blob) };
});
setObjectUrls(dObjects);
}, [data]);
const links = objectUrls.map((dOption, index) => (React.createElement("a", { key: index, download: `${fullFilename}.${dOption.extension}`, href: data && data.length > 0 ? dOption.url : "#", "aria-disabled": !data || data.length === 0 },
React.createElement(DownloadButtonStyled, null,
React.createElement(CloudArrowDown, { color: "#999", size: "20", style: { paddingRight: 5 } }),
React.createElement("span", { style: { verticalAlign: "middle" } }, dOption.label)))));
const dropdownPropsMerged = {
titleElement: React.createElement(ThreeDotsVertical, { size: 18, color: "#999" }),
...dropdownProps,
};
return React.createElement(Dropdown, { ...dropdownPropsMerged }, links);
};
export default DataDownload;
//# sourceMappingURL=DataDownload.js.map