Skip to content

Commit f9045a9

Browse files
committed
feat: add workspace build status to task page
1 parent 4fd0312 commit f9045a9

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

site/src/pages/TaskPage/TaskPage.stories.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Meta, StoryObj } from "@storybook/react";
22
import { expect, spyOn, within } from "@storybook/test";
3+
import { API } from "api/api";
34
import type {
45
Workspace,
56
WorkspaceApp,
@@ -9,6 +10,7 @@ import {
910
MockFailedWorkspace,
1011
MockStartingWorkspace,
1112
MockStoppedWorkspace,
13+
MockTemplate,
1214
MockWorkspace,
1315
MockWorkspaceAgent,
1416
MockWorkspaceApp,
@@ -59,6 +61,16 @@ export const WaitingOnBuild: Story = {
5961
},
6062
};
6163

64+
export const WaitingOnBuildWithTemplate: Story = {
65+
beforeEach: () => {
66+
spyOn(API, "getTemplate").mockResolvedValue(MockTemplate);
67+
spyOn(data, "fetchTask").mockResolvedValue({
68+
prompt: "Create competitors page",
69+
workspace: MockStartingWorkspace,
70+
});
71+
},
72+
};
73+
6274
export const WaitingOnStatus: Story = {
6375
beforeEach: () => {
6476
spyOn(data, "fetchTask").mockResolvedValue({

site/src/pages/TaskPage/TaskPage.tsx

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { API } from "api/api";
22
import { getErrorDetail, getErrorMessage } from "api/errors";
3+
import { template as templateQueryOptions } from "api/queries/templates";
34
import type { Workspace, WorkspaceStatus } from "api/typesGenerated";
45
import { Button } from "components/Button/Button";
56
import { Loader } from "components/Loader/Loader";
67
import { Margins } from "components/Margins/Margins";
78
import { Spinner } from "components/Spinner/Spinner";
9+
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
810
import { ArrowLeftIcon, RotateCcwIcon } from "lucide-react";
911
import { AI_PROMPT_PARAMETER_NAME, type Task } from "modules/tasks/tasks";
1012
import type { ReactNode } from "react";
@@ -14,6 +16,10 @@ import { useParams } from "react-router-dom";
1416
import { Link as RouterLink } from "react-router-dom";
1517
import { ellipsizeText } from "utils/ellipsizeText";
1618
import { pageTitle } from "utils/page";
19+
import {
20+
ActiveTransition,
21+
WorkspaceBuildProgress,
22+
} from "../WorkspacePage/WorkspaceBuildProgress";
1723
import { TaskApps } from "./TaskApps";
1824
import { TaskSidebar } from "./TaskSidebar";
1925

@@ -32,6 +38,19 @@ const TaskPage = () => {
3238
refetchInterval: 5_000,
3339
});
3440

41+
const { data: template } = useQuery({
42+
...templateQueryOptions(task?.workspace.template_id ?? ""),
43+
enabled: Boolean(task),
44+
});
45+
46+
const waitingStatuses: WorkspaceStatus[] = ["starting", "pending"];
47+
const shouldStreamBuildLogs =
48+
task && waitingStatuses.includes(task.workspace.latest_build.status);
49+
const buildLogs = useWorkspaceBuildLogs(
50+
task?.workspace.latest_build.id ?? "",
51+
shouldStreamBuildLogs,
52+
);
53+
3554
if (error) {
3655
return (
3756
<>
@@ -77,7 +96,6 @@ const TaskPage = () => {
7796
}
7897

7998
let content: ReactNode = null;
80-
const waitingStatuses: WorkspaceStatus[] = ["starting", "pending"];
8199
const terminatedStatuses: WorkspaceStatus[] = [
82100
"canceled",
83101
"canceling",
@@ -88,17 +106,29 @@ const TaskPage = () => {
88106
];
89107

90108
if (waitingStatuses.includes(task.workspace.latest_build.status)) {
109+
// If no template yet, use an indeterminate progress bar.
110+
const transition = (template &&
111+
ActiveTransition(template, task.workspace)) || { P50: 0, P95: null };
112+
const lastStage = buildLogs?.[buildLogs.length - 1]?.stage;
91113
content = (
92-
<div className="w-full min-h-80 flex items-center justify-center">
114+
<div className="w-full min-h-80 flex flex-col items-center justify-center gap-2">
93115
<div className="flex flex-col items-center">
94-
<Spinner loading className="mb-4" />
95116
<h3 className="m-0 font-medium text-content-primary text-base">
96117
Starting your workspace
97118
</h3>
98119
<span className="text-content-secondary text-sm">
99120
This should take a few minutes
100121
</span>
101122
</div>
123+
{lastStage && (
124+
<div className="text-content-secondary text-sm">{lastStage}</div>
125+
)}
126+
<div css={{ minWidth: 315 }}>
127+
<WorkspaceBuildProgress
128+
workspace={task.workspace}
129+
transitionStats={transition}
130+
/>
131+
</div>
102132
</div>
103133
);
104134
} else if (task.workspace.latest_build.status === "failed") {

0 commit comments

Comments
 (0)