Skip to content

Commit

Permalink
Misc Improvements to assist Connection Form Refactor (#16303)
Browse files Browse the repository at this point in the history
* Move exports to declaration for formConfig

* Add ConnectionOrPartialConnection, move ConnectionForm exports

* Removing additionBottomControls as it was unused

* Create and use FormError, test createFormErrorMessage

* Remove unnecessary eslint ignore, remove unnecessary async/await

* rename createFormErrorMessage
  • Loading branch information
krishnaglick committed Sep 7, 2022
1 parent 42c5265 commit a686508
Show file tree
Hide file tree
Showing 16 changed files with 102 additions and 106 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { faRedoAlt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { Suspense, useMemo } from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components";

import { Button, ContentCard } from "components";
import { IDataItem } from "components/base/DropDown/components/Option";
Expand All @@ -13,25 +12,14 @@ import { Action, Namespace } from "core/analytics";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics";
import { useCreateConnection, ValuesProps } from "hooks/services/useConnectionHook";
import ConnectionForm from "views/Connection/ConnectionForm";
import { ConnectionFormProps } from "views/Connection/ConnectionForm/ConnectionForm";
import { ConnectionForm, ConnectionFormProps } from "views/Connection/ConnectionForm";

import { DestinationRead, SourceRead, WebBackendConnectionRead } from "../../core/request/AirbyteClient";
import { useDiscoverSchema } from "../../hooks/services/useSourceHook";
import TryAfterErrorBlock from "./components/TryAfterErrorBlock";
import styles from "./CreateConnectionContent.module.scss";

const SkipButton = styled.div`
margin-top: 6px;
& > button {
min-width: 239px;
margin-left: 9px;
}
`;

interface CreateConnectionContentProps {
additionBottomControls?: React.ReactNode;
source: SourceRead;
destination: DestinationRead;
afterSubmitConnection?: (connection: WebBackendConnectionRead) => void;
Expand All @@ -41,7 +29,6 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
source,
destination,
afterSubmitConnection,
additionBottomControls,
}) => {
const { mutateAsync: createConnection } = useCreateConnection();
const analyticsService = useAnalyticsService();
Expand Down Expand Up @@ -104,10 +91,7 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
const job = LogsRequestError.extractJobInfo(schemaErrorStatus);
return (
<ContentCard>
<TryAfterErrorBlock
onClick={onDiscoverSchema}
additionControl={<SkipButton>{additionBottomControls}</SkipButton>}
/>
<TryAfterErrorBlock onClick={onDiscoverSchema} />
{job && <JobItem job={job} />}
</ContentCard>
);
Expand All @@ -120,7 +104,6 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
<ConnectionForm
mode="create"
connection={connection}
additionBottomControls={additionBottomControls}
onDropDownSelect={onSelectFrequency}
onSubmit={onSubmitConnectionStep}
additionalSchemaControl={
Expand Down
11 changes: 4 additions & 7 deletions airbyte-webapp/src/hooks/services/useSourceHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,12 @@ const useDiscoverSchema = (
} finally {
setIsLoading(false);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [sourceId]);
}, [disableCache, service, sourceId]);

useEffect(() => {
(async () => {
if (sourceId) {
await onDiscoverSchema();
}
})();
if (sourceId) {
onDiscoverSchema();
}
}, [onDiscoverSchema, sourceId]);

return { schemaErrorStatus, isLoading, schema, catalogId, onDiscoverSchema };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ import {
} from "hooks/services/useConnectionHook";
import { equal } from "utils/objects";
import { CatalogDiffModal } from "views/Connection/CatalogDiffModal/CatalogDiffModal";
import ConnectionForm from "views/Connection/ConnectionForm";
import { ConnectionFormSubmitResult } from "views/Connection/ConnectionForm/ConnectionForm";
import { ConnectionForm, ConnectionFormSubmitResult } from "views/Connection/ConnectionForm";

interface ReplicationViewProps {
onAfterSaveSchema: () => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics";
import useRouter from "hooks/useRouter";
import { useGetDestinationDefinitionSpecificationAsync } from "services/connector/DestinationDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";

interface DestinationFormProps {
Expand All @@ -21,7 +21,7 @@ interface DestinationFormProps {
afterSelectConnector?: () => void;
destinationDefinitions: DestinationDefinitionRead[];
hasSuccess?: boolean;
error?: { message?: string; status?: number } | null;
error?: FormError | null;
}

const hasDestinationDefinitionId = (state: unknown): state is { destinationDefinitionId: string } => {
Expand Down Expand Up @@ -75,7 +75,7 @@ export const DestinationForm: React.FC<DestinationFormProps> = ({
});
};

const errorMessage = error ? createFormErrorMessage(error) : null;
const errorMessage = error ? generateMessageFromError(error) : null;

return (
<ConnectorCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ import React, { useEffect, useState } from "react";

import { Action, Namespace } from "core/analytics";
import { ConnectionConfiguration } from "core/domain/connection";
import { JobInfo } from "core/domain/job";
import { useAnalyticsService } from "hooks/services/Analytics";
import { useCreateDestination } from "hooks/services/useDestinationHook";
import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService";
import { useGetDestinationDefinitionSpecificationAsync } from "services/connector/DestinationDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { useDocumentationPanelContext } from "views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext";

Expand All @@ -23,11 +22,7 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {
useGetDestinationDefinitionSpecificationAsync(destinationDefinitionId);
const { destinationDefinitions } = useDestinationDefinitionList();
const [successRequest, setSuccessRequest] = useState(false);
const [error, setError] = useState<{
status: number;
response: JobInfo;
message: string;
} | null>(null);
const [error, setError] = useState<FormError | null>(null);

const { mutateAsync: createDestination } = useCreateDestination();

Expand Down Expand Up @@ -89,7 +84,7 @@ const DestinationStep: React.FC<Props> = ({ onNextStep, onSuccess }) => {
});
};

const errorMessage = error ? createFormErrorMessage(error) : null;
const errorMessage = error ? generateMessageFromError(error) : null;

return (
<ConnectorCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import React, { useEffect, useState } from "react";

import { Action, Namespace } from "core/analytics";
import { ConnectionConfiguration } from "core/domain/connection";
import { JobInfo } from "core/domain/job";
import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics";
import { useCreateSource } from "hooks/services/useSourceHook";
import { useSourceDefinitionList } from "services/connector/SourceDefinitionService";
import { useGetSourceDefinitionSpecificationAsync } from "services/connector/SourceDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { useDocumentationPanelContext } from "views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext";

Expand All @@ -21,11 +20,7 @@ const SourceStep: React.FC<SourcesStepProps> = ({ onNextStep, onSuccess }) => {
const { sourceDefinitions } = useSourceDefinitionList();
const [sourceDefinitionId, setSourceDefinitionId] = useState<string | null>(null);
const [successRequest, setSuccessRequest] = useState(false);
const [error, setError] = useState<{
status: number;
response: JobInfo;
message: string;
} | null>(null);
const [error, setError] = useState<FormError | null>(null);

const { setDocumentationUrl, setDocumentationPanelOpen } = useDocumentationPanelContext();
const { mutateAsync: createSource } = useCreateSource();
Expand Down Expand Up @@ -91,7 +86,7 @@ const SourceStep: React.FC<SourcesStepProps> = ({ onNextStep, onSuccess }) => {
...values,
});

const errorMessage = error ? createFormErrorMessage(error) : "";
const errorMessage = error ? generateMessageFromError(error) : "";

return (
<ConnectorCard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useAnalyticsService } from "hooks/services/Analytics";
import useRouter from "hooks/useRouter";
import { SourceDefinitionReadWithLatestTag } from "services/connector/SourceDefinitionService";
import { useGetSourceDefinitionSpecificationAsync } from "services/connector/SourceDefinitionSpecificationService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { generateMessageFromError, FormError } from "utils/errorStatusMessage";
import { ConnectorCard } from "views/Connector/ConnectorCard";
import { ServiceFormValues } from "views/Connector/ServiceForm/types";

Expand All @@ -22,7 +22,7 @@ interface SourceFormProps {
afterSelectConnector?: () => void;
sourceDefinitions: SourceDefinitionReadWithLatestTag[];
hasSuccess?: boolean;
error?: { message?: string; status?: number } | null;
error?: FormError | null;
}

const hasSourceDefinitionId = (state: unknown): state is { sourceDefinitionId: string } => {
Expand Down Expand Up @@ -76,7 +76,7 @@ export const SourceForm: React.FC<SourceFormProps> = ({
});
};

const errorMessage = error ? createFormErrorMessage(error) : null;
const errorMessage = error ? generateMessageFromError(error) : null;

return (
<ConnectorCard
Expand Down
35 changes: 35 additions & 0 deletions airbyte-webapp/src/utils/errorStatusMessage.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { generateMessageFromError, FormError } from "./errorStatusMessage";

describe("#errorStatusMessage", () => {
it("should return a provided error message", () => {
const errMsg = "test";
expect(generateMessageFromError(new Error(errMsg))).toBe(errMsg);
});

it("should return null if no error message and no status, or status is 0", () => {
expect(generateMessageFromError(new Error())).toBe(null);
const fakeStatusError = new FormError();
fakeStatusError.status = 0;
expect(generateMessageFromError(fakeStatusError)).toBe(null);
});

it("should return a validation error message if status is 400", () => {
const fakeStatusError = new FormError();
fakeStatusError.status = 400;
expect(generateMessageFromError(fakeStatusError)).toMatchInlineSnapshot(`
<Memo(MemoizedFormattedMessage)
id="form.validationError"
/>
`);
});

it("should return a 'some error' message if status is > 0 and not 400", () => {
const fakeStatusError = new FormError();
fakeStatusError.status = 401;
expect(generateMessageFromError(fakeStatusError)).toMatchInlineSnapshot(`
<Memo(MemoizedFormattedMessage)
id="form.someError"
/>
`);
});
});
6 changes: 5 additions & 1 deletion airbyte-webapp/src/utils/errorStatusMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { FormattedMessage } from "react-intl";

export const createFormErrorMessage = (error: { status?: number; message?: string }): JSX.Element | string | null => {
export class FormError extends Error {
status?: number;
}

export const generateMessageFromError = (error: FormError): JSX.Element | string | null => {
if (error.message) {
return error.message;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import { ConfirmationModalService } from "hooks/services/ConfirmationModal/ConfirmationModalService";
import { render } from "utils/testutils";

import ConnectionForm, { ConnectionFormProps } from "./ConnectionForm";
import { ConnectionForm, ConnectionFormProps } from "./ConnectionForm";

const mockSource: SourceRead = {
sourceId: "test-source",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { useFormChangeTrackerService, useUniqueFormId } from "hooks/services/FormChangeTracker";
import { useGetDestinationDefinitionSpecification } from "services/connector/DestinationDefinitionSpecificationService";
import { useCurrentWorkspace } from "services/workspaces/WorkspacesService";
import { createFormErrorMessage } from "utils/errorStatusMessage";
import { generateMessageFromError } from "utils/errorStatusMessage";

import CreateControls from "./components/CreateControls";
import EditControls from "./components/EditControls";
Expand Down Expand Up @@ -118,10 +118,13 @@ const DirtyChangeTracker: React.FC<DirtyChangeTrackerProps> = ({ dirty, onChange
return null;
};

interface ConnectionFormProps {
export type ConnectionOrPartialConnection =
| WebBackendConnectionRead
| (Partial<WebBackendConnectionRead> & Pick<WebBackendConnectionRead, "syncCatalog" | "source" | "destination">);

export interface ConnectionFormProps {
onSubmit: (values: ConnectionFormValues) => Promise<ConnectionFormSubmitResult | void>;
className?: string;
additionBottomControls?: React.ReactNode;
successMessage?: React.ReactNode;
onDropDownSelect?: (item: DropDownRow.IDataItem) => void;
onCancel?: () => void;
Expand All @@ -132,19 +135,16 @@ interface ConnectionFormProps {
mode: ConnectionFormMode;
additionalSchemaControl?: React.ReactNode;

connection:
| WebBackendConnectionRead
| (Partial<WebBackendConnectionRead> & Pick<WebBackendConnectionRead, "syncCatalog" | "source" | "destination">);
connection: ConnectionOrPartialConnection;
}

const ConnectionForm: React.FC<ConnectionFormProps> = ({
export const ConnectionForm: React.FC<ConnectionFormProps> = ({
onSubmit,
onCancel,
className,
onDropDownSelect,
mode,
successMessage,
additionBottomControls,
canSubmitUntouchedForm,
additionalSchemaControl,
connection,
Expand Down Expand Up @@ -194,7 +194,7 @@ const ConnectionForm: React.FC<ConnectionFormProps> = ({
[connection.operations, workspace.workspaceId, onSubmit, clearFormChange, formId]
);

const errorMessage = submitError ? createFormErrorMessage(submitError) : null;
const errorMessage = submitError ? generateMessageFromError(submitError) : null;
const frequencies = useFrequencyDropdownData(connection.scheduleData);

return (
Expand Down Expand Up @@ -373,7 +373,6 @@ const ConnectionForm: React.FC<ConnectionFormProps> = ({
onEndEditTransformation={toggleEditingTransformation}
/>
<CreateControls
additionBottomControls={additionBottomControls}
isSubmitting={isSubmitting}
isValid={isValid && !editingTransformation}
errorMessage={
Expand All @@ -387,6 +386,3 @@ const ConnectionForm: React.FC<ConnectionFormProps> = ({
</Formik>
);
};

export type { ConnectionFormProps };
export default ConnectionForm;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ interface CreateControlsProps {
isSubmitting: boolean;
isValid: boolean;
errorMessage?: React.ReactNode;
additionBottomControls?: React.ReactNode;
}

const ButtonContainer = styled.div`
Expand Down Expand Up @@ -59,12 +58,7 @@ const ErrorText = styled.div`
max-width: 400px;
`;

const CreateControls: React.FC<CreateControlsProps> = ({
isSubmitting,
errorMessage,
additionBottomControls,
isValid,
}) => {
const CreateControls: React.FC<CreateControlsProps> = ({ isSubmitting, errorMessage, isValid }) => {
if (isSubmitting) {
return (
<LoadingContainer>
Expand All @@ -90,7 +84,6 @@ const CreateControls: React.FC<CreateControlsProps> = ({
<div />
)}
<div>
{additionBottomControls || null}
<Button type="submit" disabled={isSubmitting || !isValid}>
<FormattedMessage id="onboarding.setUpConnection" />
</Button>
Expand Down

0 comments on commit a686508

Please sign in to comment.