@@ -26,6 +26,17 @@ import {
26
26
PopoverTrigger ,
27
27
} from "components/Popover/Popover" ;
28
28
import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown" ;
29
+ import Stack from "@mui/material/Stack" ;
30
+ import Select from "@mui/material/Select" ;
31
+ import MenuItem from "@mui/material/MenuItem" ;
32
+ import FormControl from "@mui/material/FormControl" ;
33
+ import TextField from "@mui/material/TextField" ;
34
+ import SensorsIcon from '@mui/icons-material/Sensors' ;
35
+ import Add from '@mui/icons-material/Add' ;
36
+ import IconButton from "@mui/material/IconButton" ;
37
+ import LockIcon from '@mui/icons-material/Lock' ;
38
+ import LockOpenIcon from '@mui/icons-material/LockOpen' ;
39
+ import DeleteIcon from '@mui/icons-material/Delete' ;
29
40
30
41
export interface PortForwardButtonProps {
31
42
host : string ;
@@ -96,6 +107,16 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
96
107
ports,
97
108
} ) => {
98
109
const theme = useTheme ( ) ;
110
+ const sharedPorts = [
111
+ {
112
+ port : 8090 ,
113
+ share_level : "Authenticated" ,
114
+ } ,
115
+ {
116
+ port : 8091 ,
117
+ share_level : "Public" ,
118
+ }
119
+ ] ;
99
120
100
121
return (
101
122
< >
@@ -105,13 +126,69 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
105
126
borderBottom : `1px solid ${ theme . palette . divider } ` ,
106
127
} }
107
128
>
108
- < HelpTooltipTitle > Forwarded ports</ HelpTooltipTitle >
129
+ < Stack direction = "row" justifyContent = "space-between" alignItems = "start" >
130
+ < HelpTooltipTitle > Listening ports</ HelpTooltipTitle >
131
+ < HelpTooltipLink href = { docs ( "/networking/port-forwarding#dashboard" ) } >
132
+ Learn more
133
+ </ HelpTooltipLink >
134
+ </ Stack >
109
135
< HelpTooltipText css = { { color : theme . palette . text . secondary } } >
110
136
{ ports ?. length === 0
111
137
? "No open ports were detected."
112
- : "The forwarded ports are exclusively accessible to you." }
138
+ : "The listening ports are exclusively accessible to you."
139
+ }
140
+
113
141
</ HelpTooltipText >
114
- < div css = { { marginTop : 12 } } >
142
+ < form
143
+ css = { styles . newPortForm }
144
+ onSubmit = { ( e ) => {
145
+ e . preventDefault ( ) ;
146
+ const formData = new FormData ( e . currentTarget ) ;
147
+ const port = Number ( formData . get ( "portNumber" ) ) ;
148
+ const url = portForwardURL (
149
+ host ,
150
+ port ,
151
+ agent . name ,
152
+ workspaceName ,
153
+ username ,
154
+ ) ;
155
+ window . open ( url , "_blank" ) ;
156
+ } }
157
+ >
158
+ < input
159
+ aria-label = "Port number"
160
+ name = "portNumber"
161
+ type = "number"
162
+ placeholder = "Connect to port..."
163
+ min = { 0 }
164
+ max = { 65535 }
165
+ required
166
+ css = { styles . newPortInput }
167
+ />
168
+ < Button
169
+ type = "submit"
170
+ size = "small"
171
+ variant = "text"
172
+ css = { {
173
+ paddingLeft : 12 ,
174
+ paddingRight : 12 ,
175
+ minWidth : 0 ,
176
+ } }
177
+ >
178
+ < OpenInNewOutlined
179
+ css = { {
180
+ flexShrink : 0 ,
181
+ width : 14 ,
182
+ height : 14 ,
183
+ color : theme . palette . text . primary ,
184
+ } }
185
+ />
186
+ </ Button >
187
+ </ form >
188
+ < div
189
+ css = { {
190
+ paddingTop : 10 ,
191
+ } } >
115
192
{ ports ?. map ( ( port ) => {
116
193
const url = portForwardURL (
117
194
host ,
@@ -123,24 +200,123 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
123
200
const label =
124
201
port . process_name !== "" ? port . process_name : port . port ;
125
202
return (
126
- < Link
127
- underline = "none"
128
- css = { styles . portLink }
129
- key = { port . port }
130
- href = { url }
131
- target = "_blank"
132
- rel = "noreferrer"
133
- >
134
- < OpenInNewOutlined css = { { width : 14 , height : 14 } } />
135
- { label }
136
- < span css = { styles . portNumber } > { port . port } </ span >
137
- </ Link >
203
+ < Stack key = { port . port } direction = "row" justifyContent = "space-between" alignItems = "center" >
204
+ < Link
205
+ underline = "none"
206
+ css = { styles . portLink }
207
+ href = { url }
208
+ target = "_blank"
209
+ rel = "noreferrer"
210
+ >
211
+ < SensorsIcon css = { { width : 14 , height : 14 } } />
212
+ { label }
213
+ </ Link >
214
+ < Link
215
+ underline = "none"
216
+ css = { styles . portLink }
217
+ href = { url }
218
+ target = "_blank"
219
+ rel = "noreferrer"
220
+ >
221
+ < span css = { styles . portNumber } > { port . port } </ span >
222
+ </ Link >
223
+ < Button size = "small" variant = "text" >
224
+ Share
225
+ </ Button >
226
+ </ Stack >
138
227
) ;
139
228
} ) }
140
229
</ div >
230
+ </ div >
231
+ < div css = { {
232
+ padding : 20 ,
233
+ } } >
234
+ < HelpTooltipTitle > Shared Ports</ HelpTooltipTitle >
235
+ < HelpTooltipText css = { { color : theme . palette . text . secondary } } >
236
+ { ports ?. length === 0
237
+ ? "No ports are shared."
238
+ : "Ports can be shared with other Coder users or with the public." }
239
+ </ HelpTooltipText >
240
+ < div >
241
+ { sharedPorts ?. map ( ( port ) => {
242
+ const url = portForwardURL (
243
+ host ,
244
+ port . port ,
245
+ agent . name ,
246
+ workspaceName ,
247
+ username ,
248
+ ) ;
249
+ const label = port . port ;
250
+ return (
251
+ < Stack key = { port . port } direction = "row" justifyContent = "space-between" alignItems = "center" >
252
+ < Link
253
+ underline = "none"
254
+ css = { styles . portLink }
255
+ href = { url }
256
+ target = "_blank"
257
+ rel = "noreferrer"
258
+ >
259
+ { port . share_level === "Public" ?
260
+ (
261
+ < LockOpenIcon css = { { width : 14 , height : 14 } } />
262
+ )
263
+ : (
264
+ < LockIcon css = { { width : 14 , height : 14 } } />
265
+ ) }
266
+ { label }
267
+ </ Link >
268
+ < Stack direction = "row" gap = { 1 } >
269
+ < FormControl size = "small" >
270
+ < Select
271
+ sx = { {
272
+ boxShadow : "none" ,
273
+ ".MuiOutlinedInput-notchedOutline" : { border : 0 } ,
274
+ "&.MuiOutlinedInput-root:hover .MuiOutlinedInput-notchedOutline" :
275
+ {
276
+ border : 0 ,
277
+ } ,
278
+ "&.MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline" :
279
+ {
280
+ border : 0 ,
281
+ } ,
282
+ } }
283
+ value = { port . share_level }
284
+ >
285
+ < MenuItem value = "Owner" > Owner</ MenuItem >
286
+ < MenuItem value = "Authenticated" > Authenticated</ MenuItem >
287
+ < MenuItem value = "Public" > Public</ MenuItem >
288
+ </ Select >
289
+ </ FormControl >
290
+ </ Stack >
291
+
292
+ </ Stack >
293
+ ) ;
294
+ } ) }
295
+ </ div >
296
+ < Stack direction = "column" gap = { 1 } justifyContent = "flex-end" sx = { {
297
+ marginTop : 2 ,
298
+ } } >
299
+ < TextField
300
+ label = "Port"
301
+ variant = "outlined"
302
+ size = "small"
303
+ />
304
+ < FormControl size = "small" >
305
+ < Select
306
+ value = "Authenticated"
307
+ >
308
+ < MenuItem value = "Authenticated" > Authenticated</ MenuItem >
309
+ < MenuItem value = "Public" > Public</ MenuItem >
310
+ </ Select >
311
+ </ FormControl >
312
+ < Button variant = "contained" >
313
+ Add Shared Port
314
+ </ Button >
315
+ </ Stack >
141
316
</ div >
142
317
143
- < div css = { { padding : 20 } } >
318
+
319
+ { /* <div css={{ padding: 20 }}>
144
320
<HelpTooltipTitle>Forward port</HelpTooltipTitle>
145
321
<HelpTooltipText css={{ color: theme.palette.text.secondary }}>
146
322
Access ports running on the agent:
@@ -198,7 +374,7 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
198
374
Learn more
199
375
</HelpTooltipLink>
200
376
</HelpTooltipLinksGroup>
201
- </ div >
377
+ </div> */ }
202
378
</ >
203
379
) ;
204
380
} ;
@@ -232,8 +408,8 @@ const styles = {
232
408
display : "flex" ,
233
409
alignItems : "center" ,
234
410
gap : 8 ,
235
- paddingTop : 4 ,
236
- paddingBottom : 4 ,
411
+ paddingTop : 8 ,
412
+ paddingBottom : 8 ,
237
413
fontWeight : 500 ,
238
414
} ) ,
239
415
@@ -247,7 +423,7 @@ const styles = {
247
423
newPortForm : ( theme ) => ( {
248
424
border : `1px solid ${ theme . palette . divider } ` ,
249
425
borderRadius : "4px" ,
250
- marginTop : 16 ,
426
+ marginTop : 8 ,
251
427
display : "flex" ,
252
428
alignItems : "center" ,
253
429
"&:focus-within" : {
0 commit comments