Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Connect workflow #64

Merged
merged 9 commits into from
Oct 24, 2024
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
2 changes: 1 addition & 1 deletion apps/web/app/connect/portal/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default async function PortalPage({
}

const isAgMode =
viewer.orgId = 'org_2nJZrA4Dk8i3wszhm6PsP3M2Vwy' ||
viewer.orgId === 'org_2nJZrA4Dk8i3wszhm6PsP3M2Vwy' ||
viewer.orgId === 'org_2lcCCimyICKI8cpPNQt195h5zrP' ||
viewer.orgId === 'org_2ms9FdeczlbrDIHJLcwGdpv3dTx'

Expand Down
29 changes: 29 additions & 0 deletions packages/engine-frontend/components/AddConnectionTabContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type {ConnectorConfigFilters} from '../hocs/WithConnectConfig'
import {ConnectIntegrations} from './ConnectIntegrations'

interface AddConnectionTabContentProps {
connectorConfigFilters: ConnectorConfigFilters
refetch: () => void
}

export function AddConnectionTabContent({
connectorConfigFilters,
refetch,
}: AddConnectionTabContentProps) {
return (
<div className="flex flex-col gap-2 p-4">
<div>
<p className="text-base font-semibold">Setup a new Connection</p>
<p className="text-base">Choose a connector config to start</p>
</div>
<ConnectIntegrations
connectorConfigFilters={connectorConfigFilters}
onEvent={(event) => {
if (event.type === 'close') {
refetch()
}
}}
/>
</div>
)
}
34 changes: 34 additions & 0 deletions packages/engine-frontend/components/ConnectIntegrations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
WithConnectConfig,
type ConnectorConfigFilters,
} from '../hocs/WithConnectConfig'
import {IntegrationSearch} from './IntegrationSearch'

export function ConnectIntegrations({
connectorConfigFilters,
connectorNames = [],
onEvent,
}: {
connectorConfigFilters: ConnectorConfigFilters
connectorNames?: string[]
onEvent: (event: any) => void
}) {
return (
<WithConnectConfig {...connectorConfigFilters}>
{({ccfgs}) => {
const filteredCcfgs = ccfgs.filter(
(c) => !connectorNames.includes(c.connectorName),
)

return (
<IntegrationSearch
connectorConfigs={filteredCcfgs}
onEvent={(e) => {
if (onEvent) onEvent(e)
}}
/>
)
}}
</WithConnectConfig>
)
}
177 changes: 32 additions & 145 deletions packages/engine-frontend/components/ConnectionPortal.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,15 @@
'use client'

import {Loader, Settings} from 'lucide-react'
import type {Id} from '@openint/cdk'
import type {UIPropsNoChildren} from '@openint/ui'
import {
Badge,
ConnectorLogo,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
Separator,
useToast,
} from '@openint/ui'
import {Tabs, TabsContent, TabsList, TabsTrigger} from '@openint/ui/shadcn/Tabs'
import {useToast} from '@openint/ui'
import {Tabs} from '@openint/ui/components/Tabs'
import {cn} from '@openint/ui/utils'
import {R} from '@openint/util'
import {WithConnectConfig} from '../hocs/WithConnectConfig'
import {_trpcReact} from '../providers/TRPCProvider'
import {ConnectDialog} from './ConnectDialog'
import {AddConnectionTabContent} from './AddConnectionTabContent'
import {ConnectionsTabContent} from './ConnectionsTabContent'

type ConnectEventType = 'open' | 'close' | 'error'

