From c4f47b6b8ed08eb9f758aec0c6e90be41f00c012 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 09:15:58 +0000 Subject: [PATCH 1/9] add a switch to toggle whether or not to show preset parameters --- .../CreateWorkspacePageView.stories.tsx | 23 +++++++++ .../CreateWorkspacePageView.tsx | 49 +++++++++++++------ 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index a972cefd2bafe..b6a548e3410ff 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -159,6 +159,29 @@ export const PresetSelected: Story = { }, }; +export const PresetSelectedWithHiddenParameters: Story = { + args: PresetsButNoneSelected.args, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Select a preset + await userEvent.click(canvas.getByLabelText("Preset")); + await userEvent.click(canvas.getByText("Preset 1")); + // Toggle off the show preset parameters switch + await userEvent.click(canvas.getByLabelText("Show preset parameters")); + }, +}; + +export const PresetSelectedWithVisibleParameters: Story = { + args: PresetsButNoneSelected.args, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + // Select a preset + await userEvent.click(canvas.getByLabelText("Preset")); + await userEvent.click(canvas.getByText("Preset 1")); + // Ensure the show preset parameters switch is on (it's on by default) + }, +}; + export const PresetReselected: Story = { args: PresetsButNoneSelected.args, play: async ({ canvasElement }) => { diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 34917fe14b058..9ea900819631f 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -1,6 +1,7 @@ import type { Interpolation, Theme } from "@emotion/react"; import FormHelperText from "@mui/material/FormHelperText"; import TextField from "@mui/material/TextField"; +import FormControlLabel from "@mui/material/FormControlLabel"; import type * as TypesGen from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; import { ErrorAlert } from "components/Alert/ErrorAlert"; @@ -45,6 +46,7 @@ import type { } from "./CreateWorkspacePage"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWSPermissions } from "./permissions"; +import { Switch } from "components/Switch/Switch"; export const Language = { duplicationWarning: @@ -101,6 +103,7 @@ export const CreateWorkspacePageView: FC = ({ const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), ); + const [showPresetParameters, setShowPresetParameters] = useState(true); const rerollSuggestedName = useCallback(() => { setSuggestedName(() => generateWorkspaceName()); @@ -281,22 +284,31 @@ export const CreateWorkspacePageView: FC = ({ - - { - const index = presetOptions.findIndex( - (preset) => preset.value === option?.value, - ); - if (index === -1) { - return; - } - setSelectedPresetIndex(index); - }} - placeholder="Select a preset" - selectedOption={presetOptions[selectedPresetIndex]} - /> + + + { + const index = presetOptions.findIndex( + (preset) => preset.value === option?.value, + ); + if (index === -1) { + return; + } + setSelectedPresetIndex(index); + }} + placeholder="Select a preset" + selectedOption={presetOptions[selectedPresetIndex]} + /> + +
+ + Show preset parameters +
)} @@ -383,6 +395,11 @@ export const CreateWorkspacePageView: FC = ({ creatingWorkspace || presetParameterNames.includes(parameter.name); + // Skip rendering preset parameters if showPresetParameters is false + if (!showPresetParameters && presetParameterNames.includes(parameter.name)) { + return null; + } + return ( Date: Mon, 31 Mar 2025 09:19:48 +0000 Subject: [PATCH 2/9] fix bug where changing preset overwrote which parameters were being hidden --- .../CreateWorkspacePage/CreateWorkspacePageView.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 9ea900819631f..edc3245c85607 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -200,13 +200,7 @@ export const CreateWorkspacePageView: FC = ({ value: presetParameter.Value, }); } - }, [ - presetOptions, - selectedPresetIndex, - presets, - parameters, - form.setFieldValue, - ]); + }, [presetOptions, selectedPresetIndex, presets, parameters, form.setFieldValue]); return ( @@ -395,7 +389,8 @@ export const CreateWorkspacePageView: FC = ({ creatingWorkspace || presetParameterNames.includes(parameter.name); - // Skip rendering preset parameters if showPresetParameters is false + // Hide preset parameters if showPresetParameters is false + // but keep their values in the form if (!showPresetParameters && presetParameterNames.includes(parameter.name)) { return null; } From f1a58396992747e238e2bfda6efac78d9ff30988 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 09:35:35 +0000 Subject: [PATCH 3/9] Label preset parameters as such --- .../RichParameterInput.stories.tsx | 38 +++++++++++++++++++ .../RichParameterInput/RichParameterInput.tsx | 15 +++++++- .../CreateWorkspacePageView.tsx | 34 +++++++++-------- 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx index 3ec838272e7c6..ea034586fccf7 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx @@ -374,3 +374,41 @@ export const SmallBasicWithDisplayName: Story = { size: "small", }, }; + +export const WithPreset: Story = { + args: { + value: "preset-value", + id: "project_name", + parameter: createTemplateVersionParameter({ + name: "project_name", + description: "Customize the name of a Google Cloud project that will be created!", + }), + isPreset: true, + }, +}; + +export const WithPresetAndImmutable: Story = { + args: { + value: "preset-value", + id: "project_name", + parameter: createTemplateVersionParameter({ + name: "project_name", + description: "Customize the name of a Google Cloud project that will be created!", + mutable: false, + }), + isPreset: true, + }, +}; + +export const WithPresetAndOptional: Story = { + args: { + value: "preset-value", + id: "project_name", + parameter: createTemplateVersionParameter({ + name: "project_name", + description: "Customize the name of a Google Cloud project that will be created!", + required: false, + }), + isPreset: true, + }, +}; diff --git a/site/src/components/RichParameterInput/RichParameterInput.tsx b/site/src/components/RichParameterInput/RichParameterInput.tsx index 9919fca44b592..ceda7ecf39039 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.tsx @@ -19,6 +19,7 @@ import type { AutofillSource, } from "utils/richParameters"; import { MultiTextField } from "./MultiTextField"; +import SettingsIcon from "@mui/icons-material/Settings"; const isBoolean = (parameter: TemplateVersionParameter) => { return parameter.type === "bool"; @@ -122,9 +123,10 @@ const styles = { export interface ParameterLabelProps { parameter: TemplateVersionParameter; + isPreset?: boolean; } -const ParameterLabel: FC = ({ parameter }) => { +const ParameterLabel: FC = ({ parameter, isPreset }) => { const hasDescription = parameter.description && parameter.description !== ""; const displayName = parameter.display_name ? parameter.display_name @@ -146,6 +148,13 @@ const ParameterLabel: FC = ({ parameter }) => { )} + {isPreset && ( + + }> + Preset + + + )} ); @@ -187,6 +196,7 @@ export type RichParameterInputProps = Omit< parameterAutofill?: AutofillBuildParameter; onChange: (value: string) => void; size?: Size; + isPreset?: boolean; }; const autofillDescription: Partial> = { @@ -198,6 +208,7 @@ export const RichParameterInput: FC = ({ parameter, parameterAutofill, onChange, + isPreset, ...fieldProps }) => { const autofillSource = parameterAutofill?.source; @@ -211,7 +222,7 @@ export const RichParameterInput: FC = ({ className={size} data-testid={`parameter-field-${parameter.name}`} > - +
= ({ {parameters.map((parameter, index) => { const parameterField = `rich_parameter_values.${index}`; const parameterInputName = `${parameterField}.value`; + const isPresetParameter = presetParameterNames.includes(parameter.name); const isDisabled = disabledParams?.includes( parameter.name.toLowerCase().replace(/ /g, "_"), ) || creatingWorkspace || - presetParameterNames.includes(parameter.name); + isPresetParameter; // Hide preset parameters if showPresetParameters is false - // but keep their values in the form - if (!showPresetParameters && presetParameterNames.includes(parameter.name)) { + if (!showPresetParameters && isPresetParameter) { return null; } return ( - { - await form.setFieldValue(parameterField, { - name: parameter.name, - value, - }); - }} - key={parameter.name} - parameter={parameter} - parameterAutofill={autofillByName[parameter.name]} - disabled={isDisabled} - /> +
+ { + await form.setFieldValue(parameterField, { + name: parameter.name, + value, + }); + }} + parameter={parameter} + parameterAutofill={autofillByName[parameter.name]} + disabled={isDisabled} + isPreset={isPresetParameter} + /> +
); })} From f6d7a8e141c8ca4512bf5362ded072f711343328 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 09:37:00 +0000 Subject: [PATCH 4/9] text sizing --- site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 786cdf45aa742..2d6af185e77b2 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -301,7 +301,7 @@ export const CreateWorkspacePageView: FC = ({ checked={showPresetParameters} onCheckedChange={setShowPresetParameters} /> - Show preset parameters + Show preset parameters
From 464e2e705cf54efe8c9679d7f662d7a42a288424 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 09:39:00 +0000 Subject: [PATCH 5/9] make lint --- .../RichParameterInput.stories.tsx | 9 ++++++--- .../RichParameterInput/RichParameterInput.tsx | 2 +- .../CreateWorkspacePageView.tsx | 20 ++++++++++++++----- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx index ea034586fccf7..80ed2c9c8111e 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx @@ -381,7 +381,8 @@ export const WithPreset: Story = { id: "project_name", parameter: createTemplateVersionParameter({ name: "project_name", - description: "Customize the name of a Google Cloud project that will be created!", + description: + "Customize the name of a Google Cloud project that will be created!", }), isPreset: true, }, @@ -393,7 +394,8 @@ export const WithPresetAndImmutable: Story = { id: "project_name", parameter: createTemplateVersionParameter({ name: "project_name", - description: "Customize the name of a Google Cloud project that will be created!", + description: + "Customize the name of a Google Cloud project that will be created!", mutable: false, }), isPreset: true, @@ -406,7 +408,8 @@ export const WithPresetAndOptional: Story = { id: "project_name", parameter: createTemplateVersionParameter({ name: "project_name", - description: "Customize the name of a Google Cloud project that will be created!", + description: + "Customize the name of a Google Cloud project that will be created!", required: false, }), isPreset: true, diff --git a/site/src/components/RichParameterInput/RichParameterInput.tsx b/site/src/components/RichParameterInput/RichParameterInput.tsx index ceda7ecf39039..beaff8ca2772e 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.tsx @@ -1,5 +1,6 @@ import type { Interpolation, Theme } from "@emotion/react"; import ErrorOutline from "@mui/icons-material/ErrorOutline"; +import SettingsIcon from "@mui/icons-material/Settings"; import Button from "@mui/material/Button"; import FormControlLabel from "@mui/material/FormControlLabel"; import FormHelperText from "@mui/material/FormHelperText"; @@ -19,7 +20,6 @@ import type { AutofillSource, } from "utils/richParameters"; import { MultiTextField } from "./MultiTextField"; -import SettingsIcon from "@mui/icons-material/Settings"; const isBoolean = (parameter: TemplateVersionParameter) => { return parameter.type === "bool"; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 2d6af185e77b2..a1af92028918a 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -1,7 +1,7 @@ import type { Interpolation, Theme } from "@emotion/react"; +import FormControlLabel from "@mui/material/FormControlLabel"; import FormHelperText from "@mui/material/FormHelperText"; import TextField from "@mui/material/TextField"; -import FormControlLabel from "@mui/material/FormControlLabel"; import type * as TypesGen from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; import { ErrorAlert } from "components/Alert/ErrorAlert"; @@ -25,6 +25,7 @@ import { Pill } from "components/Pill/Pill"; import { RichParameterInput } from "components/RichParameterInput/RichParameterInput"; import { Spinner } from "components/Spinner/Spinner"; import { Stack } from "components/Stack/Stack"; +import { Switch } from "components/Switch/Switch"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { type FormikContextType, useFormik } from "formik"; import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName"; @@ -46,7 +47,6 @@ import type { } from "./CreateWorkspacePage"; import { ExternalAuthButton } from "./ExternalAuthButton"; import type { CreateWSPermissions } from "./permissions"; -import { Switch } from "components/Switch/Switch"; export const Language = { duplicationWarning: @@ -200,7 +200,13 @@ export const CreateWorkspacePageView: FC = ({ value: presetParameter.Value, }); } - }, [presetOptions, selectedPresetIndex, presets, parameters, form.setFieldValue]); + }, [ + presetOptions, + selectedPresetIndex, + presets, + parameters, + form.setFieldValue, + ]); return ( @@ -296,7 +302,9 @@ export const CreateWorkspacePageView: FC = ({ selectedOption={presetOptions[selectedPresetIndex]} /> -
+
= ({ {parameters.map((parameter, index) => { const parameterField = `rich_parameter_values.${index}`; const parameterInputName = `${parameterField}.value`; - const isPresetParameter = presetParameterNames.includes(parameter.name); + const isPresetParameter = presetParameterNames.includes( + parameter.name, + ); const isDisabled = disabledParams?.includes( parameter.name.toLowerCase().replace(/ /g, "_"), From 5df4ad6b85ba30b3fe2dd030d5fde3768cf3ce15 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 09:57:18 +0000 Subject: [PATCH 6/9] add id for storybook testing --- .../pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index a1af92028918a..9bf4c01da8398 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -306,10 +306,16 @@ export const CreateWorkspacePageView: FC = ({ css={{ display: "flex", alignItems: "center", gap: "8px" }} > - Show preset parameters +
From d6000e43bdd7c50ca3da8676dbc1465b21ffe981 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 12:01:05 +0000 Subject: [PATCH 7/9] Move presets to the parameter section --- .../CreateWorkspacePageView.tsx | 93 ++++++++++--------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index 9bf4c01da8398..bf438253d3f6c 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -276,50 +276,6 @@ export const CreateWorkspacePageView: FC = ({ )} - {presets.length > 0 && ( - - - - Select a preset to get started - - - - - - { - const index = presetOptions.findIndex( - (preset) => preset.value === option?.value, - ); - if (index === -1) { - return; - } - setSelectedPresetIndex(index); - }} - placeholder="Select a preset" - selectedOption={presetOptions[selectedPresetIndex]} - /> - -
- - -
-
-
- )}
= ({ hence they require additional vertical spacing for better readability and user experience. */} + {presets.length > 0 && ( + + + + Select a preset to get started + + + + + + { + const index = presetOptions.findIndex( + (preset) => preset.value === option?.value, + ); + if (index === -1) { + return; + } + setSelectedPresetIndex(index); + }} + placeholder="Select a preset" + selectedOption={presetOptions[selectedPresetIndex]} + /> + +
+ + +
+
+
+ )} + {parameters.map((parameter, index) => { const parameterField = `rich_parameter_values.${index}`; const parameterInputName = `${parameterField}.value`; From 633e7f871b6b73404285452ac62276ac2feafc88 Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 12:03:32 +0000 Subject: [PATCH 8/9] hide preset parameters by default --- site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index bf438253d3f6c..6dab8de306a10 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -103,7 +103,7 @@ export const CreateWorkspacePageView: FC = ({ const [suggestedName, setSuggestedName] = useState(() => generateWorkspaceName(), ); - const [showPresetParameters, setShowPresetParameters] = useState(true); + const [showPresetParameters, setShowPresetParameters] = useState(false); const rerollSuggestedName = useCallback(() => { setSuggestedName(() => generateWorkspaceName()); From dd5f042820133962a205ca4a73e32da88948a14f Mon Sep 17 00:00:00 2001 From: Sas Swart Date: Mon, 31 Mar 2025 12:06:05 +0000 Subject: [PATCH 9/9] update preset stories based on new default --- .../CreateWorkspacePage/CreateWorkspacePageView.stories.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index b6a548e3410ff..47d1198765452 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -166,8 +166,6 @@ export const PresetSelectedWithHiddenParameters: Story = { // Select a preset await userEvent.click(canvas.getByLabelText("Preset")); await userEvent.click(canvas.getByText("Preset 1")); - // Toggle off the show preset parameters switch - await userEvent.click(canvas.getByLabelText("Show preset parameters")); }, }; @@ -178,7 +176,8 @@ export const PresetSelectedWithVisibleParameters: Story = { // Select a preset await userEvent.click(canvas.getByLabelText("Preset")); await userEvent.click(canvas.getByText("Preset 1")); - // Ensure the show preset parameters switch is on (it's on by default) + // Toggle off the show preset parameters switch + await userEvent.click(canvas.getByLabelText("Show preset parameters")); }, };