From b2174747a838dc859a07fde3e6a24f91d4bb2756 Mon Sep 17 00:00:00 2001 From: Artem Astapenko Date: Sat, 3 Jul 2021 15:45:05 +0300 Subject: [PATCH 1/2] Fix enabling connection in refresh catalog mode --- .../hooks/services/useConnectionHook.tsx | 47 +++++----------- .../domain/connection/ConnectionService.ts | 22 ++++++++ .../src/core/domain/connection/types.ts | 28 ++++++++++ .../src/core/resources/Connection.ts | 33 +++-------- .../components/EnabledControl.tsx | 14 +++-- .../components/SettingsView.tsx | 55 +++++++++++++------ 6 files changed, 118 insertions(+), 81 deletions(-) create mode 100644 airbyte-webapp/src/core/domain/connection/ConnectionService.ts diff --git a/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx b/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx index a6ae16b653ef..8735ebd6b8f6 100644 --- a/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx +++ b/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx @@ -1,5 +1,5 @@ -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 { AnalyticsService } from "core/analytics/AnalyticsService"; @@ -21,6 +21,7 @@ import { } from "core/domain/connection"; import { Operation } from "core/domain/connection/operation"; import { equal } from "utils/objects"; +import { connectionService } from "../../../core/domain/connection/ConnectionService"; export type ValuesProps = { schedule: ScheduleProperties | null; @@ -58,44 +59,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); - 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; +} => { + 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, }; }; @@ -155,7 +137,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, diff --git a/airbyte-webapp/src/core/domain/connection/ConnectionService.ts b/airbyte-webapp/src/core/domain/connection/ConnectionService.ts new file mode 100644 index 000000000000..a8f467df31b8 --- /dev/null +++ b/airbyte-webapp/src/core/domain/connection/ConnectionService.ts @@ -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 { + const rs = ((await this.fetch(`${this.url}/get`, { + connectionId, + withRefreshedCatalog, + })) as any) as Connection; + + return rs; + } +} + +export const connectionService = new ConnectionService(); diff --git a/airbyte-webapp/src/core/domain/connection/types.ts b/airbyte-webapp/src/core/domain/connection/types.ts index dd5decf1552a..ab1badf7b299 100644 --- a/airbyte-webapp/src/core/domain/connection/types.ts +++ b/airbyte-webapp/src/core/domain/connection/types.ts @@ -1,4 +1,10 @@ // eslint-disable-next-line @typescript-eslint/no-explicit-any +import { SyncSchema } from "../catalog"; +import { Source } from "../../resources/Source"; +import { Destination } from "../../resources/Destination"; +import { Operation } from "./operation"; +import { ScheduleProperties } from "../../resources/Connection"; + type ConnectionConfiguration = any; type ConnectionSpecification = { @@ -14,3 +20,25 @@ export enum ConnectionNamespaceDefinition { Destination = "destination", CustomFormat = "customformat", } + +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[]; +} diff --git a/airbyte-webapp/src/core/resources/Connection.ts b/airbyte-webapp/src/core/resources/Connection.ts index 2eec13d0b57d..5a878277a244 100644 --- a/airbyte-webapp/src/core/resources/Connection.ts +++ b/airbyte-webapp/src/core/resources/Connection.ts @@ -14,34 +14,17 @@ import { Source } from "./Source"; import { Destination } from "./Destination"; import BaseResource from "./BaseResource"; -import { ConnectionNamespaceDefinition } from "../domain/connection"; +import { + ConnectionNamespaceDefinition, + Connection, +} 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[]; -} +export type { Connection }; export default class ConnectionResource extends BaseResource @@ -83,10 +66,8 @@ export default class ConnectionResource ): ReadShape> { 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> ): Promise => diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/EnabledControl.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/EnabledControl.tsx index a30272a0f820..c5334b278b63 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/EnabledControl.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/EnabledControl.tsx @@ -27,10 +27,15 @@ const Content = styled.div` type IProps = { connection: Connection; + disabled?: boolean; frequencyText?: string; }; -const EnabledControl: React.FC = ({ connection, frequencyText }) => { +const EnabledControl: React.FC = ({ + connection, + disabled, + frequencyText, +}) => { const { updateConnection } = useConnection(); const onChangeStatus = async () => { @@ -48,7 +53,7 @@ const EnabledControl: React.FC = ({ connection, frequencyText }) => { AnalyticsService.track("Source - Action", { action: - connection.status === "active" + connection.status === Status.ACTIVE ? "Disable connection" : "Reenable connection", connector_source: connection.source?.sourceName, @@ -65,15 +70,16 @@ const EnabledControl: React.FC = ({ connection, frequencyText }) => { diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/SettingsView.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/SettingsView.tsx index 36d812401f7f..d28fcf8208c0 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/SettingsView.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/ConnectionItemPage/components/SettingsView.tsx @@ -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; @@ -86,17 +87,13 @@ const SettingsView: React.FC = ({ prefix: "", syncCatalog: { streams: [] }, }); + const { updateConnection, deleteConnection, resetConnection, } = useConnection(); - const { connection, isLoadingConnection } = useConnectionLoad( - connectionId, - activeUpdatingSchemaMode - ); - const onDelete = useCallback(() => deleteConnection({ connectionId }), [ deleteConnection, connectionId, @@ -107,13 +104,27 @@ const SettingsView: React.FC = ({ 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, }); @@ -141,10 +152,19 @@ const SettingsView: React.FC = ({ } }; - const UpdateSchemaButton = () => { + const onEnterRefreshCatalogMode = async () => { + setActiveUpdatingSchemaMode(true); + await refreshCatalog(); + }; + + const onExitRefreshCatalogMode = () => { + setActiveUpdatingSchemaMode(false); + }; + + const renderUpdateSchemaButton = () => { if (!activeUpdatingSchemaMode) { return ( - @@ -168,16 +188,15 @@ const SettingsView: React.FC = ({ {" "} - {connection && ( - - )} + } > - {!isLoadingConnection && connection ? ( + {!isRefreshingCatalog && connection ? ( = ({ successMessage={ saved && } - onCancel={() => setActiveUpdatingSchemaMode(false)} + onCancel={onExitRefreshCatalogMode} editSchemeMode={activeUpdatingSchemaMode} - additionalSchemaControl={UpdateSchemaButton()} + additionalSchemaControl={renderUpdateSchemaButton()} destinationIcon={destinationDefinition?.icon} sourceIcon={sourceDefinition?.icon} /> From 60613df724505f9ea5e55177606f6d3bb7fc0cfd Mon Sep 17 00:00:00 2001 From: Artem Astapenko Date: Sat, 3 Jul 2021 15:51:51 +0300 Subject: [PATCH 2/2] Minor type fixes --- .../hooks/services/useConnectionHook.tsx | 7 ++++--- airbyte-webapp/src/core/domain/connection/index.ts | 3 +++ airbyte-webapp/src/core/domain/connection/types.ts | 14 +++++++++----- airbyte-webapp/src/core/resources/Connection.ts | 12 ++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx b/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx index 8735ebd6b8f6..3dff6088ca6f 100644 --- a/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx +++ b/airbyte-webapp/src/components/hooks/services/useConnectionHook.tsx @@ -2,14 +2,16 @@ 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"; @@ -21,7 +23,6 @@ import { } from "core/domain/connection"; import { Operation } from "core/domain/connection/operation"; import { equal } from "utils/objects"; -import { connectionService } from "../../../core/domain/connection/ConnectionService"; export type ValuesProps = { schedule: ScheduleProperties | null; diff --git a/airbyte-webapp/src/core/domain/connection/index.ts b/airbyte-webapp/src/core/domain/connection/index.ts index eea524d65570..5ac0dd6fe578 100644 --- a/airbyte-webapp/src/core/domain/connection/index.ts +++ b/airbyte-webapp/src/core/domain/connection/index.ts @@ -1 +1,4 @@ export * from "./types"; +export * from "./operation"; +export * from "./ConnectionService"; +export * from "./OperationService"; diff --git a/airbyte-webapp/src/core/domain/connection/types.ts b/airbyte-webapp/src/core/domain/connection/types.ts index ab1badf7b299..565206c62c9f 100644 --- a/airbyte-webapp/src/core/domain/connection/types.ts +++ b/airbyte-webapp/src/core/domain/connection/types.ts @@ -1,10 +1,9 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -import { SyncSchema } from "../catalog"; -import { Source } from "../../resources/Source"; -import { Destination } from "../../resources/Destination"; +import { SyncSchema } from "core/domain/catalog"; +import { Source } from "core/resources/Source"; +import { Destination } from "core/resources/Destination"; import { Operation } from "./operation"; -import { ScheduleProperties } from "../../resources/Connection"; +// eslint-disable-next-line @typescript-eslint/no-explicit-any type ConnectionConfiguration = any; type ConnectionSpecification = { @@ -21,6 +20,11 @@ export enum ConnectionNamespaceDefinition { CustomFormat = "customformat", } +export type ScheduleProperties = { + units: number; + timeUnit: string; +}; + export interface Connection { connectionId: string; name: string; diff --git a/airbyte-webapp/src/core/resources/Connection.ts b/airbyte-webapp/src/core/resources/Connection.ts index 5a878277a244..1248a7a81c34 100644 --- a/airbyte-webapp/src/core/resources/Connection.ts +++ b/airbyte-webapp/src/core/resources/Connection.ts @@ -9,7 +9,6 @@ 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"; @@ -17,14 +16,11 @@ import BaseResource from "./BaseResource"; import { ConnectionNamespaceDefinition, Connection, -} from "../domain/connection"; + ScheduleProperties, + Operation, +} from "core/domain/connection"; -export type ScheduleProperties = { - units: number; - timeUnit: string; -}; - -export type { Connection }; +export type { Connection, ScheduleProperties }; export default class ConnectionResource extends BaseResource