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 = {
|
export const REACT_QUERY_KEY = {
|
||||||
GET_ALL_LICENCES: 'GET_ALL_LICENCES',
|
GET_ALL_LICENCES: 'GET_ALL_LICENCES',
|
||||||
GET_QUERY_RANGE: 'GET_QUERY_RANGE',
|
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