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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy