1
- import { type Interpolation , type Theme } from "@emotion/react" ;
2
1
import Box from "@mui/material/Box" ;
3
2
import { useMutation , useQuery , useQueryClient } from "react-query" ;
4
3
import { getHealth } from "api/api" ;
5
4
import { Loader } from "components/Loader/Loader" ;
6
5
import { useTab } from "hooks" ;
7
6
import { Helmet } from "react-helmet-async" ;
8
7
import { pageTitle } from "utils/page" ;
9
- import { colors } from "theme/colors" ;
10
8
import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined" ;
11
9
import ErrorOutline from "@mui/icons-material/ErrorOutline" ;
12
10
import { SyntaxHighlighter } from "components/SyntaxHighlighter/SyntaxHighlighter" ;
13
- import { Stack } from "components/Stack/Stack" ;
14
- import {
15
- FullWidthPageHeader ,
16
- PageHeaderTitle ,
17
- PageHeaderSubtitle ,
18
- } from "components/PageHeader/FullWidthPageHeader" ;
19
- import { Stats , StatsItem } from "components/Stats/Stats" ;
20
11
import { createDayString } from "utils/createDayString" ;
21
12
import { DashboardFullPage } from "components/Dashboard/DashboardLayout" ;
22
- import { LoadingButton } from "@mui/lab" ;
23
13
import ReplayIcon from "@mui/icons-material/Replay" ;
24
- import { FC } from "react" ;
25
14
import { health , refreshHealth } from "api/queries/debug" ;
15
+ import { useTheme } from "@mui/material/styles" ;
16
+ import IconButton from "@mui/material/IconButton" ;
17
+ import Tooltip from "@mui/material/Tooltip" ;
18
+ import CircularProgress from "@mui/material/CircularProgress" ;
26
19
27
20
const sections = {
28
21
derp : "DERP" ,
@@ -74,62 +67,10 @@ export function HealthPageView({
74
67
forceRefresh : ( ) => void ;
75
68
isRefreshing : boolean ;
76
69
} ) {
70
+ const theme = useTheme ( ) ;
71
+
77
72
return (
78
73
< DashboardFullPage >
79
- < FullWidthPageHeader sticky = { false } >
80
- < Stack direction = "row" spacing = { 2 } alignItems = "center" >
81
- { healthStatus . healthy ? (
82
- < CheckCircleOutlined
83
- sx = { {
84
- width : 32 ,
85
- height : 32 ,
86
- color : ( theme ) => theme . palette . success . light ,
87
- } }
88
- />
89
- ) : (
90
- < ErrorOutline
91
- sx = { {
92
- width : 32 ,
93
- height : 32 ,
94
- color : ( theme ) => theme . palette . error . main ,
95
- } }
96
- />
97
- ) }
98
-
99
- < div >
100
- < PageHeaderTitle >
101
- { healthStatus . healthy ? "Healthy" : "Unhealthy" }
102
- </ PageHeaderTitle >
103
- < PageHeaderSubtitle >
104
- { healthStatus . healthy
105
- ? Object . keys ( sections ) . some (
106
- ( key ) =>
107
- healthStatus [ key as keyof typeof sections ] . warnings !==
108
- null &&
109
- healthStatus [ key as keyof typeof sections ] . warnings
110
- . length > 0 ,
111
- )
112
- ? "All systems operational, but performance might be degraded"
113
- : "All systems operational"
114
- : "Some issues have been detected" }
115
- </ PageHeaderSubtitle >
116
- </ div >
117
- </ Stack >
118
-
119
- < Stats aria-label = "Deployment details" css = { styles . stats } >
120
- < StatsItem
121
- css = { styles . statsItem }
122
- label = "Last check"
123
- value = { createDayString ( healthStatus . time ) }
124
- />
125
- < StatsItem
126
- css = { styles . statsItem }
127
- label = "Coder version"
128
- value = { healthStatus . coder_version }
129
- />
130
- </ Stats >
131
- < RefreshButton loading = { isRefreshing } handleAction = { forceRefresh } />
132
- </ FullWidthPageHeader >
133
74
< Box
134
75
sx = { {
135
76
display : "flex" ,
@@ -138,26 +79,112 @@ export function HealthPageView({
138
79
overflow : "hidden" ,
139
80
} }
140
81
>
141
- < Box
142
- sx = { {
82
+ < div
83
+ css = { {
143
84
width : 256 ,
144
85
flexShrink : 0 ,
145
- borderRight : ( theme ) => `1px solid ${ theme . palette . divider } ` ,
86
+ borderRight : `1px solid ${ theme . palette . divider } ` ,
87
+ fontSize : 14 ,
146
88
} }
147
89
>
148
- < Box
149
- sx = { {
150
- fontSize : 10 ,
151
- textTransform : "uppercase" ,
152
- fontWeight : 500 ,
153
- color : ( theme ) => theme . palette . text . secondary ,
154
- padding : "12px 24px" ,
155
- letterSpacing : "0.5px" ,
90
+ < div
91
+ css = { {
92
+ padding : 24 ,
93
+ display : "flex" ,
94
+ flexDirection : "column" ,
95
+ gap : 16 ,
156
96
} }
157
97
>
158
- Health
159
- </ Box >
160
- < Box component = "nav" >
98
+ < div >
99
+ < div
100
+ css = { {
101
+ display : "flex" ,
102
+ alignItems : "center" ,
103
+ justifyContent : "space-between" ,
104
+ } }
105
+ >
106
+ { healthStatus . healthy ? (
107
+ < CheckCircleOutlined
108
+ css = { {
109
+ width : 32 ,
110
+ height : 32 ,
111
+ color : theme . palette . success . light ,
112
+ } }
113
+ />
114
+ ) : (
115
+ < ErrorOutline
116
+ css = { {
117
+ width : 32 ,
118
+ height : 32 ,
119
+ color : theme . palette . error . light ,
120
+ } }
121
+ />
122
+ ) }
123
+
124
+ < Tooltip title = "Refresh health checks" >
125
+ < IconButton
126
+ size = "small"
127
+ disabled = { isRefreshing }
128
+ data-testid = "healthcheck-refresh-button"
129
+ onClick = { forceRefresh }
130
+ >
131
+ { isRefreshing ? (
132
+ < CircularProgress size = { 16 } />
133
+ ) : (
134
+ < ReplayIcon css = { { width : 20 , height : 20 } } />
135
+ ) }
136
+ </ IconButton >
137
+ </ Tooltip >
138
+ </ div >
139
+ < div css = { { fontWeight : 500 , marginTop : 16 } } >
140
+ { healthStatus . healthy ? "Healthy" : "Unhealthy" }
141
+ </ div >
142
+ < div
143
+ css = { {
144
+ color : theme . palette . text . secondary ,
145
+ lineHeight : "150%" ,
146
+ } }
147
+ >
148
+ { healthStatus . healthy
149
+ ? Object . keys ( sections ) . some (
150
+ ( key ) =>
151
+ healthStatus [ key as keyof typeof sections ] . warnings !==
152
+ null &&
153
+ healthStatus [ key as keyof typeof sections ] . warnings
154
+ . length > 0 ,
155
+ )
156
+ ? "All systems operational, but performance might be degraded"
157
+ : "All systems operational"
158
+ : "Some issues have been detected" }
159
+ </ div >
160
+ </ div >
161
+
162
+ < div css = { { display : "flex" , flexDirection : "column" } } >
163
+ < span css = { { fontWeight : 500 } } > Last check</ span >
164
+ < span
165
+ css = { {
166
+ color : theme . palette . text . secondary ,
167
+ lineHeight : "150%" ,
168
+ } }
169
+ >
170
+ { createDayString ( healthStatus . time ) }
171
+ </ span >
172
+ </ div >
173
+
174
+ < div css = { { display : "flex" , flexDirection : "column" } } >
175
+ < span css = { { fontWeight : 500 } } > Version</ span >
176
+ < span
177
+ css = { {
178
+ color : theme . palette . text . secondary ,
179
+ lineHeight : "150%" ,
180
+ } }
181
+ >
182
+ { healthStatus . coder_version }
183
+ </ span >
184
+ </ div >
185
+ </ div >
186
+
187
+ < nav css = { { display : "flex" , flexDirection : "column" , gap : 1 } } >
161
188
{ Object . keys ( sections )
162
189
. sort ( )
163
190
. map ( ( key ) => {
@@ -168,68 +195,68 @@ export function HealthPageView({
168
195
const isHealthy = healthSection . healthy ;
169
196
const isWarning = healthSection . warnings ?. length > 0 ;
170
197
return (
171
- < Box
172
- component = "button"
198
+ < button
173
199
key = { key }
174
200
onClick = { ( ) => {
175
201
tab . set ( key ) ;
176
202
} }
177
- sx = { {
178
- background : isActive ? colors . gray [ 13 ] : "none" ,
203
+ css = { {
204
+ background : isActive
205
+ ? theme . palette . action . hover
206
+ : "none" ,
179
207
border : "none" ,
180
208
fontSize : 14 ,
181
209
width : "100%" ,
182
210
display : "flex" ,
183
211
alignItems : "center" ,
184
- gap : 1 ,
212
+ gap : 12 ,
185
213
textAlign : "left" ,
186
214
height : 36 ,
187
215
padding : "0 24px" ,
188
216
cursor : "pointer" ,
189
217
pointerEvents : isActive ? "none" : "auto" ,
190
- color : ( theme ) =>
191
- isActive
192
- ? theme . palette . text . primary
193
- : theme . palette . text . secondary ,
218
+ color : isActive
219
+ ? theme . palette . text . primary
220
+ : theme . palette . text . secondary ,
194
221
"&:hover" : {
195
- background : ( theme ) => theme . palette . action . hover ,
196
- color : ( theme ) => theme . palette . text . primary ,
222
+ background : theme . palette . action . hover ,
223
+ color : theme . palette . text . primary ,
197
224
} ,
198
225
} }
199
226
>
200
227
{ isHealthy ? (
201
228
isWarning ? (
202
229
< CheckCircleOutlined
203
- sx = { {
230
+ css = { {
204
231
width : 16 ,
205
232
height : 16 ,
206
- color : ( theme ) => theme . palette . warning . main ,
233
+ color : theme . palette . warning . light ,
207
234
} }
208
235
/>
209
236
) : (
210
237
< CheckCircleOutlined
211
- sx = { {
238
+ css = { {
212
239
width : 16 ,
213
240
height : 16 ,
214
- color : ( theme ) => theme . palette . success . light ,
241
+ color : theme . palette . success . light ,
215
242
} }
216
243
/>
217
244
)
218
245
) : (
219
246
< ErrorOutline
220
- sx = { {
247
+ css = { {
221
248
width : 16 ,
222
249
height : 16 ,
223
- color : ( theme ) => theme . palette . error . main ,
250
+ color : theme . palette . error . main ,
224
251
} }
225
252
/>
226
253
) }
227
254
{ label }
228
- </ Box >
255
+ </ button >
229
256
) ;
230
257
} ) }
231
- </ Box >
232
- </ Box >
258
+ </ nav >
259
+ </ div >
233
260
{ /* 62px - navbar and 36px - the bottom bar */ }
234
261
< Box sx = { { overflowY : "auto" , width : "100%" } } data-chromatic = "ignore" >
235
262
< SyntaxHighlighter
@@ -246,53 +273,3 @@ export function HealthPageView({
246
273
</ DashboardFullPage >
247
274
) ;
248
275
}
249
-
250
- const styles = {
251
- stats : ( theme ) => ( {
252
- padding : 0 ,
253
- border : 0 ,
254
- gap : 48 ,
255
- rowGap : 24 ,
256
- flex : 1 ,
257
-
258
- [ theme . breakpoints . down ( "md" ) ] : {
259
- display : "flex" ,
260
- flexDirection : "column" ,
261
- alignItems : "flex-start" ,
262
- gap : 8 ,
263
- } ,
264
- } ) ,
265
-
266
- statsItem : {
267
- flexDirection : "column" ,
268
- gap : 0 ,
269
- padding : 0 ,
270
-
271
- "& > span:first-of-type" : {
272
- fontSize : 12 ,
273
- fontWeight : 500 ,
274
- } ,
275
- } ,
276
- } satisfies Record < string , Interpolation < Theme > > ;
277
-
278
- interface HealthcheckAction {
279
- handleAction : ( ) => void ;
280
- loading : boolean ;
281
- }
282
-
283
- export const RefreshButton : FC < HealthcheckAction > = ( {
284
- handleAction,
285
- loading,
286
- } ) => {
287
- return (
288
- < LoadingButton
289
- loading = { loading }
290
- loadingPosition = "start"
291
- data-testid = "healthcheck-refresh-button"
292
- startIcon = { < ReplayIcon /> }
293
- onClick = { handleAction }
294
- >
295
- Refresh
296
- </ LoadingButton >
297
- ) ;
298
- } ;
0 commit comments