Skip to content

🪟 🔧 Move the serviceType prop out from Formik form (<ServiceForm/> refactoring part 2) #18168

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cf2b5b5
add ConnectorFormValues type
dizel852 Oct 19, 2022
92ce4bc
update useTestConnector
dizel852 Oct 19, 2022
2a190d6
update testConnector
dizel852 Oct 19, 2022
8897903
update serviceFormContext
dizel852 Oct 19, 2022
176cef3
useTestConnector - fix import
dizel852 Oct 19, 2022
c4ee73c
remove serviceType from ServiceForm
dizel852 Oct 19, 2022
59bb27d
handle setting the default connector name in ConnectorCard
dizel852 Oct 19, 2022
96439f6
move doc panel handling to ConnectorCard
dizel852 Oct 19, 2022
f1df51f
refactored ConnectorCard
dizel852 Oct 19, 2022
b7d55cf
update the usage of ConnectorCard
dizel852 Oct 19, 2022
2d4fd37
update the ServiceForm tests
dizel852 Oct 19, 2022
3d6fe3d
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Oct 19, 2022
f2a9e92
get rid of the term "service" from ConnectorCard and ConnectorService…
dizel852 Oct 26, 2022
4588f4c
rename ConnectorServiceTypeControl to ConnectorDefinitionTypeControl
dizel852 Oct 26, 2022
1da56c3
Rename "ServiceForm" to "ConnectorForm"
dizel852 Oct 26, 2022
53ce62c
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Oct 27, 2022
e328916
Rename "ServiceForm" to "ConnectorForm" tests
dizel852 Oct 27, 2022
8dc42ac
add issue link
dizel852 Oct 27, 2022
c931344
rename "ConnectorFormValues" to "ConnectorCardValues"
dizel852 Oct 27, 2022
97f9ba7
rename folder "ServiceForm" to "ConnectorForm"
dizel852 Oct 27, 2022
e5b4149
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Oct 27, 2022
da7ac94
rename "serviceFormContext" and it's usages to "connectorFormContext"
dizel852 Oct 27, 2022
8b8647a
rename type "ServiceFormValues" to "ConnectorFormValues"
dizel852 Oct 27, 2022
7a5773d
update connectorFormContext: rename "selectedConnector" to "selectedC…
dizel852 Oct 27, 2022
f70e1de
rename "selectedConnector" and "selectedService" to "selectedConnecto…
dizel852 Oct 27, 2022
73d87ae
leave comments to distinguish blocks of code
dizel852 Oct 27, 2022
0e7c761
reorder props
dizel852 Oct 27, 2022
89e0431
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Oct 28, 2022
3dc4247
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Oct 31, 2022
18f5b37
remove serviceType from useBuildForm startValues
dizel852 Oct 31, 2022
80a3b9d
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 1, 2022
19583a5
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 2, 2022
1c6c803
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 2, 2022
df70625
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 3, 2022
a78c2de
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 7, 2022
11156a9
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 7, 2022
e5dc205
Merge branch 'master' into vlad/18051-remove-servicetype-from-formik-…
dizel852 Nov 7, 2022
88dcb96
fixed broken import after merge
dizel852 Nov 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LogsRequestError } from "core/request/LogsRequestError";
import { useGetDestinationDefinitionSpecificationAsync } from "services/connector/DestinationDefinitionSpecificationService";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { FrequentlyUsedDestinations, StartWithDestination } from "views/Connector/ServiceForm";
import { ConnectorFormValues, FrequentlyUsedDestinations, StartWithDestination } from "views/Connector/ServiceForm";

import styles from "./DestinationForm.module.scss";

