Skip to content

Commit f6364a2

Browse files
authored
feat: add opt-out option to new parameters form (#17456)
Closes coder/preview#62
1 parent c0ca47d commit f6364a2

File tree

4 files changed

+112
-14
lines changed

4 files changed

+112
-14
lines changed
Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,76 @@
1+
import { templateByName } from "api/queries/templates";
2+
import { ErrorAlert } from "components/Alert/ErrorAlert";
3+
import { Loader } from "components/Loader/Loader";
14
import { useDashboard } from "modules/dashboard/useDashboard";
2-
import type { FC } from "react";
5+
import { type FC, createContext } from "react";
6+
import { useQuery } from "react-query";
7+
import { useParams } from "react-router-dom";
38
import CreateWorkspacePage from "./CreateWorkspacePage";
49
import CreateWorkspacePageExperimental from "./CreateWorkspacePageExperimental";
510

611
const CreateWorkspaceExperimentRouter: FC = () => {
712
const { experiments } = useDashboard();
8-
913
const dynamicParametersEnabled = experiments.includes("dynamic-parameters");
1014

15+
const { organization: organizationName = "default", template: templateName } =
16+
useParams() as { organization?: string; template: string };
17+
const templateQuery = useQuery(
18+
dynamicParametersEnabled
19+
? templateByName(organizationName, templateName)
20+
: { enabled: false },
21+
);
22+
23+
const optOutQuery = useQuery(
24+
templateQuery.data
25+
? {
26+
queryKey: [
27+
organizationName,
28+
"template",
29+
templateQuery.data.id,
30+
"optOut",
31+
],
32+
queryFn: () => ({
33+
templateId: templateQuery.data.id,
34+
optedOut:
35+
localStorage.getItem(optOutKey(templateQuery.data.id)) === "true",
36+
}),
37+
}
38+
: { enabled: false },
39+
);
40+
1141
if (dynamicParametersEnabled) {
12-
return <CreateWorkspacePageExperimental />;
42+
if (optOutQuery.isLoading) {
43+
return <Loader />;
44+
}
45+
if (!optOutQuery.data) {
46+
return <ErrorAlert error={optOutQuery.error} />;
47+
}
48+
49+
const toggleOptedOut = () => {
50+
const key = optOutKey(optOutQuery.data.templateId);
51+
const current = localStorage.getItem(key) === "true";
52+
localStorage.setItem(key, (!current).toString());
53+
optOutQuery.refetch();
54+
};
55+
56+
return (
57+
<ExperimentalFormContext.Provider value={{ toggleOptedOut }}>
58+
{optOutQuery.data.optedOut ? (
59+
<CreateWorkspacePage />
60+
) : (
61+
<CreateWorkspacePageExperimental />
62+
)}
63+
</ExperimentalFormContext.Provider>
64+
);
1365
}
1466

1567
return <CreateWorkspacePage />;
1668
};
1769

1870
export default CreateWorkspaceExperimentRouter;
71+
72+
const optOutKey = (id: string) => `parameters.${id}.optOut`;
73+
74+
export const ExperimentalFormContext = createContext<
75+
{ toggleOptedOut: () => void } | undefined
76+
>(undefined);

site/src/pages/CreateWorkspacePage/CreateWorkspacePageExperimental.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ const CreateWorkspacePageExperimental: FC = () => {
6969
const templateQuery = useQuery(
7070
templateByName(organizationName, templateName),
7171
);
72-
const templateVersionPresetsQuery = useQuery({
73-
...templateVersionPresets(templateQuery.data?.active_version_id ?? ""),
74-
enabled: templateQuery.data !== undefined,
75-
});
72+
const templateVersionPresetsQuery = useQuery(
73+
templateQuery.data
74+
? templateVersionPresets(templateQuery.data.active_version_id)
75+
: { enabled: false },
76+
);
7677
const permissionsQuery = useQuery(
7778
templateQuery.data
7879
? checkAuthorization({

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { Interpolation, Theme } from "@emotion/react";
2-
import FormControlLabel from "@mui/material/FormControlLabel";
32
import FormHelperText from "@mui/material/FormHelperText";
43
import TextField from "@mui/material/TextField";
54
import type * as TypesGen from "api/typesGenerated";
@@ -29,7 +28,14 @@ import { Switch } from "components/Switch/Switch";
2928
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
3029
import { type FormikContextType, useFormik } from "formik";
3130
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
32-
import { type FC, useCallback, useEffect, useMemo, useState } from "react";
31+
import {
32+
type FC,
33+
useCallback,
34+
useContext,
35+
useEffect,
36+
useMemo,
37+
useState,
38+
} from "react";
3339
import {
3440
getFormHelpers,
3541
nameValidator,
@@ -41,12 +47,14 @@ import {
4147
useValidationSchemaForRichParameters,
4248
} from "utils/richParameters";
4349
import * as Yup from "yup";
50+
import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter";
4451
import type {
4552
CreateWorkspaceMode,
4653
ExternalAuthPollingState,
4754
} from "./CreateWorkspacePage";
4855
import { ExternalAuthButton } from "./ExternalAuthButton";
4956
import type { CreateWorkspacePermissions } from "./permissions";
57+
5058
export const Language = {
5159
duplicationWarning:
5260
"Duplicating a workspace only copies its parameters. No state from the old workspace is copied over.",
@@ -98,6 +106,7 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
98106
onSubmit,
99107
onCancel,
100108
}) => {
109+
const experimentalFormContext = useContext(ExperimentalFormContext);
101110
const [owner, setOwner] = useState(defaultOwner);
102111
const [suggestedName, setSuggestedName] = useState(() =>
103112
generateWorkspaceName(),
@@ -211,9 +220,20 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
211220
<Margins size="medium">
212221
<PageHeader
213222
actions={
214-
<Button size="sm" variant="outline" onClick={onCancel}>
215-
Cancel
216-
</Button>
223+
<>
224+
{experimentalFormContext && (
225+
<Button
226+
size="sm"
227+
variant="outline"
228+
onClick={experimentalFormContext.toggleOptedOut}
229+
>
230+
Try out the new workspace creation flow ✨
231+
</Button>
232+
)}
233+
<Button size="sm" variant="outline" onClick={onCancel}>
234+
Cancel
235+
</Button>
236+
</>
217237
}
218238
>
219239
<Stack direction="row">

site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,18 @@ import {
2222
useValidationSchemaForDynamicParameters,
2323
} from "modules/workspaces/DynamicParameter/DynamicParameter";
2424
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
25-
import { type FC, useCallback, useEffect, useId, useState } from "react";
25+
import {
26+
type FC,
27+
useCallback,
28+
useContext,
29+
useEffect,
30+
useId,
31+
useState,
32+
} from "react";
2633
import { getFormHelpers, nameValidator } from "utils/formUtils";
2734
import type { AutofillBuildParameter } from "utils/richParameters";
2835
import * as Yup from "yup";
36+
import { ExperimentalFormContext } from "./CreateWorkspaceExperimentRouter";
2937
import type {
3038
CreateWorkspaceMode,
3139
ExternalAuthPollingState,
@@ -89,6 +97,7 @@ export const CreateWorkspacePageViewExperimental: FC<
8997
owner,
9098
setOwner,
9199
}) => {
100+
const experimentalFormContext = useContext(ExperimentalFormContext);
92101
const [suggestedName, setSuggestedName] = useState(() =>
93102
generateWorkspaceName(),
94103
);
@@ -251,7 +260,7 @@ export const CreateWorkspacePageViewExperimental: FC<
251260
</button>
252261
</div>
253262
<div className="flex flex-col gap-6 max-w-screen-sm mx-auto">
254-
<header className="flex flex-col gap-2 mt-10">
263+
<header className="flex flex-col items-start gap-2 mt-10">
255264
<div className="flex items-center gap-2">
256265
<Avatar
257266
variant="icon"
@@ -268,6 +277,16 @@ export const CreateWorkspacePageViewExperimental: FC<
268277
<h1 className="text-3xl font-semibold m-0">New workspace</h1>
269278

270279
{template.deprecated && <Pill type="warning">Deprecated</Pill>}
280+
281+
{experimentalFormContext && (
282+
<Button
283+
size="sm"
284+
variant="subtle"
285+
onClick={experimentalFormContext.toggleOptedOut}
286+
>
287+
Go back to the classic workspace creation flow
288+
</Button>
289+
)}
271290
</header>
272291

273292
<form

0 commit comments

Comments
 (0)