This commit is contained in:
Alex Holliday committed 2026-02-02 17:49:36 +00:00
1 parent 83b628c8f9
commit 6063532c79
4 files changed
+117 -30

No files matched your search

@@ -0,0 +1,81 @@
import Stack from "@mui/material/Stack";
import { Select, Button } from "@/Components/v2/inputs";
import MenuItem from "@mui/material/MenuItem";
import useMediaQuery from "@mui/material/useMediaQuery";
import { Typography, useTheme } from "@mui/material";
import { useTranslation } from "react-i18next";
import type { Monitor } from "@/Types/Monitor";
const resolutionTypes = ["manual", "automatic"];
interface ControlsIncidentFilterProps {
monitors?: Monitor[];
selectedMonitor: string;
setSelectedMonitor: React.Dispatch<React.SetStateAction<string>>;
selectedResolutionType: string;
setSelectedResolutionType: React.Dispatch<React.SetStateAction<string>>;
onClearFilters: () => void;
}
export const ControlsIncidentFilter = ({
monitors,
selectedMonitor,
setSelectedMonitor,
selectedResolutionType,
setSelectedResolutionType,
onClearFilters,
}: ControlsIncidentFilterProps) => {
const { t } = useTranslation();
const theme = useTheme();
const isSmall = useMediaQuery(theme.breakpoints.down("md"));
const isFilterActive = selectedMonitor !== "0" || selectedResolutionType !== "";
return (
<Stack
direction={isSmall ? "column" : "row"}
gap={theme.spacing(2)}
>
<Select
placeholder={t("pages.incidents.filters.monitor")}
value={selectedMonitor}
onChange={(e) => setSelectedMonitor(e.target.value)}
>
<MenuItem value="0">
<Typography>{t("pages.incidents.filters.allMonitors")}</Typography>
</MenuItem>
{monitors?.map((monitor) => (
<MenuItem
key={monitor.id}
value={monitor.id}
>
<Typography>{monitor.name}</Typography>
</MenuItem>
))}
</Select>
<Select
placeholder={t("pages.incidents.filters.resolutionType")}
value={selectedResolutionType}
onChange={(e) => setSelectedResolutionType(e.target.value)}
>
{resolutionTypes.map((type) => (
<MenuItem
key={type}
value={type}
>
<Typography textTransform="capitalize">
{t(`pages.incidents.filters.resolutionTypes.${type}`)}
</Typography>
</MenuItem>
))}
</Select>
{isFilterActive && (
<Button
variant="contained"
onClick={onClearFilters}
>
{t("pages.incidents.filters.clearFilters")}
</Button>
)}
</Stack>
);
};
@@ -18,6 +18,7 @@ import { useTheme } from "@mui/material/styles";
import Box from "@mui/material/Box";
interface IncidentsTableProps {
title?: string;
incidents?: Incident[];
monitors?: Monitor[];
incidentsCount: number;
@@ -30,7 +31,6 @@ interface IncidentsTableProps {
}
export const IncidentsTable = ({
title,
incidents,
monitors,
incidentsCount,
+25 -29
View File
@@ -12,6 +12,7 @@ import { IncidentsTable } from "@/Pages/Incidents/Components/IncidentTable";
import { DialogResolution } from "@/Pages/Incidents/Components/DialogResolution";
import { DialogIncidentDetails } from "@/Pages/Incidents/Components/DialogIncidentDetails";
import { HeaderTimeRange } from "@/Components/v2/common";
import { ControlsIncidentFilter } from "@/Pages/Incidents/Components/ControlsIncidentFilter";
import { useGet } from "@/Hooks/UseApi";
import { useState, useEffect, useMemo } from "react";
@@ -64,7 +65,6 @@ const IncidentsPage = () => {
const {
data: incidentsData,
isLoading: isLoadingIncidents,
error: incidentsError,
refetch: refetchIncidents,
} = useGet<IncidentsResponse>(
incidentsUrl,
@@ -73,11 +73,7 @@ const IncidentsPage = () => {
);
// Fetch monitors for lookup
const {
data: monitorsData,
isLoading: isLoadingMonitors,
error: monitorsError,
} = useGet<Monitor[]>("/monitors/team");
const { data: monitorsData } = useGet<Monitor[]>("/monitors/team");
// Build active incidents URL (always fetch all active, no date filter)
const activeIncidentsUrl = useMemo(() => {
@@ -99,12 +95,9 @@ const IncidentsPage = () => {
);
// Fetch incident summary
const {
data: summaryData,
isLoading: isLoadingSummary,
error: summaryError,
refetch: refetchSummary,
} = useGet<IncidentSummary>("/incidents/team/summary");
const { data: summaryData, refetch: refetchSummary } = useGet<IncidentSummary>(
"/incidents/team/summary"
);
// Reset page when filters change
useEffect(() => {
@@ -116,17 +109,11 @@ const IncidentsPage = () => {
const incidentsCount = incidentsData?.count ?? 0;
const activeIncidents = activeIncidentsData?.incidents ?? [];
const activeIncidentsCount = activeIncidentsData?.count ?? 0;
const networkError = !!incidentsError || !!monitorsError || !!summaryError;
// Expose state and handlers for future UI use
void selectedMonitor;
void setSelectedMonitor;
void filter;
void setFilter;
void isLoadingIncidents;
void isLoadingMonitors;
void isLoadingSummary;
void networkError;
const handleClearFilters = () => {
setSelectedMonitor("0");
setFilter("all");
};
const handleOpenDetails = (incidentId: string) => {
const incident =
@@ -176,15 +163,23 @@ const IncidentsPage = () => {
<SummaryCardLatestIncidents summary={summaryData} />
<SummaryCardStats summary={summaryData} />
</Stack>
<Typography
variant="h6"
sx={{ mb: theme.spacing(4), textTransform: "uppercase" }}
>
{t("pages.incidents.table.activeIncidents")}
</Typography>
<ControlsIncidentFilter
monitors={monitorsData ?? undefined}
selectedMonitor={selectedMonitor}
setSelectedMonitor={setSelectedMonitor}
selectedResolutionType={filter}
setSelectedResolutionType={setFilter}
onClearFilters={handleClearFilters}
/>
{activeIncidentsCount > 0 && (
<>
<Typography
variant="h6"
sx={{ mb: theme.spacing(4), textTransform: "uppercase" }}
>
{t("pages.incidents.table.activeIncidents")}
</Typography>
<IncidentsTable
incidents={activeIncidents}
monitors={monitorsData ?? undefined}
@@ -206,6 +201,7 @@ const IncidentsPage = () => {
>
{t("pages.incidents.table.resolvedIncidents")}
</Typography>
<HeaderTimeRange
dateRange={dateRange}
setDateRange={setDateRange}
+10
View File
@@ -414,6 +414,16 @@
"resolveManually": "Resolve Manually"
}
},
"filters": {
"monitor": "Monitor",
"allMonitors": "All monitors",
"resolutionType": "Resolution type",
"resolutionTypes": {
"automatic": "Automatic",
"manual": "Manual"
},
"clearFilters": "Clear Filters"
},
"dialog": {
"details": {
"title": "Incident details",