Merge pull request #256 from bluewave-labs/feat/details-pg

Details page implementation.
This commit is contained in:
Alexander Holliday authored and GitHub committed 2024-07-10 09:51:12 -07:00
commit 1ba37a7ec9
5 files changed
+321

No files matched your search

+6
View File
@@ -18,8 +18,10 @@ import CheckEmail from "./Pages/CheckEmail";
import SetNewPassword from "./Pages/SetNewPassword";
import NewPasswordConfirmed from "./Pages/NewPasswordConfirmed";
import ProtectedRoute from "./Components/ProtectedRoute";
import Details from "./Pages/Details";
import Maintenance from "./Pages/Maintenance";
function App() {
return (
<>
@@ -42,6 +44,10 @@ function App() {
path="incidents"
element={<ProtectedRoute Component={Incidents} />}
/>
<Route
path="details"
element={<ProtectedRoute Component={Details} />}
/>
<Route
path="status"
element={<ProtectedRoute Component={Status} />}
Whitespace-only changes.
@@ -0,0 +1,152 @@
import { styled, useTheme } from '@mui/material/styles';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell, { tableCellClasses } from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { StatusLabel } from "../../Components/Label/";
import PropTypes from 'prop-types';
const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
backgroundColor: theme.palette.action.hover,
color: theme.palette.common.black,
},
[`&.${tableCellClasses.body}`]: {
fontSize: 14,
},
}));
const StyledTableRow = styled(TableRow)(({ theme }) => ({
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.action.hover,
},
'&:nth-of-type(even)': {
backgroundColor: theme.palette.common.white,
},
'&:last-child td, &:last-child th': {
border: 0,
},
}));
function createData(name, date, message) {
return { name, date, message };
}
const CustomizedTables = ({ monitor }) => {
const theme = useTheme();
const rows = (monitor && monitor.checks) ? monitor.checks.map(check => createData(
<StatusLabel status={check.status ? "Up" : "Down"} customStyles={{ backgroundColor: check.status ? '#f2f4f7' : '#fff9f9', borderColor: check.status ? '#d2d6de' : '#ffcac6', color: '#344054' }} />,
new Date(check.createdAt).toLocaleString(),
`HTTP ${check.statusCode} - ${check.status ? 'OK' : 'NOK'}`
)) : [];
return (
<Box
sx={{
marginTop: theme.spacing(4),
marginX: 'auto',
width: '80%',
paddingX: theme.spacing(6),
[theme.breakpoints.down('md')]: {
width: '100%',
},
}}
>
<Box sx={{ display: 'flex', justifyContent: 'space-around', marginBottom: theme.spacing(4) }}>
{[...Array(4)].map((_, index) => (
<Box
key={index}
sx={{
width: '223.35px',
height: '87px',
borderRadius: '4px',
border: '1px solid',
borderColor: '#EAECF0',
padding: theme.spacing(1),
textAlign: 'left',
boxShadow: '0px 1px 2px rgba(16, 24, 40, 0.05)',
backdropFilter: 'blur(2px)',
}}
>
<Typography
variant="body2"
sx={{
fontFamily: 'Roboto',
fontWeight: 400,
fontSize: '16px',
lineHeight: '24px',
color: '#1570EF',
marginBottom: theme.spacing(1),
}}
>
Currently up for
</Typography>
<Typography
variant="body1"
sx={{
fontFamily: 'Roboto',
fontWeight: 600,
fontSize: '13px',
lineHeight: '20px',
color: '#344054',
}}
>
4h 30m 2s
</Typography>
</Box>
))}
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: theme.spacing(2) }}>
<Typography variant="h6" component="div" sx={{ fontWeight: 600, fontSize: 16 }}>
History
</Typography>
</Box>
<TableContainer component={Paper}>
<Table sx={{ minWidth: 700 }} aria-label="customized table">
<TableHead>
<TableRow>
<StyledTableCell>Status</StyledTableCell>
<StyledTableCell align="right">Date & Time</StyledTableCell>
<StyledTableCell align="right">Message</StyledTableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<StyledTableRow key={row.name.props.status.key}>
<StyledTableCell component="th" scope="row">
{row.name}
</StyledTableCell>
<StyledTableCell align="right">{row.date}</StyledTableCell>
<StyledTableCell align="right">{row.message}</StyledTableCell>
</StyledTableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
);
};
CustomizedTables.propTypes = {
monitor: PropTypes.shape({
checks: PropTypes.arrayOf(
PropTypes.shape({
status: PropTypes.bool.isRequired,
createdAt: PropTypes.string.isRequired,
statusCode: PropTypes.number.isRequired,
})
),
}),
};
CustomizedTables.defaultProps = {
monitor: { checks: [] },
};
export default CustomizedTables;
View File
Whitespace-only changes.
+163
View File
@@ -0,0 +1,163 @@
import React from 'react';
import CustomizedTables from '../../Components/CustomizedTables';
import { Box, Typography, useTheme } from '@mui/material';
/**
* Details page component displaying monitor details and related information.
* @component
*/
const DetailsPage = () => {
const theme = useTheme();
// Example monitor data (replace with actual data or fetch from API)
const monitorData = {
"_id": "66863aa2437936b46e225d1f",
"userId": "66863a8f437936b46e225d1a",
"name": "Google",
"description": "Google",
"status": false,
"type": "http",
"url": "https://www.google.com/404",
"isActive": true,
"interval": 60000,
"createdAt": "2024-07-04T06:01:06.527Z",
"updatedAt": "2024-07-04T06:02:00.250Z",
"__v": 0,
"checks": [
{
"_id": "66863ad8437936b46e225d6d",
"monitorId": "66863aa2437936b46e225d1f",
"status": false,
"responseTime": 144,
"expiry": "2024-07-04T06:02:00.247Z",
"statusCode": 404,
"createdAt": "2024-07-04T06:02:00.248Z",
"updatedAt": "2024-07-04T06:02:00.248Z",
"__v": 0
},
{
"_id": "66863b14437936b46e225d79",
"monitorId": "66863aa2437936b46e225d1f",
"status": false,
"responseTime": 140,
"expiry": "2024-07-04T06:03:00.167Z",
"statusCode": 404,
"createdAt": "2024-07-04T06:03:00.168Z",
"updatedAt": "2024-07-04T06:03:00.168Z",
"__v": 0
}
]
};
/**
* Function to calculate uptime duration based on the most recent check.
* @param {Array} checks Array of check objects.
* @returns {string} Uptime duration in hours, minutes, and seconds.
* TODO - NEED TO REVISIT THIS FOR PROPER LOGIC.
*/
const calculateUptimeDuration = (checks) => {
if (!checks || checks.length === 0) {
return 'N/A';
}
const mostRecentCheck = checks[0];
const currentTime = new Date();
const lastCheckedTime = new Date(mostRecentCheck.createdAt);
let uptimeDuration = currentTime - lastCheckedTime;
// Calculate hours, minutes, and seconds from uptime duration
// TODO - NEED TO REVISIT THIS FOR PROPER LOGIC.
let uptimeHours = Math.floor(uptimeDuration / (1000 * 60 * 60));
uptimeDuration %= (1000 * 60 * 60);
let uptimeMinutes = Math.floor(uptimeDuration / (1000 * 60));
uptimeDuration %= (1000 * 60);
let uptimeSeconds = Math.floor(uptimeDuration / 1000);
return `${uptimeHours}h ${uptimeMinutes}m ${uptimeSeconds}s`;
};
/**
* Helper function to get timestamp of the most recent check.
* @param {Array} checks Array of check objects.
* @returns {string} Timestamp of the most recent check.
* TODO - NEED TO REVISIT THIS FOR PROPER LOGIC.
*/
const getLastCheckedTimestamp = (checks) => {
if (!checks || checks.length === 0) {
return 'N/A'; // Handle case when no checks are available
}
const mostRecentCheck = checks[0];
return new Date(mostRecentCheck.createdAt).toLocaleString();
};
/**
* Helper function to count incidents (checks with status === false).
* @param {Array} checks Array of check objects.
* @returns {number} Number of incidents.
* TODO - NEED TO REVISIT THIS FOR PROPER LOGIC.
*/
const countIncidents = (checks) => {
if (!checks || checks.length === 0) {
return 0; // Handle case when no checks are available
}
// Count checks with status === false
// TODO - NEED TO REVISIT THIS FOR PROPER LOGIC.
const incidentCount = checks.filter(check => !check.status).length;
return incidentCount;
};
return (
<Box>
{/* Customized Tables Component */}
<CustomizedTables monitor={monitorData} />
{/* Uptime duration */}
<Typography
variant="body1"
sx={{
fontFamily: 'Roboto',
fontWeight: 600,
fontSize: '13px',
lineHeight: '20px',
color: '#344054',
marginTop: theme.spacing(2),
}}
>
Up for: {calculateUptimeDuration(monitorData.checks)}
</Typography>
{/* Last checked */}
<Typography
variant="body2"
sx={{
fontFamily: 'Roboto',
fontWeight: 400,
fontSize: '16px',
lineHeight: '24px',
color: '#1570EF',
marginBottom: theme.spacing(1),
}}
>
Last checked: {getLastCheckedTimestamp(monitorData.checks)}
</Typography>
{/* Incidents */}
<Typography
variant="body1"
sx={{
fontFamily: 'Roboto',
fontWeight: 600,
fontSize: '13px',
lineHeight: '20px',
color: '#344054',
}}
>
Incidents: {countIncidents(monitorData.checks)}
</Typography>
</Box>
);
};
export default DetailsPage;