Skip to content

Commit 8f971cf

Browse files
authored
Merge pull request #2826 from bluewave-labs/develop
develop -> master
2 parents 9b3ad54 + 32c811e commit 8f971cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1574
-1688
lines changed

client/src/Components/Fallback/FallbackBackground.jsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useTheme } from "@emotion/react";
22
import Box from "@mui/material/Box";
33
import Background from "../../assets/Images/background-grid.svg?react";
4-
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
54
import OutputAnimation from "../../assets/Animations/output.gif";
65
import DarkmodeOutput from "../../assets/Animations/darkmodeOutput.gif";
76
import { useSelector } from "react-redux";
@@ -13,7 +12,7 @@ const FallbackBackground = () => {
1312
<Box
1413
component="img"
1514
src={mode === "light" ? OutputAnimation : DarkmodeOutput}
16-
Background="transparent"
15+
background="transparent"
1716
alt="Loading animation"
1817
sx={{
1918
zIndex: 1,

client/src/Components/StarPrompt/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const StarPrompt = ({ repoUrl = "https://github.com/bluewave-labs/checkmate" })
7474
<Typography
7575
variant="body1"
7676
sx={{
77-
color: theme.palette.text.secondary,
77+
color: theme.palette.primary.contrastTextTertiary,
7878
fontSize: "0.938rem",
7979
lineHeight: 1.5,
8080
mb: 1,

client/src/Hooks/monitorHooks.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@ const useUpdateMonitor = () => {
369369
setIsLoading(true);
370370
const updatedFields = {
371371
name: monitor.name,
372+
statusWindowSize: monitor.statusWindowSize,
373+
statusWindowThreshold: monitor.statusWindowThreshold,
372374
description: monitor.description,
373375
interval: monitor.interval,
374376
notifications: monitor.notifications,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import ConfigBox from "../../../../Components/ConfigBox";
2+
import { Box, Stack, Typography } from "@mui/material";
3+
import { CustomThreshold } from "../Components/CustomThreshold";
4+
import { capitalizeFirstLetter } from "../../../../Utils/stringUtils";
5+
import { useTheme } from "@emotion/react";
6+
import { useTranslation } from "react-i18next";
7+
import PropTypes from "prop-types";
8+
const CustomAlertsSection = ({
9+
errors,
10+
onChange,
11+
infrastructureMonitor,
12+
handleCheckboxChange,
13+
}) => {
14+
const theme = useTheme();
15+
const { t } = useTranslation();
16+
17+
const METRICS = ["cpu", "memory", "disk", "temperature"];
18+
const METRIC_PREFIX = "usage_";
19+
const hasAlertError = (errors) => {
20+
return Object.keys(errors).filter((k) => k.startsWith(METRIC_PREFIX)).length > 0;
21+
};
22+
const getAlertError = (errors) => {
23+
const errorKey = Object.keys(errors).find((key) => key.startsWith(METRIC_PREFIX));
24+
return errorKey ? errors[errorKey] : null;
25+
};
26+
return (
27+
<ConfigBox>
28+
<Box>
29+
<Typography
30+
component="h2"
31+
variant="h2"
32+
>
33+
{t("infrastructureCustomizeAlerts")}
34+
</Typography>
35+
<Typography component="p">
36+
{t("infrastructureAlertNotificationDescription")}
37+
</Typography>
38+
</Box>
39+
<Stack gap={theme.spacing(6)}>
40+
{METRICS.map((metric) => {
41+
return (
42+
<CustomThreshold
43+
key={metric}
44+
infrastructureMonitor={infrastructureMonitor}
45+
errors={errors}
46+
checkboxId={metric}
47+
checkboxName={metric}
48+
checkboxLabel={
49+
metric !== "cpu" ? capitalizeFirstLetter(metric) : metric.toUpperCase()
50+
}
51+
onCheckboxChange={handleCheckboxChange}
52+
isChecked={infrastructureMonitor[metric]}
53+
fieldId={METRIC_PREFIX + metric}
54+
fieldName={METRIC_PREFIX + metric}
55+
fieldValue={String(infrastructureMonitor[METRIC_PREFIX + metric])}
56+
onFieldChange={onChange}
57+
alertUnit={metric == "temperature" ? "°C" : "%"}
58+
/>
59+
);
60+
})}
61+
62+
{hasAlertError(errors) && (
63+
<Typography
64+
component="span"
65+
className="input-error"
66+
color={theme.palette.error.main}
67+
mt={theme.spacing(2)}
68+
sx={{
69+
opacity: 0.8,
70+
}}
71+
>
72+
{getAlertError(errors)}
73+
</Typography>
74+
)}
75+
</Stack>
76+
</ConfigBox>
77+
);
78+
};
79+
80+
CustomAlertsSection.propTypes = {
81+
errors: PropTypes.object.isRequired,
82+
onChange: PropTypes.func.isRequired,
83+
infrastructureMonitor: PropTypes.object.isRequired,
84+
handleCheckboxChange: PropTypes.func.isRequired,
85+
};
86+
87+
export default CustomAlertsSection;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useState } from "react";
2+
import { Box, Button } from "@mui/material";
3+
import { useTheme } from "@emotion/react";
4+
import { useTranslation } from "react-i18next";
5+
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
6+
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
7+
import Dialog from "../../../../Components/Dialog";
8+
import PropTypes from "prop-types";
9+
10+
const MonitorActionButtons = ({ monitor, isBusy, handlePause, handleRemove }) => {
11+
const theme = useTheme();
12+
const { t } = useTranslation();
13+
const [isOpen, setIsOpen] = useState(false);
14+
15+
return (
16+
<Box
17+
alignSelf="flex-end"
18+
ml="auto"
19+
>
20+
<Button
21+
onClick={handlePause}
22+
loading={isBusy}
23+
variant="contained"
24+
color="secondary"
25+
sx={{
26+
pl: theme.spacing(4),
27+
pr: theme.spacing(6),
28+
"& svg": {
29+
mr: theme.spacing(2),
30+
"& path": {
31+
stroke: theme.palette.primary.contrastTextTertiary,
32+
strokeWidth: 0.1,
33+
},
34+
},
35+
}}
36+
>
37+
{monitor?.isActive ? (
38+
<>
39+
<PauseCircleOutlineIcon />
40+
{t("pause")}
41+
</>
42+
) : (
43+
<>
44+
<PlayCircleOutlineRoundedIcon />
45+
{t("resume")}
46+
</>
47+
)}
48+
</Button>
49+
<Button
50+
loading={isBusy}
51+
variant="contained"
52+
color="error"
53+
onClick={() => setIsOpen(true)}
54+
sx={{ ml: theme.spacing(6) }}
55+
>
56+
{t("remove")}
57+
</Button>
58+
<Dialog
59+
open={isOpen}
60+
theme={theme}
61+
title={t("deleteDialogTitle")}
62+
description={t("deleteDialogDescription")}
63+
onCancel={() => setIsOpen(false)}
64+
confirmationButtonLabel={t("delete")}
65+
onConfirm={handleRemove}
66+
/>
67+
</Box>
68+
);
69+
};
70+
71+
MonitorActionButtons.propTypes = {
72+
monitor: PropTypes.object.isRequired,
73+
isBusy: PropTypes.bool.isRequired,
74+
handlePause: PropTypes.func.isRequired,
75+
handleRemove: PropTypes.func.isRequired,
76+
};
77+
78+
export default MonitorActionButtons;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Box, Stack, Tooltip, Typography } from "@mui/material";
2+
import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
3+
import { useTheme } from "@emotion/react";
4+
import { useTranslation } from "react-i18next";
5+
import PulseDot from "../../../../Components/Animated/PulseDot";
6+
import PropTypes from "prop-types";
7+
const MonitorStatusHeader = ({ monitor, infrastructureMonitor }) => {
8+
const theme = useTheme();
9+
const { t } = useTranslation();
10+
const { statusColor, pagespeedStatusMsg, determineState } = useMonitorUtils();
11+
return (
12+
<Stack
13+
direction="row"
14+
alignItems="center"
15+
height="fit-content"
16+
gap={theme.spacing(2)}
17+
>
18+
<Tooltip
19+
title={pagespeedStatusMsg[determineState(monitor)]}
20+
disableInteractive
21+
slotProps={{
22+
popper: {
23+
modifiers: [
24+
{
25+
name: "offset",
26+
options: { offset: [0, -8] },
27+
},
28+
],
29+
},
30+
}}
31+
>
32+
<Box>
33+
<PulseDot color={statusColor[determineState(monitor)]} />
34+
</Box>
35+
</Tooltip>
36+
<Typography
37+
component="h2"
38+
variant="monitorUrl"
39+
>
40+
{infrastructureMonitor.url?.replace(/^https?:\/\//, "") || "..."}
41+
</Typography>
42+
<Typography
43+
position="relative"
44+
variant="body2"
45+
ml={theme.spacing(6)}
46+
mt={theme.spacing(1)}
47+
sx={{
48+
"&:before": {
49+
position: "absolute",
50+
content: `""`,
51+
width: theme.spacing(2),
52+
height: theme.spacing(2),
53+
borderRadius: "50%",
54+
backgroundColor: theme.palette.primary.contrastTextTertiary,
55+
opacity: 0.8,
56+
left: theme.spacing(-5),
57+
top: "50%",
58+
transform: "translateY(-50%)",
59+
},
60+
}}
61+
>
62+
{t("editing")}
63+
</Typography>
64+
</Stack>
65+
);
66+
};
67+
68+
MonitorStatusHeader.propTypes = {
69+
monitor: PropTypes.object.isRequired,
70+
infrastructureMonitor: PropTypes.object.isRequired,
71+
};
72+
73+
export default MonitorStatusHeader;
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { useState } from "react";
2+
const useInfrastructureMonitorForm = () => {
3+
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
4+
url: "",
5+
name: "",
6+
notifications: [],
7+
notify_email: false,
8+
interval: 0.25,
9+
cpu: false,
10+
usage_cpu: "",
11+
memory: false,
12+
usage_memory: "",
13+
disk: false,
14+
usage_disk: "",
15+
temperature: false,
16+
usage_temperature: "",
17+
secret: "",
18+
});
19+
20+
const onChangeForm = (name, value) => {
21+
setInfrastructureMonitor({
22+
...infrastructureMonitor,
23+
[name]: value,
24+
});
25+
};
26+
const handleCheckboxChange = (event) => {
27+
setInfrastructureMonitor({
28+
...infrastructureMonitor,
29+
[event.target.name]: event.target.checked,
30+
});
31+
};
32+
const initializeInfrastructureMonitorForCreate = (globalSettings) => {
33+
const gt = globalSettings?.data?.settings?.globalThresholds || {};
34+
setInfrastructureMonitor({
35+
url: "",
36+
name: "",
37+
notifications: [],
38+
interval: 0.25,
39+
cpu: gt.cpu !== undefined,
40+
usage_cpu: gt.cpu !== undefined ? gt.cpu.toString() : "",
41+
memory: gt.memory !== undefined,
42+
usage_memory: gt.memory !== undefined ? gt.memory.toString() : "",
43+
disk: gt.disk !== undefined,
44+
usage_disk: gt.disk !== undefined ? gt.disk.toString() : "",
45+
temperature: gt.temperature !== undefined,
46+
usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "",
47+
secret: "",
48+
});
49+
};
50+
51+
const initializeInfrastructureMonitorForUpdate = (monitor) => {
52+
const MS_PER_MINUTE = 60000;
53+
const { thresholds = {} } = monitor;
54+
setInfrastructureMonitor({
55+
url: monitor.url.replace(/^https?:\/\//, ""),
56+
name: monitor.name || "",
57+
notifications: monitor.notifications || [],
58+
interval: monitor.interval / MS_PER_MINUTE,
59+
cpu: thresholds.usage_cpu !== undefined,
60+
usage_cpu:
61+
thresholds.usage_cpu !== undefined ? (thresholds.usage_cpu * 100).toString() : "",
62+
memory: thresholds.usage_memory !== undefined,
63+
usage_memory:
64+
thresholds.usage_memory !== undefined
65+
? (thresholds.usage_memory * 100).toString()
66+
: "",
67+
disk: thresholds.usage_disk !== undefined,
68+
usage_disk:
69+
thresholds.usage_disk !== undefined
70+
? (thresholds.usage_disk * 100).toString()
71+
: "",
72+
temperature: thresholds.usage_temperature !== undefined,
73+
usage_temperature:
74+
thresholds.usage_temperature !== undefined
75+
? (thresholds.usage_temperature * 100).toString()
76+
: "",
77+
secret: monitor.secret || "",
78+
});
79+
};
80+
return {
81+
infrastructureMonitor,
82+
setInfrastructureMonitor,
83+
onChangeForm,
84+
handleCheckboxChange,
85+
initializeInfrastructureMonitorForCreate,
86+
initializeInfrastructureMonitorForUpdate,
87+
};
88+
};
89+
90+
export default useInfrastructureMonitorForm;

0 commit comments

Comments
 (0)