Expand Down Expand Up @@ -54,7 +54,7 @@ export const DestinationForm: React.FC<DestinationFormProps> = ({
setDestinationDefinitionId(destinationDefinitionId);
};

const onSubmitForm = async (values: { name: string; serviceType: string }) => {
const onSubmitForm = async (values: ConnectorFormValues) => {
onSubmit({
...values,
destinationDefinitionId: destinationDefinitionSpecification?.destinationDefinitionId,
Expand Down Expand Up @@ -85,7 +85,6 @@ export const DestinationForm: React.FC<DestinationFormProps> = ({
hasSuccess={hasSuccess}
errorMessage={errorMessage}
isLoading={isLoading}
formValues={destinationDefinitionId ? { serviceType: destinationDefinitionId } : undefined}
title={<FormattedMessage id="onboarding.destinationSetUp" />}
jobInfo={LogsRequestError.extractJobInfo(error)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { FormattedMessage } from "react-intl";

import DeleteBlock from "components/DeleteBlock";

import { ConnectionConfiguration } from "core/domain/connection";
import { Connector } from "core/domain/connector";
import { DestinationRead, WebBackendConnectionListItem } from "core/request/AirbyteClient";
import { useTrackPage, PageTrackingCodes } from "hooks/services/Analytics";
import { useFormChangeTrackerService, useUniqueFormId } from "hooks/services/FormChangeTracker";
import { useDeleteDestination, useUpdateDestination } from "hooks/services/useDestinationHook";
import { useDestinationDefinition } from "services/connector/DestinationDefinitionService";
import { useGetDestinationDefinitionSpecification } from "services/connector/DestinationDefinitionSpecificationService";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { ConnectorFormValues } from "views/Connector/ServiceForm";

import styles from "./DestinationSettings.module.scss";

Expand All @@ -33,11 +32,7 @@ const DestinationsSettings: React.FC<DestinationsSettingsProps> = ({

useTrackPage(PageTrackingCodes.DESTINATION_ITEM_SETTINGS);

const onSubmitForm = async (values: {
name: string;
serviceType: string;
connectionConfiguration?: ConnectionConfiguration;
}) => {
const onSubmitForm = async (values: ConnectorFormValues) => {
await updateDestination({
values,
destinationId: currentDestination.destinationId,
Expand All @@ -60,10 +55,6 @@ const DestinationsSettings: React.FC<DestinationsSettingsProps> = ({
onSubmit={onSubmitForm}
formType="destination"
availableServices={[destinationDefinition]}
formValues={{
...currentDestination,
serviceType: Connector.id(destinationDefinition),
}}
connector={currentDestination}
selectedConnectorDefinitionSpecification={destinationSpecification}
title={<FormattedMessage id="destination.destinationSettings" />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useGetDestinationDefinitionSpecificationAsync } from "services/connecto
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { useDocumentationPanelContext } from "views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext";
import { ConnectorFormValues } from "views/Connector/ServiceForm";

interface Props {
onNextStep: () => void;
Expand Down Expand Up @@ -67,7 +68,7 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {
setError(null);
setDestinationDefinitionId(destinationDefinitionId);
};
const onSubmitForm = async (values: { name: string; serviceType: string }) => {
const onSubmitForm = async (values: ConnectorFormValues) => {
await onSubmitDestinationStep({
...values,
destinationDefinitionId: destinationDefinitionSpecification?.destinationDefinitionId,
Expand All @@ -87,7 +88,6 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {
errorMessage={errorMessage}
selectedConnectorDefinitionSpecification={destinationDefinitionSpecification}
isLoading={isLoading}
formValues={destinationDefinitionId ? { serviceType: destinationDefinitionId } : undefined}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useGetSourceDefinitionSpecificationAsync } from "services/connector/Sou
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { useDocumentationPanelContext } from "views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext";
import { ConnectorFormValues } from "views/Connector/ServiceForm";

interface SourcesStepProps {
onSuccess: () => void;
Expand Down Expand Up @@ -71,7 +72,7 @@ const SourceStep: React.FC<SourcesStepProps> = ({ onNextStep, onSuccess }) => {
setSourceDefinitionId(sourceId);
};

const onSubmitForm = async (values: { name: string; serviceType: string }) =>
const onSubmitForm = async (values: ConnectorFormValues) =>
onSubmitSourceStep({
...values,
});
Expand All @@ -90,7 +91,6 @@ const SourceStep: React.FC<SourcesStepProps> = ({ onNextStep, onSuccess }) => {
errorMessage={errorMessage}
selectedConnectorDefinitionSpecification={sourceDefinitionSpecification}
isLoading={isLoading}
formValues={sourceDefinitionId ? { serviceType: sourceDefinitionId } : undefined}
/>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { SourceDefinitionReadWithLatestTag } from "services/connector/SourceDefi
import { useGetSourceDefinitionSpecificationAsync } from "services/connector/SourceDefinitionSpecificationService";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { ServiceFormValues } from "views/Connector/ServiceForm/types";
import { ConnectorFormValues } from "views/Connector/ServiceForm/types";

interface SourceFormProps {
onSubmit: (values: {
Expand Down Expand Up @@ -47,7 +47,7 @@ export const SourceForm: React.FC<SourceFormProps> = ({ onSubmit, sourceDefiniti
setSourceDefinitionId(sourceDefinitionId);
};

const onSubmitForm = (values: ServiceFormValues) => {
const onSubmitForm = (values: ConnectorFormValues) => {
onSubmit({
...values,
sourceDefinitionId: sourceDefinitionSpecification?.sourceDefinitionId,
Expand All @@ -67,7 +67,6 @@ export const SourceForm: React.FC<SourceFormProps> = ({ onSubmit, sourceDefiniti
fetchingConnectorError={sourceDefinitionError instanceof Error ? sourceDefinitionError : null}
errorMessage={errorMessage}
isLoading={isLoading}
formValues={sourceDefinitionId ? { serviceType: sourceDefinitionId, name: "" } : undefined}
title={<FormattedMessage id="onboarding.sourceSetUp" />}
jobInfo={LogsRequestError.extractJobInfo(error)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ const SourceSettings: React.FC<SourceSettingsProps> = ({ currentSource, connecti
formType="source"
connector={currentSource}
availableServices={[sourceDefinition]}
formValues={{
...currentSource,
serviceType: currentSource.sourceDefinitionId,
}}
selectedConnectorDefinitionSpecification={sourceDefinitionSpecification}
/>
<DeleteBlock type="source" onDelete={onDelete} />
Expand Down
84 changes: 65 additions & 19 deletions airbyte-webapp/src/views/Connector/ConnectorCard/ConnectorCard.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,51 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useMemo, useState } from "react";
import { FormattedMessage } from "react-intl";

import { JobItem } from "components/JobItem/JobItem";
import { Card } from "components/ui/Card";

import { Connector, ConnectorSpecification, ConnectorT } from "core/domain/connector";
import {
Connector,
ConnectorDefinition,
ConnectorDefinitionSpecification,
ConnectorSpecification,
ConnectorT,
} from "core/domain/connector";
import { SynchronousJobRead } from "core/request/AirbyteClient";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAdvancedModeSetting } from "hooks/services/useAdvancedModeSetting";
import { generateMessageFromError } from "utils/errorStatusMessage";
import { ServiceForm, ServiceFormProps, ServiceFormValues } from "views/Connector/ServiceForm";
import { ConnectorFormValues, ServiceForm, ServiceFormValues } from "views/Connector/ServiceForm";

import { useDocumentationPanelContext } from "../ConnectorDocumentationLayout/DocumentationPanelContext";
import { ConnectorServiceTypeControl } from "../ServiceForm/components/Controls/ConnectorServiceTypeControl";
import styles from "./ConnectorCard.module.scss";
import { useAnalyticsTrackFunctions } from "./useAnalyticsTrackFunctions";
import { useTestConnector } from "./useTestConnector";

type ConnectorCardProvidedProps = Omit<
ServiceFormProps,
"isKeyConnectionInProgress" | "isSuccess" | "onStopTesting" | "testConnector"
>;

interface ConnectorCardBaseProps extends ConnectorCardProvidedProps {
// TODO: need to clean up the ConnectorCard and ServiceForm props,
// since some of props are used in both components, and some of them used just as a prop-drill
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you create an issue for this, which captures why the current state is bad and what might be a better solution?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, here is it: #18553
I will add it to comment also

interface ConnectorCardBaseProps {
title?: React.ReactNode;
full?: boolean;
jobInfo?: SynchronousJobRead | null;
additionalSelectorComponent?: React.ReactNode;
onSubmit: (values: ConnectorFormValues) => Promise<void> | void;
onServiceSelect?: (id: string) => void;
availableServices: ConnectorDefinition[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While we're here changing things anyway, we should go ahead and try to get rid of the term "service" from all of these places.

It is confusing that this component and the ServiceForm component are the only places that refer to connectors and connector definitions as "services", so we should fix that. In this case, better names for these props would be onConnectorDefinitionSelect and availableConnectorDefinitions, to better match the terminology that we use for these objects throughout the rest of the Airbyte codebase.

Ideally we would also rename ServiceForm to something like ConnectorForm, and rename all related methods/variables/components as such.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also was thinking about that, but wasn't sure 😊
Ok, will fix that!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decided to try to rename all "service" related usages - got more modified files than I expected 😕
Good news - no "service" term mentions anymore 😊


// used in ConnectorCard and ServiceForm
formType: "source" | "destination";
selectedConnectorDefinitionSpecification?: ConnectorDefinitionSpecification;
isEditMode?: boolean;

// used in ServiceForm
formId?: string;
fetchingConnectorError?: Error | null;
errorMessage?: React.ReactNode;
successMessage?: React.ReactNode;
hasSuccess?: boolean;
isLoading?: boolean;
}

interface ConnectorCardCreateProps extends ConnectorCardBaseProps {
Expand All @@ -50,6 +70,7 @@ export const ConnectorCard: React.FC<ConnectorCardCreateProps | ConnectorCardEdi
const [isFormSubmitting, setIsFormSubmitting] = useState(false);
const [advancedMode] = useAdvancedModeSetting();

const { setDocumentationUrl, setDocumentationPanelOpen } = useDocumentationPanelContext();
const { testConnector, isTestConnectionInProgress, onStopTesting, error, reset } = useTestConnector(props);
const { trackTestConnectorFailure, trackTestConnectorSuccess, trackTestConnectorStarted } =
useAnalyticsTrackFunctions(props.formType);
Expand All @@ -60,26 +81,50 @@ export const ConnectorCard: React.FC<ConnectorCardCreateProps | ConnectorCardEdi
setErrorStatusRequest(null);
}, [props.selectedConnectorDefinitionSpecification, reset]);

const { selectedConnectorDefinitionSpecification, onServiceSelect, availableServices, isEditMode } = props;

const selectedConnectorDefinitionSpecificationId =
selectedConnectorDefinitionSpecification && ConnectorSpecification.id(selectedConnectorDefinitionSpecification);

const selectedService = useMemo(
() => availableServices.find((s) => Connector.id(s) === selectedConnectorDefinitionSpecificationId),
[availableServices, selectedConnectorDefinitionSpecificationId]
);

// Handle Doc panel
useEffect(() => {
if (!selectedService) {
return;
}

setDocumentationUrl(selectedService?.documentationUrl ?? "");
setDocumentationPanelOpen(true);
}, [selectedConnectorDefinitionSpecification, selectedService, setDocumentationPanelOpen, setDocumentationUrl]);

const onHandleSubmit = async (values: ServiceFormValues) => {
if (!selectedService) {
return;
}
setErrorStatusRequest(null);
setIsFormSubmitting(true);

const connector = props.availableServices.find((item) => Connector.id(item) === values.serviceType);
// combine the "ServiceFormValues" and serviceType to make "ConnectorFormValues"
const connectorFormValues: ConnectorFormValues = { ...values, serviceType: Connector.id(selectedService) };

const testConnectorWithTracking = async () => {
trackTestConnectorStarted(connector);
trackTestConnectorStarted(selectedService);
try {
await testConnector(values);
trackTestConnectorSuccess(connector);
await testConnector(connectorFormValues);
trackTestConnectorSuccess(selectedService);
} catch (e) {
trackTestConnectorFailure(connector);
trackTestConnectorFailure(selectedService);
throw e;
}
};

try {
await testConnectorWithTracking();
onSubmit(values);
onSubmit(connectorFormValues);
setSaved(true);
} catch (e) {
setErrorStatusRequest(e);
Expand All @@ -89,9 +134,8 @@ export const ConnectorCard: React.FC<ConnectorCardCreateProps | ConnectorCardEdi

const job = jobInfo || LogsRequestError.extractJobInfo(errorStatusRequest);

const { selectedConnectorDefinitionSpecification, onServiceSelect, availableServices, isEditMode } = props;
const selectedConnectorDefinitionSpecificationId =
selectedConnectorDefinitionSpecification && ConnectorSpecification.id(selectedConnectorDefinitionSpecification);
// Fill form with existing connector values otherwise set the default service name
const formValues = isEditMode ? props.connector : { name: selectedService?.name };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest we move the default name logic into the ServiceForm where the initialValues of the Formik context are actually calculated, so that we have all the "formik" values logic ideally inside the ServiceForm as much as possible and not passing those values from the outside.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable, and I also did a try:
The first thing which confuses me, we just replace one prop(formValues) with another dependency - connector.
And here is the place where the errors come:
Screenshot at Oct 28 01-20-44
Because of:

interface ConnectorCardCreateProps extends ConnectorCardBaseProps {
  isEditMode?: false;
}

interface ConnectorCardEditProps extends ConnectorCardBaseProps {
  isEditMode: true;
  connector: ConnectorT;
}

export const ConnectorCard: React.FC<ConnectorCardCreateProps | ConnectorCardEditProps>

Also did a try to pass the connector prop implicitly to <ServiceForm /> just for testing, and surprisingly, the tests start failing...

Should I continue digging into it?
Since the PR already has some changes out of the scope.


return (
<Card title={title} fullWidth={full}>
Expand All @@ -110,11 +154,13 @@ export const ConnectorCard: React.FC<ConnectorCardCreateProps | ConnectorCardEdi
<div>
<ServiceForm
{...props}
errorMessage={props.errorMessage || (error && generateMessageFromError(error))}
selectedService={selectedService}
isTestConnectionInProgress={isTestConnectionInProgress}
onStopTesting={onStopTesting}
testConnector={testConnector}
onSubmit={onHandleSubmit}
formValues={formValues}
errorMessage={props.errorMessage || (error && generateMessageFromError(error))}
successMessage={
props.successMessage || (saved && props.isEditMode && <FormattedMessage id="form.changesSaved" />)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useRef } from "react";

import { ConnectorHelper } from "core/domain/connector";
import { ConnectorT } from "core/domain/connector/types";
import { CheckConnectionRead } from "core/request/AirbyteClient";
import { CheckConnectorParams, useCheckConnector } from "hooks/services/useConnector";
import { useCurrentWorkspace } from "services/workspaces/WorkspacesService";
import { ServiceFormValues } from "views/Connector/ServiceForm";

import { CheckConnectionRead } from "../../../core/request/AirbyteClient";
import { ConnectorFormValues } from "../ServiceForm";

export const useTestConnector = (
props: {
Expand All @@ -21,7 +21,7 @@ export const useTestConnector = (
isTestConnectionInProgress: boolean;
isSuccess: boolean;
onStopTesting: () => void;
testConnector: (v?: ServiceFormValues) => Promise<CheckConnectionRead>;
testConnector: (v?: ConnectorFormValues) => Promise<CheckConnectionRead>;
error: Error | null;
reset: () => void;
} => {
Expand Down
Loading