Skip to content

Commit e6d1b85

Browse files
committed
Add based structure on queries
1 parent 5e0cb37 commit e6d1b85

File tree

7 files changed

+55
-112
lines changed

7 files changed

+55
-112
lines changed

site/src/api/api.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -775,10 +775,10 @@ export const regenerateUserSSHKey = async (
775775

776776
export const getWorkspaceBuilds = async (
777777
workspaceId: string,
778-
since: Date,
779-
): Promise<TypesGen.WorkspaceBuild[]> => {
780-
const response = await axios.get<TypesGen.WorkspaceBuild[]>(
781-
`/api/v2/workspaces/${workspaceId}/builds?since=${since.toISOString()}`,
778+
req?: TypesGen.WorkspaceBuildsRequest,
779+
) => {
780+
const response = await axios.get<TypesGen.WorkspaceBuildsResponse>(
781+
getURLWithSearchParams(`/api/v2/workspaces/${workspaceId}/builds`, req),
782782
);
783783
return response.data;
784784
};
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
import * as API from "api/api";
2+
import { WorkspaceBuildsRequest } from "api/typesGenerated";
23

34
export const workspaceBuildByNumber = (
45
username: string,
56
workspaceName: string,
67
buildNumber: number,
78
) => {
89
return {
9-
queryKey: [username, workspaceName, "workspaceBuild", buildNumber],
10+
queryKey: ["workspaceBuild", username, workspaceName, buildNumber],
1011
queryFn: () =>
1112
API.getWorkspaceBuildByNumber(username, workspaceName, buildNumber),
1213
};
1314
};
15+
16+
export const workspaceBuilds = (
17+
workspaceId: string,
18+
req?: WorkspaceBuildsRequest,
19+
) => {
20+
return {
21+
queryKey: ["workspaceBuilds", workspaceId, req],
22+
queryFn: () => {
23+
return API.getWorkspaceBuilds(workspaceId, req);
24+
},
25+
};
26+
};

site/src/api/typesGenerated.ts

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/pages/WorkspaceBuildPage/WorkspaceBuildPage.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ export const WorkspaceBuildPage: FC = () => {
2323
keepPreviousData: true,
2424
});
2525
const build = wsBuildQuery.data;
26-
const { data: builds } = useQuery({
26+
const buildsQuery = useQuery({
2727
queryKey: ["builds", username, build?.workspace_id],
2828
queryFn: () => {
29-
return getWorkspaceBuilds(
30-
build?.workspace_id ?? "",
31-
dayjs().add(-30, "day").toDate(),
32-
);
29+
return getWorkspaceBuilds(build?.workspace_id ?? "", {
30+
since: dayjs().add(-30, "day").toISOString(),
31+
});
3332
},
3433
enabled: Boolean(build),
3534
});
@@ -50,7 +49,7 @@ export const WorkspaceBuildPage: FC = () => {
5049
<WorkspaceBuildPageView
5150
logs={logs}
5251
build={build}
53-
builds={builds}
52+
builds={buildsQuery.data?.builds}
5453
activeBuildNumber={buildNumber}
5554
/>
5655
</>

site/src/pages/WorkspacePage/WorkspacePage.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { isAxiosError } from "axios";
1111
import { Margins } from "components/Margins/Margins";
1212
import { workspaceQuota } from "api/queries/workspaceQuota";
1313
import { useQuery } from "@tanstack/react-query";
14+
import { workspaceBuilds } from "api/queries/workspaceBuilds";
1415

1516
export const WorkspacePage: FC = () => {
1617
const params = useParams() as {
@@ -26,10 +27,19 @@ export const WorkspacePage: FC = () => {
2627
workspaceName,
2728
username,
2829
},
30+
actions: {
31+
refreshBuilds: () => {
32+
console.log("REFETCH!");
33+
},
34+
},
2935
});
3036
const { workspace, error } = workspaceState.context;
3137
const quotaQuery = useQuery(workspaceQuota(username));
3238
const pageError = error ?? quotaQuery.error;
39+
const buildsQuery = useQuery({
40+
...workspaceBuilds(workspace?.id ?? ""),
41+
enabled: Boolean(workspace),
42+
});
3343

3444
if (pageError) {
3545
return (
@@ -53,6 +63,8 @@ export const WorkspacePage: FC = () => {
5363
workspaceState={workspaceState}
5464
quota={quotaQuery.data}
5565
workspaceSend={workspaceSend}
66+
builds={buildsQuery.data?.builds}
67+
buildsError={buildsQuery.error}
5668
/>
5769
</RequirePermission>
5870
);

site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ interface WorkspaceReadyPageProps {
3939
workspaceState: StateFrom<typeof workspaceMachine>;
4040
workspaceSend: (event: WorkspaceEvent) => void;
4141
quota?: TypesGen.WorkspaceQuota;
42+
builds: TypesGen.WorkspaceBuild[] | undefined;
43+
buildsError: unknown;
4244
}
4345

4446
export const WorkspaceReadyPage = ({
4547
workspaceState,
4648
workspaceSend,
4749
quota,
50+
builds,
51+
buildsError,
4852
}: WorkspaceReadyPageProps): JSX.Element => {
4953
const [_, bannerSend] = useActor(
5054
workspaceState.children["scheduleBannerMachine"],
@@ -56,8 +60,6 @@ export const WorkspaceReadyPage = ({
5660
template,
5761
templateVersion: currentVersion,
5862
deploymentValues,
59-
builds,
60-
getBuildsError,
6163
buildError,
6264
cancellationError,
6365
sshPrefix,
@@ -175,7 +177,7 @@ export const WorkspaceReadyPage = ({
175177
hideSSHButton={featureVisibility["browser_only"]}
176178
hideVSCodeDesktopButton={featureVisibility["browser_only"]}
177179
workspaceErrors={{
178-
[WorkspaceErrors.GET_BUILDS_ERROR]: getBuildsError,
180+
[WorkspaceErrors.GET_BUILDS_ERROR]: buildsError,
179181
[WorkspaceErrors.BUILD_ERROR]: buildError || restartBuildError,
180182
[WorkspaceErrors.CANCELLATION_ERROR]: cancellationError,
181183
}}

site/src/xServices/workspace/workspaceXService.ts

Lines changed: 8 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,10 @@
11
import { getErrorMessage } from "api/errors";
2-
import dayjs from "dayjs";
32
import { workspaceScheduleBannerMachine } from "xServices/workspaceSchedule/workspaceScheduleBannerXService";
4-
import { assign, createMachine, send } from "xstate";
3+
import { assign, createMachine } from "xstate";
54
import * as API from "api/api";
65
import * as TypesGen from "api/typesGenerated";
76
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
87

9-
const latestBuild = (builds: TypesGen.WorkspaceBuild[]) => {
10-
// Cloning builds to not change the origin object with the sort()
11-
return [...builds].sort((a, b) => {
12-
return new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime();
13-
})[0];
14-
};
15-
16-
const moreBuildsAvailable = (
17-
context: WorkspaceContext,
18-
event: {
19-
type: "REFRESH_TIMELINE";
20-
checkRefresh?: boolean;
21-
data?: TypesGen.ServerSentEvent["data"];
22-
},
23-
) => {
24-
// No need to refresh the timeline if it is not loaded
25-
if (!context.builds) {
26-
return false;
27-
}
28-
29-
if (!event.checkRefresh) {
30-
return true;
31-
}
32-
33-
// After we refresh a workspace, we want to check if the latest
34-
// build was updated before refreshing the timeline so as to not over fetch the builds
35-
const latestBuildInTimeline = latestBuild(context.builds);
36-
return (
37-
event.data.latest_build.updated_at !== latestBuildInTimeline.updated_at
38-
);
39-
};
40-
418
type Permissions = Record<keyof ReturnType<typeof permissionsToCheck>, boolean>;
429

4310
export interface WorkspaceContext {
@@ -87,8 +54,6 @@ export type WorkspaceEvent =
8754
| { type: "CANCEL" }
8855
| {
8956
type: "REFRESH_TIMELINE";
90-
checkRefresh?: boolean;
91-
data?: TypesGen.ServerSentEvent["data"];
9257
}
9358
| { type: "EVENT_SOURCE_ERROR"; error: unknown }
9459
| { type: "INCREASE_DEADLINE"; hours: number }
@@ -201,6 +166,11 @@ export const workspaceMachine = createMachine(
201166
},
202167
ready: {
203168
type: "parallel",
169+
on: {
170+
REFRESH_TIMELINE: {
171+
actions: ["refreshBuilds"],
172+
},
173+
},
204174
states: {
205175
listening: {
206176
initial: "gettingEvents",
@@ -422,36 +392,6 @@ export const workspaceMachine = createMachine(
422392
},
423393
},
424394
},
425-
timeline: {
426-
initial: "gettingBuilds",
427-
states: {
428-
gettingBuilds: {
429-
invoke: {
430-
src: "getBuilds",
431-
onDone: [
432-
{
433-
actions: ["assignBuilds", "clearGetBuildsError"],
434-
target: "loadedBuilds",
435-
},
436-
],
437-
onError: [
438-
{
439-
actions: "assignGetBuildsError",
440-
target: "loadedBuilds",
441-
},
442-
],
443-
},
444-
},
445-
loadedBuilds: {
446-
on: {
447-
REFRESH_TIMELINE: {
448-
target: "#workspaceState.ready.timeline.gettingBuilds",
449-
cond: "moreBuildsAvailable",
450-
},
451-
},
452-
},
453-
},
454-
},
455395
sshConfig: {
456396
initial: "gettingSshConfig",
457397
states: {
@@ -553,16 +493,6 @@ export const workspaceMachine = createMachine(
553493
logWatchWorkspaceWarning: (_, event) => {
554494
console.error("Watch workspace error:", event);
555495
},
556-
// Timeline
557-
assignBuilds: assign({
558-
builds: (_, event) => event.data,
559-
}),
560-
assignGetBuildsError: assign({
561-
getBuildsError: (_, event) => event.data,
562-
}),
563-
clearGetBuildsError: assign({
564-
getBuildsError: (_) => undefined,
565-
}),
566496
// SSH
567497
assignSSHPrefix: assign({
568498
sshPrefix: (_, { data }) => data.hostname_prefix,
@@ -599,7 +529,6 @@ export const workspaceMachine = createMachine(
599529
}),
600530
},
601531
guards: {
602-
moreBuildsAvailable,
603532
isMissingBuildParameterError: (_, { data }) => {
604533
return data instanceof API.MissingBuildParameters;
605534
},
@@ -670,7 +599,7 @@ export const workspaceMachine = createMachine(
670599
throw Error("Cannot stop workspace without workspace id");
671600
}
672601
},
673-
deleteWorkspace: async (context) => {
602+
deleteWorkspace: (context) => async (send) => {
674603
if (context.workspace) {
675604
const deleteWorkspacePromise = await API.deleteWorkspace(
676605
context.workspace.id,
@@ -715,12 +644,7 @@ export const workspaceMachine = createMachine(
715644
// refresh our workspace with each SSE
716645
send({ type: "REFRESH_WORKSPACE", data: JSON.parse(event.data) });
717646
// refresh our timeline
718-
send({
719-
type: "REFRESH_TIMELINE",
720-
checkRefresh: true,
721-
data: JSON.parse(event.data),
722-
});
723-
// refresh
647+
send({ type: "REFRESH_TIMELINE" });
724648
});
725649

726650
// handle any error events returned by our sse
@@ -737,18 +661,6 @@ export const workspaceMachine = createMachine(
737661
context.eventSource?.close();
738662
};
739663
},
740-
getBuilds: async (context) => {
741-
if (context.workspace) {
742-
// For now, we only retrieve the last month of builds to minimize
743-
// page bloat. We should add pagination in the future.
744-
return await API.getWorkspaceBuilds(
745-
context.workspace.id,
746-
dayjs().add(-30, "day").toDate(),
747-
);
748-
} else {
749-
throw Error("Cannot get builds without id");
750-
}
751-
},
752664
scheduleBannerMachine: workspaceScheduleBannerMachine,
753665
getSSHPrefix: async () => {
754666
return API.getDeploymentSSHConfig();

0 commit comments

Comments
 (0)