From 5944b1c595778ecbc830b197be126a17d353a29f Mon Sep 17 00:00:00 2001 From: Jaayden Halko Date: Thu, 12 Jun 2025 18:37:07 +0100 Subject: [PATCH] chore: remove local storage based optin/optout (#18344) This removes the opt-in and opt-out buttons for dynamic parameters on the create workspace page and the workspace parameters settings page. --------- Co-authored-by: Steven Masley --- coderd/parameters_test.go | 1 + site/e2e/helpers.ts | 2 + .../useDynamicParametersOptOut.ts | 37 ------------------ .../WorkspaceMoreActions.tsx | 16 +++----- .../workspaces/WorkspaceUpdateDialogs.tsx | 31 ++------------- .../CreateWorkspaceExperimentRouter.tsx | 35 ++--------------- .../CreateWorkspacePageView.tsx | 28 ++----------- .../CreateWorkspacePageViewExperimental.tsx | 15 +------ .../ExperimentalFormContext.tsx | 5 --- .../WorkspacePage/WorkspacePage.test.tsx | 2 +- .../WorkspaceParametersExperimentRouter.tsx | 39 ++----------------- .../WorkspaceParametersPage.tsx | 14 +------ .../WorkspaceParametersPageExperimental.tsx | 17 +------- 13 files changed, 28 insertions(+), 214 deletions(-) delete mode 100644 site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts delete mode 100644 site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx diff --git a/coderd/parameters_test.go b/coderd/parameters_test.go index da2c19ba20..640dc3ad22 100644 --- a/coderd/parameters_test.go +++ b/coderd/parameters_test.go @@ -249,6 +249,7 @@ func TestDynamicParametersWithTerraformValues(t *testing.T) { Value: "GO", }, } + request.EnableDynamicParameters = true }) coderdtest.AwaitWorkspaceBuildJobCompleted(t, setup.client, wrk.LatestBuild.ID) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 52e9f5e820..0d6c10df50 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -1011,6 +1011,8 @@ export const updateWorkspace = async ( await page.getByTestId("workspace-update-button").click(); await page.getByTestId("confirm-button").click(); + await page.waitForSelector('[data-testid="dialog"]', { state: "visible" }); + await fillParameters(page, richParameters, buildParameters); await page.getByRole("button", { name: /update parameters/i }).click(); diff --git a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts b/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts deleted file mode 100644 index 22364edb0c..0000000000 --- a/site/src/modules/workspaces/DynamicParameter/useDynamicParametersOptOut.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useQuery } from "react-query"; - -export const optOutKey = (id: string): string => `parameters.${id}.optOut`; - -interface UseDynamicParametersOptOutOptions { - templateId: string | undefined; - templateUsesClassicParameters: boolean | undefined; - enabled: boolean; -} - -export const useDynamicParametersOptOut = ({ - templateId, - templateUsesClassicParameters, - enabled, -}: UseDynamicParametersOptOutOptions) => { - return useQuery({ - enabled: !!templateId && enabled, - queryKey: ["dynamicParametersOptOut", templateId], - queryFn: () => { - if (!templateId) { - // This should not happen if enabled is working correctly, - // but as a type guard and sanity check. - throw new Error("templateId is required"); - } - const localStorageKey = optOutKey(templateId); - const storedOptOutString = localStorage.getItem(localStorageKey); - - // Since the dynamic-parameters experiment was removed, always use classic parameters - const optedOut = true; - - return { - templateId, - optedOut, - }; - }, - }); -}; diff --git a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx index ff20aea807..d2d916f71e 100644 --- a/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx +++ b/site/src/modules/workspaces/WorkspaceMoreActions/WorkspaceMoreActions.tsx @@ -21,7 +21,6 @@ import { SettingsIcon, TrashIcon, } from "lucide-react"; -import { useDynamicParametersOptOut } from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import { type FC, useEffect, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { Link as RouterLink } from "react-router-dom"; @@ -43,13 +42,6 @@ export const WorkspaceMoreActions: FC = ({ }) => { const queryClient = useQueryClient(); - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - // Permissions const { data: permissions } = useQuery(workspacePermissions(workspace)); @@ -59,7 +51,11 @@ export const WorkspaceMoreActions: FC = ({ // Change version const [changeVersionDialogOpen, setChangeVersionDialogOpen] = useState(false); const changeVersionMutation = useMutation( - changeVersion(workspace, queryClient, optOutQuery.data?.optedOut === false), + changeVersion( + workspace, + queryClient, + !workspace.template_use_classic_parameter_flow, + ), ); // Delete @@ -151,7 +147,7 @@ export const WorkspaceMoreActions: FC = ({ onClose={() => setIsDownloadDialogOpen(false)} /> - {optOutQuery.data?.optedOut ? ( + {workspace.template_use_classic_parameter_flow ? ( { updateWorkspaceMutation.mutate({ buildParameters, - isDynamicParametersEnabled: optOutQuery.data?.optedOut === false, + isDynamicParametersEnabled: + !workspace.template_use_classic_parameter_flow, }); setIsConfirmingUpdate(false); }; @@ -160,29 +151,13 @@ const MissingBuildParametersDialog: FC = ({ error, ...dialogProps }) => { - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - const missedParameters = error instanceof MissingBuildParameters ? error.parameters : []; const versionId = error instanceof MissingBuildParameters ? error.versionId : undefined; const isOpen = error instanceof MissingBuildParameters; - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const shouldUseClassicDialog = optOutQuery.data?.optedOut; - - return shouldUseClassicDialog ? ( + return workspace.template_use_classic_parameter_flow ? ( { const { organization: organizationName = "default", template: templateName } = @@ -19,43 +14,21 @@ const CreateWorkspaceExperimentRouter: FC = () => { templateByName(organizationName, templateName), ); - const optOutQuery = useDynamicParametersOptOut({ - templateId: templateQuery.data?.id, - templateUsesClassicParameters: - templateQuery.data?.use_classic_parameter_flow, - enabled: !!templateQuery.data, - }); - if (templateQuery.isError) { return ; } - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { + if (!templateQuery.data) { return ; } - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data?.templateId ?? ""); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(templateQuery.data?.use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - return ( - - {optOutQuery.data.optedOut ? ( + <> + {templateQuery.data?.use_classic_parameter_flow ? ( ) : ( )} - + ); }; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 64ea110709..d365a565af 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -28,14 +28,7 @@ import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; -import { - type FC, - useCallback, - useContext, - useEffect, - useMemo, - useState, -} from "react"; +import { type FC, useCallback, useEffect, useMemo, useState } from "react"; import { getFormHelpers, nameValidator, @@ -51,7 +44,6 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; @@ -106,7 +98,6 @@ export const CreateWorkspacePageView: FC = ({ onSubmit, onCancel, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); const [owner, setOwner] = useState(defaultOwner); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), @@ -220,20 +211,9 @@ export const CreateWorkspacePageView: FC = ({ - {experimentalFormContext && ( - - )} - - + } > diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx index c2b6807a58..4fff4db92e 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageViewExperimental.tsx @@ -26,7 +26,7 @@ import { } from "components/Tooltip/Tooltip"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; -import { ArrowLeft, CircleHelp, Undo2 } from "lucide-react"; +import { ArrowLeft, CircleHelp } from "lucide-react"; import { useSyncFormParameters } from "modules/hooks/useSyncFormParameters"; import { Diagnostics } from "modules/workspaces/DynamicParameter/DynamicParameter"; import { @@ -38,7 +38,6 @@ import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName" import { type FC, useCallback, - useContext, useEffect, useId, useRef, @@ -52,7 +51,6 @@ import type { CreateWorkspaceMode, ExternalAuthPollingState, } from "./CreateWorkspacePage"; -import { ExperimentalFormContext } from "./ExperimentalFormContext"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWorkspacePermissions } from "./permissions"; @@ -112,7 +110,6 @@ export const CreateWorkspacePageViewExperimental: FC< owner, setOwner, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), ); @@ -372,16 +369,6 @@ export const CreateWorkspacePageViewExperimental: FC< )} - {experimentalFormContext && ( - - )}

New workspace

diff --git a/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx b/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx deleted file mode 100644 index f79665a0e4..0000000000 --- a/site/src/pages/CreateWorkspacePage/ExperimentalFormContext.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -export const ExperimentalFormContext = createContext< - { toggleOptedOut: () => void } | undefined ->(undefined); diff --git a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx index fb95d0c883..67a1a460dc 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.test.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.test.tsx @@ -305,7 +305,7 @@ describe("WorkspacePage", () => { // Check if the update was called using the values from the form await waitFor(() => { - expect(API.updateWorkspace).toBeCalledWith( + expect(API.updateWorkspace).toHaveBeenCalledWith( MockOutdatedWorkspace, [ { diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx index 8e47b01056..0a01c9907b 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersExperimentRouter.tsx @@ -1,11 +1,4 @@ -import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Loader } from "components/Loader/Loader"; -import { - optOutKey, - useDynamicParametersOptOut, -} from "modules/workspaces/DynamicParameter/useDynamicParametersOptOut"; import type { FC } from "react"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import WorkspaceParametersPage from "./WorkspaceParametersPage"; import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperimental"; @@ -13,40 +6,14 @@ import WorkspaceParametersPageExperimental from "./WorkspaceParametersPageExperi const WorkspaceParametersExperimentRouter: FC = () => { const workspace = useWorkspaceSettings(); - const optOutQuery = useDynamicParametersOptOut({ - templateId: workspace.template_id, - templateUsesClassicParameters: - workspace.template_use_classic_parameter_flow, - enabled: true, - }); - - if (optOutQuery.isError) { - return ; - } - if (!optOutQuery.data) { - return ; - } - - const toggleOptedOut = () => { - const key = optOutKey(optOutQuery.data.templateId); - const storedValue = localStorage.getItem(key); - - const current = storedValue - ? storedValue === "true" - : Boolean(workspace.template_use_classic_parameter_flow); - - localStorage.setItem(key, (!current).toString()); - optOutQuery.refetch(); - }; - return ( - - {optOutQuery.data.optedOut ? ( + <> + {workspace.template_use_classic_parameter_flow ? ( ) : ( )} - + ); }; diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx index 5672029295..50f2eedaee 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPage.tsx @@ -4,11 +4,10 @@ import { isApiValidationError } from "api/errors"; import { checkAuthorization } from "api/queries/authCheck"; import type { Workspace, WorkspaceBuildParameter } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Button as ShadcnButton } from "components/Button/Button"; import { EmptyState } from "components/EmptyState/EmptyState"; import { Loader } from "components/Loader/Loader"; import { ExternalLinkIcon } from "lucide-react"; -import { type FC, useContext } from "react"; +import type { FC } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery } from "react-query"; import { useNavigate } from "react-router-dom"; @@ -18,7 +17,6 @@ import { type WorkspacePermissions, workspaceChecks, } from "../../../modules/workspaces/permissions"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import { WorkspaceParametersForm, @@ -113,21 +111,11 @@ export const WorkspaceParametersPageView: FC< isSubmitting, onCancel, }) => { - const experimentalFormContext = useContext(ExperimentalFormContext); return (

Workspace parameters

- {experimentalFormContext && ( - - Try out the new workspace parameters ✨ - - )}
diff --git a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx index 5fa3033542..755291ec28 100644 --- a/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx +++ b/site/src/pages/WorkspaceSettingsPage/WorkspaceParametersPage/WorkspaceParametersPageExperimental.tsx @@ -7,7 +7,6 @@ import type { WorkspaceBuildParameter, } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; -import { Button } from "components/Button/Button"; import { EmptyState } from "components/EmptyState/EmptyState"; import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge"; import { Link } from "components/Link/Link"; @@ -19,9 +18,9 @@ import { TooltipTrigger, } from "components/Tooltip/Tooltip"; import { useEffectEvent } from "hooks/hookPolyfills"; -import { CircleHelp, Undo2 } from "lucide-react"; +import { CircleHelp } from "lucide-react"; import type { FC } from "react"; -import { useContext, useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery } from "react-query"; import { useNavigate, useSearchParams } from "react-router-dom"; @@ -32,14 +31,12 @@ import { type WorkspacePermissions, workspaceChecks, } from "../../../modules/workspaces/permissions"; -import { ExperimentalFormContext } from "../../CreateWorkspacePage/ExperimentalFormContext"; import { useWorkspaceSettings } from "../WorkspaceSettingsLayout"; import { WorkspaceParametersPageViewExperimental } from "./WorkspaceParametersPageViewExperimental"; const WorkspaceParametersPageExperimental: FC = () => { const workspace = useWorkspaceSettings(); const navigate = useNavigate(); - const experimentalFormContext = useContext(ExperimentalFormContext); const [searchParams] = useSearchParams(); const templateVersionId = searchParams.get("templateVersionId") ?? undefined; @@ -236,16 +233,6 @@ const WorkspaceParametersPageExperimental: FC = () => { - {experimentalFormContext && ( - - )}