Skip to content

Commit

Permalink
🪟 🐛 Fix OAuth validation not allowing to create source or destination (
Browse files Browse the repository at this point in the history
…#14197)

* Enable "Set up source/destination" button only if the form is valid

* Update how ServiceForm initial values are patched so that it correctly patches the configuration with default values

* Update initial values patching in service form to use initialValues to preserve already set values
Update useOAuthFlowAdapter to correctly merge the values from the oauth response

* Remove unused values var from ServiceForm
  • Loading branch information
edmundito authored Jun 30, 2022
1 parent dd4079f commit cfea528
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const FormRoot: React.FC<FormRootProps> = ({
isLoadSchema={isLoadingSchema}
fetchingConnectorError={fetchingConnectorError}
hasSuccess={hasSuccess}
isValid={isValid}
/>
)}
</FormContainer>
Expand Down
41 changes: 19 additions & 22 deletions airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Formik, getIn, setIn, useFormikContext } from "formik";
import { JSONSchema7 } from "json-schema";
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useToggle } from "react-use";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useDeepCompareEffect, useToggle } from "react-use";

import { FormChangeTracker } from "components/FormChangeTracker";

Expand All @@ -13,7 +13,6 @@ import { useFormChangeTrackerService, useUniqueFormId } from "hooks/services/For
import { isDefined } from "utils/common";
import RequestConnectorModal from "views/Connector/RequestConnectorModal";

import { ConnectionConfiguration } from "../../../core/domain/connection";
import { CheckConnectionRead } from "../../../core/request/AirbyteClient";
import { useDocumentationPanelContext } from "../ConnectorDocumentationLayout/DocumentationPanelContext";
import { ConnectorNameControl } from "./components/Controls/ConnectorNameControl";
Expand Down Expand Up @@ -41,31 +40,28 @@ const FormikPatch: React.FC = () => {
*/
const PatchInitialValuesWithWidgetConfig: React.FC<{
schema: JSONSchema7;
}> = ({ schema }) => {
initialValues: ServiceFormValues;
}> = ({ schema, initialValues }) => {
const { widgetsInfo } = useServiceForm();
const { values, resetForm } = useFormikContext<ServiceFormValues>();
const { setFieldValue } = useFormikContext<ServiceFormValues>();

const valueRef = useRef<ConnectionConfiguration>();
valueRef.current = values.connectionConfiguration;
useDeepCompareEffect(() => {
const widgetsInfoEntries = Object.entries(widgetsInfo);

useEffect(() => {
// set all const fields to form field values, so we could send form
const constPatchedValues = Object.entries(widgetsInfo)
.filter(([_, v]) => isDefined(v.const))
.reduce((acc, [k, v]) => setIn(acc, k, v.const), valueRef.current);
const patchedConstValues = widgetsInfoEntries
.filter(([_, value]) => isDefined(value.const))
.reduce((acc, [key, value]) => setIn(acc, key, value.const), initialValues);

// set default fields as current values, so values could be populated correctly
// fix for https://github.com/airbytehq/airbyte/issues/6791
const defaultPatchedValues = Object.entries(widgetsInfo)
.filter(([k, v]) => isDefined(v.default) && !isDefined(getIn(constPatchedValues, k)))
.reduce((acc, [k, v]) => setIn(acc, k, v.default), constPatchedValues);

resetForm({
values: {
...values,
connectionConfiguration: defaultPatchedValues,
},
});
const patchedDefaultValues = widgetsInfoEntries
.filter(([key, value]) => isDefined(value.default) && !isDefined(getIn(patchedConstValues, key)))
.reduce((acc, [key, value]) => setIn(acc, key, value.default), patchedConstValues);

if (patchedDefaultValues?.connectionConfiguration) {
setFieldValue("connectionConfiguration", patchedDefaultValues.connectionConfiguration);
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [schema]);
Expand Down Expand Up @@ -237,6 +233,7 @@ const ServiceForm: React.FC<ServiceFormProps> = (props) => {
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={onFormSubmit}
enableReinitialize
>
{({ dirty }) => (
<ServiceFormContextProvider
Expand All @@ -252,7 +249,7 @@ const ServiceForm: React.FC<ServiceFormProps> = (props) => {
{!props.isEditMode && <SetDefaultName />}
<FormikPatch />
<FormChangeTracker changed={dirty} formId={formId} />
<PatchInitialValuesWithWidgetConfig schema={jsonSchema} />
<PatchInitialValuesWithWidgetConfig schema={jsonSchema} initialValues={initialValues} />
<FormRoot
{...props}
errorMessage={props.errorMessage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { TestingConnectionError, FetchingConnectorError } from "./TestingConnect
import TestingConnectionSpinner from "./TestingConnectionSpinner";
import TestingConnectionSuccess from "./TestingConnectionSuccess";

interface IProps {
interface CreateControlProps {
formType: "source" | "destination";
isSubmitting: boolean;
errorMessage?: React.ReactNode;
Expand All @@ -18,6 +18,7 @@ interface IProps {

isTestConnectionInProgress: boolean;
onCancelTesting?: () => void;
isValid: boolean;
}

const ButtonContainer = styled.div`
Expand All @@ -31,7 +32,7 @@ const SubmitButton = styled(Button)`
margin-left: auto;
`;

const CreateControls: React.FC<IProps> = ({
const CreateControls: React.FC<CreateControlProps> = ({
isTestConnectionInProgress,
isSubmitting,
formType,
Expand All @@ -40,6 +41,7 @@ const CreateControls: React.FC<IProps> = ({
fetchingConnectorError,
isLoadSchema,
onCancelTesting,
isValid,
}) => {
if (isSubmitting) {
return <TestingConnectionSpinner isCancellable={isTestConnectionInProgress} onCancelTesting={onCancelTesting} />;
Expand All @@ -53,7 +55,7 @@ const CreateControls: React.FC<IProps> = ({
<ButtonContainer>
{errorMessage && !fetchingConnectorError && <TestingConnectionError errorMessage={errorMessage} />}
{fetchingConnectorError && <FetchingConnectorError />}
<SubmitButton type="submit" disabled={isLoadSchema}>
<SubmitButton type="submit" disabled={isLoadSchema || !isValid}>
<FormattedMessage id={`onboarding.${formType}SetUp.buttonText`} />
</SubmitButton>
</ButtonContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function useFormikOauthAdapter(connector: ConnectorDefinitionSpecification): {
);
} else {
newValues = merge(values, {
connectionConfiguration: completeOauthResponse,
connectionConfiguration: { credentials: completeOauthResponse },
});
}

Expand Down

0 comments on commit cfea528

Please sign in to comment.