From f799d460257764e68c84f430b54afd785eabc33f Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 3 Feb 2026 21:29:02 +0000 Subject: [PATCH] cleanup, style picler --- .../src/Components/v2/inputs/ColorPicker.tsx | 48 +++ client/src/Components/v2/inputs/index.tsx | 1 + .../Create/Components/MonitorList/index.jsx | 110 ------- .../Create/Components/Progress/index.jsx | 43 --- .../Create/Components/Skeleton/index.jsx | 14 - .../Create/Components/Tabs/ConfigStack.jsx | 31 -- .../Create/Components/Tabs/Content.jsx | 107 ------ .../Create/Components/Tabs/Settings.jsx | 187 ----------- .../Create/Components/Tabs/index.jsx | 99 ------ .../Create/Hooks/useCreateStatusPage.jsx | 25 -- .../Create/Hooks/useMonitorsFetch.jsx | 33 -- client/src/Pages/StatusPage/Create/index.tsx | 6 +- client/src/Pages/StatusPage/Create/old.jsx | 311 ------------------ .../Status/Hooks/useStatusPageDelete.jsx | 43 --- .../Status/Hooks/useStatusPageFetch.jsx | 53 --- client/src/locales/en.json | 20 -- 16 files changed, 52 insertions(+), 1079 deletions(-) create mode 100644 client/src/Components/v2/inputs/ColorPicker.tsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Progress/index.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx delete mode 100644 client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx delete mode 100644 client/src/Pages/StatusPage/Create/old.jsx delete mode 100644 client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx delete mode 100644 client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx diff --git a/client/src/Components/v2/inputs/ColorPicker.tsx b/client/src/Components/v2/inputs/ColorPicker.tsx new file mode 100644 index 000000000..f52e66317 --- /dev/null +++ b/client/src/Components/v2/inputs/ColorPicker.tsx @@ -0,0 +1,48 @@ +import { MuiColorInput } from "mui-color-input"; +import type { MuiColorInputProps } from "mui-color-input"; +import { typographyLevels } from "@/Utils/Theme/v2Palette"; +import { useTheme } from "@mui/material"; +import Stack from "@mui/material/Stack"; +import { FieldLabel } from "@/Components/v2/inputs/FieldLabel"; + +interface ColorPickerProps extends MuiColorInputProps { + fieldLabel?: string; + required?: boolean; +} + +export const ColorInput = ({ fieldLabel, required, ...props }: ColorPickerProps) => { + const theme = useTheme(); + const input = ( + + ); + if (fieldLabel) { + return ( + + {fieldLabel} + {input} + + ); + } + + return input; +}; diff --git a/client/src/Components/v2/inputs/index.tsx b/client/src/Components/v2/inputs/index.tsx index ad7c984bd..fa04903c9 100644 --- a/client/src/Components/v2/inputs/index.tsx +++ b/client/src/Components/v2/inputs/index.tsx @@ -13,3 +13,4 @@ export * from "./Radio"; export * from "./Switch"; export * from "./Slider"; export * from "./ImageUpload"; +export * from "./ColorPicker"; diff --git a/client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx b/client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx deleted file mode 100644 index 349571fe8..000000000 --- a/client/src/Pages/StatusPage/Create/Components/MonitorList/index.jsx +++ /dev/null @@ -1,110 +0,0 @@ -// Components -import { Stack, Typography } from "@mui/material"; -import Icon from "@/Components/v1/Icon"; - -// Utils -import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd"; -import { useTheme } from "@emotion/react"; -const MonitorListItem = ({ - monitor, - innerRef, - draggableProps, - dragHandleProps, - onDelete, -}) => { - const theme = useTheme(); - return ( - - - {monitor.name} - { - onDelete(monitor); - }} - /> - - ); -}; - -const MonitorList = ({ selectedMonitors, setSelectedMonitors }) => { - const onDelete = (monitorToDelete) => { - const newMonitors = selectedMonitors.filter( - (monitor) => monitor.id !== monitorToDelete.id - ); - setSelectedMonitors(newMonitors); - }; - const reorder = (list, startIndex, endIndex) => { - const result = Array.from(list); - const [removed] = result.splice(startIndex, 1); - result.splice(endIndex, 0, removed); - - return result; - }; - - const onDragEnd = (result) => { - // dropped outside the list - if (!result.destination) { - return; - } - - const reorderedMonitors = reorder( - selectedMonitors, - result.source.index, - result.destination.index - ); - - setSelectedMonitors(reorderedMonitors); - }; - - return ( - - - {(provided, snapshot) => ( - - {selectedMonitors?.map((monitor, index) => ( - - {(provided, snapshot) => ( - - )} - - ))} - {provided.placeholder} - - )} - - - ); -}; - -export default MonitorList; diff --git a/client/src/Pages/StatusPage/Create/Components/Progress/index.jsx b/client/src/Pages/StatusPage/Create/Components/Progress/index.jsx deleted file mode 100644 index 594fd9709..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Progress/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Button, Box } from "@mui/material"; -import ProgressUpload from "@/Components/v1/ProgressBars/index.jsx"; -import Icon from "@/Components/v1/Icon"; -import { useTranslation } from "react-i18next"; -import { formatBytes } from "../../../../../Utils/fileUtils.js"; -const Progress = ({ isLoading, progressValue, logo, logoType, removeLogo, errors }) => { - const { t } = useTranslation(); - if (isLoading) { - return ( - - } - label={logo?.name} - size={formatBytes(logo?.size)} - progress={progressValue} - onClick={removeLogo} - /> - ); - } - - if (logo && logoType) { - return ( - - - - ); - } -}; - -export default Progress; diff --git a/client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx b/client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx deleted file mode 100644 index 482c490fb..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Skeleton/index.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import { Stack, Skeleton } from "@mui/material"; - -const SkeletonLayout = () => { - return ( - - - - ); -}; - -export default SkeletonLayout; diff --git a/client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx deleted file mode 100644 index f31c456ef..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Stack, Typography } from "@mui/material"; -import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; -import PropTypes from "prop-types"; -import { useTheme } from "@emotion/react"; - -// This can be used to add any extra/additional section/stacks on top of existing sections on the tab -const ConfigStack = ({ title, description, children }) => { - const theme = useTheme(); - return ( - - - - {title} - - {description} - - {children} - - ); -}; - -ConfigStack.propTypes = { - title: PropTypes.string.isRequired, // Title must be a string and is required - description: PropTypes.string.isRequired, // Description must be a string and is required - children: PropTypes.node.isRequired, -}; - -export default ConfigStack; diff --git a/client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx deleted file mode 100644 index e84de16dc..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx +++ /dev/null @@ -1,107 +0,0 @@ -// Components -import { Stack, Typography } from "@mui/material"; -import { TabPanel } from "@mui/lab"; -import MonitorList from "../MonitorList/index.jsx"; -import Search from "@/Components/v1/Inputs/Search/index.jsx"; -import Checkbox from "@/Components/v1/Inputs/Checkbox/index.jsx"; -// Utils -import { useState } from "react"; -import { useTheme } from "@emotion/react"; -import { useTranslation } from "react-i18next"; -import ConfigStack from "./ConfigStack.jsx"; -const Content = ({ - tabValue, - form, - monitors, - handleFormChange, - errors, - selectedMonitors, - setSelectedMonitors, -}) => { - // Local state - const [search, setSearch] = useState(""); - - // Handlers - const handleMonitorsChange = (selectedMonitors) => { - handleFormChange({ - target: { name: "monitors", value: selectedMonitors.map((monitor) => monitor.id) }, - }); - setSelectedMonitors(selectedMonitors); - }; - - // Utils - const theme = useTheme(); - const { t } = useTranslation(); - - return ( - - - - - - - - - {errors["monitors"]} - - - - - - - - - - - - - - ); -}; - -export default Content; diff --git a/client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx deleted file mode 100644 index d4c583d3a..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx +++ /dev/null @@ -1,187 +0,0 @@ -// Components -import { Stack, Typography } from "@mui/material"; -import { TabPanel } from "@mui/lab"; -import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; -import Checkbox from "@/Components/v1/Inputs/Checkbox/index.jsx"; -import TextInput from "@/Components/v1/Inputs/TextInput/index.jsx"; -import Search from "@/Components/v1/Inputs/Search/index.jsx"; -import ImageUpload from "@/Components/v1/Inputs/ImageUpload/index.jsx"; -import ColorPicker from "@/Components/v1/Inputs/ColorPicker/index.jsx"; -import Progress from "../Progress/index.jsx"; - -// Utils -import { useTheme } from "@emotion/react"; -import timezones from "../../../../../Utils/timezones.json"; -import PropTypes from "prop-types"; -import { useTranslation } from "react-i18next"; -import { useMemo, useState, useCallback } from "react"; - -const TabSettings = ({ - isCreate, - tabValue, - form, - handleFormChange, - handleImageChange, - progress, - removeLogo, - errors, -}) => { - // Utils - const theme = useTheme(); - const { t } = useTranslation(); - const [rawInput, setRawInput] = useState(""); - - const selectedTimezone = useMemo( - () => timezones.find((tz) => tz._id === form.timezone) ?? null, - [form.timezone] - ); - - const handleTimezoneChange = useCallback( - (newValue) => { - setRawInput(""); - handleFormChange({ - target: { - name: "timezone", - value: newValue?._id ?? "", - }, - }); - }, - [handleFormChange] - ); - - return ( - - - - - - {t("access")} - - {t("statusPageCreateSettings")} - - - - - - - - - {t("basicInformation")} - - - {t("statusPageCreateBasicInfoDescription")} - - - - - - - - - - - {t("timezone")} - - - {t("statusPageCreateSelectTimeZoneDescription")} - - - - setRawInput(newVal)} - handleChange={handleTimezoneChange} - isAdorned={true} - unit="timezone" - /> - - - - - - {t("statusPageCreateAppearanceTitle")} - - - {t("statusPageCreateAppearanceDescription")} - - - - - - - - - - - ); -}; - -TabSettings.propTypes = { - isCreate: PropTypes.bool, - tabValue: PropTypes.string, - form: PropTypes.object, - handleFormChange: PropTypes.func, - handleImageChange: PropTypes.func, - progress: PropTypes.object, - removeLogo: PropTypes.func, - errors: PropTypes.object, -}; - -export default TabSettings; diff --git a/client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx b/client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx deleted file mode 100644 index e8669c474..000000000 --- a/client/src/Pages/StatusPage/Create/Components/Tabs/index.jsx +++ /dev/null @@ -1,99 +0,0 @@ -// Components -import { TabContext } from "@mui/lab"; -import { Tab } from "@mui/material"; -import Settings from "./Settings.jsx"; -import Content from "./Content.jsx"; - -// Utils -import PropTypes from "prop-types"; -import CustomTabList from "@/Components/v1/Tab/index.jsx"; - -const Tabs = ({ - isCreate, - form, - errors, - monitors, - selectedMonitors, - setSelectedMonitors, - handleFormChange, - handleImageChange, - progress, - removeLogo, - tab, - setTab, - TAB_LIST, - handleDelete, - isDeleteOpen, - setIsDeleteOpen, - isDeleting, - isLoading, -}) => { - return ( - - { - setTab(TAB_LIST.indexOf(selected)); - }} - aria-label="status page tabs" - > - {TAB_LIST.map((tabLabel) => ( - - ))} - - {tab === 0 ? ( - - ) : ( - - )} - - ); -}; - -Tabs.propTypes = { - isCreate: PropTypes.bool, - form: PropTypes.object, - errors: PropTypes.object, - monitors: PropTypes.array, - selectedMonitors: PropTypes.array, - setSelectedMonitors: PropTypes.func, - handleFormChange: PropTypes.func, - handleImageChange: PropTypes.func, - progress: PropTypes.object, - removeLogo: PropTypes.func, - tab: PropTypes.number, - setTab: PropTypes.func, - TAB_LIST: PropTypes.array, - handleDelete: PropTypes.func, - isDeleteOpen: PropTypes.bool, - setIsDeleteOpen: PropTypes.func, - isDeleting: PropTypes.bool, - isLoading: PropTypes.bool, -}; - -export default Tabs; diff --git a/client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx b/client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx deleted file mode 100644 index c0bcf5ab4..000000000 --- a/client/src/Pages/StatusPage/Create/Hooks/useCreateStatusPage.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useState } from "react"; -import { networkService } from "../../../../main.jsx"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; - -const useCreateStatusPage = (isCreate) => { - const [isLoading, setIsLoading] = useState(false); - const [networkError, setNetworkError] = useState(false); - const createStatusPage = async ({ form, id }) => { - setIsLoading(true); - try { - await networkService.createStatusPage({ form, isCreate, id }); - return true; - } catch (error) { - setNetworkError(true); - createToast({ body: error?.response?.data?.msg ?? error.message }); - return false; - } finally { - setIsLoading(false); - } - }; - - return [createStatusPage, isLoading, networkError]; -}; - -export { useCreateStatusPage }; diff --git a/client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx b/client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx deleted file mode 100644 index 03ebb07bf..000000000 --- a/client/src/Pages/StatusPage/Create/Hooks/useMonitorsFetch.jsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useEffect, useState } from "react"; -import { networkService } from "../../../../main.jsx"; -import { useSelector } from "react-redux"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; - -const useMonitorsFetch = () => { - const { user } = useSelector((state) => state.auth); - - const [monitors, setMonitors] = useState(undefined); - const [isLoading, setIsLoading] = useState(true); - const [networkError, setNetworkError] = useState(false); - useEffect(() => { - const fetchMonitors = async () => { - try { - const response = await networkService.getMonitorsByTeamId({ - limit: null, // donot return any checks for the monitors - types: ["http", "ping", "port", "game"], // include game servers in status page monitor selection - }); - setMonitors(response.data.data); - } catch (error) { - setNetworkError(true); - createToast({ body: error.message }); - } finally { - setIsLoading(false); - } - }; - fetchMonitors(); - }, [user]); - - return [monitors, isLoading, networkError]; -}; - -export { useMonitorsFetch }; diff --git a/client/src/Pages/StatusPage/Create/index.tsx b/client/src/Pages/StatusPage/Create/index.tsx index 83286277b..f5eff80ca 100644 --- a/client/src/Pages/StatusPage/Create/index.tsx +++ b/client/src/Pages/StatusPage/Create/index.tsx @@ -14,6 +14,7 @@ import { Autocomplete, Checkbox, Dialog, + ColorInput, } from "@/Components/v2/inputs"; import { useTheme } from "@mui/material/styles"; @@ -29,7 +30,6 @@ import type { StatusPageResponse } from "@/Types/StatusPage"; import timezones from "@/Utils/timezones.json"; import { useNavigate, useParams } from "react-router-dom"; import axios from "axios"; -import { MuiColorInput } from "mui-color-input"; import { HeaderConfigStatusControls } from "./Components/HeaderConfigStatusControls"; interface TimezoneOption { @@ -393,11 +393,11 @@ const CreateStatusPage = () => { name="color" control={control} render={({ field }) => ( - )} /> diff --git a/client/src/Pages/StatusPage/Create/old.jsx b/client/src/Pages/StatusPage/Create/old.jsx deleted file mode 100644 index c5aee4b0a..000000000 --- a/client/src/Pages/StatusPage/Create/old.jsx +++ /dev/null @@ -1,311 +0,0 @@ -// Components -import { Stack, Button, Typography } from "@mui/material"; -import Tabs from "./Components/Tabs/index.jsx"; -import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; -import SkeletonLayout from "./Components/Skeleton/index.jsx"; -import Dialog from "@/Components/v1/Dialog/index.jsx"; -import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -//Utils -import { useTheme } from "@emotion/react"; -import { useState, useEffect, useRef, useCallback } from "react"; -import { statusPageValidation } from "../../../Validation/validation.js"; -import { buildErrors } from "../../../Validation/error.js"; -import { useMonitorsFetch } from "./Hooks/useMonitorsFetch.jsx"; -import { useCreateStatusPage } from "./Hooks/useCreateStatusPage.jsx"; -import { createToast } from "../../../Utils/toastUtils.jsx"; -import { useNavigate } from "react-router-dom"; -import { useStatusPageFetch } from "../Status/Hooks/useStatusPageFetch.jsx"; -import { useParams } from "react-router-dom"; -import { useTranslation } from "react-i18next"; -//Constants -const ERROR_TAB_MAPPING = [ - ["companyName", "url", "timezone", "color", "isPublished", "logo"], - ["monitors", "showUptimePercentage", "showCharts", "showAdminLoginLink"], -]; - -const CreateStatusPage = () => { - const { url } = useParams(); - //Local state - const [tab, setTab] = useState(0); - const [progress, setProgress] = useState({ value: 0, isLoading: false }); - const [isDeleteOpen, setIsDeleteOpen] = useState(false); - const [form, setForm] = useState({ - isPublished: false, - companyName: "", - url: url ?? Math.floor(Math.random() * 1000000).toFixed(0), - logo: undefined, - timezone: "America/Toronto", - color: "#4169E1", - type: "uptime", - monitors: [], - showCharts: true, - showUptimePercentage: true, - showAdminLoginLink: false, - }); - const [errors, setErrors] = useState({}); - const [selectedMonitors, setSelectedMonitors] = useState([]); - // Refs - const intervalRef = useRef(null); - - // Setup - const isCreate = typeof url === "undefined"; - - //Utils - const theme = useTheme(); - const [monitors, isLoading, networkError] = useMonitorsFetch(); - const navigate = useNavigate(); - const { t } = useTranslation(); - - const [createStatusPage] = useCreateStatusPage(isCreate); - const [statusPage, statusPageMonitors, statusPageIsLoading, , fetchStatusPage] = - useStatusPageFetch(isCreate, url); - // const [deleteStatusPage, isDeleting] = useStatusPageDelete(fetchStatusPage, url); - - // Handlers - const handleFormChange = (e) => { - let { type, name, value, checked } = e.target; - // Handle errors - const { error } = statusPageValidation.validate( - { [name]: value }, - { abortEarly: false } - ); - setErrors((prev) => { - return buildErrors(prev, name, error); - }); - - //Handle checkbox - if (type === "checkbox") { - setForm((prev) => ({ - ...prev, - [name]: checked, - })); - return; - } - - // Handle other inputs - setForm((prev) => ({ - ...prev, - [name]: value, - })); - }; - - const handleImageChange = useCallback((fileObj) => { - if (!fileObj || !fileObj.file) return; - - setForm((prev) => ({ - ...prev, - logo: { - src: fileObj.src, - name: fileObj.name, - type: fileObj.file.type, - size: fileObj.file.size, - }, - })); - - intervalRef.current = setInterval(() => { - const buffer = 12; - setProgress((prev) => { - if (prev.value + buffer >= 100) { - clearInterval(intervalRef.current); - return { value: 100, isLoading: false }; - } - return { ...prev, value: prev.value + buffer }; - }); - }, 120); - }, []); - - const removeLogo = () => { - setForm((prev) => ({ - ...prev, - logo: undefined, - })); - // interrupt interval if image upload is canceled prior to completing the process - clearInterval(intervalRef.current); - setProgress({ value: 0, isLoading: false }); - }; - - /** - * Handle status page deletion with optimistic UI update - * Immediately navigates away without waiting for the deletion to complete - * to prevent unnecessary network requests for the deleted page - */ - const handleDelete = async () => { - setIsDeleteOpen(false); - // Start deletion process but don't wait for it - // deleteStatusPage(); - // Immediately navigate away to prevent additional fetches for the deleted page - navigate("/status"); - }; - - const handleSubmit = async () => { - let toSubmit = { - ...form, - logo: { type: form.logo?.type ?? null, size: form.logo?.size ?? null }, - }; - - const { error } = statusPageValidation.validate(toSubmit, { - abortEarly: false, - }); - - if (typeof error === "undefined") { - const success = await createStatusPage({ form, id: statusPage?.id }); - if (success) { - createToast({ - body: isCreate ? t("statusPage.createSuccess") : t("statusPage.updateSuccess"), - }); - navigate(`/status/uptime/${form.url}`); - } - return; - } - - const newErrors = {}; - error?.details?.forEach((err) => { - newErrors[err.path[0]] = err.message; - }); - setErrors((prev) => ({ ...prev, ...newErrors })); - const errorTabs = Object.keys(newErrors).map((err) => { - return ERROR_TAB_MAPPING.findIndex((tab) => tab.includes(err)); - }); - - // If there's an error in the current tab, don't change the tab - if (errorTabs.some((errorTab) => errorTab === tab)) { - return; - } - - // If we get -1, there's an unknown error - if (errorTabs[0] === -1) { - createToast({ body: t("common.toasts.unknownError") }); - return; - } - - // Otherwise go to tab with error - setTab(errorTabs[0]); - }; - - // If we are configuring, populate fields - useEffect(() => { - if (isCreate) return; - if (typeof statusPage === "undefined") { - return; - } - - let newLogo = undefined; - if (statusPage.logo && Object.keys(statusPage.logo).length > 0) { - newLogo = { - src: `data:${statusPage.logo.contentType};base64,${statusPage.logo.data}`, - name: "logo", - type: statusPage.logo.contentType, - size: null, - }; - } - setForm((prev) => { - return { - ...prev, - companyName: statusPage?.companyName, - isPublished: statusPage?.isPublished, - timezone: statusPage?.timezone, - monitors: statusPageMonitors.map((monitor) => monitor.id), - color: statusPage?.color, - logo: newLogo, - showCharts: statusPage?.showCharts ?? true, - showUptimePercentage: statusPage?.showUptimePercentage ?? true, - showAdminLoginLink: statusPage?.showAdminLoginLink ?? false, - }; - }); - setSelectedMonitors(statusPageMonitors); - }, [isCreate, statusPage, statusPageMonitors]); - - if (networkError === true) { - return ( - - - {t("common.toasts.networkError")} - - {t("common.toasts.checkConnection")} - - ); - } - - if (isLoading) return ; - - // Load fields - return ( - - - {!isCreate && ( - - - setIsDeleteOpen(false)} - open={isDeleteOpen} - confirmationButtonLabel={t("deleteStatusPageConfirm")} - description={t("deleteStatusPageDescription")} - // isLoading={isDeleting || statusPageIsLoading} - /> - - )} - - - - - - ); -}; - -export default CreateStatusPage; diff --git a/client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx deleted file mode 100644 index 73b9a8a5f..000000000 --- a/client/src/Pages/StatusPage/Status/Hooks/useStatusPageDelete.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import { useState } from "react"; -import { networkService } from "../../../../Utils/NetworkService.js"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; -import { useTranslation } from "react-i18next"; - -/** - * Hook for deleting a status page with optimistic UI update - * @param {Function} fetchStatusPage - Function to fetch status page data - * @param {string} url - URL of the status page - * @returns {Array} - [deleteStatusPage function, isLoading state] - */ -const useStatusPageDelete = (fetchStatusPage, url) => { - const [isLoading, setIsLoading] = useState(false); - const { t } = useTranslation(); - - /** - * Delete a status page with optimistic UI update - * @returns {Promise} - Success status - */ - const deleteStatusPage = async () => { - // We don't need to call fetchStatusPage after deletion - // This prevents the 404 error when trying to fetch a deleted status page - try { - setIsLoading(true); - await networkService.deleteStatusPage({ url }); - createToast({ - body: t("statusPage.deleteSuccess", "Status page deleted successfully"), - }); - return true; - } catch (error) { - createToast({ - body: t("statusPage.deleteFailed", "Failed to delete status page"), - }); - return false; - } finally { - setIsLoading(false); - } - }; - - return [deleteStatusPage, isLoading]; -}; - -export { useStatusPageDelete }; diff --git a/client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx b/client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx deleted file mode 100644 index 7db6b6c5e..000000000 --- a/client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect, useState, useCallback } from "react"; -import { networkService } from "../../../../main.jsx"; -import { useSelector } from "react-redux"; -import { createToast } from "../../../../Utils/toastUtils.jsx"; -import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils.js"; - -const useStatusPageFetch = (isCreate = false, url) => { - const [isLoading, setIsLoading] = useState(true); - const [networkError, setNetworkError] = useState(false); - const [statusPage, setStatusPage] = useState(undefined); - const [monitors, setMonitors] = useState(undefined); - const theme = useTheme(); - const { getMonitorWithPercentage } = useMonitorUtils(); - const fetchStatusPage = useCallback(async () => { - try { - const response = await networkService.getStatusPageByUrl({ - url, - type: "uptime", - }); - if (!response?.data?.data) return; - const { statusPage, monitors } = response.data.data; - setStatusPage(statusPage); - - const monitorsWithPercentage = monitors.map((monitor) => - getMonitorWithPercentage(monitor, theme) - ); - - setMonitors(monitorsWithPercentage); - } catch (error) { - // If there is a 404, status page is not found - if (error?.response?.status === 404) { - setStatusPage(undefined); - return; - } - createToast({ body: error.message }); - setNetworkError(true); - } finally { - setIsLoading(false); - } - }, [theme, getMonitorWithPercentage, url]); - - useEffect(() => { - if (isCreate === true) { - return; - } - fetchStatusPage(); - }, [isCreate, fetchStatusPage]); - - return [statusPage, monitors, isLoading, networkError, fetchStatusPage]; -}; - -export { useStatusPageFetch }; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 04eca42b0..a26f1808e 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -359,7 +359,6 @@ "errors": "Errors", "expectedValue": "Expected value", "failedToSendEmail": "Failed to send email", - "features": "Features", "FirstName": "First name", "frequency": "Frequency", "friendlyNameInput": "Friendly name", @@ -1044,7 +1043,6 @@ }, "rate": "Rate", "remove": "Remove", - "removeLogo": "Remove Logo", "repeat": "Repeat", "reset": "Reset", "response": "RESPONSE", @@ -1058,7 +1056,6 @@ }, "save": "Save", "selectAll": "Select all", - "settingsDisplayTimezone": "Display timezone", "settingsFailedToClearStats": "Failed to clear stats", "settingsFailedToDeleteMonitors": "Failed to delete all monitors", "settingsFailedToSave": "Failed to save settings", @@ -1151,25 +1148,18 @@ "settingsTestEmailFailedWithReason": "Failed to send test email: {{reason}}", "settingsTestEmailSuccess": "Test email sent successfully", "settingsTestEmailUnknownError": "Unknown error", - "showAdminLoginLink": "Show \"Administrator? Login Here\" link on the status page", - "showCharts": "Show charts", "shown": "Shown", - "showUptimePercentage": "Show uptime percentage", "starPromptDescription": "See the latest releases and help grow the community on GitHub", "starPromptTitle": "Star Checkmate", "startTime": "Start time", "state": "State", "status": "Status", - "statusBreadCrumbsDetails": "Details", - "statusBreadCrumbsStatusPages": "Status Pages", "statusCode": "Status code", "statusPage": { "contents": "Contents", - "createSuccess": "Status page created successfully", "deleteFailed": "Failed to delete status page", "deleteSuccess": "Status page deleted successfully", "generalSettings": "General settings", - "updateSuccess": "Status page updated successfully", "details": { "statusHeader": { "allUp": "All systems operational", @@ -1181,16 +1171,6 @@ "statusPageCreate": { "buttonSave": "Save" }, - "statusPageCreateAppearanceDescription": "Define the default look and feel of your public status page.", - "statusPageCreateAppearanceTitle": "Appearance", - "statusPageCreateBasicInfoDescription": "Define company name and the subdomain that your status page points to.", - "statusPageCreateBasicInfoStatusPageAddress": "Your status page address", - "statusPageCreateSelectTimeZoneDescription": "Select the timezone that your status page will be displayed in.", - "statusPageCreateSettings": "If your status page is ready, you can mark it as published.", - "statusPageCreateSettingsCheckboxLabel": "Published and visible to the public", - "statusPageCreateTabsContent": "Status page servers", - "statusPageCreateTabsContentDescription": "You can add any number of servers that you monitor to your status page. You can also reorder them for the best viewing experience.", - "statusPageCreateTabsContentFeaturesDescription": "Show more details on the status page", "statusPageStatusServiceStatus": "Service status", "submit": "Submit", "SupportedFormats": "Supported formats",