Skip to content

Commit ba975a9

Browse files
committed
Add basic flow for missing parameters on update
1 parent 84fd4a7 commit ba975a9

File tree

6 files changed

+281
-174
lines changed

6 files changed

+281
-174
lines changed

site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx

Lines changed: 4 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
HorizontalForm,
2222
} from "components/HorizontalForm/HorizontalForm"
2323
import { makeStyles } from "@material-ui/core/styles"
24+
import {
25+
selectInitialRichParametersValues,
26+
ValidationSchemaForRichParameters,
27+
} from "util/richParameters"
2428

2529
export enum CreateWorkspaceErrors {
2630
GET_TEMPLATES_ERROR = "getTemplatesError",
@@ -398,44 +402,6 @@ const useStyles = makeStyles((theme) => ({
398402
},
399403
}))
400404

401-
const selectInitialRichParametersValues = (
402-
templateParameters?: TypesGen.TemplateVersionParameter[],
403-
defaultValuesFromQuery?: Record<string, string>,
404-
): TypesGen.WorkspaceBuildParameter[] => {
405-
const defaults: TypesGen.WorkspaceBuildParameter[] = []
406-
if (!templateParameters) {
407-
return defaults
408-
}
409-
410-
templateParameters.forEach((parameter) => {
411-
if (parameter.options.length > 0) {
412-
let parameterValue = parameter.options[0].value
413-
if (defaultValuesFromQuery && defaultValuesFromQuery[parameter.name]) {
414-
parameterValue = defaultValuesFromQuery[parameter.name]
415-
}
416-
417-
const buildParameter: TypesGen.WorkspaceBuildParameter = {
418-
name: parameter.name,
419-
value: parameterValue,
420-
}
421-
defaults.push(buildParameter)
422-
return
423-
}
424-
425-
let parameterValue = parameter.default_value
426-
if (defaultValuesFromQuery && defaultValuesFromQuery[parameter.name]) {
427-
parameterValue = defaultValuesFromQuery[parameter.name]
428-
}
429-
430-
const buildParameter: TypesGen.WorkspaceBuildParameter = {
431-
name: parameter.name,
432-
value: parameterValue || "",
433-
}
434-
defaults.push(buildParameter)
435-
})
436-
return defaults
437-
}
438-
439405
export const workspaceBuildParameterValue = (
440406
workspaceBuildParameters: TypesGen.WorkspaceBuildParameter[],
441407
parameter: TypesGen.TemplateVersionParameter,
@@ -445,107 +411,3 @@ export const workspaceBuildParameterValue = (
445411
})
446412
return (buildParameter && buildParameter.value) || ""
447413
}
448-
449-
export const ValidationSchemaForRichParameters = (
450-
ns: string,
451-
templateParameters?: TypesGen.TemplateVersionParameter[],
452-
lastBuildParameters?: TypesGen.WorkspaceBuildParameter[],
453-
): Yup.AnySchema => {
454-
const { t } = useTranslation(ns)
455-
456-
if (!templateParameters) {
457-
return Yup.object()
458-
}
459-
460-
return Yup.array()
461-
.of(
462-
Yup.object().shape({
463-
name: Yup.string().required(),
464-
value: Yup.string().test("verify with template", (val, ctx) => {
465-
const name = ctx.parent.name
466-
const templateParameter = templateParameters.find(
467-
(parameter) => parameter.name === name,
468-
)
469-
if (templateParameter) {
470-
switch (templateParameter.type) {
471-
case "number":
472-
if (
473-
templateParameter.validation_min &&
474-
templateParameter.validation_max
475-
) {
476-
if (
477-
Number(val) < templateParameter.validation_min ||
478-
templateParameter.validation_max < Number(val)
479-
) {
480-
return ctx.createError({
481-
path: ctx.path,
482-
message: t("validationNumberNotInRange", {
483-
min: templateParameter.validation_min,
484-
max: templateParameter.validation_max,
485-
}),
486-
})
487-
}
488-
}
489-
490-
if (
491-
templateParameter.validation_monotonic &&
492-
lastBuildParameters
493-
) {
494-
const lastBuildParameter = lastBuildParameters.find(
495-
(last) => last.name === name,
496-
)
497-
if (lastBuildParameter) {
498-
switch (templateParameter.validation_monotonic) {
499-
case "increasing":
500-
if (Number(lastBuildParameter.value) > Number(val)) {
501-
return ctx.createError({
502-
path: ctx.path,
503-
message: t("validationNumberNotIncreasing", {
504-
last: lastBuildParameter.value,
505-
}),
506-
})
507-
}
508-
break
509-
case "decreasing":
510-
if (Number(lastBuildParameter.value) < Number(val)) {
511-
return ctx.createError({
512-
path: ctx.path,
513-
message: t("validationNumberNotDecreasing", {
514-
last: lastBuildParameter.value,
515-
}),
516-
})
517-
}
518-
break
519-
}
520-
}
521-
}
522-
break
523-
case "string":
524-
{
525-
if (
526-
!templateParameter.validation_regex ||
527-
templateParameter.validation_regex.length === 0
528-
) {
529-
return true
530-
}
531-
532-
const regex = new RegExp(templateParameter.validation_regex)
533-
if (val && !regex.test(val)) {
534-
return ctx.createError({
535-
path: ctx.path,
536-
message: t("validationPatternNotMatched", {
537-
error: templateParameter.validation_error,
538-
pattern: templateParameter.validation_regex,
539-
}),
540-
})
541-
}
542-
}
543-
break
544-
}
545-
}
546-
return true
547-
}),
548-
}),
549-
)
550-
.required()
551-
}

