Skip to content

Commit afcea74

Browse files
fix(site): retry and debug passing build parameters options (#12384)
1 parent af4d0b1 commit afcea74

15 files changed

+400
-77
lines changed

site/src/components/FullPageLayout/Sidebar.tsx

+6-3
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,17 @@ interface SidebarIconButton extends ComponentProps<typeof TopbarIconButton> {
7474
isActive: boolean;
7575
}
7676

77-
export const SidebarIconButton: FC<SidebarIconButton> = (props) => {
77+
export const SidebarIconButton: FC<SidebarIconButton> = ({
78+
isActive,
79+
...buttonProps
80+
}) => {
7881
return (
7982
<TopbarIconButton
8083
css={[
8184
{ opacity: 0.75, "&:hover": { opacity: 1 } },
82-
props.isActive && styles.activeSidebarIconButton,
85+
isActive && styles.activeSidebarIconButton,
8386
]}
84-
{...props}
87+
{...buttonProps}
8588
/>
8689
);
8790
};

site/src/pages/WorkspacePage/Workspace.tsx

+10-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { type Interpolation, type Theme } from "@emotion/react";
2-
import Button from "@mui/material/Button";
32
import AlertTitle from "@mui/material/AlertTitle";
43
import { type FC } from "react";
54
import { useNavigate } from "react-router-dom";
@@ -43,9 +42,9 @@ export interface WorkspaceProps {
4342
buildInfo?: TypesGen.BuildInfoResponse;
4443
sshPrefix?: string;
4544
template: TypesGen.Template;
46-
canRetryDebugMode: boolean;
47-
handleBuildRetry: () => void;
48-
handleBuildRetryDebug: () => void;
45+
canDebugMode: boolean;
46+
handleRetry: (buildParameters?: TypesGen.WorkspaceBuildParameter[]) => void;
47+
handleDebug: (buildParameters?: TypesGen.WorkspaceBuildParameter[]) => void;
4948
buildLogs?: React.ReactNode;
5049
latestVersion?: TypesGen.TemplateVersion;
5150
permissions: WorkspacePermissions;
@@ -75,9 +74,9 @@ export const Workspace: FC<WorkspaceProps> = ({
7574
buildInfo,
7675
sshPrefix,
7776
template,
78-
canRetryDebugMode,
79-
handleBuildRetry,
80-
handleBuildRetryDebug,
77+
canDebugMode,
78+
handleRetry,
79+
handleDebug,
8180
buildLogs,
8281
latestVersion,
8382
permissions,
@@ -129,12 +128,12 @@ export const Workspace: FC<WorkspaceProps> = ({
129128
handleUpdate={handleUpdate}
130129
handleCancel={handleCancel}
131130
handleSettings={handleSettings}
132-
handleBuildRetry={handleBuildRetry}
133-
handleBuildRetryDebug={handleBuildRetryDebug}
131+
handleRetry={handleRetry}
132+
handleDebug={handleDebug}
134133
handleChangeVersion={handleChangeVersion}
135134
handleDormantActivate={handleDormantActivate}
136135
handleToggleFavorite={handleToggleFavorite}
137-
canRetryDebugMode={canRetryDebugMode}
136+
canDebugMode={canDebugMode}
138137
canChangeVersions={canChangeVersions}
139138
isUpdating={isUpdating}
140139
isRestarting={isRestarting}
@@ -208,20 +207,7 @@ export const Workspace: FC<WorkspaceProps> = ({
208207
)}
209208

210209
{workspace.latest_build.job.error && (
211-
<Alert
212-
severity="error"
213-
actions={
214-
<Button
215-
onClick={
216-
canRetryDebugMode ? handleBuildRetryDebug : handleBuildRetry
217-
}
218-
variant="text"
219-
size="small"
220-
>
221-
Retry{canRetryDebugMode && " in debug mode"}
222-
</Button>
223-
}
224-
>
210+
<Alert severity="error">
225211
<AlertTitle>Workspace build failed</AlertTitle>
226212
<AlertDetail>{workspace.latest_build.job.error}</AlertDetail>
227213
</Alert>

site/src/pages/WorkspacePage/WorkspaceActions/BuildParametersPopover.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,19 @@ import {
3232
usePopover,
3333
} from "components/Popover/Popover";
3434
import { TopbarButton } from "components/FullPageLayout/Topbar";
35+
import visuallyHidden from "@mui/utils/visuallyHidden";
3536

3637
interface BuildParametersPopoverProps {
3738
workspace: Workspace;
3839
disabled?: boolean;
3940
onSubmit: (buildParameters: WorkspaceBuildParameter[]) => void;
41+
label: string;
4042
}
4143

4244
export const BuildParametersPopover: FC<BuildParametersPopoverProps> = ({
4345
workspace,
4446
disabled,
47+
label,
4548
onSubmit,
4649
}) => {
4750
const { data: parameters } = useQuery({
@@ -62,6 +65,7 @@ export const BuildParametersPopover: FC<BuildParametersPopoverProps> = ({
6265
css={{ paddingLeft: 0, paddingRight: 0, minWidth: "28px !important" }}
6366
>
6467
<ExpandMoreOutlined css={{ fontSize: 14 }} />
68+
<span css={{ ...visuallyHidden }}>{label}</span>
6569
</TopbarButton>
6670
</PopoverTrigger>
6771
<PopoverContent

site/src/pages/WorkspacePage/WorkspaceActions/Buttons.tsx

+3-21
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,14 @@ import ReplayIcon from "@mui/icons-material/Replay";
77
import BlockIcon from "@mui/icons-material/Block";
88
import OutlinedBlockIcon from "@mui/icons-material/BlockOutlined";
99
import PowerSettingsNewIcon from "@mui/icons-material/PowerSettingsNew";
10-
import RetryIcon from "@mui/icons-material/BuildOutlined";
11-
import RetryDebugIcon from "@mui/icons-material/BugReportOutlined";
1210
import Star from "@mui/icons-material/Star";
1311
import StarBorder from "@mui/icons-material/StarBorder";
1412
import { type FC } from "react";
1513
import type { Workspace, WorkspaceBuildParameter } from "api/typesGenerated";
1614
import { BuildParametersPopover } from "./BuildParametersPopover";
1715
import { TopbarButton } from "components/FullPageLayout/Topbar";
1816

19-
interface ActionButtonProps {
17+
export interface ActionButtonProps {
2018
loading?: boolean;
2119
handleAction: (buildParameters?: WorkspaceBuildParameter[]) => void;
2220
disabled?: boolean;
@@ -84,6 +82,7 @@ export const StartButton: FC<ActionButtonPropsWithWorkspace> = ({
8482
{loading ? <>Starting&hellip;</> : "Start"}
8583
</TopbarButton>
8684
<BuildParametersPopover
85+
label="Start with build parameters"
8786
workspace={workspace}
8887
disabled={loading}
8988
onSubmit={handleAction}
@@ -141,6 +140,7 @@ export const RestartButton: FC<ActionButtonPropsWithWorkspace> = ({
141140
{loading ? <>Restarting&hellip;</> : <>Restart&hellip;</>}
142141
</TopbarButton>
143142
<BuildParametersPopover
143+
label="Restart with build parameters"
144144
workspace={workspace}
145145
disabled={loading}
146146
onSubmit={handleAction}
@@ -175,24 +175,6 @@ export const DisabledButton: FC<DisabledButtonProps> = ({ label }) => {
175175
);
176176
};
177177

178-
type RetryButtonProps = Omit<ActionButtonProps, "loading"> & {
179-
debug?: boolean;
180-
};
181-
182-
export const RetryButton: FC<RetryButtonProps> = ({
183-
handleAction,
184-
debug = false,
185-
}) => {
186-
return (
187-
<TopbarButton
188-
startIcon={debug ? <RetryDebugIcon /> : <RetryIcon />}
189-
onClick={() => handleAction()}
190-
>
191-
Retry{debug && " (Debug)"}
192-
</TopbarButton>
193-
);
194-
};
195-
196178
interface FavoriteButtonProps {
197179
onToggle: (workspaceID: string) => void;
198180
workspaceID: string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Meta, StoryObj } from "@storybook/react";
2+
import { DebugButton } from "./DebugButton";
3+
import { MockWorkspace } from "testHelpers/entities";
4+
import { userEvent, waitFor, within, expect } from "@storybook/test";
5+
6+
const meta: Meta<typeof DebugButton> = {
7+
title: "pages/WorkspacePage/DebugButton",
8+
component: DebugButton,
9+
};
10+
11+
export default meta;
12+
type Story = StoryObj<typeof DebugButton>;
13+
14+
export const Default: Story = {};
15+
16+
export const WithBuildParameters: Story = {
17+
args: {
18+
enableBuildParameters: true,
19+
workspace: MockWorkspace,
20+
},
21+
parameters: {
22+
queries: [
23+
{
24+
key: ["workspace", MockWorkspace.id, "parameters"],
25+
data: { templateVersionRichParameters: [], buildParameters: [] },
26+
},
27+
],
28+
},
29+
};
30+
31+
export const WithOpenBuildParameters: Story = {
32+
args: {
33+
enableBuildParameters: true,
34+
workspace: MockWorkspace,
35+
},
36+
parameters: {
37+
queries: [
38+
{
39+
key: ["workspace", MockWorkspace.id, "parameters"],
40+
data: { templateVersionRichParameters: [], buildParameters: [] },
41+
},
42+
],
43+
},
44+
play: async ({ canvasElement, step }) => {
45+
const screen = within(canvasElement);
46+
47+
await step("open popover", async () => {
48+
await userEvent.click(screen.getByTestId("build-parameters-button"));
49+
await waitFor(() =>
50+
expect(screen.getByText("Build Options")).toBeInTheDocument(),
51+
);
52+
});
53+
},
54+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import ButtonGroup from "@mui/material/ButtonGroup";
2+
import DebugIcon from "@mui/icons-material/BugReportOutlined";
3+
import { type FC } from "react";
4+
import type { Workspace } from "api/typesGenerated";
5+
import { BuildParametersPopover } from "./BuildParametersPopover";
6+
import { TopbarButton } from "components/FullPageLayout/Topbar";
7+
import { ActionButtonProps } from "./Buttons";
8+
9+
type DebugButtonProps = Omit<ActionButtonProps, "loading"> & {
10+
workspace: Workspace;
11+
enableBuildParameters: boolean;
12+
};
13+
14+
export const DebugButton: FC<DebugButtonProps> = ({
15+
handleAction,
16+
workspace,
17+
enableBuildParameters,
18+
}) => {
19+
const mainAction = (
20+
<TopbarButton startIcon={<DebugIcon />} onClick={() => handleAction()}>
21+
Debug
22+
</TopbarButton>
23+
);
24+
25+
if (!enableBuildParameters) {
26+
return mainAction;
27+
}
28+
29+
return (
30+
<ButtonGroup
31+
variant="outlined"
32+
css={{
33+
// Workaround to make the border transitions smoothly on button groups
34+
"& > button:hover + button": {
35+
borderLeft: "1px solid #FFF",
36+
},
37+
}}
38+
>
39+
{mainAction}
40+
<BuildParametersPopover
41+
label="Debug with build parameters"
42+
workspace={workspace}
43+
onSubmit={handleAction}
44+
/>
45+
</ButtonGroup>
46+
);
47+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Meta, StoryObj } from "@storybook/react";
2+
import { RetryButton } from "./RetryButton";
3+
import { MockWorkspace } from "testHelpers/entities";
4+
import { userEvent, waitFor, within, expect } from "@storybook/test";
5+
6+
const meta: Meta<typeof RetryButton> = {
7+
title: "pages/WorkspacePage/RetryButton",
8+
component: RetryButton,
9+
};
10+
11+
export default meta;
12+
type Story = StoryObj<typeof RetryButton>;
13+
14+
export const Default: Story = {};
15+
16+
export const WithBuildParameters: Story = {
17+
args: {
18+
enableBuildParameters: true,
19+
workspace: MockWorkspace,
20+
},
21+
parameters: {
22+
queries: [
23+
{
24+
key: ["workspace", MockWorkspace.id, "parameters"],
25+
data: { templateVersionRichParameters: [], buildParameters: [] },
26+
},
27+
],
28+
},
29+
};
30+
31+
export const WithOpenBuildParameters: Story = {
32+
args: {
33+
enableBuildParameters: true,
34+
workspace: MockWorkspace,
35+
},
36+
parameters: {
37+
queries: [
38+
{
39+
key: ["workspace", MockWorkspace.id, "parameters"],
40+
data: { templateVersionRichParameters: [], buildParameters: [] },
41+
},
42+
],
43+
},
44+
play: async ({ canvasElement, step }) => {
45+
const screen = within(canvasElement);
46+
47+
await step("open popover", async () => {
48+
await userEvent.click(screen.getByTestId("build-parameters-button"));
49+
await waitFor(() =>
50+
expect(screen.getByText("Build Options")).toBeInTheDocument(),
51+
);
52+
});
53+
},
54+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import ButtonGroup from "@mui/material/ButtonGroup";
2+
import RetryIcon from "@mui/icons-material/CachedOutlined";
3+
import { type FC } from "react";
4+
import type { Workspace } from "api/typesGenerated";
5+
import { BuildParametersPopover } from "./BuildParametersPopover";
6+
import { TopbarButton } from "components/FullPageLayout/Topbar";
7+
import { ActionButtonProps } from "./Buttons";
8+
9+
type RetryButtonProps = Omit<ActionButtonProps, "loading"> & {
10+
enableBuildParameters: boolean;
11+
workspace: Workspace;
12+
};
13+
14+
export const RetryButton: FC<RetryButtonProps> = ({
15+
handleAction,
16+
workspace,
17+
enableBuildParameters,
18+
}) => {
19+
const mainAction = (
20+
<TopbarButton startIcon={<RetryIcon />} onClick={() => handleAction()}>
21+
Retry
22+
</TopbarButton>
23+
);
24+
25+
if (!enableBuildParameters) {
26+
return mainAction;
27+
}
28+
29+
return (
30+
<ButtonGroup
31+
variant="outlined"
32+
css={{
33+
// Workaround to make the border transitions smoothly on button groups
34+
"& > button:hover + button": {
35+
borderLeft: "1px solid #FFF",
36+
},
37+
}}
38+
>
39+
{mainAction}
40+
<BuildParametersPopover
41+
label="Retry with build parameters"
42+
workspace={workspace}
43+
onSubmit={handleAction}
44+
/>
45+
</ButtonGroup>
46+
);
47+
};

site/src/pages/WorkspacePage/WorkspaceActions/WorkspaceActions.stories.tsx

+7
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ export const Failed: Story = {
7373
},
7474
};
7575

76+
export const FailedWithDebug: Story = {
77+
args: {
78+
workspace: Mocks.MockFailedWorkspace,
79+
canDebug: true,
80+
},
81+
};
82+
7683
export const Updating: Story = {
7784
args: {
7885
isUpdating: true,

0 commit comments

Comments
 (0)