diff --git a/site/src/components/WarningAlert/WarningAlert.stories.tsx b/site/src/components/WarningAlert/WarningAlert.stories.tsx index 57ffdebb65..774f995010 100644 --- a/site/src/components/WarningAlert/WarningAlert.stories.tsx +++ b/site/src/components/WarningAlert/WarningAlert.stories.tsx @@ -1,18 +1,21 @@ -import { Story } from "@storybook/react" -import { WarningAlert, WarningAlertProps } from "./WarningAlert" +import { Meta, StoryObj } from "@storybook/react" +import { WarningAlert } from "./WarningAlert" import Button from "@mui/material/Button" -export default { +const meta: Meta = { title: "components/WarningAlert", component: WarningAlert, } -const Template: Story = (args) => +export default meta -export const ExampleWithDismiss = Template.bind({}) -ExampleWithDismiss.args = { - text: "This is a warning", - dismissible: true, +type Story = StoryObj + +export const ExampleWithDismiss: Story = { + args: { + text: "This is a warning", + dismissible: true, + }, } const ExampleAction = ( @@ -21,15 +24,17 @@ const ExampleAction = ( ) -export const ExampleWithAction = Template.bind({}) -ExampleWithAction.args = { - text: "This is a warning", - actions: [ExampleAction], +export const ExampleWithAction = { + args: { + text: "This is a warning", + actions: [ExampleAction], + }, } -export const ExampleWithActionAndDismiss = Template.bind({}) -ExampleWithActionAndDismiss.args = { - text: "This is a warning", - actions: [ExampleAction], - dismissible: true, +export const ExampleWithActionAndDismiss = { + args: { + text: "This is a warning", + actions: [ExampleAction], + dismissible: true, + }, } diff --git a/site/src/pages/TerminalPage/TerminalPage.tsx b/site/src/pages/TerminalPage/TerminalPage.tsx index d49709aa3c..ccf035d55e 100644 --- a/site/src/pages/TerminalPage/TerminalPage.tsx +++ b/site/src/pages/TerminalPage/TerminalPage.tsx @@ -1,7 +1,4 @@ -import Button from "@mui/material/Button" import { makeStyles, useTheme } from "@mui/styles" -import WarningIcon from "@mui/icons-material/ErrorOutlineRounded" -import RefreshOutlined from "@mui/icons-material/RefreshOutlined" import { useMachine } from "@xstate/react" import { portForwardURL } from "components/PortForwardButton/PortForwardButton" import { Stack } from "components/Stack/Stack" @@ -18,13 +15,13 @@ import { MONOSPACE_FONT_FAMILY } from "../../theme/constants" import { pageTitle } from "../../utils/page" import { terminalMachine } from "../../xServices/terminal/terminalXService" import { useProxy } from "contexts/ProxyContext" -import { combineClasses } from "utils/combineClasses" import Box from "@mui/material/Box" import { useDashboard } from "components/Dashboard/DashboardProvider" import { Region } from "api/typesGenerated" import { getLatencyColor } from "utils/latency" import Popover from "@mui/material/Popover" import { ProxyStatusLatency } from "components/ProxyStatusLatency/ProxyStatusLatency" +import TerminalPageAlert, { TerminalPageAlertType } from "./TerminalPageAlert" export const Language = { workspaceErrorMessagePrefix: "Unable to fetch workspace: ", @@ -80,12 +77,26 @@ const TerminalPage: FC = () => { websocketError, } = terminalState.context const reloading = useReloading(isDisconnected) - const shouldDisplayStartupWarning = workspaceAgent - ? ["starting", "starting_timeout"].includes(workspaceAgent.lifecycle_state) - : false - const shouldDisplayStartupError = workspaceAgent - ? workspaceAgent.lifecycle_state === "start_error" - : false + const lifecycleState = workspaceAgent?.lifecycle_state + const [startupWarning, setStartupWarning] = useState< + TerminalPageAlertType | undefined + >(undefined) + + useEffect(() => { + if (lifecycleState === "start_error") { + setStartupWarning("error") + } else if (lifecycleState === "starting") { + setStartupWarning("starting") + } else { + setStartupWarning((prev) => { + if (prev === "starting") { + return "success" + } + return undefined + }) + } + }, [lifecycleState]) + const dashboard = useDashboard() const proxyContext = useProxy() const selectedProxy = proxyContext.proxy.proxy @@ -305,49 +316,8 @@ const TerminalPage: FC = () => { )} - {shouldDisplayStartupError && ( -
- -
-
Startup script failed
-
- You can continue using this terminal, but something may be missing - or not fully set up. -
-
-
- )} - {shouldDisplayStartupWarning && ( -
- -
-
- Startup script is still running -
-
- You can continue using this terminal, but something may be - missing or not fully set up. -
-
-
- -
-
- )} + {startupWarning && }
= { + component: TerminalPageAlert, + title: "components/TerminalPageAlert", + argTypes: { + alertType: { + control: { + type: "radio", + }, + options: ["error", "starting", "success"], + }, + }, +} +type Story = StoryObj + +export const Error: Story = { + args: { + alertType: "error", + }, +} + +export const Starting: Story = { + args: { + alertType: "starting", + }, +} + +export const Success: Story = { + args: { + alertType: "success", + }, +} + +export default meta diff --git a/site/src/pages/TerminalPage/TerminalPageAlert.tsx b/site/src/pages/TerminalPage/TerminalPageAlert.tsx new file mode 100644 index 0000000000..3816ff60a9 --- /dev/null +++ b/site/src/pages/TerminalPage/TerminalPageAlert.tsx @@ -0,0 +1,113 @@ +import { AlertColor } from "@mui/material/Alert/Alert" +import Button from "@mui/material/Button" +import Link from "@mui/material/Link" +import { Alert } from "components/Alert/Alert" +import { ReactNode } from "react" + +export type TerminalPageAlertType = "error" | "starting" | "success" + +type MapAlertTypeToComponent = { + [key in TerminalPageAlertType]: { + severity: AlertColor + children: ReactNode | undefined + } +} + +const mapAlertTypeToText: MapAlertTypeToComponent = { + error: { + severity: "warning", + children: ( + <> + The workspace{" "} + + startup script has exited with an error + + , we recommend reloading this session and{" "} + + debugging the startup script + {" "} + because{" "} + + your workspace may be incomplete. + {" "} + + ), + }, + starting: { + severity: "info", + children: ( + <> + Startup script is still running. You can continue using this terminal, + but{" "} + + {" "} + your workspace may be incomplete. + + + ), + }, + success: { + severity: "success", + children: ( + <> + Startup script has completed successfully. The workspace is ready but + this{" "} + + session was started before the startup script finished. + {" "} + To ensure your shell environment is up-to-date, we recommend reloading + this session. + + ), + }, +} + +export default ({ alertType }: { alertType: TerminalPageAlertType }) => { + return ( + { + // By redirecting the user without the session in the URL we + // create a new one + window.location.href = window.location.pathname + }} + > + Refresh session + , + ]} + > + {mapAlertTypeToText[alertType].children} + + ) +}