mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 10:15:54 +08:00
feat: add the export panel (#2925)
* feat: add the export panel * feat: dropdown overlay is updated to dropdown * chore: loading variable is updated for create dashboard * chore: export panel is updated --------- Co-authored-by: Nazarenko19 <danil.nazarenko2000@gmail.com> Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
37fc00b55f
commit
96b94a619e
@ -1,4 +1,5 @@
|
||||
export const REACT_QUERY_KEY = {
|
||||
GET_ALL_LICENCES: 'GET_ALL_LICENCES',
|
||||
GET_QUERY_RANGE: 'GET_QUERY_RANGE',
|
||||
GET_ALL_DASHBOARDS: 'GET_ALL_DASHBOARDS',
|
||||
};
|
||||
|
113
frontend/src/container/ExportPanel/ExportPanel.tsx
Normal file
113
frontend/src/container/ExportPanel/ExportPanel.tsx
Normal file
@ -0,0 +1,113 @@
|
||||
import { Button, Typography } from 'antd';
|
||||
import createDashboard from 'api/dashboard/create';
|
||||
import getAll from 'api/dashboard/getAll';
|
||||
import axios from 'axios';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useMutation, useQuery } from 'react-query';
|
||||
|
||||
import { ExportPanelProps } from '.';
|
||||
import {
|
||||
DashboardSelect,
|
||||
NewDashboardButton,
|
||||
SelectWrapper,
|
||||
Title,
|
||||
Wrapper,
|
||||
} from './styles';
|
||||
import { getSelectOptions } from './utils';
|
||||
|
||||
function ExportPanel({ onExport }: ExportPanelProps): JSX.Element {
|
||||
const { notifications } = useNotifications();
|
||||
const { t } = useTranslation(['dashboard']);
|
||||
|
||||
const [selectedDashboardId, setSelectedDashboardId] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const { data, isLoading, refetch } = useQuery({
|
||||
queryFn: getAll,
|
||||
queryKey: REACT_QUERY_KEY.GET_ALL_DASHBOARDS,
|
||||
});
|
||||
|
||||
const {
|
||||
mutate: createNewDashboard,
|
||||
isLoading: createDashboardLoading,
|
||||
} = useMutation(createDashboard, {
|
||||
onSuccess: () => {
|
||||
refetch();
|
||||
},
|
||||
onError: (error) => {
|
||||
if (axios.isAxiosError(error)) {
|
||||
notifications.error({
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const options = useMemo(() => getSelectOptions(data?.payload || []), [data]);
|
||||
|
||||
const handleExportClick = useCallback((): void => {
|
||||
const currentSelectedDashboard = data?.payload?.find(
|
||||
({ uuid }) => uuid === selectedDashboardId,
|
||||
);
|
||||
|
||||
onExport(currentSelectedDashboard || null);
|
||||
}, [data, selectedDashboardId, onExport]);
|
||||
|
||||
const handleSelect = useCallback(
|
||||
(selectedDashboardValue: string): void => {
|
||||
setSelectedDashboardId(selectedDashboardValue);
|
||||
},
|
||||
[setSelectedDashboardId],
|
||||
);
|
||||
|
||||
const handleNewDashboard = useCallback(async () => {
|
||||
createNewDashboard({
|
||||
title: t('new_dashboard_title', {
|
||||
ns: 'dashboard',
|
||||
}),
|
||||
uploadedGrafana: false,
|
||||
});
|
||||
}, [t, createNewDashboard]);
|
||||
|
||||
return (
|
||||
<Wrapper direction="vertical">
|
||||
<Title>Export Panel</Title>
|
||||
|
||||
<SelectWrapper direction="horizontal">
|
||||
<DashboardSelect
|
||||
placeholder="Select Dashboard"
|
||||
options={options}
|
||||
loading={isLoading || createDashboardLoading}
|
||||
disabled={isLoading || createDashboardLoading}
|
||||
value={selectedDashboardId}
|
||||
onSelect={handleSelect}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={isLoading || !options?.length || !selectedDashboardId}
|
||||
onClick={handleExportClick}
|
||||
>
|
||||
Export
|
||||
</Button>
|
||||
</SelectWrapper>
|
||||
|
||||
<Typography>
|
||||
Or create dashboard with this panel -
|
||||
<NewDashboardButton
|
||||
disabled={createDashboardLoading}
|
||||
loading={createDashboardLoading}
|
||||
type="link"
|
||||
onClick={handleNewDashboard}
|
||||
>
|
||||
New Dashboard
|
||||
</NewDashboardButton>
|
||||
</Typography>
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExportPanel;
|
9
frontend/src/container/ExportPanel/config.ts
Normal file
9
frontend/src/container/ExportPanel/config.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export const MENU_KEY = {
|
||||
EXPORT: 'export',
|
||||
CREATE_ALERTS: 'create-alerts',
|
||||
};
|
||||
|
||||
export const MENU_LABEL = {
|
||||
EXPORT: 'Export Panel',
|
||||
CREATE_ALERTS: 'Create Alerts',
|
||||
};
|
70
frontend/src/container/ExportPanel/index.tsx
Normal file
70
frontend/src/container/ExportPanel/index.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
import { Button, Dropdown, MenuProps, Modal } from 'antd';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||
|
||||
import { MENU_KEY, MENU_LABEL } from './config';
|
||||
import ExportPanelContainer from './ExportPanel';
|
||||
|
||||
function ExportPanel({ onExport }: ExportPanelProps): JSX.Element {
|
||||
const [isExport, setIsExport] = useState<boolean>(false);
|
||||
|
||||
const onModalToggle = useCallback((value: boolean) => {
|
||||
setIsExport(value);
|
||||
}, []);
|
||||
|
||||
const onMenuClickHandler: MenuProps['onClick'] = useCallback(
|
||||
(e: OnClickProps) => {
|
||||
if (e.key === MENU_KEY.EXPORT) {
|
||||
onModalToggle(true);
|
||||
}
|
||||
},
|
||||
[onModalToggle],
|
||||
);
|
||||
|
||||
const menu: MenuProps = useMemo(
|
||||
() => ({
|
||||
items: [
|
||||
{
|
||||
key: MENU_KEY.EXPORT,
|
||||
label: MENU_LABEL.EXPORT,
|
||||
},
|
||||
{
|
||||
key: MENU_KEY.CREATE_ALERTS,
|
||||
label: MENU_LABEL.CREATE_ALERTS,
|
||||
},
|
||||
],
|
||||
onClick: onMenuClickHandler,
|
||||
}),
|
||||
[onMenuClickHandler],
|
||||
);
|
||||
|
||||
const onCancel = (value: boolean) => (): void => {
|
||||
onModalToggle(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Dropdown trigger={['click']} menu={menu}>
|
||||
<Button>Actions</Button>
|
||||
</Dropdown>
|
||||
<Modal
|
||||
onOk={onCancel(false)}
|
||||
onCancel={onCancel(false)}
|
||||
open={isExport}
|
||||
centered
|
||||
>
|
||||
<ExportPanelContainer onExport={onExport} />
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface OnClickProps {
|
||||
key: string;
|
||||
}
|
||||
|
||||
export interface ExportPanelProps {
|
||||
onExport: (dashboard: Dashboard | null) => void;
|
||||
}
|
||||
|
||||
export default ExportPanel;
|
33
frontend/src/container/ExportPanel/styles.ts
Normal file
33
frontend/src/container/ExportPanel/styles.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { Button, Select, SelectProps, Space, Typography } from 'antd';
|
||||
import { FunctionComponent } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const DashboardSelect: FunctionComponent<SelectProps> = styled(
|
||||
Select,
|
||||
)<SelectProps>`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const SelectWrapper = styled(Space)`
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.ant-space-item:first-child {
|
||||
width: 100%;
|
||||
max-width: 20rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Wrapper = styled(Space)`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const NewDashboardButton = styled(Button)`
|
||||
&&& {
|
||||
padding: 0 0.125rem;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Title = styled(Typography.Text)`
|
||||
font-size: 1rem;
|
||||
`;
|
10
frontend/src/container/ExportPanel/utils.ts
Normal file
10
frontend/src/container/ExportPanel/utils.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { SelectProps } from 'antd';
|
||||
import { PayloadProps as AllDashboardsData } from 'types/api/dashboard/getAll';
|
||||
|
||||
export const getSelectOptions = (
|
||||
data: AllDashboardsData,
|
||||
): SelectProps['options'] =>
|
||||
data.map(({ uuid, data }) => ({
|
||||
label: data.title,
|
||||
value: uuid,
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user