Skip to content

Commit

Permalink
feat(ui): integrate gitlab repositories (#1988)
Browse files Browse the repository at this point in the history
  • Loading branch information
liangfung authored Apr 27, 2024
1 parent 4184b1b commit 8d75c27
Show file tree
Hide file tree
Showing 29 changed files with 1,069 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useForm, UseFormReturn } from 'react-hook-form'
import { toast } from 'sonner'
import * as z from 'zod'

import { RepositoryKind } from '@/lib/gql/generates/graphql'
import {
AlertDialog,
AlertDialogAction,
Expand All @@ -33,6 +34,8 @@ import {
import { IconExternalLink, IconSpinner } from '@/components/ui/icons'
import { Input } from '@/components/ui/input'

import { useRepositoryKind } from '../hooks/use-repository-kind'

export const repositoryProviderFormSchema = z.object({
displayName: z.string(),
accessToken: z.string()
Expand All @@ -51,14 +54,15 @@ interface GithubProviderFormProps {
deletable?: boolean
}

export const GithubProviderForm: React.FC<GithubProviderFormProps> = ({
export const CommonProviderForm: React.FC<GithubProviderFormProps> = ({
isNew,
form,
onSubmit,
onDelete,
cancleable = true,
deletable
}) => {
const kind = useRepositoryKind()
const router = useRouter()

const [deleteAlertVisible, setDeleteAlertVisible] = React.useState(false)
Expand All @@ -83,6 +87,29 @@ export const GithubProviderForm: React.FC<GithubProviderFormProps> = ({
}
}

const displayNamePlaceholder = React.useMemo(() => {
switch (kind) {
case RepositoryKind.Github:
return 'e.g. GitHub'
case RepositoryKind.Gitlab:
return 'e.g. GitLab'
default:
return ''
}
}, [kind])

const accessTokenPlaceholder = React.useMemo(() => {
if (!isNew) return '*****'
switch (kind) {
case RepositoryKind.Github:
return 'e.g. github_pat_1ABCD1234ABCD1234ABCD1234ABCD1234ABCD1234'
case RepositoryKind.Gitlab:
return 'e.g. glpat_1ABCD1234ABCD1234ABCD1234ABCD1234'
default:
return ''
}
}, [kind, isNew])

return (
<Form {...form}>
<div className="grid gap-2">
Expand All @@ -98,7 +125,7 @@ export const GithubProviderForm: React.FC<GithubProviderFormProps> = ({
</FormDescription>
<FormControl>
<Input
placeholder="e.g. GitHub"
placeholder={displayNamePlaceholder}
autoCapitalize="none"
autoCorrect="off"
autoComplete="off"
Expand All @@ -116,23 +143,11 @@ export const GithubProviderForm: React.FC<GithubProviderFormProps> = ({
<FormItem>
<FormLabel required>Personal Access Token</FormLabel>
<FormDescription>
<div>
Create a dedicated service user and generate a{' '}
<ExternalLink href="https://github.com/settings/personal-access-tokens/new">
fine-grained personal access
</ExternalLink>{' '}
token with the member role for the organization or all
projects to be managed.
</div>
<div className="my-2 ml-4">• Contents (Read-only)</div>
<AccessTokenDescription />
</FormDescription>
<FormControl>
<Input
placeholder={
isNew
? 'e.g. github_pat_1ABCD1234ABCD1234ABCD1234ABCD1234ABCD1234'
: '*****'
}
placeholder={accessTokenPlaceholder}
autoCapitalize="none"
autoCorrect="off"
autoComplete="off"
Expand Down Expand Up @@ -217,6 +232,46 @@ export function useRepositoryProviderForm(
})
}

function AccessTokenDescription() {
const kind = useRepositoryKind()
if (kind === RepositoryKind.Github) {
return (
<>
<div>
Create a dedicated service user and generate a{' '}
<ExternalLink href="https://github.com/settings/personal-access-tokens/new">
fine-grained personal access
</ExternalLink>{' '}
token with the member role for the organization or all projects to be
managed.
</div>
<div className="my-2 ml-4">• Contents (Read-only)</div>
</>
)
}

if (kind === RepositoryKind.Gitlab) {
return (
<>
<div>
Create a dedicated service user and generate a{' '}
<ExternalLink href="https://gitlab.com/-/user_settings/personal_access_tokens">
personal access token
</ExternalLink>{' '}
with the maintainer role and at least following permissions for the
group or projects to be managed. You can generate a project access
token for managing a single project, or generate a group access token
to manage all projects within the group.
</div>
<div className="my-2 ml-4">• api</div>
<div className="my-2 ml-4">• read repository</div>
</>
)
}

return null
}

function ExternalLink({
href,
children
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,90 @@ import Link from 'next/link'
import { useQuery } from 'urql'

import {
ListGithubRepositoryProvidersQuery,
RepositoryKind,
RepositoryProviderStatus
} from '@/lib/gql/generates/graphql'
import { listGithubRepositoryProviders } from '@/lib/tabby/query'
import {
listGithubRepositoryProviders,
listGitlabRepositoryProviders
} 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'

export default function GitProvidersPage() {
import { useRepositoryKind } from '../hooks/use-repository-kind'

interface GitProvidersListProps {
kind: RepositoryKind
}

export default function RepositoryProvidersPage({
kind
}: GitProvidersListProps) {
if (kind === RepositoryKind.Github) {
return <GithubProviders />
}

if (kind === RepositoryKind.Gitlab) {
return <GitlabProviders />
}

return <div>404</div>
}

function GithubProviders() {
const [{ data, fetching }] = useQuery({
query: listGithubRepositoryProviders
})
const githubRepositoryProviders = data?.githubRepositoryProviders?.edges
const providers = data?.githubRepositoryProviders?.edges

return <RepositoryProvidersView fetching={fetching} providers={providers} />
}

function GitlabProviders() {
const [{ data, fetching }] = useQuery({
query: listGitlabRepositoryProviders
})
const providers = data?.gitlabRepositoryProviders?.edges

return <RepositoryProvidersView fetching={fetching} providers={providers} />
}

interface RepositoryProvidersViewProps {
fetching: boolean
providers:
| Array<{
node: {
id: string
displayName: string
status: RepositoryProviderStatus
}
}>
| undefined
}
function RepositoryProvidersView({
fetching,
providers
}: RepositoryProvidersViewProps) {
return (
<>
<LoadingWrapper loading={fetching}>
{githubRepositoryProviders?.length ? (
<div>
<GitProvidersList data={githubRepositoryProviders} />
<div className="mt-4 flex justify-end">
<Link href="./github/new" className={buttonVariants()}>
Create
</Link>
</div>
</div>
) : (
<GitProvidersPlaceholder />
)}
</LoadingWrapper>
</>
<LoadingWrapper loading={fetching}>
{providers?.length ? (
<>
<GitProvidersList data={providers} />
<CreateRepositoryProvider />·
</>
) : (
<GitProvidersPlaceholder />
)}
</LoadingWrapper>
)
}

interface GitProvidersTableProps {
data: ListGithubRepositoryProvidersQuery['githubRepositoryProviders']['edges']
data: RepositoryProvidersViewProps['providers']
}

const GitProvidersList: React.FC<GitProvidersTableProps> = ({ data }) => {
const kind = useRepositoryKind()
return (
<div className="space-y-8">
{data?.map(item => {
Expand All @@ -56,7 +101,7 @@ const GitProvidersList: React.FC<GitProvidersTableProps> = ({ data }) => {
</div>
</CardTitle>
<Link
href={`github/detail?id=${item.node.id}`}
href={`${kind.toLocaleLowerCase()}/detail?id=${item.node.id}`}
className={buttonVariants({ variant: 'secondary' })}
>
View
Expand All @@ -78,6 +123,20 @@ const GitProvidersList: React.FC<GitProvidersTableProps> = ({ data }) => {
)
}

const CreateRepositoryProvider = () => {
const kind = useRepositoryKind()
return (
<div className="mt-4 flex justify-end">
<Link
href={`./${kind.toLocaleLowerCase()}/new`}
className={buttonVariants()}
>
Create
</Link>
</div>
)
}

function toStatusMessage(status: RepositoryProviderStatus) {
switch (status) {
case RepositoryProviderStatus.Ready:
Expand All @@ -90,12 +149,13 @@ function toStatusMessage(status: RepositoryProviderStatus) {
}

const GitProvidersPlaceholder = () => {
const kind = useRepositoryKind()
return (
<div className="flex flex-col items-center gap-4 rounded-lg border-4 border-dashed py-8">
<div>No Data</div>
<div className="flex justify-center">
<Link
href="./github/new"
href={`./${kind.toLocaleLowerCase()}/new`}
className={buttonVariants({ variant: 'default' })}
>
Create
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { RepositoryKind } from '@/lib/gql/generates/graphql'

export const REPOSITORY_KIND_METAS: Array<{
name: string
enum: RepositoryKind
meta: {
domain: string
displayName: string
}
}> = [
{
name: 'github',
enum: RepositoryKind.Github,
meta: {
domain: 'github.com',
displayName: 'GitHub'
}
},
{
name: 'gitlab',
enum: RepositoryKind.Gitlab,
meta: {
domain: 'gitlab.com',
displayName: 'GitLab'
}
}
]
Loading

0 comments on commit 8d75c27

Please sign in to comment.