Skip to content

Commit

Permalink
feat: integrations ux improvements (#159)
Browse files Browse the repository at this point in the history
* fix: button loading states for delete actions

* refactor: split create creds comonent from dialog

* fix: service id for github

* feat: misc improvements to empty states

* fix: misc fixes to handle various ui states
  • Loading branch information
rohan-chaturvedi authored Jan 26, 2024
1 parent 533d018 commit e3db938
Show file tree
Hide file tree
Showing 6 changed files with 350 additions and 274 deletions.
123 changes: 92 additions & 31 deletions frontend/app/[team]/integrations/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
'use client'

import { organisationContext } from '@/contexts/organisationContext'
import { Fragment, useContext, useEffect } from 'react'
import { Fragment, useContext, useEffect, useState } from 'react'
import GetSavedCredentials from '@/graphql/queries/syncing/getSavedCredentials.gql'
import GetOrganisationSyncs from '@/graphql/queries/syncing/GetOrgSyncs.gql'
import { useLazyQuery } from '@apollo/client'
import { AppType, EnvironmentSyncType, ProviderCredentialsType } from '@/apollo/graphql'
import GetProviderList from '@/graphql/queries/syncing/getProviders.gql'
import { useLazyQuery, useQuery } from '@apollo/client'
import {
AppType,
EnvironmentSyncType,
ProviderCredentialsType,
ProviderType,
} from '@/apollo/graphql'
import { CreateProviderCredentialsDialog } from '@/components/syncing/CreateProviderCredentialsDialog'
import { SyncCard } from '@/components/syncing/SyncCard'
import { ProviderCredentialCard } from '@/components/syncing/ProviderCredentialCard'
import { GetApps } from '@/graphql/queries/getApps.gql'
import { Button } from '@/components/common/Button'
import { SyncOptions } from '@/components/syncing/SyncOptions'
import { Menu, Transition } from '@headlessui/react'
import { FaArrowRight, FaPlus } from 'react-icons/fa'
import { FaArrowRight, FaCubes, FaPlus } from 'react-icons/fa'
import clsx from 'clsx'
import Link from 'next/link'
import { userIsAdmin } from '@/utils/permissions'
import { useSearchParams } from 'next/navigation'
import { FrameworkIntegrations } from '@/components/syncing/FrameworkIntegrations'
import { ProviderCard } from '@/components/syncing/CreateProviderCredentials'
import { AppCard } from '@/components/apps/AppCard'

export default function Integrations({ params }: { params: { team: string } }) {
const { activeOrganisation: organisation } = useContext(organisationContext)
Expand All @@ -27,6 +34,12 @@ export default function Integrations({ params }: { params: { team: string } }) {

const openCreateCredentialDialog = searchParams.get('newCredential')

const { data: providersData } = useQuery(GetProviderList)

const providers: ProviderType[] = providersData?.providers ?? []

const [provider, setProvider] = useState<ProviderType | null>(null)

const [getApps, { data: appsData }] = useLazyQuery(GetApps)
const [getSavedCredentials, { data: credentialsData }] = useLazyQuery(GetSavedCredentials)
const [getOrgSyncs, { data: syncsData }] = useLazyQuery(GetOrganisationSyncs)
Expand All @@ -46,6 +59,10 @@ export default function Integrations({ params }: { params: { team: string } }) {

const noCredentials = credentialsData?.savedCredentials.length === 0

const noSyncs = syncsData?.syncs.length === 0

const noApps = appsData?.apps.length === 0

const NewSyncMenu = () => {
return (
<Menu as="div" className="relative group">
Expand Down Expand Up @@ -106,58 +123,102 @@ export default function Integrations({ params }: { params: { team: string } }) {
<p className="text-neutral-500">Manage syncs</p>
</div>

{syncsData?.syncs.length > 0 && activeUserIsAdmin && (
{!noSyncs && activeUserIsAdmin && (
<div className="flex justify-end">
<NewSyncMenu />
</div>
)}

{syncsData?.syncs.length > 0 ? (
syncsData?.syncs.map((sync: EnvironmentSyncType) => (
<SyncCard key={sync.id} sync={sync} showAppName={true} showManageButton={true} />
))
) : (
<div className="flex flex-col items-center text-center p-16">
<div className="font-semibold text-black dark:text-white text-xl">No syncs</div>
<div className="text-neutral-500">
Create a sync from the &quot;Syncing&quot; tab of an App
{noApps && (
<div className="flex flex-col items-center text-center gap-4 p-16">
<div>
<div className="font-semibold text-black dark:text-white text-xl">No Apps</div>
<div className="text-neutral-500">
You don&apos;t have access to any Apps. Create a new app, or contact your
organistion admin for access to start syncing.
</div>
</div>
{activeUserIsAdmin && (
<div className="flex justify-center p-4">
<NewSyncMenu />
<Link href={`/${params.team}/apps`}>
<Button variant="primary">
<FaCubes /> Go to Apps
</Button>
</Link>
</div>
)}

{noSyncs && !noApps ? (
<div className="flex flex-col text-center py-4 gap-6">
<div>
<div className="font-semibold text-black dark:text-white text-xl">No syncs</div>
<div className="text-neutral-500">
You don&apos;t have any syncs at the moment. Choose an App below to create a sync.
</div>
)}
</div>
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:max-w-none xl:grid-cols-4">
{apps?.map((app: AppType) => (
<Link href={`/${params.team}/apps/${app.id}/syncing`} key={app.id}>
<AppCard app={app} />
</Link>
))}
</div>
</div>
) : (
syncsData?.syncs.map((sync: EnvironmentSyncType) => (
<SyncCard key={sync.id} sync={sync} showAppName={true} showManageButton={true} />
))
)}
</div>

<hr className="border-neutral-500/40" />

<div className="space-y-4">
<div className="border-b border-neutral-500/20 pb-4">
<h2 className="text-black dark:text-white text-xl font-medium"> Service credentials</h2>
<h2 className="text-black dark:text-white text-xl font-medium">Service credentials</h2>
<p className="text-neutral-500">Manage stored credentials for third party services</p>
</div>

<div
className={clsx(
noCredentials ? 'flex flex-col items-center text-center p-16' : 'flex justify-end'
noCredentials ? 'flex flex-col text-center gap-6 py-4' : 'flex justify-end'
)}
>
{noCredentials && (
<div className="font-semibold text-black dark:text-white text-xl">
No service credentials
</div>
)}
{noCredentials && (
<div className="text-neutral-500">
Set up a new authentication method to start syncing with third party services.
<div>
<div className="font-semibold text-black dark:text-white text-xl">
No service credentials
</div>
<div className="text-neutral-500">
{activeUserIsAdmin
? 'Set up a new authentication method to start syncing with third party services.'
: 'Contact your organisation admin or owner to create credentials.'}
</div>
</div>
)}

{activeUserIsAdmin && (
<div className={clsx(noCredentials && 'flex justify-center p-4')}>
<CreateProviderCredentialsDialog defaultOpen={openCreateCredentialDialog !== null} />
</div>
<>
<div className="flex justify-end">
<CreateProviderCredentialsDialog
showButton={!noCredentials}
provider={provider}
defaultOpen={openCreateCredentialDialog !== null}
closeDialogCallback={() => setProvider(null)}
/>
</div>
{noCredentials ? (
<div className="">
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 xl:max-w-none xl:grid-cols-4">
{providers.map((provider) => (
<button key={provider.id} type="button" onClick={() => setProvider(provider)}>
<ProviderCard provider={provider} />
</button>
))}
</div>
</div>
) : (
<div className={clsx(noCredentials && 'flex justify-center p-4')}></div>
)}
</>
)}
</div>

Expand Down
Loading

0 comments on commit e3db938

Please sign in to comment.