From a8c72121f8fd50407425250d3a6ddc3756db8b55 Mon Sep 17 00:00:00 2001 From: Parker Mossman Date: Wed, 28 Sep 2022 12:01:10 -0700 Subject: [PATCH] Remove catalog from web_backend/connections/list (#17002) * Use PATCH Api for toggling connections * remove catalog from web backend connection list, and move icon to source/destination field in response * Adjust FE code * comment out failing tests * Resolve merge conflict * add back in tests and make them pass with new list items * format * leave repository layer alone for now, just remove catalog from API response * format * load the icon when returning * update sourceHandler and destinationHandler test to account for icons * add icon to source and destination in webBackendConnectionHandlerTest * change icon test to actually load an svg rather than using static mocks * also fix icon test for WebBackendConnectionsHandlerTest * make PMD happy Co-authored-by: Tim Roes Co-authored-by: Davin Chia Co-authored-by: KC --- airbyte-api/src/main/openapi/config.yaml | 51 ++- .../server/converters/ApiPojoConverters.java | 99 +++--- .../server/handlers/DestinationHandler.java | 3 +- .../server/handlers/SourceHandler.java | 3 +- .../WebBackendConnectionsHandler.java | 54 +++- .../handlers/DestinationHandlerTest.java | 30 +- .../server/handlers/SourceHandlerTest.java | 11 +- .../WebBackendConnectionsHandlerTest.java | 42 ++- .../server/helpers/ConnectionHelpers.java | 29 ++ .../server/helpers/DestinationHelpers.java | 4 +- .../airbyte/server/helpers/SourceHelpers.java | 4 +- .../test/resources/icons/test-destination.svg | 3 + .../src/test/resources/icons/test-source.svg | 3 + .../src/components/EntityTable/hooks.tsx | 6 +- .../src/components/EntityTable/utils.tsx | 59 ++-- .../src/hooks/services/useConnectionHook.tsx | 26 +- .../src/hooks/services/useDestinationHook.tsx | 4 +- .../src/hooks/services/useSourceHook.tsx | 4 +- .../components/ConnectionsTable.tsx | 13 +- .../components/DestinationConnectionTable.tsx | 11 +- .../components/DestinationSettings.tsx | 4 +- .../components/SourceConnectionTable.tsx | 12 +- .../components/SourceSettings.tsx | 4 +- .../api/generated-api-html/index.html | 295 +++--------------- 24 files changed, 371 insertions(+), 403 deletions(-) create mode 100644 airbyte-server/src/test/resources/icons/test-destination.svg create mode 100644 airbyte-server/src/test/resources/icons/test-source.svg diff --git a/airbyte-api/src/main/openapi/config.yaml b/airbyte-api/src/main/openapi/config.yaml index 02a91076c5f0..6d13ebe89e34 100644 --- a/airbyte-api/src/main/openapi/config.yaml +++ b/airbyte-api/src/main/openapi/config.yaml @@ -2756,6 +2756,8 @@ components: type: string sourceName: type: string + icon: + type: string SourceReadList: type: object required: @@ -3053,6 +3055,8 @@ components: type: string destinationName: type: string + icon: + type: string DestinationReadList: type: object required: @@ -3813,6 +3817,10 @@ components: type: array items: $ref: "#/components/schemas/AttemptRead" + JobCreatedAt: + description: epoch time of the latest sync job. null if no sync job has taken place. + type: integer + format: int64 JobStatus: type: string enum: @@ -4508,6 +4516,43 @@ components: type: object additionalProperties: true # Web Backend + WebBackendConnectionListItem: + type: object + description: Information about a connection that shows up in the connection list view. + required: + - connectionId + - name + - sourceId + - destinationId + - source + - destination + - status + - isSyncing + properties: + connectionId: + $ref: "#/components/schemas/ConnectionId" + name: + type: string + sourceId: + $ref: "#/components/schemas/SourceId" + destinationId: + $ref: "#/components/schemas/DestinationId" + scheduleType: + $ref: "#/components/schemas/ConnectionScheduleType" + scheduleData: + $ref: "#/components/schemas/ConnectionScheduleData" + status: + $ref: "#/components/schemas/ConnectionStatus" + source: + $ref: "#/components/schemas/SourceRead" + destination: + $ref: "#/components/schemas/DestinationRead" + latestSyncJobCreatedAt: + $ref: "#/components/schemas/JobCreatedAt" + latestSyncJobStatus: + $ref: "#/components/schemas/JobStatus" + isSyncing: + type: boolean WebBackendConnectionRead: type: object required: @@ -4562,9 +4607,7 @@ components: items: $ref: "#/components/schemas/OperationRead" latestSyncJobCreatedAt: - description: epoch time of the latest sync job. null if no sync job has taken place. - type: integer - format: int64 + $ref: "#/components/schemas/JobCreatedAt" latestSyncJobStatus: $ref: "#/components/schemas/JobStatus" isSyncing: @@ -4584,7 +4627,7 @@ components: connections: type: array items: - $ref: "#/components/schemas/WebBackendConnectionRead" + $ref: "#/components/schemas/WebBackendConnectionListItem" SyncMode: type: string enum: diff --git a/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java b/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java index 6a3aeae05799..73d9e0f61220 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java +++ b/airbyte-server/src/main/java/io/airbyte/server/converters/ApiPojoConverters.java @@ -4,7 +4,6 @@ package io.airbyte.server.converters; -import io.airbyte.api.client.model.generated.ConnectionScheduleType; import io.airbyte.api.model.generated.ActorDefinitionResourceRequirements; import io.airbyte.api.model.generated.ConnectionRead; import io.airbyte.api.model.generated.ConnectionSchedule; @@ -19,7 +18,6 @@ import io.airbyte.config.BasicSchedule; import io.airbyte.config.Schedule; import io.airbyte.config.StandardSync; -import io.airbyte.config.StandardSync.ScheduleType; import io.airbyte.server.handlers.helpers.CatalogConverter; import java.util.stream.Collectors; @@ -153,63 +151,94 @@ public static ConnectionScheduleDataBasicSchedule.TimeUnitEnum toApiBasicSchedul return Enums.convertTo(timeUnit, ConnectionScheduleDataBasicSchedule.TimeUnitEnum.class); } - public static void populateConnectionReadSchedule(final StandardSync standardSync, final ConnectionRead connectionRead) { - // TODO(https://github.com/airbytehq/airbyte/issues/11432): only return new schema once frontend is - // ready. + public static io.airbyte.api.model.generated.ConnectionScheduleType toApiConnectionScheduleType(final StandardSync standardSync) { if (standardSync.getScheduleType() != null) { - // Populate everything based on the new schema. switch (standardSync.getScheduleType()) { case MANUAL -> { - connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL); + return io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL; } case BASIC_SCHEDULE -> { - connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.BASIC); - connectionRead.scheduleData(new ConnectionScheduleData() + return io.airbyte.api.model.generated.ConnectionScheduleType.BASIC; + } + case CRON -> { + return io.airbyte.api.model.generated.ConnectionScheduleType.CRON; + } + default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); + } + } else if (standardSync.getManual()) { + // Legacy schema, manual sync. + return io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL; + } else { + // Legacy schema, basic schedule. + return io.airbyte.api.model.generated.ConnectionScheduleType.BASIC; + } + } + + public static io.airbyte.api.model.generated.ConnectionScheduleData toApiConnectionScheduleData(final StandardSync standardSync) { + if (standardSync.getScheduleType() != null) { + switch (standardSync.getScheduleType()) { + case MANUAL -> { + return null; + } + case BASIC_SCHEDULE -> { + return new ConnectionScheduleData() .basicSchedule(new ConnectionScheduleDataBasicSchedule() .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) - .units(standardSync.getScheduleData().getBasicSchedule().getUnits()))); - connectionRead.schedule(new ConnectionSchedule() - .timeUnit(toApiTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) - .units(standardSync.getScheduleData().getBasicSchedule().getUnits())); + .units(standardSync.getScheduleData().getBasicSchedule().getUnits())); } case CRON -> { - // We don't populate any legacy data here. - connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.CRON); - connectionRead.scheduleData(new ConnectionScheduleData() + return new ConnectionScheduleData() .cron(new ConnectionScheduleDataCron() .cronExpression(standardSync.getScheduleData().getCron().getCronExpression()) - .cronTimeZone(standardSync.getScheduleData().getCron().getCronTimeZone()))); + .cronTimeZone(standardSync.getScheduleData().getCron().getCronTimeZone())); } + default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); } } else if (standardSync.getManual()) { // Legacy schema, manual sync. - connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.MANUAL); + return null; } else { // Legacy schema, basic schedule. - connectionRead.scheduleType(io.airbyte.api.model.generated.ConnectionScheduleType.BASIC); - connectionRead.schedule(new ConnectionSchedule() - .timeUnit(toApiTimeUnit(standardSync.getSchedule().getTimeUnit())) - .units(standardSync.getSchedule().getUnits())); - connectionRead.scheduleData(new ConnectionScheduleData() + return new ConnectionScheduleData() .basicSchedule(new ConnectionScheduleDataBasicSchedule() .timeUnit(toApiBasicScheduleTimeUnit(standardSync.getSchedule().getTimeUnit())) - .units(standardSync.getSchedule().getUnits()))); + .units(standardSync.getSchedule().getUnits())); } } - public static ConnectionScheduleType toApiScheduleType(final ScheduleType scheduleType) { - switch (scheduleType) { - case MANUAL -> { - return ConnectionScheduleType.MANUAL; - } - case BASIC_SCHEDULE -> { - return ConnectionScheduleType.BASIC; - } - case CRON -> { - return ConnectionScheduleType.CRON; + public static ConnectionSchedule toLegacyConnectionSchedule(final StandardSync standardSync) { + if (standardSync.getScheduleType() != null) { + // Populate everything based on the new schema. + switch (standardSync.getScheduleType()) { + case MANUAL, CRON -> { + // We don't populate any legacy data here. + return null; + } + case BASIC_SCHEDULE -> { + return new ConnectionSchedule() + .timeUnit(toApiTimeUnit(standardSync.getScheduleData().getBasicSchedule().getTimeUnit())) + .units(standardSync.getScheduleData().getBasicSchedule().getUnits()); + } + default -> throw new RuntimeException("Unexpected scheduleType " + standardSync.getScheduleType()); } + } else if (standardSync.getManual()) { + // Legacy schema, manual sync. + return null; + } else { + // Legacy schema, basic schedule. + return new ConnectionSchedule() + .timeUnit(toApiTimeUnit(standardSync.getSchedule().getTimeUnit())) + .units(standardSync.getSchedule().getUnits()); } - throw new RuntimeException("Unexpected schedule type"); + } + + public static void populateConnectionReadSchedule(final StandardSync standardSync, final ConnectionRead connectionRead) { + connectionRead.scheduleType(toApiConnectionScheduleType(standardSync)); + connectionRead.scheduleData(toApiConnectionScheduleData(standardSync)); + + // TODO(https://github.com/airbytehq/airbyte/issues/11432): only return new schema once frontend is + // ready. + connectionRead.schedule(toLegacyConnectionSchedule(standardSync)); } } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/DestinationHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/DestinationHandler.java index d6a2111eded8..1d4ecdf2c2de 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/DestinationHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/DestinationHandler.java @@ -309,7 +309,8 @@ protected static DestinationRead toDestinationRead(final DestinationConnection d .destinationDefinitionId(destinationConnection.getDestinationDefinitionId()) .connectionConfiguration(destinationConnection.getConfiguration()) .name(destinationConnection.getName()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(DestinationDefinitionsHandler.loadIcon(standardDestinationDefinition.getIcon())); } } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/SourceHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/SourceHandler.java index dd21d18ab80d..0990887d68ee 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/SourceHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/SourceHandler.java @@ -316,7 +316,8 @@ protected static SourceRead toSourceRead(final SourceConnection sourceConnection .workspaceId(sourceConnection.getWorkspaceId()) .sourceDefinitionId(sourceConnection.getSourceDefinitionId()) .connectionConfiguration(sourceConnection.getConfiguration()) - .name(sourceConnection.getName()); + .name(sourceConnection.getName()) + .icon(SourceDefinitionsHandler.loadIcon(standardSourceDefinition.getIcon())); } } diff --git a/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java b/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java index 27bd3e9b4de3..28293cfadce1 100644 --- a/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java +++ b/airbyte-server/src/main/java/io/airbyte/server/handlers/WebBackendConnectionsHandler.java @@ -31,6 +31,7 @@ import io.airbyte.api.model.generated.StreamDescriptor; import io.airbyte.api.model.generated.StreamTransform; import io.airbyte.api.model.generated.WebBackendConnectionCreate; +import io.airbyte.api.model.generated.WebBackendConnectionListItem; import io.airbyte.api.model.generated.WebBackendConnectionRead; import io.airbyte.api.model.generated.WebBackendConnectionReadList; import io.airbyte.api.model.generated.WebBackendConnectionRequestBody; @@ -42,9 +43,11 @@ import io.airbyte.commons.enums.Enums; import io.airbyte.commons.json.Jsons; import io.airbyte.commons.lang.MoreBooleans; +import io.airbyte.config.StandardSync; import io.airbyte.config.persistence.ConfigNotFoundException; import io.airbyte.config.persistence.ConfigRepository; import io.airbyte.protocol.models.ConfiguredAirbyteCatalog; +import io.airbyte.server.converters.ApiPojoConverters; import io.airbyte.server.handlers.helpers.CatalogConverter; import io.airbyte.server.scheduler.EventRunner; import io.airbyte.validation.json.JsonValidationException; @@ -96,17 +99,20 @@ public ConnectionStateType getStateType(final ConnectionIdRequestBody connection public WebBackendConnectionReadList webBackendListConnectionsForWorkspace(final WorkspaceIdRequestBody workspaceIdRequestBody) throws ConfigNotFoundException, IOException, JsonValidationException { - final List reads = Lists.newArrayList(); - for (final ConnectionRead connection : connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody).getConnections()) { - reads.add(buildWebBackendConnectionRead(connection)); + final List connectionItems = Lists.newArrayList(); + + // passing 'false' so that deleted connections are not included + for (final StandardSync standardSync : configRepository.listWorkspaceStandardSyncs(workspaceIdRequestBody.getWorkspaceId(), false)) { + connectionItems.add(buildWebBackendConnectionListItem(standardSync)); } - return new WebBackendConnectionReadList().connections(reads); + + return new WebBackendConnectionReadList().connections(connectionItems); } private WebBackendConnectionRead buildWebBackendConnectionRead(final ConnectionRead connectionRead) throws ConfigNotFoundException, IOException, JsonValidationException { - final SourceRead source = getSourceRead(connectionRead); - final DestinationRead destination = getDestinationRead(connectionRead); + final SourceRead source = getSourceRead(connectionRead.getSourceId()); + final DestinationRead destination = getDestinationRead(connectionRead.getDestinationId()); final OperationReadList operations = getOperationReadList(connectionRead); final Optional latestSyncJob = jobHistoryHandler.getLatestSyncJob(connectionRead.getConnectionId()); final Optional latestRunningSyncJob = jobHistoryHandler.getLatestRunningSyncJob(connectionRead.getConnectionId()); @@ -124,14 +130,42 @@ private WebBackendConnectionRead buildWebBackendConnectionRead(final ConnectionR return webBackendConnectionRead; } - private SourceRead getSourceRead(final ConnectionRead connectionRead) throws JsonValidationException, IOException, ConfigNotFoundException { - final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(connectionRead.getSourceId()); + private WebBackendConnectionListItem buildWebBackendConnectionListItem(final StandardSync standardSync) + throws JsonValidationException, ConfigNotFoundException, IOException { + final SourceRead source = getSourceRead(standardSync.getSourceId()); + final DestinationRead destination = getDestinationRead(standardSync.getDestinationId()); + final Optional latestSyncJob = jobHistoryHandler.getLatestSyncJob(standardSync.getConnectionId()); + final Optional latestRunningSyncJob = jobHistoryHandler.getLatestRunningSyncJob(standardSync.getConnectionId()); + + final WebBackendConnectionListItem listItem = new WebBackendConnectionListItem() + .connectionId(standardSync.getConnectionId()) + .sourceId(standardSync.getSourceId()) + .destinationId(standardSync.getDestinationId()) + .status(ApiPojoConverters.toApiStatus(standardSync.getStatus())) + .name(standardSync.getName()) + .scheduleType(ApiPojoConverters.toApiConnectionScheduleType(standardSync)) + .scheduleData(ApiPojoConverters.toApiConnectionScheduleData(standardSync)) + .source(source) + .destination(destination); + + listItem.setIsSyncing(latestRunningSyncJob.isPresent()); + + latestSyncJob.ifPresent(job -> { + listItem.setLatestSyncJobCreatedAt(job.getCreatedAt()); + listItem.setLatestSyncJobStatus(job.getStatus()); + }); + + return listItem; + } + + private SourceRead getSourceRead(final UUID sourceId) throws JsonValidationException, IOException, ConfigNotFoundException { + final SourceIdRequestBody sourceIdRequestBody = new SourceIdRequestBody().sourceId(sourceId); return sourceHandler.getSource(sourceIdRequestBody); } - private DestinationRead getDestinationRead(final ConnectionRead connectionRead) + private DestinationRead getDestinationRead(final UUID destinationId) throws JsonValidationException, IOException, ConfigNotFoundException { - final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(connectionRead.getDestinationId()); + final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(destinationId); return destinationHandler.getDestination(destinationIdRequestBody); } diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/DestinationHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/DestinationHandlerTest.java index 41f9c4561bb4..6dc096c862e1 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/DestinationHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/DestinationHandlerTest.java @@ -5,6 +5,7 @@ package io.airbyte.server.handlers; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -58,6 +59,10 @@ class DestinationHandlerTest { private JsonSecretsProcessor secretsProcessor; private ConnectorSpecification connectorSpecification; + // needs to match name of file in src/test/resources/icons + private static final String ICON = "test-destination.svg"; + private static final String LOADED_ICON = DestinationDefinitionsHandler.loadIcon(ICON); + @SuppressWarnings("unchecked") @BeforeEach void setUp() throws IOException { @@ -78,7 +83,8 @@ void setUp() throws IOException { .withDockerRepository("thebestrepo") .withDockerImageTag("thelatesttag") .withDocumentationUrl("https://wikipedia.org") - .withSpec(connectorSpecification); + .withSpec(connectorSpecification) + .withIcon(ICON); destinationDefinitionSpecificationRead = new DestinationDefinitionSpecificationRead() .connectionSpecification(connectorSpecification.getConnectionSpecification()) @@ -127,7 +133,8 @@ void testCreateDestination() throws JsonValidationException, ConfigNotFoundExcep .workspaceId(destinationConnection.getWorkspaceId()) .destinationId(destinationConnection.getDestinationId()) .connectionConfiguration(DestinationHelpers.getTestDestinationJson()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); assertEquals(expectedDestinationRead, actualDestinationRead); @@ -187,7 +194,8 @@ void testGetDestination() throws JsonValidationException, ConfigNotFoundExceptio .workspaceId(destinationConnection.getWorkspaceId()) .destinationId(destinationConnection.getDestinationId()) .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); final DestinationIdRequestBody destinationIdRequestBody = new DestinationIdRequestBody().destinationId(expectedDestinationRead.getDestinationId()); @@ -201,6 +209,10 @@ void testGetDestination() throws JsonValidationException, ConfigNotFoundExceptio final DestinationRead actualDestinationRead = destinationHandler.getDestination(destinationIdRequestBody); assertEquals(expectedDestinationRead, actualDestinationRead); + + // make sure the icon was loaded into actual svg content + assertTrue(expectedDestinationRead.getIcon().startsWith("")); + verify(secretsProcessor) .prepareSecretsForOutput(destinationConnection.getConfiguration(), destinationDefinitionSpecificationRead.getConnectionSpecification()); } @@ -213,7 +225,8 @@ void testListDestinationForWorkspace() throws JsonValidationException, ConfigNot .workspaceId(destinationConnection.getWorkspaceId()) .destinationId(destinationConnection.getDestinationId()) .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody().workspaceId(destinationConnection.getWorkspaceId()); when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())).thenReturn(destinationConnection); @@ -239,7 +252,8 @@ void testSearchDestinations() throws JsonValidationException, ConfigNotFoundExce .workspaceId(destinationConnection.getWorkspaceId()) .destinationId(destinationConnection.getDestinationId()) .connectionConfiguration(destinationConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); when(configRepository.getDestinationConnection(destinationConnection.getDestinationId())).thenReturn(destinationConnection); when(configRepository.listDestinationConnection()).thenReturn(Lists.newArrayList(destinationConnection)); @@ -270,7 +284,8 @@ void testCloneDestinationWithConfiguration() throws JsonValidationException, Con .workspaceId(clonedConnection.getWorkspaceId()) .destinationId(clonedConnection.getDestinationId()) .connectionConfiguration(clonedConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); final DestinationRead destinationRead = new DestinationRead() .name(destinationConnection.getName()) .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) @@ -309,7 +324,8 @@ void testCloneDestinationWithoutConfiguration() throws JsonValidationException, .workspaceId(clonedConnection.getWorkspaceId()) .destinationId(clonedConnection.getDestinationId()) .connectionConfiguration(clonedConnection.getConfiguration()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(LOADED_ICON); final DestinationRead destinationRead = new DestinationRead() .name(destinationConnection.getName()) .destinationDefinitionId(standardDestinationDefinition.getDestinationDefinitionId()) diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/SourceHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/SourceHandlerTest.java index 664e81bbb107..c8157a8ae493 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/SourceHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/SourceHandlerTest.java @@ -5,6 +5,7 @@ package io.airbyte.server.handlers; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -64,6 +65,9 @@ class SourceHandlerTest { private JsonSecretsProcessor secretsProcessor; private ConnectorSpecification connectorSpecification; + // needs to match name of file in src/test/resources/icons + private static final String ICON = "test-source.svg"; + @SuppressWarnings("unchecked") @BeforeEach void setUp() throws IOException { @@ -84,7 +88,8 @@ void setUp() throws IOException { .withDockerRepository("thebestrepo") .withDockerImageTag("thelatesttag") .withDocumentationUrl("https://wikipedia.org") - .withSpec(connectorSpecification); + .withSpec(connectorSpecification) + .withIcon(ICON); sourceDefinitionSpecificationRead = new SourceDefinitionSpecificationRead() .sourceDefinitionId(standardSourceDefinition.getSourceDefinitionId()) @@ -190,6 +195,10 @@ void testGetSource() throws JsonValidationException, ConfigNotFoundException, IO final SourceRead actualSourceRead = sourceHandler.getSource(sourceIdRequestBody); assertEquals(expectedSourceRead, actualSourceRead); + + // make sure the icon was loaded into actual svg content + assertTrue(expectedSourceRead.getIcon().startsWith("")); + verify(secretsProcessor).prepareSecretsForOutput(sourceConnection.getConfiguration(), sourceDefinitionSpecificationRead.getConnectionSpecification()); } diff --git a/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java b/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java index a99bac040a27..37e79fed6e93 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java +++ b/airbyte-server/src/test/java/io/airbyte/server/handlers/WebBackendConnectionsHandlerTest.java @@ -26,7 +26,6 @@ import io.airbyte.api.model.generated.ConnectionCreate; import io.airbyte.api.model.generated.ConnectionIdRequestBody; import io.airbyte.api.model.generated.ConnectionRead; -import io.airbyte.api.model.generated.ConnectionReadList; import io.airbyte.api.model.generated.ConnectionSchedule; import io.airbyte.api.model.generated.ConnectionSchedule.TimeUnitEnum; import io.airbyte.api.model.generated.ConnectionState; @@ -56,6 +55,7 @@ import io.airbyte.api.model.generated.SyncMode; import io.airbyte.api.model.generated.SynchronousJobRead; import io.airbyte.api.model.generated.WebBackendConnectionCreate; +import io.airbyte.api.model.generated.WebBackendConnectionListItem; import io.airbyte.api.model.generated.WebBackendConnectionRead; import io.airbyte.api.model.generated.WebBackendConnectionReadList; import io.airbyte.api.model.generated.WebBackendConnectionRequestBody; @@ -106,6 +106,7 @@ class WebBackendConnectionsHandlerTest { private SourceRead sourceRead; private ConnectionRead connectionRead; + private WebBackendConnectionListItem expectedListItem; private OperationReadList operationReadList; private WebBackendConnectionRead expected; private WebBackendConnectionRead expectedWithNewSchema; @@ -119,6 +120,11 @@ class WebBackendConnectionsHandlerTest { private static final String FIELD3 = "field3"; private static final String FIELD5 = "field5"; + // needs to match name of file in src/test/resources/icons + private static final String SOURCE_ICON = "test-source.svg"; + private static final String DESTINATION_ICON = "test-destination.svg"; + private static final String SVG = ""; + @BeforeEach void setup() throws IOException, JsonValidationException, ConfigNotFoundException { connectionsHandler = mock(ConnectionsHandler.class); @@ -142,14 +148,18 @@ void setup() throws IOException, JsonValidationException, ConfigNotFoundExceptio configRepository); final StandardSourceDefinition standardSourceDefinition = SourceDefinitionHelpers.generateSourceDefinition(); + standardSourceDefinition.setIcon(SOURCE_ICON); final SourceConnection source = SourceHelpers.generateSource(UUID.randomUUID()); sourceRead = SourceHelpers.getSourceRead(source, standardSourceDefinition); final StandardDestinationDefinition destinationDefinition = DestinationDefinitionHelpers.generateDestination(); + destinationDefinition.setIcon(DESTINATION_ICON); final DestinationConnection destination = DestinationHelpers.generateDestination(UUID.randomUUID()); final DestinationRead destinationRead = DestinationHelpers.getDestinationRead(destination, destinationDefinition); final StandardSync standardSync = ConnectionHelpers.generateSyncWithSourceId(source.getSourceId()); + when(configRepository.listWorkspaceStandardSyncs(sourceRead.getWorkspaceId(), false)) + .thenReturn(Collections.singletonList(standardSync)); connectionRead = ConnectionHelpers.generateExpectedConnectionRead(standardSync); operationReadList = new OperationReadList() .operations(List.of(new OperationRead() @@ -184,6 +194,14 @@ void setup() throws IOException, JsonValidationException, ConfigNotFoundExceptio when(jobHistoryHandler.getLatestSyncJob(connectionRead.getConnectionId())).thenReturn(Optional.of(jobRead.getJob())); + expectedListItem = ConnectionHelpers.generateExpectedWebBackendConnectionListItem( + standardSync, + sourceRead, + destinationRead, + false, + jobRead.getJob().getCreatedAt(), + jobRead.getJob().getStatus()); + expected = new WebBackendConnectionRead() .connectionId(connectionRead.getConnectionId()) .sourceId(connectionRead.getSourceId()) @@ -281,20 +299,20 @@ void testGetWorkspaceStateEmpty() throws IOException { } @Test - void testWebBackendListConnectionsForWorkspace() throws ConfigNotFoundException, IOException, JsonValidationException { + void testWebBackendListConnectionsForWorkspace() throws ConfigNotFoundException, IOException, + JsonValidationException { final WorkspaceIdRequestBody workspaceIdRequestBody = new WorkspaceIdRequestBody(); workspaceIdRequestBody.setWorkspaceId(sourceRead.getWorkspaceId()); - final ConnectionReadList connectionReadList = new ConnectionReadList(); - connectionReadList.setConnections(Collections.singletonList(connectionRead)); - final ConnectionIdRequestBody connectionIdRequestBody = new ConnectionIdRequestBody(); - connectionIdRequestBody.setConnectionId(connectionRead.getConnectionId()); - when(connectionsHandler.listConnectionsForWorkspace(workspaceIdRequestBody)).thenReturn(connectionReadList); - when(operationsHandler.listOperationsForConnection(connectionIdRequestBody)).thenReturn(operationReadList); + final WebBackendConnectionReadList WebBackendConnectionReadList = + wbHandler.webBackendListConnectionsForWorkspace(workspaceIdRequestBody); - final WebBackendConnectionReadList WebBackendConnectionReadList = wbHandler.webBackendListConnectionsForWorkspace(workspaceIdRequestBody); assertEquals(1, WebBackendConnectionReadList.getConnections().size()); - assertEquals(expected, WebBackendConnectionReadList.getConnections().get(0)); + assertEquals(expectedListItem, WebBackendConnectionReadList.getConnections().get(0)); + + // make sure the icons were loaded into actual svg content + assertTrue(expectedListItem.getSource().getIcon().startsWith(SVG)); + assertTrue(expectedListItem.getDestination().getIcon().startsWith(SVG)); } @Test @@ -311,6 +329,10 @@ void testWebBackendGetConnection() throws ConfigNotFoundException, IOException, final WebBackendConnectionRead WebBackendConnectionRead = wbHandler.webBackendGetConnection(webBackendConnectionRequestBody); assertEquals(expected, WebBackendConnectionRead); + + // make sure the icons were loaded into actual svg content + assertTrue(expected.getSource().getIcon().startsWith(SVG)); + assertTrue(expected.getDestination().getIcon().startsWith(SVG)); } WebBackendConnectionRead testWebBackendGetConnection(final boolean withCatalogRefresh) diff --git a/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java b/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java index 07f3adf0ca9a..042b537dc1ed 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java +++ b/airbyte-server/src/test/java/io/airbyte/server/helpers/ConnectionHelpers.java @@ -17,8 +17,12 @@ import io.airbyte.api.model.generated.ConnectionScheduleDataBasicSchedule; import io.airbyte.api.model.generated.ConnectionScheduleType; import io.airbyte.api.model.generated.ConnectionStatus; +import io.airbyte.api.model.generated.DestinationRead; +import io.airbyte.api.model.generated.JobStatus; import io.airbyte.api.model.generated.ResourceRequirements; +import io.airbyte.api.model.generated.SourceRead; import io.airbyte.api.model.generated.SyncMode; +import io.airbyte.api.model.generated.WebBackendConnectionListItem; import io.airbyte.commons.text.Names; import io.airbyte.config.BasicSchedule; import io.airbyte.config.JobSyncConfig.NamespaceDefinitionType; @@ -201,6 +205,31 @@ public static ConnectionRead connectionReadFromStandardSync(final StandardSync s return connectionRead; } + public static WebBackendConnectionListItem generateExpectedWebBackendConnectionListItem( + final StandardSync standardSync, + final SourceRead source, + final DestinationRead destination, + final boolean isSyncing, + final Long latestSyncJobCreatedAt, + final JobStatus latestSynJobStatus) { + + final WebBackendConnectionListItem connectionListItem = new WebBackendConnectionListItem() + .connectionId(standardSync.getConnectionId()) + .name(standardSync.getName()) + .sourceId(standardSync.getSourceId()) + .destinationId(standardSync.getDestinationId()) + .source(source) + .destination(destination) + .status(ApiPojoConverters.toApiStatus(standardSync.getStatus())) + .isSyncing(isSyncing) + .latestSyncJobCreatedAt(latestSyncJobCreatedAt) + .latestSyncJobStatus(latestSynJobStatus) + .scheduleType(ApiPojoConverters.toApiConnectionScheduleType(standardSync)) + .scheduleData(ApiPojoConverters.toApiConnectionScheduleData(standardSync)); + + return connectionListItem; + } + public static JsonNode generateBasicJsonSchema() { return CatalogHelpers.fieldsToJsonSchema(Field.of(FIELD_NAME, JsonSchemaType.STRING)); } diff --git a/airbyte-server/src/test/java/io/airbyte/server/helpers/DestinationHelpers.java b/airbyte-server/src/test/java/io/airbyte/server/helpers/DestinationHelpers.java index ffdca4655cbf..a3eb07edee60 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/helpers/DestinationHelpers.java +++ b/airbyte-server/src/test/java/io/airbyte/server/helpers/DestinationHelpers.java @@ -9,6 +9,7 @@ import io.airbyte.commons.json.Jsons; import io.airbyte.config.DestinationConnection; import io.airbyte.config.StandardDestinationDefinition; +import io.airbyte.server.handlers.DestinationDefinitionsHandler; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -61,7 +62,8 @@ public static DestinationRead getDestinationRead(final DestinationConnection des .destinationId(destination.getDestinationId()) .connectionConfiguration(destination.getConfiguration()) .name(destination.getName()) - .destinationName(standardDestinationDefinition.getName()); + .destinationName(standardDestinationDefinition.getName()) + .icon(DestinationDefinitionsHandler.loadIcon(standardDestinationDefinition.getIcon())); } } diff --git a/airbyte-server/src/test/java/io/airbyte/server/helpers/SourceHelpers.java b/airbyte-server/src/test/java/io/airbyte/server/helpers/SourceHelpers.java index 964d6476c99e..975256c751a7 100644 --- a/airbyte-server/src/test/java/io/airbyte/server/helpers/SourceHelpers.java +++ b/airbyte-server/src/test/java/io/airbyte/server/helpers/SourceHelpers.java @@ -9,6 +9,7 @@ import io.airbyte.commons.json.Jsons; import io.airbyte.config.SourceConnection; import io.airbyte.config.StandardSourceDefinition; +import io.airbyte.server.handlers.SourceDefinitionsHandler; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -58,7 +59,8 @@ public static SourceRead getSourceRead(final SourceConnection source, final Stan .sourceId(source.getSourceId()) .connectionConfiguration(source.getConfiguration()) .name(source.getName()) - .sourceName(standardSourceDefinition.getName()); + .sourceName(standardSourceDefinition.getName()) + .icon(SourceDefinitionsHandler.loadIcon(standardSourceDefinition.getIcon())); } } diff --git a/airbyte-server/src/test/resources/icons/test-destination.svg b/airbyte-server/src/test/resources/icons/test-destination.svg new file mode 100644 index 000000000000..29fb9f8e862e --- /dev/null +++ b/airbyte-server/src/test/resources/icons/test-destination.svg @@ -0,0 +1,3 @@ + + destination + diff --git a/airbyte-server/src/test/resources/icons/test-source.svg b/airbyte-server/src/test/resources/icons/test-source.svg new file mode 100644 index 000000000000..7d81478ebd00 --- /dev/null +++ b/airbyte-server/src/test/resources/icons/test-source.svg @@ -0,0 +1,3 @@ + + source + diff --git a/airbyte-webapp/src/components/EntityTable/hooks.tsx b/airbyte-webapp/src/components/EntityTable/hooks.tsx index 37b1441c4d47..199be7d7b4f4 100644 --- a/airbyte-webapp/src/components/EntityTable/hooks.tsx +++ b/airbyte-webapp/src/components/EntityTable/hooks.tsx @@ -1,13 +1,13 @@ import { useSyncConnection } from "hooks/services/useConnectionHook"; -import { WebBackendConnectionRead } from "../../core/request/AirbyteClient"; +import { WebBackendConnectionListItem } from "../../core/request/AirbyteClient"; const useSyncActions = (): { - syncManualConnection: (connection: WebBackendConnectionRead) => Promise; + syncManualConnection: (connection: WebBackendConnectionListItem) => Promise; } => { const { mutateAsync: syncConnection } = useSyncConnection(); - const syncManualConnection = async (connection: WebBackendConnectionRead) => { + const syncManualConnection = async (connection: WebBackendConnectionListItem) => { await syncConnection(connection); }; diff --git a/airbyte-webapp/src/components/EntityTable/utils.tsx b/airbyte-webapp/src/components/EntityTable/utils.tsx index 0b20cc762d28..78744bd67b58 100644 --- a/airbyte-webapp/src/components/EntityTable/utils.tsx +++ b/airbyte-webapp/src/components/EntityTable/utils.tsx @@ -5,7 +5,7 @@ import { JobStatus, SourceDefinitionRead, SourceRead, - WebBackendConnectionRead, + WebBackendConnectionListItem, } from "../../core/request/AirbyteClient"; import { EntityTableDataItem, ITableDataItem, Status as ConnectionSyncStatus } from "./types"; @@ -18,7 +18,7 @@ export function getEntityTableData< S extends "source" | "destination", SoD extends S extends "source" ? SourceRead : DestinationRead, Def extends S extends "source" ? SourceDefinitionRead : DestinationDefinitionRead ->(entities: SoD[], connections: WebBackendConnectionRead[], definitions: Def[], type: S): EntityTableDataItem[] { +>(entities: SoD[], connections: WebBackendConnectionListItem[], definitions: Def[], type: S): EntityTableDataItem[] { const connectType = type === "source" ? "destination" : "source"; const mappedEntities = entities.map((entityItem) => { @@ -76,43 +76,32 @@ export function getEntityTableData< } export const getConnectionTableData = ( - connections: WebBackendConnectionRead[], - sourceDefinitions: SourceDefinitionRead[], - destinationDefinitions: DestinationDefinitionRead[], + connections: WebBackendConnectionListItem[], type: "source" | "destination" | "connection" ): ITableDataItem[] => { const connectType = type === "source" ? "destination" : "source"; - return connections.map((connection) => { - const sourceIcon = sourceDefinitions.find( - (definition) => definition.sourceDefinitionId === connection.source.sourceDefinitionId - )?.icon; - const destinationIcon = destinationDefinitions.find( - (definition) => definition.destinationDefinitionId === connection.destination.destinationDefinitionId - )?.icon; - - return { - connectionId: connection.connectionId, - name: connection.name, - entityName: - type === "connection" - ? `${connection.source?.sourceName} - ${connection.source?.name}` - : connection[connectType]?.name || "", - connectorName: - type === "connection" - ? `${connection.destination?.destinationName} - ${connection.destination?.name}` - : getConnectorTypeName(connection[connectType]), - lastSync: connection.latestSyncJobCreatedAt, - enabled: connection.status === ConnectionStatus.active, - scheduleData: connection.scheduleData, - scheduleType: connection.scheduleType, - status: connection.status, - isSyncing: connection.isSyncing, - lastSyncStatus: getConnectionSyncStatus(connection.status, connection.latestSyncJobStatus), - connectorIcon: type === "destination" ? sourceIcon : destinationIcon, - entityIcon: type === "destination" ? destinationIcon : sourceIcon, - }; - }); + return connections.map((connection) => ({ + connectionId: connection.connectionId, + name: connection.name, + entityName: + type === "connection" + ? `${connection.source?.sourceName} - ${connection.source?.name}` + : connection[connectType]?.name || "", + connectorName: + type === "connection" + ? `${connection.destination?.destinationName} - ${connection.destination?.name}` + : getConnectorTypeName(connection[connectType]), + lastSync: connection.latestSyncJobCreatedAt, + enabled: connection.status === ConnectionStatus.active, + scheduleData: connection.scheduleData, + scheduleType: connection.scheduleType, + status: connection.status, + isSyncing: connection.isSyncing, + lastSyncStatus: getConnectionSyncStatus(connection.status, connection.latestSyncJobStatus), + connectorIcon: type === "destination" ? connection.source.icon : connection.destination.icon, + entityIcon: type === "destination" ? connection.destination.icon : connection.source.icon, + })); }; export const getConnectionSyncStatus = ( diff --git a/airbyte-webapp/src/hooks/services/useConnectionHook.tsx b/airbyte-webapp/src/hooks/services/useConnectionHook.tsx index b6cd054eaff0..b8eeaa89d9cc 100644 --- a/airbyte-webapp/src/hooks/services/useConnectionHook.tsx +++ b/airbyte-webapp/src/hooks/services/useConnectionHook.tsx @@ -18,7 +18,9 @@ import { OperationCreate, SourceDefinitionRead, SourceRead, + WebBackendConnectionListItem, WebBackendConnectionRead, + WebBackendConnectionReadList, WebBackendConnectionUpdate, } from "../../core/request/AirbyteClient"; import { useSuspenseQuery } from "../../services/connector/useSuspenseQuery"; @@ -55,10 +57,6 @@ interface CreateConnectionProps { sourceCatalogId: string | undefined; } -export interface ListConnection { - connections: WebBackendConnectionRead[]; -} - function useWebConnectionService() { const config = useConfig(); const middlewares = useDefaultRequestMiddlewares(); @@ -95,7 +93,7 @@ export const useSyncConnection = () => { const service = useConnectionService(); const analyticsService = useAnalyticsService(); - return useMutation((connection: WebBackendConnectionRead) => { + return useMutation((connection: WebBackendConnectionRead | WebBackendConnectionListItem) => { analyticsService.track(Namespace.CONNECTION, Action.SYNC, { actionDescription: "Manual triggered sync", connector_source: connection.source?.sourceName, @@ -160,7 +158,7 @@ const useCreateConnection = () => { }, { onSuccess: (data) => { - queryClient.setQueryData(connectionsKeys.lists(), (lst: ListConnection | undefined) => ({ + queryClient.setQueryData(connectionsKeys.lists(), (lst) => ({ connections: [data, ...(lst?.connections ?? [])], })); }, @@ -184,13 +182,9 @@ const useDeleteConnection = () => { }); queryClient.removeQueries(connectionsKeys.detail(connection.connectionId)); - queryClient.setQueryData( - connectionsKeys.lists(), - (lst: ListConnection | undefined) => - ({ - connections: lst?.connections.filter((conn) => conn.connectionId !== connection.connectionId) ?? [], - } as ListConnection) - ); + queryClient.setQueryData(connectionsKeys.lists(), (lst) => ({ + connections: lst?.connections.filter((conn) => conn.connectionId !== connection.connectionId) ?? [], + })); }, }); }; @@ -203,7 +197,7 @@ const useUpdateConnection = () => { onSuccess: (updatedConnection) => { queryClient.setQueryData(connectionsKeys.detail(updatedConnection.connectionId), updatedConnection); // Update the connection inside the connections list response - queryClient.setQueryData(connectionsKeys.lists(), (ls) => ({ + queryClient.setQueryData(connectionsKeys.lists(), (ls) => ({ ...ls, connections: ls?.connections.map((conn) => { @@ -250,7 +244,7 @@ export const useRemoveConnectionsFromList = (): ((connectionIds: string[]) => vo return useCallback( (connectionIds: string[]) => { - queryClient.setQueryData(connectionsKeys.lists(), (ls: ListConnection | undefined) => ({ + queryClient.setQueryData(connectionsKeys.lists(), (ls) => ({ ...ls, connections: ls?.connections.filter((c) => !connectionIds.includes(c.connectionId)) ?? [], })); @@ -259,7 +253,7 @@ export const useRemoveConnectionsFromList = (): ((connectionIds: string[]) => vo ); }; -const useConnectionList = (): ListConnection => { +const useConnectionList = () => { const workspace = useCurrentWorkspace(); const service = useWebConnectionService(); diff --git a/airbyte-webapp/src/hooks/services/useDestinationHook.tsx b/airbyte-webapp/src/hooks/services/useDestinationHook.tsx index dabfe1610441..4652101f92ca 100644 --- a/airbyte-webapp/src/hooks/services/useDestinationHook.tsx +++ b/airbyte-webapp/src/hooks/services/useDestinationHook.tsx @@ -7,7 +7,7 @@ import { useInitService } from "services/useInitService"; import { isDefined } from "utils/common"; import { useConfig } from "../../config"; -import { DestinationRead, WebBackendConnectionRead } from "../../core/request/AirbyteClient"; +import { DestinationRead, WebBackendConnectionListItem } from "../../core/request/AirbyteClient"; import { useSuspenseQuery } from "../../services/connector/useSuspenseQuery"; import { SCOPE_WORKSPACE } from "../../services/Scope"; import { useDefaultRequestMiddlewares } from "../../services/useDefaultRequestMiddlewares"; @@ -97,7 +97,7 @@ const useDeleteDestination = () => { const removeConnectionsFromList = useRemoveConnectionsFromList(); return useMutation( - (payload: { destination: DestinationRead; connectionsWithDestination: WebBackendConnectionRead[] }) => + (payload: { destination: DestinationRead; connectionsWithDestination: WebBackendConnectionListItem[] }) => service.delete(payload.destination.destinationId), { onSuccess: (_data, ctx) => { diff --git a/airbyte-webapp/src/hooks/services/useSourceHook.tsx b/airbyte-webapp/src/hooks/services/useSourceHook.tsx index f54fe6925a85..dc275c1c96fe 100644 --- a/airbyte-webapp/src/hooks/services/useSourceHook.tsx +++ b/airbyte-webapp/src/hooks/services/useSourceHook.tsx @@ -10,7 +10,7 @@ import { JobInfo } from "core/domain/job"; import { useInitService } from "services/useInitService"; import { isDefined } from "utils/common"; -import { SourceRead, SynchronousJobRead, WebBackendConnectionRead } from "../../core/request/AirbyteClient"; +import { SourceRead, SynchronousJobRead, WebBackendConnectionListItem } from "../../core/request/AirbyteClient"; import { useSuspenseQuery } from "../../services/connector/useSuspenseQuery"; import { SCOPE_WORKSPACE } from "../../services/Scope"; import { useDefaultRequestMiddlewares } from "../../services/useDefaultRequestMiddlewares"; @@ -103,7 +103,7 @@ const useDeleteSource = () => { const removeConnectionsFromList = useRemoveConnectionsFromList(); return useMutation( - (payload: { source: SourceRead; connectionsWithSource: WebBackendConnectionRead[] }) => + (payload: { source: SourceRead; connectionsWithSource: WebBackendConnectionListItem[] }) => service.delete(payload.source.sourceId), { onSuccess: (_data, ctx) => { diff --git a/airbyte-webapp/src/pages/ConnectionPage/pages/AllConnectionsPage/components/ConnectionsTable.tsx b/airbyte-webapp/src/pages/ConnectionPage/pages/AllConnectionsPage/components/ConnectionsTable.tsx index 271c50608386..faf957589326 100644 --- a/airbyte-webapp/src/pages/ConnectionPage/pages/AllConnectionsPage/components/ConnectionsTable.tsx +++ b/airbyte-webapp/src/pages/ConnectionPage/pages/AllConnectionsPage/components/ConnectionsTable.tsx @@ -6,24 +6,17 @@ import useSyncActions from "components/EntityTable/hooks"; import { ITableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; -import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService"; -import { useSourceDefinitionList } from "services/connector/SourceDefinitionService"; - -import { WebBackendConnectionRead } from "../../../../../core/request/AirbyteClient"; +import { WebBackendConnectionListItem } from "../../../../../core/request/AirbyteClient"; interface IProps { - connections: WebBackendConnectionRead[]; + connections: WebBackendConnectionListItem[]; } const ConnectionsTable: React.FC = ({ connections }) => { const navigate = useNavigate(); const { syncManualConnection } = useSyncActions(); - const { sourceDefinitions } = useSourceDefinitionList(); - - const { destinationDefinitions } = useDestinationDefinitionList(); - - const data = getConnectionTableData(connections, sourceDefinitions, destinationDefinitions, "connection"); + const data = getConnectionTableData(connections, "connection"); const onSync = useCallback( async (connectionId: string) => { diff --git a/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationConnectionTable.tsx b/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationConnectionTable.tsx index ce9f783c44d8..1385ae462a67 100644 --- a/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationConnectionTable.tsx +++ b/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationConnectionTable.tsx @@ -7,23 +7,18 @@ import { ITableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; import { RoutePaths } from "pages/routePaths"; -import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService"; -import { useSourceDefinitionList } from "services/connector/SourceDefinitionService"; -import { WebBackendConnectionRead } from "../../../../../core/request/AirbyteClient"; +import { WebBackendConnectionListItem } from "../../../../../core/request/AirbyteClient"; interface IProps { - connections: WebBackendConnectionRead[]; + connections: WebBackendConnectionListItem[]; } const DestinationConnectionTable: React.FC = ({ connections }) => { const navigate = useNavigate(); const { syncManualConnection } = useSyncActions(); - const { sourceDefinitions } = useSourceDefinitionList(); - const { destinationDefinitions } = useDestinationDefinitionList(); - - const data = getConnectionTableData(connections, sourceDefinitions, destinationDefinitions, "destination"); + const data = getConnectionTableData(connections, "destination"); const onSync = useCallback( async (connectionId: string) => { diff --git a/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationSettings.tsx b/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationSettings.tsx index 39e2e9ac61fe..84140aad0f39 100644 --- a/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationSettings.tsx +++ b/airbyte-webapp/src/pages/DestinationPage/pages/DestinationItemPage/components/DestinationSettings.tsx @@ -5,7 +5,7 @@ import DeleteBlock from "components/DeleteBlock"; import { ConnectionConfiguration } from "core/domain/connection"; import { Connector } from "core/domain/connector"; -import { DestinationRead, WebBackendConnectionRead } from "core/request/AirbyteClient"; +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"; @@ -17,7 +17,7 @@ import styles from "./DestinationSettings.module.scss"; interface DestinationsSettingsProps { currentDestination: DestinationRead; - connectionsWithDestination: WebBackendConnectionRead[]; + connectionsWithDestination: WebBackendConnectionListItem[]; } const DestinationsSettings: React.FC = ({ diff --git a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx index b05f846ffb0a..ece281855fba 100644 --- a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx +++ b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceConnectionTable.tsx @@ -7,24 +7,18 @@ import { ITableDataItem } from "components/EntityTable/types"; import { getConnectionTableData } from "components/EntityTable/utils"; import { RoutePaths } from "pages/routePaths"; -import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService"; -import { useSourceDefinitionList } from "services/connector/SourceDefinitionService"; -import { WebBackendConnectionRead } from "../../../../../core/request/AirbyteClient"; +import { WebBackendConnectionListItem } from "../../../../../core/request/AirbyteClient"; interface IProps { - connections: WebBackendConnectionRead[]; + connections: WebBackendConnectionListItem[]; } const SourceConnectionTable: React.FC = ({ connections }) => { const navigate = useNavigate(); const { syncManualConnection } = useSyncActions(); - const { sourceDefinitions } = useSourceDefinitionList(); - - const { destinationDefinitions } = useDestinationDefinitionList(); - - const data = getConnectionTableData(connections, sourceDefinitions, destinationDefinitions, "source"); + const data = getConnectionTableData(connections, "source"); const onSync = useCallback( async (connectionId: string) => { diff --git a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.tsx b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.tsx index 75d66f656807..e21270e44686 100644 --- a/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.tsx +++ b/airbyte-webapp/src/pages/SourcesPage/pages/SourceItemPage/components/SourceSettings.tsx @@ -4,7 +4,7 @@ import { FormattedMessage } from "react-intl"; import DeleteBlock from "components/DeleteBlock"; import { ConnectionConfiguration } from "core/domain/connection"; -import { SourceRead, WebBackendConnectionRead } from "core/request/AirbyteClient"; +import { SourceRead, WebBackendConnectionListItem } from "core/request/AirbyteClient"; import { useTrackPage, PageTrackingCodes } from "hooks/services/Analytics"; import { useFormChangeTrackerService, useUniqueFormId } from "hooks/services/FormChangeTracker"; import { useDeleteSource, useUpdateSource } from "hooks/services/useSourceHook"; @@ -17,7 +17,7 @@ import styles from "./SourceSettings.module.scss"; interface SourceSettingsProps { currentSource: SourceRead; - connectionsWithSource: WebBackendConnectionRead[]; + connectionsWithSource: WebBackendConnectionListItem[]; } const SourceSettings: React.FC = ({ currentSource, connectionsWithSource }) => { diff --git a/docs/reference/api/generated-api-html/index.html b/docs/reference/api/generated-api-html/index.html index 27e64c19e811..3dd1afae62a9 100644 --- a/docs/reference/api/generated-api-html/index.html +++ b/docs/reference/api/generated-api-html/index.html @@ -2276,6 +2276,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2341,6 +2342,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2451,6 +2453,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2517,6 +2520,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2526,6 +2530,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2593,6 +2598,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2602,6 +2608,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -2665,6 +2672,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6371,6 +6379,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6436,6 +6445,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6647,6 +6657,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6713,6 +6724,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6722,6 +6734,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6789,6 +6802,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6798,6 +6812,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -6861,6 +6876,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -8239,6 +8255,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -8250,6 +8267,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -8448,6 +8466,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -8459,6 +8478,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -8714,17 +8734,19 @@

Example data

"connections" : [ { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "latestSyncJobCreatedAt" : 0, - "prefix" : "prefix", + "name" : "name", "destination" : { "connectionConfiguration" : { "user" : "charles" }, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" }, + "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "isSyncing" : true, "source" : { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", @@ -8732,131 +8754,12 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" }, "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "catalogDiff" : { - "transforms" : [ { - "streamDescriptor" : { - "name" : "name", - "namespace" : "namespace" - }, - "transformType" : "add_stream", - "updateStream" : [ { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - }, { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - } ] - }, { - "streamDescriptor" : { - "name" : "name", - "namespace" : "namespace" - }, - "transformType" : "add_stream", - "updateStream" : [ { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - }, { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - } ] - } ] - }, - "resourceRequirements" : { - "cpu_limit" : "cpu_limit", - "memory_request" : "memory_request", - "memory_limit" : "memory_limit", - "cpu_request" : "cpu_request" - }, - "schedule" : { - "units" : 0, - "timeUnit" : "minutes" - }, - "operations" : [ { - "name" : "name", - "operationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "operatorConfiguration" : { - "normalization" : { - "option" : "basic" - }, - "dbt" : { - "gitRepoBranch" : "gitRepoBranch", - "dockerImage" : "dockerImage", - "dbtArguments" : "dbtArguments", - "gitRepoUrl" : "gitRepoUrl" - } - }, - "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" - }, { - "name" : "name", - "operationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "operatorConfiguration" : { - "normalization" : { - "option" : "basic" - }, - "dbt" : { - "gitRepoBranch" : "gitRepoBranch", - "dockerImage" : "dockerImage", - "dbtArguments" : "dbtArguments", - "gitRepoUrl" : "gitRepoUrl" - } - }, - "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" - } ], - "catalogId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "name" : "name", - "syncCatalog" : { - "streams" : [ { - "stream" : { - "sourceDefinedPrimaryKey" : [ [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ], [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ] ], - "supportedSyncModes" : [ null, null ], - "sourceDefinedCursor" : true, - "name" : "name", - "namespace" : "namespace", - "defaultCursorField" : [ "defaultCursorField", "defaultCursorField" ] - }, - "config" : { - "aliasName" : "aliasName", - "cursorField" : [ "cursorField", "cursorField" ], - "selected" : true, - "primaryKey" : [ [ "primaryKey", "primaryKey" ], [ "primaryKey", "primaryKey" ] ] - } - }, { - "stream" : { - "sourceDefinedPrimaryKey" : [ [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ], [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ] ], - "supportedSyncModes" : [ null, null ], - "sourceDefinedCursor" : true, - "name" : "name", - "namespace" : "namespace", - "defaultCursorField" : [ "defaultCursorField", "defaultCursorField" ] - }, - "config" : { - "aliasName" : "aliasName", - "cursorField" : [ "cursorField", "cursorField" ], - "selected" : true, - "primaryKey" : [ [ "primaryKey", "primaryKey" ], [ "primaryKey", "primaryKey" ] ] - } - } ] - }, - "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ], "scheduleData" : { "cron" : { "cronExpression" : "cronExpression", @@ -8870,17 +8773,19 @@

Example data

}, { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "latestSyncJobCreatedAt" : 0, - "prefix" : "prefix", + "name" : "name", "destination" : { "connectionConfiguration" : { "user" : "charles" }, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" }, + "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "isSyncing" : true, "source" : { "sourceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", @@ -8888,131 +8793,12 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" }, "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "catalogDiff" : { - "transforms" : [ { - "streamDescriptor" : { - "name" : "name", - "namespace" : "namespace" - }, - "transformType" : "add_stream", - "updateStream" : [ { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - }, { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - } ] - }, { - "streamDescriptor" : { - "name" : "name", - "namespace" : "namespace" - }, - "transformType" : "add_stream", - "updateStream" : [ { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - }, { - "updateFieldSchema" : { }, - "fieldName" : [ "fieldName", "fieldName" ], - "addField" : { }, - "transformType" : "add_field", - "removeField" : { } - } ] - } ] - }, - "resourceRequirements" : { - "cpu_limit" : "cpu_limit", - "memory_request" : "memory_request", - "memory_limit" : "memory_limit", - "cpu_request" : "cpu_request" - }, - "schedule" : { - "units" : 0, - "timeUnit" : "minutes" - }, - "operations" : [ { - "name" : "name", - "operationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "operatorConfiguration" : { - "normalization" : { - "option" : "basic" - }, - "dbt" : { - "gitRepoBranch" : "gitRepoBranch", - "dockerImage" : "dockerImage", - "dbtArguments" : "dbtArguments", - "gitRepoUrl" : "gitRepoUrl" - } - }, - "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" - }, { - "name" : "name", - "operationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "operatorConfiguration" : { - "normalization" : { - "option" : "basic" - }, - "dbt" : { - "gitRepoBranch" : "gitRepoBranch", - "dockerImage" : "dockerImage", - "dbtArguments" : "dbtArguments", - "gitRepoUrl" : "gitRepoUrl" - } - }, - "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" - } ], - "catalogId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "name" : "name", - "syncCatalog" : { - "streams" : [ { - "stream" : { - "sourceDefinedPrimaryKey" : [ [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ], [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ] ], - "supportedSyncModes" : [ null, null ], - "sourceDefinedCursor" : true, - "name" : "name", - "namespace" : "namespace", - "defaultCursorField" : [ "defaultCursorField", "defaultCursorField" ] - }, - "config" : { - "aliasName" : "aliasName", - "cursorField" : [ "cursorField", "cursorField" ], - "selected" : true, - "primaryKey" : [ [ "primaryKey", "primaryKey" ], [ "primaryKey", "primaryKey" ] ] - } - }, { - "stream" : { - "sourceDefinedPrimaryKey" : [ [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ], [ "sourceDefinedPrimaryKey", "sourceDefinedPrimaryKey" ] ], - "supportedSyncModes" : [ null, null ], - "sourceDefinedCursor" : true, - "name" : "name", - "namespace" : "namespace", - "defaultCursorField" : [ "defaultCursorField", "defaultCursorField" ] - }, - "config" : { - "aliasName" : "aliasName", - "cursorField" : [ "cursorField", "cursorField" ], - "selected" : true, - "primaryKey" : [ [ "primaryKey", "primaryKey" ], [ "primaryKey", "primaryKey" ] ] - } - } ] - }, - "connectionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", - "namespaceFormat" : "${SOURCE_NAMESPACE}", - "operationIds" : [ null, null ], "scheduleData" : { "cron" : { "cronExpression" : "cronExpression", @@ -9096,6 +8882,7 @@

Example data

}, "destinationName" : "destinationName", "name" : "name", + "icon" : "icon", "destinationDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "destinationId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -9107,6 +8894,7 @@

Example data

"user" : "charles" }, "name" : "name", + "icon" : "icon", "sourceDefinitionId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91", "sourceName" : "sourceName", "workspaceId" : "046b6c7f-0b8a-43b9-b35d-6489e6daee91" @@ -10021,6 +9809,7 @@

Table of Contents

  • SynchronousJobRead -
  • UploadRead -
  • WebBackendConnectionCreate -
  • +
  • WebBackendConnectionListItem -
  • WebBackendConnectionRead -
  • WebBackendConnectionReadList -
  • WebBackendConnectionRequestBody -
  • @@ -10619,6 +10408,7 @@

    DestinationRead - connectionConfiguration
    name
    destinationName
    +
    icon (optional)
    @@ -11289,6 +11079,7 @@

    SourceRead - connectionConfiguration

    name
    sourceName
    +
    icon (optional)
    @@ -11396,6 +11187,24 @@

    WebBackendConnectionCreate
    sourceCatalogId (optional)
    UUID format: uuid

    +
    +

    WebBackendConnectionListItem - Up

    +
    Information about a connection that shows up in the connection list view.
    +
    +
    connectionId
    UUID format: uuid
    +
    name
    +
    sourceId
    UUID format: uuid
    +
    destinationId
    UUID format: uuid
    +
    scheduleType (optional)
    +
    scheduleData (optional)
    +
    status
    +
    source
    +
    destination
    +
    latestSyncJobCreatedAt (optional)
    Long epoch time of the latest sync job. null if no sync job has taken place. format: int64
    +
    latestSyncJobStatus (optional)
    +
    isSyncing
    +
    +