diff --git a/client/src/Components/v1/Host/index.jsx b/client/src/Components/v1/Host/index.jsx
index 935224994..6670722c1 100644
--- a/client/src/Components/v1/Host/index.jsx
+++ b/client/src/Components/v1/Host/index.jsx
@@ -23,12 +23,12 @@ const Host = ({ url, title, percentageColor, percentage, showURL, status }) => {
direction="row"
position="relative"
alignItems="center"
- gap={theme.spacing(5)}
+ gap={theme.spacing(4)}
>
{title}
@@ -38,9 +38,9 @@ const Host = ({ url, title, percentageColor, percentage, showURL, status }) => {
<>
diff --git a/client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx b/client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx
index b6024ce53..8ed80d037 100644
--- a/client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx
+++ b/client/src/Pages/Incidents2/Components/ActiveIncidentsPanel/index.jsx
@@ -43,39 +43,36 @@ const ActiveIncidentsPanel = ({ totalCount = 0, isLoading = false, error = null
if (!totalCount || totalCount === 0) {
return (
-
+
{t("incidentsPage.allSystemsAreOperational")}
@@ -86,21 +83,20 @@ const ActiveIncidentsPanel = ({ totalCount = 0, isLoading = false, error = null
}
return (
-
+
{totalCount}
-
- {t("incidentsPage.incidentsActivePanelTitle")}
-
);
diff --git a/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx b/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx
index 43071fa03..33ba21cd1 100644
--- a/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx
+++ b/client/src/Pages/Incidents2/Components/IncidentsSummaryPanel/index.jsx
@@ -53,7 +53,7 @@ const IncidentsSummaryPanel = ({ updateTrigger }) => {
<>
{!incidents || incidents.length === 0 ? (
-
+
+
+
+
{t("incidentsPage.incidentsLatestPanelEmpty")}
-
+
) : (
{incidents.map((incident, index) => (
diff --git a/client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx b/client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx
index ede9c619a..c8559d7a2 100644
--- a/client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx
+++ b/client/src/Pages/Incidents2/Components/StatisticsPanel/index.jsx
@@ -3,10 +3,8 @@ import { Box, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import PanelSkeleton from "../IncidentsSummaryPanel/skeleton.jsx";
import { useTranslation } from "react-i18next";
-import { Divider } from "@mui/material";
import Clock from "@/assets/icons/maintenance.svg?react";
import Incidents from "@/assets/icons/incidents.svg?react";
-import ResolutionItem from "@/assets/icons/interval-check.svg?react";
import NotificationIcon from "@/assets/icons/notifications.svg?react";
import SummaryCard from "../SummaryCard/index.jsx";
@@ -43,10 +41,15 @@ const StatisticsPanel = ({ isLoading = false, error = null, summary = {} }) => {
const iconWrapperStyle = {
display: "flex",
justifyContent: "center",
- mx: theme.spacing(3),
+ mx: theme.spacing(2),
color: theme.palette.primary.contrastTextTertiary,
+ "& svg": {
+ width: 18,
+ height: 18,
+ },
"& svg path": {
stroke: "currentColor",
+ strokeWidth: 1.5,
},
};
if (isLoading) {
@@ -76,6 +79,13 @@ const StatisticsPanel = ({ isLoading = false, error = null, summary = {} }) => {
);
}
+ const getMostAffectedMonitor = () => {
+ if (!summary.total || summary.total === 0) {
+ return t("incidentsPage.none");
+ }
+ return summary.topMonitor?.monitorName || t("incidentsPage.none");
+ };
+
return (
@@ -99,11 +109,10 @@ const StatisticsPanel = ({ isLoading = false, error = null, summary = {} }) => {
lineHeight: 1.2,
}}
>
- {t("incidentsPage.totalIncidents")} : {summary.total || 0}
+ {t("incidentsPage.totalIncidents")}: {summary.total || 0}
-
{
lineHeight: 1.2,
}}
>
- {t("incidentsPage.mostAffectedMonitor")} :{" "}
- {summary.topMonitor?.monitorName || t("incidentsPage.unknownMonitor")}
+ {t("incidentsPage.mostAffectedMonitor")}: {getMostAffectedMonitor()}
-
{
- {t("incidentsPage.avgResolutionTime")} :{" "}
- {summary.avgResolutionTimeHours || 0} {t("incidentsPage.hours")}
+ {t("incidentsPage.avgResolutionTime")}:{" "}
+ {summary.total > 0 ? `${summary.avgResolutionTimeHours || 0} ${t("incidentsPage.hours")}` : "N/A"}
-
-
-
-
-
-
-
-
-
-
- {t("incidentsPage.resolutions")}: {totalResolutions}
-
-
-
-
-
-
-
-
- {summary.totalAutomaticResolutions > 0 && (
-
- {t("incidentsPage.automatic")} ({summary.totalAutomaticResolutions})
-
- )}
- {summary.totalManualResolutions > 0 && (
-
- {t("incidentsPage.manual")} ({summary.totalManualResolutions})
-
- )}
-
-
);
diff --git a/client/src/Pages/Incidents2/Components/SummaryCard/index.jsx b/client/src/Pages/Incidents2/Components/SummaryCard/index.jsx
index cb895dc50..3a8589dc1 100644
--- a/client/src/Pages/Incidents2/Components/SummaryCard/index.jsx
+++ b/client/src/Pages/Incidents2/Components/SummaryCard/index.jsx
@@ -8,17 +8,14 @@ const SummaryCard = ({ children, isHighPriority = false, sx = {}, title = null }
{title}
@@ -49,9 +45,9 @@ const SummaryCard = ({ children, isHighPriority = false, sx = {}, title = null }
)}
{children}
diff --git a/client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx b/client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx
index b38837cf2..be6dc99aa 100644
--- a/client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx
+++ b/client/src/Pages/Logs/Diagnostics/components/gauges/index.jsx
@@ -12,13 +12,16 @@ import { Box } from "@mui/material";
const BaseContainer = ({children}) => {
const theme = useTheme()
return(
-
{children}
@@ -99,7 +102,7 @@ const Gauges = ({ diagnostics, isLoading }) => {
return (
{
+const LevelBadge = ({ level }) => {
+ const theme = useTheme();
+
const levelColors = {
info: theme.palette.success.main,
warn: theme.palette.warning.main,
@@ -17,31 +20,38 @@ const formatLog = (theme, log, idx) => {
debug: theme.palette.accent.main,
};
- const color = levelColors[log.level] || theme.palette.primary.contrastText;
+ const color = levelColors[level] || theme.palette.primary.contrastText;
return (
-
- [{log.timestamp}]{" "}
- {log.level.toUpperCase()}
- {": "}
- {`(${log.service})`}
- {`(${log.method})`}
- {": "}
- {log.message}
-
-
+
+ {level}
+
);
};
-const Logs = () => {
- // Local state
- const [logLevel, setLogLevel] = useState("all");
+const formatTimestamp = (timestamp) => {
+ if (!timestamp) return "-";
+ const date = new Date(timestamp);
+ return date.toLocaleString();
+};
+
+const Logs = () => {
+ const [logLevel, setLogLevel] = useState("all");
+ const [page, setPage] = useState(0);
+ const [rowsPerPage, setRowsPerPage] = useState(15);
- // Hooks
const theme = useTheme();
const { t } = useTranslation();
const [logs, isLoading, error] = useFetchLogs();
- // Setup
+
const LOG_LEVELS = [
{ _id: "all", name: t("logsPage.logLevelSelect.values.all") },
{ _id: "info", name: t("logsPage.logLevelSelect.values.info") },
@@ -49,52 +59,116 @@ const Logs = () => {
{ _id: "error", name: t("logsPage.logLevelSelect.values.error") },
{ _id: "debug", name: t("logsPage.logLevelSelect.values.debug") },
];
+
+ const headers = [
+ {
+ id: "timestamp",
+ content: t("logsPage.table.timestamp"),
+ render: (row) => (
+
+ {formatTimestamp(row.timestamp)}
+
+ ),
+ },
+ {
+ id: "level",
+ content: t("logsPage.table.level"),
+ render: (row) => ,
+ },
+ {
+ id: "service",
+ content: t("logsPage.table.service"),
+ render: (row) => (
+ {row.service || "-"}
+ ),
+ },
+ {
+ id: "method",
+ content: t("logsPage.table.method"),
+ render: (row) => (
+ {row.method || "-"}
+ ),
+ },
+ {
+ id: "message",
+ content: t("logsPage.table.message"),
+ render: (row) => (
+
+ {row.message || "-"}
+
+ ),
+ },
+ ];
+
+ const filteredLogs = logs
+ ?.filter((log) => {
+ if (logLevel === "all") return true;
+ return log.level === logLevel;
+ })
+ .reverse()
+ .map((log, idx) => ({ ...log, id: idx }));
+
+ const paginatedLogs = filteredLogs?.slice(
+ page * rowsPerPage,
+ page * rowsPerPage + rowsPerPage
+ );
+
+ const handleChangePage = (event, newPage) => {
+ setPage(newPage);
+ };
+
+ const handleChangeRowsPerPage = (event) => {
+ setRowsPerPage(parseInt(event.target.value, 10));
+ setPage(0);
+ };
+
+ const handleLogLevelChange = (e) => {
+ setLogLevel(e.target.value);
+ setPage(0);
+ };
+
return (
{t("logsPage.logLevelSelect.title")}
-
-
- {logs
- ?.filter((log) => {
- if (logLevel === "all") return true;
- return log.level === logLevel;
- })
- .reverse()
- .map((log, idx) => formatLog(theme, log, idx))}
-
-
+ />
+
+ {filteredLogs?.length > 0 && (
+
+ )}
);
};
diff --git a/client/src/locales/en.json b/client/src/locales/en.json
index a658d6d66..e59bf1615 100644
--- a/client/src/locales/en.json
+++ b/client/src/locales/en.json
@@ -791,7 +791,16 @@
"error": "Error",
"debug": "Debug"
}
- }
+ },
+ "table": {
+ "timestamp": "Timestamp",
+ "level": "Level",
+ "service": "Service",
+ "method": "Method",
+ "message": "Message",
+ "logs": "logs"
+ },
+ "noLogs": "No logs found"
},
"queuePage": {
"title": "Queue",
@@ -1195,6 +1204,7 @@
"incidentsOptionsHeaderFilterResolved": "Resolved",
"incidentsTableResolved": "Closed",
"incidentsTableActionResolveManually": "Resolve Manually",
- "hours": "hours"
+ "hours": "hours",
+ "none": "None"
}
}