strings
This commit is contained in:
1 parent
6b67f4977f
commit
bcc57c7135
7 files changed
+143
-36
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import Dialog from "@mui/material/Dialog";
|
||||
import type { DialogProps } from "@mui/material/Dialog";
|
||||
import DialogActions from "@mui/material/DialogActions";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import DialogContentText from "@mui/material/DialogContentText";
|
||||
@@ -6,6 +7,7 @@ import DialogTitle from "@mui/material/DialogTitle";
|
||||
import { Button } from "@/Components/v2/inputs";
|
||||
import { typographyLevels } from "@/Utils/Theme/v2Palette";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export const DialogInput = ({
|
||||
open,
|
||||
@@ -18,6 +20,9 @@ export const DialogInput = ({
|
||||
loading = false,
|
||||
cancelText,
|
||||
confirmText,
|
||||
children,
|
||||
maxWidth,
|
||||
fullWidth = false,
|
||||
}: {
|
||||
open: boolean;
|
||||
title?: string;
|
||||
@@ -29,13 +34,21 @@ export const DialogInput = ({
|
||||
loading?: boolean;
|
||||
cancelText?: string;
|
||||
confirmText?: string;
|
||||
children?: ReactNode;
|
||||
maxWidth?: DialogProps["maxWidth"];
|
||||
fullWidth?: boolean;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Dialog open={open}>
|
||||
<Dialog
|
||||
open={open}
|
||||
maxWidth={maxWidth}
|
||||
fullWidth={fullWidth}
|
||||
>
|
||||
<DialogTitle sx={{ fontSize: typographyLevels.l }}>{title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText>{content}</DialogContentText>
|
||||
{content && <DialogContentText>{content}</DialogContentText>}
|
||||
{children}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,70 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import Box from "@mui/material/Box";
|
||||
import { Dialog, TextField } from "@/Components/v2/inputs";
|
||||
import { usePut } from "@/Hooks/UseApi";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useTheme } from "@mui/material";
|
||||
|
||||
interface DialogResolutionProps {
|
||||
open: boolean;
|
||||
incidentId: string | null;
|
||||
onClose: () => void;
|
||||
onResolved?: () => void;
|
||||
}
|
||||
|
||||
export const DialogResolution = ({
|
||||
open,
|
||||
incidentId,
|
||||
onClose,
|
||||
onResolved,
|
||||
}: DialogResolutionProps) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const [comment, setComment] = useState("");
|
||||
const { put: resolveIncident, loading: isResolving } = usePut();
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setComment("");
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
const handleCancel = () => {
|
||||
onClose();
|
||||
};
|
||||
|
||||
const handleConfirm = async () => {
|
||||
if (!incidentId) return;
|
||||
const body = comment.trim() ? { comment: comment.trim() } : {};
|
||||
const result = await resolveIncident(`/incidents/${incidentId}/resolve`, body);
|
||||
if (result) {
|
||||
onClose();
|
||||
onResolved?.();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={open}
|
||||
title={t("incidentsPage.resolveIncidentDialogTitle")}
|
||||
onCancel={handleCancel}
|
||||
onConfirm={handleConfirm}
|
||||
confirmText={t("incidentsPage.resolveIncidentDialogConfirm")}
|
||||
confirmColor="error"
|
||||
cancelColor="primary"
|
||||
loading={isResolving}
|
||||
maxWidth="sm"
|
||||
fullWidth
|
||||
>
|
||||
<Box sx={{ mt: theme.spacing(4) }}>
|
||||
<TextField
|
||||
fieldLabel={t("incidentsPage.resolveIncidentDialogCommentLabel")}
|
||||
placeholder={t("incidentsPage.resolveIncidentDialogCommentPlaceholder")}
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
fullWidth
|
||||
/>
|
||||
</Box>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
Whitespace-only changes.
@@ -1,7 +1,7 @@
|
||||
import { Table } from "@/Components/v2/design-elements";
|
||||
import { Pagination } from "@/Components/v2/design-elements/Table";
|
||||
import type { Header } from "@/Components/v2/design-elements/Table";
|
||||
import { StatusLabel, ValueLabel } from "@/Components/v2/design-elements";
|
||||
import { ValueLabel } from "@/Components/v2/design-elements";
|
||||
import type { ValueType } from "@/Components/v2/design-elements/StatusLabel";
|
||||
import { ActionsMenu } from "@/Components/v2/actions-menu";
|
||||
import type { Incident } from "@/Types/Incident";
|
||||
@@ -52,13 +52,13 @@ export const IncidentsTable = ({
|
||||
const actions: ActionMenuItem[] = [
|
||||
{
|
||||
id: "details",
|
||||
label: t("incidentsPage.incidentsTableActionDetails"),
|
||||
label: t("pages.incidents.table.actions.details"),
|
||||
action: () => onOpenDetails?.(incident.id),
|
||||
closeMenu: true,
|
||||
},
|
||||
{
|
||||
id: "goToMonitor",
|
||||
label: t("incidentsPage.incidentsTableActionGoToMonitor"),
|
||||
label: t("pages.incidents.table.actions.goToMonitor"),
|
||||
action: () => {
|
||||
if (monitor) {
|
||||
const path = TypeToPathMap[monitor.type as keyof typeof TypeToPathMap];
|
||||
@@ -74,7 +74,7 @@ export const IncidentsTable = ({
|
||||
if (isActive) {
|
||||
actions.push({
|
||||
id: "resolve",
|
||||
label: t("incidentsPage.incidentsTableActionResolveManually"),
|
||||
label: t("pages.incidents.table.actions.resolveManually"),
|
||||
action: () => onResolve?.(incident.id),
|
||||
closeMenu: true,
|
||||
});
|
||||
@@ -97,13 +97,18 @@ export const IncidentsTable = ({
|
||||
id: "status",
|
||||
content: t("common.table.headers.status"),
|
||||
render: (row) => {
|
||||
const status = row.status === true ? false : true;
|
||||
return <StatusLabel status={status} />;
|
||||
const isActive = row.status === true;
|
||||
return (
|
||||
<ValueLabel
|
||||
value={isActive ? "negative" : "positive"}
|
||||
text={isActive ? t("pages.incidents.table.status.active") : t("pages.incidents.table.status.resolved")}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "startTime",
|
||||
content: t("incidentsPage.startTime"),
|
||||
content: t("pages.incidents.table.headers.startTime"),
|
||||
render: (row) => {
|
||||
return formatDateWithTz(
|
||||
row.createdAt,
|
||||
@@ -114,7 +119,7 @@ export const IncidentsTable = ({
|
||||
},
|
||||
{
|
||||
id: "endTime",
|
||||
content: t("incidentsPage.endTime"),
|
||||
content: t("pages.incidents.table.headers.endTime"),
|
||||
render: (row) => {
|
||||
if (row.endTime) {
|
||||
return formatDateWithTz(
|
||||
@@ -128,7 +133,7 @@ export const IncidentsTable = ({
|
||||
},
|
||||
{
|
||||
id: "resolutionType",
|
||||
content: t("incidentsPage.resolutionType"),
|
||||
content: t("pages.incidents.table.headers.resolutionType"),
|
||||
render: (row) => {
|
||||
if (row.resolutionType) {
|
||||
return (
|
||||
@@ -151,7 +156,7 @@ export const IncidentsTable = ({
|
||||
},
|
||||
{
|
||||
id: "statusCode",
|
||||
content: t("incidentsPage.statusCode"),
|
||||
content: t("pages.incidents.table.headers.statusCode"),
|
||||
render: (row) => {
|
||||
const code = row.statusCode;
|
||||
if (!code) return "N/A";
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
SummaryCardStats,
|
||||
} from "@/Pages/Incidents/Components/SummaryCard";
|
||||
import { IncidentsTable } from "@/Pages/Incidents/Components/IncidentTable";
|
||||
import { DialogResolution } from "@/Pages/Incidents/Components/DialogResolution";
|
||||
|
||||
import { useGet } from "@/Hooks/UseApi";
|
||||
import { useState, useEffect, useMemo } from "react";
|
||||
@@ -14,10 +15,6 @@ import type { IncidentsResponse, IncidentSummary } from "@/Types/Incident";
|
||||
import type { Monitor } from "@/Types/Monitor";
|
||||
import { useTheme } from "@mui/material";
|
||||
|
||||
interface MonitorLookup {
|
||||
[key: string]: { id: string; name: string; type: string };
|
||||
}
|
||||
|
||||
const IncidentsPage = () => {
|
||||
const theme = useTheme();
|
||||
const { monitorId } = useParams();
|
||||
@@ -29,6 +26,10 @@ const IncidentsPage = () => {
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
|
||||
// Resolve dialog state
|
||||
const [isResolveDialogOpen, setIsResolveDialogOpen] = useState(false);
|
||||
const [resolveIncidentId, setResolveIncidentId] = useState<string | null>(null);
|
||||
|
||||
// Build incidents URL with query params
|
||||
const incidentsUrl = useMemo(() => {
|
||||
const params = new URLSearchParams();
|
||||
@@ -50,7 +51,11 @@ const IncidentsPage = () => {
|
||||
isLoading: isLoadingIncidents,
|
||||
error: incidentsError,
|
||||
refetch: refetchIncidents,
|
||||
} = useGet<IncidentsResponse>(incidentsUrl);
|
||||
} = useGet<IncidentsResponse>(
|
||||
incidentsUrl,
|
||||
{},
|
||||
{ keepPreviousData: true, refreshInterval: 10000 }
|
||||
);
|
||||
|
||||
// Fetch monitors for lookup
|
||||
const {
|
||||
@@ -67,19 +72,6 @@ const IncidentsPage = () => {
|
||||
refetch: refetchSummary,
|
||||
} = useGet<IncidentSummary>("/incidents/team/summary");
|
||||
|
||||
// Build monitor lookup
|
||||
const monitorLookup = useMemo<MonitorLookup | undefined>(() => {
|
||||
if (!monitorsData) return undefined;
|
||||
return monitorsData.reduce<MonitorLookup>((acc, monitor) => {
|
||||
acc[monitor.id] = {
|
||||
id: monitor.id,
|
||||
name: monitor.name,
|
||||
type: monitor.type,
|
||||
};
|
||||
return acc;
|
||||
}, {});
|
||||
}, [monitorsData]);
|
||||
|
||||
// Reset page when filters change
|
||||
useEffect(() => {
|
||||
setPage(0);
|
||||
@@ -100,10 +92,6 @@ const IncidentsPage = () => {
|
||||
void isLoadingIncidents;
|
||||
void isLoadingMonitors;
|
||||
void isLoadingSummary;
|
||||
void refetchIncidents;
|
||||
void refetchSummary;
|
||||
void monitorLookup;
|
||||
void summaryData;
|
||||
void networkError;
|
||||
|
||||
const handleOpenDetails = (incidentId: string) => {
|
||||
@@ -111,7 +99,18 @@ const IncidentsPage = () => {
|
||||
};
|
||||
|
||||
const handleResolve = (incidentId: string) => {
|
||||
console.log("Resolve incident:", incidentId);
|
||||
setResolveIncidentId(incidentId);
|
||||
setIsResolveDialogOpen(true);
|
||||
};
|
||||
|
||||
const handleResolveClose = () => {
|
||||
setIsResolveDialogOpen(false);
|
||||
setResolveIncidentId(null);
|
||||
};
|
||||
|
||||
const handleResolved = () => {
|
||||
refetchIncidents();
|
||||
refetchSummary();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -138,6 +137,12 @@ const IncidentsPage = () => {
|
||||
onOpenDetails={handleOpenDetails}
|
||||
onResolve={handleResolve}
|
||||
/>
|
||||
<DialogResolution
|
||||
open={isResolveDialogOpen}
|
||||
incidentId={resolveIncidentId}
|
||||
onClose={handleResolveClose}
|
||||
onResolved={handleResolved}
|
||||
/>
|
||||
</BasePage>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -368,7 +368,21 @@
|
||||
}
|
||||
},
|
||||
"table": {
|
||||
"headers": {}
|
||||
"headers": {
|
||||
"startTime": "Start Time",
|
||||
"endTime": "End Time",
|
||||
"resolutionType": "Resolution Type",
|
||||
"statusCode": "Status Code"
|
||||
},
|
||||
"status": {
|
||||
"active": "Active",
|
||||
"resolved": "Resolved"
|
||||
},
|
||||
"actions": {
|
||||
"details": "Details",
|
||||
"goToMonitor": "Go to monitor",
|
||||
"resolveManually": "Resolve Manually"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user