Skip to content

Commit a3f62d1

Browse files
committed
Move app status to be inside of the agent row
1 parent 644aaf0 commit a3f62d1

File tree

4 files changed

+288
-290
lines changed

4 files changed

+288
-290
lines changed

site/src/modules/resources/AgentRow.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { DropdownArrow } from "components/DropdownArrow/DropdownArrow";
1515
import type { Line } from "components/Logs/LogLine";
1616
import { Stack } from "components/Stack/Stack";
1717
import { useProxy } from "contexts/ProxyContext";
18+
import { AppStatuses } from "pages/WorkspacePage/AppStatuses";
1819
import {
1920
type FC,
2021
useCallback,
@@ -225,6 +226,13 @@ export const AgentRow: FC<AgentRowProps> = ({
225226
</header>
226227

227228
<div css={styles.content}>
229+
{workspace.latest_app_status?.agent_id === agent.id && (
230+
<section>
231+
<h3 className="sr-only">App statuses</h3>
232+
<AppStatuses workspace={workspace} agent={agent} />
233+
</section>
234+
)}
235+
228236
{agent.status === "connected" && (
229237
<section css={styles.apps}>
230238
{shouldDisplayApps && (

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

Lines changed: 150 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import { AppStatuses } from "./AppStatuses";
1212
const meta: Meta<typeof AppStatuses> = {
1313
title: "pages/WorkspacePage/AppStatuses",
1414
component: AppStatuses,
15+
args: {
16+
referenceDate: new Date("2024-03-26T15:15:00Z"),
17+
},
1518
// Add decorator for ProxyContext
1619
decorators: [
1720
(Story) => (
@@ -43,165 +46,163 @@ export default meta;
4346

4447
type Story = StoryObj<typeof AppStatuses>;
4548

46-
// Helper function to create timestamps easily
47-
const createTimestamp = (
48-
minuteOffset: number,
49-
secondOffset: number,
50-
): string => {
51-
const baseDate = new Date("2024-03-26T15:00:00Z");
52-
baseDate.setMinutes(baseDate.getMinutes() + minuteOffset);
53-
baseDate.setSeconds(baseDate.getSeconds() + secondOffset);
54-
return baseDate.toISOString();
55-
};
56-
57-
// Define a fixed reference date for Storybook, slightly after the last status
58-
const storyReferenceDate = new Date("2024-03-26T15:15:00Z"); // 15 minutes after base
59-
6049
export const Default: Story = {
6150
args: {
6251
workspace: MockWorkspace,
63-
agents: [MockWorkspaceAgent],
64-
apps: [
65-
{
66-
...MockWorkspaceApp,
67-
statuses: [
68-
{
69-
// This is the latest status chronologically (15:04:38)
70-
...MockWorkspaceAppStatus,
71-
id: "status-7",
72-
icon: "/emojis/1f4dd.png", // 📝
73-
message: "Creating PR with gh CLI",
74-
created_at: createTimestamp(4, 38), // 15:04:38
75-
uri: "https://github.com/coder/coder/pull/5678",
76-
state: "complete" as const,
77-
},
78-
{
79-
// (15:03:56)
80-
...MockWorkspaceAppStatus,
81-
id: "status-6",
82-
icon: "/emojis/1f680.png", // 🚀
83-
message: "Pushing branch to remote",
84-
created_at: createTimestamp(3, 56), // 15:03:56
85-
uri: "",
86-
state: "complete" as const,
87-
},
88-
{
89-
// (15:02:29)
90-
...MockWorkspaceAppStatus,
91-
id: "status-5",
92-
icon: "/emojis/1f527.png", // 🔧
93-
message: "Configuring git identity",
94-
created_at: createTimestamp(2, 29), // 15:02:29
95-
uri: "",
96-
state: "complete" as const,
97-
},
98-
{
99-
// (15:02:04)
100-
...MockWorkspaceAppStatus,
101-
id: "status-4",
102-
icon: "/emojis/1f4be.png", // 💾
103-
message: "Committing changes",
104-
created_at: createTimestamp(2, 4), // 15:02:04
105-
uri: "",
106-
state: "complete" as const,
107-
},
108-
{
109-
// (15:01:44)
110-
...MockWorkspaceAppStatus,
111-
id: "status-3",
112-
icon: "/emojis/2795.png", // +
113-
message: "Adding files to staging",
114-
created_at: createTimestamp(1, 44), // 15:01:44
115-
uri: "",
116-
state: "complete" as const,
117-
},
118-
{
119-
// (15:01:32)
120-
...MockWorkspaceAppStatus,
121-
id: "status-2",
122-
icon: "/emojis/1f33f.png", // 🌿
123-
message: "Creating a new branch for PR",
124-
created_at: createTimestamp(1, 32), // 15:01:32
125-
uri: "",
126-
state: "complete" as const,
127-
},
128-
{
129-
// (15:01:00) - Oldest
130-
...MockWorkspaceAppStatus,
131-
id: "status-1",
132-
icon: "/emojis/1f680.png", // 🚀
133-
message: "Starting to create a PR",
134-
created_at: createTimestamp(1, 0), // 15:01:00
135-
uri: "",
136-
state: "complete" as const,
137-
},
138-
].sort(
139-
(a, b) =>
140-
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
141-
), // Ensure sorted correctly for component input if needed
142-
},
143-
],
52+
agent: {
53+
...MockWorkspaceAgent,
54+
apps: [
55+
{
56+
...MockWorkspaceApp,
57+
statuses: [
58+
{
59+
// This is the latest status chronologically (15:04:38)
60+
...MockWorkspaceAppStatus,
61+
id: "status-7",
62+
icon: "/emojis/1f4dd.png", // 📝
63+
message: "Creating PR with gh CLI",
64+
created_at: createTimestamp(4, 38), // 15:04:38
65+
uri: "https://github.com/coder/coder/pull/5678",
66+
state: "complete" as const,
67+
},
68+
{
69+
// (15:03:56)
70+
...MockWorkspaceAppStatus,
71+
id: "status-6",
72+
icon: "/emojis/1f680.png", // 🚀
73+
message: "Pushing branch to remote",
74+
created_at: createTimestamp(3, 56), // 15:03:56
75+
uri: "",
76+
state: "complete" as const,
77+
},
78+
{
79+
// (15:02:29)
80+
...MockWorkspaceAppStatus,
81+
id: "status-5",
82+
icon: "/emojis/1f527.png", // 🔧
83+
message: "Configuring git identity",
84+
created_at: createTimestamp(2, 29), // 15:02:29
85+
uri: "",
86+
state: "complete" as const,
87+
},
88+
{
89+
// (15:02:04)
90+
...MockWorkspaceAppStatus,
91+
id: "status-4",
92+
icon: "/emojis/1f4be.png", // 💾
93+
message: "Committing changes",
94+
created_at: createTimestamp(2, 4), // 15:02:04
95+
uri: "",
96+
state: "complete" as const,
97+
},
98+
{
99+
// (15:01:44)
100+
...MockWorkspaceAppStatus,
101+
id: "status-3",
102+
icon: "/emojis/2795.png", // +
103+
message: "Adding files to staging",
104+
created_at: createTimestamp(1, 44), // 15:01:44
105+
uri: "",
106+
state: "complete" as const,
107+
},
108+
{
109+
// (15:01:32)
110+
...MockWorkspaceAppStatus,
111+
id: "status-2",
112+
icon: "/emojis/1f33f.png", // 🌿
113+
message: "Creating a new branch for PR",
114+
created_at: createTimestamp(1, 32), // 15:01:32
115+
uri: "",
116+
state: "complete" as const,
117+
},
118+
{
119+
// (15:01:00) - Oldest
120+
...MockWorkspaceAppStatus,
121+
id: "status-1",
122+
icon: "/emojis/1f680.png", // 🚀
123+
message: "Starting to create a PR",
124+
created_at: createTimestamp(1, 0), // 15:01:00
125+
uri: "",
126+
state: "complete" as const,
127+
},
128+
].sort(
129+
(a, b) =>
130+
new Date(b.created_at).getTime() -
131+
new Date(a.created_at).getTime(),
132+
), // Ensure sorted correctly for component input if needed
133+
},
134+
],
135+
},
136+
144137
// Pass the reference date to the component for Storybook rendering
145-
referenceDate: storyReferenceDate,
146138
},
147139
};
148140

149141
// Add a story with a "Working" status as the latest
150142
export const WorkingState: Story = {
151143
args: {
152144
workspace: MockWorkspace,
153-
agents: [MockWorkspaceAgent],
154-
apps: [
155-
{
156-
...MockWorkspaceApp,
157-
statuses: [
158-
{
159-
// This is now the latest (15:05:15) and is "working"
160-
...MockWorkspaceAppStatus,
161-
id: "status-8",
162-
icon: "", // Let the component handle the spinner icon
163-
message: "Processing final checks...",
164-
created_at: createTimestamp(5, 15), // 15:05:15 (after referenceDate)
165-
uri: "",
166-
state: "working" as const,
167-
},
168-
{
169-
// Previous latest (15:04:38)
170-
...MockWorkspaceAppStatus,
171-
id: "status-7",
172-
icon: "/emojis/1f4dd.png", // 📝
173-
message: "Creating PR with gh CLI",
174-
created_at: createTimestamp(4, 38), // 15:04:38
175-
uri: "https://github.com/coder/coder/pull/5678",
176-
state: "complete" as const,
177-
},
178-
{
179-
// (15:03:56)
180-
...MockWorkspaceAppStatus,
181-
id: "status-6",
182-
icon: "/emojis/1f680.png", // 🚀
183-
message: "Pushing branch to remote",
184-
created_at: createTimestamp(3, 56), // 15:03:56
185-
uri: "",
186-
state: "complete" as const,
187-
},
188-
// ... include other older statuses if desired ...
189-
{
190-
// (15:01:00) - Oldest
191-
...MockWorkspaceAppStatus,
192-
id: "status-1",
193-
icon: "/emojis/1f680.png", // 🚀
194-
message: "Starting to create a PR",
195-
created_at: createTimestamp(1, 0), // 15:01:00
196-
uri: "",
197-
state: "complete" as const,
198-
},
199-
].sort(
200-
(a, b) =>
201-
new Date(b.created_at).getTime() - new Date(a.created_at).getTime(),
202-
),
203-
},
204-
],
205-
referenceDate: storyReferenceDate, // Use the same reference date
145+
agent: {
146+
...MockWorkspaceAgent,
147+
apps: [
148+
{
149+
...MockWorkspaceApp,
150+
statuses: [
151+
{
152+
// This is now the latest (15:05:15) and is "working"
153+
...MockWorkspaceAppStatus,
154+
id: "status-8",
155+
icon: "", // Let the component handle the spinner icon
156+
message: "Processing final checks...",
157+
created_at: createTimestamp(5, 15), // 15:05:15 (after referenceDate)
158+
uri: "",
159+
state: "working" as const,
160+
},
161+
{
162+
// Previous latest (15:04:38)
163+
...MockWorkspaceAppStatus,
164+
id: "status-7",
165+
icon: "/emojis/1f4dd.png", // 📝
166+
message: "Creating PR with gh CLI",
167+
created_at: createTimestamp(4, 38), // 15:04:38
168+
uri: "https://github.com/coder/coder/pull/5678",
169+
state: "complete" as const,
170+
},
171+
{
172+
// (15:03:56)
173+
...MockWorkspaceAppStatus,
174+
id: "status-6",
175+
icon: "/emojis/1f680.png", // 🚀
176+
message: "Pushing branch to remote",
177+
created_at: createTimestamp(3, 56), // 15:03:56
178+
uri: "",
179+
state: "complete" as const,
180+
},
181+
// ... include other older statuses if desired ...
182+
{
183+
// (15:01:00) - Oldest
184+
...MockWorkspaceAppStatus,
185+
id: "status-1",
186+
icon: "/emojis/1f680.png", // 🚀
187+
message: "Starting to create a PR",
188+
created_at: createTimestamp(1, 0), // 15:01:00
189+
uri: "",
190+
state: "complete" as const,
191+
},
192+
].sort(
193+
(a, b) =>
194+
new Date(b.created_at).getTime() -
195+
new Date(a.created_at).getTime(),
196+
),
197+
},
198+
],
199+
},
206200
},
207201
};
202+
203+
function createTimestamp(minuteOffset: number, secondOffset: number) {
204+
const baseDate = new Date("2024-03-26T15:00:00Z");
205+
baseDate.setMinutes(baseDate.getMinutes() + minuteOffset);
206+
baseDate.setSeconds(baseDate.getSeconds() + secondOffset);
207+
return baseDate.toISOString();
208+
}

0 commit comments

Comments
 (0)