Skip to content

Commit 5a6d595

Browse files
authored
Merge pull request #2886 from bluewave-labs/develop
develop->demo
2 parents 3a34ee8 + 0101da7 commit 5a6d595

File tree

17 files changed

+473
-350
lines changed

17 files changed

+473
-350
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.vscode

client/src/Components/Table/index.jsx

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
TableHead,
88
TableRow,
99
} from "@mui/material";
10+
import Tooltip from "@mui/material/Tooltip";
1011
import SkeletonLayout from "./skeleton";
1112
import PropTypes from "prop-types";
1213
import { useTheme } from "@emotion/react";
@@ -41,6 +42,7 @@ const DataTable = ({
4142
data = [],
4243
config = {
4344
emptyView: "No data",
45+
tooltipContent: null,
4446
onRowClick: () => {},
4547
},
4648
}) => {
@@ -101,24 +103,54 @@ const DataTable = ({
101103
data.map((row) => {
102104
const key = row.id || row._id || Math.random();
103105
return (
104-
<TableRow
106+
<Tooltip
105107
key={key}
106-
sx={config?.rowSX ?? {}}
107-
onClick={config?.onRowClick ? () => config.onRowClick(row) : null}
108+
followCursor
109+
enterDelay={500}
110+
enterNextDelay={500}
111+
title={
112+
typeof config.tooltipContent === "function"
113+
? config.tooltipContent(row)
114+
: config.tooltipContent
115+
}
116+
slotProps={{
117+
tooltip: {
118+
sx: {
119+
background: "unset",
120+
},
121+
},
122+
popper: {
123+
modifiers: [
124+
{
125+
name: "offset",
126+
options: {
127+
offset: ({ popper }) => {
128+
return [popper.width / 2 + 20, -popper.height / 8];
129+
},
130+
},
131+
},
132+
],
133+
},
134+
}}
108135
>
109-
{headers.map((header, index) => {
110-
return (
111-
<TableCell
112-
align={index === 0 ? "left" : "center"}
113-
key={header.id}
114-
onClick={header.onClick ? (e) => header.onClick(e, row) : null}
115-
sx={header.getCellSx ? header.getCellSx(row) : {}}
116-
>
117-
{header.render(row)}
118-
</TableCell>
119-
);
120-
})}
121-
</TableRow>
136+
<TableRow
137+
sx={config?.rowSX ?? {}}
138+
onClick={config?.onRowClick ? () => config.onRowClick(row) : null}
139+
>
140+
{headers.map((header, index) => {
141+
return (
142+
<TableCell
143+
align={index === 0 ? "left" : "center"}
144+
key={header.id}
145+
onClick={header.onClick ? (e) => header.onClick(e, row) : null}
146+
sx={header.getCellSx ? header.getCellSx(row) : {}}
147+
>
148+
{header.render(row)}
149+
</TableCell>
150+
);
151+
})}
152+
</TableRow>
153+
</Tooltip>
122154
);
123155
})
124156
)}

client/src/Hooks/logHooks.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ const useFetchLogs = () => {
1515
setIsLoading(true);
1616
const response = await networkService.getLogs();
1717
setLogs(response.data.data);
18-
createToast({
19-
body: t("logsPage.toast.fetchLogsSuccess"),
20-
});
2118
} catch (error) {
2219
setError(error);
2320
createToast({

client/src/Pages/Incidents/Components/IncidentTable/index.jsx

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
//Components
2-
import Table from "../../../../Components/Table";
2+
import Stack from "@mui/material/Stack";
3+
import DataTable from "../../../../Components/Table";
4+
import Table from "@mui/material/Table";
5+
import TableBody from "@mui/material/TableBody";
6+
import TableRow from "@mui/material/TableRow";
7+
import TableCell from "@mui/material/TableCell";
38
import TableSkeleton from "../../../../Components/Table/skeleton";
49
import Pagination from "../../../../Components/Table/TablePagination";
510
import { StatusLabel } from "../../../../Components/Label";
@@ -16,7 +21,68 @@ import { useTranslation } from "react-i18next";
1621
import { useFetchChecksTeam } from "../../../../Hooks/checkHooks";
1722
import { useFetchChecksByMonitor } from "../../../../Hooks/checkHooks";
1823
import { useResolveIncident } from "../../../../Hooks/checkHooks";
19-
import { Button, Typography } from "@mui/material";
24+
import { Button, Typography, useTheme } from "@mui/material";
25+
import { lighten } from "@mui/material/styles";
26+
27+
const GetTooltip = (row) => {
28+
const theme = useTheme();
29+
const phases = row?.timings?.phases;
30+
31+
const phaseKeyFormattingMap = {
32+
firstByte: "first byte",
33+
};
34+
return (
35+
<Stack
36+
backgroundColor={lighten(theme.palette.primary.main, 0.1)}
37+
border={`1px solid ${theme.palette.primary.lowContrast}`}
38+
borderRadius={theme.shape.borderRadius}
39+
py={theme.spacing(2)}
40+
px={theme.spacing(4)}
41+
>
42+
<Typography
43+
variant="body2"
44+
color={theme.palette.primary.contrastText}
45+
>{`Status code: ${row?.statusCode}`}</Typography>
46+
<Typography
47+
variant="body2"
48+
color={theme.palette.primary.contrastText}
49+
>{`Response time: ${row?.responseTime} ms`}</Typography>
50+
{phases && (
51+
<>
52+
<Typography
53+
variant="body2"
54+
color={theme.palette.primary.contrastText}
55+
>{`Request timing: `}</Typography>
56+
<Table
57+
size="small"
58+
sx={{ ml: theme.spacing(2), mt: theme.spacing(2) }}
59+
>
60+
<TableBody>
61+
{Object.keys(phases)?.map((phaseKey) => (
62+
<TableRow key={phaseKey}>
63+
<TableCell sx={{ border: "none", p: 0 }}>
64+
<Typography
65+
variant="body2"
66+
color="success"
67+
>
68+
{`${phaseKeyFormattingMap[phaseKey] || phaseKey}:`}
69+
</Typography>
70+
</TableCell>
71+
<TableCell sx={{ border: "none", p: 0 }}>
72+
<Typography
73+
color={theme.palette.primary.contrastText}
74+
variant="body2"
75+
>{`${phases[phaseKey]} ms`}</Typography>
76+
</TableCell>
77+
</TableRow>
78+
))}
79+
</TableBody>
80+
</Table>
81+
</>
82+
)}
83+
</Stack>
84+
);
85+
};
2086

2187
const IncidentTable = ({
2288
isLoading,
@@ -167,9 +233,10 @@ const IncidentTable = ({
167233

168234
return (
169235
<>
170-
<Table
236+
<DataTable
171237
headers={headers}
172238
data={checks}
239+
config={{ tooltipContent: GetTooltip }}
173240
/>
174241
<Pagination
175242
paginationLabel={t("incidentsTablePaginationLabel")}

client/src/Pages/Logs/Queue/components/JobTable/index.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ const JobTable = ({ jobs = [] }) => {
4646
content: t("queuePage.jobTable.urlHeader"),
4747
render: (row) => row.monitorUrl,
4848
},
49+
{
50+
id: "interval",
51+
content: t("queuePage.jobTable.intervalHeader"),
52+
render: (row) => `${row.monitorInterval} ms`,
53+
},
4954
{
5055
id: "type",
5156
content: t("queuePage.jobTable.typeHeader"),

client/src/Validation/validation.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,12 @@ const monitorValidation = joi.object({
130130
then: joi
131131
.string()
132132
.trim()
133-
.regex(/^[a-z0-9]{64}$/)
133+
.regex(
134+
/^(\/+)?([a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]|[a-zA-Z0-9]+|[a-f0-9]{12,64})$/
135+
)
134136
.messages({
135137
"string.empty": "This field is required.",
136-
"string.pattern.base": "Please enter a valid 64-character Docker container ID.",
138+
"string.pattern.base": "Please enter a valid container name or ID.",
137139
}),
138140
otherwise: joi
139141
.string()

client/src/locales/en.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@
440440
"uptimeGeneralInstructions": {
441441
"http": "Enter the URL or IP to monitor (e.g., https://example.com/ or 192.168.1.100) and add a clear display name that appears on the dashboard.",
442442
"ping": "Enter the IP address or hostname to ping (e.g., 192.168.1.100 or example.com) and add a clear display name that appears on the dashboard.",
443-
"docker": "Enter the Docker ID of your container. Docker IDs must be the full 64 char Docker ID. You can run docker inspect <short_id> to get the full container ID.",
443+
"docker": "Enter the Docker container name or ID. You can use either the container name (e.g., my-app) or the container ID (full 64-char ID or short ID).",
444444
"port": "Enter the URL or IP of the server, the port number and a clear display name that appears on the dashboard.",
445445
"game": "Enter the IP address or hostname and the port number to ping (e.g., 192.168.1.100 or example.com) and choose game type."
446446
},
@@ -740,6 +740,7 @@
740740
"idHeader": "Monitor ID",
741741
"urlHeader": "URL",
742742
"typeHeader": "Type",
743+
"intervalHeader": "Interval",
743744
"activeHeader": "Active",
744745
"lockedAtHeader": "Locked at",
745746
"runCountHeader": "Run count",
@@ -1014,9 +1015,9 @@
10141015
},
10151016
"monitorType": {
10161017
"docker": {
1017-
"label": "Container ID",
1018+
"label": "Container Name/ID",
10181019
"namePlaceholder": "My Container",
1019-
"placeholder": "abcd1234"
1020+
"placeholder": "my-app or abcd1234"
10201021
},
10211022
"http": {
10221023
"label": "URL to monitor",

client/vite.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { execSync } from "child_process";
55

66
export default defineConfig(({ mode }) => {
77
const env = loadEnv(mode, process.cwd(), "");
8-
let version = "3.1.3";
8+
let version = "3.1.4";
99

1010
return {
1111
base: "/",

0 commit comments

Comments
 (0)