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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy