@@ -2,7 +2,6 @@ import { DeploymentStats, WorkspaceStatus } from "api/typesGenerated";
2
2
import { FC , useMemo , useEffect , useState } from "react" ;
3
3
import prettyBytes from "pretty-bytes" ;
4
4
import BuildingIcon from "@mui/icons-material/Build" ;
5
- import { makeStyles } from "@mui/styles" ;
6
5
import { RocketIcon } from "components/Icons/RocketIcon" ;
7
6
import { MONOSPACE_FONT_FAMILY } from "theme/constants" ;
8
7
import Tooltip from "@mui/material/Tooltip" ;
@@ -19,9 +18,36 @@ import CollectedIcon from "@mui/icons-material/Compare";
19
18
import RefreshIcon from "@mui/icons-material/Refresh" ;
20
19
import Button from "@mui/material/Button" ;
21
20
import { getDisplayWorkspaceStatus } from "utils/workspace" ;
21
+ import { css , type Theme , type Interpolation , useTheme } from "@emotion/react" ;
22
22
23
23
export const bannerHeight = 36 ;
24
24
25
+ const styles = {
26
+ group : css `
27
+ display : flex;
28
+ align-items : center;
29
+ ` ,
30
+ category : ( theme : Theme ) => ( {
31
+ marginRight : theme . spacing ( 2 ) ,
32
+ color : theme . palette . text . primary ,
33
+ } ) ,
34
+ values : ( theme : Theme ) => ( {
35
+ display : "flex" ,
36
+ gap : theme . spacing ( 1 ) ,
37
+ color : theme . palette . text . secondary ,
38
+ } ) ,
39
+ value : ( theme : Theme ) => css `
40
+ display : flex;
41
+ align-items : center;
42
+ gap : ${ theme . spacing ( 0.5 ) } ;
43
+
44
+ & svg {
45
+ width : 12px ;
46
+ height : 12px ;
47
+ }
48
+ ` ,
49
+ } satisfies Record < string , Interpolation < Theme > > ;
50
+
25
51
export interface DeploymentBannerViewProps {
26
52
fetchStats ?: ( ) => void ;
27
53
stats ?: DeploymentStats ;
@@ -31,7 +57,7 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
31
57
stats,
32
58
fetchStats,
33
59
} ) => {
34
- const styles = useStyles ( ) ;
60
+ const theme = useTheme ( ) ;
35
61
const aggregatedMinutes = useMemo ( ( ) => {
36
62
if ( ! stats ) {
37
63
return ;
@@ -80,15 +106,46 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
80
106
} , [ timeUntilRefresh , stats ] ) ;
81
107
82
108
return (
83
- < div className = { styles . container } >
109
+ < div
110
+ css = { {
111
+ position : "sticky" ,
112
+ height : bannerHeight ,
113
+ bottom : 0 ,
114
+ zIndex : 1 ,
115
+ padding : theme . spacing ( 0 , 2 ) ,
116
+ backgroundColor : theme . palette . background . paper ,
117
+ display : "flex" ,
118
+ alignItems : "center" ,
119
+ fontFamily : MONOSPACE_FONT_FAMILY ,
120
+ fontSize : 12 ,
121
+ gap : theme . spacing ( 4 ) ,
122
+ borderTop : `1px solid ${ theme . palette . divider } ` ,
123
+ overflowX : "auto" ,
124
+ whiteSpace : "nowrap" ,
125
+ } }
126
+ >
84
127
< Tooltip title = "Status of your Coder deployment. Only visible for admins!" >
85
- < div className = { styles . rocket } >
128
+ < div
129
+ css = { css `
130
+ display : flex;
131
+ align-items : center;
132
+
133
+ & svg {
134
+ width : 16px ;
135
+ height : 16px ;
136
+ }
137
+
138
+ ${ theme . breakpoints . down ( "lg" ) } {
139
+ display : none;
140
+ }
141
+ ` }
142
+ >
86
143
< RocketIcon />
87
144
</ div >
88
145
</ Tooltip >
89
- < div className = { styles . group } >
90
- < div className = { styles . category } > Workspaces</ div >
91
- < div className = { styles . values } >
146
+ < div css = { styles . group } >
147
+ < div css = { styles . category } > Workspaces</ div >
148
+ < div css = { styles . values } >
92
149
< WorkspaceBuildValue
93
150
status = "pending"
94
151
count = { stats ?. workspaces . pending }
@@ -115,21 +172,21 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
115
172
/>
116
173
</ div >
117
174
</ div >
118
- < div className = { styles . group } >
175
+ < div css = { styles . group } >
119
176
< Tooltip title = { `Activity in the last ~${ aggregatedMinutes } minutes` } >
120
- < div className = { styles . category } > Transmission</ div >
177
+ < div css = { styles . category } > Transmission</ div >
121
178
</ Tooltip >
122
179
123
- < div className = { styles . values } >
180
+ < div css = { styles . values } >
124
181
< Tooltip title = "Data sent to workspaces" >
125
- < div className = { styles . value } >
182
+ < div css = { styles . value } >
126
183
< DownloadIcon />
127
184
{ stats ? prettyBytes ( stats . workspaces . rx_bytes ) : "-" }
128
185
</ div >
129
186
</ Tooltip >
130
187
< ValueSeparator />
131
188
< Tooltip title = "Data sent from workspaces" >
132
- < div className = { styles . value } >
189
+ < div css = { styles . value } >
133
190
< UploadIcon />
134
191
{ stats ? prettyBytes ( stats . workspaces . tx_bytes ) : "-" }
135
192
</ div >
@@ -142,28 +199,34 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
142
199
: "The average latency of user connections to workspaces"
143
200
}
144
201
>
145
- < div className = { styles . value } >
202
+ < div css = { styles . value } >
146
203
< LatencyIcon />
147
204
{ displayLatency > 0 ? displayLatency ?. toFixed ( 2 ) + " ms" : "-" }
148
205
</ div >
149
206
</ Tooltip >
150
207
</ div >
151
208
</ div >
152
- < div className = { styles . group } >
153
- < div className = { styles . category } > Active Connections</ div >
209
+ < div css = { styles . group } >
210
+ < div css = { styles . category } > Active Connections</ div >
154
211
155
- < div className = { styles . values } >
212
+ < div css = { styles . values } >
156
213
< Tooltip title = "VS Code Editors with the Coder Remote Extension" >
157
- < div className = { styles . value } >
158
- < VSCodeIcon className = { styles . iconStripColor } />
214
+ < div css = { styles . value } >
215
+ < VSCodeIcon
216
+ css = { css `
217
+ & * {
218
+ fill : currentColor;
219
+ }
220
+ ` }
221
+ />
159
222
{ typeof stats ?. session_count . vscode === "undefined"
160
223
? "-"
161
224
: stats ?. session_count . vscode }
162
225
</ div >
163
226
</ Tooltip >
164
227
< ValueSeparator />
165
228
< Tooltip title = "SSH Sessions" >
166
- < div className = { styles . value } >
229
+ < div css = { styles . value } >
167
230
< TerminalIcon />
168
231
{ typeof stats ?. session_count . ssh === "undefined"
169
232
? "-"
@@ -172,7 +235,7 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
172
235
</ Tooltip >
173
236
< ValueSeparator />
174
237
< Tooltip title = "Web Terminal Sessions" >
175
- < div className = { styles . value } >
238
+ < div css = { styles . value } >
176
239
< WebTerminalIcon />
177
240
{ typeof stats ?. session_count . reconnecting_pty === "undefined"
178
241
? "-"
@@ -181,17 +244,41 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
181
244
</ Tooltip >
182
245
</ div >
183
246
</ div >
184
- < div className = { styles . refresh } >
247
+ < div
248
+ css = { {
249
+ color : theme . palette . text . primary ,
250
+ marginLeft : "auto" ,
251
+ display : "flex" ,
252
+ alignItems : "center" ,
253
+ gap : theme . spacing ( 2 ) ,
254
+ } }
255
+ >
185
256
< Tooltip title = "The last time stats were aggregated. Workspaces report statistics periodically, so it may take a bit for these to update!" >
186
- < div className = { styles . value } >
257
+ < div css = { styles . value } >
187
258
< CollectedIcon />
188
259
{ lastAggregated }
189
260
</ div >
190
261
</ Tooltip >
191
262
192
263
< Tooltip title = "A countdown until stats are fetched again. Click to refresh!" >
193
264
< Button
194
- className = { `${ styles . value } ${ styles . refreshButton } ` }
265
+ css = { css `
266
+ ${ styles . value ( theme ) }
267
+
268
+ margin : 0 ;
269
+ padding : 0 8px ;
270
+ height : unset;
271
+ min-height : unset;
272
+ font-size : unset;
273
+ color : unset;
274
+ border : 0 ;
275
+ min-width : unset;
276
+ font-family : inherit;
277
+
278
+ & svg {
279
+ margin-right : ${ theme . spacing ( 0.5 ) } ;
280
+ }
281
+ ` }
195
282
onClick = { ( ) => {
196
283
if ( fetchStats ) {
197
284
fetchStats ( ) ;
@@ -209,15 +296,18 @@ export const DeploymentBannerView: FC<DeploymentBannerViewProps> = ({
209
296
} ;
210
297
211
298
const ValueSeparator : FC = ( ) => {
212
- const styles = useStyles ( ) ;
213
- return < div className = { styles . valueSeparator } > /</ div > ;
299
+ const theme = useTheme ( ) ;
300
+ const separatorStyles = css `
301
+ color : ${ theme . palette . text . disabled } ;
302
+ ` ;
303
+
304
+ return < div css = { separatorStyles } > /</ div > ;
214
305
} ;
215
306
216
307
const WorkspaceBuildValue : FC < {
217
308
status : WorkspaceStatus ;
218
309
count ?: number ;
219
310
} > = ( { status, count } ) => {
220
- const styles = useStyles ( ) ;
221
311
const displayStatus = getDisplayWorkspaceStatus ( status ) ;
222
312
let statusText = displayStatus . text ;
223
313
let icon = displayStatus . icon ;
@@ -232,96 +322,11 @@ const WorkspaceBuildValue: FC<{
232
322
component = { RouterLink }
233
323
to = { `/workspaces?filter=${ encodeURIComponent ( "status:" + status ) } ` }
234
324
>
235
- < div className = { styles . value } >
325
+ < div css = { styles . value } >
236
326
{ icon }
237
327
{ typeof count === "undefined" ? "-" : count }
238
328
</ div >
239
329
</ Link >
240
330
</ Tooltip >
241
331
) ;
242
332
} ;
243
-
244
- const useStyles = makeStyles ( ( theme ) => ( {
245
- rocket : {
246
- display : "flex" ,
247
- alignItems : "center" ,
248
-
249
- "& svg" : {
250
- width : 16 ,
251
- height : 16 ,
252
- } ,
253
-
254
- [ theme . breakpoints . down ( "lg" ) ] : {
255
- display : "none" ,
256
- } ,
257
- } ,
258
- container : {
259
- position : "sticky" ,
260
- height : bannerHeight ,
261
- bottom : 0 ,
262
- zIndex : 1 ,
263
- padding : theme . spacing ( 0 , 2 ) ,
264
- backgroundColor : theme . palette . background . paper ,
265
- display : "flex" ,
266
- alignItems : "center" ,
267
- fontFamily : MONOSPACE_FONT_FAMILY ,
268
- fontSize : 12 ,
269
- gap : theme . spacing ( 4 ) ,
270
- borderTop : `1px solid ${ theme . palette . divider } ` ,
271
- overflowX : "auto" ,
272
- whiteSpace : "nowrap" ,
273
- } ,
274
- group : {
275
- display : "flex" ,
276
- alignItems : "center" ,
277
- } ,
278
- category : {
279
- marginRight : theme . spacing ( 2 ) ,
280
- color : theme . palette . text . primary ,
281
- } ,
282
- values : {
283
- display : "flex" ,
284
- gap : theme . spacing ( 1 ) ,
285
- color : theme . palette . text . secondary ,
286
- } ,
287
- valueSeparator : {
288
- color : theme . palette . text . disabled ,
289
- } ,
290
- value : {
291
- display : "flex" ,
292
- alignItems : "center" ,
293
- gap : theme . spacing ( 0.5 ) ,
294
-
295
- "& svg" : {
296
- width : 12 ,
297
- height : 12 ,
298
- } ,
299
- } ,
300
- iconStripColor : {
301
- "& *" : {
302
- fill : "currentColor" ,
303
- } ,
304
- } ,
305
- refresh : {
306
- color : theme . palette . text . primary ,
307
- marginLeft : "auto" ,
308
- display : "flex" ,
309
- alignItems : "center" ,
310
- gap : theme . spacing ( 2 ) ,
311
- } ,
312
- refreshButton : {
313
- margin : 0 ,
314
- padding : "0px 8px" ,
315
- height : "unset" ,
316
- minHeight : "unset" ,
317
- fontSize : "unset" ,
318
- color : "unset" ,
319
- border : 0 ,
320
- minWidth : "unset" ,
321
- fontFamily : "inherit" ,
322
-
323
- "& svg" : {
324
- marginRight : theme . spacing ( 0.5 ) ,
325
- } ,
326
- } ,
327
- } ) ) ;
0 commit comments