From 1499bb5cc15dea3dc94ea0d213b5422c47da62e0 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Mon, 11 Sep 2023 17:39:53 +0000 Subject: [PATCH 1/5] chore(site): refactor workspace quota to use react-query instead of XState --- site/src/api/api.ts | 4 +- site/src/api/queries/workspaceQuota.ts | 14 +++++ .../src/pages/WorkspacePage/WorkspacePage.tsx | 11 ++-- .../WorkspacePage/WorkspaceReadyPage.tsx | 7 +-- site/src/xServices/quotas/quotasXService.ts | 63 ------------------- 5 files changed, 24 insertions(+), 75 deletions(-) create mode 100644 site/src/api/queries/workspaceQuota.ts delete mode 100644 site/src/xServices/quotas/quotasXService.ts diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 8bc258e072d1c..10d4931a8dbb7 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -963,9 +963,9 @@ export const deleteGroup = async (groupId: string): Promise => { }; export const getWorkspaceQuota = async ( - userID: string, + username: string, ): Promise => { - const response = await axios.get(`/api/v2/workspace-quota/${userID}`); + const response = await axios.get(`/api/v2/workspace-quota/${username}`); return response.data; }; diff --git a/site/src/api/queries/workspaceQuota.ts b/site/src/api/queries/workspaceQuota.ts new file mode 100644 index 0000000000000..5bafdd3b96e95 --- /dev/null +++ b/site/src/api/queries/workspaceQuota.ts @@ -0,0 +1,14 @@ +import { useQuery } from "@tanstack/react-query"; +import * as API from "api/api"; + +const getWorkspaceQuotaQueryKey = (username: string) => [ + username, + "workspaceQuota", +]; + +export const useWorkspaceQuota = (username: string) => { + return useQuery({ + queryKey: getWorkspaceQuotaQueryKey(username), + queryFn: () => API.getWorkspaceQuota(username), + }); +}; diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index c3accb8de1882..b00bcbf5affca 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -3,7 +3,6 @@ import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"; import { Loader } from "components/Loader/Loader"; import { FC } from "react"; import { useParams } from "react-router-dom"; -import { quotaMachine } from "xServices/quotas/quotasXService"; import { workspaceMachine } from "xServices/workspace/workspaceXService"; import { WorkspaceReadyPage } from "./WorkspaceReadyPage"; import { RequirePermission } from "components/RequirePermission/RequirePermission"; @@ -11,6 +10,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { useOrganizationId } from "hooks"; import { isAxiosError } from "axios"; import { Margins } from "components/Margins/Margins"; +import { useWorkspaceQuota } from "api/queries/workspaceQuota"; export const WorkspacePage: FC = () => { const params = useParams() as { @@ -28,9 +28,8 @@ export const WorkspacePage: FC = () => { }, }); const { workspace, error } = workspaceState.context; - const [quotaState] = useMachine(quotaMachine, { context: { username } }); - const { getQuotaError } = quotaState.context; - const pageError = error ?? getQuotaError; + const quotaQuery = useWorkspaceQuota(username); + const pageError = error ?? quotaQuery.error; return ( { condition={ Boolean(workspace) && workspaceState.matches("ready") && - quotaState.matches("success") + quotaQuery.isSuccess } > diff --git a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx index 7579e11b176be..20452996f27e8 100644 --- a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx @@ -12,7 +12,6 @@ import { getMaxDeadlineChange, getMinDeadline, } from "utils/schedule"; -import { quotaMachine } from "xServices/quotas/quotasXService"; import { StateFrom } from "xstate"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { Workspace, WorkspaceErrors } from "./Workspace"; @@ -39,14 +38,14 @@ import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection"; interface WorkspaceReadyPageProps { workspaceState: StateFrom; - quotaState: StateFrom; workspaceSend: (event: WorkspaceEvent) => void; + quota?: TypesGen.WorkspaceQuota; } export const WorkspaceReadyPage = ({ workspaceState, - quotaState, workspaceSend, + quota, }: WorkspaceReadyPageProps): JSX.Element => { const [_, bannerSend] = useActor( workspaceState.children["scheduleBannerMachine"], @@ -188,7 +187,7 @@ export const WorkspaceReadyPage = ({ buildInfo={buildInfo} sshPrefix={sshPrefix} template={template} - quota_budget={quotaState.context.quota?.budget} + quota_budget={quota?.budget} templateWarnings={templateVersion?.warnings} buildLogs={ shouldDisplayBuildLogs && ( diff --git a/site/src/xServices/quotas/quotasXService.ts b/site/src/xServices/quotas/quotasXService.ts deleted file mode 100644 index 811cbea04f718..0000000000000 --- a/site/src/xServices/quotas/quotasXService.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { assign, createMachine } from "xstate"; -import * as API from "../../api/api"; -import { WorkspaceQuota } from "../../api/typesGenerated"; - -export type QuotaContext = { - username: string; - quota?: WorkspaceQuota; - getQuotaError?: unknown; -}; - -export const quotaMachine = createMachine( - { - id: "quotasMachine", - predictableActionArguments: true, - tsTypes: {} as import("./quotasXService.typegen").Typegen0, - schema: { - context: {} as QuotaContext, - services: { - getQuota: { - data: {} as WorkspaceQuota, - }, - }, - }, - initial: "gettingQuotas", - states: { - idle: {}, - gettingQuotas: { - entry: "clearGetQuotaError", - invoke: { - id: "getQuota", - src: "getQuota", - onDone: { - target: "success", - actions: ["assignQuota"], - }, - onError: { - target: "idle", - actions: ["assignGetQuotaError"], - }, - }, - }, - success: { - type: "final", - }, - }, - }, - { - actions: { - assignQuota: assign({ - quota: (_, event) => event.data, - }), - assignGetQuotaError: assign({ - getQuotaError: (_, event) => event.data, - }), - clearGetQuotaError: assign({ - getQuotaError: (_) => undefined, - }), - }, - services: { - getQuota: ({ username }) => API.getWorkspaceQuota(username), - }, - }, -); From faf6c3576b3fa35a58b8b27ed5e9b55c2c740f99 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Tue, 12 Sep 2023 13:48:44 -0300 Subject: [PATCH 2/5] Update site/src/api/api.ts Co-authored-by: Kayla Washburn --- site/src/api/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 10d4931a8dbb7..b30d02148eeda 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -965,7 +965,7 @@ export const deleteGroup = async (groupId: string): Promise => { export const getWorkspaceQuota = async ( username: string, ): Promise => { - const response = await axios.get(`/api/v2/workspace-quota/${username}`); + const response = await axios.get(`/api/v2/workspace-quota/${encodeURIComponent(username)}`); return response.data; }; From 83b834fea24bbe679571f11ae0037cf4a0872afe Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Sep 2023 17:41:38 +0000 Subject: [PATCH 3/5] Rename quota_budget to quotaBudget --- site/src/pages/WorkspacePage/Workspace.tsx | 6 +++--- site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx | 2 +- site/src/pages/WorkspacePage/WorkspaceStats.tsx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/site/src/pages/WorkspacePage/Workspace.tsx b/site/src/pages/WorkspacePage/Workspace.tsx index f691212eae140..8bea64cd0fff3 100644 --- a/site/src/pages/WorkspacePage/Workspace.tsx +++ b/site/src/pages/WorkspacePage/Workspace.tsx @@ -68,7 +68,7 @@ export interface WorkspaceProps { buildInfo?: TypesGen.BuildInfoResponse; sshPrefix?: string; template?: TypesGen.Template; - quota_budget?: number; + quotaBudget?: number; handleBuildRetry: () => void; buildLogs?: React.ReactNode; } @@ -101,7 +101,7 @@ export const Workspace: FC> = ({ buildInfo, sshPrefix, template, - quota_budget, + quotaBudget, handleBuildRetry, templateWarnings, buildLogs, @@ -183,7 +183,7 @@ export const Workspace: FC> = ({ void; onDeadlineMinus: (hours: number) => void; handleUpdate: () => void; @@ -47,7 +47,7 @@ export interface WorkspaceStatsProps { export const WorkspaceStats: FC = ({ workspace, - quota_budget, + quotaBudget, maxDeadlineDecrease, maxDeadlineIncrease, canUpdateWorkspace, @@ -169,7 +169,7 @@ export const WorkspaceStats: FC = ({ className={styles.statsItem} label={Language.costLabel} value={`${workspace.latest_build.daily_cost} ${ - quota_budget ? `/ ${quota_budget}` : "" + quotaBudget ? `/ ${quotaBudget}` : "" }`} /> )} From a73597e1f921ef5ae03fa7e3545fe5e3b5f9cb55 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Sep 2023 17:42:46 +0000 Subject: [PATCH 4/5] Refactor to use factory style --- site/src/api/queries/workspaceQuota.ts | 7 +++---- site/src/pages/WorkspacePage/WorkspacePage.tsx | 5 +++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/site/src/api/queries/workspaceQuota.ts b/site/src/api/queries/workspaceQuota.ts index 5bafdd3b96e95..72aaf5c716af3 100644 --- a/site/src/api/queries/workspaceQuota.ts +++ b/site/src/api/queries/workspaceQuota.ts @@ -1,4 +1,3 @@ -import { useQuery } from "@tanstack/react-query"; import * as API from "api/api"; const getWorkspaceQuotaQueryKey = (username: string) => [ @@ -6,9 +5,9 @@ const getWorkspaceQuotaQueryKey = (username: string) => [ "workspaceQuota", ]; -export const useWorkspaceQuota = (username: string) => { - return useQuery({ +export const workspaceQuota = (username: string) => { + return { queryKey: getWorkspaceQuotaQueryKey(username), queryFn: () => API.getWorkspaceQuota(username), - }); + }; }; diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index b00bcbf5affca..7cc6247dbef98 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -10,7 +10,8 @@ import { ErrorAlert } from "components/Alert/ErrorAlert"; import { useOrganizationId } from "hooks"; import { isAxiosError } from "axios"; import { Margins } from "components/Margins/Margins"; -import { useWorkspaceQuota } from "api/queries/workspaceQuota"; +import { workspaceQuota } from "api/queries/workspaceQuota"; +import { useQuery } from "@tanstack/react-query"; export const WorkspacePage: FC = () => { const params = useParams() as { @@ -28,7 +29,7 @@ export const WorkspacePage: FC = () => { }, }); const { workspace, error } = workspaceState.context; - const quotaQuery = useWorkspaceQuota(username); + const quotaQuery = useQuery(workspaceQuota(username)); const pageError = error ?? quotaQuery.error; return ( From 48286eef093cdc67d31e6df9456f39536f665c76 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Tue, 12 Sep 2023 17:47:36 +0000 Subject: [PATCH 5/5] Fix fmt --- site/src/api/api.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 12dc9d2a0a68f..b0fd104d6fda0 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -963,7 +963,9 @@ export const deleteGroup = async (groupId: string): Promise => { export const getWorkspaceQuota = async ( username: string, ): Promise => { - const response = await axios.get(`/api/v2/workspace-quota/${encodeURIComponent(username)}`); + const response = await axios.get( + `/api/v2/workspace-quota/${encodeURIComponent(username)}`, + ); return response.data; };