Skip to content

feature: Add SSH button in the agent access column #2931

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
21 changes: 11 additions & 10 deletions site/src/components/Resources/Resources.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FC } from "react"
import { Workspace, WorkspaceResource } from "../../api/typesGenerated"
import { getDisplayAgentStatus } from "../../util/workspace"
import { AppLink } from "../AppLink/AppLink"
import { SSHButton } from "../SSHButton/SSHButton"
import { Stack } from "../Stack/Stack"
import { TableHeaderRow } from "../TableHeaders/TableHeaders"
import { TerminalLink } from "../TerminalLink/TerminalLink"
Expand Down Expand Up @@ -107,18 +108,17 @@ export const Resources: FC<ResourcesProps> = ({
<span style={{ color: agentStatus.color }}>{agentStatus.status}</span>
</div>
</TableCell>
{canUpdateWorkspace && (
<TableCell>
<div className={styles.accessLinks}>
{agent.status === "connected" && (
<TableCell>
<>
{canUpdateWorkspace && agent.status === "connected" && (
<div className={styles.accessLinks}>
<SSHButton workspaceName={workspace.name} agentName={agent.name} />
<TerminalLink
workspaceName={workspace.name}
agentName={agent.name}
userName={workspace.owner_name}
/>
)}
{agent.status === "connected" &&
agent.apps.map((app) => (
{agent.apps.map((app) => (
<AppLink
key={app.name}
appIcon={app.icon}
Expand All @@ -127,9 +127,10 @@ export const Resources: FC<ResourcesProps> = ({
workspaceName={workspace.name}
/>
))}
</div>
</TableCell>
)}
</div>
)}
</>
</TableCell>
</TableRow>
)
})
Expand Down
23 changes: 23 additions & 0 deletions site/src/components/SSHButton/SSHButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Story } from "@storybook/react"
import { MockWorkspace, MockWorkspaceAgent } from "../../testHelpers/renderHelpers"
import { SSHButton, SSHButtonProps } from "./SSHButton"

export default {
title: "components/SSHButton",
component: SSHButton,
}

const Template: Story<SSHButtonProps> = (args) => <SSHButton {...args} />

export const Closed = Template.bind({})
Closed.args = {
workspaceName: MockWorkspace.name,
agentName: MockWorkspaceAgent.name,
}

export const Opened = Template.bind({})
Opened.args = {
workspaceName: MockWorkspace.name,
agentName: MockWorkspaceAgent.name,
defaultIsOpen: true,
}
109 changes: 109 additions & 0 deletions site/src/components/SSHButton/SSHButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import Button from "@material-ui/core/Button"
import Popover from "@material-ui/core/Popover"
import { makeStyles } from "@material-ui/core/styles"
import CloudIcon from "@material-ui/icons/CloudOutlined"
import { useRef, useState } from "react"
import { CodeExample } from "../CodeExample/CodeExample"
import { Stack } from "../Stack/Stack"
import { HelpTooltipLink, HelpTooltipLinksGroup, HelpTooltipText } from "../Tooltips/HelpTooltip"

export interface SSHButtonProps {
workspaceName: string
agentName: string
defaultIsOpen?: boolean
}

export const SSHButton: React.FC<SSHButtonProps> = ({
workspaceName,
agentName,
defaultIsOpen = false,
}) => {
const anchorRef = useRef<HTMLButtonElement>(null)
const [isOpen, setIsOpen] = useState(defaultIsOpen)
const id = isOpen ? "schedule-popover" : undefined
const styles = useStyles()

const onClose = () => {
setIsOpen(false)
}

return (
<>
<Button
startIcon={<CloudIcon />}
size="small"
ref={anchorRef}
onClick={() => {
setIsOpen(true)
}}
>
SSH
</Button>
<Popover
classes={{ paper: styles.popoverPaper }}
id={id}
open={isOpen}
anchorEl={anchorRef.current}
onClose={onClose}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<HelpTooltipText>Run the following commands to connect with SSH:</HelpTooltipText>

<Stack spacing={0.5} className={styles.codeExamples}>
<div>
<HelpTooltipText>
<strong className={styles.codeExampleLabel}>
Configure ssh{" "}
<span className={styles.textHelper}>
- only needs to be run once, or after managing workspaces
</span>
</strong>
</HelpTooltipText>
<CodeExample code="coder config-ssh" />
</div>

<div>
<HelpTooltipText>
<strong className={styles.codeExampleLabel}>Connect to the agent</strong>
</HelpTooltipText>
<CodeExample code={`ssh coder.${workspaceName}.${agentName}`} />
</div>
</Stack>

<HelpTooltipLinksGroup>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about having some text before these links introducing them as docs? Like "For more information:" or something like that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... I would add if the links are not explicit enough.

<HelpTooltipLink href="#">Install Coder CLI</HelpTooltipLink>
<HelpTooltipLink href="#">Configuring VS Code</HelpTooltipLink>
<HelpTooltipLink href="#">SSH configuration</HelpTooltipLink>
</HelpTooltipLinksGroup>
</Popover>
</>
)
}

const useStyles = makeStyles((theme) => ({
popoverPaper: {
padding: `${theme.spacing(2)}px ${theme.spacing(3)}px ${theme.spacing(3)}px`,
width: theme.spacing(38),
color: theme.palette.text.secondary,
marginTop: theme.spacing(0.25),
},

codeExamples: {
marginTop: theme.spacing(1.5),
},

codeExampleLabel: {
fontSize: 12,
},

textHelper: {
fontWeight: 400,
},
}))