site/src/pages/WorkspaceBuildParametersPage/WorkspaceBuildParametersPageView.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ import { makeStyles } from "@material-ui/core/styles"
88
import { getFormHelpers } from "util/formUtils"
99
import { FormikContextType, FormikTouched, useFormik } from "formik"
1010
import { RichParameterInput } from "components/RichParameterInput/RichParameterInput"
11-
import {
12-
ValidationSchemaForRichParameters,
13-
workspaceBuildParameterValue,
14-
} from "pages/CreateWorkspacePage/CreateWorkspacePageView"
11+
import { workspaceBuildParameterValue } from "pages/CreateWorkspacePage/CreateWorkspacePageView"
1512
import { FormFooter } from "components/FormFooter/FormFooter"
1613
import * as Yup from "yup"
1714
import { Maybe } from "components/Conditionals/Maybe"
1815
import { GoBackButton } from "components/GoBackButton/GoBackButton"
16+
import { ValidationSchemaForRichParameters } from "util/richParameters"
1917

2018
export enum UpdateWorkspaceErrors {
2119
GET_WORKSPACE_ERROR = "getWorkspaceError",
Lines changed: 109 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,122 @@
1-
import Button from "@material-ui/core/Button"
1+
import { makeStyles } from "@material-ui/core/styles"
22
import Dialog from "@material-ui/core/Dialog"
3-
import DialogActions from "@material-ui/core/DialogActions"
43
import DialogContent from "@material-ui/core/DialogContent"
54
import DialogContentText from "@material-ui/core/DialogContentText"
65
import DialogTitle from "@material-ui/core/DialogTitle"
7-
import TextField from "@material-ui/core/TextField"
86
import { DialogProps } from "components/Dialogs/Dialog"
97
import { FC } from "react"
8+
import { getFormHelpers } from "util/formUtils"
9+
import {
10+
FormFields,
11+
FormFooter,
12+
} from "components/HorizontalForm/HorizontalForm"
13+
import {
14+
TemplateVersionParameter,
15+
WorkspaceBuildParameter,
16+
} from "api/typesGenerated"
17+
import { RichParameterInput } from "components/RichParameterInput/RichParameterInput"
18+
import { Stack } from "components/Stack/Stack"
19+
import { useFormik } from "formik"
20+
import {
21+
selectInitialRichParametersValues,
22+
ValidationSchemaForRichParameters,
23+
} from "util/richParameters"
24+
import * as Yup from "yup"
25+
26+
export type UpdateBuildParametersDialogProps = DialogProps & {
27+
onClose: () => void
28+
onUpdate: (buildParameters: WorkspaceBuildParameter[]) => void
29+
parameters?: TemplateVersionParameter[]
30+
}
31+
32+
export const UpdateBuildParametersDialog: FC<
33+
UpdateBuildParametersDialogProps
34+
> = ({ parameters, onUpdate, ...dialogProps }) => {
35+
const styles = useStyles()
36+
const form = useFormik({
37+
initialValues: {
38+
rich_parameter_values: selectInitialRichParametersValues(parameters),
39+
},
40+
validationSchema: Yup.object({
41+
rich_parameter_values: ValidationSchemaForRichParameters(
42+
"createWorkspacePage",
43+
parameters,
44+
),
45+
}),
46+
onSubmit: (values) => {
47+
onUpdate(values.rich_parameter_values)
48+
},
49+
})
50+
const getFieldHelpers = getFormHelpers(form)
1051

11-
export const UpdateBuildParametersDialog: FC<DialogProps> = (props) => {
1252
return (
13-
<Dialog {...props} aria-labelledby="update-build-parameters-title">
14-
<DialogTitle id="update-build-parameters-title">Subscribe</DialogTitle>
15-
<DialogContent>
16-
<DialogContentText>
17-
To subscribe to this website, please enter your email address here. We
18-
will send updates occasionally.
53+
<Dialog {...dialogProps} aria-labelledby="update-build-parameters-title">
54+
<DialogTitle
55+
id="update-build-parameters-title"
56+
classes={{ root: styles.title }}
57+
>
58+
Missing workspace parameters
59+
</DialogTitle>
60+
<DialogContent className={styles.content}>
61+
<DialogContentText className={styles.contentText}>
62+
It looks like the new version has some mandatory parameters that need
63+
to be filled in to update the workspace.
1964
</DialogContentText>
20-
<TextField
21-
autoFocus
22-
margin="dense"
23-
id="name"
24-
label="Email Address"
25-
type="email"
26-
fullWidth
27-
/>
65+
<form className={styles.form} onSubmit={form.handleSubmit}>
66+
<Stack spacing={5}>
67+
<FormFields>
68+
{parameters &&
69+
parameters.map((parameter, index) => {
70+
return (
71+
<RichParameterInput
72+
{...getFieldHelpers(
73+
"rich_parameter_values[" + index + "].value",
74+
)}
75+
key={parameter.name}
76+
parameter={parameter}
77+
initialValue=""
78+
index={index}
79+
onChange={async (value) => {
80+
await form.setFieldValue(
81+
"rich_parameter_values." + index,
82+
{
83+
name: parameter.name,
84+
value: value,
85+
},
86+
)
87+
}}
88+
/>
89+
)
90+
})}
91+
</FormFields>
92+
<FormFooter onCancel={dialogProps.onClose} isLoading={false} />
93+
</Stack>
94+
</form>
2895
</DialogContent>
29-
<DialogActions>
30-
<Button onClick={() => {}} color="primary">
31-
Subscribe
32-
</Button>
33-
</DialogActions>
3496
</Dialog>
3597
)
3698
}
99+
100+
const useStyles = makeStyles((theme) => ({
101+
title: {
102+
padding: theme.spacing(5, 5, 2, 5),
103+
104+
"& h2": {
105+
fontSize: theme.spacing(2.5),
106+
fontWeight: 400,
107+
},
108+
},
109+
110+
content: {
111+
padding: theme.spacing(0, 5, 5, 5),
112+
},
113+
114+
contentText: {
115+
fontSize: theme.spacing(2),
116+
lineHeight: "160%",
117+
},
118+
119+
form: {
120+
marginTop: theme.spacing(4),
121+
},
122+
}))

site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const WorkspaceReadyPage = ({
5454
cancellationError,
5555
applicationsHost,
5656
permissions,
57+
missingParameters,
5758
} = workspaceState.context
5859
if (workspace === undefined) {
5960
throw Error("Workspace is undefined")
@@ -144,9 +145,16 @@ export const WorkspaceReadyPage = ({
144145
}}
145146
/>
146147
<UpdateBuildParametersDialog
148+
parameters={missingParameters}
147149
open={workspaceState.matches(
148150
"ready.build.askingForMissedBuildParameters",
149151
)}
152+
onClose={() => {
153+
workspaceSend({ type: "CANCEL" })
154+
}}
155+
onUpdate={(buildParameters) => {
156+
workspaceSend({ type: "UPDATE", buildParameters })
157+
}}
150158
/>
151159
</>
152160
)

0 commit comments

Comments
 (0)