Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 00e1ea4

Browse files
authored
feat: add the ability to hide preset parameters (#17168)
This PR adds the ability to hide presets on the workspace creation form. When showing them, a clear indication is now made as to which inputs were preset and which weren't. ![image](https://github.com/user-attachments/assets/6c8f690c-7cf6-44a9-9657-65039b2b3cb7)
1 parent 88bae05 commit 00e1ea4

File tree

4 files changed

+152
-43
lines changed

4 files changed

+152
-43
lines changed

site/src/components/RichParameterInput/RichParameterInput.stories.tsx

+41
Original file line numberDiff line numberDiff line change
@@ -374,3 +374,44 @@ export const SmallBasicWithDisplayName: Story = {
374374
size: "small",
375375
},
376376
};
377+
378+
export const WithPreset: Story = {
379+
args: {
380+
value: "preset-value",
381+
id: "project_name",
382+
parameter: createTemplateVersionParameter({
383+
name: "project_name",
384+
description:
385+
"Customize the name of a Google Cloud project that will be created!",
386+
}),
387+
isPreset: true,
388+
},
389+
};
390+
391+
export const WithPresetAndImmutable: Story = {
392+
args: {
393+
value: "preset-value",
394+
id: "project_name",
395+
parameter: createTemplateVersionParameter({
396+
name: "project_name",
397+
description:
398+
"Customize the name of a Google Cloud project that will be created!",
399+
mutable: false,
400+
}),
401+
isPreset: true,
402+
},
403+
};
404+
405+
export const WithPresetAndOptional: Story = {
406+
args: {
407+
value: "preset-value",
408+
id: "project_name",
409+
parameter: createTemplateVersionParameter({
410+
name: "project_name",
411+
description:
412+
"Customize the name of a Google Cloud project that will be created!",
413+
required: false,
414+
}),
415+
isPreset: true,
416+
},
417+
};

site/src/components/RichParameterInput/RichParameterInput.tsx

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Interpolation, Theme } from "@emotion/react";
22
import ErrorOutline from "@mui/icons-material/ErrorOutline";
3+
import SettingsIcon from "@mui/icons-material/Settings";
34
import Button from "@mui/material/Button";
45
import FormControlLabel from "@mui/material/FormControlLabel";
56
import FormHelperText from "@mui/material/FormHelperText";
@@ -122,9 +123,10 @@ const styles = {
122123

123124
export interface ParameterLabelProps {
124125
parameter: TemplateVersionParameter;
126+
isPreset?: boolean;
125127
}
126128

127-
const ParameterLabel: FC<ParameterLabelProps> = ({ parameter }) => {
129+
const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
128130
const hasDescription = parameter.description && parameter.description !== "";
129131
const displayName = parameter.display_name
130132
? parameter.display_name
@@ -146,6 +148,13 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter }) => {
146148
</Pill>
147149
</Tooltip>
148150
)}
151+
{isPreset && (
152+
<Tooltip title="This value was set by a preset">
153+
<Pill type="info" icon={<SettingsIcon />}>
154+
Preset
155+
</Pill>
156+
</Tooltip>
157+
)}
149158
</span>
150159
);
151160

@@ -187,6 +196,7 @@ export type RichParameterInputProps = Omit<
187196
parameterAutofill?: AutofillBuildParameter;
188197
onChange: (value: string) => void;
189198
size?: Size;
199+
isPreset?: boolean;
190200
};
191201

192202
const autofillDescription: Partial<Record<AutofillSource, ReactNode>> = {
@@ -198,6 +208,7 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
198208
parameter,
199209
parameterAutofill,
200210
onChange,
211+
isPreset,
201212
...fieldProps
202213
}) => {
203214
const autofillSource = parameterAutofill?.source;
@@ -211,7 +222,7 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
211222
className={size}
212223
data-testid={`parameter-field-${parameter.name}`}
213224
>
214-
<ParameterLabel parameter={parameter} />
225+
<ParameterLabel parameter={parameter} isPreset={isPreset} />
215226
<div css={{ display: "flex", flexDirection: "column" }}>
216227
<RichParameterField
217228
{...fieldProps}

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx

+22
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,28 @@ export const PresetSelected: Story = {
159159
},
160160
};
161161

