mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-07 02:09:46 -06:00
Merge pull request #2431 from bluewave-labs/fix/redux-removal-hook-cleanup
fix: redux removal hook cleanup
This commit is contained in:
@@ -105,7 +105,7 @@ const Checkbox = ({
|
||||
};
|
||||
|
||||
Checkbox.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
id: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
|
||||
size: PropTypes.oneOf(["small", "medium", "large"]),
|
||||
|
||||
@@ -11,10 +11,9 @@ import EmailIcon from "@mui/icons-material/Email";
|
||||
import PropTypes from "prop-types";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { usePauseMonitor } from "../../Hooks/useMonitorControls";
|
||||
import { usePauseMonitor } from "../../Hooks/monitorHooks";
|
||||
import { useSendTestEmail } from "../../Hooks/useSendTestEmail";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
/**
|
||||
* MonitorDetailsControlHeader component displays the control header for monitor details.
|
||||
* It includes status display, pause/resume button, and a configure button for admins.
|
||||
@@ -38,10 +37,7 @@ const MonitorDetailsControlHeader = ({
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const [pauseMonitor, isPausing, error] = usePauseMonitor({
|
||||
monitorId: monitor?._id,
|
||||
triggerUpdate,
|
||||
});
|
||||
const [pauseMonitor, isPausing, error] = usePauseMonitor();
|
||||
|
||||
const [isSending, emailError, sendTestEmail] = useSendTestEmail();
|
||||
|
||||
@@ -88,7 +84,10 @@ const MonitorDetailsControlHeader = ({
|
||||
monitor?.isActive ? <PauseOutlinedIcon /> : <PlayArrowOutlinedIcon />
|
||||
}
|
||||
onClick={() => {
|
||||
pauseMonitor();
|
||||
pauseMonitor({
|
||||
monitorId: monitor?._id,
|
||||
triggerUpdate,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{monitor?.isActive ? "Pause" : "Resume"}
|
||||
|
||||
@@ -7,8 +7,7 @@ import Dot from "../../Components/Dot";
|
||||
import { formatDurationRounded } from "../../Utils/timeUtils";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
|
||||
import { useMonitorUtils } from "../../Hooks/useMonitorUtils";
|
||||
/**
|
||||
* Status component displays the status information of a monitor.
|
||||
* It includes the monitor's name, URL, and check interval.
|
||||
@@ -23,7 +22,7 @@ import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
*/
|
||||
const Status = ({ monitor }) => {
|
||||
const theme = useTheme();
|
||||
const { statusColor, determineState } = useUtils();
|
||||
const { statusColor, determineState } = useMonitorUtils();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material";
|
||||
import PulseDot from "../Animated/PulseDot";
|
||||
import Dot from "../Dot";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../Hooks/useMonitorUtils";
|
||||
import { formatDurationRounded } from "../../Utils/timeUtils";
|
||||
import ConfigButton from "./ConfigButton";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
@@ -12,7 +12,7 @@ import { useTranslation } from "react-i18next";
|
||||
const MonitorStatusHeader = ({ path, isLoading = false, isAdmin, monitor }) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { statusColor, determineState } = useUtils();
|
||||
const { statusColor, determineState } = useMonitorUtils();
|
||||
if (isLoading) {
|
||||
return <SkeletonLayout />;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material";
|
||||
import Image from "../Image";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import PropTypes from "prop-types";
|
||||
import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../Hooks/useMonitorUtils";
|
||||
|
||||
/**
|
||||
* StatBox Component
|
||||
@@ -41,7 +41,7 @@ const StatBox = ({
|
||||
sx,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { statusToTheme } = useUtils();
|
||||
const { statusToTheme } = useMonitorUtils();
|
||||
const themeColor = statusToTheme[status];
|
||||
|
||||
const statusBoxStyles = gradient
|
||||
|
||||
85
client/src/Hooks/checkHooks.js
Normal file
85
client/src/Hooks/checkHooks.js
Normal file
@@ -0,0 +1,85 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
|
||||
const useFetchChecks = ({
|
||||
teamId,
|
||||
monitorId,
|
||||
type,
|
||||
status,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
filter,
|
||||
page,
|
||||
rowsPerPage,
|
||||
}) => {
|
||||
const [checks, setChecks] = useState(undefined);
|
||||
const [checksCount, setChecksCount] = useState(undefined);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchChecks = async () => {
|
||||
if (!type && !teamId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const method = monitorId
|
||||
? networkService.getChecksByMonitor
|
||||
: networkService.getChecksByTeam;
|
||||
|
||||
const config = monitorId
|
||||
? {
|
||||
monitorId,
|
||||
type,
|
||||
status,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
filter,
|
||||
page,
|
||||
rowsPerPage,
|
||||
}
|
||||
: {
|
||||
status,
|
||||
teamId,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
filter,
|
||||
page,
|
||||
rowsPerPage,
|
||||
};
|
||||
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await method(config);
|
||||
setChecks(res.data.data.checks);
|
||||
setChecksCount(res.data.data.checksCount);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchChecks();
|
||||
}, [
|
||||
monitorId,
|
||||
teamId,
|
||||
type,
|
||||
status,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
filter,
|
||||
page,
|
||||
rowsPerPage,
|
||||
]);
|
||||
|
||||
return [checks, checksCount, isLoading, networkError];
|
||||
};
|
||||
|
||||
export { useFetchChecks };
|
||||
398
client/src/Hooks/monitorHooks.js
Normal file
398
client/src/Hooks/monitorHooks.js
Normal file
@@ -0,0 +1,398 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorUtils } from "./useMonitorUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const useFetchMonitorsWithSummary = ({ teamId, types, monitorUpdateTrigger }) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [monitorsSummary, setMonitorsSummary] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsWithSummaryByTeamId({
|
||||
teamId,
|
||||
types,
|
||||
});
|
||||
const { monitors, summary } = res?.data?.data ?? {};
|
||||
setMonitors(monitors);
|
||||
setMonitorsSummary(summary);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [teamId, types, monitorUpdateTrigger]);
|
||||
return [monitors, monitorsSummary, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useFetchMonitorsWithChecks = ({
|
||||
teamId,
|
||||
types,
|
||||
limit,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
monitorUpdateTrigger,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [count, setCount] = useState(undefined);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const { getMonitorWithPercentage } = useMonitorUtils();
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsWithChecksByTeamId({
|
||||
teamId,
|
||||
limit,
|
||||
types,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
});
|
||||
const { count, monitors } = res?.data?.data ?? {};
|
||||
const mappedMonitors = monitors.map((monitor) =>
|
||||
getMonitorWithPercentage(monitor, theme)
|
||||
);
|
||||
setMonitors(mappedMonitors);
|
||||
setCount(count?.monitorsCount ?? 0);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [
|
||||
field,
|
||||
filter,
|
||||
getMonitorWithPercentage,
|
||||
limit,
|
||||
order,
|
||||
page,
|
||||
rowsPerPage,
|
||||
teamId,
|
||||
theme,
|
||||
types,
|
||||
monitorUpdateTrigger,
|
||||
]);
|
||||
return [monitors, count, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useFetchMonitorsByTeamId = ({
|
||||
teamId,
|
||||
types,
|
||||
limit,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
checkOrder,
|
||||
normalize,
|
||||
status,
|
||||
updateTrigger,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [summary, setSummary] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
teamId,
|
||||
limit,
|
||||
types,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
checkOrder,
|
||||
status,
|
||||
normalize,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [
|
||||
teamId,
|
||||
types,
|
||||
limit,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
updateTrigger,
|
||||
checkOrder,
|
||||
normalize,
|
||||
status,
|
||||
]);
|
||||
return [monitors, summary, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useFetchStatsByMonitorId = ({
|
||||
monitorId,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
numToDisplay,
|
||||
normalize,
|
||||
}) => {
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
const [audits, setAudits] = useState(undefined);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getStatsByMonitorId({
|
||||
monitorId: monitorId,
|
||||
sortOrder,
|
||||
limit,
|
||||
dateRange,
|
||||
numToDisplay,
|
||||
normalize,
|
||||
});
|
||||
setMonitor(res?.data?.data ?? undefined);
|
||||
setAudits(res?.data?.data?.checks?.[0]?.audits ?? undefined);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitor();
|
||||
}, [monitorId, dateRange, numToDisplay, normalize, sortOrder, limit]);
|
||||
return [monitor, audits, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useFetchMonitorById = ({ monitorId, setMonitor, updateTrigger }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorById({ monitorId: monitorId });
|
||||
setMonitor(res.data.data);
|
||||
} catch (error) {
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitor();
|
||||
}, [monitorId, setMonitor, updateTrigger]);
|
||||
return [isLoading];
|
||||
};
|
||||
|
||||
const useFetchHardwareMonitorById = ({ monitorId, dateRange }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
if (!monitorId) {
|
||||
return { monitor: undefined, isLoading: false, networkError: undefined };
|
||||
}
|
||||
const response = await networkService.getHardwareDetailsByMonitorId({
|
||||
monitorId: monitorId,
|
||||
dateRange: dateRange,
|
||||
});
|
||||
setMonitor(response.data.data);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitor();
|
||||
}, [monitorId, dateRange]);
|
||||
return [monitor, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useFetchUptimeMonitorById = ({ monitorId, dateRange, trigger }) => {
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
const [monitorStats, setMonitorStats] = useState(undefined);
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const res = await networkService.getUptimeDetailsById({
|
||||
monitorId: monitorId,
|
||||
dateRange: dateRange,
|
||||
normalize: true,
|
||||
});
|
||||
const { monitorData, monitorStats } = res?.data?.data ?? {};
|
||||
setMonitor(monitorData);
|
||||
setMonitorStats(monitorStats);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [dateRange, monitorId, trigger]);
|
||||
return [monitor, monitorStats, isLoading, networkError];
|
||||
};
|
||||
|
||||
const useCreateMonitor = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const createMonitor = async ({ monitor, redirect }) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await networkService.createMonitor({ monitor });
|
||||
createToast({ body: "Monitor created successfully!" });
|
||||
if (redirect) {
|
||||
navigate(redirect);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({ body: "Failed to create monitor." });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
return [createMonitor, isLoading];
|
||||
};
|
||||
|
||||
const useDeleteMonitor = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const deleteMonitor = async ({ monitor, redirect }) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
await networkService.deleteMonitorById({ monitorId: monitor._id });
|
||||
createToast({ body: "Monitor deleted successfully!" });
|
||||
if (redirect) {
|
||||
navigate(redirect);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({ body: "Failed to delete monitor." });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
return [deleteMonitor, isLoading];
|
||||
};
|
||||
|
||||
const useUpdateMonitor = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
const updateMonitor = async ({ monitor, redirect }) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const updatedFields = {
|
||||
name: monitor.name,
|
||||
description: monitor.description,
|
||||
interval: monitor.interval,
|
||||
notifications: monitor.notifications,
|
||||
matchMethod: monitor.matchMethod,
|
||||
expectedValue: monitor.expectedValue,
|
||||
ignoreTlsErrors: monitor.ignoreTlsErrors,
|
||||
jsonPath: monitor.jsonPath,
|
||||
...(monitor.type === "port" && { port: monitor.port }),
|
||||
...(monitor.type === "hardware" && {
|
||||
thresholds: monitor.thresholds,
|
||||
secret: monitor.secret,
|
||||
}),
|
||||
};
|
||||
await networkService.updateMonitor({
|
||||
monitorId: monitor._id,
|
||||
updatedFields,
|
||||
});
|
||||
|
||||
createToast({ body: "Monitor updated successfully!" });
|
||||
if (redirect) {
|
||||
navigate(redirect);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({ body: "Failed to update monitor." });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
return [updateMonitor, isLoading];
|
||||
};
|
||||
|
||||
const usePauseMonitor = () => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState(undefined);
|
||||
const pauseMonitor = async ({ monitorId, triggerUpdate }) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.pauseMonitorById({ monitorId });
|
||||
createToast({
|
||||
body: res.data.data.isActive
|
||||
? "Monitor resumed successfully"
|
||||
: "Monitor paused successfully",
|
||||
});
|
||||
triggerUpdate();
|
||||
} catch (error) {
|
||||
setError(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return [pauseMonitor, isLoading, error];
|
||||
};
|
||||
|
||||
export {
|
||||
useFetchMonitorsWithSummary,
|
||||
useFetchMonitorsWithChecks,
|
||||
useFetchMonitorsByTeamId,
|
||||
useFetchStatsByMonitorId,
|
||||
useFetchMonitorById,
|
||||
useFetchUptimeMonitorById,
|
||||
useFetchHardwareMonitorById,
|
||||
useCreateMonitor,
|
||||
useDeleteMonitor,
|
||||
useUpdateMonitor,
|
||||
usePauseMonitor,
|
||||
};
|
||||
@@ -1,72 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorUtils } from "./useMonitorUtils";
|
||||
|
||||
export const useFetchMonitorsWithChecks = ({
|
||||
teamId,
|
||||
types,
|
||||
limit,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
monitorUpdateTrigger,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [count, setCount] = useState(undefined);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const { getMonitorWithPercentage } = useMonitorUtils();
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsWithChecksByTeamId({
|
||||
teamId,
|
||||
limit,
|
||||
types,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
});
|
||||
const { count, monitors } = res?.data?.data ?? {};
|
||||
const mappedMonitors = monitors.map((monitor) =>
|
||||
getMonitorWithPercentage(monitor, theme)
|
||||
);
|
||||
setMonitors(mappedMonitors);
|
||||
setCount(count?.monitorsCount ?? 0);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [
|
||||
field,
|
||||
filter,
|
||||
getMonitorWithPercentage,
|
||||
limit,
|
||||
order,
|
||||
page,
|
||||
rowsPerPage,
|
||||
teamId,
|
||||
theme,
|
||||
types,
|
||||
monitorUpdateTrigger,
|
||||
]);
|
||||
return [monitors, count, isLoading, networkError];
|
||||
};
|
||||
|
||||
export default useFetchMonitorsWithChecks;
|
||||
@@ -1,37 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
|
||||
export const useFetchMonitorsWithSummary = ({ teamId, types, monitorUpdateTrigger }) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [monitorsSummary, setMonitorsSummary] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsWithSummaryByTeamId({
|
||||
teamId,
|
||||
types,
|
||||
});
|
||||
const { monitors, summary } = res?.data?.data ?? {};
|
||||
setMonitors(monitors);
|
||||
setMonitorsSummary(summary);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [teamId, types, monitorUpdateTrigger]);
|
||||
return [monitors, monitorsSummary, isLoading, networkError];
|
||||
};
|
||||
|
||||
export default useFetchMonitorsWithSummary;
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { getUptimeMonitorById } from "../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const useFetchUptimeMonitorById = (monitorId, updateTrigger) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
const [monitor, setMonitor] = useState(null);
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const action = await dispatch(getUptimeMonitorById({ monitorId }));
|
||||
|
||||
if (getUptimeMonitorById.fulfilled.match(action)) {
|
||||
const monitor = action.payload.data;
|
||||
setMonitor(monitor);
|
||||
} else if (getUptimeMonitorById.rejected.match(action)) {
|
||||
throw new Error(action.error.message);
|
||||
}
|
||||
} catch (error) {
|
||||
navigate("/not-found", { replace: true });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitor();
|
||||
}, [monitorId, dispatch, navigate, updateTrigger]);
|
||||
return [monitor, isLoading, error];
|
||||
};
|
||||
|
||||
export { useFetchUptimeMonitorById };
|
||||
@@ -1,35 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
|
||||
export const useFetchUptimeMonitorDetails = ({ monitorId, dateRange, trigger }) => {
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
const [monitorStats, setMonitorStats] = useState(undefined);
|
||||
const navigate = useNavigate();
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const res = await networkService.getUptimeDetailsById({
|
||||
monitorId: monitorId,
|
||||
dateRange: dateRange,
|
||||
normalize: true,
|
||||
});
|
||||
const { monitorData, monitorStats } = res?.data?.data ?? {};
|
||||
setMonitor(monitorData);
|
||||
setMonitorStats(monitorStats);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [dateRange, monitorId, navigate, trigger]);
|
||||
return [monitor, monitorStats, isLoading, networkError];
|
||||
};
|
||||
|
||||
export default useFetchUptimeMonitorDetails;
|
||||
@@ -1,28 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import { networkService } from "../main";
|
||||
import { createToast } from "../Utils/toastUtils";
|
||||
|
||||
const usePauseMonitor = ({ monitorId, triggerUpdate }) => {
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState(undefined);
|
||||
const pauseMonitor = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.pauseMonitorById({ monitorId });
|
||||
createToast({
|
||||
body: res.data.data.isActive
|
||||
? "Monitor resumed successfully"
|
||||
: "Monitor paused successfully",
|
||||
});
|
||||
triggerUpdate();
|
||||
} catch (error) {
|
||||
setError(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return [pauseMonitor, isLoading, error];
|
||||
};
|
||||
|
||||
export { usePauseMonitor };
|
||||
@@ -46,7 +46,27 @@ const useMonitorUtils = () => {
|
||||
pending: theme.palette.warning.lowContrast,
|
||||
};
|
||||
|
||||
return { getMonitorWithPercentage, determineState, statusColor };
|
||||
const statusToTheme = {
|
||||
up: "success",
|
||||
down: "error",
|
||||
paused: "warning",
|
||||
pending: "secondary",
|
||||
"cannot resolve": "tertiary",
|
||||
};
|
||||
|
||||
const pagespeedStatusMsg = {
|
||||
up: "Live (collecting data)",
|
||||
down: "Inactive",
|
||||
paused: "Paused",
|
||||
};
|
||||
|
||||
return {
|
||||
getMonitorWithPercentage,
|
||||
determineState,
|
||||
statusColor,
|
||||
statusToTheme,
|
||||
pagespeedStatusMsg,
|
||||
};
|
||||
};
|
||||
|
||||
export { useMonitorUtils };
|
||||
|
||||
@@ -10,10 +10,10 @@ import NetworkError from "../../../../Components/GenericFallback/NetworkError";
|
||||
//Utils
|
||||
import { formatDateWithTz } from "../../../../Utils/timeUtils";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useState } from "react";
|
||||
import useChecksFetch from "../../Hooks/useChecksFetch";
|
||||
import { useState, useEffect } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFetchChecks } from "../../../../Hooks/checkHooks";
|
||||
|
||||
const IncidentTable = ({
|
||||
shouldRender,
|
||||
@@ -24,19 +24,28 @@ const IncidentTable = ({
|
||||
}) => {
|
||||
//Redux state
|
||||
const uiTimezone = useSelector((state) => state.ui.timezone);
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
|
||||
//Local state
|
||||
const [teamId, setTeamId] = useState(undefined);
|
||||
const [monitorId, setMonitorId] = useState(undefined);
|
||||
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const selectedMonitorDetails = monitors?.[selectedMonitor];
|
||||
const selectedMonitorType = selectedMonitorDetails?.type;
|
||||
const { isLoading, networkError, checks, checksCount } = useChecksFetch({
|
||||
selectedMonitor,
|
||||
selectedMonitorType,
|
||||
filter,
|
||||
|
||||
const [checks, checksCount, isLoading, networkError] = useFetchChecks({
|
||||
status: false,
|
||||
monitorId,
|
||||
teamId,
|
||||
type: selectedMonitorType,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter: filter,
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
|
||||
const { t } = useTranslation();
|
||||
@@ -50,6 +59,16 @@ const IncidentTable = ({
|
||||
setRowsPerPage(event.target.value);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedMonitor === "0") {
|
||||
setTeamId(user.teamId);
|
||||
setMonitorId(undefined);
|
||||
} else {
|
||||
setMonitorId(selectedMonitor);
|
||||
setTeamId(undefined);
|
||||
}
|
||||
}, [selectedMonitor, user.teamId]);
|
||||
|
||||
const headers = [
|
||||
{
|
||||
id: "monitorName",
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { networkService } from "../../../main";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useSelector } from "react-redux";
|
||||
const useChecksFetch = ({
|
||||
selectedMonitor,
|
||||
selectedMonitorType,
|
||||
filter,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
}) => {
|
||||
//Redux
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
|
||||
//Local
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [checks, setChecks] = useState(undefined);
|
||||
const [checksCount, setChecksCount] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchChecks = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
let res;
|
||||
|
||||
if (selectedMonitor === "0") {
|
||||
res = await networkService.getChecksByTeam({
|
||||
status: false,
|
||||
teamId: user.teamId,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange,
|
||||
filter: filter,
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
} else {
|
||||
res = await networkService.getChecksByMonitor({
|
||||
status: false,
|
||||
monitorId: selectedMonitor,
|
||||
type: selectedMonitorType,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange,
|
||||
filter: filter,
|
||||
page,
|
||||
rowsPerPage,
|
||||
});
|
||||
}
|
||||
setChecks(res.data.data.checks);
|
||||
setChecksCount(res.data.data.checksCount);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchChecks();
|
||||
}, [user, dateRange, page, rowsPerPage, filter, selectedMonitor, selectedMonitorType]);
|
||||
return { isLoading, networkError, checks, checksCount };
|
||||
};
|
||||
|
||||
export default useChecksFetch;
|
||||
@@ -1,54 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { networkService } from "../../../main";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
const useMonitorsFetch = ({ teamId }) => {
|
||||
//Local state
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
teamId,
|
||||
limit: null,
|
||||
types: null,
|
||||
status: null,
|
||||
checkOrder: null,
|
||||
normalize: null,
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors?.length > 0) {
|
||||
const monitorLookup = res.data.data.filteredMonitors.reduce((acc, monitor) => {
|
||||
acc[monitor._id] = {
|
||||
_id: monitor._id,
|
||||
name: monitor.name,
|
||||
type: monitor.type,
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
setMonitors(monitorLookup);
|
||||
}
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [teamId]);
|
||||
return { isLoading, monitors, networkError };
|
||||
};
|
||||
|
||||
export { useMonitorsFetch };
|
||||
@@ -1,19 +1,19 @@
|
||||
// Components
|
||||
import { Stack } from "@mui/material";
|
||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||
import GenericFallback from "../../Components/GenericFallback";
|
||||
import IncidentTable from "./Components/IncidentTable";
|
||||
import OptionsHeader from "./Components/OptionsHeader";
|
||||
|
||||
//Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorsFetch } from "./Hooks/useMonitorsFetch";
|
||||
import { useFetchMonitorsByTeamId } from "../../Hooks/monitorHooks";
|
||||
import { useSelector } from "react-redux";
|
||||
import OptionsHeader from "./Components/OptionsHeader";
|
||||
import { useState } from "react";
|
||||
import IncidentTable from "./Components/IncidentTable";
|
||||
import GenericFallback from "../../Components/GenericFallback";
|
||||
import { useState, useEffect } from "react";
|
||||
import NetworkError from "../../Components/GenericFallback/NetworkError";
|
||||
import { useTranslation } from "react-i18next";
|
||||
//Constants
|
||||
|
||||
//Constants
|
||||
const Incidents = () => {
|
||||
// Redux state
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
@@ -27,13 +27,26 @@ const Incidents = () => {
|
||||
const [selectedMonitor, setSelectedMonitor] = useState("0");
|
||||
const [filter, setFilter] = useState(undefined);
|
||||
const [dateRange, setDateRange] = useState(undefined);
|
||||
const [monitorLookup, setMonitorLookup] = useState(undefined);
|
||||
|
||||
//Utils
|
||||
const theme = useTheme();
|
||||
|
||||
const { monitors, isLoading, networkError } = useMonitorsFetch({
|
||||
const [monitors, , isLoading, networkError] = useFetchMonitorsByTeamId({
|
||||
teamId: user.teamId,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const monitorLookup = monitors?.reduce((acc, monitor) => {
|
||||
acc[monitor._id] = {
|
||||
_id: monitor._id,
|
||||
name: monitor.name,
|
||||
type: monitor.type,
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
setMonitorLookup(monitorLookup);
|
||||
}, [monitors]);
|
||||
|
||||
if (networkError) {
|
||||
return (
|
||||
<GenericFallback>
|
||||
@@ -47,7 +60,7 @@ const Incidents = () => {
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<OptionsHeader
|
||||
shouldRender={!isLoading}
|
||||
monitors={monitors}
|
||||
monitors={monitorLookup}
|
||||
selectedMonitor={selectedMonitor}
|
||||
setSelectedMonitor={setSelectedMonitor}
|
||||
filter={filter}
|
||||
@@ -57,7 +70,7 @@ const Incidents = () => {
|
||||
/>
|
||||
<IncidentTable
|
||||
shouldRender={!isLoading}
|
||||
monitors={monitors}
|
||||
monitors={monitorLookup ? monitorLookup : {}}
|
||||
selectedMonitor={selectedMonitor}
|
||||
filter={filter}
|
||||
dateRange={dateRange}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
// React, Redux, Router
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
// Utility and Network
|
||||
import { infrastructureMonitorValidation } from "../../../Validation/validation";
|
||||
import {
|
||||
createInfrastructureMonitor,
|
||||
updateInfrastructureMonitor,
|
||||
} from "../../../Features/InfrastructureMonitors/infrastructureMonitorsSlice";
|
||||
import { useHardwareMonitorsFetch } from "../Details/Hooks/useHardwareMonitorsFetch";
|
||||
import { useFetchHardwareMonitorById } from "../../../Hooks/monitorHooks";
|
||||
import { capitalizeFirstLetter } from "../../../Utils/stringUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||
import { useUpdateMonitor, useCreateMonitor } from "../../../Hooks/monitorHooks";
|
||||
|
||||
// MUI
|
||||
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
|
||||
@@ -55,9 +52,6 @@ const getAlertError = (errors) => {
|
||||
const CreateInfrastructureMonitor = () => {
|
||||
const theme = useTheme();
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const monitorState = useSelector((state) => state.infrastructureMonitor);
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const { monitorId } = useParams();
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -65,9 +59,11 @@ const CreateInfrastructureMonitor = () => {
|
||||
const isCreate = typeof monitorId === "undefined";
|
||||
|
||||
// Fetch monitor details if editing
|
||||
const { monitor, isLoading, networkError } = useHardwareMonitorsFetch({ monitorId });
|
||||
const [monitor, isLoading, networkError] = useFetchHardwareMonitorById({ monitorId });
|
||||
const [notifications, notificationsAreLoading, notificationsError] =
|
||||
useGetNotificationsByTeamId();
|
||||
const [updateMonitor, isUpdating] = useUpdateMonitor();
|
||||
const [createMonitor, isCreating] = useCreateMonitor();
|
||||
|
||||
// State
|
||||
const [errors, setErrors] = useState({});
|
||||
@@ -187,6 +183,7 @@ const CreateInfrastructureMonitor = () => {
|
||||
};
|
||||
|
||||
form = {
|
||||
...(isCreate ? {} : { _id: monitorId }),
|
||||
...rest,
|
||||
description: form.name,
|
||||
teamId: user.teamId,
|
||||
@@ -197,19 +194,9 @@ const CreateInfrastructureMonitor = () => {
|
||||
};
|
||||
|
||||
// Handle create or update
|
||||
const action = isCreate
|
||||
? await dispatch(createInfrastructureMonitor({ monitor: form }))
|
||||
: await dispatch(updateInfrastructureMonitor({ monitorId, monitor: form }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
createToast({
|
||||
body: isCreate
|
||||
? t("infrastructureMonitorCreated")
|
||||
: t("infrastructureMonitorUpdated"),
|
||||
});
|
||||
navigate("/infrastructure");
|
||||
} else {
|
||||
createToast({ body: "Failed to save monitor." });
|
||||
}
|
||||
isCreate
|
||||
? await createMonitor({ monitor: form, redirect: "/infrastructure" })
|
||||
: await updateMonitor({ monitor: form, redirect: "/infrastructure" });
|
||||
};
|
||||
|
||||
const onChange = (event) => {
|
||||
@@ -448,7 +435,7 @@ const CreateInfrastructureMonitor = () => {
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="accent"
|
||||
loading={monitorState?.isLoading}
|
||||
loading={isLoading || isUpdating || isCreating || notificationsAreLoading}
|
||||
>
|
||||
{t(isCreate ? "infrastructureCreateMonitor" : "infrastructureEditMonitor")}
|
||||
</Button>
|
||||
|
||||
@@ -4,14 +4,14 @@ import StatusBoxes from "../../../../../Components/StatusBoxes";
|
||||
import StatBox from "../../../../../Components/StatBox";
|
||||
|
||||
//Utils
|
||||
import useUtils from "../../../../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
import { useHardwareUtils } from "../../Hooks/useHardwareUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const InfraStatBoxes = ({ shouldRender, monitor }) => {
|
||||
// Utils
|
||||
const { formatBytes } = useHardwareUtils();
|
||||
const { determineState } = useUtils();
|
||||
const { determineState } = useMonitorUtils();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { stats } = monitor ?? {};
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
|
||||
const useHardwareMonitorsFetch = ({ monitorId, dateRange }) => {
|
||||
// Abort early if creating monitor
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
if (!monitorId) {
|
||||
return { monitor: undefined, isLoading: false, networkError: undefined };
|
||||
}
|
||||
const response = await networkService.getHardwareDetailsByMonitorId({
|
||||
monitorId: monitorId,
|
||||
dateRange: dateRange,
|
||||
});
|
||||
setMonitor(response.data.data);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, [monitorId, dateRange]);
|
||||
|
||||
return {
|
||||
isLoading,
|
||||
networkError,
|
||||
monitor,
|
||||
};
|
||||
};
|
||||
|
||||
export { useHardwareMonitorsFetch };
|
||||
@@ -11,7 +11,7 @@ import GenericFallback from "../../../Components/GenericFallback";
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import { useHardwareMonitorsFetch } from "./Hooks/useHardwareMonitorsFetch";
|
||||
import { useFetchHardwareMonitorById } from "../../../Hooks/monitorHooks";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useParams } from "react-router-dom";
|
||||
@@ -33,7 +33,7 @@ const InfrastructureDetails = () => {
|
||||
const { t } = useTranslation();
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
const { isLoading, networkError, monitor } = useHardwareMonitorsFetch({
|
||||
const [monitor, isLoading, networkError] = useFetchHardwareMonitorById({
|
||||
monitorId,
|
||||
dateRange,
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import CustomGauge from "../../../../../Components/Charts/CustomGauge";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -19,7 +19,7 @@ const MonitorsTable = ({ shouldRender, monitors, isAdmin, handleActionMenuDelete
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { determineState } = useUtils();
|
||||
const { determineState } = useMonitorUtils();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Handlers
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
const useMonitorFetch = ({ page, field, filter, rowsPerPage, updateTrigger }) => {
|
||||
// Redux state
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
|
||||
// Local state
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [summary, setSummary] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const response = await networkService.getMonitorsByTeamId({
|
||||
teamId: user.teamId,
|
||||
limit: 1,
|
||||
field: field,
|
||||
filter: filter,
|
||||
types: ["hardware"],
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
setMonitors(response?.data?.data?.filteredMonitors ?? []);
|
||||
setSummary(response?.data?.data?.summary ?? {});
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [page, field, filter, rowsPerPage, user.teamId, updateTrigger]);
|
||||
|
||||
return { monitors, summary, isLoading, networkError };
|
||||
};
|
||||
|
||||
export { useMonitorFetch };
|
||||
@@ -10,15 +10,20 @@ import Fallback from "../../../Components/Fallback";
|
||||
import Filter from "./Components/Filters";
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorFetch } from "./Hooks/useMonitorFetch";
|
||||
import { useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks";
|
||||
// Constants
|
||||
const TYPES = ["hardware"];
|
||||
const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }];
|
||||
|
||||
const InfrastructureMonitors = () => {
|
||||
// Redux state
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
|
||||
// Local state
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||
@@ -50,7 +55,10 @@ const InfrastructureMonitors = () => {
|
||||
|
||||
const field = toFilterStatus !== undefined ? "status" : undefined;
|
||||
|
||||
const { monitors, summary, isLoading, networkError } = useMonitorFetch({
|
||||
const [monitors, summary, isLoading, networkError] = useFetchMonitorsByTeamId({
|
||||
teamId: user.teamId,
|
||||
limit: 1,
|
||||
types: TYPES,
|
||||
page,
|
||||
field: field,
|
||||
filter: toFilterStatus,
|
||||
|
||||
@@ -12,45 +12,43 @@ import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||
import Dialog from "../../../Components/Dialog";
|
||||
|
||||
// Utils
|
||||
import { useEffect, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import {
|
||||
deletePageSpeed,
|
||||
getPagespeedMonitorById,
|
||||
getPageSpeedByTeamId,
|
||||
updatePageSpeed,
|
||||
pausePageSpeed,
|
||||
} from "../../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
|
||||
import { useParams } from "react-router";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../Hooks/useMonitorUtils";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
|
||||
import {
|
||||
useFetchMonitorById,
|
||||
useDeleteMonitor,
|
||||
useUpdateMonitor,
|
||||
usePauseMonitor,
|
||||
} from "../../../Hooks/monitorHooks";
|
||||
const PageSpeedConfigure = () => {
|
||||
// Redux state
|
||||
const { isLoading } = useSelector((state) => state.pageSpeedMonitors);
|
||||
|
||||
// Local state
|
||||
const [monitor, setMonitor] = useState({});
|
||||
const [errors, setErrors] = useState({});
|
||||
const [buttonLoading, setButtonLoading] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const dispatch = useDispatch();
|
||||
const MS_PER_MINUTE = 60000;
|
||||
const { monitorId } = useParams();
|
||||
const { statusColor, pagespeedStatusMsg, determineState } = useUtils();
|
||||
const { statusColor, pagespeedStatusMsg, determineState } = useMonitorUtils();
|
||||
|
||||
const [notifications, notificationsAreLoading, notificationsError] =
|
||||
useGetNotificationsByTeamId();
|
||||
|
||||
const [isLoading] = useFetchMonitorById({ monitorId, setMonitor, updateTrigger });
|
||||
const [deleteMonitor, isDeleting] = useDeleteMonitor();
|
||||
const [updateMonitor, isUpdating] = useUpdateMonitor();
|
||||
const [pauseMonitor, isPausing] = usePauseMonitor();
|
||||
|
||||
const frequencies = [
|
||||
{ _id: 3, name: "3 minutes" },
|
||||
{ _id: 5, name: "5 minutes" },
|
||||
@@ -61,24 +59,10 @@ const PageSpeedConfigure = () => {
|
||||
{ _id: 10080, name: "1 week" },
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
const action = await dispatch(getPagespeedMonitorById({ monitorId }));
|
||||
|
||||
if (getPagespeedMonitorById.fulfilled.match(action)) {
|
||||
const monitor = action.payload.data;
|
||||
setMonitor(monitor);
|
||||
} else if (getPagespeedMonitorById.rejected.match(action)) {
|
||||
throw new Error(action.error.message);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("Error fetching monitor of id: " + monitorId);
|
||||
navigate("/not-found", { replace: true });
|
||||
}
|
||||
};
|
||||
fetchMonitor();
|
||||
}, [dispatch, monitorId, navigate]);
|
||||
// Handlers
|
||||
const triggerUpdate = () => {
|
||||
setUpdateTrigger(!updateTrigger);
|
||||
};
|
||||
|
||||
const onChange = (event) => {
|
||||
let { value, name } = event.target;
|
||||
@@ -106,42 +90,17 @@ const PageSpeedConfigure = () => {
|
||||
};
|
||||
|
||||
const handlePause = async () => {
|
||||
try {
|
||||
const action = await dispatch(pausePageSpeed({ monitorId }));
|
||||
if (pausePageSpeed.fulfilled.match(action)) {
|
||||
const monitor = action.payload.data;
|
||||
setMonitor(monitor);
|
||||
const state = action?.payload?.data.isActive === false ? "paused" : "resumed";
|
||||
createToast({ body: `Monitor ${state} successfully.` });
|
||||
} else if (pausePageSpeed.rejected.match(action)) {
|
||||
throw new Error(action.error.message);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({ body: "Failed to pause monitor" });
|
||||
}
|
||||
await pauseMonitor({ monitorId, triggerUpdate });
|
||||
};
|
||||
|
||||
const onSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
const action = await dispatch(updatePageSpeed({ monitor: monitor }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
createToast({ body: "Monitor updated successfully!" });
|
||||
dispatch(getPageSpeedByTeamId());
|
||||
} else {
|
||||
createToast({ body: "Failed to update monitor." });
|
||||
}
|
||||
await updateMonitor({ monitor, redirect: "/pagespeed" });
|
||||
};
|
||||
|
||||
const handleRemove = async (event) => {
|
||||
event.preventDefault();
|
||||
setButtonLoading(true);
|
||||
const action = await dispatch(deletePageSpeed({ monitor }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
navigate("/pagespeed");
|
||||
} else {
|
||||
createToast({ body: "Failed to delete monitor." });
|
||||
}
|
||||
setButtonLoading(false);
|
||||
await deleteMonitor({ monitor, redirect: "/pagespeed" });
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -363,7 +322,7 @@ const PageSpeedConfigure = () => {
|
||||
mt="auto"
|
||||
>
|
||||
<Button
|
||||
loading={isLoading}
|
||||
loading={isLoading || isDeleting || isUpdating || isPausing}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="accent"
|
||||
@@ -383,7 +342,7 @@ const PageSpeedConfigure = () => {
|
||||
onCancel={() => setIsOpen(false)}
|
||||
confirmationButtonLabel={t("delete")}
|
||||
onConfirm={handleRemove}
|
||||
isLoading={buttonLoading}
|
||||
isLoading={isLoading || isDeleting || isUpdating || isPausing}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
// React, Redux, Router
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
// Utility and Network
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import {
|
||||
createPageSpeed,
|
||||
checkEndpointResolution,
|
||||
} from "../../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
|
||||
import { parseDomainName } from "../../../Utils/monitorUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
|
||||
// MUI
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
|
||||
|
||||
//Components
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import ButtonGroup from "@mui/material/ButtonGroup";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import TextInput from "../../../Components/Inputs/TextInput";
|
||||
import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
||||
import ConfigBox from "../../../Components/ConfigBox";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import Radio from "../../../Components/Inputs/Radio";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||
|
||||
// Utils
|
||||
import { useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { parseDomainName } from "../../../Utils/monitorUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useCreateMonitor } from "../../../Hooks/monitorHooks";
|
||||
|
||||
const MS_PER_MINUTE = 60000;
|
||||
|
||||
const CRUMBS = [
|
||||
@@ -56,13 +53,11 @@ const CreatePageSpeed = () => {
|
||||
const [https, setHttps] = useState(true);
|
||||
const [errors, setErrors] = useState({});
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const { isLoading } = useSelector((state) => state.pageSpeedMonitors);
|
||||
const [notifications, notificationsAreLoading, error] = useGetNotificationsByTeamId();
|
||||
|
||||
// Setup
|
||||
const dispatch = useDispatch();
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
const [createMonitor, isCreating] = useCreateMonitor();
|
||||
|
||||
// Handlers
|
||||
const onSubmit = async (event) => {
|
||||
@@ -88,18 +83,6 @@ const CreatePageSpeed = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const checkEndpointAction = await dispatch(
|
||||
checkEndpointResolution({ monitorURL: form.url })
|
||||
);
|
||||
|
||||
if (checkEndpointAction.meta.requestStatus === "rejected") {
|
||||
createToast({
|
||||
body: "The endpoint you entered doesn't resolve. Check the URL again.",
|
||||
});
|
||||
setErrors({ url: "The entered URL is not reachable." });
|
||||
return;
|
||||
}
|
||||
|
||||
form = {
|
||||
...form,
|
||||
description: form.name,
|
||||
@@ -108,13 +91,7 @@ const CreatePageSpeed = () => {
|
||||
notifications: monitor.notifications,
|
||||
};
|
||||
|
||||
const action = await dispatch(createPageSpeed({ monitor: form }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
createToast({ body: "Monitor created successfully!" });
|
||||
navigate("/pagespeed");
|
||||
} else {
|
||||
createToast({ body: "Failed to create monitor." });
|
||||
}
|
||||
await createMonitor({ monitor: form, redirect: "/pagespeed" });
|
||||
};
|
||||
|
||||
const handleChange = (event) => {
|
||||
@@ -325,7 +302,7 @@ const CreatePageSpeed = () => {
|
||||
variant="contained"
|
||||
color="accent"
|
||||
disabled={!Object.values(errors).every((value) => value === undefined)}
|
||||
loading={isLoading}
|
||||
loading={isCreating}
|
||||
>
|
||||
{t("createMonitor")}
|
||||
</Button>
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
const useMonitorFetch = ({ monitorId }) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
const [audits, setAudits] = useState(undefined);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
try {
|
||||
const res = await networkService.getStatsByMonitorId({
|
||||
monitorId: monitorId,
|
||||
sortOrder: "desc",
|
||||
limit: 50,
|
||||
dateRange: "day",
|
||||
numToDisplay: null,
|
||||
normalize: null,
|
||||
});
|
||||
setMonitor(res?.data?.data ?? undefined);
|
||||
setAudits(res?.data?.data?.checks?.[0]?.audits ?? undefined);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitor();
|
||||
}, [monitorId, navigate]);
|
||||
|
||||
return { monitor, audits, isLoading };
|
||||
};
|
||||
|
||||
export { useMonitorFetch };
|
||||
@@ -11,8 +11,7 @@ import GenericFallback from "../../../Components/GenericFallback";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useMonitorFetch } from "./Hooks/useMonitorFetch";
|
||||
import { useFetchStatsByMonitorId } from "../../../Hooks/monitorHooks";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
// Constants
|
||||
@@ -28,8 +27,13 @@ const PageSpeedDetails = () => {
|
||||
const isAdmin = useIsAdmin();
|
||||
const { monitorId } = useParams();
|
||||
|
||||
const { monitor, audits, isLoading, networkError } = useMonitorFetch({
|
||||
const [monitor, audits, isLoading, networkError] = useFetchStatsByMonitorId({
|
||||
monitorId,
|
||||
sortOrder: "desc",
|
||||
limit: 50,
|
||||
dateRange: "day",
|
||||
numToDisplay: null,
|
||||
normalize: null,
|
||||
});
|
||||
|
||||
const [metrics, setMetrics] = useState({
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useTheme } from "@emotion/react";
|
||||
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDateWithTz, formatDurationSplit } from "../../../../../Utils/timeUtils";
|
||||
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import IconBox from "../../../../../Components/IconBox";
|
||||
@@ -118,7 +118,7 @@ const processData = (data) => {
|
||||
const PagespeedAreaChart = ({ data, status }) => {
|
||||
const theme = useTheme();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const { statusToTheme } = useUtils();
|
||||
const { statusToTheme } = useMonitorUtils();
|
||||
|
||||
const themeColor = statusToTheme[status];
|
||||
|
||||
@@ -206,7 +206,7 @@ PagespeedAreaChart.propTypes = {
|
||||
* @returns {JSX.Element} - The rendered card.
|
||||
*/
|
||||
const Card = ({ monitor }) => {
|
||||
const { determineState, pagespeedStatusMsg } = useUtils();
|
||||
const { determineState, pagespeedStatusMsg } = useMonitorUtils();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
@@ -275,7 +275,7 @@ const Card = ({ monitor }) => {
|
||||
sx={{ gridColumnStart: 1, gridColumnEnd: 4 }}
|
||||
>
|
||||
<PagespeedAreaChart
|
||||
data={monitor.checks.slice().reverse()}
|
||||
data={monitor?.checks?.slice().reverse()}
|
||||
status={monitorState}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
const useMonitorsFetch = ({ teamId }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
teamId: teamId,
|
||||
limit: 10,
|
||||
types: ["pagespeed"],
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [teamId]);
|
||||
return { isLoading, monitors, summary, networkError };
|
||||
};
|
||||
|
||||
export default useMonitorsFetch;
|
||||
@@ -5,17 +5,17 @@ import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||
import MonitorGrid from "./Components/MonitorGrid";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
import GenericFallback from "../../../Components/GenericFallback";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import useMonitorsFetch from "./Hooks/useMonitorsFetch";
|
||||
import GenericFallback from "../../../Components/GenericFallback";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useFetchMonitorsByTeamId } from "../../../Hooks/monitorHooks";
|
||||
// Constants
|
||||
const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
|
||||
|
||||
const TYPES = ["pagespeed"];
|
||||
const PageSpeed = () => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
@@ -23,8 +23,15 @@ const PageSpeed = () => {
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const { pagespeedApiKey } = useSelector((state) => state.settings);
|
||||
|
||||
const { isLoading, monitors, summary, networkError } = useMonitorsFetch({
|
||||
const [monitors, monitorsSummary, isLoading, networkError] = useFetchMonitorsByTeamId({
|
||||
teamId: user.teamId,
|
||||
limit: 10,
|
||||
types: TYPES,
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
|
||||
if (networkError === true) {
|
||||
@@ -68,7 +75,7 @@ const PageSpeed = () => {
|
||||
/>
|
||||
<MonitorCountHeader
|
||||
shouldRender={!isLoading}
|
||||
monitorCount={summary?.totalMonitors}
|
||||
monitorCount={monitorsSummary?.totalMonitors}
|
||||
sx={{ mb: theme.spacing(8) }}
|
||||
/>
|
||||
<MonitorGrid
|
||||
|
||||
@@ -6,14 +6,14 @@ import { StatusLabel } from "../../../../../Components/Label";
|
||||
|
||||
//Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const MonitorsList = ({ isLoading = false, shouldRender = true, monitors = [] }) => {
|
||||
const theme = useTheme();
|
||||
const { determineState } = useUtils();
|
||||
const { determineState } = useMonitorUtils();
|
||||
|
||||
const { showURL } = useSelector((state) => state.ui);
|
||||
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Box,
|
||||
Stack,
|
||||
Tooltip,
|
||||
Typography,
|
||||
Button,
|
||||
FormControlLabel,
|
||||
Switch,
|
||||
} from "@mui/material";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
// Components
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import ConfigBox from "../../../Components/ConfigBox";
|
||||
import {
|
||||
updateUptimeMonitor,
|
||||
deleteUptimeMonitor,
|
||||
} from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import TextInput from "../../../Components/Inputs/TextInput";
|
||||
import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import "./index.css";
|
||||
import Dialog from "../../../Components/Dialog";
|
||||
import { usePauseMonitor } from "../../../Hooks/useMonitorControls";
|
||||
import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
||||
|
||||
// Utils
|
||||
import { useParams } from "react-router";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useState } from "react";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import PauseOutlinedIcon from "@mui/icons-material/PauseOutlined";
|
||||
import PlayArrowOutlinedIcon from "@mui/icons-material/PlayArrowOutlined";
|
||||
import { useMonitorUtils } from "../../../Hooks/useMonitorUtils";
|
||||
import { useFetchUptimeMonitorById } from "../../../Hooks/useFetchUptimeMonitorById";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
import {
|
||||
useDeleteMonitor,
|
||||
useUpdateMonitor,
|
||||
usePauseMonitor,
|
||||
useFetchMonitorById,
|
||||
} from "../../../Hooks/monitorHooks";
|
||||
import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||
|
||||
/**
|
||||
@@ -76,18 +76,19 @@ const Configure = () => {
|
||||
};
|
||||
|
||||
// Network
|
||||
const [monitor, isLoading, error] = useFetchUptimeMonitorById(monitorId, updateTrigger);
|
||||
const [notifications, notificationsAreLoading, notificationsError] =
|
||||
useGetNotificationsByTeamId();
|
||||
const [pauseMonitor, isPausing, pauseError] = usePauseMonitor({
|
||||
monitorId: monitor?._id,
|
||||
triggerUpdate,
|
||||
const [pauseMonitor, isPausing, pauseError] = usePauseMonitor({});
|
||||
const [deleteMonitor, isDeleting] = useDeleteMonitor();
|
||||
const [updateMonitor, isUpdating] = useUpdateMonitor();
|
||||
const [isLoading] = useFetchMonitorById({
|
||||
monitorId,
|
||||
setMonitor: setForm,
|
||||
updateTrigger,
|
||||
});
|
||||
|
||||
const MS_PER_MINUTE = 60000;
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const matchMethodOptions = [
|
||||
{ _id: "equal", name: "Equal" },
|
||||
@@ -111,7 +112,7 @@ const Configure = () => {
|
||||
|
||||
// Handlers
|
||||
const handlePause = async () => {
|
||||
const res = await pauseMonitor();
|
||||
const res = await pauseMonitor({ monitorId: form?._id, triggerUpdate });
|
||||
if (typeof res !== "undefined") {
|
||||
triggerUpdate();
|
||||
}
|
||||
@@ -119,12 +120,7 @@ const Configure = () => {
|
||||
|
||||
const handleRemove = async (event) => {
|
||||
event.preventDefault();
|
||||
const action = await dispatch(deleteUptimeMonitor({ monitor }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
navigate("/uptime");
|
||||
} else {
|
||||
createToast({ body: "Failed to delete monitor." });
|
||||
}
|
||||
await deleteMonitor({ monitor: form, redirect: "/uptime" });
|
||||
};
|
||||
|
||||
const onChange = (event) => {
|
||||
@@ -134,6 +130,17 @@ const Configure = () => {
|
||||
value = checked;
|
||||
}
|
||||
|
||||
if (name === "useAdvancedMatching") {
|
||||
setForm((prevForm) => {
|
||||
return {
|
||||
...prevForm,
|
||||
matchMethod: "equal",
|
||||
};
|
||||
});
|
||||
setUseAdvancedMatching(!useAdvancedMatching);
|
||||
return;
|
||||
}
|
||||
|
||||
if (name === "interval") {
|
||||
value = value * MS_PER_MINUTE;
|
||||
}
|
||||
@@ -146,7 +153,6 @@ const Configure = () => {
|
||||
|
||||
setErrors((prev) => {
|
||||
const updatedErrors = { ...prev };
|
||||
|
||||
if (validation.error) updatedErrors[name] = validation.error.details[0].message;
|
||||
else delete updatedErrors[name];
|
||||
return updatedErrors;
|
||||
@@ -183,7 +189,7 @@ const Configure = () => {
|
||||
|
||||
if (validation.error) {
|
||||
const newErrors = {};
|
||||
error.details.forEach((err) => {
|
||||
validation.error.details.forEach((err) => {
|
||||
newErrors[err.path[0]] = err.message;
|
||||
});
|
||||
setErrors(newErrors);
|
||||
@@ -192,27 +198,12 @@ const Configure = () => {
|
||||
}
|
||||
|
||||
toSubmit.notifications = form.notifications;
|
||||
const action = await dispatch(updateUptimeMonitor({ monitor: toSubmit }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
createToast({ body: "Monitor updated successfully!" });
|
||||
} else {
|
||||
createToast({ body: "Failed to update monitor." });
|
||||
}
|
||||
console.log(JSON.stringify(toSubmit, null, 2));
|
||||
// await updateMonitor({ monitor: toSubmit, redirect: "/uptime" });
|
||||
};
|
||||
|
||||
// Effects
|
||||
useEffect(() => {
|
||||
if (monitor?.matchMethod) {
|
||||
setUseAdvancedMatching(true);
|
||||
}
|
||||
|
||||
setForm({
|
||||
...monitor,
|
||||
});
|
||||
}, [monitor, notifications]);
|
||||
|
||||
// Parse the URL
|
||||
const parsedUrl = parseUrl(monitor?.url);
|
||||
const parsedUrl = parseUrl(form?.url);
|
||||
const protocol = parsedUrl?.protocol?.replace(":", "") || "";
|
||||
|
||||
const { determineState, statusColor } = useMonitorUtils();
|
||||
@@ -434,7 +425,13 @@ const Configure = () => {
|
||||
onChange={onChange}
|
||||
items={frequencies}
|
||||
/>
|
||||
{form.type === "http" && (
|
||||
<Checkbox
|
||||
name="useAdvancedMatching"
|
||||
label={t("advancedMatching")}
|
||||
isChecked={useAdvancedMatching}
|
||||
onChange={onChange}
|
||||
/>
|
||||
{form.type === "http" && useAdvancedMatching && (
|
||||
<>
|
||||
<Select
|
||||
name="matchMethod"
|
||||
@@ -502,6 +499,7 @@ const Configure = () => {
|
||||
mt="auto"
|
||||
>
|
||||
<Button
|
||||
disabled={isDeleting || isUpdating}
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="accent"
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
// React, Redux, Router
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
// Utility and Network
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
// MUI
|
||||
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
|
||||
//Components
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import TextInput from "../../../Components/Inputs/TextInput";
|
||||
import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import Radio from "../../../Components/Inputs/Radio";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import ConfigBox from "../../../Components/ConfigBox";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
import NotificationsConfig from "../../../Components/NotificationConfig";
|
||||
import Button from "@mui/material/Button";
|
||||
import ButtonGroup from "@mui/material/ButtonGroup";
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
|
||||
import { useCreateMonitor } from "../../../Hooks/monitorHooks";
|
||||
|
||||
const CreateMonitor = () => {
|
||||
// Redux state
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const { isLoading } = useSelector((state) => state.uptimeMonitors);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
// Local state
|
||||
const [errors, setErrors] = useState({});
|
||||
@@ -49,6 +49,7 @@ const CreateMonitor = () => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [notifications, notificationsAreLoading, error] = useGetNotificationsByTeamId();
|
||||
const [createMonitor, isCreating] = useCreateMonitor();
|
||||
|
||||
const MS_PER_MINUTE = 60000;
|
||||
const SELECT_VALUES = [
|
||||
@@ -147,13 +148,7 @@ const CreateMonitor = () => {
|
||||
notifications: monitor.notifications,
|
||||
};
|
||||
|
||||
const action = await dispatch(createUptimeMonitor({ monitor: form }));
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
createToast({ body: "Monitor created successfully!" });
|
||||
navigate("/uptime");
|
||||
} else {
|
||||
createToast({ body: "Failed to create monitor." });
|
||||
}
|
||||
await createMonitor({ monitor: form, redirect: "/uptime" });
|
||||
};
|
||||
|
||||
const onChange = (event) => {
|
||||
@@ -472,7 +467,7 @@ const CreateMonitor = () => {
|
||||
variant="contained"
|
||||
color="accent"
|
||||
disabled={!Object.values(errors).every((value) => value === undefined)}
|
||||
loading={isLoading}
|
||||
loading={isLoading || isCreating}
|
||||
>
|
||||
{t("createMonitor")}
|
||||
</Button>
|
||||
|
||||
@@ -5,7 +5,7 @@ import PropTypes from "prop-types";
|
||||
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { Typography } from "@mui/material";
|
||||
import useUtils from "../../../Monitors/Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
|
||||
const UptimeStatusBoxes = ({
|
||||
isLoading = false,
|
||||
@@ -14,7 +14,7 @@ const UptimeStatusBoxes = ({
|
||||
certificateExpiry,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const { determineState } = useUtils();
|
||||
const { determineState } = useMonitorUtils();
|
||||
|
||||
// Determine time since last failure
|
||||
const timeOfLastFailure = monitorStats?.timeOfLastFailure;
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
export const useChecksFetch = ({
|
||||
monitorId,
|
||||
monitorType,
|
||||
dateRange,
|
||||
page,
|
||||
rowsPerPage,
|
||||
}) => {
|
||||
const [checks, setChecks] = useState(undefined);
|
||||
const [checksCount, setChecksCount] = useState(undefined);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!monitorType) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchChecks = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getChecksByMonitor({
|
||||
monitorId: monitorId,
|
||||
type: monitorType,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange: dateRange,
|
||||
filter: null,
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
setChecks(res.data.data.checks);
|
||||
setChecksCount(res.data.data.checksCount);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchChecks();
|
||||
}, [monitorId, monitorType, dateRange, page, rowsPerPage]);
|
||||
|
||||
return [checks, checksCount, isLoading, networkError];
|
||||
};
|
||||
|
||||
export default useChecksFetch;
|
||||
@@ -1,33 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
export const useMonitorFetch = ({ monitorId, dateRange }) => {
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitor, setMonitor] = useState(undefined);
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const res = await networkService.getUptimeDetailsById({
|
||||
monitorId: monitorId,
|
||||
dateRange: dateRange,
|
||||
normalize: true,
|
||||
});
|
||||
setMonitor(res?.data?.data ?? {});
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({ body: error.message });
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [dateRange, monitorId, navigate]);
|
||||
return [monitor, isLoading, networkError];
|
||||
};
|
||||
|
||||
export default useMonitorFetch;
|
||||
@@ -1,15 +1,14 @@
|
||||
// Components
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import MonitorDetailsControlHeader from "../../../Components/MonitorDetailsControlHeader";
|
||||
import MonitorStatusHeader from "../../../Components/MonitorStatusHeader";
|
||||
import MonitorTimeFrameHeader from "../../../Components/MonitorTimeFrameHeader";
|
||||
import ChartBoxes from "./Components/ChartBoxes";
|
||||
import ResponseTimeChart from "./Components/Charts/ResponseTimeChart";
|
||||
import ResponseTable from "./Components/ResponseTable";
|
||||
import UptimeStatusBoxes from "./Components/UptimeStatusBoxes";
|
||||
import GenericFallback from "../../../Components/GenericFallback";
|
||||
// MUI Components
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
// Utils
|
||||
import { useState } from "react";
|
||||
@@ -17,9 +16,9 @@ import { useParams } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import useFetchUptimeMonitorDetails from "../../../Hooks/useFetchUptimeMonitorDetails";
|
||||
import { useFetchUptimeMonitorById } from "../../../Hooks/monitorHooks";
|
||||
import useCertificateFetch from "./Hooks/useCertificateFetch";
|
||||
import useChecksFetch from "./Hooks/useChecksFetch";
|
||||
import { useFetchChecks } from "../../../Hooks/checkHooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
// Constants
|
||||
@@ -50,7 +49,7 @@ const UptimeDetails = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [monitorData, monitorStats, monitorIsLoading, monitorNetworkError] =
|
||||
useFetchUptimeMonitorDetails({
|
||||
useFetchUptimeMonitorById({
|
||||
monitorId,
|
||||
dateRange,
|
||||
trigger,
|
||||
@@ -66,10 +65,14 @@ const UptimeDetails = () => {
|
||||
});
|
||||
|
||||
const monitorType = monitor?.type;
|
||||
const [checks, checksCount, checksAreLoading, checksNetworkError] = useChecksFetch({
|
||||
|
||||
const [checks, checksCount, checksAreLoading, checksNetworkError] = useFetchChecks({
|
||||
monitorId,
|
||||
monitorType,
|
||||
type: monitorType,
|
||||
sortOrder: "desc",
|
||||
limit: null,
|
||||
dateRange,
|
||||
filter: null,
|
||||
page,
|
||||
rowsPerPage,
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ import TableSkeleton from "../../../../../Components/Table/skeleton";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../Hooks/useUtils";
|
||||
import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -58,7 +58,7 @@ const UptimeDataTable = ({
|
||||
}) => {
|
||||
// Utils
|
||||
const navigate = useNavigate();
|
||||
const { determineState } = useUtils();
|
||||
const { determineState } = useMonitorUtils();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
|
||||
|
||||
export const useMonitorFetch = ({
|
||||
teamId,
|
||||
limit,
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
triggerUpdate,
|
||||
}) => {
|
||||
const [monitorsAreLoading, setMonitorsAreLoading] = useState(false);
|
||||
const [monitors, setMonitors] = useState(undefined);
|
||||
const [filteredMonitors, setFilteredMonitors] = useState(undefined);
|
||||
const [monitorsSummary, setMonitorsSummary] = useState(undefined);
|
||||
const [networkError, setNetworkError] = useState(false);
|
||||
|
||||
const theme = useTheme();
|
||||
const { getMonitorWithPercentage } = useMonitorUtils();
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setMonitorsAreLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
teamId,
|
||||
limit,
|
||||
types: ["http", "ping", "docker", "port"],
|
||||
page,
|
||||
rowsPerPage,
|
||||
filter,
|
||||
field,
|
||||
order,
|
||||
});
|
||||
const { monitors, filteredMonitors, summary } = res.data.data;
|
||||
const mappedMonitors = filteredMonitors.map((monitor) =>
|
||||
getMonitorWithPercentage(monitor, theme)
|
||||
);
|
||||
setMonitors(monitors);
|
||||
setFilteredMonitors(mappedMonitors);
|
||||
setMonitorsSummary(summary);
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setMonitorsAreLoading(false);
|
||||
}
|
||||
};
|
||||
fetchMonitors();
|
||||
}, [
|
||||
teamId,
|
||||
limit,
|
||||
field,
|
||||
filter,
|
||||
order,
|
||||
page,
|
||||
rowsPerPage,
|
||||
theme,
|
||||
triggerUpdate,
|
||||
getMonitorWithPercentage,
|
||||
]);
|
||||
return {
|
||||
monitors,
|
||||
filteredMonitors,
|
||||
monitorsSummary,
|
||||
monitorsAreLoading,
|
||||
networkError,
|
||||
};
|
||||
};
|
||||
|
||||
export default useMonitorFetch;
|
||||
@@ -1,110 +0,0 @@
|
||||
import { useTheme } from "@mui/material";
|
||||
|
||||
const useUtils = () => {
|
||||
const determineState = (monitor) => {
|
||||
if (typeof monitor === "undefined") return "pending";
|
||||
if (monitor.isActive === false) return "paused";
|
||||
if (monitor?.status === undefined) return "pending";
|
||||
return monitor?.status == true ? "up" : "down";
|
||||
};
|
||||
|
||||
/* TODO Refactor: from here on shouldn't live in a custom hook, but on theme, or constants */
|
||||
const theme = useTheme();
|
||||
|
||||
const statusColor = {
|
||||
up: theme.palette.success.lowContrast,
|
||||
down: theme.palette.error.lowContrast,
|
||||
paused: theme.palette.warning.lowContrast,
|
||||
pending: theme.palette.warning.lowContrast,
|
||||
};
|
||||
|
||||
const statusMsg = {
|
||||
up: "Your site is up.",
|
||||
down: "Your site is down.",
|
||||
paused: "Pending...",
|
||||
};
|
||||
|
||||
const pagespeedStatusMsg = {
|
||||
up: "Live (collecting data)",
|
||||
down: "Inactive",
|
||||
paused: "Paused",
|
||||
};
|
||||
|
||||
/*
|
||||
TODO
|
||||
This is used on
|
||||
1) Details > Gradient card */
|
||||
/* These are rediections. We should do something that maps up to success, down to error, and get the theme by that
|
||||
See Client\src\Components\Label\index.jsx
|
||||
*/
|
||||
|
||||
const statusToTheme = {
|
||||
up: "success",
|
||||
down: "error",
|
||||
paused: "warning",
|
||||
pending: "secondary",
|
||||
"cannot resolve": "tertiary",
|
||||
};
|
||||
|
||||
const getStatusStyles = (status) => {
|
||||
const themeColor = statusToTheme[status];
|
||||
|
||||
return {
|
||||
backgroundColor: theme.palette[themeColor].lowContrast,
|
||||
background: `linear-gradient(340deg, ${theme.palette[themeColor].main} -60%, ${theme.palette[themeColor].lowContrast} 35%)`,
|
||||
borderColor: theme.palette[themeColor].lowContrast,
|
||||
"& h2": {
|
||||
color: theme.palette[themeColor].contrastText,
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
"& p": {
|
||||
color: theme.palette[themeColor].contrastText,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const statusStyles = {
|
||||
up: {
|
||||
backgroundColor: theme.palette.success.lowContrast,
|
||||
background: `linear-gradient(340deg, ${theme.palette.tertiary.main} -60%, ${theme.palette.success.lowContrast} 35%)`, // CAIO_REVIEW
|
||||
borderColor: theme.palette.success.contrastText,
|
||||
// "& h2": { color: theme.palette.success.contrastText }, // CAIO_REVIEW
|
||||
},
|
||||
down: {
|
||||
backgroundColor: theme.palette.error.lowContrast,
|
||||
background: `linear-gradient(340deg, ${theme.palette.tertiary.main} -60%, ${theme.palette.error.lowContrast} 35%)`, // CAIO_REVIEW
|
||||
borderColor: theme.palette.error.contrastText,
|
||||
"& h2": { color: theme.palette.error.contrastText }, // CAIO_REVIEW
|
||||
"& .MuiTypography-root": { color: theme.palette.error.contrastText }, // CAIO_REVIEW
|
||||
},
|
||||
paused: {
|
||||
backgroundColor: theme.palette.warning.lowContrast,
|
||||
background: `linear-gradient(340deg, ${theme.palette.tertiary.main} -60%, ${theme.palette.warning.lowContrast} 35%)`, // CAIO_REVIEW
|
||||
borderColor: theme.palette.warning.contrastText,
|
||||
"& h2": { color: theme.palette.warning.contrastText }, // CAIO_REVIEW
|
||||
"& .MuiTypography-root": { color: theme.palette.warning.contrastText }, // CAIO_REVIEW
|
||||
},
|
||||
pending: {
|
||||
backgroundColor: theme.palette.warning.lowContrast,
|
||||
background: `linear-gradient(340deg, ${theme.palette.tertiary.main} -60%, ${theme.palette.warning.lowContrast} 35%)`, // CAIO_REVIEW
|
||||
borderColor: theme.palette.warning.contrastText,
|
||||
"& h2": { color: theme.palette.warning.contrastText }, // CAIO_REVIEW
|
||||
},
|
||||
};
|
||||
|
||||
/* These are rediections. We should do something that maps up to success, down to error, and get the theme by that
|
||||
|
||||
*/
|
||||
|
||||
return {
|
||||
determineState,
|
||||
statusColor,
|
||||
statusMsg,
|
||||
pagespeedStatusMsg,
|
||||
statusStyles,
|
||||
statusToTheme,
|
||||
getStatusStyles,
|
||||
};
|
||||
};
|
||||
|
||||
export default useUtils;
|
||||
@@ -28,9 +28,12 @@ import { useNavigate } from "react-router-dom";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { setRowsPerPage } from "../../../Features/UI/uiSlice";
|
||||
import PropTypes from "prop-types";
|
||||
import useFetchMonitorsWithSummary from "../../../Hooks/useFetchMonitorsWithSummary";
|
||||
import useFetchMonitorsWithChecks from "../../../Hooks/useFetchMonitorsWithChecks";
|
||||
import {
|
||||
useFetchMonitorsWithSummary,
|
||||
useFetchMonitorsWithChecks,
|
||||
} from "../../../Hooks/monitorHooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const TYPES = ["http", "ping", "docker", "port"];
|
||||
const CreateMonitorButton = ({ shouldRender }) => {
|
||||
// Utils
|
||||
@@ -78,7 +81,6 @@ const UptimeMonitors = () => {
|
||||
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const isAdmin = useIsAdmin();
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -587,7 +587,7 @@ class NetworkService {
|
||||
*
|
||||
*/
|
||||
|
||||
async getChecksByMonitor(config) {
|
||||
getChecksByMonitor = async (config) => {
|
||||
const params = new URLSearchParams();
|
||||
if (config.type) params.append("type", config.type);
|
||||
if (config.sortOrder) params.append("sortOrder", config.sortOrder);
|
||||
@@ -599,7 +599,7 @@ class NetworkService {
|
||||
if (config.status !== undefined) params.append("status", config.status);
|
||||
|
||||
return this.axiosInstance.get(`/checks/${config.monitorId}?${params.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ************************************
|
||||
@@ -618,7 +618,7 @@ class NetworkService {
|
||||
* @returns {Promise<AxiosResponse>} The response from the axios GET request.
|
||||
*
|
||||
*/
|
||||
async getChecksByTeam(config) {
|
||||
getChecksByTeam = async (config) => {
|
||||
const params = new URLSearchParams();
|
||||
if (config.sortOrder) params.append("sortOrder", config.sortOrder);
|
||||
if (config.limit) params.append("limit", config.limit);
|
||||
@@ -628,7 +628,7 @@ class NetworkService {
|
||||
if (config.rowsPerPage) params.append("rowsPerPage", config.rowsPerPage);
|
||||
if (config.status !== undefined) params.append("status", config.status);
|
||||
return this.axiosInstance.get(`/checks/team/${config.teamId}?${params.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ************************************
|
||||
|
||||
@@ -525,6 +525,7 @@
|
||||
"notifyEmails": "Also notify via email to multiple addresses (coming soon)",
|
||||
"seperateEmails": "You can separate multiple emails with a comma",
|
||||
"checkFrequency": "Check frequency",
|
||||
"advancedMatching": "Advanced matching",
|
||||
"matchMethod": "Match Method",
|
||||
"expectedValue": "Expected value",
|
||||
"deleteDialogTitle": "Do you really want to delete this monitor?",
|
||||
|
||||
Reference in New Issue
Block a user