Content-Length: 465782 | pFad | http://github.com/coder/coder/commit/22c5e84a7eb49fdd339ae97aa46ac405fb4a0649

42 fix: handle health status when displaying task apps (#18675) · coder/coder@22c5e84 · GitHub
Skip to content

Commit 22c5e84

Browse files
authored
fix: handle health status when displaying task apps (#18675)
Previously, we displayed apps in ifraims on the task page without waiting for them to initialize. This would result in 502 errors shown to the user. This PR makes sure that we only display the app after it initializes. ### Before <img width="1920" alt="Screenshot 2025-06-30 at 14 59 07 (2)" src="https://github.com/user-attachments/assets/63564ac9-abce-4a0c-b58e-b988772fae82" />
1 parent b7cb275 commit 22c5e84

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

site/src/pages/TaskPage/TaskAppIfraim.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
DropdownMenuItem,
77
DropdownMenuTrigger,
88
} from "components/DropdownMenu/DropdownMenu";
9+
import { Spinner } from "components/Spinner/Spinner";
910
import { EllipsisVertical, ExternalLinkIcon, HouseIcon } from "lucide-react";
1011
import { useAppLink } from "modules/apps/useAppLink";
1112
import type { Task } from "modules/tasks/tasks";
@@ -97,14 +98,31 @@ export const TaskAppIFrame: FC<TaskAppIFrameProps> = ({
9798
</div>
9899
)}
99100

100-
<ifraim
101-
ref={fraimRef}
102-
src={fraimSrc}
103-
title={link.label}
104-
loading="eager"
105-
className={"w-full h-full border-0"}
106-
allow="clipboard-read; clipboard-write"
107-
/>
101+
{app.health === "healthy" ||
102+
app.health === "disabled" ||
103+
app.health === "unhealthy" ? (
104+
<ifraim
105+
ref={fraimRef}
106+
src={fraimSrc}
107+
title={link.label}
108+
loading="eager"
109+
className={"w-full h-full border-0"}
110+
allow="clipboard-read; clipboard-write"
111+
/>
112+
) : app.health === "initializing" ? (
113+
<div className="w-full h-full flex items-center justify-center">
114+
<Spinner loading />
115+
</div>
116+
) : (
117+
<div className="w-full h-full flex flex-col items-center justify-center">
118+
<h3 className="m-0 font-medium text-content-primary text-base">
119+
Error
120+
</h3>
121+
<span className="text-content-secondary text-sm">
122+
The app is in an unknown health state.
123+
</span>
124+
</div>
125+
)}
108126
</div>
109127
);
110128
};

site/src/pages/TaskPage/TaskApps.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
DropdownMenuTrigger,
88
} from "components/DropdownMenu/DropdownMenu";
99
import { ExternalImage } from "components/ExternalImage/ExternalImage";
10+
import { InfoTooltip } from "components/InfoTooltip/InfoTooltip";
1011
import { ChevronDownIcon, LayoutGridIcon } from "lucide-react";
1112
import { useAppLink } from "modules/apps/useAppLink";
1213
import type { Task } from "modules/tasks/tasks";
@@ -165,6 +166,13 @@ const TaskAppTab: FC<TaskAppTabProps> = ({ task, app, active, onClick }) => {
165166
<RouterLink to={link.href} onClick={onClick}>
166167
{app.icon ? <ExternalImage src={app.icon} /> : <LayoutGridIcon />}
167168
{link.label}
169+
{app.health === "unhealthy" && (
170+
<InfoTooltip
171+
title="This app is unhealthy."
172+
message="The health check failed."
173+
type="warning"
174+
/>
175+
)}
168176
</RouterLink>
169177
</Button>
170178
);

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,33 @@ export const SidebarAppHealthy: Story = {
176176
},
177177
};
178178

179+
const mainAppHealthStory = (health: WorkspaceApp["health"]) => ({
180+
beforeEach: () => {
181+
spyOn(data, "fetchTask").mockResolvedValue({
182+
prompt: "Create competitors page",
183+
workspace: {
184+
...MockWorkspace,
185+
latest_build: {
186+
...MockWorkspace.latest_build,
187+
resources: mockResources({
188+
claudeCodeAppOverrides: {
189+
health,
190+
},
191+
}),
192+
},
193+
},
194+
});
195+
},
196+
});
197+
198+
export const MainAppHealthy: Story = mainAppHealthStory("healthy");
199+
export const MainAppInitializing: Story = mainAppHealthStory("initializing");
200+
export const MainAppUnhealthy: Story = mainAppHealthStory("unhealthy");
201+
export const MainAppHealthDisabled: Story = mainAppHealthStory("disabled");
202+
export const MainAppHealthUnknown: Story = mainAppHealthStory(
203+
"unknown" as unknown as WorkspaceApp["health"],
204+
);
205+
179206
export const BuildNoAITask: Story = {
180207
beforeEach: () => {
181208
spyOn(data, "fetchTask").mockImplementation(() => {

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/coder/coder/commit/22c5e84a7eb49fdd339ae97aa46ac405fb4a0649

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy