diff --git a/frontend/src/constants/reactQueryKeys.ts b/frontend/src/constants/reactQueryKeys.ts index 920bba6e7b..c4997dd45b 100644 --- a/frontend/src/constants/reactQueryKeys.ts +++ b/frontend/src/constants/reactQueryKeys.ts @@ -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', }; diff --git a/frontend/src/container/ExportPanel/ExportPanel.tsx b/frontend/src/container/ExportPanel/ExportPanel.tsx new file mode 100644 index 0000000000..2cd24e25d1 --- /dev/null +++ b/frontend/src/container/ExportPanel/ExportPanel.tsx @@ -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( + 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 ( + + Export Panel + + + + + + + + Or create dashboard with this panel - + + New Dashboard + + + + ); +} + +export default ExportPanel; diff --git a/frontend/src/container/ExportPanel/config.ts b/frontend/src/container/ExportPanel/config.ts new file mode 100644 index 0000000000..a70d996b79 --- /dev/null +++ b/frontend/src/container/ExportPanel/config.ts @@ -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', +}; diff --git a/frontend/src/container/ExportPanel/index.tsx b/frontend/src/container/ExportPanel/index.tsx new file mode 100644 index 0000000000..a1673b541c --- /dev/null +++ b/frontend/src/container/ExportPanel/index.tsx @@ -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(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 ( + <> + + + + + + + + ); +} + +interface OnClickProps { + key: string; +} + +export interface ExportPanelProps { + onExport: (dashboard: Dashboard | null) => void; +} + +export default ExportPanel; diff --git a/frontend/src/container/ExportPanel/styles.ts b/frontend/src/container/ExportPanel/styles.ts new file mode 100644 index 0000000000..8aa3f2fde8 --- /dev/null +++ b/frontend/src/container/ExportPanel/styles.ts @@ -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 = styled( + Select, +)` + 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; +`; diff --git a/frontend/src/container/ExportPanel/utils.ts b/frontend/src/container/ExportPanel/utils.ts new file mode 100644 index 0000000000..128de92324 --- /dev/null +++ b/frontend/src/container/ExportPanel/utils.ts @@ -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, + }));