Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4732f08

Browse files
authored
fix: show an error when a user doesn't have permission to view the health page (#16580)
1 parent 2c6df5a commit 4732f08

File tree

1 file changed

+149
-134
lines changed

1 file changed

+149
-134
lines changed

site/src/pages/HealthPage/HealthLayout.tsx

+149-134
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import IconButton from "@mui/material/IconButton";
77
import Tooltip from "@mui/material/Tooltip";
88
import { health, refreshHealth } from "api/queries/debug";
99
import type { HealthSeverity } from "api/typesGenerated";
10+
import { ErrorAlert } from "components/Alert/ErrorAlert";
1011
import { Loader } from "components/Loader/Loader";
1112
import { type ClassName, useClassName } from "hooks/useClassName";
1213
import kebabCase from "lodash/fp/kebabCase";
@@ -22,7 +23,11 @@ import { HealthIcon } from "./Content";
2223
export const HealthLayout: FC = () => {
2324
const theme = useTheme();
2425
const queryClient = useQueryClient();
25-
const { data: healthStatus } = useQuery({
26+
const {
27+
data: healthStatus,
28+
isLoading,
29+
error,
30+
} = useQuery({
2631
...health(),
2732
refetchInterval: 30_000,
2833
});
@@ -42,161 +47,171 @@ export const HealthLayout: FC = () => {
4247
const link = useClassName(classNames.link, []);
4348
const activeLink = useClassName(classNames.activeLink, []);
4449

50+
if (isLoading || !healthStatus) {
51+
return (
52+
<div className="p-6">
53+
<Loader />
54+
</div>
55+
);
56+
}
57+
58+
if (error) {
59+
return (
60+
<div className="p-6">
61+
<ErrorAlert error={error} />
62+
</div>
63+
);
64+
}
65+
4566
return (
4667
<>
4768
<Helmet>
4869
<title>{pageTitle("Health")}</title>
4970
</Helmet>
5071

51-
{healthStatus ? (
52-
<DashboardFullPage>
72+
<DashboardFullPage>
73+
<div
74+
css={{
75+
display: "flex",
76+
flexBasis: 0,
77+
flex: 1,
78+
overflow: "hidden",
79+
}}
80+
>
5381
<div
5482
css={{
55-
display: "flex",
56-
flexBasis: 0,
57-
flex: 1,
58-
overflow: "hidden",
83+
width: 256,
84+
flexShrink: 0,
85+
borderRight: `1px solid ${theme.palette.divider}`,
86+
fontSize: 14,
5987
}}
6088
>
6189
<div
6290
css={{
63-
width: 256,
64-
flexShrink: 0,
65-
borderRight: `1px solid ${theme.palette.divider}`,
66-
fontSize: 14,
91+
padding: 24,
92+
display: "flex",
93+
flexDirection: "column",
94+
gap: 16,
6795
}}
6896
>
69-
<div
70-
css={{
71-
padding: 24,
72-
display: "flex",
73-
flexDirection: "column",
74-
gap: 16,
75-
}}
76-
>
77-
<div>
78-
<div
79-
css={{
80-
display: "flex",
81-
alignItems: "center",
82-
justifyContent: "space-between",
83-
}}
84-
>
85-
<HealthIcon size={32} severity={healthStatus.severity} />
86-
87-
<Tooltip title="Refresh health checks">
88-
<IconButton
89-
size="small"
90-
disabled={isRefreshing}
91-
data-testid="healthcheck-refresh-button"
92-
onClick={() => {
93-
forceRefresh();
94-
}}
95-
>
96-
{isRefreshing ? (
97-
<CircularProgress size={16} />
98-
) : (
99-
<ReplayIcon css={{ width: 20, height: 20 }} />
100-
)}
101-
</IconButton>
102-
</Tooltip>
103-
</div>
104-
<div css={{ fontWeight: 500, marginTop: 16 }}>
105-
{healthStatus.healthy ? "Healthy" : "Unhealthy"}
106-
</div>
107-
<div
108-
css={{
109-
color: theme.palette.text.secondary,
110-
lineHeight: "150%",
111-
}}
112-
>
113-
{healthStatus.healthy
114-
? Object.keys(visibleSections).some((key) => {
115-
const section =
116-
healthStatus[key as keyof typeof visibleSections];
117-
return (
118-
section.warnings && section.warnings.length > 0
119-
);
120-
})
121-
? "All systems operational, but performance might be degraded"
122-
: "All systems operational"
123-
: "Some issues have been detected"}
124-
</div>
125-
</div>
97+
<div>
98+
<div
99+
css={{
100+
display: "flex",
101+
alignItems: "center",
102+
justifyContent: "space-between",
103+
}}
104+
>
105+
<HealthIcon size={32} severity={healthStatus.severity} />
126106

127-
<div css={{ display: "flex", flexDirection: "column" }}>
128-
<span css={{ fontWeight: 500 }}>Last check</span>
129-
<span
130-
data-chromatic="ignore"
131-
css={{
132-
color: theme.palette.text.secondary,
133-
lineHeight: "150%",
134-
}}
135-
>
136-
{createDayString(healthStatus.time)}
137-
</span>
107+
<Tooltip title="Refresh health checks">
108+
<IconButton
109+
size="small"
110+
disabled={isRefreshing}
111+
data-testid="healthcheck-refresh-button"
112+
onClick={() => {
113+
forceRefresh();
114+
}}
115+
>
116+
{isRefreshing ? (
117+
<CircularProgress size={16} />
118+
) : (
119+
<ReplayIcon css={{ width: 20, height: 20 }} />
120+
)}
121+
</IconButton>
122+
</Tooltip>
138123
</div>
139-
140-
<div css={{ display: "flex", flexDirection: "column" }}>
141-
<span css={{ fontWeight: 500 }}>Version</span>
142-
<span
143-
data-chromatic="ignore"
144-
css={{
145-
color: theme.palette.text.secondary,
146-
lineHeight: "150%",
147-
}}
148-
>
149-
{healthStatus.coder_version}
150-
</span>
124+
<div css={{ fontWeight: 500, marginTop: 16 }}>
125+
{healthStatus.healthy ? "Healthy" : "Unhealthy"}
126+
</div>
127+
<div
128+
css={{
129+
color: theme.palette.text.secondary,
130+
lineHeight: "150%",
131+
}}
132+
>
133+
{healthStatus.healthy
134+
? Object.keys(visibleSections).some((key) => {
135+
const section =
136+
healthStatus[key as keyof typeof visibleSections];
137+
return section.warnings && section.warnings.length > 0;
138+
})
139+
? "All systems operational, but performance might be degraded"
140+
: "All systems operational"
141+
: "Some issues have been detected"}
151142
</div>
152143
</div>
153144

154-
<nav css={{ display: "flex", flexDirection: "column", gap: 1 }}>
155-
{Object.entries(visibleSections)
156-
.sort()
157-
.map(([key, label]) => {
158-
const healthSection =
159-
healthStatus[key as keyof typeof visibleSections];
160-
161-
return (
162-
<NavLink
163-
end
164-
key={key}
165-
to={`/health/${kebabCase(key)}`}
166-
className={({ isActive }) =>
167-
cx([link, isActive && activeLink])
168-
}
169-
>
170-
<HealthIcon
171-
size={16}
172-
severity={healthSection.severity as HealthSeverity}
173-
/>
174-
{label}
175-
{healthSection.dismissed && (
176-
<NotificationsOffOutlined
177-
css={{
178-
fontSize: 14,
179-
marginLeft: "auto",
180-
color: theme.palette.text.disabled,
181-
}}
182-
/>
183-
)}
184-
</NavLink>
185-
);
186-
})}
187-
</nav>
188-
</div>
145+
<div css={{ display: "flex", flexDirection: "column" }}>
146+
<span css={{ fontWeight: 500 }}>Last check</span>
147+
<span
148+
data-chromatic="ignore"
149+
css={{
150+
color: theme.palette.text.secondary,
151+
lineHeight: "150%",
152+
}}
153+
>
154+
{createDayString(healthStatus.time)}
155+
</span>
156+
</div>
189157

190-
<div css={{ overflowY: "auto", width: "100%" }}>
191-
<Suspense fallback={<Loader />}>
192-
<Outlet context={healthStatus} />
193-
</Suspense>
158+
<div css={{ display: "flex", flexDirection: "column" }}>
159+
<span css={{ fontWeight: 500 }}>Version</span>
160+
<span
161+
data-chromatic="ignore"
162+
css={{
163+
color: theme.palette.text.secondary,
164+
lineHeight: "150%",
165+
}}
166+
>
167+
{healthStatus.coder_version}
168+
</span>
169+
</div>
194170
</div>
171+
172+
<nav css={{ display: "flex", flexDirection: "column", gap: 1 }}>
173+
{Object.entries(visibleSections)
174+
.sort()
175+
.map(([key, label]) => {
176+
const healthSection =
177+
healthStatus[key as keyof typeof visibleSections];
178+
179+
return (
180+
<NavLink
181+
end
182+
key={key}
183+
to={`/health/${kebabCase(key)}`}
184+
className={({ isActive }) =>
185+
cx([link, isActive && activeLink])
186+
}
187+
>
188+
<HealthIcon
189+
size={16}
190+
severity={healthSection.severity as HealthSeverity}
191+
/>
192+
{label}
193+
{healthSection.dismissed && (
194+
<NotificationsOffOutlined
195+
css={{
196+
fontSize: 14,
197+
marginLeft: "auto",
198+
color: theme.palette.text.disabled,
199+
}}
200+
/>
201+
)}
202+
</NavLink>
203+
);
204+
})}
205+
</nav>
195206
</div>
196-
</DashboardFullPage>
197-
) : (
198-
<Loader />
199-
)}
207+
208+
<div css={{ overflowY: "auto", width: "100%" }}>
209+
<Suspense fallback={<Loader />}>
210+
<Outlet context={healthStatus} />
211+
</Suspense>
212+
</div>
213+
</div>
214+
</DashboardFullPage>
200215
</>
201216
);
202217
};

0 commit comments

Comments
 (0)