@@ -190,7 +190,7 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
190
190
( port ) => port . agent_name === agent . name ,
191
191
) ;
192
192
// we don't want to show listening ports if it's a shared port
193
- const filteredListeningPorts = listeningPorts ? .filter ( ( port ) => {
193
+ const filteredListeningPorts = ( listeningPorts ? listeningPorts : [ ] ) . filter ( ( port ) => {
194
194
for ( let i = 0 ; i < filteredSharedPorts . length ; i ++ ) {
195
195
if ( filteredSharedPorts [ i ] . port === port . port ) {
196
196
return false ;
@@ -225,17 +225,10 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
225
225
overflowY : "auto" ,
226
226
} }
227
227
>
228
- < header
229
- css = { ( theme ) => ( {
228
+ < Stack direction = "column"
229
+ css = { {
230
230
padding : 20 ,
231
- paddingBottom : 10 ,
232
- position : "sticky" ,
233
- top : 0 ,
234
- background : theme . palette . background . paper ,
235
- // For some reason the Share button label has a higher z-index than
236
- // the header. Probably some tricky stuff from MUI.
237
- zIndex : 1 ,
238
- } ) }
231
+ } }
239
232
>
240
233
< Stack
241
234
direction = "row"
@@ -249,144 +242,153 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
249
242
Learn more
250
243
</ HelpTooltipLink >
251
244
</ Stack >
252
- < HelpTooltipText css = { { color : theme . palette . text . secondary } } >
253
- { filteredListeningPorts ?. length === 0
254
- ? "No open ports were detected."
255
- : "The listening ports are exclusively accessible to you." }
256
- </ HelpTooltipText >
257
- < Stack direction = "row" gap = { 1 } alignItems = "flex-end" justifyContent = "flex-end" >
258
- < form
259
- css = { styles . newPortForm }
260
- onSubmit = { ( e ) => {
261
- e . preventDefault ( ) ;
262
- const formData = new FormData ( e . currentTarget ) ;
263
- const port = Number ( formData . get ( "portNumber" ) ) ;
264
- const url = portForwardURL (
265
- host ,
266
- port ,
267
- agent . name ,
268
- workspaceName ,
269
- username ,
270
- ) ;
271
- window . open ( url , "_blank" ) ;
245
+ < Stack direction = "column" gap = { 1 } >
246
+ < HelpTooltipText css = { { color : theme . palette . text . secondary } } >
247
+ { "The listening ports are exclusively accessible to you." }
248
+ </ HelpTooltipText >
249
+ < Stack
250
+ direction = "row"
251
+ gap = { 2 }
252
+ css = { {
253
+ paddingBottom : 8 ,
272
254
} }
273
255
>
274
- < input
275
- aria-label = "Port number"
276
- name = "portNumber"
277
- type = "number"
278
- placeholder = "Connect to port..."
279
- min = { 9 }
280
- max = { 65535 }
281
- required
282
- css = { styles . newPortInput }
283
- />
284
- < Button
285
- type = "submit"
286
- size = "small"
287
- variant = "text"
288
- css = { {
289
- paddingLeft : 12 ,
290
- paddingRight : 12 ,
291
- minWidth : 0 ,
256
+ < FormControl size = "small" css = { styles . protocolFormControl } >
257
+ < Select
258
+ css = { styles . listeningPortProtocol }
259
+ value = { listeningPortProtocol }
260
+ onChange = { async ( event ) => {
261
+ const selectedProtocol = event . target . value as "http" | "https" ;
262
+ setListeningPortProtocol ( selectedProtocol ) ;
263
+ saveWorkspaceListeningPortsProtocol ( workspaceID , selectedProtocol ) ;
264
+ } }
265
+ >
266
+ < MenuItem value = "http" > HTTP</ MenuItem >
267
+ < MenuItem value = "https" > HTTPS</ MenuItem >
268
+ </ Select >
269
+ </ FormControl >
270
+ < form
271
+ css = { styles . newPortForm }
272
+ onSubmit = { ( e ) => {
273
+ e . preventDefault ( ) ;
274
+ const formData = new FormData ( e . currentTarget ) ;
275
+ const port = Number ( formData . get ( "portNumber" ) ) ;
276
+ const url = portForwardURL (
277
+ host ,
278
+ port ,
279
+ agent . name ,
280
+ workspaceName ,
281
+ username ,
282
+ listeningPortProtocol ,
283
+ ) ;
284
+ window . open ( url , "_blank" ) ;
292
285
} }
293
286
>
294
- < OpenInNewOutlined
287
+ < input
288
+ aria-label = "Port number"
289
+ name = "portNumber"
290
+ type = "number"
291
+ placeholder = "Connect to port..."
292
+ min = { 9 }
293
+ max = { 65535 }
294
+ required
295
+ css = { styles . newPortInput }
296
+ />
297
+ < Button
298
+ type = "submit"
299
+ size = "small"
300
+ variant = "text"
295
301
css = { {
296
- flexShrink : 0 ,
297
- width : 14 ,
298
- height : 14 ,
299
- color : theme . palette . text . primary ,
302
+ paddingLeft : 12 ,
303
+ paddingRight : 12 ,
304
+ minWidth : 0 ,
300
305
} }
301
- />
302
- </ Button >
303
- </ form >
304
- < FormControl size = "small" css = { styles . protocolFormControl } >
305
- < Select
306
- css = { styles . listeningPortProtocol }
307
- value = { listeningPortProtocol }
308
- onChange = { async ( event ) => {
309
- const selectedProtocol = event . target . value as "http" | "https" ;
310
- setListeningPortProtocol ( selectedProtocol ) ;
311
- saveWorkspaceListeningPortsProtocol ( workspaceID , selectedProtocol ) ;
312
- } }
313
- >
314
- < MenuItem value = "http" > HTTP</ MenuItem >
315
- < MenuItem value = "https" > HTTPS</ MenuItem >
316
- </ Select >
317
- </ FormControl >
318
- </ Stack >
319
- </ header >
320
- < div
321
- css = { {
322
- padding : 20 ,
323
- paddingTop : 0 ,
324
- } }
325
- >
326
- { filteredListeningPorts ?. map ( ( port ) => {
327
- const url = portForwardURL (
328
- host ,
329
- port . port ,
330
- agent . name ,
331
- workspaceName ,
332
- username ,
333
- ) ;
334
- const label =
335
- port . process_name !== "" ? port . process_name : port . port ;
336
- return (
337
- < Stack
338
- key = { port . port }
339
- direction = "row"
340
- alignItems = "center"
341
- justifyContent = "space-between"
342
- >
343
- < Link
344
- underline = "none"
345
- css = { styles . portLink }
346
- href = { url }
347
- target = "_blank"
348
- rel = "noreferrer"
349
306
>
350
- < SensorsIcon css = { { width : 14 , height : 14 } } />
351
- { label }
352
- </ Link >
307
+ < OpenInNewOutlined
308
+ css = { {
309
+ flexShrink : 0 ,
310
+ width : 14 ,
311
+ height : 14 ,
312
+ color : theme . palette . text . primary ,
313
+ } }
314
+ />
315
+ </ Button >
316
+ </ form >
317
+ </ Stack >
318
+ </ Stack >
319
+ { filteredListeningPorts . length === 0 && (
320
+ < HelpTooltipText css = { styles . noPortText } >
321
+ { "No open ports were detected." }
322
+ </ HelpTooltipText >
323
+ ) }
324
+ { filteredListeningPorts . map ( ( port ) => {
325
+ const url = portForwardURL (
326
+ host ,
327
+ port . port ,
328
+ agent . name ,
329
+ workspaceName ,
330
+ username ,
331
+ listeningPortProtocol ,
332
+ ) ;
333
+ const label =
334
+ port . process_name !== "" ? port . process_name : port . port ;
335
+ return (
353
336
< Stack
337
+ key = { port . port }
354
338
direction = "row"
355
- gap = { 2 }
356
- justifyContent = "flex-end"
357
339
alignItems = "center"
340
+ justifyContent = "space-between"
358
341
>
342
+ < Stack direction = "row" gap = { 3 } >
359
343
< Link
360
344
underline = "none"
361
345
css = { styles . portLink }
362
346
href = { url }
363
347
target = "_blank"
364
348
rel = "noreferrer"
365
349
>
366
- < span css = { styles . portNumber } > { port . port } </ span >
350
+ < SensorsIcon css = { { width : 14 , height : 14 } } />
351
+ { port . port }
367
352
</ Link >
368
- { canSharePorts && (
369
- < Button
370
- size = "small"
371
- variant = "text"
372
- onClick = { async ( ) => {
373
- await upsertSharedPortMutation . mutateAsync ( {
374
- agent_name : agent . name ,
375
- port : port . port ,
376
- protocol : "http" ,
377
- share_level : "authenticated" ,
378
- } ) ;
379
- await sharedPortsQuery . refetch ( ) ;
380
- } }
353
+ < Link
354
+ underline = "none"
355
+ css = { styles . portLink }
356
+ href = { url }
357
+ target = "_blank"
358
+ rel = "noreferrer"
381
359
>
382
- Share
383
- </ Button >
384
- ) }
360
+ { label }
361
+ </ Link >
362
+ </ Stack >
363
+ < Stack
364
+ direction = "row"
365
+ gap = { 2 }
366
+ justifyContent = "flex-end"
367
+ alignItems = "center"
368
+ >
369
+
370
+ { canSharePorts && (
371
+ < Button
372
+ size = "small"
373
+ variant = "text"
374
+ onClick = { async ( ) => {
375
+ await upsertSharedPortMutation . mutateAsync ( {
376
+ agent_name : agent . name ,
377
+ port : port . port ,
378
+ protocol : listeningPortProtocol ,
379
+ share_level : "authenticated" ,
380
+ } ) ;
381
+ await sharedPortsQuery . refetch ( ) ;
382
+ } }
383
+ >
384
+ Share
385
+ </ Button >
386
+ ) }
387
+ </ Stack >
385
388
</ Stack >
386
- </ Stack >
387
- ) ;
388
- } ) }
389
- </ div >
389
+ ) ;
390
+ } ) }
391
+ </ Stack >
390
392
</ div >
391
393
{ portSharingExperimentEnabled && (
392
394
< div
@@ -410,7 +412,7 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
410
412
agent . name ,
411
413
workspaceName ,
412
414
username ,
413
- share . protocol === "https" ,
415
+ share . protocol ,
414
416
) ;
415
417
const label = share . port ;
416
418
return (
@@ -666,6 +668,12 @@ const styles = {
666
668
display : "block" ,
667
669
width : "100%" ,
668
670
} ) ,
671
+ noPortText : ( theme ) => ( {
672
+ color : theme . palette . text . secondary ,
673
+ paddingTop : 20 ,
674
+ paddingBottom : 10 ,
675
+ textAlign : "center" ,
676
+ } ) ,
669
677
sharedPortLink : ( ) => ( {
670
678
minWidth : 80 ,
671
679
} ) ,
0 commit comments