Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter connections list on source or destination item pages #21027

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Heading } from "components/ui/Heading";
import { Text } from "components/ui/Text";

import { ReleaseStage } from "core/request/AirbyteClient";
import { getIcon } from "utils/imageUtils";

import { Button } from "../ui/Button";
import styles from "./TableItemTitle.module.scss";
Expand All @@ -17,7 +18,7 @@ interface TableItemTitleProps {
onSelect: (data: DropdownMenuOptionType) => void;
entity: string;
entityName: string;
entityIcon?: React.ReactNode;
entityIcon?: string;
releaseStage?: ReleaseStage;
}

Expand All @@ -35,7 +36,7 @@ const TableItemTitle: React.FC<TableItemTitleProps> = ({
return (
<>
<div className={styles.entityInfo}>
{entityIcon && <div className={styles.entityIcon}>{entityIcon}</div>}
{entityIcon && <div className={styles.entityIcon}>{getIcon(entityIcon)}</div>}
<div>
<Heading as="h2">{entityName}</Heading>
<Text size="lg" bold className={styles.entityType}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
WebBackendConnectionCreate,
WebBackendConnectionListRequestBody,
WebBackendConnectionUpdate,
webBackendCreateConnection,
webBackendGetConnection,
Expand All @@ -13,8 +14,8 @@ export class WebBackendConnectionService extends AirbyteRequestService {
return webBackendGetConnection({ connectionId, withRefreshedCatalog }, this.requestOptions);
}

public list(workspaceId: string) {
return webBackendListConnectionsForWorkspace({ workspaceId }, this.requestOptions);
public list(payload: WebBackendConnectionListRequestBody) {
return webBackendListConnectionsForWorkspace(payload, this.requestOptions);
}

public update(payload: WebBackendConnectionUpdate) {
Expand Down
10 changes: 6 additions & 4 deletions airbyte-webapp/src/hooks/services/useConnectionHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
SourceDefinitionRead,
SourceRead,
WebBackendConnectionListItem,
WebBackendConnectionListRequestBody,
WebBackendConnectionRead,
WebBackendConnectionReadList,
WebBackendConnectionUpdate,
Expand All @@ -31,8 +32,7 @@ import { useCurrentWorkspace } from "./useWorkspace";

export const connectionsKeys = {
all: [SCOPE_WORKSPACE, "connections"] as const,
lists: () => [...connectionsKeys.all, "list"] as const,
list: (filters: string) => [...connectionsKeys.lists(), { filters }] as const,
lists: (sourceOrDestinationIds: string[] = []) => [...connectionsKeys.all, "list", ...sourceOrDestinationIds],
detail: (connectionId: string) => [...connectionsKeys.all, "details", connectionId] as const,
getState: (connectionId: string) => [...connectionsKeys.all, "getState", connectionId] as const,
};
Expand Down Expand Up @@ -236,11 +236,13 @@ export const useRemoveConnectionsFromList = (): ((connectionIds: string[]) => vo
);
};

const useConnectionList = () => {
const useConnectionList = (payload: Pick<WebBackendConnectionListRequestBody, "destinationId" | "sourceId"> = {}) => {
const workspace = useCurrentWorkspace();
const service = useWebConnectionService();

return useSuspenseQuery(connectionsKeys.lists(), () => service.list(workspace.workspaceId));
return useSuspenseQuery(connectionsKeys.lists(payload.destinationId ?? payload.sourceId), () =>
service.list({ ...payload, workspaceId: workspace.workspaceId })
);
};

const useGetConnectionState = (connectionId: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ import { PageHeader } from "components/ui/PageHeader";

import { useTrackPage, PageTrackingCodes } from "hooks/services/Analytics";
import { useConnectionList } from "hooks/services/useConnectionHook";
import { useDestinationList } from "hooks/services/useDestinationHook";
import { useGetSource } from "hooks/services/useSourceHook";
import { useDestinationDefinitionList } from "services/connector/DestinationDefinitionService";
import { useSourceDefinition } from "services/connector/SourceDefinitionService";
import { getIcon } from "utils/imageUtils";
import { ConnectorDocumentationWrapper } from "views/Connector/ConnectorDocumentationLayout";

import { DropdownMenuOptionType } from "../../../../components/ui/DropdownMenu";
import { useDestinationList } from "../../../../hooks/services/useDestinationHook";
import { RoutePaths } from "../../../routePaths";
import SourceConnectionTable from "./components/SourceConnectionTable";
import SourceSettings from "./components/SourceSettings";
Expand All @@ -35,14 +33,11 @@ const SourceItemPage: React.FC = () => {
[params]
);

const { destinations } = useDestinationList();

const { destinationDefinitions } = useDestinationDefinitionList();

const source = useGetSource(params.id || "");
const sourceDefinition = useSourceDefinition(source?.sourceDefinitionId);
const sourceDefinition = useSourceDefinition(source.sourceDefinitionId);

const { connections } = useConnectionList();
// We load only connections attached to this source to be shown in the connections grid
const { connections } = useConnectionList({ sourceId: [source.sourceId] });

const breadcrumbsData = [
{
Expand All @@ -52,23 +47,20 @@ const SourceItemPage: React.FC = () => {
{ label: source.name },
];

const connectionsWithSource = connections.filter(({ source: { sourceId } }) => sourceId === source.sourceId);

// We load all destinations so the add destination button has a pre-filled list of options.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We load all destinations so the add destination button has a pre-filled list of options.
// We load all configured destinations so the add destination button has a pre-filled list of options.

const { destinations } = useDestinationList();
const destinationDropdownOptions: DropdownMenuOptionType[] = useMemo(
() =>
destinations.map((item) => {
const destinationDef = destinationDefinitions.find(
(dd) => dd.destinationDefinitionId === item.destinationDefinitionId
);
destinations.map((destination) => {
return {
as: "button",
icon: <ConnectorIcon icon={destinationDef?.icon} />,
icon: <ConnectorIcon icon={destination.icon} />,
iconPosition: "right",
displayName: item.name,
value: item.destinationId,
displayName: destination.name,
value: destination.destinationId,
};
}),
[destinations, destinationDefinitions]
[destinations]
);

const onSelectStep = (id: string) => {
Expand Down Expand Up @@ -102,7 +94,7 @@ const SourceItemPage: React.FC = () => {
<Routes>
<Route
path="/settings"
element={<SourceSettings currentSource={source} connectionsWithSource={connectionsWithSource} />}
element={<SourceSettings currentSource={source} connectionsWithSource={connections} />}
/>
<Route
index
Expand All @@ -114,11 +106,11 @@ const SourceItemPage: React.FC = () => {
onSelect={onSelect}
entity={source.sourceName}
entityName={source.name}
entityIcon={sourceDefinition ? getIcon(sourceDefinition.icon) : null}
entityIcon={source.icon}
releaseStage={sourceDefinition.releaseStage}
/>
{connectionsWithSource.length ? (
<SourceConnectionTable connections={connectionsWithSource} />
{connections.length ? (
<SourceConnectionTable connections={connections} />
) : (
<Placeholder resource={ResourceTypes.Destinations} />
)}
Expand Down
33 changes: 14 additions & 19 deletions airbyte-webapp/src/pages/destination/DestinationOverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,30 @@ import { useGetDestination } from "hooks/services/useDestinationHook";
import { useSourceList } from "hooks/services/useSourceHook";
import { DestinationPaths } from "pages/routePaths";
import { useDestinationDefinition } from "services/connector/DestinationDefinitionService";
import { useSourceDefinitionList } from "services/connector/SourceDefinitionService";
import { getIcon } from "utils/imageUtils";

export const DestinationOverviewPage = () => {
const params = useParams() as { "*": StepsTypes | ""; id: string };
const { sources } = useSourceList();
const navigate = useNavigate();

const destination = useGetDestination(params.id);
const destinationDefinition = useDestinationDefinition(destination.destinationDefinitionId);
const { connections } = useConnectionList();
const { sourceDefinitions } = useSourceDefinitionList();
// We load only connections attached to this destination to be shown in the connections grid
const { connections } = useConnectionList({ destinationId: [destination.destinationId] });

const connectionsWithDestination = connections.filter(
({ destination: { destinationId } }) => destinationId === destination.destinationId
);

const sourceDropdownOptions: DropdownMenuOptionType[] = useMemo(
// We load all sources so the add source button has a pre-filled list of options.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// We load all sources so the add source button has a pre-filled list of options.
// We load all configured sources so the add source button has a pre-filled list of options.

const { sources } = useSourceList();
const sourceDropdownOptions = useMemo<DropdownMenuOptionType[]>(
() =>
sources.map((item) => {
const sourceDef = sourceDefinitions.find((sd) => sd.sourceDefinitionId === item.sourceDefinitionId);
sources.map((source) => {
return {
as: "button",
icon: <ConnectorIcon icon={sourceDef?.icon} />,
icon: <ConnectorIcon icon={source.icon} />,
iconPosition: "right",
displayName: item.name,
value: item.sourceId,
displayName: source.name,
value: source.sourceId,
};
}),
[sources, sourceDefinitions]
[sources]
);

const onSelect = (data: DropdownMenuOptionType) => {
Expand All @@ -64,11 +59,11 @@ export const DestinationOverviewPage = () => {
onSelect={onSelect}
entityName={destination.name}
entity={destination.destinationName}
entityIcon={destinationDefinition.icon ? getIcon(destinationDefinition.icon) : null}
entityIcon={destination.icon}
releaseStage={destinationDefinition.releaseStage}
/>
{connectionsWithDestination.length ? (
<DestinationConnectionTable connections={connectionsWithDestination} />
{connections.length ? (
<DestinationConnectionTable connections={connections} />
) : (
<Placeholder resource={ResourceTypes.Sources} />
)}
Expand Down