Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
feat: add listening ports protocol selector
  • Loading branch information
f0ssel committed Apr 10, 2024
commit c9863709345adffeda21f8c0cb50bf739fcf09f3
121 changes: 77 additions & 44 deletions site/src/modules/resources/PortForwardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import { type FormikContextType, useFormik } from "formik";
import type { FC } from "react";
import { useState, type FC } from "react";
import { useQuery, useMutation } from "react-query";
import * as Yup from "yup";
import { getAgentListeningPorts } from "api/api";
Expand Down Expand Up @@ -48,7 +48,7 @@ import { type ClassName, useClassName } from "hooks/useClassName";
import { useDashboard } from "modules/dashboard/useDashboard";
import { docs } from "utils/docs";
import { getFormHelpers } from "utils/formUtils";
import { portForwardURL } from "utils/portForward";
import { getWorkspaceListeningPortsProtocol, portForwardURL, saveWorkspaceListeningPortsProtocol } from "utils/portForward";

export interface PortForwardButtonProps {
host: string;
Expand Down Expand Up @@ -135,6 +135,7 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
portSharingControlsEnabled,
}) => {
const theme = useTheme();
const [listeningPortProtocol, setListeningPortProtocol] = useState(getWorkspaceListeningPortsProtocol(workspaceID));

const sharedPortsQuery = useQuery({
...workspacePortShares(workspaceID),
Expand Down Expand Up @@ -253,52 +254,68 @@ export const PortForwardPopoverView: FC<PortForwardPopoverViewProps> = ({
? "No open ports were detected."
: "The listening ports are exclusively accessible to you."}
</HelpTooltipText>
<form
css={styles.newPortForm}
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const port = Number(formData.get("portNumber"));
const url = portForwardURL(
host,
port,
agent.name,
workspaceName,
username,
);
window.open(url, "_blank");
}}
>
<input
aria-label="Port number"
name="portNumber"
type="number"
placeholder="Connect to port..."
min={9}
max={65535}
required
css={styles.newPortInput}
/>
<Button
type="submit"
size="small"
variant="text"
css={{
paddingLeft: 12,
paddingRight: 12,
minWidth: 0,
<Stack direction="row" gap={1} alignItems="flex-end" justifyContent="flex-end">
<form
css={styles.newPortForm}
onSubmit={(e) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const port = Number(formData.get("portNumber"));
const url = portForwardURL(
host,
port,
agent.name,
workspaceName,
username,
);
window.open(url, "_blank");
}}
>
<OpenInNewOutlined
<input
aria-label="Port number"
name="portNumber"
type="number"
placeholder="Connect to port..."
min={9}
max={65535}
required
css={styles.newPortInput}
/>
<Button
type="submit"
size="small"
variant="text"
css={{
flexShrink: 0,
width: 14,
height: 14,
color: theme.palette.text.primary,
paddingLeft: 12,
paddingRight: 12,
minWidth: 0,
}}
/>
</Button>
</form>
>
<OpenInNewOutlined
css={{
flexShrink: 0,
width: 14,
height: 14,
color: theme.palette.text.primary,
}}
/>
</Button>
</form>
<FormControl size="small" css={styles.protocolFormControl}>
<Select
css={styles.listeningPortProtocol}
value={listeningPortProtocol}
onChange={async (event) => {
const selectedProtocol = event.target.value as "http" | "https";
setListeningPortProtocol(selectedProtocol);
saveWorkspaceListeningPortsProtocol(workspaceID, selectedProtocol);
}}
>
<MenuItem value="http">HTTP</MenuItem>
<MenuItem value="https">HTTPS</MenuItem>
</Select>
</FormControl>
</Stack>
</header>
<div
css={{
Expand Down Expand Up @@ -619,6 +636,22 @@ const styles = {
"&:focus-within": {
borderColor: theme.palette.primary.main,
},
width: "100%",
}),

listeningPortProtocol: (theme) => ({
boxShadow: "none",
".MuiOutlinedInput-notchedOutline": { border: 0 },
"&.MuiOutlinedInput-root:hover .MuiOutlinedInput-notchedOutline": {
border: 0,
},
"&.MuiOutlinedInput-root.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: 0,
},
border: `1px solid ${theme.palette.divider}`,
borderRadius: "4px",
marginTop: 8,
minWidth: "100px",
}),

newPortInput: (theme) => ({
Expand Down
8 changes: 8 additions & 0 deletions site/src/utils/portForward.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,11 @@ export const openMaybePortForwardedURL = (
open(uri);
}
};

export const saveWorkspaceListeningPortsProtocol = (workspaceID: string, protocol: "http" | "https") => {
localStorage.setItem(`listening-ports-protocol-workspace-${workspaceID}`, protocol);
}

export const getWorkspaceListeningPortsProtocol = (workspaceID: string) => {
return localStorage.getItem(`listening-ports-protocol-workspace-${workspaceID}`) || "http";
}