mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-10-19 23:51:08 +08:00

* feat: tabs and filters for alert history page (#5655) * feat: alert history page route and component setup * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * chore: unused components and files cleanup * chore: improve alert history and overview route paths * chore: use parent selector in scss files * chore: alert -> alerts * feat: alert rule details metadata header (#5675) * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * chore: unused components and files cleanup * feat: copy to clipboard component * feat: see more component * feat: key value label component * feat: alert rule details meta data header * fix: apply the missing changes * chore: uncomment the alert status with static data * chore: compress the alert status svg icons and define props, types, and defaultProps * feat: alert rule history skeleton using static data (#5688) * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * feat: top contributors UI using static data * feat: avg. resolution time and total triggered stats card UI using static data * feat: tabs component * feat: timeline tabs and filters * feat: overall status graph UI using dummy data with graph placeholder * feat: timeline table and pagination UI using dummy data * fix: bugfix in reset tabs * feat: add popover to go to logs/traces to top contributors and timeline table * chore: remove comments * chore: rename AlertIcon to AlertState * fix: add cursor pointer to timeline table rows * feat: add parent tabs to alert history * chore: add icon to the configure tab * fix: display popover on hovering the more button in see more component * fix: wrap key value label * feat: alert rule history enable/disable toggle UI * Feat: get alert history data from API (#5718) * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * feat: data state renderer component * feat: get total triggered and avg. resolution cards data from API * fix: hide stats card if we get NaN * chore: improve rule stats types * feat: get top contributors data from API * feat: get timeline table data from API * fix: properly render change percentage indicator * feat: total triggered and avg resolution empty states * fix: fix stats height issue that would cause short border-right in empty case * feat: top contributors empty state * fix: fix table and graph borders * feat: build alert timeline labels filter and handle client side filtering * fix: select the first tab on clicking reset * feat: set param and send in payload on clicking timeline filter tabs * Feat: alert history timeline remaining subtasks except graphs (#5720) * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * feat: implement timeline table sorting * chore: add initial count to see more and alert labels * chore: move PaginationInfoText component to /periscope * chore: implement top contributor rows using Ant Table * feat: top contributors view all * fix: hide border for last row and prevent layout shift in top contributors by specifying height * feat: properly display duration in average resolution time * fix: properly display normal alert rule state * feat: add/remove view all top contributors param to url on opening/closing view all * feat: calculate start and end time from relative time and add/remove param to url * fix: fix console warnings * fix: enable timeline table query only if start and end times exist * feat: handle enable/disable alert rule toggle request * chore: replace string values with constants * fix: hide stats card if only past data is available + remove unnecessary states from AlertState * fix: redirect configure alert rule to alert overview tab * fix: display total triggers in timeline chart wrapper based on API response data * fix: choosing the same relative time doesn't udpate start and end time * Feat: total triggered and avg. resolution time graph (#5750) * feat: alert history basic tabs and fitlers UI * feat: route based tabs for alert history and overview and improve the UI to match designs * feat: handle enable/disable alert rule toggle request * feat: stats card line chart * fix: overall improvements to stats card graph * fix: overall UI improvements to match the Figma screens * chore: remove duplicate hook * fix: make the changes w.r.t timeline table API changes to prevent breaking the page * fix: update stats card null check based on updated API response * feat: stats card no previous data UI * feat: redirect to 404 page if rule id is invalid * chore: improve alert enable toggle success toast message * feat: get top contributors row and timeline table row related logs and traces links from API * feat: get total items from API and make pagination work * feat: implement timeline filters based on API response * fix: in case of current and target units, convert the value unit in timeline table * fix: timeline table y axis unit null check * fix: hide stats card graph if only a single entry is there in timeseries * chore: redirect alert from all alerts to overview tab * fix: prevent adding extra unnecessary params on clicking alerts top level tabs * chore: use conditional alert popover in timeline table and import the scss file * fix: prevent infinity if we receive totalPastTriggers as '0' * fix: improve UI to be pixel perfect based on figma designs * fix: fix the incorrect change direction * fix: add height to top contributors row * feat: alert history light mode * fix: remove the extra padding from alert overview query builder tabs * chore: overall improvements * chore: remove mock file * fix: overall improvements * fix: add dark mode support for top contributors empty state * chore: improve timeline chart placeholder bg in light mode * Feat: alert history horizontal timeline chart (#5773) * feat: timeline horizontal chart * fix: remove the labels from horizontal timeline chart * chore: add null check to timeline chart * chore: hide cursor from timeline chart * fix: fix the blank container being displayed in loading state * fix: alert history UI fixes (#5776) * fix: remove extra padding from alert overview query section tabs * fix: add padding to alert overview container * fix: improve breadcrumb click behavior * chore: temporarily hide reset button from alert details timepicker * fix: improve breadcrumb click behavior * chore: hide alert firing since * fix: don't use the data state renderer for timeline table * fix: alert history pr review changes (#5778) * chore: rename alert history scss files in pascal case * fix: use proper variables * chore: use color variable for action button dropdown item * chore: improve the directory structure for alert history components * chore: move inline style to scss file and extract dropdown renderer component * chore: use colors from Color instead of css variables inside tsx files * chore: return null in default case * chore: update alert details spinner tip * chore: timelinePlugin warnings and remove file wide warning disabling * chore: change Arial to Geist Mono in timeline plugin * feat: alert history remaining feats (#5825) * fix: add switch case for inactive state to alert state component * feat: add API enabled label search similar to Query Builder * feat: add reset button to date and time picker * feat: add vertical timeline chart using static data * chore: use Colors instead of hex + dummy data for 90 days * fix: label search light mode UI * fix: remove placeholder logic, and display vertical charts if more than 1 day * chore: extract dayjs manipulate types to a constant * fix: hide the overflow of top contributors card * fix: throw instead of return error to prevent breaking alert history page in case of error * chore: temporarily comment alert history vertical charts * chore: calculate start and end times from relative time and remove query params (#5828) * chore: calculate start and end times from relative time and remove query params * fix: hide reset button if selected time is 30m * feat: alert history dropdown functionality (#5833) * feat: alert history dropdown actions * chore: use query keys from react query key constant * fix: properly handle error states for alert rule APIs * fix: handle dropdown state using onOpenChange to fix clicking delete not closing the dropdown * Fix: bugfixes and overall improvements to alert history (#5841) * fix: don't display severity label * chore: remove id from alert header * chore: add tooltip to enable/disable alert toggle * chore: update enable/disbale toast message * fix: set default relative time to 6h if relative time is not provided * chore: update empty top contributors text and remove configure alert * chore: temporarily hide value column from timeline column * fix: use correct links for logs and traces in alert popover * fix: properly set timeline table offset * fix: display all values in graph * fix: resolve conflicts * chore: remove style for value column in timeline table * chore: temporarily hide labels search * fix: incorrect current page in pagination info text * chore: remove label QB search * chore: remove value column * chore: remove commented code * fix: show traces button when trace link is available * fix: display horizontal chart even for a single entry * fix: show inactive state in horizontal similar to normal state * fix: properly render inactive state in horizontal chart * fix: properly handle preserving alert toggle between overview and history tabs * feat: get page size from query param * chore: remove commented code + minor refactor * chore: remove tsconfi.tmp * fix: don't add default relative time if start and times exist in the url * feat: display date range preview for stat cards * chore: remove custom dropdown renderer component * Fix: UI feedback changes (#5852) * fix: add divider before delete button * fix: timeline section title color in lightmode * fix: remove the extra border from alert history tabs * fix: populate alert rule disabled state on toggling alert state (#5854) --------- Co-authored-by: Shaheer Kochai <ashaheerki@gmail.com>
526 lines
14 KiB
TypeScript
526 lines
14 KiB
TypeScript
import { FilterValue, SorterResult } from 'antd/es/table/interface';
|
|
import { TablePaginationConfig, TableProps } from 'antd/lib';
|
|
import deleteAlerts from 'api/alerts/delete';
|
|
import get from 'api/alerts/get';
|
|
import getAll from 'api/alerts/getAll';
|
|
import patchAlert from 'api/alerts/patch';
|
|
import ruleStats from 'api/alerts/ruleStats';
|
|
import save from 'api/alerts/save';
|
|
import timelineGraph from 'api/alerts/timelineGraph';
|
|
import timelineTable from 'api/alerts/timelineTable';
|
|
import topContributors from 'api/alerts/topContributors';
|
|
import { TabRoutes } from 'components/RouteTab/types';
|
|
import { QueryParams } from 'constants/query';
|
|
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
|
import ROUTES from 'constants/routes';
|
|
import AlertHistory from 'container/AlertHistory';
|
|
import { TIMELINE_TABLE_PAGE_SIZE } from 'container/AlertHistory/constants';
|
|
import { AlertDetailsTab, TimelineFilter } from 'container/AlertHistory/types';
|
|
import { urlKey } from 'container/AllError/utils';
|
|
import useAxiosError from 'hooks/useAxiosError';
|
|
import { useNotifications } from 'hooks/useNotifications';
|
|
import useUrlQuery from 'hooks/useUrlQuery';
|
|
import createQueryParams from 'lib/createQueryParams';
|
|
import GetMinMax from 'lib/getMinMax';
|
|
import history from 'lib/history';
|
|
import { History, Table } from 'lucide-react';
|
|
import EditRules from 'pages/EditRules';
|
|
import { OrderPreferenceItems } from 'pages/Logs/config';
|
|
import PaginationInfoText from 'periscope/components/PaginationInfoText/PaginationInfoText';
|
|
import { useAlertRule } from 'providers/Alert';
|
|
import { useCallback, useMemo } from 'react';
|
|
import { useMutation, useQuery, useQueryClient } from 'react-query';
|
|
import { useSelector } from 'react-redux';
|
|
import { generatePath, useLocation } from 'react-router-dom';
|
|
import { AppState } from 'store/reducers';
|
|
import { ErrorResponse, SuccessResponse } from 'types/api';
|
|
import {
|
|
AlertDef,
|
|
AlertRuleStatsPayload,
|
|
AlertRuleTimelineGraphResponsePayload,
|
|
AlertRuleTimelineTableResponse,
|
|
AlertRuleTimelineTableResponsePayload,
|
|
AlertRuleTopContributorsPayload,
|
|
} from 'types/api/alerts/def';
|
|
import { PayloadProps } from 'types/api/alerts/get';
|
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
|
import { nanoToMilli } from 'utils/timeUtils';
|
|
|
|
export const useAlertHistoryQueryParams = (): {
|
|
ruleId: string | null;
|
|
startTime: number;
|
|
endTime: number;
|
|
hasStartAndEndParams: boolean;
|
|
params: URLSearchParams;
|
|
} => {
|
|
const params = useUrlQuery();
|
|
|
|
const globalTime = useSelector<AppState, GlobalReducer>(
|
|
(state) => state.globalTime,
|
|
);
|
|
const startTime = params.get(QueryParams.startTime);
|
|
const endTime = params.get(QueryParams.endTime);
|
|
|
|
const intStartTime = parseInt(startTime || '0', 10);
|
|
const intEndTime = parseInt(endTime || '0', 10);
|
|
const hasStartAndEndParams = !!intStartTime && !!intEndTime;
|
|
|
|
const { maxTime, minTime } = useMemo(() => {
|
|
if (hasStartAndEndParams)
|
|
return GetMinMax('custom', [intStartTime, intEndTime]);
|
|
return GetMinMax(globalTime.selectedTime);
|
|
}, [hasStartAndEndParams, intStartTime, intEndTime, globalTime.selectedTime]);
|
|
|
|
const ruleId = params.get(QueryParams.ruleId);
|
|
|
|
return {
|
|
ruleId,
|
|
startTime: Math.floor(nanoToMilli(minTime)),
|
|
endTime: Math.floor(nanoToMilli(maxTime)),
|
|
hasStartAndEndParams,
|
|
params,
|
|
};
|
|
};
|
|
export const useRouteTabUtils = (): { routes: TabRoutes[] } => {
|
|
const urlQuery = useUrlQuery();
|
|
|
|
const getRouteUrl = (tab: AlertDetailsTab): string => {
|
|
let route = '';
|
|
let params = urlQuery.toString();
|
|
const ruleIdKey = QueryParams.ruleId;
|
|
const relativeTimeKey = QueryParams.relativeTime;
|
|
|
|
switch (tab) {
|
|
case AlertDetailsTab.OVERVIEW:
|
|
route = ROUTES.ALERT_OVERVIEW;
|
|
break;
|
|
case AlertDetailsTab.HISTORY:
|
|
params = `${ruleIdKey}=${urlQuery.get(
|
|
ruleIdKey,
|
|
)}&${relativeTimeKey}=${urlQuery.get(relativeTimeKey)}`;
|
|
route = ROUTES.ALERT_HISTORY;
|
|
break;
|
|
default:
|
|
return '';
|
|
}
|
|
|
|
return `${generatePath(route)}?${params}`;
|
|
};
|
|
|
|
const routes = [
|
|
{
|
|
Component: EditRules,
|
|
name: (
|
|
<div className="tab-item">
|
|
<Table size={14} />
|
|
Overview
|
|
</div>
|
|
),
|
|
route: getRouteUrl(AlertDetailsTab.OVERVIEW),
|
|
key: ROUTES.ALERT_OVERVIEW,
|
|
},
|
|
{
|
|
Component: AlertHistory,
|
|
name: (
|
|
<div className="tab-item">
|
|
<History size={14} />
|
|
History
|
|
</div>
|
|
),
|
|
route: getRouteUrl(AlertDetailsTab.HISTORY),
|
|
key: ROUTES.ALERT_HISTORY,
|
|
},
|
|
];
|
|
|
|
return { routes };
|
|
};
|
|
type Props = {
|
|
ruleId: string | null;
|
|
isValidRuleId: boolean;
|
|
alertDetailsResponse:
|
|
| SuccessResponse<PayloadProps, unknown>
|
|
| ErrorResponse
|
|
| undefined;
|
|
isLoading: boolean;
|
|
isRefetching: boolean;
|
|
isError: boolean;
|
|
};
|
|
|
|
export const useGetAlertRuleDetails = (): Props => {
|
|
const { ruleId } = useAlertHistoryQueryParams();
|
|
|
|
const isValidRuleId = ruleId !== null && String(ruleId).length !== 0;
|
|
|
|
const {
|
|
isLoading,
|
|
data: alertDetailsResponse,
|
|
isRefetching,
|
|
isError,
|
|
} = useQuery([REACT_QUERY_KEY.ALERT_RULE_DETAILS, ruleId], {
|
|
queryFn: () =>
|
|
get({
|
|
id: parseInt(ruleId || '', 10),
|
|
}),
|
|
enabled: isValidRuleId,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
});
|
|
|
|
return {
|
|
ruleId,
|
|
isLoading,
|
|
alertDetailsResponse,
|
|
isRefetching,
|
|
isError,
|
|
isValidRuleId,
|
|
};
|
|
};
|
|
|
|
type GetAlertRuleDetailsApiProps = {
|
|
isLoading: boolean;
|
|
isRefetching: boolean;
|
|
isError: boolean;
|
|
isValidRuleId: boolean;
|
|
ruleId: string | null;
|
|
};
|
|
|
|
type GetAlertRuleDetailsStatsProps = GetAlertRuleDetailsApiProps & {
|
|
data:
|
|
| SuccessResponse<AlertRuleStatsPayload, unknown>
|
|
| ErrorResponse
|
|
| undefined;
|
|
};
|
|
|
|
export const useGetAlertRuleDetailsStats = (): GetAlertRuleDetailsStatsProps => {
|
|
const { ruleId, startTime, endTime } = useAlertHistoryQueryParams();
|
|
|
|
const isValidRuleId = ruleId !== null && String(ruleId).length !== 0;
|
|
|
|
const { isLoading, isRefetching, isError, data } = useQuery(
|
|
[REACT_QUERY_KEY.ALERT_RULE_STATS, ruleId, startTime, endTime],
|
|
{
|
|
queryFn: () =>
|
|
ruleStats({
|
|
id: parseInt(ruleId || '', 10),
|
|
start: startTime,
|
|
end: endTime,
|
|
}),
|
|
enabled: isValidRuleId && !!startTime && !!endTime,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
);
|
|
|
|
return { isLoading, isRefetching, isError, data, isValidRuleId, ruleId };
|
|
};
|
|
|
|
type GetAlertRuleDetailsTopContributorsProps = GetAlertRuleDetailsApiProps & {
|
|
data:
|
|
| SuccessResponse<AlertRuleTopContributorsPayload, unknown>
|
|
| ErrorResponse
|
|
| undefined;
|
|
};
|
|
|
|
export const useGetAlertRuleDetailsTopContributors = (): GetAlertRuleDetailsTopContributorsProps => {
|
|
const { ruleId, startTime, endTime } = useAlertHistoryQueryParams();
|
|
|
|
const isValidRuleId = ruleId !== null && String(ruleId).length !== 0;
|
|
|
|
const { isLoading, isRefetching, isError, data } = useQuery(
|
|
[REACT_QUERY_KEY.ALERT_RULE_TOP_CONTRIBUTORS, ruleId, startTime, endTime],
|
|
{
|
|
queryFn: () =>
|
|
topContributors({
|
|
id: parseInt(ruleId || '', 10),
|
|
start: startTime,
|
|
end: endTime,
|
|
}),
|
|
enabled: isValidRuleId,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
);
|
|
|
|
return { isLoading, isRefetching, isError, data, isValidRuleId, ruleId };
|
|
};
|
|
|
|
type GetAlertRuleDetailsTimelineTableProps = GetAlertRuleDetailsApiProps & {
|
|
data:
|
|
| SuccessResponse<AlertRuleTimelineTableResponsePayload, unknown>
|
|
| ErrorResponse
|
|
| undefined;
|
|
};
|
|
|
|
export const useGetAlertRuleDetailsTimelineTable = (): GetAlertRuleDetailsTimelineTableProps => {
|
|
const { ruleId, startTime, endTime, params } = useAlertHistoryQueryParams();
|
|
const { updatedOrder, offset } = useMemo(
|
|
() => ({
|
|
updatedOrder: params.get(urlKey.order) ?? OrderPreferenceItems.ASC,
|
|
offset: parseInt(params.get(urlKey.offset) ?? '1', 10),
|
|
}),
|
|
[params],
|
|
);
|
|
|
|
const timelineFilter = params.get('timelineFilter');
|
|
|
|
const isValidRuleId = ruleId !== null && String(ruleId).length !== 0;
|
|
const hasStartAndEnd = startTime !== null && endTime !== null;
|
|
|
|
const { isLoading, isRefetching, isError, data } = useQuery(
|
|
[
|
|
REACT_QUERY_KEY.ALERT_RULE_TIMELINE_TABLE,
|
|
ruleId,
|
|
startTime,
|
|
endTime,
|
|
timelineFilter,
|
|
updatedOrder,
|
|
offset,
|
|
],
|
|
{
|
|
queryFn: () =>
|
|
timelineTable({
|
|
id: parseInt(ruleId || '', 10),
|
|
start: startTime,
|
|
end: endTime,
|
|
limit: TIMELINE_TABLE_PAGE_SIZE,
|
|
order: updatedOrder,
|
|
offset,
|
|
|
|
...(timelineFilter && timelineFilter !== TimelineFilter.ALL
|
|
? {
|
|
state: timelineFilter === TimelineFilter.FIRED ? 'firing' : 'normal',
|
|
}
|
|
: {}),
|
|
}),
|
|
enabled: isValidRuleId && hasStartAndEnd,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
);
|
|
|
|
return { isLoading, isRefetching, isError, data, isValidRuleId, ruleId };
|
|
};
|
|
|
|
export const useTimelineTable = ({
|
|
totalItems,
|
|
}: {
|
|
totalItems: number;
|
|
}): {
|
|
paginationConfig: TablePaginationConfig;
|
|
onChangeHandler: (
|
|
pagination: TablePaginationConfig,
|
|
sorter: any,
|
|
filters: any,
|
|
extra: any,
|
|
) => void;
|
|
} => {
|
|
const { pathname } = useLocation();
|
|
|
|
const { search } = useLocation();
|
|
|
|
const params = useMemo(() => new URLSearchParams(search), [search]);
|
|
|
|
const offset = params.get('offset') ?? '0';
|
|
|
|
const onChangeHandler: TableProps<AlertRuleTimelineTableResponse>['onChange'] = useCallback(
|
|
(
|
|
pagination: TablePaginationConfig,
|
|
filters: Record<string, FilterValue | null>,
|
|
sorter:
|
|
| SorterResult<AlertRuleTimelineTableResponse>[]
|
|
| SorterResult<AlertRuleTimelineTableResponse>,
|
|
) => {
|
|
if (!Array.isArray(sorter)) {
|
|
const { pageSize = 0, current = 0 } = pagination;
|
|
const { order } = sorter;
|
|
const updatedOrder = order === 'ascend' ? 'asc' : 'desc';
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
history.replace(
|
|
`${pathname}?${createQueryParams({
|
|
...Object.fromEntries(params),
|
|
order: updatedOrder,
|
|
offset: current * TIMELINE_TABLE_PAGE_SIZE - TIMELINE_TABLE_PAGE_SIZE,
|
|
pageSize,
|
|
})}`,
|
|
);
|
|
}
|
|
},
|
|
[pathname],
|
|
);
|
|
|
|
const offsetInt = parseInt(offset, 10);
|
|
const pageSize = params.get('pageSize') ?? String(TIMELINE_TABLE_PAGE_SIZE);
|
|
const pageSizeInt = parseInt(pageSize, 10);
|
|
|
|
const paginationConfig: TablePaginationConfig = {
|
|
pageSize: pageSizeInt,
|
|
showTotal: PaginationInfoText,
|
|
current: offsetInt / TIMELINE_TABLE_PAGE_SIZE + 1,
|
|
showSizeChanger: false,
|
|
hideOnSinglePage: true,
|
|
total: totalItems,
|
|
};
|
|
|
|
return { paginationConfig, onChangeHandler };
|
|
};
|
|
|
|
export const useAlertRuleStatusToggle = ({
|
|
ruleId,
|
|
}: {
|
|
ruleId: string;
|
|
}): {
|
|
handleAlertStateToggle: (state: boolean) => void;
|
|
} => {
|
|
const { isAlertRuleDisabled, setIsAlertRuleDisabled } = useAlertRule();
|
|
const { notifications } = useNotifications();
|
|
|
|
const queryClient = useQueryClient();
|
|
const handleError = useAxiosError();
|
|
|
|
const { mutate: toggleAlertState } = useMutation(
|
|
[REACT_QUERY_KEY.TOGGLE_ALERT_STATE, ruleId],
|
|
patchAlert,
|
|
{
|
|
onMutate: () => {
|
|
setIsAlertRuleDisabled((prev) => !prev);
|
|
},
|
|
onSuccess: () => {
|
|
notifications.success({
|
|
message: `Alert has been ${isAlertRuleDisabled ? 'enabled' : 'disabled'}.`,
|
|
});
|
|
},
|
|
onError: (error) => {
|
|
queryClient.refetchQueries([REACT_QUERY_KEY.ALERT_RULE_DETAILS]);
|
|
handleError(error);
|
|
},
|
|
},
|
|
);
|
|
|
|
const handleAlertStateToggle = (): void => {
|
|
const args = {
|
|
id: parseInt(ruleId, 10),
|
|
data: { disabled: !isAlertRuleDisabled },
|
|
};
|
|
toggleAlertState(args);
|
|
};
|
|
|
|
return { handleAlertStateToggle };
|
|
};
|
|
|
|
export const useAlertRuleDuplicate = ({
|
|
alertDetails,
|
|
}: {
|
|
alertDetails: AlertDef;
|
|
}): {
|
|
handleAlertDuplicate: () => void;
|
|
} => {
|
|
const { notifications } = useNotifications();
|
|
|
|
const params = useUrlQuery();
|
|
|
|
const { refetch } = useQuery(REACT_QUERY_KEY.GET_ALL_ALLERTS, {
|
|
queryFn: getAll,
|
|
cacheTime: 0,
|
|
});
|
|
const handleError = useAxiosError();
|
|
const { mutate: duplicateAlert } = useMutation(
|
|
[REACT_QUERY_KEY.DUPLICATE_ALERT_RULE],
|
|
save,
|
|
{
|
|
onSuccess: async () => {
|
|
notifications.success({
|
|
message: `Success`,
|
|
});
|
|
|
|
const { data: allAlertsData } = await refetch();
|
|
|
|
if (
|
|
allAlertsData &&
|
|
allAlertsData.payload &&
|
|
allAlertsData.payload.length > 0
|
|
) {
|
|
const clonedAlert =
|
|
allAlertsData.payload[allAlertsData.payload.length - 1];
|
|
params.set(QueryParams.ruleId, String(clonedAlert.id));
|
|
history.push(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
|
|
}
|
|
},
|
|
onError: handleError,
|
|
},
|
|
);
|
|
|
|
const handleAlertDuplicate = (): void => {
|
|
const args = {
|
|
data: { ...alertDetails, alert: alertDetails.alert?.concat(' - Copy') },
|
|
};
|
|
duplicateAlert(args);
|
|
};
|
|
|
|
return { handleAlertDuplicate };
|
|
};
|
|
|
|
export const useAlertRuleDelete = ({
|
|
ruleId,
|
|
}: {
|
|
ruleId: number;
|
|
}): {
|
|
handleAlertDelete: () => void;
|
|
} => {
|
|
const { notifications } = useNotifications();
|
|
const handleError = useAxiosError();
|
|
|
|
const { mutate: deleteAlert } = useMutation(
|
|
[REACT_QUERY_KEY.REMOVE_ALERT_RULE, ruleId],
|
|
deleteAlerts,
|
|
{
|
|
onSuccess: async () => {
|
|
notifications.success({
|
|
message: `Success`,
|
|
});
|
|
|
|
history.push(ROUTES.LIST_ALL_ALERT);
|
|
},
|
|
onError: handleError,
|
|
},
|
|
);
|
|
|
|
const handleAlertDelete = (): void => {
|
|
const args = { id: ruleId };
|
|
deleteAlert(args);
|
|
};
|
|
|
|
return { handleAlertDelete };
|
|
};
|
|
|
|
type GetAlertRuleDetailsTimelineGraphProps = GetAlertRuleDetailsApiProps & {
|
|
data:
|
|
| SuccessResponse<AlertRuleTimelineGraphResponsePayload, unknown>
|
|
| ErrorResponse
|
|
| undefined;
|
|
};
|
|
|
|
export const useGetAlertRuleDetailsTimelineGraphData = (): GetAlertRuleDetailsTimelineGraphProps => {
|
|
const { ruleId, startTime, endTime } = useAlertHistoryQueryParams();
|
|
|
|
const isValidRuleId = ruleId !== null && String(ruleId).length !== 0;
|
|
const hasStartAndEnd = startTime !== null && endTime !== null;
|
|
|
|
const { isLoading, isRefetching, isError, data } = useQuery(
|
|
[REACT_QUERY_KEY.ALERT_RULE_TIMELINE_GRAPH, ruleId, startTime, endTime],
|
|
{
|
|
queryFn: () =>
|
|
timelineGraph({
|
|
id: parseInt(ruleId || '', 10),
|
|
start: startTime,
|
|
end: endTime,
|
|
}),
|
|
enabled: isValidRuleId && hasStartAndEnd,
|
|
refetchOnMount: false,
|
|
refetchOnWindowFocus: false,
|
|
},
|
|
);
|
|
|
|
return { isLoading, isRefetching, isError, data, isValidRuleId, ruleId };
|
|
};
|