Skip to content
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

🪟Persist unsaved changes on schema refresh #13895

Merged
merged 6 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
@@ -1,6 +1,6 @@
import { faRedoAlt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { Suspense, useMemo } from "react";
import React, { Suspense, useMemo, useState } from "react";
import { FormattedMessage } from "react-intl";
import styled from "styled-components";

Expand All @@ -13,6 +13,7 @@ import { LogsRequestError } from "core/request/LogsRequestError";
import { useAnalyticsService } from "hooks/services/Analytics/useAnalyticsService";
import { useCreateConnection, ValuesProps } from "hooks/services/useConnectionHook";
import ConnectionForm from "views/Connection/ConnectionForm";
import { FormikConnectionFormValues } from "views/Connection/ConnectionForm/formConfig";

import { DestinationRead, SourceRead, WebBackendConnectionRead } from "../../core/request/AirbyteClient";
import { useDiscoverSchema } from "../../hooks/services/useSourceHook";
Expand Down Expand Up @@ -52,15 +53,23 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({

const { schema, isLoading, schemaErrorStatus, catalogId, onDiscoverSchema } = useDiscoverSchema(source.sourceId);

const [connectionFormValues, setConnectionFormValues] = useState<FormikConnectionFormValues>();

const connection = useMemo(
() => ({
name: connectionFormValues?.name ?? "",
namespaceDefinition: connectionFormValues?.namespaceDefinition,
namespaceFormat: connectionFormValues?.namespaceFormat,
prefix: connectionFormValues?.prefix,
schedule: connectionFormValues?.schedule,
syncCatalog: schema,
destination,
source,
catalogId,
}),
[schema, destination, source, catalogId]
[connectionFormValues, schema, destination, source, catalogId]
);
console.log(connection.schedule);
teallarson marked this conversation as resolved.
Show resolved Hide resolved

const onSubmitConnectionStep = async (values: ValuesProps) => {
const connection = await createConnection({
Expand Down Expand Up @@ -126,6 +135,7 @@ const CreateConnectionContent: React.FC<CreateConnectionContentProps> = ({
</Button>
}
onSubmit={onSubmitConnectionStep}
onChangeValues={setConnectionFormValues}
/>
</Suspense>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { faSyncAlt } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FormikHelpers } from "formik";
import React, { useState } from "react";
import React, { useMemo, useState } from "react";
import { FormattedMessage } from "react-intl";
import { useAsyncFn } from "react-use";
import styled from "styled-components";
Expand All @@ -20,6 +20,7 @@ import {
} from "hooks/services/useConnectionHook";
import { equal } from "utils/objects";
import ConnectionForm from "views/Connection/ConnectionForm";
import { FormikConnectionFormValues } from "views/Connection/ConnectionForm/formConfig";

interface ReplicationViewProps {
onAfterSaveSchema: () => void;
Expand Down Expand Up @@ -52,6 +53,7 @@ export const ReplicationView: React.FC<ReplicationViewProps> = ({ onAfterSaveSch
const { openConfirmationModal, closeConfirmationModal } = useConfirmationModalService();
const [activeUpdatingSchemaMode, setActiveUpdatingSchemaMode] = useState(false);
const [saved, setSaved] = useState(false);
const [connectionFormValues, setConnectionFormValues] = useState<FormikConnectionFormValues>();

const { mutateAsync: updateConnection } = useUpdateConnection();
const { mutateAsync: resetConnection } = useResetConnection();
Expand All @@ -65,7 +67,24 @@ export const ReplicationView: React.FC<ReplicationViewProps> = ({ onAfterSaveSch
[connectionId]
);

const connection = activeUpdatingSchemaMode ? connectionWithRefreshCatalog : initialConnection;
const connection = useMemo(() => {
if (activeUpdatingSchemaMode && connectionWithRefreshCatalog) {
// merge connectionFormValues (unsaved previous form state) with the refreshed connection data:
// 1. if there is a namespace definition, format, prefix, or schedule in connectionFormValues,
// use those and fill in the rest from the database
// 2. otherwise, use the values from the database
// 3. if none of the above, use the default values.
return {
...connectionWithRefreshCatalog,
namespaceDefinition:
connectionFormValues?.namespaceDefinition ?? connectionWithRefreshCatalog.namespaceDefinition,
namespaceFormat: connectionFormValues?.namespaceFormat ?? connectionWithRefreshCatalog.namespaceFormat,
prefix: connectionFormValues?.prefix ?? connectionWithRefreshCatalog.prefix,
schedule: connectionFormValues?.schedule ?? connectionWithRefreshCatalog.schedule,
};
}
return initialConnection;
}, [activeUpdatingSchemaMode, connectionWithRefreshCatalog, initialConnection, connectionFormValues]);

const onSubmit = async (values: ValuesProps, formikHelpers?: FormikHelpers<ValuesProps>) => {
if (!connection) {
Expand Down Expand Up @@ -125,7 +144,7 @@ export const ReplicationView: React.FC<ReplicationViewProps> = ({ onAfterSaveSch
await refreshCatalog();
};

const onExitRefreshCatalogMode = () => {
const onCancelConnectionFormEdit = () => {
setActiveUpdatingSchemaMode(false);
};

Expand Down Expand Up @@ -158,9 +177,10 @@ export const ReplicationView: React.FC<ReplicationViewProps> = ({ onAfterSaveSch
onSubmit={onSubmitForm}
onReset={onReset}
successMessage={saved && <FormattedMessage id="form.changesSaved" />}
onCancel={onExitRefreshCatalogMode}
onCancel={onCancelConnectionFormEdit}
editSchemeMode={activeUpdatingSchemaMode}
additionalSchemaControl={renderUpdateSchemaButton()}
onChangeValues={setConnectionFormValues}
/>
) : (
<LoadingSchema />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Field, FieldProps, Form, Formik, FormikHelpers } from "formik";
import { Field, FieldProps, Form, Formik, FormikHelpers, useFormikContext } from "formik";
import React, { useCallback, useState } from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { useToggle } from "react-use";
import { useDebounce } from "react-use";
import styled from "styled-components";

import { ControlLabels, DropDown, DropDownRow, H5, Input, Label } from "components";
Expand Down Expand Up @@ -93,6 +94,19 @@ interface ConnectionFormSubmitResult {

export type ConnectionFormMode = "create" | "edit" | "readonly";

function FormValuesChangeTracker<T>({ onChangeValues }: { onChangeValues?: (values: T) => void }) {
// Grab values from context
const { values } = useFormikContext<T>();
useDebounce(
() => {
onChangeValues?.(values);
},
200,
[values, onChangeValues]
);
return null;
}

interface ConnectionFormProps {
onSubmit: (values: ConnectionFormValues) => Promise<ConnectionFormSubmitResult | void>;
className?: string;
Expand All @@ -101,6 +115,7 @@ interface ConnectionFormProps {
onReset?: (connectionId?: string) => void;
onDropDownSelect?: (item: DropDownRow.IDataItem) => void;
onCancel?: () => void;
onChangeValues?: (values: FormikConnectionFormValues) => void;

/** Should be passed when connection is updated with withRefreshCatalog flag */
editSchemeMode?: boolean;
Expand All @@ -124,6 +139,7 @@ const ConnectionForm: React.FC<ConnectionFormProps> = ({
editSchemeMode,
additionalSchemaControl,
connection,
onChangeValues,
}) => {
const { openConfirmationModal, closeConfirmationModal } = useConfirmationModalService();
const destDefinition = useGetDestinationDefinitionSpecification(connection.destination.destinationDefinitionId);
Expand Down Expand Up @@ -204,6 +220,7 @@ const ConnectionForm: React.FC<ConnectionFormProps> = ({
{({ isSubmitting, setFieldValue, isValid, dirty, resetForm, values }) => (
<FormContainer className={className}>
<FormChangeTracker changed={dirty} formId={formId} />
<FormValuesChangeTracker onChangeValues={onChangeValues} />
{!isEditMode && (
<StyledSection>
<Field name="name">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ const useInitialValues = (
const initialValues: FormikConnectionFormValues = {
name: connection.name ?? `${connection.source.name} <> ${connection.destination.name}`,
syncCatalog: initialSchema,
schedule: connection.connectionId ? connection.schedule ?? null : DEFAULT_SCHEDULE,
schedule: connection.connectionId || connection.schedule ? connection.schedule ?? null : DEFAULT_SCHEDULE,
prefix: connection.prefix || "",
namespaceDefinition: connection.namespaceDefinition || NamespaceDefinitionType.source,
namespaceFormat: connection.namespaceFormat ?? SOURCE_NAMESPACE_TAG,
Expand Down