From 4ffb6832e2217e3cdf288472cbd83b96ea381fc3 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Fri, 28 Mar 2025 01:19:13 +0530 Subject: [PATCH] Feat: Uptime Monitor Filters --- src/Components/FilterHeader/index.jsx | 109 ++++++++++++++++++ .../Monitors/Components/Filter/index.jsx | 109 ++++++++++++++++++ .../Components/SearchComponent/index.jsx | 1 + src/Pages/Uptime/Monitors/index.jsx | 30 ++++- 4 files changed, 246 insertions(+), 3 deletions(-) create mode 100644 src/Components/FilterHeader/index.jsx create mode 100644 src/Pages/Uptime/Monitors/Components/Filter/index.jsx diff --git a/src/Components/FilterHeader/index.jsx b/src/Components/FilterHeader/index.jsx new file mode 100644 index 000000000..46a17221b --- /dev/null +++ b/src/Components/FilterHeader/index.jsx @@ -0,0 +1,109 @@ +import { + Checkbox, + FormControl, + InputLabel, + ListItemText, + MenuItem, + Select, +} from "@mui/material"; +import { useTheme } from "@emotion/react"; +import PropTypes from "prop-types"; +import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline"; + +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 ( +
+ + + {header} + + + +
+ ); +}; + +FilterHeader.propTypes = { + header: PropTypes.string, + options: PropTypes.arrayOf(PropTypes.string), + value: PropTypes.arrayOf(PropTypes.string), + onChange: PropTypes.func, + multiple: PropTypes.bool, +}; + +export default FilterHeader; diff --git a/src/Pages/Uptime/Monitors/Components/Filter/index.jsx b/src/Pages/Uptime/Monitors/Components/Filter/index.jsx new file mode 100644 index 000000000..7a8798e6a --- /dev/null +++ b/src/Pages/Uptime/Monitors/Components/Filter/index.jsx @@ -0,0 +1,109 @@ +import { useTheme } from "@emotion/react"; +import PropTypes from "prop-types"; +import FilterHeader from "../../../../../Components/FilterHeader"; +import { useMemo, useState } from "react"; +import { Box, Button } from "@mui/material"; +import ClearIcon from "@mui/icons-material/Clear"; + +const Filter = ({ selectedTypes, setSelectedTypes, setToFilterStatus, setToFilterActive }) => { + const theme = useTheme(); + + const [selectedState, setSelectedState] = useState([]); + const [selectedStatus, setSelectedStatus] = useState([]); + + const handleTypeChange = (event) => { + setSelectedTypes(event.target.value); + }; + + const handleStatusChange = (event) => { + const selectedValues = event.target.value; + setSelectedStatus(selectedValues); + + if (selectedValues.length === 0 || selectedValues.length === 2) { + setToFilterStatus(null); + } else { + setToFilterStatus(selectedValues[0] === "Up" ? "true" : "false"); + } + } + + const handleStateChange = (event) => { + const selectedValues = event.target.value; + setSelectedState(selectedValues); + + if (selectedValues.length === 0 || selectedValues.length === 2) { + setToFilterActive(null); + } else { + setToFilterActive(selectedValues[0] === "Active" ? "true" : "false"); + } + }; + + const handleReset = () => { + setSelectedState([]); + setSelectedTypes([]); + setSelectedStatus([]); + setToFilterStatus(null); + setToFilterActive(null); + }; + + const isFilterActive = useMemo(() => { + return selectedTypes.length > 0 || selectedState.length > 0 || selectedStatus.length > 0; + }, [selectedState, selectedTypes, selectedStatus]); + + const typeOptions = ["http", "ping", "docker", "port"]; + const statusOptions = ["Up", "Down"]; + const stateOptions = ["Active", "Paused"]; + + return ( + + + + + + + ); +}; + +Filter.propTypes = { + selectedTypes: PropTypes.arrayOf(PropTypes.string), + setSelectedTypes: PropTypes.func, + setToFilterStatus: PropTypes.func, + setToFilterActive: PropTypes.func, +}; + +export default Filter; diff --git a/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx b/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx index 749f921a8..0c6eec854 100644 --- a/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx +++ b/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx @@ -28,6 +28,7 @@ const SearchComponent = ({ monitors = [], onSearchChange, setIsSearching }) => { width="25%" minWidth={150} ml="auto" + mt={2} > { const [sort, setSort] = useState(undefined); const [isSearching, setIsSearching] = useState(false); const [monitorUpdateTrigger, setMonitorUpdateTrigger] = useState(false); + const [selectedTypes, setSelectedTypes] = useState([]); + const [toFilterStatus, setToFilterStatus] = useState(null); + const [toFilterActive, setToFilterActive] = useState(null); // Utils const theme = useTheme(); @@ -103,6 +107,19 @@ 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 [ monitorsWithChecks, @@ -111,12 +128,12 @@ const UptimeMonitors = () => { monitorsWithChecksNetworkError, ] = useFetchMonitorsWithChecks({ teamId, - types: TYPES, + types: selectedTypes && selectedTypes.length > 0 ? selectedTypes : TYPES, limit: 25, page: page, rowsPerPage: rowsPerPage, - filter: search, - field: sort?.field, + filter: filter, + field: field, order: sort?.order, monitorUpdateTrigger, }); @@ -179,6 +196,13 @@ const UptimeMonitors = () => { monitorCount={monitorsSummary?.totalMonitors} heading={"Uptime monitors"} > +