diff --git a/src/Components/FilterHeader/index.jsx b/src/Components/FilterHeader/index.jsx
index 46a17221b..96c151db0 100644
--- a/src/Components/FilterHeader/index.jsx
+++ b/src/Components/FilterHeader/index.jsx
@@ -1,108 +1,78 @@
-import {
- Checkbox,
- FormControl,
- InputLabel,
- ListItemText,
- MenuItem,
- Select,
-} from "@mui/material";
+import { Checkbox, FormControl, ListItemText, MenuItem, Select } from "@mui/material";
import { useTheme } from "@emotion/react";
import PropTypes from "prop-types";
import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline";
+/**
+ * A reusable filter header component that displays a dropdown menu with selectable options.
+ *
+ * @component
+ * @param {Object} props - The component props.
+ * @param {string} props.header - The header text to display when no options are selected.
+ * @param {Array} props.options - An array of options to display in the dropdown menu. Each option should have a `value` and `label`.
+ * @param {Array} [props.value] - The currently selected values.
+ * @param {Function} props.onChange - The callback function to handle changes in the selected values.
+ * @param {boolean} [props.multiple=true] - Whether multiple options can be selected.
+ * @returns {JSX.Element} The rendered FilterHeader component.
+ */
+
const FilterHeader = ({ header, options, value, onChange, multiple = true }) => {
const theme = useTheme();
- const selectStyles = {
- "& .MuiOutlinedInput-input": {
- color: theme.palette.primary.contrastText,
- },
- "& .MuiOutlinedInput-notchedOutline": {
- borderColor: theme.palette.primary.lowContrast,
- borderRadius: theme.shape.borderRadius,
- },
- "& .MuiSelect-icon": {
- color: theme.palette.primary.contrastText,
- },
- "&:hover": {
- backgroundColor: theme.palette.primary.main,
- },
- "&:hover .MuiOutlinedInput-notchedOutline": {
- borderColor: theme.palette.primary.lowContrast,
- },
- };
-
- const menuItemStyles = {
- "&:hover": {
- backgroundColor: theme.palette.secondary.main,
- },
- };
-
return (
-
-
+
-
+
+
+ ))}
+
+
);
};
FilterHeader.propTypes = {
- header: PropTypes.string,
- options: PropTypes.arrayOf(PropTypes.string),
+ header: PropTypes.string.isRequired,
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ value: PropTypes.string.isRequired,
+ label: PropTypes.string.isRequired,
+ })
+ ).isRequired,
value: PropTypes.arrayOf(PropTypes.string),
- onChange: PropTypes.func,
+ onChange: PropTypes.func.isRequired,
multiple: PropTypes.bool,
};
diff --git a/src/Pages/Uptime/Monitors/Components/Filter/index.jsx b/src/Pages/Uptime/Monitors/Components/Filter/index.jsx
index 7a8798e6a..f99ac3980 100644
--- a/src/Pages/Uptime/Monitors/Components/Filter/index.jsx
+++ b/src/Pages/Uptime/Monitors/Components/Filter/index.jsx
@@ -1,30 +1,61 @@
import { useTheme } from "@emotion/react";
import PropTypes from "prop-types";
import FilterHeader from "../../../../../Components/FilterHeader";
-import { useMemo, useState } from "react";
+import { useMemo } from "react";
import { Box, Button } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
+import { useTranslation } from "react-i18next";
-const Filter = ({ selectedTypes, setSelectedTypes, setToFilterStatus, setToFilterActive }) => {
+/**
+ * Filter Component
+ *
+ * A high-level component that provides filtering options for type, status, and state.
+ * It allows users to select multiple options for each filter and reset the filters.
+ *
+ * @component
+ * @param {Object} props - The component props.
+ * @param {string[]} props.selectedTypes - An array of selected type values.
+ * @param {function} props.setSelectedTypes - A function to set the selected type values.
+ * @param {string[]} props.selectedStatus - An array of selected status values.
+ * @param {function} props.setSelectedStatus - A function to set the selected status values.
+ * @param {string[]} props.selectedState - An array of selected state values.
+ * @param {function} props.setSelectedState - A function to set the selected state values.
+ * @param {function} props.setToFilterStatus - A function to set the filter status based on selected status values.
+ * @param {function} props.setToFilterActive - A function to set the filter active state based on selected state values.
+ * @param {function} props.handleReset - A function to reset all filters.
+ *
+ * @returns {JSX.Element} The rendered Filter component.
+ */
+
+const Filter = ({
+ selectedTypes,
+ setSelectedTypes,
+ selectedStatus,
+ setSelectedStatus,
+ selectedState,
+ setSelectedState,
+ setToFilterStatus,
+ setToFilterActive,
+ handleReset,
+}) => {
const theme = useTheme();
-
- const [selectedState, setSelectedState] = useState([]);
- const [selectedStatus, setSelectedStatus] = useState([]);
+ const { t } = useTranslation();
const handleTypeChange = (event) => {
- setSelectedTypes(event.target.value);
+ const selectedValues = event.target.value;
+ setSelectedTypes(selectedValues.length > 0 ? selectedValues : undefined);
};
const handleStatusChange = (event) => {
const selectedValues = event.target.value;
- setSelectedStatus(selectedValues);
+ setSelectedStatus(selectedValues.length > 0 ? selectedValues : undefined);
if (selectedValues.length === 0 || selectedValues.length === 2) {
setToFilterStatus(null);
} else {
setToFilterStatus(selectedValues[0] === "Up" ? "true" : "false");
}
- }
+ };
const handleStateChange = (event) => {
const selectedValues = event.target.value;
@@ -37,21 +68,30 @@ const Filter = ({ selectedTypes, setSelectedTypes, setToFilterStatus, setToFilte
}
};
- const handleReset = () => {
- setSelectedState([]);
- setSelectedTypes([]);
- setSelectedStatus([]);
- setToFilterStatus(null);
- setToFilterActive(null);
- };
-
const isFilterActive = useMemo(() => {
- return selectedTypes.length > 0 || selectedState.length > 0 || selectedStatus.length > 0;
+ return (
+ (selectedTypes?.length ?? 0) > 0 ||
+ (selectedState?.length ?? 0) > 0 ||
+ (selectedStatus?.length ?? 0) > 0
+ );
}, [selectedState, selectedTypes, selectedStatus]);
- const typeOptions = ["http", "ping", "docker", "port"];
- const statusOptions = ["Up", "Down"];
- const stateOptions = ["Active", "Paused"];
+ const typeOptions = [
+ { value: "http", label: "HTTP(S)" },
+ { value: "ping", label: "Ping" },
+ { value: "docker", label: "Docker" },
+ { value: "port", label: "Port" },
+ ];
+
+ const statusOptions = [
+ { value: "Up", label: "Up" },
+ { value: "Down", label: "Down" },
+ ];
+
+ const stateOptions = [
+ { value: "Active", label: "Active" },
+ { value: "Paused", label: "Paused" },
+ ];
return (
+
+
+
}
sx={{
- "&:hover": {
- backgroundColor: theme.palette.primary.lowContrast,
- },
visibility: isFilterActive ? "visible" : "hidden",
}}
>
- Reset
+ {t("reset")}
-
-
-
);
};
Filter.propTypes = {
- selectedTypes: PropTypes.arrayOf(PropTypes.string),
- setSelectedTypes: PropTypes.func,
- setToFilterStatus: PropTypes.func,
- setToFilterActive: PropTypes.func,
+ selectedTypes: PropTypes.arrayOf(PropTypes.string).isRequired,
+ setSelectedTypes: PropTypes.func.isRequired,
+ selectedStatus: PropTypes.arrayOf(PropTypes.string).isRequired,
+ setSelectedStatus: PropTypes.func.isRequired,
+ selectedState: PropTypes.arrayOf(PropTypes.string).isRequired,
+ setSelectedState: PropTypes.func.isRequired,
+ setToFilterStatus: PropTypes.func.isRequired,
+ setToFilterActive: PropTypes.func.isRequired,
+ handleReset: PropTypes.func.isRequired,
};
export default Filter;
diff --git a/src/Pages/Uptime/Monitors/index.jsx b/src/Pages/Uptime/Monitors/index.jsx
index 8d339a734..d90e525d2 100644
--- a/src/Pages/Uptime/Monitors/index.jsx
+++ b/src/Pages/Uptime/Monitors/index.jsx
@@ -70,7 +70,9 @@ const UptimeMonitors = () => {
const [sort, setSort] = useState(undefined);
const [isSearching, setIsSearching] = useState(false);
const [monitorUpdateTrigger, setMonitorUpdateTrigger] = useState(false);
- const [selectedTypes, setSelectedTypes] = useState([]);
+ const [selectedTypes, setSelectedTypes] = useState(undefined);
+ const [selectedState, setSelectedState] = useState(undefined);
+ const [selectedStatus, setSelectedStatus] = useState(undefined);
const [toFilterStatus, setToFilterStatus] = useState(null);
const [toFilterActive, setToFilterActive] = useState(null);
@@ -107,19 +109,28 @@ const UptimeMonitors = () => {
types: TYPES,
monitorUpdateTrigger,
});
-
- let field = sort?.field;
- let filter = search;
- if (toFilterStatus !== null) {
- field = "status";
- filter = toFilterStatus;
- } else if (toFilterActive !== null) {
- field = "isActive";
- filter = toFilterActive;
- } else {
- field = sort?.field;
- filter = search;
- }
+
+ const handleReset = () => {
+ setSelectedState(undefined);
+ setSelectedTypes(undefined);
+ setSelectedStatus(undefined);
+ setToFilterStatus(null);
+ setToFilterActive(null);
+ };
+
+ const field =
+ toFilterStatus !== null
+ ? "status"
+ : toFilterActive !== null
+ ? "isActive"
+ : sort?.field;
+
+ const filter =
+ toFilterStatus !== null
+ ? toFilterStatus
+ : toFilterActive !== null
+ ? toFilterActive
+ : search;
const [
monitorsWithChecks,
@@ -199,9 +210,13 @@ const UptimeMonitors = () => {
({
},
},
},
+ MuiListItemText: {
+ styleOverrides: {
+ root: ({ theme }) => ({
+ "& .MuiTypography-root": {
+ color: theme.palette.primary.contrastText,
+ },
+ }),
+ },
+ },
MuiMenuItem: {
styleOverrides: {
root: ({ theme }) => ({
@@ -453,6 +462,28 @@ const baseTheme = (palette) => ({
}),
},
},
+ MuiSelect: {
+ styleOverrides: {
+ root: ({ theme }) => ({
+ "& .MuiOutlinedInput-input": {
+ color: theme.palette.primary.contrastText,
+ },
+ "& .MuiOutlinedInput-notchedOutline": {
+ borderColor: theme.palette.primary.lowContrast,
+ borderRadius: theme.shape.borderRadius,
+ },
+ "& .MuiSelect-icon": {
+ color: theme.palette.primary.contrastTextSecondary, // Dropdown + color
+ },
+ "&:hover": {
+ backgroundColor: theme.palette.primary.main, // Background on hover
+ },
+ "&:hover .MuiOutlinedInput-notchedOutline": {
+ borderColor: theme.palette.primary.lowContrast,
+ },
+ }),
+ },
+ },
MuiButtonGroup: {
styleOverrides: {
root: ({ theme }) => ({
diff --git a/src/locales/gb.json b/src/locales/gb.json
index 05a4bdc8e..cc22e6b80 100644
--- a/src/locales/gb.json
+++ b/src/locales/gb.json
@@ -111,6 +111,7 @@
"configure": "Configure",
"networkError": "Network error",
"responseTime": "Response time:",
+ "reset": "Reset",
"ms": "ms",
"bar": "Bar",
"area": "Area",
@@ -316,6 +317,7 @@
"statusCode": "Status code",
"date&Time": "Date & Time",
"type": "Type",
+ "state": "State",
"statusPageName": "Status page name",
"publicURL": "Public URL",
"repeat": "Repeat",