-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
useBuildForm.tsx
142 lines (126 loc) · 4.99 KB
/
useBuildForm.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import { JSONSchema7, JSONSchema7Definition } from "json-schema";
import { useMemo } from "react";
import { useIntl } from "react-intl";
import { AnySchema } from "yup";
import {
ConnectorDefinitionSpecification,
ConnectorSpecification,
SourceDefinitionSpecificationDraft,
} from "core/domain/connector";
import { isSourceDefinitionSpecificationDraft } from "core/domain/connector/source";
import { FormBuildError, isFormBuildError } from "core/form/FormBuildError";
import { jsonSchemaToFormBlock } from "core/form/schemaToFormBlock";
import { buildYupFormForJsonSchema } from "core/form/schemaToYup";
import { FormBlock, FormGroupItem } from "core/form/types";
import { ConnectorFormValues } from "./types";
export interface BuildFormHook {
initialValues: ConnectorFormValues;
formFields: FormBlock;
validationSchema: AnySchema;
}
export function setDefaultValues(
formGroup: FormGroupItem,
values: Record<string, unknown>,
options: { respectExistingValues: boolean } = { respectExistingValues: false }
) {
formGroup.properties.forEach((property) => {
if (property.const && (!options.respectExistingValues || !values[property.fieldKey])) {
values[property.fieldKey] = property.const;
}
if (property.default && (!options.respectExistingValues || !values[property.fieldKey])) {
values[property.fieldKey] = property.default;
}
switch (property._type) {
case "formGroup":
values[property.fieldKey] =
options.respectExistingValues && values[property.fieldKey] ? values[property.fieldKey] : {};
setDefaultValues(property, values[property.fieldKey] as Record<string, unknown>, options);
break;
case "formCondition":
values[property.fieldKey] = {};
let chosenCondition = property.conditions[0];
// if default is set, try to find it in the list of possible selection const values.
// if there is a match, default to this condition.
// In all other cases, go with the first one.
if (property.default) {
const matchingConditionIndex = property.selectionConstValues.indexOf(property.default);
if (matchingConditionIndex !== -1) {
chosenCondition = property.conditions[matchingConditionIndex];
}
}
setDefaultValues(chosenCondition, values[property.fieldKey] as Record<string, unknown>);
}
});
}
export function useBuildForm(
isEditMode: boolean,
formType: "source" | "destination",
selectedConnectorDefinitionSpecification: ConnectorDefinitionSpecification | SourceDefinitionSpecificationDraft,
initialValues?: Partial<ConnectorFormValues>
): BuildFormHook {
const { formatMessage } = useIntl();
const isDraft = isSourceDefinitionSpecificationDraft(selectedConnectorDefinitionSpecification);
try {
const jsonSchema: JSONSchema7 = useMemo(() => {
const schema: JSONSchema7 = {
type: "object",
properties: {
connectionConfiguration:
selectedConnectorDefinitionSpecification.connectionSpecification as JSONSchema7Definition,
},
};
if (isDraft) {
return schema;
}
schema.properties = {
name: {
type: "string",
title: formatMessage({ id: `form.${formType}Name` }),
description: formatMessage({ id: `form.${formType}Name.message` }),
},
...schema.properties,
};
schema.required = ["name"];
return schema;
}, [formType, formatMessage, isDraft, selectedConnectorDefinitionSpecification.connectionSpecification]);
const formFields = useMemo<FormBlock>(() => jsonSchemaToFormBlock(jsonSchema), [jsonSchema]);
if (formFields._type !== "formGroup") {
throw new FormBuildError("connectorForm.error.topLevelNonObject");
}
const validationSchema = useMemo(() => buildYupFormForJsonSchema(jsonSchema, formFields), [formFields, jsonSchema]);
const startValues = useMemo<ConnectorFormValues>(() => {
let baseValues = {
name: "",
connectionConfiguration: {},
...initialValues,
};
if (isDraft) {
try {
baseValues = validationSchema.cast(baseValues, { stripUnknown: true });
} catch {
// cast did not work which can happen if there are unexpected values in the form. Reset form in this case
baseValues.connectionConfiguration = {};
}
}
if (isEditMode) {
return baseValues;
}
setDefaultValues(formFields, baseValues as Record<string, unknown>, { respectExistingValues: isDraft });
return baseValues;
}, [formFields, initialValues, isDraft, isEditMode, validationSchema]);
return {
initialValues: startValues,
formFields,
validationSchema,
};
} catch (e) {
// catch and re-throw form-build errors to enrich them with the connector id
if (isFormBuildError(e)) {
throw new FormBuildError(
e.message,
isDraft ? undefined : ConnectorSpecification.id(selectedConnectorDefinitionSpecification)
);
}
throw e;
}
}