Skip to content

Commit 4554895

Browse files
committed
refactor: extract workspace duplication outside CreateWorkspacePage file
1 parent 294156e commit 4554895

File tree

2 files changed

+71
-62
lines changed

2 files changed

+71
-62
lines changed

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ import { checkAuthorization } from "api/queries/authCheck";
2929
import { CreateWSPermissions, createWorkspaceChecks } from "./permissions";
3030
import { paramsUsedToCreateWorkspace } from "utils/workspace";
3131
import { useEffectEvent } from "hooks/hookPolyfills";
32-
import { workspaceBuildParameters } from "api/queries/workspaceBuilds";
3332

3433
export const createWorkspaceModes = ["form", "auto", "duplicate"] as const;
3534
export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
@@ -264,64 +263,3 @@ function getDefaultName(mode: CreateWorkspaceMode, params: URLSearchParams) {
264263

265264
return paramsName ?? "";
266265
}
267-
268-
function getDuplicationUrlParams(
269-
workspaceParams: readonly WorkspaceBuildParameter[],
270-
workspace: Workspace,
271-
): URLSearchParams {
272-
// Record type makes sure that every property key added starts with "param.";
273-
// page is also set up to parse params with this prefix for auto mode
274-
const consolidatedParams: Record<`param.${string}`, string> = {};
275-
276-
for (const p of workspaceParams) {
277-
consolidatedParams[`param.${p.name}`] = p.value;
278-
}
279-
280-
return new URLSearchParams({
281-
...consolidatedParams,
282-
mode: "duplicate" satisfies CreateWorkspaceMode,
283-
name: workspace.name,
284-
version: workspace.template_active_version_id,
285-
});
286-
}
287-
288-
/**
289-
* Takes a workspace, and returns out a function that will navigate the user to
290-
* the 'Create Workspace' page, pre-filling the form with as much information
291-
* about the workspace as possible.
292-
*/
293-
// Meant to be consumed by components outside of this file
294-
export function useWorkspaceDuplication(workspace: Workspace) {
295-
const navigate = useNavigate();
296-
const buildParametersQuery = useQuery(
297-
workspaceBuildParameters(workspace.latest_build.id),
298-
);
299-
300-
// Not using useEffectEvent for this, because useEffect isn't really an
301-
// intended use case for this custom hook
302-
const duplicateWorkspace = useCallback(() => {
303-
const buildParams = buildParametersQuery.data;
304-
if (buildParams === undefined) {
305-
return;
306-
}
307-
308-
const newUrlParams = getDuplicationUrlParams(buildParams, workspace);
309-
310-
// Necessary for giving modals/popups time to flush their state changes and
311-
// close the popup before actually navigating. MUI does provide the
312-
// disablePortal prop, which also side-steps this issue, but you have to
313-
// remember to put it on any component that calls this function. Better to
314-
// code defensively and have some redundancy in case someone forgets
315-
void Promise.resolve().then(() => {
316-
navigate({
317-
pathname: `/templates/${workspace.template_name}/workspace`,
318-
search: newUrlParams.toString(),
319-
});
320-
});
321-
}, [navigate, workspace, buildParametersQuery.data]);
322-
323-
return {
324-
duplicateWorkspace,
325-
duplicationReady: buildParametersQuery.isSuccess,
326-
} as const;
327-
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { useNavigate } from "react-router-dom";
2+
import { useQuery } from "react-query";
3+
import { type CreateWorkspaceMode } from "./CreateWorkspacePage";
4+
import {
5+
type Workspace,
6+
type WorkspaceBuildParameter,
7+
} from "api/typesGenerated";
8+
import { workspaceBuildParameters } from "api/queries/workspaceBuilds";
9+
import { useCallback } from "react";
10+
11+
function getDuplicationUrlParams(
12+
workspaceParams: readonly WorkspaceBuildParameter[],
13+
workspace: Workspace,
14+
): URLSearchParams {
15+
// Record type makes sure that every property key added starts with "param.";
16+
// page is also set up to parse params with this prefix for auto mode
17+
const consolidatedParams: Record<`param.${string}`, string> = {};
18+
19+
for (const p of workspaceParams) {
20+
consolidatedParams[`param.${p.name}`] = p.value;
21+
}
22+
23+
return new URLSearchParams({
24+
...consolidatedParams,
25+
mode: "duplicate" satisfies CreateWorkspaceMode,
26+
name: workspace.name,
27+
version: workspace.template_active_version_id,
28+
});
29+
}
30+
31+
/**
32+
* Takes a workspace, and returns out a function that will navigate the user to
33+
* the 'Create Workspace' page, pre-filling the form with as much information
34+
* about the workspace as possible.
35+
*/
36+
export function useWorkspaceDuplication(workspace?: Workspace) {
37+
const navigate = useNavigate();
38+
const buildParametersQuery = useQuery(
39+
workspace !== undefined
40+
? workspaceBuildParameters(workspace.latest_build.id)
41+
: { enabled: false },
42+
);
43+
44+
// Not using useEffectEvent for this, because useEffect isn't really an
45+
// intended use case for this custom hook
46+
const duplicateWorkspace = useCallback(() => {
47+
const buildParams = buildParametersQuery.data;
48+
if (buildParams === undefined || workspace === undefined) {
49+
return;
50+
}
51+
52+
const newUrlParams = getDuplicationUrlParams(buildParams, workspace);
53+
54+
// Necessary for giving modals/popups time to flush their state changes and
55+
// close the popup before actually navigating. MUI does provide the
56+
// disablePortal prop, which also side-steps this issue, but you have to
57+
// remember to put it on any component that calls this function. Better to
58+
// code defensively and have some redundancy in case someone forgets
59+
void Promise.resolve().then(() => {
60+
navigate({
61+
pathname: `/templates/${workspace.template_name}/workspace`,
62+
search: newUrlParams.toString(),
63+
});
64+
});
65+
}, [navigate, workspace, buildParametersQuery.data]);
66+
67+
return {
68+
duplicateWorkspace,
69+
duplicationReady: buildParametersQuery.isSuccess,
70+
} as const;
71+
}

0 commit comments

Comments
 (0)