github.com/minio/console@v1.4.1/web-app/src/screens/Console/Dashboard/DownloadWidgetDataButton.tsx (about)

     1  // This file is part of MinIO Console Server
     2  // Copyright (c) 2022 MinIO, Inc.
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16  
    17  import React, { Fragment } from "react";
    18  import { Box, DownloadIcon, DropdownSelector } from "mds";
    19  import { exportComponentAsPNG } from "react-component-export-image";
    20  import { ErrorResponseHandler } from "../../../common/types";
    21  import { useAppDispatch } from "../../../../src/store";
    22  import { setErrorSnackMessage } from "../../../../src/systemSlice";
    23  
    24  interface IDownloadWidgetDataButton {
    25    title: any;
    26    componentRef: any;
    27    data: any;
    28  }
    29  
    30  const DownloadWidgetDataButton = ({
    31    title,
    32    componentRef,
    33    data,
    34  }: IDownloadWidgetDataButton) => {
    35    const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
    36    const openDownloadMenu = Boolean(anchorEl);
    37    const handleClick = (event: React.MouseEvent<HTMLElement>) => {
    38      setAnchorEl(event.currentTarget);
    39    };
    40    const handleCloseDownload = () => {
    41      setAnchorEl(null);
    42    };
    43    const download = (filename: string, text: string) => {
    44      let element = document.createElement("a");
    45      element.setAttribute("href", "data:text/plain;charset=utf-8," + text);
    46      element.setAttribute("download", filename);
    47  
    48      element.style.display = "none";
    49      document.body.appendChild(element);
    50  
    51      element.click();
    52      document.body.removeChild(element);
    53    };
    54  
    55    const dispatch = useAppDispatch();
    56    const onDownloadError = (err: ErrorResponseHandler) =>
    57      dispatch(setErrorSnackMessage(err));
    58  
    59    const convertToCSV = (objectToConvert: any) => {
    60      const array = [Object.keys(objectToConvert[0])].concat(objectToConvert);
    61      return array
    62        .map((it) => {
    63          return Object.values(it).toString();
    64        })
    65        .join("\n");
    66    };
    67  
    68    const widgetDataCSVFileName = () => {
    69      if (title !== null) {
    70        return (title + "_" + Date.now().toString() + ".csv")
    71          .replace(/\s+/g, "")
    72          .trim()
    73          .toLowerCase();
    74      } else {
    75        return "widgetData_" + Date.now().toString() + ".csv";
    76      }
    77    };
    78  
    79    const downloadAsCSV = () => {
    80      if (data !== null && data.length > 0) {
    81        download(widgetDataCSVFileName(), convertToCSV(data));
    82      } else {
    83        let err: ErrorResponseHandler;
    84        err = {
    85          errorMessage: "Unable to download widget data",
    86          detailedError: "Unable to download widget data - data not available",
    87        };
    88        onDownloadError(err);
    89      }
    90    };
    91  
    92    const downloadAsPNG = () => {
    93      if (title !== null) {
    94        const pngFileName = (title + "_" + Date.now().toString() + ".png")
    95          .replace(/\s+/g, "")
    96          .trim()
    97          .toLowerCase();
    98        exportComponentAsPNG(componentRef, { fileName: pngFileName });
    99      } else {
   100        const pngFileName = "widgetData_" + Date.now().toString() + ".png";
   101        exportComponentAsPNG(componentRef, { fileName: pngFileName });
   102      }
   103    };
   104  
   105    const handleSelectedOption = (selectOption: string) => {
   106      if (selectOption === "csv") {
   107        downloadAsCSV();
   108      } else if (selectOption === "png") {
   109        downloadAsPNG();
   110      }
   111    };
   112  
   113    return (
   114      <Fragment>
   115        <Box
   116          sx={{
   117            justifyItems: "center",
   118            "& .download-icon": {
   119              backgroundColor: "transparent",
   120              border: 0,
   121              padding: 0,
   122              cursor: "pointer",
   123              "& svg": {
   124                color: "#D0D0D0",
   125                height: 16,
   126              },
   127              "&:hover": {
   128                "& svg": {
   129                  color: "#404143",
   130                },
   131              },
   132            },
   133          }}
   134        >
   135          <button className={"download-icon"} onClick={handleClick}>
   136            <DownloadIcon />
   137          </button>
   138          <DropdownSelector
   139            id={"download-widget-main-menu"}
   140            options={[
   141              { label: "Download as CSV", value: "csv" },
   142              { label: "Download as PNG", value: "png" },
   143            ]}
   144            selectedOption={""}
   145            onSelect={(value) => handleSelectedOption(value)}
   146            hideTriggerAction={() => {
   147              handleCloseDownload();
   148            }}
   149            open={openDownloadMenu}
   150            anchorEl={anchorEl}
   151            anchorOrigin={"end"}
   152          />
   153        </Box>
   154      </Fragment>
   155    );
   156  };
   157  
   158  export default DownloadWidgetDataButton;