From 06c9bef632e204da918a5ea548e8de11e9513918 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 13:49:02 +0000 Subject: [PATCH 01/26] Refactor resource metadata --- .vscode/settings.json | 1 + site/src/components/Resources/AgentRow.tsx | 39 +++++---- site/src/pages/WorkspacePage/Workspace.tsx | 96 ++++++++++++++++++++-- 3 files changed, 109 insertions(+), 27 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f9b18af11a55d..1b7cb32e874c5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,7 @@ "bodyclose", "buildinfo", "buildname", + "childrens", "circbuf", "cliflag", "cliui", diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 36358d7f921dd..626f68d2adfb9 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -163,7 +163,7 @@ export const AgentRow: FC = ({ styles[`agentRow-lifecycle-${agent.lifecycle_state}`], ]} > -
+
@@ -270,7 +270,7 @@ export const AgentRow: FC = ({ />
)} -
+
@@ -506,61 +506,59 @@ const useAgentLogs = ( const styles = { agentRow: (theme) => ({ fontSize: 16, - borderLeft: `2px solid ${theme.palette.text.secondary}`, - - "&:not(:first-of-type)": { - borderTop: `2px solid ${theme.palette.divider}`, - }, + border: `1px solid ${theme.palette.text.secondary}`, + backgroundColor: theme.palette.background.default, + borderRadius: 8, }), "agentRow-connected": (theme) => ({ - borderLeftColor: theme.palette.success.light, + borderColor: theme.palette.success.light, }), "agentRow-disconnected": (theme) => ({ - borderLeftColor: theme.palette.text.secondary, + borderColor: theme.palette.text.secondary, }), "agentRow-connecting": (theme) => ({ - borderLeftColor: theme.palette.info.light, + borderColor: theme.palette.info.light, }), "agentRow-timeout": (theme) => ({ - borderLeftColor: theme.palette.warning.light, + borderColor: theme.palette.warning.light, }), "agentRow-lifecycle-created": {}, "agentRow-lifecycle-starting": (theme) => ({ - borderLeftColor: theme.palette.info.light, + borderColor: theme.palette.info.light, }), "agentRow-lifecycle-ready": (theme) => ({ - borderLeftColor: theme.palette.success.light, + borderColor: theme.palette.success.light, }), "agentRow-lifecycle-start_timeout": (theme) => ({ - borderLeftColor: theme.palette.warning.light, + borderColor: theme.palette.warning.light, }), "agentRow-lifecycle-start_error": (theme) => ({ - borderLeftColor: theme.palette.error.light, + borderColor: theme.palette.error.light, }), "agentRow-lifecycle-shutting_down": (theme) => ({ - borderLeftColor: theme.palette.info.light, + borderColor: theme.palette.info.light, }), "agentRow-lifecycle-shutdown_timeout": (theme) => ({ - borderLeftColor: theme.palette.warning.light, + borderColor: theme.palette.warning.light, }), "agentRow-lifecycle-shutdown_error": (theme) => ({ - borderLeftColor: theme.palette.error.light, + borderColor: theme.palette.error.light, }), "agentRow-lifecycle-off": (theme) => ({ - borderLeftColor: theme.palette.text.secondary, + borderColor: theme.palette.text.secondary, }), agentInfo: (theme) => ({ @@ -570,7 +568,6 @@ const styles = { alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", - backgroundColor: theme.palette.background.paper, [theme.breakpoints.down("md")]: { gap: 16, @@ -675,6 +672,8 @@ const styles = { gap: 8, whiteSpace: "nowrap", width: "100%", + borderBottomLeftRadius: 8, + borderBottomRightRadius: 8, "&:hover": { color: theme.palette.text.primary, diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index dff3f1f9041a1..867e74a5af1f6 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -1,7 +1,7 @@ import { type Interpolation, type Theme } from "@emotion/react"; import Button from "@mui/material/Button"; import AlertTitle from "@mui/material/AlertTitle"; -import { type FC } from "react"; +import { PropsWithChildren, type FC, Children } from "react"; import { useNavigate } from "react-router-dom"; import type * as TypesGen from "api/typesGenerated"; import { Alert, AlertDetail } from "components/Alert/Alert"; @@ -19,9 +19,11 @@ import { useTheme } from "@mui/material/styles"; import { SidebarIconButton } from "components/FullPageLayout/Sidebar"; import HubOutlined from "@mui/icons-material/HubOutlined"; import { ResourcesSidebar } from "./ResourcesSidebar"; -import { ResourceCard } from "components/Resources/ResourceCard"; import { WorkspacePermissions } from "./permissions"; import { resourceOptionValue, useResourcesNav } from "./useResourcesNav"; +import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; +import { SensitiveValue } from "components/Resources/SensitiveValue"; +import { CopyableValue } from "components/CopyableValue/CopyableValue"; export interface WorkspaceProps { handleStart: (buildParameters?: TypesGen.WorkspaceBuildParameter[]) => void; @@ -182,6 +184,9 @@ export const Workspace: FC = ({
+ {selectedResource && ( + + )}
= ({ {buildLogs} {selectedResource && ( - ( +
+ {selectedResource.agents?.map((agent) => ( = ({ serverAPIVersion={buildInfo?.agent_api_version || ""} onUpdateAgent={handleUpdate} // On updating the workspace the agent version is also updated /> - )} - /> + ))} +
)}
@@ -255,6 +261,53 @@ export const Workspace: FC = ({ ); }; +const WorkspaceResourceData: FC<{ resource: TypesGen.WorkspaceResource }> = ({ + resource, +}) => { + const metadata = resource.metadata ?? []; + + if (resource.daily_cost > 0) { + metadata.push({ + key: "Daily cost", + value: resource.daily_cost.toString(), + sensitive: false, + }); + } + + if (metadata.length === 0) { + return null; + } + + return ( +
+ {resource.metadata?.map((meta) => { + return ( +
+
+ {meta.sensitive ? ( + + ) : ( + + {meta.value} + + )} +
+
{meta.key}
+
+ ); + })} +
+ ); +}; + +const p = ({ children }: PropsWithChildren) => { + const childrens = Children.toArray(children); + if (childrens.every((child) => typeof child === "string")) { + return {children}; + } + return <>{children}; +}; + const countAgents = (resource: TypesGen.WorkspaceResource) => { return resource.agents ? resource.agents.length : 0; }; @@ -264,6 +317,7 @@ const styles = { padding: 24, gridArea: "content", overflowY: "auto", + position: "relative", }, dotBackground: (theme) => ({ @@ -288,4 +342,32 @@ const styles = { flexDirection: "column", }, }), + + resourceData: (theme) => ({ + padding: 24, + margin: "-48px 0 0 -48px", + display: "flex", + gap: 48, + marginBottom: 24, + fontSize: 14, + background: `linear-gradient(180deg, ${theme.palette.background.default} 0%, rgba(0, 0, 0, 0) 100%)`, + }), + + resourceDataItem: () => ({ + lineHeight: "1.5", + }), + + resourceDataItemLabel: (theme) => ({ + fontSize: 13, + color: theme.palette.text.secondary, + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", + }), + + resourceDataItemValue: () => ({ + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", + }), } satisfies Record>; From f2346e68568dc5503bfcd24dd2f3b13a2d0a8b5b Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 15:39:28 +0000 Subject: [PATCH 02/26] Fix scrolling --- site/src/pages/WorkspacePage/Workspace.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 867e74a5af1f6..9745923d1719d 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -110,6 +110,7 @@ export const Workspace: FC = ({ return (
Date: Tue, 16 Jan 2024 16:02:13 +0000 Subject: [PATCH 03/26] Refactor agent apps --- site/src/components/Resources/AgentButton.tsx | 22 +- site/src/components/Resources/AgentRow.tsx | 219 +++++++++--------- site/src/utils/latency.ts | 6 +- 3 files changed, 122 insertions(+), 125 deletions(-) diff --git a/site/src/components/Resources/AgentButton.tsx b/site/src/components/Resources/AgentButton.tsx index 58f0e533b8095..7fe5376a316d3 100644 --- a/site/src/components/Resources/AgentButton.tsx +++ b/site/src/components/Resources/AgentButton.tsx @@ -1,32 +1,30 @@ import Button, { type ButtonProps } from "@mui/material/Button"; -import { useTheme } from "@emotion/react"; import { forwardRef } from "react"; // eslint-disable-next-line react/display-name -- Name is inferred from variable name export const AgentButton = forwardRef( (props, ref) => { const { children, ...buttonProps } = props; - const theme = useTheme(); return ( diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 626f68d2adfb9..5df7afdf800d0 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -31,7 +31,6 @@ import { FixedSizeList as List, ListOnScrollProps } from "react-window"; import { Stack } from "../Stack/Stack"; import { AgentLatency } from "./AgentLatency"; import { AgentMetadata } from "./AgentMetadata"; -import { AgentStatus } from "./AgentStatus"; import { AgentVersion } from "./AgentVersion"; import { AppLink } from "./AppLink/AppLink"; import { PortForwardButton } from "./PortForwardButton"; @@ -163,114 +162,102 @@ export const AgentRow: FC = ({ styles[`agentRow-lifecycle-${agent.lifecycle_state}`], ]} > -
-
-
- -
{agent.name}
- - {agent.status === "connected" && ( - <> - {agent.operating_system} - - - - )} - {agent.status === "connecting" && ( - <> - - - - )} - -
+
+
+
{agent.name}
+ {agent.status === "connected" && ( + <> + + + + )} + {agent.status === "connecting" && ( + <> + + + + )}
+
- {agent.status === "connected" && ( -
- {shouldDisplayApps && ( - <> - {(agent.display_apps.includes("vscode") || - agent.display_apps.includes("vscode_insiders")) && - !hideVSCodeDesktopButton && ( - - )} - {agent.apps.map((app) => ( - - ))} - - )} - - {showBuiltinApps && ( - <> - {agent.display_apps.includes("web_terminal") && ( - + {shouldDisplayApps && ( + <> + {(agent.display_apps.includes("vscode") || + agent.display_apps.includes("vscode_insiders")) && + !hideVSCodeDesktopButton && ( + )} - {!hideSSHButton && - agent.display_apps.includes("ssh_helper") && ( - - )} - {proxy.preferredWildcardHostname && - proxy.preferredWildcardHostname !== "" && - agent.display_apps.includes("port_forwarding_helper") && ( - - )} - - )} -
- )} - - {agent.status === "connecting" && ( -
- - -
- )} -
+ {agent.apps.map((app) => ( + + ))} + + )} + + {showBuiltinApps && ( + <> + {agent.display_apps.includes("web_terminal") && ( + + )} + {!hideSSHButton && agent.display_apps.includes("ssh_helper") && ( + + )} + {proxy.preferredWildcardHostname && + proxy.preferredWildcardHostname !== "" && + agent.display_apps.includes("port_forwarding_helper") && ( + + )} + + )} + + )} + + {agent.status === "connecting" && ( +
+ + +
+ )} @@ -505,7 +492,7 @@ const useAgentLogs = ( const styles = { agentRow: (theme) => ({ - fontSize: 16, + fontSize: 14, border: `1px solid ${theme.palette.text.secondary}`, backgroundColor: theme.palette.background.default, borderRadius: 8, @@ -561,19 +548,29 @@ const styles = { borderColor: theme.palette.text.secondary, }), - agentInfo: (theme) => ({ - padding: "24px 32px", + header: (theme) => ({ + padding: "16px 24px", display: "flex", - gap: 16, + gap: 24, alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", + lineHeight: "1.5", + borderBottom: `1px solid ${theme.palette.divider}`, [theme.breakpoints.down("md")]: { gap: 16, }, }), + agentInfo: (theme) => ({ + display: "flex", + alignItems: "center", + gap: 24, + color: theme.palette.text.secondary, + fontSize: 13, + }), + agentNameAndInfo: (theme) => ({ display: "flex", alignItems: "center", @@ -585,9 +582,10 @@ const styles = { }, }), - agentButtons: (theme) => ({ + apps: (theme) => ({ + padding: 24, display: "flex", - gap: 8, + gap: 16, flexWrap: "wrap", [theme.breakpoints.down("md")]: { @@ -629,9 +627,10 @@ const styles = { textOverflow: "ellipsis", maxWidth: 260, fontWeight: 600, - fontSize: 16, flexShrink: 0, width: "fit-content", + fontSize: 14, + color: theme.palette.text.primary, [theme.breakpoints.down("md")]: { overflow: "unset", diff --git a/site/src/utils/latency.ts b/site/src/utils/latency.ts index 4281fa17e990f..b98aba8954fc3 100644 --- a/site/src/utils/latency.ts +++ b/site/src/utils/latency.ts @@ -5,12 +5,12 @@ export const getLatencyColor = (theme: Theme, latency?: number) => { return theme.palette.text.secondary; } - let color = theme.experimental.roles.success.fill; + let color = theme.experimental.roles.success.outline; if (latency >= 150 && latency < 300) { - color = theme.experimental.roles.warning.fill; + color = theme.experimental.roles.warning.outline; } else if (latency >= 300) { - color = theme.experimental.roles.error.fill; + color = theme.experimental.roles.error.outline; } return color; }; From 0a2cb43f5889a1c6c41f21a97066be8e7cb7d4f6 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 16:21:55 +0000 Subject: [PATCH 04/26] Refactor metadata and logs button --- .../components/Resources/AgentMetadata.tsx | 60 +++++++++---------- site/src/components/Resources/AgentRow.tsx | 33 +++++----- 2 files changed, 43 insertions(+), 50 deletions(-) diff --git a/site/src/components/Resources/AgentMetadata.tsx b/site/src/components/Resources/AgentMetadata.tsx index ab78842854fb1..6776b5be7c4c0 100644 --- a/site/src/components/Resources/AgentMetadata.tsx +++ b/site/src/components/Resources/AgentMetadata.tsx @@ -98,16 +98,14 @@ export const AgentMetadataView: FC = ({ metadata }) => { return null; } return ( -
- - {metadata.map((m) => { - if (m.description === undefined) { - throw new Error("Metadata item description is undefined"); - } - return ; - })} - -
+
+ {metadata.map((m) => { + if (m.description === undefined) { + throw new Error("Metadata item description is undefined"); + } + return ; + })} +
); }; @@ -162,13 +160,19 @@ export const AgentMetadata: FC = ({ if (metadata === undefined) { return ( -
+
-
+ ); } - return ; + return ( + + a.description.display_name.localeCompare(b.description.display_name), + )} + /> + ); }; export const AgentMetadataSkeleton: FC = () => { @@ -221,25 +225,21 @@ const StaticWidth: FC> = ({ // These are more or less copied from // site/src/components/Resources/ResourceCard.tsx const styles = { - root: (theme) => ({ - padding: "20px 32px", - borderTop: `1px solid ${theme.palette.divider}`, - overflowX: "auto", - scrollPadding: "0 32px", - }), + root: { + padding: "0 24px 32px", + display: "flex", + alignItems: "baseline", + flexWrap: "wrap", + gap: 32, + rowGap: 16, + }, metadata: { - fontSize: 12, - lineHeight: "normal", + lineHeight: "1.6", display: "flex", flexDirection: "column", - gap: 4, overflow: "visible", - - // Because of scrolling - "&:last-child": { - paddingRight: 32, - }, + flexShrink: 0, }, metadataLabel: (theme) => ({ @@ -247,7 +247,7 @@ const styles = { textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap", - fontWeight: 500, + fontSize: 13, }), metadataValue: { @@ -259,9 +259,7 @@ const styles = { }, metadataValueSuccess: (theme) => ({ - // color: theme.palette.success.light, - color: theme.experimental.roles.success.fill, - // color: theme.experimental.roles.success.text, + color: theme.experimental.roles.success.outline, }), metadataValueError: (theme) => ({ diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 5df7afdf800d0..4b40516f17fbb 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -243,7 +243,7 @@ export const AgentRow: FC = ({ )} {agent.status === "connecting" && ( -
+
= ({ variant="rectangular" css={styles.buttonSkeleton} /> -
+ )} {hasStartupFeatures && ( -
+
{({ width }) => ( @@ -417,16 +417,14 @@ export const AgentRow: FC = ({ -
- -
-
+ + )} ); @@ -583,7 +581,7 @@ const styles = { }), apps: (theme) => ({ - padding: 24, + padding: "32px 24px", display: "flex", gap: 16, flexWrap: "wrap", @@ -602,6 +600,7 @@ const styles = { startupLogs: (theme) => ({ maxHeight: 256, borderBottom: `1px solid ${theme.palette.divider}`, + borderTop: `1px solid ${theme.palette.divider}`, backgroundColor: theme.palette.background.paper, paddingTop: 16, @@ -654,16 +653,12 @@ const styles = { }, }), - logsPanel: (theme) => ({ - borderTop: `1px solid ${theme.palette.divider}`, - }), - logsPanelButton: (theme) => ({ textAlign: "left", background: "transparent", border: 0, fontFamily: "inherit", - padding: "12px 32px", + padding: "16px 24px", color: theme.palette.text.secondary, cursor: "pointer", display: "flex", From 7db1022a13b8e8caa448bed2a2c9f261a7920d5c Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 16:35:51 +0000 Subject: [PATCH 05/26] Refactor ssh and open port actions --- site/src/components/Resources/AgentRow.tsx | 46 +++++++++++-------- .../components/Resources/AppLink/AppLink.tsx | 4 +- .../Resources/PortForwardButton.tsx | 29 ++++++++---- .../Resources/SSHButton/SSHButton.tsx | 12 ++++- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 4b40516f17fbb..5a2913c0d5cea 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -183,6 +183,28 @@ export const AgentRow: FC = ({ )}
+ + {showBuiltinApps && ( +
+ {!hideSSHButton && agent.display_apps.includes("ssh_helper") && ( + + )} + {proxy.preferredWildcardHostname && + proxy.preferredWildcardHostname !== "" && + agent.display_apps.includes("port_forwarding_helper") && ( + + )} +
+ )} {agent.status === "connected" && ( @@ -220,23 +242,6 @@ export const AgentRow: FC = ({ userName={workspace.owner_name} /> )} - {!hideSSHButton && agent.display_apps.includes("ssh_helper") && ( - - )} - {proxy.preferredWildcardHostname && - proxy.preferredWildcardHostname !== "" && - agent.display_apps.includes("port_forwarding_helper") && ( - - )} )} @@ -262,7 +267,9 @@ export const AgentRow: FC = ({ {hasStartupFeatures && ( -
+
({ borderTop: `1px solid ${theme.palette.divider}` })} + > {({ width }) => ( @@ -600,7 +607,6 @@ const styles = { startupLogs: (theme) => ({ maxHeight: 256, borderBottom: `1px solid ${theme.palette.divider}`, - borderTop: `1px solid ${theme.palette.divider}`, backgroundColor: theme.palette.background.paper, paddingTop: 16, @@ -658,7 +664,7 @@ const styles = { background: "transparent", border: 0, fontFamily: "inherit", - padding: "16px 24px", + padding: "12px 24px", color: theme.palette.text.secondary, cursor: "pointer", display: "flex", diff --git a/site/src/components/Resources/AppLink/AppLink.tsx b/site/src/components/Resources/AppLink/AppLink.tsx index 24afe3cef541f..6e6bd90ae39c3 100644 --- a/site/src/components/Resources/AppLink/AppLink.tsx +++ b/site/src/components/Resources/AppLink/AppLink.tsx @@ -14,8 +14,8 @@ import { BaseIcon } from "./BaseIcon"; import { ShareIcon } from "./ShareIcon"; export const DisplayAppNameMap: Record = { - port_forwarding_helper: "Ports", - ssh_helper: "SSH", + port_forwarding_helper: "Open ports", + ssh_helper: "Connect SSH", vscode: "VS Code Desktop", vscode_insiders: "VS Code Insiders", web_terminal: "Terminal", diff --git a/site/src/components/Resources/PortForwardButton.tsx b/site/src/components/Resources/PortForwardButton.tsx index 2b284586eaf45..8fda535706be9 100644 --- a/site/src/components/Resources/PortForwardButton.tsx +++ b/site/src/components/Resources/PortForwardButton.tsx @@ -20,13 +20,13 @@ import { HelpTooltipText, HelpTooltipTitle, } from "components/HelpTooltip/HelpTooltip"; -import { AgentButton } from "components/Resources/AgentButton"; import { Popover, PopoverContent, PopoverTrigger, } from "components/Popover/Popover"; import { DisplayAppNameMap } from "./AppLink/AppLink"; +import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown"; export interface PortForwardButtonProps { host: string; @@ -59,14 +59,24 @@ export const PortForwardButton: FC = (props) => { return ( - + @@ -214,8 +224,7 @@ const styles = { display: "flex", alignItems: "center", justifyContent: "center", - backgroundColor: theme.experimental.l2.background, - marginLeft: 8, + backgroundColor: theme.palette.action.selected, }), portLink: (theme) => ({ diff --git a/site/src/components/Resources/SSHButton/SSHButton.tsx b/site/src/components/Resources/SSHButton/SSHButton.tsx index 9788618df6406..80f8cb2ebbe78 100644 --- a/site/src/components/Resources/SSHButton/SSHButton.tsx +++ b/site/src/components/Resources/SSHButton/SSHButton.tsx @@ -14,8 +14,9 @@ import { PopoverTrigger, } from "components/Popover/Popover"; import { Stack } from "components/Stack/Stack"; -import { AgentButton } from "../AgentButton"; import { DisplayAppNameMap } from "../AppLink/AppLink"; +import Button from "@mui/material/Button"; +import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown"; export interface SSHButtonProps { workspaceName: string; @@ -35,7 +36,14 @@ export const SSHButton: FC> = ({ return ( - {DisplayAppNameMap["ssh_helper"]} + From 91fe9f2484311ded2162229f20acfb95a8361fb3 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 16:48:07 +0000 Subject: [PATCH 06/26] Add terminal icon to the terminal button --- site/src/components/Resources/AgentRow.tsx | 16 ++++++---------- .../Resources/TerminalLink/TerminalLink.tsx | 5 ++++- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 5a2913c0d5cea..3a75e5f4c424f 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -233,16 +233,12 @@ export const AgentRow: FC = ({ )} - {showBuiltinApps && ( - <> - {agent.display_apps.includes("web_terminal") && ( - - )} - + {showBuiltinApps && agent.display_apps.includes("web_terminal") && ( + )}
)} diff --git a/site/src/components/Resources/TerminalLink/TerminalLink.tsx b/site/src/components/Resources/TerminalLink/TerminalLink.tsx index d1a8e4e9b170b..987fbc229d44a 100644 --- a/site/src/components/Resources/TerminalLink/TerminalLink.tsx +++ b/site/src/components/Resources/TerminalLink/TerminalLink.tsx @@ -4,6 +4,7 @@ import { FC } from "react"; import * as TypesGen from "api/typesGenerated"; import { generateRandomString } from "utils/random"; import { DisplayAppNameMap } from "../AppLink/AppLink"; +import { TerminalIcon } from "components/Icons/TerminalIcon"; export const Language = { terminalTitle: (identifier: string): string => `Terminal - ${identifier}`, @@ -46,7 +47,9 @@ export const TerminalLink: FC> = ({ }} data-testid="terminal" > - {DisplayAppNameMap["web_terminal"]} + }> + {DisplayAppNameMap["web_terminal"]} + ); }; From 0438f3a3f33d4dddaa951fc8efc0479cf7594fea Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 17:01:30 +0000 Subject: [PATCH 07/26] Add simple message for agentless resources --- site/src/pages/WorkspacePage/Workspace.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index 9745923d1719d..e33f3f702695e 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -253,6 +253,25 @@ export const Workspace: FC = ({ onUpdateAgent={handleUpdate} // On updating the workspace the agent version is also updated /> ))} + + {(!selectedResource.agents || + selectedResource.agents?.length === 0) && ( +
+
+

+ No agents are currently assigned to this resource. +

+
+
+ )}
)}
From c3411b308ce9b27f9cddd76fc4a13fa5d620ea45 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 17:06:15 +0000 Subject: [PATCH 08/26] Add back agent status --- site/src/components/Resources/AgentRow.tsx | 8 ++++++-- site/src/components/Resources/AgentStatus.tsx | 12 ++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 3a75e5f4c424f..46be12b4bb3dd 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -36,6 +36,7 @@ import { AppLink } from "./AppLink/AppLink"; import { PortForwardButton } from "./PortForwardButton"; import { SSHButton } from "./SSHButton/SSHButton"; import { TerminalLink } from "./TerminalLink/TerminalLink"; +import { AgentStatus } from "./AgentStatus"; // Logs are stored as the Line interface to make rendering // much more efficient. Instead of mapping objects each time, we're @@ -164,7 +165,10 @@ export const AgentRow: FC = ({ >
-
{agent.name}
+
+ + {agent.name} +
{agent.status === "connected" && ( <> ({ display: "flex", alignItems: "center", - gap: 32, + gap: 12, [theme.breakpoints.down("md")]: { width: "100%", diff --git a/site/src/components/Resources/AgentStatus.tsx b/site/src/components/Resources/AgentStatus.tsx index 0793377994b5c..ffb56953efa4a 100644 --- a/site/src/components/Resources/AgentStatus.tsx +++ b/site/src/components/Resources/AgentStatus.tsx @@ -272,8 +272,8 @@ export const AgentStatus: FC = ({ agent }) => { const styles = { status: { - width: 8, - height: 8, + width: 6, + height: 6, borderRadius: "100%", flexShrink: 0, }, @@ -306,15 +306,15 @@ const styles = { timeoutWarning: (theme) => ({ color: theme.palette.warning.light, - width: 16, - height: 16, + width: 14, + height: 14, position: "relative", }), errorWarning: (theme) => ({ color: theme.palette.error.main, - width: 16, - height: 16, + width: 14, + height: 14, position: "relative", }), } satisfies Record>; From bc1a216f7062d9cac195a18fb011eae0d7794f3e Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 17:11:51 +0000 Subject: [PATCH 09/26] Make agent header thiner --- site/src/components/Resources/AgentRow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 46be12b4bb3dd..c7666a2b1c5b4 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -554,7 +554,7 @@ const styles = { }), header: (theme) => ({ - padding: "16px 24px", + padding: "12px 24px", display: "flex", gap: 24, alignItems: "center", From 0490e894beb3839d7055b075de22f9e182cbeb30 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 19:44:25 +0000 Subject: [PATCH 10/26] rowback the changes on latency color --- site/src/utils/latency.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/src/utils/latency.ts b/site/src/utils/latency.ts index b98aba8954fc3..4281fa17e990f 100644 --- a/site/src/utils/latency.ts +++ b/site/src/utils/latency.ts @@ -5,12 +5,12 @@ export const getLatencyColor = (theme: Theme, latency?: number) => { return theme.palette.text.secondary; } - let color = theme.experimental.roles.success.outline; + let color = theme.experimental.roles.success.fill; if (latency >= 150 && latency < 300) { - color = theme.experimental.roles.warning.outline; + color = theme.experimental.roles.warning.fill; } else if (latency >= 300) { - color = theme.experimental.roles.error.outline; + color = theme.experimental.roles.error.fill; } return color; }; From e4b2aa1ee55412049b0d8230075dc3fae5331257 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 19:50:10 +0000 Subject: [PATCH 11/26] Remove non apps from preview --- site/src/components/Resources/AgentRowPreview.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/site/src/components/Resources/AgentRowPreview.tsx b/site/src/components/Resources/AgentRowPreview.tsx index e4372a131571c..d131b60d5d1fc 100644 --- a/site/src/components/Resources/AgentRowPreview.tsx +++ b/site/src/components/Resources/AgentRowPreview.tsx @@ -6,6 +6,7 @@ import { AppPreview } from "./AppLink/AppPreview"; import { BaseIcon } from "./AppLink/BaseIcon"; import { VSCodeIcon } from "components/Icons/VSCodeIcon"; import { DisplayAppNameMap } from "./AppLink/AppLink"; +import { TerminalIcon } from "components/Icons/TerminalIcon"; interface AgentRowPreviewStyles { // Helpful when there are more than one row so the values are aligned @@ -101,14 +102,9 @@ export const AgentRowPreview: FC = ({ {/* Additionally, we display any apps that are visible, e.g. apps that are included in agent.display_apps */} {agent.display_apps.includes("web_terminal") && ( - {DisplayAppNameMap["web_terminal"]} - )} - {agent.display_apps.includes("ssh_helper") && ( - {DisplayAppNameMap["ssh_helper"]} - )} - {agent.display_apps.includes("port_forwarding_helper") && ( - {DisplayAppNameMap["port_forwarding_helper"]} + + {DisplayAppNameMap["web_terminal"]} )} {/* VSCode display apps (vscode, vscode_insiders) get special presentation */} From 2e542ca06cb101e5e60728702e4c34561b39af8b Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 16 Jan 2024 20:33:15 +0000 Subject: [PATCH 12/26] rowback a few decisions --- site/src/components/Resources/AgentRowPreview.tsx | 8 ++++++++ site/src/components/Resources/AppLink/AppLink.tsx | 4 ++-- site/src/components/Resources/PortForwardButton.tsx | 3 +-- site/src/components/Resources/SSHButton/SSHButton.tsx | 3 +-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/site/src/components/Resources/AgentRowPreview.tsx b/site/src/components/Resources/AgentRowPreview.tsx index d131b60d5d1fc..f088b5ca77f08 100644 --- a/site/src/components/Resources/AgentRowPreview.tsx +++ b/site/src/components/Resources/AgentRowPreview.tsx @@ -107,6 +107,14 @@ export const AgentRowPreview: FC = ({ {DisplayAppNameMap["web_terminal"]} )} + {agent.display_apps.includes("ssh_helper") && ( + {DisplayAppNameMap["ssh_helper"]} + )} + {agent.display_apps.includes("port_forwarding_helper") && ( + + {DisplayAppNameMap["port_forwarding_helper"]} + + )} {/* VSCode display apps (vscode, vscode_insiders) get special presentation */} {agent.display_apps.includes("vscode") ? ( diff --git a/site/src/components/Resources/AppLink/AppLink.tsx b/site/src/components/Resources/AppLink/AppLink.tsx index 6e6bd90ae39c3..24afe3cef541f 100644 --- a/site/src/components/Resources/AppLink/AppLink.tsx +++ b/site/src/components/Resources/AppLink/AppLink.tsx @@ -14,8 +14,8 @@ import { BaseIcon } from "./BaseIcon"; import { ShareIcon } from "./ShareIcon"; export const DisplayAppNameMap: Record = { - port_forwarding_helper: "Open ports", - ssh_helper: "Connect SSH", + port_forwarding_helper: "Ports", + ssh_helper: "SSH", vscode: "VS Code Desktop", vscode_insiders: "VS Code Insiders", web_terminal: "Terminal", diff --git a/site/src/components/Resources/PortForwardButton.tsx b/site/src/components/Resources/PortForwardButton.tsx index 8fda535706be9..40a9cc11dc624 100644 --- a/site/src/components/Resources/PortForwardButton.tsx +++ b/site/src/components/Resources/PortForwardButton.tsx @@ -25,7 +25,6 @@ import { PopoverContent, PopoverTrigger, } from "components/Popover/Popover"; -import { DisplayAppNameMap } from "./AppLink/AppLink"; import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown"; export interface PortForwardButtonProps { @@ -75,7 +74,7 @@ export const PortForwardButton: FC = (props) => { ) } > - {DisplayAppNameMap["port_forwarding_helper"]} + Open ports diff --git a/site/src/components/Resources/SSHButton/SSHButton.tsx b/site/src/components/Resources/SSHButton/SSHButton.tsx index 80f8cb2ebbe78..62b55e9ab3764 100644 --- a/site/src/components/Resources/SSHButton/SSHButton.tsx +++ b/site/src/components/Resources/SSHButton/SSHButton.tsx @@ -14,7 +14,6 @@ import { PopoverTrigger, } from "components/Popover/Popover"; import { Stack } from "components/Stack/Stack"; -import { DisplayAppNameMap } from "../AppLink/AppLink"; import Button from "@mui/material/Button"; import KeyboardArrowDown from "@mui/icons-material/KeyboardArrowDown"; @@ -42,7 +41,7 @@ export const SSHButton: FC> = ({ endIcon={} css={{ fontSize: 13, padding: "8px 12px" }} > - {DisplayAppNameMap["ssh_helper"]} + Connect to SSH From 2b270ecae6a316a95b032527ff0ea519c6e10405 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 17 Jan 2024 13:44:45 +0000 Subject: [PATCH 13/26] Solve a few visual issues --- .../components/Resources/AgentMetadata.tsx | 1 - .../components/Resources/AgentRow.stories.tsx | 11 +- site/src/components/Resources/AgentRow.tsx | 106 ++++++++++-------- .../src/components/Resources/ResourceCard.tsx | 27 +++-- .../Resources/Resources.stories.tsx | 14 +-- .../pages/WorkspacePage/Workspace.stories.tsx | 8 ++ site/src/pages/WorkspacePage/Workspace.tsx | 2 + 7 files changed, 102 insertions(+), 67 deletions(-) diff --git a/site/src/components/Resources/AgentMetadata.tsx b/site/src/components/Resources/AgentMetadata.tsx index 6776b5be7c4c0..ece0e9466a968 100644 --- a/site/src/components/Resources/AgentMetadata.tsx +++ b/site/src/components/Resources/AgentMetadata.tsx @@ -226,7 +226,6 @@ const StaticWidth: FC> = ({ // site/src/components/Resources/ResourceCard.tsx const styles = { root: { - padding: "0 24px 32px", display: "flex", alignItems: "baseline", flexWrap: "wrap", diff --git a/site/src/components/Resources/AgentRow.stories.tsx b/site/src/components/Resources/AgentRow.stories.tsx index b760899683304..4b74c35eb9226 100644 --- a/site/src/components/Resources/AgentRow.stories.tsx +++ b/site/src/components/Resources/AgentRow.stories.tsx @@ -20,6 +20,7 @@ import { MockWorkspaceAgentDeprecated, MockWorkspaceApp, MockProxyLatencies, + MockListeningPortsResponse, } from "testHelpers/entities"; import { AgentRow, LineWithID } from "./AgentRow"; import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext"; @@ -103,7 +104,15 @@ const storybookLogs: LineWithID[] = [ const meta: Meta = { title: "components/AgentRow", - parameters: { chromatic }, + parameters: { + chromatic, + queries: [ + { + key: ["portForward", MockWorkspaceAgent.id], + data: MockListeningPortsResponse, + }, + ], + }, component: AgentRow, args: { storybookLogs, diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index c7666a2b1c5b4..8d4969246ee5b 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -79,6 +79,11 @@ export const AgentRow: FC = ({ showApps && ((agent.status === "connected" && hasAppsToDisplay) || agent.status === "connecting"); + const showVSCode = + (agent.display_apps.includes("vscode") || + agent.display_apps.includes("vscode_insiders")) && + !hideVSCodeDesktopButton; + const logSourceByID = useMemo(() => { const sources: { [id: string]: WorkspaceAgentLogSource } = {}; for (const source of agent.log_sources) { @@ -211,13 +216,12 @@ export const AgentRow: FC = ({ )}
- {agent.status === "connected" && ( -
- {shouldDisplayApps && ( - <> - {(agent.display_apps.includes("vscode") || - agent.display_apps.includes("vscode_insiders")) && - !hideVSCodeDesktopButton && ( +
+ {agent.status === "connected" && ( +
+ {shouldDisplayApps && ( + <> + {showVSCode && ( = ({ displayApps={agent.display_apps} /> )} - {agent.apps.map((app) => ( - - ))} - - )} + {agent.apps.map((app) => ( + + ))} + + )} - {showBuiltinApps && agent.display_apps.includes("web_terminal") && ( - - )} -
- )} + {showBuiltinApps && agent.display_apps.includes("web_terminal") && ( + + )} +
+ )} - {agent.status === "connecting" && ( -
- - -
- )} + {agent.status === "connecting" && ( +
+ + +
+ )} - + +
{hasStartupFeatures && (
({ - borderColor: theme.palette.text.secondary, + borderColor: theme.palette.divider, }), "agentRow-connecting": (theme) => ({ @@ -550,7 +558,7 @@ const styles = { }), "agentRow-lifecycle-off": (theme) => ({ - borderColor: theme.palette.text.secondary, + borderColor: theme.palette.divider, }), header: (theme) => ({ @@ -587,8 +595,14 @@ const styles = { }, }), - apps: (theme) => ({ + content: { padding: "32px 24px", + display: "flex", + flexDirection: "column", + gap: 32, + }, + + apps: (theme) => ({ display: "flex", gap: 16, flexWrap: "wrap", diff --git a/site/src/components/Resources/ResourceCard.tsx b/site/src/components/Resources/ResourceCard.tsx index 17a4505801199..6e7188230a10d 100644 --- a/site/src/components/Resources/ResourceCard.tsx +++ b/site/src/components/Resources/ResourceCard.tsx @@ -1,7 +1,7 @@ import { type FC, type PropsWithChildren, useState } from "react"; import IconButton from "@mui/material/IconButton"; import Tooltip from "@mui/material/Tooltip"; -import { type CSSObject, type Interpolation, type Theme } from "@emotion/react"; +import { type Interpolation, type Theme } from "@emotion/react"; import { Children } from "react"; import type { WorkspaceAgent, WorkspaceResource } from "api/typesGenerated"; import { DropdownArrow } from "../DropdownArrow/DropdownArrow"; @@ -13,14 +13,28 @@ import { SensitiveValue } from "./SensitiveValue"; const styles = { resourceCard: (theme) => ({ - borderRadius: 8, border: `1px solid ${theme.palette.divider}`, background: theme.palette.background.default, + + "&:not(:last-child)": { + borderBottom: 0, + }, + + "&:first-child": { + borderTopLeftRadius: 8, + borderTopRightRadius: 8, + }, + + "&:last-child": { + borderBottomLeftRadius: 8, + borderBottomRightRadius: 8, + }, }), resourceCardProfile: { flexShrink: 0, width: "fit-content", + minWidth: 220, }, resourceCardHeader: (theme) => ({ @@ -37,9 +51,9 @@ const styles = { }, }), - metadata: (theme) => ({ - ...(theme.typography.body2 as CSSObject), - lineHeight: "120%", + metadata: () => ({ + lineHeight: "1.5", + fontSize: 14, }), metadataLabel: (theme) => ({ @@ -50,11 +64,10 @@ const styles = { whiteSpace: "nowrap", }), - metadataValue: (theme) => ({ + metadataValue: () => ({ textOverflow: "ellipsis", overflow: "hidden", whiteSpace: "nowrap", - ...(theme.typography.body1 as CSSObject), }), } satisfies Record>; diff --git a/site/src/components/Resources/Resources.stories.tsx b/site/src/components/Resources/Resources.stories.tsx index 0a7693f5b4ead..8141b6516cc1d 100644 --- a/site/src/components/Resources/Resources.stories.tsx +++ b/site/src/components/Resources/Resources.stories.tsx @@ -1,15 +1,13 @@ -import { action } from "@storybook/addon-actions"; import { MockProxyLatencies, - MockWorkspace, MockWorkspaceResource, MockWorkspaceResourceMultipleAgents, } from "testHelpers/entities"; -import { AgentRow } from "./AgentRow"; import { Resources } from "./Resources"; import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext"; import type { Meta, StoryObj } from "@storybook/react"; import { type WorkspaceAgent } from "api/typesGenerated"; +import { AgentRowPreview } from "./AgentRowPreview"; const meta: Meta = { title: "components/Resources/Resources", @@ -189,15 +187,7 @@ function getAgentRow(agent: WorkspaceAgent): JSX.Element { }, }} > - + ); } diff --git a/site/src/pages/WorkspacePage/Workspace.stories.tsx b/site/src/pages/WorkspacePage/Workspace.stories.tsx index 47d1fad733552..07a320c56c513 100644 --- a/site/src/pages/WorkspacePage/Workspace.stories.tsx +++ b/site/src/pages/WorkspacePage/Workspace.stories.tsx @@ -28,6 +28,14 @@ const meta: Meta = { title: "pages/WorkspacePage/Workspace", args: { permissions }, component: Workspace, + parameters: { + queries: [ + { + key: ["portForward", Mocks.MockWorkspaceAgent.id], + data: Mocks.MockListeningPortsResponse, + }, + ], + }, decorators: [ (Story) => ( Date: Wed, 17 Jan 2024 15:42:40 +0000 Subject: [PATCH 14/26] More visual fixes --- site/src/components/Resources/AgentRow.tsx | 4 ++++ .../components/Resources/ResourceCard.stories.tsx | 14 ++------------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/site/src/components/Resources/AgentRow.tsx b/site/src/components/Resources/AgentRow.tsx index 8d4969246ee5b..ab80bf4e9e616 100644 --- a/site/src/components/Resources/AgentRow.tsx +++ b/site/src/components/Resources/AgentRow.tsx @@ -607,6 +607,10 @@ const styles = { gap: 16, flexWrap: "wrap", + "&:empty": { + display: "none", + }, + [theme.breakpoints.down("md")]: { marginLeft: 0, justifyContent: "flex-start", diff --git a/site/src/components/Resources/ResourceCard.stories.tsx b/site/src/components/Resources/ResourceCard.stories.tsx index 576ef68db7de2..56c373c2081e8 100644 --- a/site/src/components/Resources/ResourceCard.stories.tsx +++ b/site/src/components/Resources/ResourceCard.stories.tsx @@ -1,14 +1,12 @@ -import { action } from "@storybook/addon-actions"; import { MockProxyLatencies, - MockWorkspace, MockWorkspaceResource, } from "testHelpers/entities"; -import { AgentRow } from "./AgentRow"; import { ResourceCard } from "./ResourceCard"; import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext"; import type { Meta, StoryObj } from "@storybook/react"; import { type WorkspaceAgent } from "api/typesGenerated"; +import { AgentRowPreview } from "./AgentRowPreview"; const meta: Meta = { title: "components/Resources/ResourceCard", @@ -93,15 +91,7 @@ function getAgentRow(agent: WorkspaceAgent): JSX.Element { }, }} > - + ); } From 295f8f734323da3bf88cf1ed845ef493661d9d23 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Wed, 17 Jan 2024 16:09:41 +0000 Subject: [PATCH 15/26] Refactor agent buttons and links --- site/src/components/Resources/AgentButton.tsx | 2 +- .../components/Resources/AppLink/AppLink.tsx | 114 ++++++++---------- .../Resources/TerminalLink/TerminalLink.tsx | 8 +- 3 files changed, 58 insertions(+), 66 deletions(-) diff --git a/site/src/components/Resources/AgentButton.tsx b/site/src/components/Resources/AgentButton.tsx index 7fe5376a316d3..059d00462c41b 100644 --- a/site/src/components/Resources/AgentButton.tsx +++ b/site/src/components/Resources/AgentButton.tsx @@ -8,8 +8,8 @@ export const AgentButton = forwardRef( return (