From 97207f8e6dc94dcc6f2f30dfe5d3f1dacc01b78d Mon Sep 17 00:00:00 2001 From: Chintan Sudani <46838508+techchintan@users.noreply.github.com> Date: Wed, 7 Jun 2023 15:31:57 +0530 Subject: [PATCH] feat: added option to download logs in csv & excel format (#2841) * feat: added option to download logs in csv format * fix: suggested changes * feat: added logs download as excel * fix: updated logic for download excel and suggested changes * fix: code level changes --------- Co-authored-by: Srikanth Chekuri --- frontend/package.json | 1 + frontend/src/container/LogControls/index.tsx | 81 +++++++++++++++++++- frontend/src/container/LogControls/styles.ts | 6 ++ frontend/yarn.lock | 62 ++++++++++++++- 4 files changed, 146 insertions(+), 4 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index f26a92c9be..c691a1c44c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,6 +34,7 @@ "@xstate/react": "^3.0.0", "ansi-to-html": "0.7.2", "antd": "5.0.5", + "antd-table-saveas-excel": "2.2.1", "axios": "^0.21.0", "babel-eslint": "^10.1.0", "babel-jest": "^26.6.0", diff --git a/frontend/src/container/LogControls/index.tsx b/frontend/src/container/LogControls/index.tsx index f688e2866f..68c4c5a08b 100644 --- a/frontend/src/container/LogControls/index.tsx +++ b/frontend/src/container/LogControls/index.tsx @@ -1,13 +1,18 @@ import { + CloudDownloadOutlined, FastBackwardOutlined, LeftOutlined, RightOutlined, } from '@ant-design/icons'; -import { Button, Divider, Select } from 'antd'; +import { Button, Divider, Dropdown, MenuProps, Select } from 'antd'; +import { Excel } from 'antd-table-saveas-excel'; import { getGlobalTime } from 'container/LogsSearchFilter/utils'; import { getMinMax } from 'container/TopNav/AutoRefresh/config'; +import dayjs from 'dayjs'; +import { FlatLogData } from 'lib/logs/flatLogData'; import { defaultSelectStyle } from 'pages/Logs/config'; -import { memo, useMemo } from 'react'; +import * as Papa from 'papaparse'; +import { memo, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { Dispatch } from 'redux'; import { AppState } from 'store/reducers'; @@ -22,7 +27,7 @@ import { GlobalReducer } from 'types/reducer/globalTime'; import { ILogsReducer } from 'types/reducer/logs'; import { ITEMS_PER_PAGE_OPTIONS } from './config'; -import { Container } from './styles'; +import { Container, DownloadLogButton } from './styles'; function LogControls(): JSX.Element | null { const { @@ -72,12 +77,76 @@ function LogControls(): JSX.Element | null { type: GET_PREVIOUS_LOG_LINES, }); }; + const handleNavigateNext = (): void => { dispatch({ type: GET_NEXT_LOG_LINES, }); }; + const flattenLogData = useMemo( + () => + logs.map((log) => + FlatLogData({ + ...log, + timestamp: (dayjs(log.timestamp / 1e6).format() as unknown) as number, + }), + ), + [logs], + ); + + const downloadExcelFile = useCallback((): void => { + const headers = Object.keys(Object.assign({}, ...flattenLogData)).map( + (item) => { + const updatedTitle = item + .split('_') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + return { + title: updatedTitle, + dataIndex: item, + }; + }, + ); + const excel = new Excel(); + excel + .addSheet('log_data') + .addColumns(headers) + .addDataSource(flattenLogData, { + str2Percent: true, + }) + .saveAs('log_data.xlsx'); + }, [flattenLogData]); + + const downloadCsvFile = useCallback((): void => { + const csv = Papa.unparse(flattenLogData); + const csvBlob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); + const csvUrl = URL.createObjectURL(csvBlob); + const downloadLink = document.createElement('a'); + downloadLink.href = csvUrl; + downloadLink.download = 'log_data.csv'; + downloadLink.click(); + downloadLink.remove(); + }, [flattenLogData]); + + const menu: MenuProps = useMemo( + () => ({ + items: [ + { + key: 'download-as-excel', + label: 'Excel', + onClick: downloadExcelFile, + }, + { + key: 'download-as-csv', + label: 'CSV', + onClick: downloadCsvFile, + }, + ], + }), + [downloadCsvFile, downloadExcelFile], + ); + const isLoading = isLogsLoading || isLoadingAggregate; const isNextAndPreviousDisabled = useMemo( @@ -95,6 +164,12 @@ function LogControls(): JSX.Element | null { return ( + + + + Download + +