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")}