mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
feat: Display warning on agent connection timeout (#4983)
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
MockWorkspace,
|
||||
MockWorkspaceAgent,
|
||||
MockWorkspaceAgentConnecting,
|
||||
MockWorkspaceAgentTimeout,
|
||||
MockWorkspaceApp,
|
||||
} from "testHelpers/entities"
|
||||
import { AgentRow, AgentRowProps } from "./AgentRow"
|
||||
@@ -67,3 +68,11 @@ Connecting.args = {
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
export const Timeout = Template.bind({})
|
||||
Timeout.args = {
|
||||
agent: MockWorkspaceAgentTimeout,
|
||||
workspace: MockWorkspace,
|
||||
applicationsHost: "",
|
||||
showApps: true,
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { AgentVersion } from "./AgentVersion"
|
||||
import { Maybe } from "components/Conditionals/Maybe"
|
||||
import { AgentStatus } from "./AgentStatus"
|
||||
import { AppLinkSkeleton } from "components/AppLink/AppLinkSkeleton"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
export interface AgentRowProps {
|
||||
agent: WorkspaceAgent
|
||||
@@ -31,6 +32,7 @@ export const AgentRow: FC<AgentRowProps> = ({
|
||||
serverVersion,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const { t } = useTranslation("agent")
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -43,7 +45,7 @@ export const AgentRow: FC<AgentRowProps> = ({
|
||||
>
|
||||
<Stack direction="row" alignItems="baseline">
|
||||
<div className={styles.agentStatusWrapper}>
|
||||
<AgentStatus agent={agent} />
|
||||
<AgentStatus agent={agent} workspace={workspace} />
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.agentName}>{agent.name}</div>
|
||||
@@ -65,6 +67,10 @@ export const AgentRow: FC<AgentRowProps> = ({
|
||||
<Skeleton width={160} variant="text" />
|
||||
<Skeleton width={36} variant="text" />
|
||||
</Maybe>
|
||||
|
||||
<Maybe condition={agent.status === "timeout"}>
|
||||
{t("unableToConnect")}
|
||||
</Maybe>
|
||||
</Stack>
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
import Tooltip from "@material-ui/core/Tooltip"
|
||||
import { makeStyles } from "@material-ui/core/styles"
|
||||
import { combineClasses } from "util/combineClasses"
|
||||
import { WorkspaceAgent } from "api/typesGenerated"
|
||||
import { Workspace, WorkspaceAgent } from "api/typesGenerated"
|
||||
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import WarningRounded from "@material-ui/icons/WarningRounded"
|
||||
import {
|
||||
HelpPopover,
|
||||
HelpTooltipText,
|
||||
HelpTooltipTitle,
|
||||
} from "components/Tooltips/HelpTooltip"
|
||||
import { useRef, useState } from "react"
|
||||
import Link from "@material-ui/core/Link"
|
||||
|
||||
const ConnectedStatus: React.FC = () => {
|
||||
const styles = useStyles()
|
||||
const { t } = useTranslation("workspacePage")
|
||||
|
||||
return (
|
||||
<Tooltip title={t("agentStatus.connected")}>
|
||||
<div
|
||||
role="status"
|
||||
aria-label={t("agentStatus.connected")}
|
||||
className={combineClasses([styles.status, styles.connected])}
|
||||
/>
|
||||
</Tooltip>
|
||||
<div
|
||||
role="status"
|
||||
aria-label={t("agentStatus.connected")}
|
||||
className={combineClasses([styles.status, styles.connected])}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -50,7 +56,52 @@ const ConnectingStatus: React.FC = () => {
|
||||
)
|
||||
}
|
||||
|
||||
export const AgentStatus: React.FC<{ agent: WorkspaceAgent }> = ({ agent }) => {
|
||||
const TimeoutStatus: React.FC<{
|
||||
agent: WorkspaceAgent
|
||||
workspace: Workspace
|
||||
}> = ({ agent, workspace }) => {
|
||||
const { t } = useTranslation("agent")
|
||||
const styles = useStyles()
|
||||
const anchorRef = useRef<SVGSVGElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const id = isOpen ? "timeout-popover" : undefined
|
||||
const troubleshootLink =
|
||||
agent.troubleshooting_url ?? `/templates/${workspace.template_name}#readme`
|
||||
|
||||
return (
|
||||
<>
|
||||
<WarningRounded
|
||||
ref={anchorRef}
|
||||
onMouseEnter={() => setIsOpen(true)}
|
||||
onMouseLeave={() => setIsOpen(false)}
|
||||
role="status"
|
||||
aria-label={t("status.timeout")}
|
||||
className={styles.timeoutWarning}
|
||||
/>
|
||||
<HelpPopover
|
||||
id={id}
|
||||
open={isOpen}
|
||||
anchorEl={anchorRef.current}
|
||||
onOpen={() => setIsOpen(true)}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<HelpTooltipTitle>{t("timeoutTooltip.title")}</HelpTooltipTitle>
|
||||
<HelpTooltipText>
|
||||
{t("timeoutTooltip.message")}{" "}
|
||||
<Link target="_blank" rel="noreferrer" href={troubleshootLink}>
|
||||
{t("timeoutTooltip.link")}
|
||||
</Link>
|
||||
.
|
||||
</HelpTooltipText>
|
||||
</HelpPopover>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const AgentStatus: React.FC<{
|
||||
agent: WorkspaceAgent
|
||||
workspace: Workspace
|
||||
}> = ({ agent, workspace }) => {
|
||||
return (
|
||||
<ChooseOne>
|
||||
<Cond condition={agent.status === "connected"}>
|
||||
@@ -59,6 +110,9 @@ export const AgentStatus: React.FC<{ agent: WorkspaceAgent }> = ({ agent }) => {
|
||||
<Cond condition={agent.status === "disconnected"}>
|
||||
<DisconnectedStatus />
|
||||
</Cond>
|
||||
<Cond condition={agent.status === "timeout"}>
|
||||
<TimeoutStatus agent={agent} workspace={workspace} />
|
||||
</Cond>
|
||||
<Cond>
|
||||
<ConnectingStatus />
|
||||
</Cond>
|
||||
@@ -98,4 +152,12 @@ const useStyles = makeStyles((theme) => ({
|
||||
backgroundColor: theme.palette.info.light,
|
||||
animation: "$pulse 1.5s 0.5s ease-in-out forwards infinite",
|
||||
},
|
||||
|
||||
timeoutWarning: {
|
||||
color: theme.palette.warning.light,
|
||||
width: theme.spacing(2.5),
|
||||
height: theme.spacing(2.5),
|
||||
position: "relative",
|
||||
top: theme.spacing(1),
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -9,5 +9,14 @@
|
||||
"os": "OS",
|
||||
"apps": "Apps",
|
||||
"noApps": "None"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
"timeout": "Timeout"
|
||||
},
|
||||
"timeoutTooltip": {
|
||||
"title": "Agent is taking too long to connect",
|
||||
"message": "We noticed this agent is taking longer than expected to connect. You can try troubleshooting the issue",
|
||||
"link": "here"
|
||||
},
|
||||
"unableToConnect": "Unable to connect"
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
"agentStatus": {
|
||||
"connected": "Connected",
|
||||
"connecting": "Connecting...",
|
||||
"disconnected": "Disconnected"
|
||||
"disconnected": "Disconnected",
|
||||
"timeout": "Timeout"
|
||||
},
|
||||
"buildMessage": {
|
||||
"start": "started",
|
||||
|
||||
@@ -59,7 +59,7 @@ export const TemplateSummaryPageView: FC<
|
||||
resources={getStartedResources(templateResources)}
|
||||
/>
|
||||
|
||||
<div className={styles.markdownSection}>
|
||||
<div className={styles.markdownSection} id="readme">
|
||||
<div className={styles.readmeLabel}>README.md</div>
|
||||
<div className={styles.markdownWrapper}>
|
||||
<MemoizedMarkdown>{readme.body}</MemoizedMarkdown>
|
||||
|
||||
Reference in New Issue
Block a user