diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/common-provider-form.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/common-provider-form.tsx index 951e43167ea2..348585e27041 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/common-provider-form.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/common-provider-form.tsx @@ -9,7 +9,7 @@ import { DefaultValues, useForm, UseFormReturn } from 'react-hook-form' import { toast } from 'sonner' import * as z from 'zod' -import { RepositoryKind } from '@/lib/gql/generates/graphql' +import { IntegrationKind } from '@/lib/gql/generates/graphql' import { cn } from '@/lib/utils' import { AlertDialog, @@ -35,7 +35,7 @@ import { import { IconExternalLink, IconSpinner } from '@/components/ui/icons' import { Input } from '@/components/ui/input' -import { useRepositoryKind } from '../hooks/use-repository-kind' +import { useIntegrationKind } from '../hooks/use-repository-kind' export const createRepositoryProviderFormSchema = z.object({ displayName: z.string().trim(), @@ -77,7 +77,7 @@ export function CommonProviderForm({ cancleable = true, deletable }: GithubProviderFormProps) { - const kind = useRepositoryKind() + const kind = useIntegrationKind() const router = useRouter() const [deleteAlertVisible, setDeleteAlertVisible] = React.useState(false) @@ -104,13 +104,13 @@ export function CommonProviderForm({ const displayNamePlaceholder = React.useMemo(() => { switch (kind) { - case RepositoryKind.Github: + case IntegrationKind.Github: return 'e.g. GitHub' - case RepositoryKind.GithubSelfHosted: + case IntegrationKind.GithubSelfHosted: return 'e.g. GitHub Self-Hosted' - case RepositoryKind.Gitlab: + case IntegrationKind.Gitlab: return 'e.g. GitLab' - case RepositoryKind.GitlabSelfHosted: + case IntegrationKind.GitlabSelfHosted: return 'e.g. GitLab Self-Hosted' default: return '' @@ -120,11 +120,11 @@ export function CommonProviderForm({ const accessTokenPlaceholder = React.useMemo(() => { if (!isNew) return new Array(36).fill('*').join('') switch (kind) { - case RepositoryKind.Github: - case RepositoryKind.GithubSelfHosted: + case IntegrationKind.Github: + case IntegrationKind.GithubSelfHosted: return 'e.g. github_pat_1ABCD1234ABCD1234ABCD1234ABCD1234ABCD1234' - case RepositoryKind.Gitlab: - case RepositoryKind.GitlabSelfHosted: + case IntegrationKind.Gitlab: + case IntegrationKind.GitlabSelfHosted: return 'e.g. glpat_1ABCD1234ABCD1234ABCD1234ABCD1234' default: return '' @@ -133,9 +133,9 @@ export function CommonProviderForm({ const apiBasePlaceholder = React.useMemo(() => { switch (kind) { - case RepositoryKind.GithubSelfHosted: + case IntegrationKind.GithubSelfHosted: return 'e.g. https://api.github.yourcompany.com' - case RepositoryKind.GitlabSelfHosted: + case IntegrationKind.GitlabSelfHosted: return 'e.g. https://gitlab.yourcompany.com' default: return '' @@ -143,8 +143,8 @@ export function CommonProviderForm({ }, [kind]) const showApiBase = [ - RepositoryKind.GithubSelfHosted, - RepositoryKind.GitlabSelfHosted + IntegrationKind.GithubSelfHosted, + IntegrationKind.GitlabSelfHosted ].includes(kind) return ( @@ -303,11 +303,11 @@ export function useRepositoryProviderForm( } function AccessTokenDescription() { - const kind = useRepositoryKind() + const kind = useIntegrationKind() if ( - kind === RepositoryKind.Github || - kind === RepositoryKind.GithubSelfHosted + kind === IntegrationKind.Github || + kind === IntegrationKind.GithubSelfHosted ) { return ( <> @@ -325,8 +325,8 @@ function AccessTokenDescription() { } if ( - kind === RepositoryKind.Gitlab || - kind === RepositoryKind.GitlabSelfHosted + kind === IntegrationKind.Gitlab || + kind === IntegrationKind.GitlabSelfHosted ) { return ( <> diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/provider-list.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/provider-list.tsx index 2096a80b7085..577eee0a5497 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/provider-list.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/components/provider-list.tsx @@ -6,100 +6,39 @@ import { useParams } from 'next/navigation' import { useQuery } from 'urql' import { - RepositoryKind, - RepositoryProviderStatus + IntegrationKind, + IntegrationStatus, + ListIntegrationsQuery } from '@/lib/gql/generates/graphql' -import { QueryResponseData } from '@/lib/tabby/gql' -import { - listGithubRepositoryProviders, - listGithubSelfHostedRepositoryProviders, - listGitlabRepositoryProviders, - listGitlabSelfHostedRepositoryProviders -} from '@/lib/tabby/query' +import { listIntegrations } from '@/lib/tabby/query' import { buttonVariants } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import LoadingWrapper from '@/components/loading-wrapper' interface GitProvidersListProps { - kind: RepositoryKind + kind: IntegrationKind } -type TProviderList = - | Array<{ - node: { - id: string - displayName: string - status: RepositoryProviderStatus - apiBase?: string - } - }> - | undefined - export default function RepositoryProvidersPage({ kind }: GitProvidersListProps) { return - // return
404
} function ProviderList({ kind }: GitProvidersListProps) { - const query = React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return listGithubRepositoryProviders - case RepositoryKind.GithubSelfHosted: - return listGithubSelfHostedRepositoryProviders - case RepositoryKind.Gitlab: - return listGitlabRepositoryProviders - case RepositoryKind.GitlabSelfHosted: - return listGitlabSelfHostedRepositoryProviders - } - }, [kind]) - - const resolver = React.useMemo(() => { - // todo also return pageInfo for pagination - switch (kind) { - case RepositoryKind.Github: - return (res: QueryResponseData) => - res?.githubRepositoryProviders?.edges - case RepositoryKind.GithubSelfHosted: - return ( - res: QueryResponseData - ) => res?.githubSelfHostedRepositoryProviders?.edges - case RepositoryKind.Gitlab: - return (res: QueryResponseData) => - res?.gitlabRepositoryProviders?.edges - case RepositoryKind.GitlabSelfHosted: - return ( - res: QueryResponseData - ) => res?.gitlabSelfHostedRepositoryProviders?.edges - default: - return () => [] - } - }, [kind]) as (response: any) => TProviderList - const [{ data, fetching }] = useQuery({ - query: query as any, - pause: !query + query: listIntegrations, + variables: { kind } }) - const providers = resolver(data) + const providers = data?.integrations?.edges return } interface RepositoryProvidersViewProps { fetching: boolean - providers: - | Array<{ - node: { - id: string - displayName: string - status: RepositoryProviderStatus - apiBase?: string - } - }> - | undefined + providers: ListIntegrationsQuery['integrations']['edges'] | undefined } function RepositoryProvidersView({ @@ -171,13 +110,13 @@ const CreateRepositoryProvider = () => { ) } -function toStatusMessage(status: RepositoryProviderStatus) { +function toStatusMessage(status: IntegrationStatus) { switch (status) { - case RepositoryProviderStatus.Ready: + case IntegrationStatus.Ready: return 'Ready' - case RepositoryProviderStatus.Failed: + case IntegrationStatus.Failed: return 'Processing error. Please check if the access token is still valid' - case RepositoryProviderStatus.Pending: + case IntegrationStatus.Pending: return 'Awaiting the next data synchronization' } } diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/add-repository-form.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/add-repository-form.tsx index 5bcd5d0e7315..9bc8fb964841 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/add-repository-form.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/add-repository-form.tsx @@ -3,14 +3,14 @@ import * as React from 'react' import { zodResolver } from '@hookform/resolvers/zod' import { useForm } from 'react-hook-form' -import { TypedDocumentNode } from 'urql' import * as z from 'zod' import { - RepositoryKind, - RepositoryProviderStatus + IntegrationKind, + IntegrationStatus, + ListIntegratedRepositoriesQuery } from '@/lib/gql/generates/graphql' -import { QueryResponseData, useMutation } from '@/lib/tabby/gql' +import { useMutation } from '@/lib/tabby/gql' import { cn } from '@/lib/utils' import { Button } from '@/components/ui/button' import { @@ -39,12 +39,7 @@ import { PopoverTrigger } from '@/components/ui/popover' -import { - updateGithubProvidedRepositoryActiveMutation, - updateGithubSelfHostedProvidedRepositoryActiveMutation, - updateGitlabProvidedRepositoryActiveMutation, - updateGitlabSelfHostedProvidedRepositoryActiveMutation -} from '../query' +import { updateIntegratedRepositoryActiveMutation } from '../query' const formSchema = z.object({ id: z.string() @@ -53,27 +48,17 @@ const formSchema = z.object({ type ActivateRepositoryFormValues = z.infer interface ActivateRepositoryFormProps { - kind: RepositoryKind + kind: IntegrationKind onCreated?: (id: string) => void onCancel: () => void - providerStatus: RepositoryProviderStatus | undefined + providerStatus: IntegrationStatus | undefined repositories: - | Array<{ - cursor: string - node: { - id: string - vendorId: string - name: string - gitUrl: string - active: boolean - } - }> + | ListIntegratedRepositoriesQuery['integratedRepositories']['edges'] | undefined fetchingRepos: boolean } export default function AddRepositoryForm({ - kind, onCreated, onCancel, repositories, @@ -90,64 +75,21 @@ export default function AddRepositoryForm({ const emptyText = React.useMemo(() => { switch (providerStatus) { - case RepositoryProviderStatus.Pending: + case IntegrationStatus.Pending: return 'Awaiting the next data synchronization' - case RepositoryProviderStatus.Failed: + case IntegrationStatus.Failed: return 'Synchronizing error. Please check if the access token is still valid' default: return 'No repository found' } }, [providerStatus]) - const { mutation, resolver } = React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return { - mutation: updateGithubProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData< - typeof updateGithubProvidedRepositoryActiveMutation - > - ) => res?.updateGithubProvidedRepositoryActive - } - case RepositoryKind.GithubSelfHosted: - return { - mutation: updateGithubSelfHostedProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData< - typeof updateGithubSelfHostedProvidedRepositoryActiveMutation - > - ) => res?.updateGithubSelfHostedProvidedRepositoryActive - } - case RepositoryKind.Gitlab: - return { - mutation: updateGitlabProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData< - typeof updateGitlabProvidedRepositoryActiveMutation - > - ) => res?.updateGitlabProvidedRepositoryActive - } - case RepositoryKind.GitlabSelfHosted: - return { - mutation: updateGitlabSelfHostedProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData< - typeof updateGitlabSelfHostedProvidedRepositoryActiveMutation - > - ) => res?.updateGitlabSelfHostedProvidedRepositoryActive - } - default: - return {} + const updateProvidedRepositoryActive = useMutation( + updateIntegratedRepositoryActiveMutation, + { + form } - }, [kind]) as { - mutation: TypedDocumentNode - resolver: (data?: Record) => boolean | undefined - } - - const updateProvidedRepositoryActive = useMutation(mutation, { - form - }) + ) const onSubmit = (values: ActivateRepositoryFormValues) => { const id = values.id @@ -156,7 +98,7 @@ export default function AddRepositoryForm({ id: values.id, active: true }).then(res => { - if (resolver?.(res?.data)) { + if (res?.data?.updateIntegratedRepositoryActive) { form.reset({ id: undefined }) onCreated?.(id) } @@ -228,8 +170,7 @@ export default function AddRepositoryForm({ )} - {providerStatus !== - RepositoryProviderStatus.Pending && + {providerStatus !== IntegrationStatus.Pending && repositories?.map(repo => ( - -type ListRepositoriesResponseData = { - edges: Repositories - pageInfo: ListGithubRepositoriesQuery['githubRepositories']['pageInfo'] -} +type IntegratedRepositories = + ListIntegratedRepositoriesQuery['integratedRepositories']['edges'] const ProviderDetail: React.FC = () => { const searchParams = useSearchParams() - const kind = useRepositoryKind() + const kind = useIntegrationKind() const router = useRouter() const id = searchParams.get('id')?.toString() ?? '' - const { query, resolver } = React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return { - query: listGithubRepositoryProviders, - resolver: ( - res: QueryResponseData - ) => res?.githubRepositoryProviders?.edges - } - case RepositoryKind.GithubSelfHosted: - return { - query: listGithubSelfHostedRepositoryProviders, - resolver: ( - res?: QueryResponseData< - typeof listGithubSelfHostedRepositoryProviders - > - ) => res?.githubSelfHostedRepositoryProviders?.edges - } - case RepositoryKind.Gitlab: - return { - query: listGitlabRepositoryProviders, - resolver: ( - res: QueryResponseData - ) => res?.gitlabRepositoryProviders?.edges - } - case RepositoryKind.GitlabSelfHosted: - return { - query: listGitlabSelfHostedRepositoryProviders, - resolver: ( - res?: QueryResponseData< - typeof listGitlabSelfHostedRepositoryProviders - > - ) => res?.gitlabSelfHostedRepositoryProviders?.edges - } - default: - return { - query: listGithubRepositoryProviders, - resolver: ( - res?: QueryResponseData - ) => res?.githubRepositoryProviders?.edges - } - } - }, [kind]) - const [{ data, fetching }, reexecuteQuery] = useQuery({ - query: query as TypedDocumentNode, - variables: { ids: [id] }, - pause: !id + query: listIntegrations, + variables: { ids: [id], kind }, + pause: !id || !kind }) - const provider = resolver(data)?.[0]?.node + const provider = data?.integrations?.edges?.[0]?.node const onDeleteProvider = () => { router.back() @@ -200,116 +129,49 @@ const ProviderDetail: React.FC = () => { ) } -function toStatusBadge(status: RepositoryProviderStatus) { +function toStatusBadge(status: IntegrationStatus) { switch (status) { - case RepositoryProviderStatus.Ready: + case IntegrationStatus.Ready: return Ready - case RepositoryProviderStatus.Failed: + case IntegrationStatus.Failed: return Error - case RepositoryProviderStatus.Pending: + case IntegrationStatus.Pending: return Pending } } const ActiveRepoTable: React.FC<{ providerId: string - providerStatus: RepositoryProviderStatus | undefined - kind: RepositoryKind + providerStatus: IntegrationStatus | undefined + kind: IntegrationKind }> = ({ providerStatus, providerId, kind }) => { - const { query, resolver, updateQuery, updateResolver } = React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return { - query: listGithubRepositories, - updateQuery: updateGithubProvidedRepositoryActiveMutation, - resolver: (res?: QueryResponseData) => - res?.githubRepositories, - updateResolver: ( - res?: QueryResponseData< - typeof updateGithubProvidedRepositoryActiveMutation - > - ) => res?.updateGithubProvidedRepositoryActive - } - case RepositoryKind.GithubSelfHosted: - return { - query: listGithubSelfHostedRepositories, - updateQuery: updateGithubSelfHostedProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData - ) => res?.githubSelfHostedRepositories, - updateResolver: ( - res?: QueryResponseData< - typeof updateGithubSelfHostedProvidedRepositoryActiveMutation - > - ) => res?.updateGithubSelfHostedProvidedRepositoryActive - } - case RepositoryKind.Gitlab: - return { - query: listGitlabRepositories, - updateQuery: updateGitlabProvidedRepositoryActiveMutation, - resolver: (res?: QueryResponseData) => - res?.gitlabRepositories, - updateResolver: ( - res?: QueryResponseData< - typeof updateGitlabProvidedRepositoryActiveMutation - > - ) => res?.updateGitlabProvidedRepositoryActive - } - case RepositoryKind.GitlabSelfHosted: - return { - query: listGitlabSelfHostedRepositories, - updateQuery: updateGitlabSelfHostedProvidedRepositoryActiveMutation, - resolver: ( - res?: QueryResponseData - ) => res?.gitlabSelfHostedRepositories, - updateResolver: ( - res?: QueryResponseData< - typeof updateGitlabSelfHostedProvidedRepositoryActiveMutation - > - ) => res?.updateGitlabSelfHostedProvidedRepositoryActive - } - default: - return { - query: listGithubRepositories, - updateQuery: updateGithubProvidedRepositoryActiveMutation, - resolver: (res?: QueryResponseData) => - res?.githubRepositories, - updateResolver: ( - res?: QueryResponseData< - typeof updateGithubProvidedRepositoryActiveMutation - > - ) => res?.updateGithubProvidedRepositoryActive - } - } - }, [kind]) as { - query: TypedDocumentNode - updateQuery: TypedDocumentNode - resolver: (res?: QueryResponseData) => ListRepositoriesResponseData - updateResolver: (res?: QueryResponseData) => boolean | undefined - } - const [page, setPage] = React.useState(1) const { repositories: inactiveRepositories, setRepositories: setInactiveRepositories, isAllLoaded: isInactiveRepositoriesLoaded - } = useAllInactiveRepositories(providerId, query, resolver) + } = useAllInactiveRepositories(providerId, kind) - const fetchRepositories = (variables: QueryVariables) => { - return client.query(query, variables).toPromise() + const fetchRepositories = ( + variables: QueryVariables + ) => { + return client.query(listIntegratedRepositories, variables).toPromise() } const fetchRepositoriesSequentially = async ( page: number, cursor?: string - ): Promise => { + ): Promise< + QueryResponseData | undefined + > => { const res = await fetchRepositories({ - providerIds: [providerId], + ids: [providerId], first: PAGE_SIZE, after: cursor, - active: true + active: true, + kind }) - const responseData = resolver(res?.data) + const responseData = res?.data?.integratedRepositories const _pageInfo = responseData?.pageInfo if (page - 1 > 0 && _pageInfo?.hasNextPage && _pageInfo?.endCursor) { return fetchRepositoriesSequentially(page - 1, _pageInfo.endCursor) @@ -319,25 +181,31 @@ const ActiveRepoTable: React.FC<{ } const [activeRepositoriesResult, setActiveRepositoriesResult] = - React.useState>() + React.useState>() const [fetching, setFetching] = React.useState(true) const [recentlyActivatedRepositories, setRecentlyActivatedRepositories] = - React.useState([]) - const activeRepos = resolver?.(activeRepositoriesResult)?.edges - const pageInfo = resolver?.(activeRepositoriesResult)?.pageInfo - - const updateProvidedRepositoryActive = useMutation(updateQuery, { - onError(error) { - toast.error(error.message || 'Failed to delete') + React.useState([]) + const activeRepos = activeRepositoriesResult?.integratedRepositories?.edges + const pageInfo = activeRepositoriesResult?.integratedRepositories?.pageInfo + + const updateProvidedRepositoryActive = useMutation( + updateIntegratedRepositoryActiveMutation, + { + onError(error) { + toast.error(error.message || 'Failed to delete') + } } - }) + ) - const handleDelete = async (repo: Repositories[0], isLastItem?: boolean) => { + const handleDelete = async ( + repo: IntegratedRepositories[0], + isLastItem?: boolean + ) => { updateProvidedRepositoryActive({ id: repo.node.id, active: false }).then(res => { - if (updateResolver?.(res?.data)) { + if (res?.data?.updateIntegratedRepositoryActive) { setInactiveRepositories(sortRepos([...inactiveRepositories, repo])) const nextPage = isLastItem ? page - 1 : page loadPage(nextPage || 1) @@ -364,9 +232,11 @@ const ActiveRepoTable: React.FC<{ const [open, setOpen] = React.useState(false) - const sortRepos = (repos: Repositories) => { + const sortRepos = (repos: IntegratedRepositories) => { if (!repos?.length) return repos - return repos.sort((a, b) => a.node.name?.localeCompare(b.node.name)) + return repos.sort((a, b) => + a.node.displayName?.localeCompare(b.node.displayName) + ) } const onCreated = (id: string) => { @@ -438,7 +308,7 @@ const ActiveRepoTable: React.FC<{ {recentlyActivatedRepositories?.map(x => { return ( - {x.node.name} + {x.node.displayName} {x.node.gitUrl}
{ return ( - {x.node.name} + {x.node.displayName} {x.node.gitUrl}
@@ -518,21 +388,15 @@ const ActiveRepoTable: React.FC<{ ) } -function useAllInactiveRepositories( - id: string, - query: TypedDocumentNode, - resolver: ( - res?: QueryResponseData - ) => ListRepositoriesResponseData -) { +function useAllInactiveRepositories(id: string, kind: IntegrationKind) { const [queryVariables, setQueryVariables] = useState< - QueryVariables - >({ providerIds: [id], first: PAGE_SIZE, active: false }) - const [repositories, setRepositories] = useState([]) + QueryVariables + >({ ids: [id], first: PAGE_SIZE, active: false, kind }) + const [repositories, setRepositories] = useState([]) const [isAllLoaded, setIsAllLoaded] = useState(!id) const [{ data, fetching }] = useQuery({ - query, + query: listIntegratedRepositories, variables: queryVariables, pause: !id }) @@ -540,13 +404,13 @@ function useAllInactiveRepositories( useEffect(() => { if (isAllLoaded) return if (!fetching && data) { - const pageInfo = resolver(data)?.pageInfo + const pageInfo = data?.integratedRepositories?.pageInfo const currentList = [...repositories] - setRepositories(currentList.concat(resolver(data)?.edges)) + setRepositories(currentList.concat(data?.integratedRepositories?.edges)) if (pageInfo?.hasNextPage) { setQueryVariables({ - providerIds: [id], + ids: [id], first: PAGE_SIZE, after: pageInfo.endCursor, active: false diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/update-provider-form.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/update-provider-form.tsx index fc4f5979e6af..c467f52ee46b 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/update-provider-form.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/components/update-provider-form.tsx @@ -2,11 +2,10 @@ import React from 'react' import { toast } from 'sonner' -import { TypedDocumentNode } from 'urql' import { graphql } from '@/lib/gql/generates' -import { RepositoryKind } from '@/lib/gql/generates/graphql' -import { QueryResponseData, useMutation } from '@/lib/tabby/gql' +import { IntegrationKind } from '@/lib/gql/generates/graphql' +import { useMutation } from '@/lib/tabby/gql' import { CommonProviderForm, @@ -14,65 +13,21 @@ import { useRepositoryProviderForm } from '../../components/common-provider-form' -const deleteGithubRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation DeleteGithubRepositoryProvider($id: ID!) { - deleteGithubRepositoryProvider(id: $id) +const updateIntegrationMutation = graphql(/* GraphQL */ ` + mutation UpdateIntegration($input: UpdateIntegrationInput!) { + updateIntegration(input: $input) } `) -const updateGithubRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation UpdateGithubRepositoryProvider( - $input: UpdateRepositoryProviderInput! - ) { - updateGithubRepositoryProvider(input: $input) - } -`) - -const deleteGitlabRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation DeleteGitlabRepositoryProvider($id: ID!) { - deleteGitlabRepositoryProvider(id: $id) - } -`) - -const updateGitlabRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation UpdateGitlabRepositoryProvider( - $input: UpdateRepositoryProviderInput! - ) { - updateGitlabRepositoryProvider(input: $input) - } -`) - -const deleteGithubSelfHostedRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation DeleteGithubSelfHostedRepositoryProvider($id: ID!) { - deleteGithubSelfHostedRepositoryProvider(id: $id) - } -`) - -const updateGithubSelfHostedRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation UpdateGithubSelfHostedRepositoryProvider( - $input: UpdateSelfHostedRepositoryProviderInput! - ) { - updateGithubSelfHostedRepositoryProvider(input: $input) - } -`) - -const deleteGitlabSelfHostedRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation DeleteGitlabSelfHostedRepositoryProvider($id: ID!) { - deleteGitlabSelfHostedRepositoryProvider(id: $id) - } -`) - -const updateGitlabSelfHostedRepositoryProviderMutation = graphql(/* GraphQL */ ` - mutation UpdateGitlabSelfHostedRepositoryProvider( - $input: UpdateSelfHostedRepositoryProviderInput! - ) { - updateGitlabSelfHostedRepositoryProvider(input: $input) +const deleteIntegrationMutation = graphql(/* GraphQL */ ` + mutation DeleteIntegration($id: ID!, $kind: IntegrationKind!) { + deleteIntegration(id: $id, kind: $kind) } `) interface UpdateProviderFormProps { id: string - kind: RepositoryKind + kind: IntegrationKind defaultValues?: Partial onSuccess?: () => void onDelete: () => void @@ -89,82 +44,9 @@ export const UpdateProviderForm: React.FC = ({ }) => { const form = useRepositoryProviderForm(false, defaultValues) - const { updateMutation, deleteMutation, updateResolver, deleteResolver } = - React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return { - updateMutation: updateGithubRepositoryProviderMutation, - deleteMutation: deleteGithubRepositoryProviderMutation, - updateResolver: ( - res?: QueryResponseData< - typeof updateGithubRepositoryProviderMutation - > - ) => res?.updateGithubRepositoryProvider, - deleteResolver: ( - res?: QueryResponseData< - typeof deleteGithubRepositoryProviderMutation - > - ) => res?.deleteGithubRepositoryProvider - } - case RepositoryKind.GithubSelfHosted: - return { - updateMutation: updateGithubSelfHostedRepositoryProviderMutation, - deleteMutation: deleteGithubSelfHostedRepositoryProviderMutation, - updateResolver: ( - res?: QueryResponseData< - typeof updateGithubSelfHostedRepositoryProviderMutation - > - ) => res?.updateGithubSelfHostedRepositoryProvider, - deleteResolver: ( - res?: QueryResponseData< - typeof deleteGithubSelfHostedRepositoryProviderMutation - > - ) => res?.deleteGithubSelfHostedRepositoryProvider - } - case RepositoryKind.Gitlab: - return { - updateMutation: updateGitlabRepositoryProviderMutation, - deleteMutation: deleteGitlabRepositoryProviderMutation, - updateResolver: ( - res?: QueryResponseData< - typeof updateGitlabRepositoryProviderMutation - > - ) => res?.updateGitlabRepositoryProvider, - deleteResolver: ( - res?: QueryResponseData< - typeof deleteGitlabRepositoryProviderMutation - > - ) => res?.deleteGitlabRepositoryProvider - } - case RepositoryKind.GitlabSelfHosted: - return { - updateMutation: updateGitlabSelfHostedRepositoryProviderMutation, - deleteMutation: deleteGitlabSelfHostedRepositoryProviderMutation, - updateResolver: ( - res?: QueryResponseData< - typeof updateGitlabSelfHostedRepositoryProviderMutation - > - ) => res?.updateGitlabSelfHostedRepositoryProvider, - deleteResolver: ( - res?: QueryResponseData< - typeof deleteGitlabSelfHostedRepositoryProviderMutation - > - ) => res?.deleteGitlabSelfHostedRepositoryProvider - } - default: - return {} - } - }, [kind]) as { - updateMutation: TypedDocumentNode - deleteMutation: TypedDocumentNode - updateResolver: (data?: Record) => boolean | undefined - deleteResolver: (data?: Record) => boolean | undefined - } - - const deleteRepositoryProvider = useMutation(deleteMutation) + const deleteRepositoryProvider = useMutation(deleteIntegrationMutation) - const updateRepositoryProvider = useMutation(updateMutation, { + const updateRepositoryProvider = useMutation(updateIntegrationMutation, { form }) @@ -172,10 +54,11 @@ export const UpdateProviderForm: React.FC = ({ const res = await updateRepositoryProvider({ input: { id, - ...values + ...values, + kind } }) - if (updateResolver?.(res?.data)) { + if (res?.data?.updateIntegration) { toast.success('Updated provider successfully') form?.reset(form?.getValues()) onSuccess?.() @@ -184,8 +67,8 @@ export const UpdateProviderForm: React.FC = ({ } const handleDeleteRepositoryProvider = async () => { - const res = await deleteRepositoryProvider({ id }) - if (deleteResolver?.(res?.data)) { + const res = await deleteRepositoryProvider({ id, kind }) + if (res?.data?.deleteIntegration) { onDelete?.() } else { toast.error(res?.error?.message || 'Failed to delete provider') diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/query.ts b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/query.ts index e1532c3a9931..42e52896d095 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/query.ts +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/detail/query.ts @@ -1,35 +1,7 @@ import { graphql } from '@/lib/gql/generates' -export const updateGithubProvidedRepositoryActiveMutation = - graphql(/* GraphQL */ ` - mutation UpdateGithubProvidedRepositoryActive($id: ID!, $active: Boolean!) { - updateGithubProvidedRepositoryActive(id: $id, active: $active) - } - `) - -export const updateGitlabProvidedRepositoryActiveMutation = - graphql(/* GraphQL */ ` - mutation UpdateGitlabProvidedRepositoryActive($id: ID!, $active: Boolean!) { - updateGitlabProvidedRepositoryActive(id: $id, active: $active) - } - `) - -export const updateGithubSelfHostedProvidedRepositoryActiveMutation = - graphql(/* GraphQL */ ` - mutation UpdateGithubSelfHostedProvidedRepositoryActive( - $id: ID! - $active: Boolean! - ) { - updateGithubSelfHostedProvidedRepositoryActive(id: $id, active: $active) - } - `) - -export const updateGitlabSelfHostedProvidedRepositoryActiveMutation = - graphql(/* GraphQL */ ` - mutation UpdateGitlabSelfHostedProvidedRepositoryActive( - $id: ID! - $active: Boolean! - ) { - updateGitlabSelfHostedProvidedRepositoryActive(id: $id, active: $active) - } - `) +export const updateIntegratedRepositoryActiveMutation = graphql(/* GraphQL */ ` + mutation UpdateIntegratedRepositoryActive($id: ID!, $active: Boolean!) { + updateIntegratedRepositoryActive(id: $id, active: $active) + } +`) diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/hooks/use-repository-kind.ts b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/hooks/use-repository-kind.ts index 9b4a71483578..b93e40ffd376 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/hooks/use-repository-kind.ts +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/hooks/use-repository-kind.ts @@ -3,7 +3,7 @@ import { findIndex } from 'lodash-es' import { PROVIDER_KIND_METAS } from '../../constants' -export function useRepositoryKind() { +export function useIntegrationKind() { const params = useParams<{ kind?: string }>() const kindIndex = findIndex( PROVIDER_KIND_METAS, diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/new/components/new-page.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/new/components/new-page.tsx index fca89eea1ad6..faf1d51ca4be 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/new/components/new-page.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/[kind]/new/components/new-page.tsx @@ -3,11 +3,9 @@ import React from 'react' import { useRouter } from 'next/navigation' import { UseFormReturn } from 'react-hook-form' -import { TypedDocumentNode } from 'urql' import { graphql } from '@/lib/gql/generates' -import { RepositoryKind } from '@/lib/gql/generates/graphql' -import { QueryResponseData, useMutation } from '@/lib/tabby/gql' +import { useMutation } from '@/lib/tabby/gql' import { CommonProviderForm, @@ -15,97 +13,22 @@ import { UpdateRepositoryProviderFormValues, useRepositoryProviderForm } from '../../components/common-provider-form' -import { useRepositoryKind } from '../../hooks/use-repository-kind' +import { useIntegrationKind } from '../../hooks/use-repository-kind' -const createGithubRepositoryProvider = graphql(/* GraphQL */ ` - mutation CreateGithubRepositoryProvider( - $input: CreateRepositoryProviderInput! - ) { - createGithubRepositoryProvider(input: $input) - } -`) - -const createGithubSelfHostedRepositoryProvider = graphql(/* GraphQL */ ` - mutation CreateGithubSelfHostedRepositoryProvider( - $input: CreateSelfHostedRepositoryProviderInput! - ) { - createGithubSelfHostedRepositoryProvider(input: $input) - } -`) - -const createGitlabRepositoryProvider = graphql(/* GraphQL */ ` - mutation CreateGitlabRepositoryProvider( - $input: CreateRepositoryProviderInput! - ) { - createGitlabRepositoryProvider(input: $input) - } -`) - -const createGitlabSelfHostedRepositoryProvider = graphql(/* GraphQL */ ` - mutation CreateGitlabSelfHostedRepositoryProvider( - $input: CreateSelfHostedRepositoryProviderInput! - ) { - createGitlabSelfHostedRepositoryProvider(input: $input) +const createIntegration = graphql(/* GraphQL */ ` + mutation CreateIntegration($input: CreateIntegrationInput!) { + createIntegration(input: $input) } `) export const NewProvider = () => { - const kind = useRepositoryKind() + const kind = useIntegrationKind() const router = useRouter() const form = useRepositoryProviderForm(true) - const { mutation, resolver } = React.useMemo(() => { - switch (kind) { - case RepositoryKind.Github: - return { - mutation: createGithubRepositoryProvider, - resolver: ( - res?: QueryResponseData - ) => res?.createGithubRepositoryProvider - } - case RepositoryKind.GithubSelfHosted: - return { - mutation: createGithubSelfHostedRepositoryProvider, - resolver: ( - res?: QueryResponseData< - typeof createGithubSelfHostedRepositoryProvider - > - ) => res?.createGithubSelfHostedRepositoryProvider - } - case RepositoryKind.Gitlab: - return { - mutation: createGitlabRepositoryProvider, - resolver: ( - res?: QueryResponseData - ) => res?.createGitlabRepositoryProvider - } - case RepositoryKind.GitlabSelfHosted: - return { - mutation: createGitlabSelfHostedRepositoryProvider, - resolver: ( - res?: QueryResponseData< - typeof createGitlabSelfHostedRepositoryProvider - > - ) => res?.createGitlabSelfHostedRepositoryProvider - } - default: - return { - mutation: createGithubRepositoryProvider, - resolver: ( - res?: QueryResponseData - ) => res?.createGithubRepositoryProvider - } - } - }, [kind]) as { - mutation: TypedDocumentNode - resolver: ( - res?: QueryResponseData> - ) => string | undefined - } - - const createRepositoryProviderMutation = useMutation(mutation, { + const createRepositoryProviderMutation = useMutation(createIntegration, { onCompleted(data) { - if (resolver(data)) { + if (data?.createIntegration) { router.back() } }, @@ -114,7 +37,10 @@ export const NewProvider = () => { const handleSubmit = async (values: CreateRepositoryProviderFormValues) => { return createRepositoryProviderMutation({ - input: values + input: { + ...values, + kind + } }) } diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/components/tabs-header.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/components/tabs-header.tsx index 34aac4ab8321..d35b58183d6e 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/components/tabs-header.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/components/tabs-header.tsx @@ -4,7 +4,7 @@ import React from 'react' import Link from 'next/link' import { useParams } from 'next/navigation' -import { RepositoryKind } from '@/lib/gql/generates/graphql' +import { IntegrationKind, RepositoryKind } from '@/lib/gql/generates/graphql' import { IconGitHub, IconGitLab } from '@/components/ui/icons' import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs' @@ -41,13 +41,13 @@ export default function GitTabsHeader() { ) } -function ProviderIcon({ kind }: { kind: RepositoryKind }) { +function ProviderIcon({ kind }: { kind: IntegrationKind }) { switch (kind) { - case RepositoryKind.Github: - case RepositoryKind.GithubSelfHosted: + case IntegrationKind.Github: + case IntegrationKind.GithubSelfHosted: return - case RepositoryKind.Gitlab: - case RepositoryKind.GitlabSelfHosted: + case IntegrationKind.Gitlab: + case IntegrationKind.GitlabSelfHosted: return default: return null diff --git a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/constants.tsx b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/constants.tsx index ecbf5749454c..75fec71ce2be 100644 --- a/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/constants.tsx +++ b/ee/tabby-ui/app/(dashboard)/settings/(integrations)/repository/constants.tsx @@ -1,36 +1,36 @@ -import { RepositoryKind } from '@/lib/gql/generates/graphql' +import { IntegrationKind } from '@/lib/gql/generates/graphql' export const PROVIDER_KIND_METAS: Array<{ name: string - enum: RepositoryKind + enum: IntegrationKind meta: { displayName: string } }> = [ { name: 'github', - enum: RepositoryKind.Github, + enum: IntegrationKind.Github, meta: { displayName: 'GitHub' } }, { name: 'github-self-hosted', - enum: RepositoryKind.GithubSelfHosted, + enum: IntegrationKind.GithubSelfHosted, meta: { displayName: 'GitHub Self-Hosted' } }, { name: 'gitlab', - enum: RepositoryKind.Gitlab, + enum: IntegrationKind.Gitlab, meta: { displayName: 'GitLab' } }, { name: 'gitlab-self-hosted', - enum: RepositoryKind.GitlabSelfHosted, + enum: IntegrationKind.GitlabSelfHosted, meta: { displayName: 'GitLab Self-Hosted' } diff --git a/ee/tabby-ui/lib/tabby/query.ts b/ee/tabby-ui/lib/tabby/query.ts index 885e75589d06..1d0b37b011a7 100644 --- a/ee/tabby-ui/lib/tabby/query.ts +++ b/ee/tabby-ui/lib/tabby/query.ts @@ -168,16 +168,18 @@ export const queryDailyStats = graphql(/* GraphQL */ ` } `) -export const listGithubRepositoryProviders = graphql(/* GraphQL */ ` - query ListGithubRepositoryProviders( +export const listIntegrations = graphql(/* GraphQL */ ` + query ListIntegrations( $ids: [ID!] + $kind: IntegrationKind $after: String $before: String $first: Int $last: Int ) { - githubRepositoryProviders( + integrations( ids: $ids + kind: $kind after: $after before: $before first: $first @@ -201,194 +203,19 @@ export const listGithubRepositoryProviders = graphql(/* GraphQL */ ` } `) -export const listGithubRepositories = graphql(/* GraphQL */ ` - query ListGithubRepositories( - $providerIds: [ID!]! - $active: Boolean - $after: String - $before: String - $first: Int - $last: Int - ) { - githubRepositories( - providerIds: $providerIds - active: $active - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - vendorId - githubRepositoryProviderId - name - gitUrl - active - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGitlabRepositoryProviders = graphql(/* GraphQL */ ` - query ListGitlabRepositoryProviders( +export const listIntegratedRepositories = graphql(/* GraphQL */ ` + query ListIntegratedRepositories( $ids: [ID!] - $after: String - $before: String - $first: Int - $last: Int - ) { - gitlabRepositoryProviders( - ids: $ids - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - displayName - status - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGitlabRepositories = graphql(/* GraphQL */ ` - query ListGitlabRepositories( - $providerIds: [ID!]! + $kind: IntegrationKind $active: Boolean $after: String $before: String $first: Int $last: Int ) { - gitlabRepositories( - providerIds: $providerIds - active: $active - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - vendorId - gitlabRepositoryProviderId - name - gitUrl - active - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGithubSelfHostedRepositoryProviders = graphql(/* GraphQL */ ` - query ListGithubSelfHostedRepositoryProviders( - $ids: [ID!] - $after: String - $before: String - $first: Int - $last: Int - ) { - githubSelfHostedRepositoryProviders( + integratedRepositories( ids: $ids - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - displayName - status - apiBase - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGitlabSelfHostedRepositoryProviders = graphql(/* GraphQL */ ` - query ListGitlabSelfHostedRepositoryProviders( - $ids: [ID!] - $after: String - $before: String - $first: Int - $last: Int - ) { - gitlabSelfHostedRepositoryProviders( - ids: $ids - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - displayName - status - apiBase - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGithubSelfHostedRepositories = graphql(/* GraphQL */ ` - query ListGithubSelfHostedRepositories( - $providerIds: [ID!]! - $active: Boolean - $after: String - $before: String - $first: Int - $last: Int - ) { - githubSelfHostedRepositories( - providerIds: $providerIds + kind: $kind active: $active after: $after before: $before @@ -398,46 +225,7 @@ export const listGithubSelfHostedRepositories = graphql(/* GraphQL */ ` edges { node { id - vendorId - githubRepositoryProviderId - name - gitUrl - active - } - cursor - } - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - } - } -`) - -export const listGitlabSelfHostedRepositories = graphql(/* GraphQL */ ` - query ListGitlabSelfHostedRepositories( - $providerIds: [ID!]! - $active: Boolean - $after: String - $before: String - $first: Int - $last: Int - ) { - gitlabSelfHostedRepositories( - providerIds: $providerIds - active: $active - after: $after - before: $before - first: $first - last: $last - ) { - edges { - node { - id - vendorId - name + displayName gitUrl active }