Skip to content

Commit

Permalink
Fix enabling connection in refresh catalog mode (#4527)
Browse files Browse the repository at this point in the history
* Fix enabling connection in refresh catalog mode
  • Loading branch information
jamakase authored Jul 14, 2021
1 parent 43d8611 commit 3a775b4
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 90 deletions.
52 changes: 17 additions & 35 deletions airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { useCallback, useEffect, useState } from "react";
import { useFetcher, useResource } from "rest-hooks";
import { useCallback } from "react";
import { useResource, useFetcher } from "rest-hooks";

import config from "config";
import FrequencyConfig from "config/FrequencyConfig.json";

import { AnalyticsService } from "core/analytics/AnalyticsService";
import { connectionService, Connection } from "core/domain/connection";

import ConnectionResource, {
Connection,
ScheduleProperties,
} from "core/resources/Connection";
import { SyncSchema } from "core/domain/catalog";
import { SourceDefinition } from "core/resources/SourceDefinition";
import FrequencyConfig from "config/FrequencyConfig.json";
import { Source } from "core/resources/Source";
import { Routes } from "pages/routes";
import useRouter from "../useRouterHook";
Expand Down Expand Up @@ -58,44 +60,25 @@ type UpdateStateConnection = {
sourceName: string;
prefix: string;
connectionConfiguration: ConnectionConfiguration;
schedule: {
units: number;
timeUnit: string;
} | null;
schedule: ScheduleProperties | null;
};

export const useConnectionLoad = (
connectionId: string,
withRefresh?: boolean
): { connection: Connection | null; isLoadingConnection: boolean } => {
const [connection, setConnection] = useState<null | Connection>(null);
const [isLoadingConnection, setIsLoadingConnection] = useState(false);

// TODO: change to useStatefulResource
const fetchConnection = useFetcher(ConnectionResource.detailShape(), false);
const baseConnection = useResource(ConnectionResource.detailShape(), {
connectionId: string
): {
connection: Connection;
refreshConnectionCatalog: () => Promise<Connection>;
} => {
const connection = useResource(ConnectionResource.detailShape(), {
connectionId,
});

useEffect(() => {
(async () => {
if (withRefresh) {
setIsLoadingConnection(true);
setConnection(
await fetchConnection({
connectionId,
withRefreshedCatalog: withRefresh,
})
);

setIsLoadingConnection(false);
}
})();
}, [connectionId, fetchConnection, withRefresh]);
const refreshConnectionCatalog = async () =>
await connectionService.getConnection(connectionId, true);

return {
connection: withRefresh ? connection : baseConnection,
isLoadingConnection,
connection,
refreshConnectionCatalog,
};
};

Expand Down Expand Up @@ -155,7 +138,6 @@ const useConnection = (): {
);

AnalyticsService.track("New Connection - Action", {
user_id: config.ui.workspaceId,
action: "Set up connection",
frequency: frequencyData?.text,
connector_source_definition: source?.sourceName,
Expand Down
22 changes: 22 additions & 0 deletions airbyte-webapp/src/core/domain/connection/ConnectionService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AirbyteRequestService } from "core/request/AirbyteRequestService";
import { Connection } from "./types";

class ConnectionService extends AirbyteRequestService {
get url() {
return "web_backend/connections";
}

public async getConnection(
connectionId: string,
withRefreshedCatalog?: boolean
): Promise<Connection> {
const rs = ((await this.fetch(`${this.url}/get`, {
connectionId,
withRefreshedCatalog,
})) as any) as Connection;

return rs;
}
}

export const connectionService = new ConnectionService();
3 changes: 3 additions & 0 deletions airbyte-webapp/src/core/domain/connection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from "./types";
export * from "./operation";
export * from "./ConnectionService";
export * from "./OperationService";
32 changes: 32 additions & 0 deletions airbyte-webapp/src/core/domain/connection/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { SyncSchema } from "core/domain/catalog";
import { Source } from "core/resources/Source";
import { Destination } from "core/resources/Destination";
import { Operation } from "./operation";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ConnectionConfiguration = any;

Expand All @@ -14,3 +19,30 @@ export enum ConnectionNamespaceDefinition {
Destination = "destination",
CustomFormat = "customformat",
}

export type ScheduleProperties = {
units: number;
timeUnit: string;
};

export interface Connection {
connectionId: string;
name: string;
prefix: string;
sourceId: string;
destinationId: string;
status: string;
schedule: ScheduleProperties | null;
syncCatalog: SyncSchema;
latestSyncJobCreatedAt?: number | null;
namespaceDefinition: ConnectionNamespaceDefinition;
namespaceFormat: string;
isSyncing?: boolean;
latestSyncJobStatus: string | null;
operationIds: string[];

// WebBackend connection specific fields
source: Source;
destination: Destination;
operations: Operation[];
}
43 changes: 10 additions & 33 deletions airbyte-webapp/src/core/resources/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,18 @@ import {

import { SyncSchema } from "core/domain/catalog";
import { CommonRequestError } from "core/request/CommonRequestError";
import { Operation } from "core/domain/connection/operation";
import { Source } from "./Source";
import { Destination } from "./Destination";

import BaseResource from "./BaseResource";
import { ConnectionNamespaceDefinition } from "../domain/connection";

export type ScheduleProperties = {
units: number;
timeUnit: string;
};

export interface Connection {
connectionId: string;
name: string;
prefix: string;
sourceId: string;
destinationId: string;
status: string;
schedule: ScheduleProperties | null;
syncCatalog: SyncSchema;
latestSyncJobCreatedAt?: number | null;
namespaceDefinition: ConnectionNamespaceDefinition;
namespaceFormat: string;
isSyncing?: boolean;
latestSyncJobStatus: string | null;
operationIds: string[];

// WebBackend connection specific fields
source: Source;
destination: Destination;
operations: Operation[];
}
import {
ConnectionNamespaceDefinition,
Connection,
ScheduleProperties,
Operation,
} from "core/domain/connection";

export type { Connection, ScheduleProperties };

export default class ConnectionResource
extends BaseResource
Expand Down Expand Up @@ -83,10 +62,8 @@ export default class ConnectionResource
): ReadShape<SchemaDetail<Connection>> {
return {
...super.detailShape(),
getFetchKey: (params: {
connectionId: string;
withRefreshedCatalog?: boolean;
}) => "POST /web_backend/get" + JSON.stringify(params),
getFetchKey: (params: { connectionId: string }) =>
"POST /web_backend/get" + JSON.stringify(params),
fetch: async (
params: Readonly<Record<string, unknown>>
): Promise<Connection> =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,15 @@ const Content = styled.div`

type IProps = {
connection: Connection;
disabled?: boolean;
frequencyText?: string;
};

const EnabledControl: React.FC<IProps> = ({ connection, frequencyText }) => {
const EnabledControl: React.FC<IProps> = ({
connection,
disabled,
frequencyText,
}) => {
const { updateConnection } = useConnection();

const onChangeStatus = async () => {
Expand All @@ -48,7 +53,7 @@ const EnabledControl: React.FC<IProps> = ({ connection, frequencyText }) => {

AnalyticsService.track("Source - Action", {
action:
connection.status === "active"
connection.status === Status.ACTIVE
? "Disable connection"
: "Reenable connection",
connector_source: connection.source?.sourceName,
Expand All @@ -65,15 +70,16 @@ const EnabledControl: React.FC<IProps> = ({ connection, frequencyText }) => {
<ToggleLabel htmlFor="toggle-enabled-source">
<FormattedMessage
id={
connection.status === "active"
connection.status === Status.ACTIVE
? "tables.enabled"
: "tables.disabled"
}
/>
</ToggleLabel>
<Toggle
disabled={disabled}
onChange={onChangeStatus}
checked={connection.status === "active"}
checked={connection.status === Status.ACTIVE}
id="toggle-enabled-source"
/>
</Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { SourceDefinition } from "core/resources/SourceDefinition";
import { equal } from "utils/objects";
import EnabledControl from "./EnabledControl";
import { ConnectionNamespaceDefinition } from "core/domain/connection";
import { useAsyncFn } from "react-use";

type IProps = {
onAfterSaveSchema: () => void;
Expand Down Expand Up @@ -86,17 +87,13 @@ const SettingsView: React.FC<IProps> = ({
prefix: "",
syncCatalog: { streams: [] },
});

const {
updateConnection,
deleteConnection,
resetConnection,
} = useConnection();

const { connection, isLoadingConnection } = useConnectionLoad(
connectionId,
activeUpdatingSchemaMode
);

const onDelete = useCallback(() => deleteConnection({ connectionId }), [
deleteConnection,
connectionId,
Expand All @@ -107,13 +104,27 @@ const SettingsView: React.FC<IProps> = ({
connectionId,
]);

const {
connection: initialConnection,
refreshConnectionCatalog,
} = useConnectionLoad(connectionId);

const [
{ value: connectionWithRefreshCatalog, loading: isRefreshingCatalog },
refreshCatalog,
] = useAsyncFn(refreshConnectionCatalog, [connectionId]);

const connection = activeUpdatingSchemaMode
? connectionWithRefreshCatalog
: initialConnection;

const onSubmit = async (values: ValuesProps) => {
const initialSyncSchema = connection?.syncCatalog;

await updateConnection({
...values,
connectionId: connectionId,
status: connection?.status || "",
connectionId,
status: initialConnection.status || "",
withRefreshedCatalog: activeUpdatingSchemaMode,
});

Expand Down Expand Up @@ -141,10 +152,19 @@ const SettingsView: React.FC<IProps> = ({
}
};

const UpdateSchemaButton = () => {
const onEnterRefreshCatalogMode = async () => {
setActiveUpdatingSchemaMode(true);
await refreshCatalog();
};

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

const renderUpdateSchemaButton = () => {
if (!activeUpdatingSchemaMode) {
return (
<Button onClick={() => setActiveUpdatingSchemaMode(true)} type="button">
<Button onClick={onEnterRefreshCatalogMode} type="button">
<TryArrow icon={faRedoAlt} />
<FormattedMessage id="connection.updateSchema" />
</Button>
Expand All @@ -168,16 +188,15 @@ const SettingsView: React.FC<IProps> = ({
<TitleContainer hasButton={!activeUpdatingSchemaMode}>
<FormattedMessage id="connection.connectionSettings" />{" "}
</TitleContainer>
{connection && (
<EnabledControl
connection={connection}
frequencyText={frequencyText}
/>
)}
<EnabledControl
disabled={isRefreshingCatalog}
connection={initialConnection}
frequencyText={frequencyText}
/>
</Title>
}
>
{!isLoadingConnection && connection ? (
{!isRefreshingCatalog && connection ? (
<ConnectionForm
isEditMode
connection={connection}
Expand All @@ -186,9 +205,9 @@ const SettingsView: React.FC<IProps> = ({
successMessage={
saved && <FormattedMessage id="form.changesSaved" />
}
onCancel={() => setActiveUpdatingSchemaMode(false)}
onCancel={onExitRefreshCatalogMode}
editSchemeMode={activeUpdatingSchemaMode}
additionalSchemaControl={UpdateSchemaButton()}
additionalSchemaControl={renderUpdateSchemaButton()}
destinationIcon={destinationDefinition?.icon}
sourceIcon={sourceDefinition?.icon}
/>
Expand Down

0 comments on commit 3a775b4

Please sign in to comment.