Expand Down Expand Up @@ -77,139 +68,35 @@ export function ConnectionPortal({className}: ConnectionPortalProps) {
const connectionCount = connections.length
console.log({connectionCount})

const tabConfig = [
{
key: 'connections',
title: `My Connections (${connectionCount})`,
content: (
<ConnectionsTabContent
connectionCount={connectionCount}
refetch={listConnectionsRes.refetch}
isLoading={listConnectionsRes.isLoading}
deleteResource={deleteResource.mutate}
categoriesWithConnections={categoriesWithConnections}
/>
),
},
{
key: 'add-connection',
title: 'Add a Connection',
content: (
<AddConnectionTabContent
connectorConfigFilters={{}}
refetch={listConnectionsRes.refetch}
/>
),
},
]

return (
<div className={cn('gap-4 p-8', className)}>
{/* Listing by categories */}
<Tabs defaultValue="connections" className="w-[400px]">
<TabsList>
<TabsTrigger value="connections">
My Connections ({connectionCount})
</TabsTrigger>
<TabsTrigger value="add-connection">
Add a Connection
</TabsTrigger>
</TabsList>
<TabsContent value="connections">
{connectionCount === 0 ? (
<div className="flex flex-col gap-2 p-4">
<div>
<p className="text-base font-semibold">
No connections yet
</p>
<p className="text-base">
Add a connection to get started
</p>
</div>
<ConnectDialog
className="self-end bg-[#8A5DF6] hover:bg-[#A082E9]"
connectorConfigFilters={{}}
onEvent={(event) => {
if (event.type === 'close') {
listConnectionsRes.refetch(); // Trigger refetch
}
}}
></ConnectDialog>
</div>
) : (
<div className="p-4">
{listConnectionsRes.isLoading ? (
<div className="flex h-full items-center justify-center">
<Loader className="size-5 animate-spin text-[#8A5DF6]" />
</div>
) : (
categoriesWithConnections.map((category) => (
<div
key={category.name}
className="flex flex-col space-y-4">
{category.connections.map((conn) => (
<>
<div
key={conn.id}
className="flex flex-row justify-between gap-4">
<div className="flex flex-row gap-4">
<ConnectorLogo
connector={conn.connectorConfig.connector}
className="size-[64px] rounded-lg"
/>
<div className="flex h-full flex-col justify-center">
<div className="flex flex-row items-center gap-2">
<h4 className="font-bold">
{conn.connectorName
.charAt(0)
.toUpperCase() +
conn.connectorName.slice(1)}
</h4>
<Badge variant="secondary">
{category.name}
</Badge>
</div>
{conn.pipelineIds.length > 0 && (
<div className="mt-2">
{conn.syncInProgress ? (
<div className="flex flex-row items-center justify-start gap-2">
<Loader className="size-5 animate-spin text-[#8A5DF6]" />
<p className="font-semibold">
Syncing...
</p>
</div>
) : (
<p>Successfully synced</p>
)}
</div>
)}
</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger>
<Settings className="size-5 text-[#808080]" />
</DropdownMenuTrigger>
<DropdownMenuContent className="flex w-[80px] items-center justify-center">
<DropdownMenuItem
className="flex items-center justify-center"
onSelect={() =>
deleteResource.mutate({id: conn.id})
}>
<span className="text-center font-medium text-red-500">
Delete
</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
{/* TODO: Improve the condition to hide the separator for the last item, right now it iterates
over all categories and all connections, would be good to have a single array of connections with the category
information included already */}
<Separator className="w-full" />
</>
))}
</div>
))
)}
</div>
)}
</TabsContent>
<TabsContent value="add-connection">
<div className="flex flex-col gap-2 p-4">
<div>
<p className="text-base font-semibold">
Setup a new Connection
</p>
<p className="text-base">
Choose a connector config to start
</p>
</div>
<ConnectDialog
className="self-end bg-[#8A5DF6] hover:bg-[#A082E9]"
connectorConfigFilters={{}}
onEvent={(event) => {
if (event.type === 'close') {
listConnectionsRes.refetch(); // Trigger refetch
}
}}
></ConnectDialog>
</div>
</TabsContent>
</Tabs>
<div className={cn('gap-4 p-4 lg:p-8', className)}>
<Tabs tabConfig={tabConfig} defaultValue="connections" />
</div>
)
}}
Expand Down
120 changes: 120 additions & 0 deletions packages/engine-frontend/components/ConnectionsTabContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {Loader, Settings} from 'lucide-react'
import {
Badge,
ConnectorLogo,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
Separator,
} from '@openint/ui'
import type {ConnectorConfig} from '../hocs/WithConnectConfig'
import {ConnectDialog} from './ConnectDialog'

interface ConnectionsTabContentProps {
connectionCount: number
categoriesWithConnections: Array<{
name: string
connections: Array<{
id: string
connectorConfig: ConnectorConfig
connectorName: string
pipelineIds: string[]
syncInProgress: boolean
}>
}>
refetch: () => void
isLoading: boolean
deleteResource: ({id}: {id: string}) => void
}

export function ConnectionsTabContent({
connectionCount,
refetch,
isLoading,
deleteResource,
categoriesWithConnections,
}: ConnectionsTabContentProps) {
return connectionCount === 0 ? (
<div className="flex flex-col gap-2 p-4">
<div>
<p className="text-base font-semibold">No connections yet</p>
<p className="text-base">Add a connection to get started</p>
</div>
<ConnectDialog
className="self-end bg-[#8A5DF6] hover:bg-[#A082E9]"
connectorConfigFilters={{}}
onEvent={(event) => {
if (event.type === 'close') {
refetch() // Trigger refetch
}
}}></ConnectDialog>
</div>
) : (
<div className="p-4">
{isLoading ? (
<div className="flex h-full items-center justify-center">
<Loader className="size-5 animate-spin text-[#8A5DF6]" />
</div>
) : (
categoriesWithConnections.map((category) => (
<div key={category.name} className="flex flex-col space-y-4">
{category.connections.map((conn) => (
<>
<div
key={conn.id}
className="flex flex-row justify-between gap-4">
<div className="flex flex-row gap-4">
<ConnectorLogo
connector={conn.connectorConfig.connector}
className="size-[64px] rounded-lg"
/>
<div className="flex h-full flex-col justify-center">
<div className="flex flex-row items-center gap-2">
<h4 className="font-bold">
{conn.connectorName.charAt(0).toUpperCase() +
conn.connectorName.slice(1)}
</h4>
<Badge variant="secondary">{category.name}</Badge>
</div>
{conn.pipelineIds.length > 0 && (
<div className="mt-2">
{conn.syncInProgress ? (
<div className="flex flex-row items-center justify-start gap-2">
<Loader className="size-5 animate-spin text-[#8A5DF6]" />
<p className="font-semibold">Syncing...</p>
</div>
) : (
<p>Successfully synced</p>
)}
</div>
)}
</div>
</div>
<DropdownMenu>
<DropdownMenuTrigger>
<Settings className="size-5 text-[#808080]" />
</DropdownMenuTrigger>
<DropdownMenuContent className="flex w-[80px] items-center justify-center">
<DropdownMenuItem
className="flex items-center justify-center"
onSelect={() => deleteResource({id: conn.id})}>
<span className="text-center font-medium text-red-500">
Delete
</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
{/* TODO: Improve the condition to hide the separator for the last item, right now it iterates
over all categories and all connections, would be good to have a single array of connections with the category
information included already */}
<Separator className="w-full" />
</>
))}
</div>
))
)}
</div>
)
}
Loading
Loading