Use StatBox consistently
This commit is contained in:
1 parent
aee3e6a604
commit
e37413771e
5 files changed
+128
-132
No files matched your search
@@ -20,6 +20,7 @@ import {
|
||||
TemperatureTooltip,
|
||||
} from "../../../Components/Charts/Utils/chartUtils";
|
||||
import PropTypes from "prop-types";
|
||||
import StatBox from "../../../Components/StatBox";
|
||||
|
||||
const BASE_BOX_PADDING_VERTICAL = 4;
|
||||
const BASE_BOX_PADDING_HORIZONTAL = 8;
|
||||
@@ -29,18 +30,50 @@ const TYPOGRAPHY_PADDING = 8;
|
||||
* @param {number} bytes - Number of bytes to convert
|
||||
* @returns {number} Converted value in gigabytes
|
||||
*/
|
||||
const formatBytes = (bytes) => {
|
||||
if (bytes === undefined || bytes === null) return "0 GB";
|
||||
if (typeof bytes !== "number") return "0 GB";
|
||||
if (bytes === 0) return "0 GB";
|
||||
const formatBytes = (bytes, space = false) => {
|
||||
if (bytes === undefined || bytes === null)
|
||||
return (
|
||||
<>
|
||||
{0}
|
||||
{space ? " " : ""}
|
||||
<Typography component="span">GB</Typography>
|
||||
</>
|
||||
);
|
||||
if (typeof bytes !== "number")
|
||||
return (
|
||||
<>
|
||||
{0}
|
||||
{space ? " " : ""}
|
||||
<Typography component="span">GB</Typography>
|
||||
</>
|
||||
);
|
||||
if (bytes === 0)
|
||||
return (
|
||||
<>
|
||||
{0}
|
||||
{space ? " " : ""}
|
||||
<Typography component="span">GB</Typography>
|
||||
</>
|
||||
);
|
||||
|
||||
const GB = bytes / (1024 * 1024 * 1024);
|
||||
const MB = bytes / (1024 * 1024);
|
||||
|
||||
if (GB >= 1) {
|
||||
return `${Number(GB.toFixed(0))} GB`;
|
||||
return (
|
||||
<>
|
||||
{Number(GB.toFixed(0))}
|
||||
{space ? " " : ""}
|
||||
<Typography component="span">GB</Typography>
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
return `${Number(MB.toFixed(0))} MB`;
|
||||
return (
|
||||
<>
|
||||
{Number(MB.toFixed(0))}
|
||||
<Typography component="span">MB</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -93,27 +126,6 @@ BaseBox.propTypes = {
|
||||
sx: PropTypes.object,
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a statistic box with a heading and subheading
|
||||
* @param {Object} props - Component properties
|
||||
* @param {string} props.heading - Primary heading text
|
||||
* @param {string} props.subHeading - Secondary heading text
|
||||
* @returns {React.ReactElement} Stat box component
|
||||
*/
|
||||
const StatBox = ({ heading, subHeading }) => {
|
||||
return (
|
||||
<BaseBox>
|
||||
<Typography component="h2">{heading}</Typography>
|
||||
<Typography>{subHeading}</Typography>
|
||||
</BaseBox>
|
||||
);
|
||||
};
|
||||
|
||||
StatBox.propTypes = {
|
||||
heading: PropTypes.string.isRequired,
|
||||
subHeading: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a gauge box with usage visualization
|
||||
* @param {Object} props - Component properties
|
||||
@@ -193,7 +205,7 @@ const InfrastructureDetails = () => {
|
||||
const [monitor, setMonitor] = useState(null);
|
||||
const { authToken } = useSelector((state) => state.auth);
|
||||
const [dateRange, setDateRange] = useState("all");
|
||||
const { statusColor, determineState } = useUtils();
|
||||
const { statusColor, statusStyles, determineState } = useUtils();
|
||||
// These calculations are needed because ResponsiveContainer
|
||||
// doesn't take padding of parent/siblings into account
|
||||
// when calculating height.
|
||||
@@ -205,7 +217,7 @@ const InfrastructureDetails = () => {
|
||||
(chartContainerHeight - totalChartContainerPadding - totalTypographyPadding) * 0.95;
|
||||
// end height calculations
|
||||
|
||||
const buildStatBoxes = (checks) => {
|
||||
const buildStatBoxes = (checks, uptime) => {
|
||||
let latestCheck = checks[0] ?? null;
|
||||
if (latestCheck === null) return [];
|
||||
|
||||
@@ -224,25 +236,51 @@ const InfrastructureDetails = () => {
|
||||
const platform = latestCheck?.host?.platform ?? null;
|
||||
const osPlatform = os === null && platform === null ? null : `${os} ${platform}`;
|
||||
return [
|
||||
{
|
||||
id: 7,
|
||||
sx: statusStyles[determineState(monitor)],
|
||||
heading: "Status",
|
||||
subHeading: monitor?.status === true ? "Active" : "Inactive",
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
heading: "CPU (Physical)",
|
||||
subHeading: `${physicalCores} cores`,
|
||||
subHeading: (
|
||||
<>
|
||||
{physicalCores}
|
||||
<Typography component="span">cores</Typography>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
heading: "CPU (Logical)",
|
||||
subHeading: `${logicalCores} cores`,
|
||||
subHeading: (
|
||||
<>
|
||||
{logicalCores}
|
||||
<Typography component="span">cores</Typography>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
heading: "CPU Frequency",
|
||||
subHeading: `${(cpuFrequency / 1000).toFixed(2)} Ghz`,
|
||||
subHeading: (
|
||||
<>
|
||||
{(cpuFrequency / 1000).toFixed(2)}
|
||||
<Typography component="span">Ghz</Typography>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
heading: "Average CPU Temperature",
|
||||
subHeading: `${cpuTemperature.toFixed(2)} C`,
|
||||
subHeading: (
|
||||
<>
|
||||
{cpuTemperature.toFixed(2)}
|
||||
<Typography component="span">C</Typography>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
@@ -254,12 +292,17 @@ const InfrastructureDetails = () => {
|
||||
heading: "Disk",
|
||||
subHeading: formatBytes(diskTotalBytes),
|
||||
},
|
||||
{ id: 6, heading: "Uptime", subHeading: "100%" },
|
||||
{
|
||||
id: 7,
|
||||
heading: "Status",
|
||||
subHeading: monitor?.status === true ? "Active" : "Inactive",
|
||||
id: 6,
|
||||
heading: "Uptime",
|
||||
subHeading: (
|
||||
<>
|
||||
{(uptime * 100).toFixed(2)}
|
||||
<Typography component="span">%</Typography>
|
||||
</>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
id: 8,
|
||||
heading: "OS",
|
||||
@@ -285,9 +328,9 @@ const InfrastructureDetails = () => {
|
||||
value: decimalToPercentage(memoryUsagePercent),
|
||||
heading: "Memory usage",
|
||||
metricOne: "Used",
|
||||
valueOne: formatBytes(memoryUsedBytes),
|
||||
valueOne: formatBytes(memoryUsedBytes, true),
|
||||
metricTwo: "Total",
|
||||
valueTwo: formatBytes(memoryTotalBytes),
|
||||
valueTwo: formatBytes(memoryTotalBytes, true),
|
||||
},
|
||||
{
|
||||
type: "cpu",
|
||||
@@ -304,9 +347,9 @@ const InfrastructureDetails = () => {
|
||||
value: decimalToPercentage(disk.usage_percent),
|
||||
heading: `Disk${idx} usage`,
|
||||
metricOne: "Used",
|
||||
valueOne: formatBytes(disk.total_bytes - disk.free_bytes),
|
||||
valueOne: formatBytes(disk.total_bytes - disk.free_bytes, true),
|
||||
metricTwo: "Total",
|
||||
valueTwo: formatBytes(disk.total_bytes),
|
||||
valueTwo: formatBytes(disk.total_bytes, true),
|
||||
})),
|
||||
];
|
||||
};
|
||||
@@ -466,7 +509,10 @@ const InfrastructureDetails = () => {
|
||||
fetchData();
|
||||
}, [authToken, monitorId, dateRange, navigate]);
|
||||
|
||||
const statBoxConfigs = buildStatBoxes(monitor?.checks ?? []);
|
||||
const statBoxConfigs = buildStatBoxes(
|
||||
monitor?.checks ?? [],
|
||||
monitor?.uptimePercentage ?? "Unknown"
|
||||
);
|
||||
const gaugeBoxConfigs = buildGaugeBoxConfigs(monitor?.checks ?? []);
|
||||
const areaChartConfigs = buildAreaChartConfigs(monitor?.checks ?? []);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useTheme } from "@emotion/react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDurationRounded, formatDurationSplit } from "../../../Utils/timeUtils";
|
||||
import { ChartBox, IconBox, StatBox } from "./styled";
|
||||
import { ChartBox, IconBox } from "./styled";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
import { networkService } from "../../../main";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
@@ -22,6 +22,7 @@ import PieChart from "./Charts/PieChart";
|
||||
import useUtils from "../../Uptime/utils";
|
||||
import "./index.css";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import StatBox from "../../../Components/StatBox";
|
||||
|
||||
const PageSpeedDetails = () => {
|
||||
const theme = useTheme();
|
||||
@@ -187,20 +188,24 @@ const PageSpeedDetails = () => {
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<StatBox>
|
||||
<Typography component="h2">checks since</Typography>
|
||||
<Typography>
|
||||
{splitDuration(monitor?.uptimeDuration)}
|
||||
<Typography component="span">ago</Typography>
|
||||
</Typography>
|
||||
</StatBox>
|
||||
<StatBox>
|
||||
<Typography component="h2">last check</Typography>
|
||||
<Typography>
|
||||
{splitDuration(monitor?.lastChecked)}
|
||||
<Typography component="span">ago</Typography>
|
||||
</Typography>
|
||||
</StatBox>
|
||||
<StatBox
|
||||
heading="checks since"
|
||||
subHeading={
|
||||
<>
|
||||
{splitDuration(monitor?.uptimeDuration)}
|
||||
<Typography component="span">ago</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<StatBox
|
||||
heading="last check"
|
||||
subHeading={
|
||||
<>
|
||||
{splitDuration(monitor?.lastChecked)}
|
||||
<Typography component="span">ago</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Box>
|
||||
<Typography
|
||||
|
||||
@@ -63,31 +63,3 @@ export const IconBox = styled(Box)(({ theme }) => ({
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const StatBox = styled(Box)(({ theme }) => ({
|
||||
padding: `${theme.spacing(4)} ${theme.spacing(8)}`,
|
||||
minWidth: 200,
|
||||
width: 225,
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.palette.background.main,
|
||||
background: `linear-gradient(340deg, ${theme.palette.background.accent} 20%, ${theme.palette.background.main} 45%)`,
|
||||
"& h2": {
|
||||
fontSize: 13,
|
||||
fontWeight: 500,
|
||||
color: theme.palette.text.secondary,
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
"& p": {
|
||||
fontSize: 18,
|
||||
color: theme.palette.text.primary,
|
||||
marginTop: theme.spacing(2),
|
||||
"& span": {
|
||||
color: theme.palette.text.tertiary,
|
||||
marginLeft: theme.spacing(2),
|
||||
fontSize: 15,
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -26,7 +26,8 @@ import HistoryIcon from "../../../assets/icons/history-icon.svg?react";
|
||||
import PaginationTable from "./PaginationTable";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import { StatBox, ChartBox, IconBox } from "./styled";
|
||||
import StatBox from "../../../Components/StatBox";
|
||||
import { ChartBox, IconBox } from "./styled";
|
||||
import { DownBarChart, ResponseGaugeChart, UpBarChart } from "./Charts";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import "./index.css";
|
||||
@@ -283,24 +284,24 @@ const DetailsPage = () => {
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<StatBox sx={statusStyles[determineState(monitor)]}>
|
||||
<Typography component="h2">active for</Typography>
|
||||
<Typography>{splitDuration(monitor?.uptimeDuration)}</Typography>
|
||||
</StatBox>
|
||||
<StatBox>
|
||||
<Typography component="h2">last check</Typography>
|
||||
<Typography>
|
||||
{splitDuration(monitor?.lastChecked)}
|
||||
<Typography component="span">ago</Typography>
|
||||
</Typography>
|
||||
</StatBox>
|
||||
<StatBox>
|
||||
<Typography component="h2">last response time</Typography>
|
||||
<Typography>
|
||||
{monitor?.latestResponseTime}
|
||||
<Typography component="span">ms</Typography>
|
||||
</Typography>
|
||||
</StatBox>
|
||||
<StatBox
|
||||
sx={statusStyles[determineState(monitor)]}
|
||||
heading={"active for"}
|
||||
subHeading={splitDuration(monitor?.uptimeDuration)}
|
||||
/>
|
||||
<StatBox
|
||||
heading="last check"
|
||||
subHeading={splitDuration(monitor?.lastChecked)}
|
||||
/>
|
||||
<StatBox
|
||||
heading="last response time"
|
||||
subHeading={
|
||||
<>
|
||||
{monitor?.latestResponseTime}
|
||||
<Typography component="span">{"ms"}</Typography>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Stack>
|
||||
<Box>
|
||||
<Stack
|
||||
|
||||
@@ -66,31 +66,3 @@ export const IconBox = styled(Box)(({ theme }) => ({
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const StatBox = styled(Box)(({ theme }) => ({
|
||||
padding: `${theme.spacing(4)} ${theme.spacing(8)}`,
|
||||
minWidth: 200,
|
||||
width: 225,
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: 4,
|
||||
backgroundColor: theme.palette.background.main,
|
||||
background: `linear-gradient(340deg, ${theme.palette.background.accent} 20%, ${theme.palette.background.main} 45%)`,
|
||||
"& h2": {
|
||||
fontSize: 13,
|
||||
fontWeight: 500,
|
||||
color: theme.palette.text.secondary,
|
||||
textTransform: "uppercase",
|
||||
},
|
||||
"& p": {
|
||||
fontSize: 18,
|
||||
color: theme.palette.text.primary,
|
||||
marginTop: theme.spacing(2),
|
||||
"& span": {
|
||||
color: theme.palette.text.tertiary,
|
||||
marginLeft: theme.spacing(2),
|
||||
fontSize: 15,
|
||||
},
|
||||
},
|
||||
}));
|
||||
Reference in new issue
Block a user