Skip to content

Commit ea9690c

Browse files
committed
Change the create template flow to use variables
1 parent 2ff1c6d commit ea9690c

File tree

4 files changed

+249
-43
lines changed

4 files changed

+249
-43
lines changed

site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
ParameterSchema,
66
ProvisionerJobLog,
77
TemplateExample,
8+
TemplateVersionVariable,
89
} from "api/typesGenerated"
910
import { FormFooter } from "components/FormFooter/FormFooter"
1011
import { ParameterInput } from "components/ParameterInput/ParameterInput"
@@ -23,6 +24,7 @@ import * as Yup from "yup"
2324
import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs"
2425
import { HelpTooltip, HelpTooltipText } from "components/Tooltips/HelpTooltip"
2526
import { LazyIconField } from "components/IconField/LazyIconField"
27+
import { VariableInput } from "./VariableInput"
2628

2729
const validationSchema = Yup.object({
2830
name: nameValidator("Name"),
@@ -32,6 +34,9 @@ const validationSchema = Yup.object({
3234
default_ttl_hours: Yup.number(),
3335
allow_user_cancel_workspace_jobs: Yup.boolean(),
3436
parameter_values_by_name: Yup.object().optional(),
37+
user_variable_values: Yup.array()
38+
.of(Yup.object({ name: Yup.string(), value: Yup.string().optional() }))
39+
.optional(),
3540
})
3641

3742
const defaultInitialValues: CreateTemplateData = {
@@ -42,6 +47,7 @@ const defaultInitialValues: CreateTemplateData = {
4247
default_ttl_hours: 24,
4348
allow_user_cancel_workspace_jobs: false,
4449
parameter_values_by_name: undefined,
50+
user_variable_values: undefined,
4551
}
4652

4753
const getInitialValues = (starterTemplate?: TemplateExample) => {
@@ -62,6 +68,7 @@ interface CreateTemplateFormProps {
6268
starterTemplate?: TemplateExample
6369
error?: unknown
6470
parameters?: ParameterSchema[]
71+
variables?: TemplateVersionVariable[]
6572
isSubmitting: boolean
6673
onCancel: () => void
6774
onSubmit: (data: CreateTemplateData) => void
@@ -74,6 +81,7 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = ({
7481
starterTemplate,
7582
error,
7683
parameters,
84+
variables,
7785
isSubmitting,
7886
onCancel,
7987
onSubmit,
@@ -268,6 +276,34 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = ({
268276
</div>
269277
)}
270278

279+
{/* Variables */}
280+
{variables && (
281+
<div className={styles.formSection}>
282+
<div className={styles.formSectionInfo}>
283+
<h2 className={styles.formSectionInfoTitle}>Variables</h2>
284+
<p className={styles.formSectionInfoDescription}>
285+
Enter the user variables
286+
</p>
287+
</div>
288+
289+
<Stack direction="column" className={styles.formSectionFields}>
290+
{variables.map((variable, index) => (
291+
<VariableInput
292+
variable={variable}
293+
disabled={isSubmitting}
294+
key={variable.name}
295+
onChange={async (value) => {
296+
await form.setFieldValue("user_variable_values." + index, {
297+
name: variable.name,
298+
value: value,
299+
})
300+
}}
301+
/>
302+
))}
303+
</Stack>
304+
</div>
305+
)}
306+
271307
{jobError && (
272308
<Stack>
273309
<div className={styles.error}>

site/src/pages/CreateTemplatePage/CreateTemplatePage.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,15 @@ const CreateTemplatePage: FC = () => {
3030
},
3131
},
3232
})
33-
const { starterTemplate, parameters, error, file, jobError, jobLogs } =
34-
state.context
33+
const {
34+
starterTemplate,
35+
parameters,
36+
error,
37+
file,
38+
jobError,
39+
jobLogs,
40+
variables,
41+
} = state.context
3542
const shouldDisplayForm = !state.hasTag("loading")
3643

3744
const onCancel = () => {
@@ -59,6 +66,7 @@ const CreateTemplatePage: FC = () => {
5966
error={error}
6067
starterTemplate={starterTemplate}
6168
isSubmitting={state.hasTag("submitting")}
69+
variables={variables}
6270
parameters={parameters}
6371
onCancel={onCancel}
6472
onSubmit={(data) => {
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import FormControlLabel from "@material-ui/core/FormControlLabel"
2+
import Radio from "@material-ui/core/Radio"
3+
import RadioGroup from "@material-ui/core/RadioGroup"
4+
import { makeStyles } from "@material-ui/core/styles"
5+
import TextField from "@material-ui/core/TextField"
6+
import { Stack } from "components/Stack/Stack"
7+
import { FC } from "react"
8+
import { TemplateVersionVariable } from "../../api/typesGenerated"
9+
10+
const isBoolean = (variable: TemplateVersionVariable) => {
11+
return variable.type === "bool"
12+
}
13+
14+
const VariableLabel: React.FC<{ variable: TemplateVersionVariable }> = ({
15+
variable,
16+
}) => {
17+
const styles = useStyles()
18+
19+
return (
20+
<label htmlFor={variable.name}>
21+
<span className={styles.labelName}>var.{variable.name}</span>
22+
<span className={styles.labelDescription}>{variable.description}</span>
23+
</label>
24+
)
25+
}
26+
27+
export interface VariableInputProps {
28+
disabled?: boolean
29+
variable: TemplateVersionVariable
30+
onChange: (value: string) => void
31+
defaultValue?: string
32+
}
33+
34+
export const VariableInput: FC<VariableInputProps> = ({
35+
disabled,
36+
onChange,
37+
variable,
38+
defaultValue,
39+
}) => {
40+
const styles = useStyles()
41+
42+
return (
43+
<Stack direction="column" spacing={0.75}>
44+
<VariableLabel variable={variable} />
45+
<div className={styles.input}>
46+
<VariableField
47+
disabled={disabled}
48+
onChange={onChange}
49+
variable={variable}
50+
defaultValue={defaultValue}
51+
/>
52+
</div>
53+
</Stack>
54+
)
55+
}
56+
57+
const VariableField: React.FC<VariableInputProps> = ({
58+
disabled,
59+
onChange,
60+
variable,
61+
defaultValue,
62+
}) => {
63+
if (isBoolean(variable)) {
64+
return (
65+
<RadioGroup
66+
id={variable.name}
67+
defaultValue={variable.default_value}
68+
onChange={(event) => {
69+
onChange(event.target.value)
70+
}}
71+
>
72+
<FormControlLabel
73+
disabled={disabled}
74+
value="true"
75+
control={<Radio color="primary" size="small" disableRipple />}
76+
label="True"
77+
/>
78+
<FormControlLabel
79+
disabled={disabled}
80+
value="false"
81+
control={<Radio color="primary" size="small" disableRipple />}
82+
label="False"
83+
/>
84+
</RadioGroup>
85+
)
86+
}
87+
88+
return (
89+
<TextField
90+
id={variable.name}
91+
size="small"
92+
disabled={disabled}
93+
placeholder={variable.sensitive ? "" : variable.default_value}
94+
defaultValue={
95+
variable.sensitive ? "" : defaultValue ?? variable.default_value
96+
}
97+
onChange={(event) => {
98+
onChange(event.target.value)
99+
}}
100+
/>
101+
)
102+
}
103+
104+
const useStyles = makeStyles((theme) => ({
105+
labelName: {
106+
fontSize: 14,
107+
color: theme.palette.text.secondary,
108+
display: "block",
109+
marginBottom: theme.spacing(0.5),
110+
},
111+
labelDescription: {
112+
fontSize: 16,
113+
color: theme.palette.text.primary,
114+
display: "block",
115+
fontWeight: 600,
116+
},
117+
input: {
118+
display: "flex",
119+
flexDirection: "column",
120+
},
121+
checkbox: {
122+
display: "flex",
123+
alignItems: "center",
124+
gap: theme.spacing(1),
125+
},
126+
}))

0 commit comments

Comments
 (0)