-
Notifications
You must be signed in to change notification settings - Fork 875
feat(site): add support for presets to the create workspace page #16567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0f53056
b1aff3f
8d08a64
da9239e
e47296c
ae19b51
6787f10
4cc78c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -6,6 +6,7 @@ import { Alert } from "components/Alert/Alert"; | |||
import { ErrorAlert } from "components/Alert/ErrorAlert"; | ||||
import { Avatar } from "components/Avatar/Avatar"; | ||||
import { Button } from "components/Button/Button"; | ||||
import { SelectFilter } from "components/Filter/SelectFilter"; | ||||
import { | ||||
FormFields, | ||||
FormFooter, | ||||
|
@@ -64,6 +65,7 @@ export interface CreateWorkspacePageViewProps { | |||
hasAllRequiredExternalAuth: boolean; | ||||
parameters: TypesGen.TemplateVersionParameter[]; | ||||
autofillParameters: AutofillBuildParameter[]; | ||||
presets: TypesGen.Preset[]; | ||||
permissions: CreateWSPermissions; | ||||
creatingWorkspace: boolean; | ||||
onCancel: () => void; | ||||
|
@@ -88,6 +90,7 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({ | |||
hasAllRequiredExternalAuth, | ||||
parameters, | ||||
autofillParameters, | ||||
presets = [], | ||||
permissions, | ||||
creatingWorkspace, | ||||
onSubmit, | ||||
|
@@ -145,6 +148,62 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({ | |||
[autofillParameters], | ||||
); | ||||
|
||||
const [presetOptions, setPresetOptions] = useState([ | ||||
{ label: "None", value: "" }, | ||||
]); | ||||
useEffect(() => { | ||||
setPresetOptions([ | ||||
{ label: "None", value: "" }, | ||||
...presets.map((preset) => ({ | ||||
label: preset.Name, | ||||
value: preset.ID, | ||||
})), | ||||
]); | ||||
}, [presets]); | ||||
|
||||
const [selectedPresetIndex, setSelectedPresetIndex] = useState(0); | ||||
const [presetParameterNames, setPresetParameterNames] = useState<string[]>( | ||||
[], | ||||
); | ||||
|
||||
useEffect(() => { | ||||
const selectedPresetOption = presetOptions[selectedPresetIndex]; | ||||
let selectedPreset: TypesGen.Preset | undefined; | ||||
for (const preset of presets) { | ||||
if (preset.ID === selectedPresetOption.value) { | ||||
selectedPreset = preset; | ||||
break; | ||||
} | ||||
} | ||||
|
||||
if (!selectedPreset || !selectedPreset.Parameters) { | ||||
setPresetParameterNames([]); | ||||
return; | ||||
} | ||||
|
||||
setPresetParameterNames(selectedPreset.Parameters.map((p) => p.Name)); | ||||
|
||||
for (const presetParameter of selectedPreset.Parameters) { | ||||
const parameterIndex = parameters.findIndex( | ||||
(p) => p.name === presetParameter.Name, | ||||
); | ||||
if (parameterIndex === -1) continue; | ||||
|
||||
const parameterField = `rich_parameter_values.${parameterIndex}`; | ||||
|
||||
form.setFieldValue(parameterField, { | ||||
name: presetParameter.Name, | ||||
value: presetParameter.Value, | ||||
}); | ||||
} | ||||
}, [ | ||||
presetOptions, | ||||
selectedPresetIndex, | ||||
presets, | ||||
parameters, | ||||
form.setFieldValue, | ||||
]); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm assuming this effect is to set in the form the default values right? If yes, I think the best place to set them is in the form initialValues prop here
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This effect is not only for default values, but also for if the user chooses a new preset. If they choose a new preset then this effect will autofill the form for them using the new preset values. |
||||
|
||||
return ( | ||||
<Margins size="medium"> | ||||
<PageHeader | ||||
|
@@ -213,6 +272,28 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({ | |||
</Stack> | ||||
)} | ||||
|
||||
{presets.length > 0 && ( | ||||
<Stack direction="column" spacing={2}> | ||||
<span css={styles.description}> | ||||
Select a preset to get started | ||||
</span> | ||||
<Stack direction="row" spacing={2}> | ||||
<SelectFilter | ||||
label="Preset" | ||||
options={presetOptions} | ||||
onSelect={(option) => { | ||||
setSelectedPresetIndex( | ||||
presetOptions.findIndex( | ||||
(preset) => preset.value === option?.value, | ||||
), | ||||
); | ||||
}} | ||||
placeholder="Select a preset" | ||||
selectedOption={presetOptions[selectedPresetIndex]} | ||||
/> | ||||
</Stack> | ||||
</Stack> | ||||
)} | ||||
<div> | ||||
<TextField | ||||
{...getFieldHelpers("name")} | ||||
|
@@ -292,7 +373,9 @@ export const CreateWorkspacePageView: FC<CreateWorkspacePageViewProps> = ({ | |||
const isDisabled = | ||||
disabledParams?.includes( | ||||
parameter.name.toLowerCase().replace(/ /g, "_"), | ||||
) || creatingWorkspace; | ||||
) || | ||||
creatingWorkspace || | ||||
presetParameterNames.includes(parameter.name); | ||||
|
||||
return ( | ||||
<RichParameterInput | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only use
useMemo
when really necessary. In this case, it would be ok to compute this on every render.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. I will remove the useMemo. For my own learning: Can you help me understand why not to use useMemo in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s just a matter of adding complexity—caching—in a place where it’s not really needed.