162+
export const PresetSelectedWithHiddenParameters: Story = {
163+
args: PresetsButNoneSelected.args,
164+
play: async ({ canvasElement }) => {
165+
const canvas = within(canvasElement);
166+
// Select a preset
167+
await userEvent.click(canvas.getByLabelText("Preset"));
168+
await userEvent.click(canvas.getByText("Preset 1"));
169+
},
170+
};
171+
172+
export const PresetSelectedWithVisibleParameters: Story = {
173+
args: PresetsButNoneSelected.args,
174+
play: async ({ canvasElement }) => {
175+
const canvas = within(canvasElement);
176+
// Select a preset
177+
await userEvent.click(canvas.getByLabelText("Preset"));
178+
await userEvent.click(canvas.getByText("Preset 1"));
179+
// Toggle off the show preset parameters switch
180+
await userEvent.click(canvas.getByLabelText("Show preset parameters"));
181+
},
182+
};
183+
162184
export const PresetReselected: Story = {
163185
args: PresetsButNoneSelected.args,
164186
play: async ({ canvasElement }) => {

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

+76-41
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Interpolation, Theme } from "@emotion/react";
2+
import FormControlLabel from "@mui/material/FormControlLabel";
23
import FormHelperText from "@mui/material/FormHelperText";
34
import TextField from "@mui/material/TextField";
45
import type * as TypesGen from "api/typesGenerated";
@@ -24,6 +25,7 @@ import { Pill } from "components/Pill/Pill";
2425
import { RichParameterInput } from "components/RichParameterInput/RichParameterInput";
2526
import { Spinner } from "components/Spinner/Spinner";
2627
import { Stack } from "components/Stack/Stack";
28+
import { Switch } from "components/Switch/Switch";
2729
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
2830
import { type FormikContextType, useFormik } from "formik";
2931
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
@@ -101,6 +103,7 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
101103
const [suggestedName, setSuggestedName] = useState(() =>
102104
generateWorkspaceName(),
103105
);
106+
const [showPresetParameters, setShowPresetParameters] = useState(false);
104107

105108
const rerollSuggestedName = useCallback(() => {
106109
setSuggestedName(() => generateWorkspaceName());
@@ -273,33 +276,6 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
273276
</Stack>
274277
)}
275278

276-
{presets.length > 0 && (
277-
<Stack direction="column" spacing={2}>
278-
<Stack direction="row" spacing={2} alignItems="center">
279-
<span css={styles.description}>
280-
Select a preset to get started
281-
</span>
282-
<FeatureStageBadge contentType={"beta"} size="md" />
283-
</Stack>
284-
<Stack direction="row" spacing={2}>
285-
<SelectFilter
286-
label="Preset"
287-
options={presetOptions}
288-
onSelect={(option) => {
289-
const index = presetOptions.findIndex(
290-
(preset) => preset.value === option?.value,
291-
);
292-
if (index === -1) {
293-
return;
294-
}
295-
setSelectedPresetIndex(index);
296-
}}
297-
placeholder="Select a preset"
298-
selectedOption={presetOptions[selectedPresetIndex]}
299-
/>
300-
</Stack>
301-
</Stack>
302-
)}
303279
<div>
304280
<TextField
305281
{...getFieldHelpers("name")}
@@ -373,30 +349,89 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({
373349
hence they require additional vertical spacing for better readability and
374350
user experience. */}
375351
<FormFields css={{ gap: 36 }}>
352+
{presets.length > 0 && (
353+
<Stack direction="column" spacing={2}>
354+
<Stack direction="row" spacing={2} alignItems="center">
355+
<span css={styles.description}>
356+
Select a preset to get started
357+
</span>
358+
<FeatureStageBadge contentType={"beta"} size="md" />
359+
</Stack>
360+
<Stack direction="column" spacing={2}>
361+
<Stack direction="row" spacing={2}>
362+
<SelectFilter
363+
label="Preset"
364+
options={presetOptions}
365+
onSelect={(option) => {
366+
const index = presetOptions.findIndex(
367+
(preset) => preset.value === option?.value,
368+
);
369+
if (index === -1) {
370+
return;
371+
}
372+
setSelectedPresetIndex(index);
373+
}}
374+
placeholder="Select a preset"
375+
selectedOption={presetOptions[selectedPresetIndex]}
376+
/>
377+
</Stack>
378+
<div
379+
css={{
380+
display: "flex",
381+
alignItems: "center",
382+
gap: "8px",
383+
}}
384+
>
385+
<Switch
386+
id="show-preset-parameters"
387+
checked={showPresetParameters}
388+
onCheckedChange={setShowPresetParameters}
389+
/>
390+
<label
391+
htmlFor="show-preset-parameters"
392+
css={styles.description}
393+
>
394+
Show preset parameters
395+
</label>
396+
</div>
397+
</Stack>
398+
</Stack>
399+
)}
400+
376401
{parameters.map((parameter, index) => {
377402
const parameterField = `rich_parameter_values.${index}`;
378403
const parameterInputName = `${parameterField}.value`;
404+
const isPresetParameter = presetParameterNames.includes(
405+
parameter.name,
406+
);
379407
const isDisabled =
380408
disabledParams?.includes(
381409
parameter.name.toLowerCase().replace(/ /g, "_"),
382410
) ||
383411
creatingWorkspace ||
384-
presetParameterNames.includes(parameter.name);
412+
isPresetParameter;
413+
414+
// Hide preset parameters if showPresetParameters is false
415+
if (!showPresetParameters && isPresetParameter) {
416+
return null;
417+
}
385418

386419
return (
387-
<RichParameterInput
388-
{...getFieldHelpers(parameterInputName)}
389-
onChange={async (value) => {
390-
await form.setFieldValue(parameterField, {
391-
name: parameter.name,
392-
value,
393-
});
394-
}}
395-
key={parameter.name}
396-
parameter={parameter}
397-
parameterAutofill={autofillByName[parameter.name]}
398-
disabled={isDisabled}
399-
/>
420+
<div key={parameter.name}>
421+
<RichParameterInput
422+
{...getFieldHelpers(parameterInputName)}
423+
onChange={async (value) => {
424+
await form.setFieldValue(parameterField, {
425+
name: parameter.name,
426+
value,
427+
});
428+
}}
429+
parameter={parameter}
430+
parameterAutofill={autofillByName[parameter.name]}
431+
disabled={isDisabled}
432+
isPreset={isPresetParameter}
433+
/>
434+
</div>
400435
);
401436
})}
402437
</FormFields>

0 commit comments

Comments
 (0)