dnazarenkosignoz 37fc00b55f
feat: add the Trace Explorer page with Query Builder (#2843)
* feat: update the SideNav component

* feat: add the Trace Explorer page with Query Builder

* chore: build is fixed

* chore: tsc build is fixed

* chore: menu items is updated

---------

Co-authored-by: Nazarenko19 <danil.nazarenko2000@gmail.com>
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
2023-06-19 18:27:58 +05:30

180 lines
4.3 KiB
TypeScript

import { CloudDownloadOutlined, FastBackwardOutlined } from '@ant-design/icons';
import { Button, Divider, Dropdown, MenuProps } from 'antd';
import { Excel } from 'antd-table-saveas-excel';
import Controls from 'container/Controls';
import { getGlobalTime } from 'container/LogsSearchFilter/utils';
import { getMinMax } from 'container/TopNav/AutoRefresh/config';
import dayjs from 'dayjs';
import { FlatLogData } from 'lib/logs/flatLogData';
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';
import AppActions from 'types/actions';
import {
GET_NEXT_LOG_LINES,
GET_PREVIOUS_LOG_LINES,
RESET_ID_START_AND_END,
SET_LOG_LINES_PER_PAGE,
} from 'types/actions/logs';
import { GlobalReducer } from 'types/reducer/globalTime';
import { ILogsReducer } from 'types/reducer/logs';
import { Container, DownloadLogButton } from './styles';
function LogControls(): JSX.Element | null {
const {
logLinesPerPage,
liveTail,
isLoading: isLogsLoading,
isLoadingAggregate,
logs,
} = useSelector<AppState, ILogsReducer>((state) => state.logs);
const globalTime = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
);
const dispatch = useDispatch<Dispatch<AppActions>>();
const handleLogLinesPerPageChange = (e: number): void => {
dispatch({
type: SET_LOG_LINES_PER_PAGE,
payload: {
logsLinesPerPage: e,
},
});
};
const handleGoToLatest = (): void => {
const { maxTime, minTime } = getMinMax(
globalTime.selectedTime,
globalTime.minTime,
globalTime.maxTime,
);
const updatedGlobalTime = getGlobalTime(globalTime.selectedTime, {
maxTime,
minTime,
});
if (updatedGlobalTime) {
dispatch({
type: RESET_ID_START_AND_END,
payload: updatedGlobalTime,
});
}
};
const handleNavigatePrevious = (): void => {
dispatch({
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;
if (liveTail !== 'STOPPED') {
return null;
}
return (
<Container>
<Dropdown menu={menu} trigger={['click']}>
<DownloadLogButton loading={isLoading} size="small" type="link">
<CloudDownloadOutlined />
Download
</DownloadLogButton>
</Dropdown>
<Button
loading={isLoading}
size="small"
type="link"
onClick={handleGoToLatest}
>
<FastBackwardOutlined /> Go to latest
</Button>
<Divider type="vertical" />
<Controls
isLoading={isLoading}
count={logs.length}
countPerPage={logLinesPerPage}
handleNavigatePrevious={handleNavigatePrevious}
handleNavigateNext={handleNavigateNext}
handleCountItemsPerPageChange={handleLogLinesPerPageChange}
/>
</Container>
);
}
export default memo(LogControls);