refactor(site): improve health check page sidebar (#10960)

This commit is contained in:
Bruno Quaresma
2023-12-01 12:43:51 -03:00
committed by GitHub
parent 432925df31
commit 2aa79369a2
3 changed files with 130 additions and 154 deletions
@@ -35,11 +35,10 @@ export const SyntaxHighlighter: FC<{
return (
<div
data-chromatic="ignore"
css={(theme) => ({
css={{
padding: "8px 0",
background: theme.palette.background.paper,
height: "100%",
})}
}}
>
{hasDiff ? (
<DiffEditor original={compareWith} modified={value} {...commonProps} />
+126 -149
View File
@@ -1,4 +1,3 @@
import { type Interpolation, type Theme } from "@emotion/react";
import Box from "@mui/material/Box";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { getHealth } from "api/api";
@@ -6,23 +5,17 @@ import { Loader } from "components/Loader/Loader";
import { useTab } from "hooks";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { colors } from "theme/colors";
import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined";
import ErrorOutline from "@mui/icons-material/ErrorOutline";
import { SyntaxHighlighter } from "components/SyntaxHighlighter/SyntaxHighlighter";
import { Stack } from "components/Stack/Stack";
import {
FullWidthPageHeader,
PageHeaderTitle,
PageHeaderSubtitle,
} from "components/PageHeader/FullWidthPageHeader";
import { Stats, StatsItem } from "components/Stats/Stats";
import { createDayString } from "utils/createDayString";
import { DashboardFullPage } from "components/Dashboard/DashboardLayout";
import { LoadingButton } from "@mui/lab";
import ReplayIcon from "@mui/icons-material/Replay";
import { FC } from "react";
import { health, refreshHealth } from "api/queries/debug";
import { useTheme } from "@mui/material/styles";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import CircularProgress from "@mui/material/CircularProgress";
const sections = {
derp: "DERP",
@@ -74,62 +67,10 @@ export function HealthPageView({
forceRefresh: () => void;
isRefreshing: boolean;
}) {
const theme = useTheme();
return (
<DashboardFullPage>
<FullWidthPageHeader sticky={false}>
<Stack direction="row" spacing={2} alignItems="center">
{healthStatus.healthy ? (
<CheckCircleOutlined
sx={{
width: 32,
height: 32,
color: (theme) => theme.palette.success.light,
}}
/>
) : (
<ErrorOutline
sx={{
width: 32,
height: 32,
color: (theme) => theme.palette.error.main,
}}
/>
)}
<div>
<PageHeaderTitle>
{healthStatus.healthy ? "Healthy" : "Unhealthy"}
</PageHeaderTitle>
<PageHeaderSubtitle>
{healthStatus.healthy
? Object.keys(sections).some(
(key) =>
healthStatus[key as keyof typeof sections].warnings !==
null &&
healthStatus[key as keyof typeof sections].warnings
.length > 0,
)
? "All systems operational, but performance might be degraded"
: "All systems operational"
: "Some issues have been detected"}
</PageHeaderSubtitle>
</div>
</Stack>
<Stats aria-label="Deployment details" css={styles.stats}>
<StatsItem
css={styles.statsItem}
label="Last check"
value={createDayString(healthStatus.time)}
/>
<StatsItem
css={styles.statsItem}
label="Coder version"
value={healthStatus.coder_version}
/>
</Stats>
<RefreshButton loading={isRefreshing} handleAction={forceRefresh} />
</FullWidthPageHeader>
<Box
sx={{
display: "flex",
@@ -138,26 +79,112 @@ export function HealthPageView({
overflow: "hidden",
}}
>
<Box
sx={{
<div
css={{
width: 256,
flexShrink: 0,
borderRight: (theme) => `1px solid ${theme.palette.divider}`,
borderRight: `1px solid ${theme.palette.divider}`,
fontSize: 14,
}}
>
<Box
sx={{
fontSize: 10,
textTransform: "uppercase",
fontWeight: 500,
color: (theme) => theme.palette.text.secondary,
padding: "12px 24px",
letterSpacing: "0.5px",
<div
css={{
padding: 24,
display: "flex",
flexDirection: "column",
gap: 16,
}}
>
Health
</Box>
<Box component="nav">
<div>
<div
css={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
{healthStatus.healthy ? (
<CheckCircleOutlined
css={{
width: 32,
height: 32,
color: theme.palette.success.light,
}}
/>
) : (
<ErrorOutline
css={{
width: 32,
height: 32,
color: theme.palette.error.light,
}}
/>
)}
<Tooltip title="Refresh health checks">
<IconButton
size="small"
disabled={isRefreshing}
data-testid="healthcheck-refresh-button"
onClick={forceRefresh}
>
{isRefreshing ? (
<CircularProgress size={16} />
) : (
<ReplayIcon css={{ width: 20, height: 20 }} />
)}
</IconButton>
</Tooltip>
</div>
<div css={{ fontWeight: 500, marginTop: 16 }}>
{healthStatus.healthy ? "Healthy" : "Unhealthy"}
</div>
<div
css={{
color: theme.palette.text.secondary,
lineHeight: "150%",
}}
>
{healthStatus.healthy
? Object.keys(sections).some(
(key) =>
healthStatus[key as keyof typeof sections].warnings !==
null &&
healthStatus[key as keyof typeof sections].warnings
.length > 0,
)
? "All systems operational, but performance might be degraded"
: "All systems operational"
: "Some issues have been detected"}
</div>
</div>
<div css={{ display: "flex", flexDirection: "column" }}>
<span css={{ fontWeight: 500 }}>Last check</span>
<span
css={{
color: theme.palette.text.secondary,
lineHeight: "150%",
}}
>
{createDayString(healthStatus.time)}
</span>
</div>
<div css={{ display: "flex", flexDirection: "column" }}>
<span css={{ fontWeight: 500 }}>Version</span>
<span
css={{
color: theme.palette.text.secondary,
lineHeight: "150%",
}}
>
{healthStatus.coder_version}
</span>
</div>
</div>
<nav css={{ display: "flex", flexDirection: "column", gap: 1 }}>
{Object.keys(sections)
.sort()
.map((key) => {
@@ -168,68 +195,68 @@ export function HealthPageView({
const isHealthy = healthSection.healthy;
const isWarning = healthSection.warnings?.length > 0;
return (
<Box
component="button"
<button
key={key}
onClick={() => {
tab.set(key);
}}
sx={{
background: isActive ? colors.gray[13] : "none",
css={{
background: isActive
? theme.palette.action.hover
: "none",
border: "none",
fontSize: 14,
width: "100%",
display: "flex",
alignItems: "center",
gap: 1,
gap: 12,
textAlign: "left",
height: 36,
padding: "0 24px",
cursor: "pointer",
pointerEvents: isActive ? "none" : "auto",
color: (theme) =>
isActive
? theme.palette.text.primary
: theme.palette.text.secondary,
color: isActive
? theme.palette.text.primary
: theme.palette.text.secondary,
"&:hover": {
background: (theme) => theme.palette.action.hover,
color: (theme) => theme.palette.text.primary,
background: theme.palette.action.hover,
color: theme.palette.text.primary,
},
}}
>
{isHealthy ? (
isWarning ? (
<CheckCircleOutlined
sx={{
css={{
width: 16,
height: 16,
color: (theme) => theme.palette.warning.main,
color: theme.palette.warning.light,
}}
/>
) : (
<CheckCircleOutlined
sx={{
css={{
width: 16,
height: 16,
color: (theme) => theme.palette.success.light,
color: theme.palette.success.light,
}}
/>
)
) : (
<ErrorOutline
sx={{
css={{
width: 16,
height: 16,
color: (theme) => theme.palette.error.main,
color: theme.palette.error.main,
}}
/>
)}
{label}
</Box>
</button>
);
})}
</Box>
</Box>
</nav>
</div>
{/* 62px - navbar and 36px - the bottom bar */}
<Box sx={{ overflowY: "auto", width: "100%" }} data-chromatic="ignore">
<SyntaxHighlighter
@@ -246,53 +273,3 @@ export function HealthPageView({
</DashboardFullPage>
);
}
const styles = {
stats: (theme) => ({
padding: 0,
border: 0,
gap: 48,
rowGap: 24,
flex: 1,
[theme.breakpoints.down("md")]: {
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: 8,
},
}),
statsItem: {
flexDirection: "column",
gap: 0,
padding: 0,
"& > span:first-of-type": {
fontSize: 12,
fontWeight: 500,
},
},
} satisfies Record<string, Interpolation<Theme>>;
interface HealthcheckAction {
handleAction: () => void;
loading: boolean;
}
export const RefreshButton: FC<HealthcheckAction> = ({
handleAction,
loading,
}) => {
return (
<LoadingButton
loading={loading}
loadingPosition="start"
data-testid="healthcheck-refresh-button"
startIcon={<ReplayIcon />}
onClick={handleAction}
>
Refresh
</LoadingButton>
);
};
+2 -2
View File
@@ -80,12 +80,12 @@ export let dark = createTheme({
body1: {
fontSize: "1rem" /* 16px at default scaling */,
lineHeight: "1.5rem" /* 24px at default scaling */,
lineHeight: "160%",
},
body2: {
fontSize: "0.875rem" /* 14px at default scaling */,
lineHeight: "1.25rem" /* 20px at default scaling */,
lineHeight: "160%",
},
},
shape: {