UNPKG

@seasketch/geoprocessing

Version:

Geoprocessing and reporting framework for SeaSketch 2.0

83 lines 3.83 kB
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