diff --git a/client/src/Hooks/monitorHooks.js b/client/src/Hooks/monitorHooks.js
index d59d88c74..4f0e9c049 100644
--- a/client/src/Hooks/monitorHooks.js
+++ b/client/src/Hooks/monitorHooks.js
@@ -205,6 +205,10 @@ const useFetchStatsByMonitorId = ({
const useFetchMonitorById = ({ monitorId, setMonitor, updateTrigger }) => {
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
+ if (typeof monitorId === "undefined") {
+ setIsLoading(false);
+ return;
+ }
const fetchMonitor = async () => {
try {
setIsLoading(true);
diff --git a/client/src/Pages/PageSpeed/Configure/index.css b/client/src/Pages/PageSpeed/Configure/index.css
deleted file mode 100644
index 89a7c3466..000000000
--- a/client/src/Pages/PageSpeed/Configure/index.css
+++ /dev/null
@@ -1,9 +0,0 @@
-.configure-pagespeed button {
- height: var(--env-var-height-2);
-}
-
-.configure-pagespeed .field,
-.configure-pagespeed .section-disabled,
-.configure-pagespeed .select-wrapper {
- flex: 1;
-}
diff --git a/client/src/Pages/PageSpeed/Configure/index.jsx b/client/src/Pages/PageSpeed/Configure/index.jsx
deleted file mode 100644
index 71e1e111e..000000000
--- a/client/src/Pages/PageSpeed/Configure/index.jsx
+++ /dev/null
@@ -1,351 +0,0 @@
-// Components
-import { Box, Stack, Tooltip, Typography, Button } from "@mui/material";
-import ConfigBox from "../../../Components/ConfigBox";
-import Select from "../../../Components/Inputs/Select";
-import TextInput from "../../../Components/Inputs/TextInput";
-import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
-import Breadcrumbs from "../../../Components/Breadcrumbs";
-import PulseDot from "../../../Components/Animated/PulseDot";
-import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
-import SkeletonLayout from "./skeleton";
-import NotificationsConfig from "../../../Components/NotificationConfig";
-import Dialog from "../../../Components/Dialog";
-
-// Utils
-import { useState } from "react";
-import { useTheme } from "@emotion/react";
-import { useParams } from "react-router";
-import { monitorValidation } from "../../../Validation/validation";
-import { useTranslation } from "react-i18next";
-import { useMonitorUtils } from "../../../Hooks/useMonitorUtils";
-import { useGetNotificationsByTeamId } from "../../../Hooks/useNotifications";
-import {
- useFetchMonitorById,
- useDeleteMonitor,
- useUpdateMonitor,
- usePauseMonitor,
-} from "../../../Hooks/monitorHooks";
-const PageSpeedConfigure = () => {
- // Redux state
-
- // Local state
- const [monitor, setMonitor] = useState({});
- const [errors, setErrors] = useState({});
- const [isOpen, setIsOpen] = useState(false);
- const [updateTrigger, setUpdateTrigger] = useState(false);
-
- // Utils
- const theme = useTheme();
- const { t } = useTranslation();
- const MS_PER_MINUTE = 60000;
- const { monitorId } = useParams();
- 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" },
- { _id: 10, name: "10 minutes" },
- { _id: 20, name: "20 minutes" },
- { _id: 60, name: "1 hour" },
- { _id: 1440, name: "1 day" },
- { _id: 10080, name: "1 week" },
- ];
-
- // Handlers
- const triggerUpdate = () => {
- setUpdateTrigger(!updateTrigger);
- };
-
- const onChange = (event) => {
- let { value, name } = event.target;
-
- if (name === "interval") {
- value = value * MS_PER_MINUTE;
- }
- setMonitor((prev) => ({
- ...prev,
- [name]: value,
- }));
-
- const validation = monitorValidation.validate(
- { [name]: value },
- { abortEarly: false }
- );
-
- setErrors((prev) => {
- const updatedErrors = { ...prev };
-
- if (validation.error) updatedErrors[name] = validation.error.details[0].message;
- else delete updatedErrors[name];
- return updatedErrors;
- });
- };
-
- const handlePause = async () => {
- await pauseMonitor({ monitorId, triggerUpdate });
- };
-
- const onSubmit = async (event) => {
- event.preventDefault();
- await updateMonitor({ monitor, redirect: "/pagespeed" });
- };
-
- const handleRemove = async (event) => {
- event.preventDefault();
- await deleteMonitor({ monitor, redirect: "/pagespeed" });
- };
-
- return (
-
- {Object.keys(monitor).length === 0 ? (
-
- ) : (
- <>
-
-
-
-
-
- {monitor.name}
-
-
-
-
-
-
-
-
- {monitor.url?.replace(/^https?:\/\//, "") || "..."}
-
-
- {t("editing")}
-
-
-
-
-
-
-
-
-
-
-
- {t("settingsGeneralSettings")}
-
-
- {t("pageSpeedConfigureSettingsDescription")}
-
-
- .Mui-disabled)": {
- backgroundColor: theme.palette.tertiary.main,
- },
- }}
- >
-
-
-
-
-
-
- {t("notificationConfig.title")}
-
- {t("notificationConfig.description")}
-
-
-
-
-
-
-
- {t("distributedUptimeCreateAdvancedSettings")}
-
-
-
-
-
-
-
-
-
-
- >
- )}
-
- );
-};
-
-export default PageSpeedConfigure;
diff --git a/client/src/Pages/PageSpeed/Create/index.jsx b/client/src/Pages/PageSpeed/Create/index.jsx
index 5cc4a1a54..78709093a 100644
--- a/client/src/Pages/PageSpeed/Create/index.jsx
+++ b/client/src/Pages/PageSpeed/Create/index.jsx
@@ -1,19 +1,20 @@
-//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";
+// Components
+import { Box, Stack, Tooltip, Typography, Button, ButtonGroup } from "@mui/material";
import ConfigBox from "../../../Components/ConfigBox";
-import Radio from "../../../Components/Inputs/Radio";
import Select from "../../../Components/Inputs/Select";
+import TextInput from "../../../Components/Inputs/TextInput";
+import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
+import Breadcrumbs from "../../../Components/Breadcrumbs";
+import PulseDot from "../../../Components/Animated/PulseDot";
+import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
+import SkeletonLayout from "./skeleton";
import NotificationsConfig from "../../../Components/NotificationConfig";
+import Dialog from "../../../Components/Dialog";
+import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
+import Radio from "../../../Components/Inputs/Radio";
// Utils
-import { useState } from "react";
+import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { monitorValidation } from "../../../Validation/validation";
import { parseDomainName } from "../../../Utils/monitorUtils";
@@ -21,79 +22,130 @@ 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;
+import { useParams } from "react-router";
+import { useMonitorUtils } from "../../../Hooks/useMonitorUtils";
+import {
+ useCreateMonitor,
+ useFetchMonitorById,
+ useDeleteMonitor,
+ useUpdateMonitor,
+ usePauseMonitor,
+} from "../../../Hooks/monitorHooks";
-const CRUMBS = [
- { name: "pagespeed", path: "/pagespeed" },
- { name: "create", path: `/pagespeed/create` },
-];
-
-const SELECT_VALUES = [
- { _id: 3, name: "3 minutes" },
- { _id: 5, name: "5 minutes" },
- { _id: 10, name: "10 minutes" },
- { _id: 20, name: "20 minutes" },
- { _id: 60, name: "1 hour" },
- { _id: 1440, name: "1 day" },
- { _id: 10080, name: "1 week" },
-];
-
-const CreatePageSpeed = () => {
- // State
- const [monitor, setMonitor] = useState({
- url: "",
- name: "",
- type: "pagespeed",
- notifications: [],
- interval: 3,
- });
+const PageSpeedSetup = () => {
+ const { monitorId } = useParams();
+ const isCreate = typeof monitorId === "undefined";
+ const CRUMBS = [
+ { name: "pagespeed", path: "/pagespeed" },
+ ...(isCreate
+ ? [{ name: "create", path: `/pagespeed/create` }]
+ : [
+ { name: "details", path: `/pagespeed/${monitorId}` },
+ { name: "configure", path: `/pagespeed/configure/${monitorId}` },
+ ]),
+ ];
+ // States
+ const [monitor, setMonitor] = useState(
+ isCreate
+ ? {
+ url: "",
+ name: "",
+ type: "pagespeed",
+ notifications: [],
+ interval: 180000,
+ }
+ : {}
+ );
const [https, setHttps] = useState(true);
const [errors, setErrors] = useState({});
- const { user } = useSelector((state) => state.auth);
- const [notifications, notificationsAreLoading, error] = useGetNotificationsByTeamId();
+ const [isOpen, setIsOpen] = useState(false);
+ const [updateTrigger, setUpdateTrigger] = useState(false);
// Setup
+ const { t } = useTranslation();
const theme = useTheme();
+ // Constants
+ const MS_PER_MINUTE = 60000;
+ const FREQUENCIES = [
+ { _id: 3, name: t("time.threeMinutes") },
+ { _id: 5, name: t("time.fiveMinutes") },
+ { _id: 10, name: t("time.tenMinutes") },
+ { _id: 20, name: t("time.twentyMinutes") },
+ { _id: 60, name: t("time.oneHour") },
+ { _id: 1440, name: t("time.oneDay") },
+ { _id: 10080, name: t("time.oneWeek") },
+ ];
+
+ const { user } = useSelector((state) => state.auth);
+ const { statusColor, pagespeedStatusMsg, determineState } = useMonitorUtils();
+ const [notifications, notificationsAreLoading, notificationsError] =
+ useGetNotificationsByTeamId();
+
+ // Hooks for API actions
+ const [isLoading] = useFetchMonitorById({ monitorId, setMonitor, updateTrigger });
const [createMonitor, isCreating] = useCreateMonitor();
+ const [deleteMonitor, isDeleting] = useDeleteMonitor();
+ const [updateMonitor, isUpdating] = useUpdateMonitor();
+ const [pauseMonitor, isPausing] = usePauseMonitor();
// Handlers
const onSubmit = async (event) => {
event.preventDefault();
- let form = {
- url: `http${https ? "s" : ""}://` + monitor.url,
- name: monitor.name === "" ? monitor.url : monitor.name,
- type: monitor.type,
- interval: monitor.interval * MS_PER_MINUTE,
- };
+ if (isCreate) {
+ let form = {
+ url: `http${https ? "s" : ""}://` + monitor.url,
+ name: monitor.name === "" ? monitor.url : monitor.name,
+ type: monitor.type,
+ interval: monitor.interval,
+ };
- const { error } = monitorValidation.validate(form, {
- abortEarly: false,
- });
+ const { error } = monitorValidation.validate(form, { abortEarly: false });
+ if (error) {
+ const newErrors = {};
+ error.details.forEach((err) => {
+ newErrors[err.path[0]] = err.message;
+ });
+ setErrors(newErrors);
+ createToast({ body: t("checkFormError") });
+ return;
+ }
- if (error) {
- const newErrors = {};
- error.details.forEach((err) => {
- newErrors[err.path[0]] = err.message;
- });
- setErrors(newErrors);
- createToast({ body: "Please check the form for errors." });
- return;
+ form = {
+ ...form,
+ description: form.name,
+ notifications: monitor.notifications,
+ };
+ await createMonitor({ monitor: form, redirect: "/pagespeed" });
+ } else {
+ const monitorParams = {
+ url: monitor.url,
+ name: monitor.name === "" ? monitor.url : monitor.name,
+ type: monitor.type,
+ interval: monitor.interval,
+ };
+ const { error } = monitorValidation.validate(monitorParams, { abortEarly: false });
+ if (error) {
+ const newErrors = {};
+ error.details.forEach((err) => {
+ newErrors[err.path[0]] = err.message;
+ });
+ setErrors(newErrors);
+ createToast({ body: t("checkFormError") });
+ return;
+ }
+ await updateMonitor({ monitor, redirect: "/pagespeed" });
}
-
- form = {
- ...form,
- description: form.name,
- notifications: monitor.notifications,
- };
-
- await createMonitor({ monitor: form, redirect: "/pagespeed" });
};
const handleChange = (event) => {
- const { value, name } = event.target;
+ let { value, name } = event.target;
+
+ if (name === "interval") {
+ value = value * MS_PER_MINUTE;
+ }
+
setMonitor({
...monitor,
[name]: value,
@@ -103,7 +155,6 @@ const CreatePageSpeed = () => {
{ [name]: value },
{ abortEarly: false }
);
-
setErrors((prev) => ({
...prev,
...(error ? { [name]: error.details[0].message } : { [name]: undefined }),
@@ -111,59 +162,179 @@ const CreatePageSpeed = () => {
};
const handleBlur = (event) => {
- const { name } = event.target;
- if (name === "url") {
- const { value } = event.target;
- if (monitor.name !== "") {
- return;
- }
- setMonitor((prev) => ({
- ...prev,
- name: parseDomainName(value),
- }));
+ const { name, value } = event.target;
+ if (name === "url" && monitor.name === "") {
+ setMonitor((prev) => ({ ...prev, name: parseDomainName(value) }));
}
};
- const { t } = useTranslation();
+ const triggerUpdate = () => {
+ setUpdateTrigger(!updateTrigger);
+ };
+
+ const handlePause = async () => {
+ await pauseMonitor({ monitorId, triggerUpdate });
+ };
+
+ const handleRemove = async (event) => {
+ event.preventDefault();
+ await deleteMonitor({ monitor, redirect: "/pagespeed" });
+ };
+
+ const isBusy = isLoading || isCreating || isDeleting || isUpdating || isPausing;
+
+ if (Object.keys(monitor).length === 0) {
+ return ;
+ }
return (
-
-
- {t("createYour")}{" "}
-
-
- {t("pageSpeedMonitor")}
-
-
+
+
+
+ {!isCreate ? monitor.name : t("createYour") + " "}
+
+ {isCreate ? (
+
+ {t("pageSpeedMonitor")}
+
+ ) : (
+ <>>
+ )}
+
+ {!isCreate && (
+
+
+
+
+
+
+
+ {monitor.url?.replace(/^https?:\/\//, "") || "..."}
+
+
+ {t("editing")}
+
+
+ )}
+
+ {!isCreate && (
+
+
+
+
+ )}
+
{
>
{t("settingsGeneralSettings")}
- {t("distributedUptimeCreateSelectURL")}
+
+ {t("pageSpeedConfigureSettingsDescription")}
+
-
+ .Mui-disabled)": {
+ backgroundColor: theme.palette.tertiary.main,
+ },
+ }}
+ >
}
- placeholder="google.com"
- value={monitor.url}
+ label={!isCreate ? t("url") : t("urlMonitor")}
+ startAdornment={isCreate ? : undefined}
+ placeholder="random.website.com"
+ value={monitor.url || ""}
onChange={handleChange}
- onBlur={handleBlur}
- error={errors["url"] ? true : false}
+ onBlur={isCreate ? handleBlur : undefined}
+ error={!!errors["url"]}
helperText={errors["url"]}
+ disabled={!isCreate}
/>
-
-
-
- {t("distributedUptimeCreateChecks")}
-
-
- {t("distributedUptimeCreateChecksDescription")}
-
-
-
-
-
-
-
-
-
+ {isCreate && (
+
+
+
+ {t("distributedUptimeCreateChecks")}
+
+
+ {t("distributedUptimeCreateChecksDescription")}
+
+
+
+
+
+
+
+
+
+
+ {errors["type"] ? (
+
+
+ {errors["type"]}
+
+
+ ) : (
+ ""
+ )}
- {errors["type"] ? (
-
-
- {errors["type"]}
-
-
- ) : (
- ""
- )}
-
-
+
+ )}
{
@@ -280,33 +463,47 @@ const CreatePageSpeed = () => {
{t("distributedUptimeCreateAdvancedSettings")}
-
+
+ {!isCreate && (
+