Skip to content

Commit

Permalink
Fix form not revalidating values (#865)
Browse files Browse the repository at this point in the history
* Fix form not revalidating values

* Update comment with more meaning
  • Loading branch information
jamakase authored Nov 10, 2020
1 parent 9305461 commit 4f851a6
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 27 deletions.
13 changes: 6 additions & 7 deletions airbyte-webapp/src/components/ServiceForm/ServiceForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,25 +79,24 @@ const ServiceForm: React.FC<IProps> = ({
validateOnChange={true}
validateOnMount={true}
validationSchema={validationSchema}
onSubmit={async values => {
return onSubmit(validationSchema.cast(values, { stripUnknown: true }));
}}
onSubmit={async values =>
onSubmit(validationSchema.cast(values, { stripUnknown: true }))
}
>
{({ isSubmitting, setFieldValue, isValid, dirty, values, resetForm }) => (
{({ isSubmitting, isValid, dirty, resetForm, ...formProps }) => (
<FormContainer>
<FormContent
{...formProps}
allowChangeConnector={allowChangeConnector}
schema={validationSchema}
dropDownData={dropDownData}
formType={formType}
formFields={formFields}
specifications={specifications}
widgetsInfo={uiWidgetsInfo}
values={values}
isEditMode={isEditMode}
isLoadingSchema={isLoading}
onChangeServiceType={onDropDownSelect}
setUiWidgetsInfo={setUiWidgetsInfo}
setFieldValue={setFieldValue}
documentationUrl={documentationUrl}
/>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from "react";
import { JSONSchema7 } from "json-schema";
import React, { useEffect } from "react";

import { Field, FieldProps, useField } from "formik";
import { FormattedMessage, useIntl } from "react-intl";
Expand All @@ -17,22 +16,25 @@ import {
FormBlock,
WidgetConfigMap
} from "../../../core/form/types";
import { FormInitialValues } from "../useBuildForm";
import { FormikProps } from "formik/dist/types";

type IProps = {
schema: any;
formFields: FormBlock[];
dropDownData: Array<IDataItem>;
setFieldValue: (name: string, value: string) => void;
setUiWidgetsInfo: (path: string, value: object) => void;
isLoadingSchema?: boolean;
isEditMode?: boolean;
allowChangeConnector?: boolean;
onChangeServiceType?: (id: string) => void;
formType: "source" | "destination" | "connection";
values: { name: string; serviceType: string; frequency?: string };
specifications?: JSONSchema7;
widgetsInfo: WidgetConfigMap;
setUiWidgetsInfo: (path: string, value: object) => void;
documentationUrl?: string;
};
onChangeServiceType?: (id: string) => void;
} & Pick<
FormikProps<FormInitialValues>,
"values" | "setFieldValue" | "validateForm"
>;

const FormItem = styled.div`
margin-bottom: 27px;
Expand Down Expand Up @@ -89,6 +91,7 @@ const FrequencyInput: React.FC = () => {
};

const FormContent: React.FC<IProps> = ({
schema,
dropDownData,
formType,
setFieldValue,
Expand All @@ -98,12 +101,18 @@ const FormContent: React.FC<IProps> = ({
isLoadingSchema,
isEditMode,
onChangeServiceType,
validateForm,
documentationUrl,
allowChangeConnector,
formFields
}) => {
const formatMessage = useIntl().formatMessage;

// Formik doesn't validate values again, when validationSchema was changed on the fly.
useEffect(() => {
validateForm();
}, [validateForm, schema]);

const renderItem = (
formItem: FormBaseItem,
fieldProps: FieldProps<string>
Expand Down
4 changes: 3 additions & 1 deletion airbyte-webapp/src/components/ServiceForm/useBuildForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export const useConstructValidationSchema = (
validationShape = validationShape.shape({
connectionConfiguration: buildYupFormForJsonSchema(
jsonSchema,
uiWidgetsInfo
uiWidgetsInfo,
undefined,
"connectionConfiguration"
)
});
}
Expand Down
45 changes: 45 additions & 0 deletions airbyte-webapp/src/core/jsonSchema/schemaToYup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,48 @@ test("should build schema for conditional case", () => {

expect(JSON.stringify(yupSchema)).toEqual(JSON.stringify(expectedSchema));
});

test("should build schema for conditional case with inner schema and selected uiwidget", () => {
const yupSchema = buildYupFormForJsonSchema(
{
type: "object",
properties: {
credentials: {
type: "object",
oneOf: [
{
title: "api key",
required: ["api_key"],
properties: {
api_key: {
type: "string"
}
}
},
{
title: "oauth",
required: ["redirect_uri"],
properties: {
redirect_uri: {
type: "string",
examples: ["https://api.hubspot.com/"]
}
}
}
]
}
}
},
{ "key.credentials": { selectedItem: "oauth" } },
undefined,
"key"
);

const expectedSchema = yup.object().shape({
credentials: yup.object().shape({
redirect_uri: yup.string().required("form.empty.error")
})
});

expect(JSON.stringify(yupSchema)).toEqual(JSON.stringify(expectedSchema));
});
16 changes: 11 additions & 5 deletions airbyte-webapp/src/core/jsonSchema/schemaToYup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@ import { WidgetConfigMap } from "../form/types";
* @param uiConfig uiConfig of widget currently selected in form
* @param parentSchema used in recursive schema building as required fields can be described in parentSchema
* @param propertyKey used in recursive schema building for building path for uiConfig
* @param propertyPath constracts path of property
*/

export const buildYupFormForJsonSchema = (
jsonSchema: JSONSchema7,
uiConfig?: WidgetConfigMap,
parentSchema?: JSONSchema7,
propertyKey?: string
propertyKey?: string,
propertyPath: string | undefined = propertyKey
): yup.Schema<any> => {
let schema:
| yup.NumberSchema
| yup.StringSchema
| yup.ObjectSchema
| null = null;

if (jsonSchema.oneOf && uiConfig && propertyKey) {
if (jsonSchema.oneOf && uiConfig && propertyPath) {
const selectedSchema =
jsonSchema.oneOf.find(condition => {
if (typeof condition !== "boolean") {
return uiConfig[propertyKey]?.selectedItem === condition.title;
return uiConfig[propertyPath]?.selectedItem === condition.title;
}
return false;
}) ?? jsonSchema.oneOf[0];
Expand All @@ -42,7 +44,8 @@ export const buildYupFormForJsonSchema = (
{ type: jsonSchema.type, ...selectedSchema },
uiConfig,
jsonSchema,
propertyKey
propertyKey,
propertyPath ? `${propertyPath}.${propertyKey}` : propertyKey
);
}
}
Expand Down Expand Up @@ -76,7 +79,10 @@ export const buildYupFormForJsonSchema = (
condition,
uiConfig,
jsonSchema,
propertyKey
propertyKey,
propertyPath
? `${propertyPath}.${propertyKey}`
: propertyKey
)
: yup.mixed()
])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,11 @@ const SourceStep: React.FC<IProps> = ({

setSourceId(sourceId);
};
const onSubmitForm = async (values: {
name: string;
serviceType: string;
}) => {
await onSubmit({
const onSubmitForm = async (values: { name: string; serviceType: string }) =>
onSubmit({
...values,
sourceDefinitionId: sourceDefinitionSpecification?.sourceDefinitionId
});
};

const errorMessage =
errorStatus === 0 ? null : errorStatus === 400 ? (
Expand Down

0 comments on commit 4f851a6

Please sign in to comment.