mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-16 06:05:58 +08:00
feat: all dashboard is migrated to useQuery and action is removed (#3384)
* feat: all dashboard is migrated to useQuery and action is removed * chore: delete functionality is updated --------- Co-authored-by: Palash Gupta <palashgdev@gmail.com>
This commit is contained in:
parent
dfd94f67bd
commit
41f7a7993d
@ -1,24 +1,8 @@
|
|||||||
import axios from 'api';
|
import axios from 'api';
|
||||||
import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
|
import { ApiResponse } from 'types/api';
|
||||||
import { AxiosError } from 'axios';
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
||||||
import { PayloadProps } from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
const getAll = async (): Promise<
|
export const getAllDashboardList = (): Promise<Dashboard[]> =>
|
||||||
SuccessResponse<PayloadProps> | ErrorResponse
|
axios
|
||||||
> => {
|
.get<ApiResponse<Dashboard[]>>('/dashboards')
|
||||||
try {
|
.then((res) => res.data.data);
|
||||||
const response = await axios.get('/dashboards');
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
error: null,
|
|
||||||
message: response.data.message,
|
|
||||||
payload: response.data.data,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return ErrorResponseHandler(error as AxiosError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getAll;
|
|
||||||
|
@ -44,10 +44,10 @@ function ExportPanel({ isLoading, onExport }: ExportPanelProps): JSX.Element {
|
|||||||
onError: handleError,
|
onError: handleError,
|
||||||
});
|
});
|
||||||
|
|
||||||
const options = useMemo(() => getSelectOptions(data?.payload || []), [data]);
|
const options = useMemo(() => getSelectOptions(data || []), [data]);
|
||||||
|
|
||||||
const handleExportClick = useCallback((): void => {
|
const handleExportClick = useCallback((): void => {
|
||||||
const currentSelectedDashboard = data?.payload?.find(
|
const currentSelectedDashboard = data?.find(
|
||||||
({ uuid }) => uuid === selectedDashboardId,
|
({ uuid }) => uuid === selectedDashboardId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -10,7 +10,11 @@ import AppActions from 'types/actions';
|
|||||||
import { Data } from '../index';
|
import { Data } from '../index';
|
||||||
import { TableLinkText } from './styles';
|
import { TableLinkText } from './styles';
|
||||||
|
|
||||||
function DeleteButton({ deleteDashboard, id }: DeleteButtonProps): JSX.Element {
|
function DeleteButton({
|
||||||
|
deleteDashboard,
|
||||||
|
id,
|
||||||
|
refetchDashboardList,
|
||||||
|
}: DeleteButtonProps): JSX.Element {
|
||||||
const [modal, contextHolder] = Modal.useModal();
|
const [modal, contextHolder] = Modal.useModal();
|
||||||
|
|
||||||
const openConfirmationDialog = useCallback((): void => {
|
const openConfirmationDialog = useCallback((): void => {
|
||||||
@ -20,13 +24,14 @@ function DeleteButton({ deleteDashboard, id }: DeleteButtonProps): JSX.Element {
|
|||||||
onOk() {
|
onOk() {
|
||||||
deleteDashboard({
|
deleteDashboard({
|
||||||
uuid: id,
|
uuid: id,
|
||||||
|
refetch: refetchDashboardList,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
okText: 'Delete',
|
okText: 'Delete',
|
||||||
okButtonProps: { danger: true },
|
okButtonProps: { danger: true },
|
||||||
centered: true,
|
centered: true,
|
||||||
});
|
});
|
||||||
}, [id, modal, deleteDashboard]);
|
}, [modal, deleteDashboard, id, refetchDashboardList]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -51,13 +56,22 @@ const mapDispatchToProps = (
|
|||||||
deleteDashboard: bindActionCreators(DeleteDashboard, dispatch),
|
deleteDashboard: bindActionCreators(DeleteDashboard, dispatch),
|
||||||
});
|
});
|
||||||
|
|
||||||
type DeleteButtonProps = Data & DispatchProps;
|
export type DeleteButtonProps = Data & DispatchProps;
|
||||||
|
|
||||||
const WrapperDeleteButton = connect(null, mapDispatchToProps)(DeleteButton);
|
const WrapperDeleteButton = connect(null, mapDispatchToProps)(DeleteButton);
|
||||||
|
|
||||||
// This is to avoid the type collision
|
// This is to avoid the type collision
|
||||||
function Wrapper(props: Data): JSX.Element {
|
function Wrapper(props: Data): JSX.Element {
|
||||||
const { createdBy, description, id, key, lastUpdatedTime, name, tags } = props;
|
const {
|
||||||
|
createdBy,
|
||||||
|
description,
|
||||||
|
id,
|
||||||
|
key,
|
||||||
|
refetchDashboardList,
|
||||||
|
lastUpdatedTime,
|
||||||
|
name,
|
||||||
|
tags,
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WrapperDeleteButton
|
<WrapperDeleteButton
|
||||||
@ -69,6 +83,7 @@ function Wrapper(props: Data): JSX.Element {
|
|||||||
lastUpdatedTime,
|
lastUpdatedTime,
|
||||||
name,
|
name,
|
||||||
tags,
|
tags,
|
||||||
|
refetchDashboardList,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -14,6 +14,7 @@ import { ResizeTable } from 'components/ResizeTable';
|
|||||||
import TextToolTip from 'components/TextToolTip';
|
import TextToolTip from 'components/TextToolTip';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import SearchFilter from 'container/ListOfDashboard/SearchFilter';
|
import SearchFilter from 'container/ListOfDashboard/SearchFilter';
|
||||||
|
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||||
import useComponentPermission from 'hooks/useComponentPermission';
|
import useComponentPermission from 'hooks/useComponentPermission';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import {
|
import {
|
||||||
@ -25,6 +26,7 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { UseQueryResult } from 'react-query';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { generatePath } from 'react-router-dom';
|
import { generatePath } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
@ -32,20 +34,24 @@ import AppActions from 'types/actions';
|
|||||||
import { GET_ALL_DASHBOARD_SUCCESS } from 'types/actions/dashboard';
|
import { GET_ALL_DASHBOARD_SUCCESS } from 'types/actions/dashboard';
|
||||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
import DashboardReducer from 'types/reducer/dashboards';
|
|
||||||
|
|
||||||
import ImportJSON from './ImportJSON';
|
import ImportJSON from './ImportJSON';
|
||||||
import { ButtonContainer, NewDashboardButton, TableContainer } from './styles';
|
import { ButtonContainer, NewDashboardButton, TableContainer } from './styles';
|
||||||
import Createdby from './TableComponents/CreatedBy';
|
import Createdby from './TableComponents/CreatedBy';
|
||||||
import DateComponent from './TableComponents/Date';
|
import DateComponent from './TableComponents/Date';
|
||||||
import DeleteButton from './TableComponents/DeleteButton';
|
import DeleteButton, {
|
||||||
|
DeleteButtonProps,
|
||||||
|
} from './TableComponents/DeleteButton';
|
||||||
import Name from './TableComponents/Name';
|
import Name from './TableComponents/Name';
|
||||||
import Tags from './TableComponents/Tags';
|
import Tags from './TableComponents/Tags';
|
||||||
|
|
||||||
function ListOfAllDashboard(): JSX.Element {
|
function ListOfAllDashboard(): JSX.Element {
|
||||||
const { dashboards, loading } = useSelector<AppState, DashboardReducer>(
|
const {
|
||||||
(state) => state.dashboards,
|
data: dashboardListResponse = [],
|
||||||
);
|
isLoading: isDashboardListLoading,
|
||||||
|
refetch: refetchDashboardList,
|
||||||
|
} = useGetAllDashboard();
|
||||||
|
|
||||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||||
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
|
|
||||||
@ -66,8 +72,10 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
const [filteredDashboards, setFilteredDashboards] = useState<Dashboard[]>();
|
const [filteredDashboards, setFilteredDashboards] = useState<Dashboard[]>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFilteredDashboards(dashboards);
|
if (dashboardListResponse.length) {
|
||||||
}, [dashboards]);
|
setFilteredDashboards(dashboardListResponse);
|
||||||
|
}
|
||||||
|
}, [dashboardListResponse]);
|
||||||
|
|
||||||
const [newDashboardState, setNewDashboardState] = useState({
|
const [newDashboardState, setNewDashboardState] = useState({
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -125,22 +133,43 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
title: 'Action',
|
title: 'Action',
|
||||||
dataIndex: '',
|
dataIndex: '',
|
||||||
width: 40,
|
width: 40,
|
||||||
render: DeleteButton,
|
render: ({
|
||||||
|
createdBy,
|
||||||
|
description,
|
||||||
|
id,
|
||||||
|
key,
|
||||||
|
lastUpdatedTime,
|
||||||
|
name,
|
||||||
|
tags,
|
||||||
|
}: DeleteButtonProps) => (
|
||||||
|
<DeleteButton
|
||||||
|
description={description}
|
||||||
|
id={id}
|
||||||
|
key={key}
|
||||||
|
lastUpdatedTime={lastUpdatedTime}
|
||||||
|
name={name}
|
||||||
|
tags={tags}
|
||||||
|
createdBy={createdBy}
|
||||||
|
refetchDashboardList={refetchDashboardList}
|
||||||
|
/>
|
||||||
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return tableColumns;
|
return tableColumns;
|
||||||
}, [action]);
|
}, [action, refetchDashboardList]);
|
||||||
|
|
||||||
const data: Data[] = (filteredDashboards || dashboards).map((e) => ({
|
const data: Data[] =
|
||||||
createdBy: e.created_at,
|
filteredDashboards?.map((e) => ({
|
||||||
description: e.data.description || '',
|
createdBy: e.created_at,
|
||||||
id: e.uuid,
|
description: e.data.description || '',
|
||||||
lastUpdatedTime: e.updated_at,
|
id: e.uuid,
|
||||||
name: e.data.title,
|
lastUpdatedTime: e.updated_at,
|
||||||
tags: e.data.tags || [],
|
name: e.data.title,
|
||||||
key: e.uuid,
|
tags: e.data.tags || [],
|
||||||
}));
|
key: e.uuid,
|
||||||
|
refetchDashboardList,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
const onNewDashboardHandler = useCallback(async () => {
|
const onNewDashboardHandler = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@ -209,7 +238,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
menuItems.push({
|
menuItems.push({
|
||||||
key: t('create_dashboard').toString(),
|
key: t('create_dashboard').toString(),
|
||||||
label: t('create_dashboard'),
|
label: t('create_dashboard'),
|
||||||
disabled: loading,
|
disabled: isDashboardListLoading,
|
||||||
onClick: onNewDashboardHandler,
|
onClick: onNewDashboardHandler,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -228,7 +257,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return menuItems;
|
return menuItems;
|
||||||
}, [createNewDashboard, loading, onNewDashboardHandler, t]);
|
}, [createNewDashboard, isDashboardListLoading, onNewDashboardHandler, t]);
|
||||||
|
|
||||||
const menu: MenuProps = useMemo(
|
const menu: MenuProps = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@ -250,7 +279,11 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{newDashboard && (
|
{newDashboard && (
|
||||||
<Dropdown disabled={loading} trigger={['click']} menu={menu}>
|
<Dropdown
|
||||||
|
disabled={isDashboardListLoading}
|
||||||
|
trigger={['click']}
|
||||||
|
menu={menu}
|
||||||
|
>
|
||||||
<NewDashboardButton
|
<NewDashboardButton
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
type="primary"
|
type="primary"
|
||||||
@ -266,7 +299,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
),
|
),
|
||||||
[
|
[
|
||||||
newDashboard,
|
newDashboard,
|
||||||
loading,
|
isDashboardListLoading,
|
||||||
menu,
|
menu,
|
||||||
newDashboardState.loading,
|
newDashboardState.loading,
|
||||||
newDashboardState.error,
|
newDashboardState.error,
|
||||||
@ -278,9 +311,9 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
<Card>
|
<Card>
|
||||||
{GetHeader}
|
{GetHeader}
|
||||||
|
|
||||||
{!loading && (
|
{!isDashboardListLoading && (
|
||||||
<SearchFilter
|
<SearchFilter
|
||||||
searchData={dashboards}
|
searchData={dashboardListResponse}
|
||||||
filterDashboards={setFilteredDashboards}
|
filterDashboards={setFilteredDashboards}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -300,7 +333,7 @@ function ListOfAllDashboard(): JSX.Element {
|
|||||||
showHeader
|
showHeader
|
||||||
bordered
|
bordered
|
||||||
sticky
|
sticky
|
||||||
loading={loading}
|
loading={isDashboardListLoading}
|
||||||
dataSource={data}
|
dataSource={data}
|
||||||
showSorterTooltip
|
showSorterTooltip
|
||||||
/>
|
/>
|
||||||
@ -317,6 +350,7 @@ export interface Data {
|
|||||||
createdBy: string;
|
createdBy: string;
|
||||||
lastUpdatedTime: string;
|
lastUpdatedTime: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
refetchDashboardList: UseQueryResult['refetch'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ListOfAllDashboard;
|
export default ListOfAllDashboard;
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
import getAll from 'api/dashboard/getAll';
|
import { getAllDashboardList } from 'api/dashboard/getAll';
|
||||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||||
import { useQuery, UseQueryResult } from 'react-query';
|
import { useQuery, UseQueryResult } from 'react-query';
|
||||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
import { PayloadProps } from 'types/api/dashboard/getAll';
|
|
||||||
|
|
||||||
export const useGetAllDashboard = (): DashboardProps =>
|
export const useGetAllDashboard = (): UseQueryResult<Dashboard[], unknown> =>
|
||||||
useQuery({
|
useQuery<Dashboard[]>({
|
||||||
queryFn: getAll,
|
queryFn: getAllDashboardList,
|
||||||
queryKey: REACT_QUERY_KEY.GET_ALL_DASHBOARDS,
|
queryKey: REACT_QUERY_KEY.GET_ALL_DASHBOARDS,
|
||||||
});
|
});
|
||||||
|
|
||||||
type DashboardProps = UseQueryResult<
|
|
||||||
SuccessResponse<PayloadProps> | ErrorResponse,
|
|
||||||
unknown
|
|
||||||
>;
|
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import ReleaseNote from 'components/ReleaseNote';
|
import ReleaseNote from 'components/ReleaseNote';
|
||||||
import ListOfAllDashboard from 'container/ListOfDashboard';
|
import ListOfAllDashboard from 'container/ListOfDashboard';
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { ThunkDispatch } from 'redux-thunk';
|
|
||||||
import { GetAllDashboards } from 'store/actions';
|
|
||||||
import AppActions from 'types/actions';
|
|
||||||
|
|
||||||
function Dashboard({ getAllDashboards }: DashboardProps): JSX.Element {
|
function Dashboard(): JSX.Element {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
useEffect(() => {
|
|
||||||
getAllDashboards();
|
|
||||||
}, [getAllDashboards]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
<Space direction="vertical" size="middle" style={{ width: '100%' }}>
|
||||||
@ -23,16 +14,4 @@ function Dashboard({ getAllDashboards }: DashboardProps): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DispatchProps {
|
export default Dashboard;
|
||||||
getAllDashboards: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapDispatchToProps = (
|
|
||||||
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
|
||||||
): DispatchProps => ({
|
|
||||||
getAllDashboards: bindActionCreators(GetAllDashboards, dispatch),
|
|
||||||
});
|
|
||||||
|
|
||||||
type DashboardProps = DispatchProps;
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(Dashboard);
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import deleteDashboardApi from 'api/dashboard/delete';
|
import deleteDashboardApi from 'api/dashboard/delete';
|
||||||
|
import { UseQueryResult } from 'react-query';
|
||||||
import { Dispatch } from 'redux';
|
import { Dispatch } from 'redux';
|
||||||
import AppActions from 'types/actions';
|
import AppActions from 'types/actions';
|
||||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||||
|
|
||||||
export const DeleteDashboard = ({
|
export const DeleteDashboard = ({
|
||||||
uuid,
|
uuid,
|
||||||
|
refetch,
|
||||||
}: DeleteDashboardProps): ((dispatch: Dispatch<AppActions>) => void) => async (
|
}: DeleteDashboardProps): ((dispatch: Dispatch<AppActions>) => void) => async (
|
||||||
dispatch: Dispatch<AppActions>,
|
dispatch: Dispatch<AppActions>,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
@ -14,6 +16,8 @@ export const DeleteDashboard = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.statusCode === 200) {
|
if (response.statusCode === 200) {
|
||||||
|
refetch();
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'DELETE_DASHBOARD_SUCCESS',
|
type: 'DELETE_DASHBOARD_SUCCESS',
|
||||||
payload: {
|
payload: {
|
||||||
@ -41,4 +45,5 @@ export const DeleteDashboard = ({
|
|||||||
|
|
||||||
export interface DeleteDashboardProps {
|
export interface DeleteDashboardProps {
|
||||||
uuid: Dashboard['uuid'];
|
uuid: Dashboard['uuid'];
|
||||||
|
refetch: UseQueryResult['refetch'];
|
||||||
}
|
}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import getAll from 'api/dashboard/getAll';
|
|
||||||
import { AxiosError } from 'axios';
|
|
||||||
import { Dispatch } from 'redux';
|
|
||||||
import AppActions from 'types/actions';
|
|
||||||
|
|
||||||
export const GetAllDashboards = (): ((
|
|
||||||
dispatch: Dispatch<AppActions>,
|
|
||||||
) => void) => async (dispatch: Dispatch<AppActions>): Promise<void> => {
|
|
||||||
try {
|
|
||||||
dispatch({
|
|
||||||
type: 'GET_ALL_DASHBOARD_LOADING_START',
|
|
||||||
});
|
|
||||||
const response = await getAll();
|
|
||||||
|
|
||||||
if (response.statusCode === 200) {
|
|
||||||
dispatch({
|
|
||||||
type: 'GET_ALL_DASHBOARD_SUCCESS',
|
|
||||||
payload: response.payload,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dispatch({
|
|
||||||
type: 'GET_ALL_DASHBOARD_ERROR',
|
|
||||||
payload: {
|
|
||||||
errorMessage: response.error || 'Something went wrong',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
dispatch({
|
|
||||||
type: 'GET_ALL_DASHBOARD_ERROR',
|
|
||||||
payload: {
|
|
||||||
errorMessage: (error as AxiosError).toString() || 'Something went wrong',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,7 +1,6 @@
|
|||||||
export * from './applySettingsToPanel';
|
export * from './applySettingsToPanel';
|
||||||
export * from './deleteDashboard';
|
export * from './deleteDashboard';
|
||||||
export * from './deleteQuery';
|
export * from './deleteQuery';
|
||||||
export * from './getAllDashboard';
|
|
||||||
export * from './getDashboard';
|
export * from './getDashboard';
|
||||||
export * from './toggleEditMode';
|
export * from './toggleEditMode';
|
||||||
export * from './updateDashboardTitle';
|
export * from './updateDashboardTitle';
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import { ErrorStatusCode, SuccessStatusCode } from 'types/common';
|
import { ErrorStatusCode, SuccessStatusCode } from 'types/common';
|
||||||
|
|
||||||
|
export type ApiResponse<T> = { data: T };
|
||||||
|
|
||||||
export interface ErrorResponse {
|
export interface ErrorResponse {
|
||||||
statusCode: ErrorStatusCode;
|
statusCode: ErrorStatusCode;
|
||||||
payload: null;
|
payload: null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user