diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/FormRoot.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/FormRoot.tsx index 4da0ad1161f0..3bbbb5c88126 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/FormRoot.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/FormRoot.tsx @@ -47,9 +47,8 @@ const FormRoot: React.FC = ({ hasSuccess, onStopTestingConnector, }) => { - const { resetForm, dirty, isSubmitting, isValid } = useFormikContext(); - - const { resetUiFormProgress, isLoadingSchema, selectedService, isEditMode, formType } = useServiceForm(); + const { dirty, isSubmitting, isValid } = useFormikContext(); + const { resetServiceForm, isLoadingSchema, selectedService, isEditMode, formType } = useServiceForm(); return ( @@ -70,12 +69,11 @@ const FormRoot: React.FC = ({ isSubmitting={isSubmitting || isTestConnectionInProgress} errorMessage={errorMessage} formType={formType} - onRetest={onRetest} + onRetestClick={onRetest} isValid={isValid} dirty={dirty} - resetForm={() => { - resetForm(); - resetUiFormProgress(); + onCancelClick={() => { + resetServiceForm(); }} successMessage={successMessage} /> diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx index f8e858a447be..55edeef9d0cb 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/ServiceForm.tsx @@ -204,7 +204,11 @@ const ServiceForm: React.FC = (props) => { [formType, props.onServiceSelect, props.availableServices, props.isEditMode, toggleOpenRequestModal] ); - const { uiWidgetsInfo, setUiWidgetsInfo } = useBuildUiWidgetsContext(formFields, initialValues, uiOverrides); + const { uiWidgetsInfo, setUiWidgetsInfo, resetUiWidgetsInfo } = useBuildUiWidgetsContext( + formFields, + initialValues, + uiOverrides + ); const validationSchema = useConstructValidationSchema(jsonSchema, uiWidgetsInfo); @@ -240,6 +244,7 @@ const ServiceForm: React.FC = (props) => { widgetsInfo={uiWidgetsInfo} getValues={getValues} setUiWidgetsInfo={setUiWidgetsInfo} + resetUiWidgetsInfo={resetUiWidgetsInfo} formType={formType} selectedConnector={selectedConnectorDefinitionSpecification} availableServices={props.availableServices} diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/components/EditControls.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/components/EditControls.tsx index 70050bf5ad6c..a1b3e412192f 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/components/EditControls.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/components/EditControls.tsx @@ -25,8 +25,8 @@ interface IProps { isSubmitting: boolean; isValid: boolean; dirty: boolean; - resetForm: () => void; - onRetest?: () => void; + onCancelClick: () => void; + onRetestClick?: () => void; onCancelTesting?: () => void; isTestConnectionInProgress?: boolean; successMessage?: React.ReactNode; @@ -38,9 +38,9 @@ const EditControls: React.FC = ({ isTestConnectionInProgress, isValid, dirty, - resetForm, + onCancelClick, formType, - onRetest, + onRetestClick, successMessage, errorMessage, onCancelTesting, @@ -51,7 +51,7 @@ const EditControls: React.FC = ({ return ; } - const showStatusMessage = () => { + const renderStatusMessage = () => { if (errorMessage) { return ; } @@ -63,7 +63,7 @@ const EditControls: React.FC = ({ return ( <> - {showStatusMessage()} + {renderStatusMessage()}
-
- {onRetest && ( - )} diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/serviceFormContext.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/serviceFormContext.tsx index 85e4a17b57b1..bd50e851d33e 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/serviceFormContext.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/serviceFormContext.tsx @@ -8,7 +8,7 @@ import { FeatureItem, useFeature } from "hooks/services/Feature"; import { ServiceFormValues } from "./types"; import { makeConnectionConfigurationPath, serverProvidedOauthPaths } from "./utils"; -interface Context { +interface ServiceFormContext { formType: "source" | "destination"; getValues: (values: ServiceFormValues) => ServiceFormValues; widgetsInfo: WidgetConfigMap; @@ -16,7 +16,7 @@ interface Context { unfinishedFlows: Record; addUnfinishedFlow: (key: string, info?: Record) => void; removeUnfinishedFlow: (key: string) => void; - resetUiFormProgress: () => void; + resetServiceForm: () => void; selectedService?: ConnectorDefinition; selectedConnector?: ConnectorDefinitionSpecification; isLoadingSchema?: boolean; @@ -25,37 +25,41 @@ interface Context { authFieldsToHide: string[]; } -const FormWidgetContext = React.createContext(null); +const serviceFormContext = React.createContext(null); -const useServiceForm = (): Context => { - const serviceFormHelpers = useContext(FormWidgetContext); +export const useServiceForm = (): ServiceFormContext => { + const serviceFormHelpers = useContext(serviceFormContext); if (!serviceFormHelpers) { throw new Error("useServiceForm should be used within ServiceFormContextProvider"); } return serviceFormHelpers; }; -const ServiceFormContextProvider: React.FC<{ +interface ServiceFormContextProviderProps { widgetsInfo: WidgetConfigMap; setUiWidgetsInfo: (path: string, value: Record) => void; + resetUiWidgetsInfo: () => void; formType: "source" | "destination"; isLoadingSchema?: boolean; isEditMode?: boolean; availableServices: ConnectorDefinition[]; getValues: (values: ServiceFormValues) => ServiceFormValues; selectedConnector?: ConnectorDefinitionSpecification; -}> = ({ +} + +export const ServiceFormContextProvider: React.FC = ({ availableServices, children, widgetsInfo, setUiWidgetsInfo, + resetUiWidgetsInfo, selectedConnector, getValues, formType, isLoadingSchema, isEditMode, }) => { - const { values } = useFormikContext(); + const { values, resetForm } = useFormikContext(); const allowOAuthConnector = useFeature(FeatureItem.AllowOAuthConnector); const { serviceType } = values; @@ -81,7 +85,7 @@ const ServiceFormContextProvider: React.FC<{ [selectedConnector] ); - const ctx = useMemo(() => { + const ctx = useMemo(() => { const unfinishedFlows = widgetsInfo["_common.unfinishedFlows"] ?? {}; return { widgetsInfo, @@ -105,7 +109,10 @@ const ServiceFormContextProvider: React.FC<{ "_common.unfinishedFlows", Object.fromEntries(Object.entries(unfinishedFlows).filter(([key]) => key !== path)) ), - resetUiFormProgress: () => setUiWidgetsInfo("_common.unfinishedFlows", {}), + resetServiceForm: () => { + resetForm(); + resetUiWidgetsInfo(); + }, }; }, [ widgetsInfo, @@ -118,9 +125,9 @@ const ServiceFormContextProvider: React.FC<{ formType, isLoadingSchema, isEditMode, + resetForm, + resetUiWidgetsInfo, ]); - return {children}; + return {children}; }; - -export { useServiceForm, ServiceFormContextProvider }; diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/useBuildForm.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/useBuildForm.tsx index d33214db2c30..1dcd6660a50a 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/useBuildForm.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/useBuildForm.tsx @@ -42,7 +42,7 @@ function upgradeSchemaLegacyAuth( ); } -function useBuildInitialSchema( +export function useBuildInitialSchema( connectorSpecification?: ConnectorDefinitionSpecification ): JSONSchema7Definition | undefined { const allowOAuthConnector = useFeature(FeatureItem.AllowOAuthConnector); @@ -61,13 +61,12 @@ function useBuildInitialSchema( }, [allowOAuthConnector, connectorSpecification]); } -function useBuildForm( - jsonSchema: JSONSchema7, - initialValues?: Partial -): { +export interface BuildFormHook { initialValues: ServiceFormValues; formFields: FormBlock; -} { +} + +export function useBuildForm(jsonSchema: JSONSchema7, initialValues?: Partial): BuildFormHook { const startValues = useMemo( () => ({ name: "", @@ -86,14 +85,17 @@ function useBuildForm( }; } -const useBuildUiWidgetsContext = ( +interface BuildUiWidgetsContextHook { + uiWidgetsInfo: WidgetConfigMap; + setUiWidgetsInfo: (widgetId: string, updatedValues: WidgetConfig) => void; + resetUiWidgetsInfo: () => void; +} + +export const useBuildUiWidgetsContext = ( formFields: FormBlock[] | FormBlock, formValues: ServiceFormValues, uiOverrides?: WidgetConfigMap -): { - uiWidgetsInfo: WidgetConfigMap; - setUiWidgetsInfo: (widgetId: string, updatedValues: WidgetConfig) => void; -} => { +): BuildUiWidgetsContextHook => { const [overriddenWidgetState, setUiWidgetsInfo] = useState(uiOverrides ?? {}); // As schema is dynamic, it is possible, that new updated values, will differ from one stored. @@ -111,17 +113,22 @@ const useBuildUiWidgetsContext = ( [mergedState, setUiWidgetsInfo] ); + const resetUiWidgetsInfo = useCallback(() => { + setUiWidgetsInfo(uiOverrides ?? {}); + }, [uiOverrides]); + return { uiWidgetsInfo: mergedState, setUiWidgetsInfo: setUiWidgetsInfoSubState, + resetUiWidgetsInfo, }; }; // As validation schema depends on what path of oneOf is currently selected in jsonschema -const useConstructValidationSchema = (jsonSchema: JSONSchema7, uiWidgetsInfo: WidgetConfigMap): AnySchema => +export const useConstructValidationSchema = (jsonSchema: JSONSchema7, uiWidgetsInfo: WidgetConfigMap): AnySchema => useMemo(() => buildYupFormForJsonSchema(jsonSchema, uiWidgetsInfo), [uiWidgetsInfo, jsonSchema]); -const usePatchFormik = (): void => { +export const usePatchFormik = (): void => { const { setFieldTouched, isSubmitting, isValidating, validationSchema, validateForm, errors } = useFormikContext(); // Formik doesn't validate values again, when validationSchema was changed on the fly. useEffect(() => { @@ -148,5 +155,3 @@ const usePatchFormik = (): void => { } }, [errors, isSubmitting, isValidating, setFieldTouched]); }; - -export { useBuildForm, useBuildInitialSchema, useBuildUiWidgetsContext, useConstructValidationSchema, usePatchFormik };