diff --git a/client/src/Components/Fallback/index.jsx b/client/src/Components/Fallback/index.jsx
index f35229494..e5a212c00 100644
--- a/client/src/Components/Fallback/index.jsx
+++ b/client/src/Components/Fallback/index.jsx
@@ -88,14 +88,15 @@ const Fallback = ({
display: "flex",
borderStyle: "dashed",
height: {
- xs: theme.spacing(200),
- sm: theme.spacing(300),
- md: theme.spacing(300),
+ sm: "50vh",
+ md: "70vh",
+ lg: "60vh",
+ xl: "55vh",
},
width: {
- xs: theme.spacing(100),
- sm: theme.spacing(210),
- md: theme.spacing(250),
+ sm: "90%",
+ md: "50%",
+ lg: "40%",
},
padding: theme.spacing(10),
}}
diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js
index a7dae8b9a..f23e1eaea 100644
--- a/client/src/Hooks/checkHooks.js
+++ b/client/src/Hooks/checkHooks.js
@@ -1,6 +1,7 @@
import { useState, useEffect } from "react";
import { networkService } from "../main";
import { createToast } from "../Utils/toastUtils";
+import { useTranslation } from "react-i18next";
const useFetchChecksTeam = ({
status,
@@ -12,6 +13,7 @@ const useFetchChecksTeam = ({
page,
rowsPerPage,
enabled = true,
+ updateTrigger,
}) => {
const [checks, setChecks] = useState(undefined);
const [checksCount, setChecksCount] = useState(undefined);
@@ -49,7 +51,18 @@ const useFetchChecksTeam = ({
};
fetchChecks();
- }, [status, sortOrder, limit, dateRange, filter, ack, page, rowsPerPage, enabled]);
+ }, [
+ status,
+ sortOrder,
+ limit,
+ dateRange,
+ filter,
+ ack,
+ page,
+ rowsPerPage,
+ enabled,
+ updateTrigger,
+ ]);
return [checks, checksCount, isLoading, networkError];
};
@@ -66,6 +79,7 @@ const useFetchChecksByMonitor = ({
page,
rowsPerPage,
enabled = true,
+ updateTrigger,
}) => {
const [checks, setChecks] = useState(undefined);
const [checksCount, setChecksCount] = useState(undefined);
@@ -117,12 +131,13 @@ const useFetchChecksByMonitor = ({
page,
rowsPerPage,
enabled,
+ updateTrigger,
]);
return [checks, checksCount, isLoading, networkError];
};
-const useFetchChecksSummaryByTeamId = () => {
+const useFetchChecksSummaryByTeamId = ({ updateTrigger } = {}) => {
const [summary, setSummary] = useState(undefined);
const [isLoading, setIsLoading] = useState(false);
const [networkError, setNetworkError] = useState(false);
@@ -143,9 +158,56 @@ const useFetchChecksSummaryByTeamId = () => {
};
fetchSummary();
- }, []);
+ }, [updateTrigger]);
return [summary, isLoading, networkError];
};
-export { useFetchChecksByMonitor, useFetchChecksTeam, useFetchChecksSummaryByTeamId };
+const useResolveIncident = () => {
+ const [isLoading, setIsLoading] = useState(false);
+ const { t } = useTranslation();
+
+ const resolveIncident = async (checkId, setUpdateTrigger) => {
+ try {
+ setIsLoading(true);
+ await networkService.updateCheckStatus({
+ checkId,
+ ack: true,
+ });
+ setUpdateTrigger((prev) => !prev);
+ } catch (error) {
+ createToast({ body: t("checkHooks.failureResolveOne") });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return [resolveIncident, isLoading];
+};
+
+const useAckAllChecks = () => {
+ const [isLoading, setIsLoading] = useState(false);
+ const { t } = useTranslation();
+
+ const ackAllChecks = async (setUpdateTrigger) => {
+ try {
+ setIsLoading(true);
+ await networkService.updateAllChecksStatus({ ack: true });
+ setUpdateTrigger((prev) => !prev);
+ } catch (error) {
+ createToast({ body: t("checkHooks.failureResolveAll") });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return [ackAllChecks, isLoading];
+};
+
+export {
+ useFetchChecksByMonitor,
+ useFetchChecksTeam,
+ useFetchChecksSummaryByTeamId,
+ useResolveIncident,
+ useAckAllChecks,
+};
diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx
index bc5eaa5ca..e8929d9ed 100644
--- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx
+++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx
@@ -15,13 +15,17 @@ import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import { useFetchChecksTeam } from "../../../../Hooks/checkHooks";
import { useFetchChecksByMonitor } from "../../../../Hooks/checkHooks";
+import { useResolveIncident } from "../../../../Hooks/checkHooks";
+import { Button, Typography } from "@mui/material";
const IncidentTable = ({
- shouldRender,
+ isLoading,
monitors,
selectedMonitor,
filter,
dateRange,
+ updateTrigger,
+ setUpdateTrigger,
}) => {
//Redux state
const uiTimezone = useSelector((state) => state.ui.timezone);
@@ -32,6 +36,9 @@ const IncidentTable = ({
const selectedMonitorDetails = monitors?.[selectedMonitor];
const selectedMonitorType = selectedMonitorDetails?.type;
+ //Hooks
+ const [resolveIncident, resolveLoading] = useResolveIncident();
+
const [checksMonitor, checksCountMonitor, isLoadingMonitor, networkErrorMonitor] =
useFetchChecksByMonitor({
monitorId: selectedMonitor === "0" ? undefined : selectedMonitor,
@@ -45,6 +52,7 @@ const IncidentTable = ({
page: page,
rowsPerPage: rowsPerPage,
enabled: selectedMonitor !== "0",
+ updateTrigger,
});
const [checksTeam, checksCountTeam, isLoadingTeam, networkErrorTeam] =
@@ -58,11 +66,12 @@ const IncidentTable = ({
page: page,
rowsPerPage: rowsPerPage,
enabled: selectedMonitor === "0",
+ updateTrigger,
});
const checks = selectedMonitor === "0" ? checksTeam : checksMonitor;
const checksCount = selectedMonitor === "0" ? checksCountTeam : checksCountMonitor;
- const isLoading = isLoadingTeam || isLoadingMonitor;
+ isLoading = isLoadingTeam || isLoadingMonitor;
const networkError = selectedMonitor === "0" ? networkErrorTeam : networkErrorMonitor;
const { t } = useTranslation();
@@ -76,6 +85,10 @@ const IncidentTable = ({
setRowsPerPage(event.target.value);
};
+ const handleResolveIncident = (checkId) => {
+ resolveIncident(checkId, setUpdateTrigger);
+ };
+
const headers = [
{
id: "monitorName",
@@ -114,9 +127,31 @@ const IncidentTable = ({
render: (row) => ,
},
{ id: "message", content: t("incidentsTableMessage"), render: (row) => row.message },
+ {
+ id: "action",
+ content: t("actions"),
+ render: (row) => {
+ return row.ack === false ? (
+
+ ) : (
+
+ {t("incidentsTableResolvedAt")}{" "}
+ {formatDateWithTz(row.ackAt, "YYYY-MM-DD HH:mm:ss A", uiTimezone)}
+
+ );
+ },
+ },
];
- if (!shouldRender || isLoading) return ;
+ if (isLoading || resolveLoading) return ;
if (networkError) {
return (
@@ -149,10 +184,12 @@ const IncidentTable = ({
};
IncidentTable.propTypes = {
- shouldRender: PropTypes.bool,
+ isLoading: PropTypes.bool,
monitors: PropTypes.object,
selectedMonitor: PropTypes.string,
filter: PropTypes.string,
dateRange: PropTypes.string,
+ updateTrigger: PropTypes.bool,
+ setUpdateTrigger: PropTypes.func,
};
export default IncidentTable;
diff --git a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx
index 08a9bcf1c..259880223 100644
--- a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx
+++ b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx
@@ -21,6 +21,12 @@ const OptionsHeader = ({
const theme = useTheme();
const { t } = useTranslation();
const monitorNames = typeof monitors !== "undefined" ? Object.values(monitors) : [];
+ const filterOptions = [
+ { _id: "all", name: t("incidentsOptionsHeaderFilterAll") },
+ { _id: "down", name: t("incidentsOptionsHeaderFilterDown") },
+ { _id: "resolve", name: t("incidentsOptionsHeaderFilterCannotResolve") },
+ { _id: "resolved", name: t("incidentsOptionsHeaderFilterResolved") },
+ ];
// The stacks below which are three in number have the same style so
const stackStyles = {
@@ -65,36 +71,16 @@ const OptionsHeader = ({
>
{t("incidentsOptionsHeaderFilterBy")}
-
-
-
-
-
-
+