2021-09-23 15:43:43 +05:30
|
|
|
import { PlusOutlined } from '@ant-design/icons';
|
2023-03-14 16:55:15 +05:30
|
|
|
import {
|
|
|
|
|
Card,
|
|
|
|
|
Dropdown,
|
|
|
|
|
MenuProps,
|
|
|
|
|
Row,
|
|
|
|
|
TableColumnProps,
|
|
|
|
|
Typography,
|
|
|
|
|
} from 'antd';
|
2023-03-03 12:09:24 +01:00
|
|
|
import { ItemType } from 'antd/es/menu/hooks/useItems';
|
2021-09-23 15:43:43 +05:30
|
|
|
import createDashboard from 'api/dashboard/create';
|
|
|
|
|
import { AxiosError } from 'axios';
|
2023-02-03 18:06:26 +05:30
|
|
|
import { ResizeTable } from 'components/ResizeTable';
|
2021-12-24 11:51:19 +05:30
|
|
|
import TextToolTip from 'components/TextToolTip';
|
2021-09-23 15:43:43 +05:30
|
|
|
import ROUTES from 'constants/routes';
|
2022-04-22 18:57:05 +05:30
|
|
|
import SearchFilter from 'container/ListOfDashboard/SearchFilter';
|
2022-05-03 15:27:09 +05:30
|
|
|
import useComponentPermission from 'hooks/useComponentPermission';
|
2022-03-22 21:56:12 +05:30
|
|
|
import history from 'lib/history';
|
2022-06-08 11:50:41 +05:30
|
|
|
import React, {
|
|
|
|
|
Dispatch,
|
|
|
|
|
useCallback,
|
|
|
|
|
useEffect,
|
|
|
|
|
useMemo,
|
|
|
|
|
useState,
|
|
|
|
|
} from 'react';
|
2022-04-25 22:41:46 +05:30
|
|
|
import { useTranslation } from 'react-i18next';
|
2022-06-08 11:50:41 +05:30
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
2022-03-22 21:56:12 +05:30
|
|
|
import { generatePath } from 'react-router-dom';
|
2021-09-23 15:43:43 +05:30
|
|
|
import { AppState } from 'store/reducers';
|
2022-06-08 11:50:41 +05:30
|
|
|
import AppActions from 'types/actions';
|
|
|
|
|
import { GET_ALL_DASHBOARD_SUCCESS } from 'types/actions/dashboard';
|
2022-04-22 18:57:05 +05:30
|
|
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
2022-05-03 15:27:09 +05:30
|
|
|
import AppReducer from 'types/reducer/app';
|
2021-09-23 15:43:43 +05:30
|
|
|
import DashboardReducer from 'types/reducer/dashboards';
|
|
|
|
|
|
2022-04-25 22:41:46 +05:30
|
|
|
import ImportJSON from './ImportJSON';
|
2022-03-14 20:12:42 +05:30
|
|
|
import { ButtonContainer, NewDashboardButton, TableContainer } from './styles';
|
2021-09-23 15:43:43 +05:30
|
|
|
import Createdby from './TableComponents/CreatedBy';
|
|
|
|
|
import DateComponent from './TableComponents/Date';
|
|
|
|
|
import DeleteButton from './TableComponents/DeleteButton';
|
|
|
|
|
import Name from './TableComponents/Name';
|
|
|
|
|
import Tags from './TableComponents/Tags';
|
|
|
|
|
|
2022-03-22 12:10:31 +05:30
|
|
|
function ListOfAllDashboard(): JSX.Element {
|
2022-03-22 21:56:12 +05:30
|
|
|
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
2021-09-23 15:43:43 +05:30
|
|
|
(state) => state.dashboards,
|
|
|
|
|
);
|
2022-06-08 11:50:41 +05:30
|
|
|
const dispatch = useDispatch<Dispatch<AppActions>>();
|
2022-05-03 15:27:09 +05:30
|
|
|
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
|
|
|
|
|
2022-05-04 20:40:49 +05:30
|
|
|
const [action, createNewDashboard, newDashboard] = useComponentPermission(
|
|
|
|
|
['action', 'create_new_dashboards', 'new_dashboard'],
|
2022-05-03 15:27:09 +05:30
|
|
|
role,
|
|
|
|
|
);
|
2021-09-23 15:43:43 +05:30
|
|
|
|
2022-04-25 22:41:46 +05:30
|
|
|
const { t } = useTranslation('dashboard');
|
2023-03-14 16:55:15 +05:30
|
|
|
|
2022-04-25 22:41:46 +05:30
|
|
|
const [
|
|
|
|
|
isImportJSONModalVisible,
|
|
|
|
|
setIsImportJSONModalVisible,
|
|
|
|
|
] = useState<boolean>(false);
|
2023-03-14 16:55:15 +05:30
|
|
|
|
2022-11-10 16:49:54 +05:30
|
|
|
const [uploadedGrafana, setUploadedGrafana] = useState<boolean>(false);
|
2022-04-25 22:41:46 +05:30
|
|
|
|
2022-04-22 18:57:05 +05:30
|
|
|
const [filteredDashboards, setFilteredDashboards] = useState<Dashboard[]>();
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setFilteredDashboards(dashboards);
|
|
|
|
|
}, [dashboards]);
|
2023-03-14 16:55:15 +05:30
|
|
|
|
2021-09-23 15:43:43 +05:30
|
|
|
const [newDashboardState, setNewDashboardState] = useState({
|
|
|
|
|
loading: false,
|
|
|
|
|
error: false,
|
|
|
|
|
errorMessage: '',
|
|
|
|
|
});
|
|
|
|
|
|
2023-05-19 12:19:42 +05:30
|
|
|
const columns: TableColumnProps<Data>[] = useMemo(
|
|
|
|
|
() => [
|
|
|
|
|
{
|
|
|
|
|
title: 'Name',
|
|
|
|
|
dataIndex: 'name',
|
|
|
|
|
width: 100,
|
|
|
|
|
render: Name,
|
2021-09-28 18:32:02 +05:30
|
|
|
},
|
2023-05-19 12:19:42 +05:30
|
|
|
{
|
|
|
|
|
title: 'Description',
|
|
|
|
|
width: 100,
|
|
|
|
|
dataIndex: 'description',
|
2021-09-23 15:43:43 +05:30
|
|
|
},
|
2023-05-19 12:19:42 +05:30
|
|
|
{
|
|
|
|
|
title: 'Tags (can be multiple)',
|
|
|
|
|
dataIndex: 'tags',
|
|
|
|
|
width: 80,
|
|
|
|
|
render: Tags,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: 'Created At',
|
|
|
|
|
dataIndex: 'createdBy',
|
|
|
|
|
width: 80,
|
|
|
|
|
sorter: (a: Data, b: Data): number => {
|
|
|
|
|
const prev = new Date(a.createdBy).getTime();
|
|
|
|
|
const next = new Date(b.createdBy).getTime();
|
|
|
|
|
|
|
|
|
|
return prev - next;
|
|
|
|
|
},
|
|
|
|
|
render: Createdby,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: 'Last Updated Time',
|
|
|
|
|
width: 90,
|
|
|
|
|
dataIndex: 'lastUpdatedTime',
|
|
|
|
|
sorter: (a: Data, b: Data): number => {
|
|
|
|
|
const prev = new Date(a.lastUpdatedTime).getTime();
|
|
|
|
|
const next = new Date(b.lastUpdatedTime).getTime();
|
|
|
|
|
|
|
|
|
|
return prev - next;
|
|
|
|
|
},
|
|
|
|
|
render: DateComponent,
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
[],
|
|
|
|
|
);
|
2022-05-03 15:27:09 +05:30
|
|
|
|
|
|
|
|
if (action) {
|
|
|
|
|
columns.push({
|
2021-09-23 15:43:43 +05:30
|
|
|
title: 'Action',
|
|
|
|
|
dataIndex: '',
|
|
|
|
|
key: 'x',
|
2023-02-02 16:53:15 +05:30
|
|
|
width: 40,
|
2021-09-23 15:43:43 +05:30
|
|
|
render: DeleteButton,
|
2022-05-03 15:27:09 +05:30
|
|
|
});
|
|
|
|
|
}
|
2021-09-23 15:43:43 +05:30
|
|
|
|
2022-04-22 18:57:05 +05:30
|
|
|
const data: Data[] = (filteredDashboards || dashboards).map((e) => ({
|
2021-09-23 15:43:43 +05:30
|
|
|
createdBy: e.created_at,
|
|
|
|
|
description: e.data.description || '',
|
|
|
|
|
id: e.uuid,
|
|
|
|
|
lastUpdatedTime: e.updated_at,
|
|
|
|
|
name: e.data.title,
|
|
|
|
|
tags: e.data.tags || [],
|
|
|
|
|
key: e.uuid,
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
const onNewDashboardHandler = useCallback(async () => {
|
|
|
|
|
try {
|
|
|
|
|
setNewDashboardState({
|
|
|
|
|
...newDashboardState,
|
|
|
|
|
loading: true,
|
|
|
|
|
});
|
|
|
|
|
const response = await createDashboard({
|
2022-04-25 22:41:46 +05:30
|
|
|
title: t('new_dashboard_title', {
|
|
|
|
|
ns: 'dashboard',
|
|
|
|
|
}),
|
2022-11-10 16:49:54 +05:30
|
|
|
uploadedGrafana: false,
|
2021-09-23 15:43:43 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (response.statusCode === 200) {
|
2022-06-08 11:50:41 +05:30
|
|
|
dispatch({
|
|
|
|
|
type: GET_ALL_DASHBOARD_SUCCESS,
|
|
|
|
|
payload: [],
|
|
|
|
|
});
|
2022-03-22 21:56:12 +05:30
|
|
|
history.push(
|
2021-10-22 17:07:22 +05:30
|
|
|
generatePath(ROUTES.DASHBOARD, {
|
2022-04-25 22:41:46 +05:30
|
|
|
dashboardId: response.payload.uuid,
|
2021-10-22 17:07:22 +05:30
|
|
|
}),
|
|
|
|
|
);
|
2021-09-23 15:43:43 +05:30
|
|
|
} else {
|
|
|
|
|
setNewDashboardState({
|
|
|
|
|
...newDashboardState,
|
|
|
|
|
loading: false,
|
|
|
|
|
error: true,
|
|
|
|
|
errorMessage: response.error || 'Something went wrong',
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
setNewDashboardState({
|
|
|
|
|
...newDashboardState,
|
|
|
|
|
error: true,
|
|
|
|
|
errorMessage: (error as AxiosError).toString() || 'Something went Wrong',
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-06-08 11:50:41 +05:30
|
|
|
}, [newDashboardState, t, dispatch]);
|
2021-09-23 15:43:43 +05:30
|
|
|
|
2022-04-25 22:41:46 +05:30
|
|
|
const getText = useCallback(() => {
|
2021-09-23 15:43:43 +05:30
|
|
|
if (!newDashboardState.error && !newDashboardState.loading) {
|
|
|
|
|
return 'New Dashboard';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newDashboardState.loading) {
|
|
|
|
|
return 'Loading';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return newDashboardState.errorMessage;
|
2022-04-25 22:41:46 +05:30
|
|
|
}, [
|
|
|
|
|
newDashboardState.error,
|
|
|
|
|
newDashboardState.errorMessage,
|
|
|
|
|
newDashboardState.loading,
|
|
|
|
|
]);
|
|
|
|
|
|
2022-11-10 16:49:54 +05:30
|
|
|
const onModalHandler = (uploadedGrafana: boolean): void => {
|
2022-04-25 22:41:46 +05:30
|
|
|
setIsImportJSONModalVisible((state) => !state);
|
2022-11-10 16:49:54 +05:30
|
|
|
setUploadedGrafana(uploadedGrafana);
|
2021-09-23 15:43:43 +05:30
|
|
|
};
|
|
|
|
|
|
2023-05-19 12:19:42 +05:30
|
|
|
const getMenuItems = useMemo(() => {
|
2023-03-03 12:09:24 +01:00
|
|
|
const menuItems: ItemType[] = [];
|
|
|
|
|
if (createNewDashboard) {
|
|
|
|
|
menuItems.push({
|
|
|
|
|
key: t('create_dashboard').toString(),
|
|
|
|
|
label: t('create_dashboard'),
|
|
|
|
|
disabled: loading,
|
|
|
|
|
onClick: onNewDashboardHandler,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menuItems.push({
|
|
|
|
|
key: t('import_json').toString(),
|
|
|
|
|
label: t('import_json'),
|
|
|
|
|
onClick: (): void => onModalHandler(false),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
menuItems.push({
|
|
|
|
|
key: t('import_grafana_json').toString(),
|
|
|
|
|
label: t('import_grafana_json'),
|
|
|
|
|
onClick: (): void => onModalHandler(true),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return menuItems;
|
|
|
|
|
}, [createNewDashboard, loading, onNewDashboardHandler, t]);
|
|
|
|
|
|
2023-03-14 16:55:15 +05:30
|
|
|
const menu: MenuProps = useMemo(
|
|
|
|
|
() => ({
|
2023-05-19 12:19:42 +05:30
|
|
|
items: getMenuItems,
|
2023-03-14 16:55:15 +05:30
|
|
|
}),
|
|
|
|
|
[getMenuItems],
|
|
|
|
|
);
|
2022-04-25 22:41:46 +05:30
|
|
|
|
|
|
|
|
const GetHeader = useMemo(
|
|
|
|
|
() => (
|
2022-04-22 18:57:05 +05:30
|
|
|
<Row justify="space-between">
|
|
|
|
|
<Typography>Dashboard List</Typography>
|
|
|
|
|
|
|
|
|
|
<ButtonContainer>
|
|
|
|
|
<TextToolTip
|
|
|
|
|
{...{
|
|
|
|
|
text: `More details on how to create dashboards`,
|
|
|
|
|
url: 'https://signoz.io/docs/userguide/dashboards',
|
|
|
|
|
}}
|
|
|
|
|
/>
|
2022-05-04 20:40:49 +05:30
|
|
|
{newDashboard && (
|
2023-05-19 12:19:42 +05:30
|
|
|
<Dropdown disabled={loading} trigger={['click']} menu={menu}>
|
2022-05-04 20:40:49 +05:30
|
|
|
<NewDashboardButton
|
|
|
|
|
icon={<PlusOutlined />}
|
|
|
|
|
type="primary"
|
|
|
|
|
loading={newDashboardState.loading}
|
|
|
|
|
danger={newDashboardState.error}
|
|
|
|
|
>
|
|
|
|
|
{getText()}
|
|
|
|
|
</NewDashboardButton>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
)}
|
2022-04-22 18:57:05 +05:30
|
|
|
</ButtonContainer>
|
|
|
|
|
</Row>
|
2022-04-25 22:41:46 +05:30
|
|
|
),
|
2022-05-04 20:40:49 +05:30
|
|
|
[
|
|
|
|
|
newDashboard,
|
2023-05-19 12:19:42 +05:30
|
|
|
loading,
|
2023-03-14 16:55:15 +05:30
|
|
|
menu,
|
2023-05-19 12:19:42 +05:30
|
|
|
newDashboardState.loading,
|
|
|
|
|
newDashboardState.error,
|
|
|
|
|
getText,
|
2022-05-04 20:40:49 +05:30
|
|
|
],
|
2022-04-25 22:41:46 +05:30
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
{GetHeader}
|
|
|
|
|
|
2022-04-22 18:57:05 +05:30
|
|
|
{!loading && (
|
|
|
|
|
<SearchFilter
|
|
|
|
|
searchData={dashboards}
|
|
|
|
|
filterDashboards={setFilteredDashboards}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
<TableContainer>
|
2022-04-25 22:41:46 +05:30
|
|
|
<ImportJSON
|
|
|
|
|
isImportJSONModalVisible={isImportJSONModalVisible}
|
2022-11-10 16:49:54 +05:30
|
|
|
uploadedGrafana={uploadedGrafana}
|
|
|
|
|
onModalHandler={(): void => onModalHandler(false)}
|
2022-04-25 22:41:46 +05:30
|
|
|
/>
|
2023-02-03 18:06:26 +05:30
|
|
|
<ResizeTable
|
|
|
|
|
columns={columns}
|
|
|
|
|
pagination={{
|
|
|
|
|
pageSize: 9,
|
|
|
|
|
defaultPageSize: 9,
|
|
|
|
|
}}
|
|
|
|
|
showHeader
|
|
|
|
|
bordered
|
|
|
|
|
sticky
|
|
|
|
|
loading={loading}
|
|
|
|
|
dataSource={data}
|
|
|
|
|
showSorterTooltip
|
|
|
|
|
/>
|
2022-04-22 18:57:05 +05:30
|
|
|
</TableContainer>
|
|
|
|
|
</Card>
|
2021-09-23 15:43:43 +05:30
|
|
|
);
|
2022-03-22 12:10:31 +05:30
|
|
|
}
|
2021-09-23 15:43:43 +05:30
|
|
|
|
|
|
|
|
export interface Data {
|
|
|
|
|
key: React.Key;
|
|
|
|
|
name: string;
|
|
|
|
|
description: string;
|
|
|
|
|
tags: string[];
|
|
|
|
|
createdBy: string;
|
|
|
|
|
lastUpdatedTime: string;
|
|
|
|
|
id: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default ListOfAllDashboard;
|