Skip to content
Clone
main
68 lines 2.8 KB
import { ErrorPanel, PanelNote } from '@app/components'
import { listPullCommits, type PullRef } from '@app/domains/pulls/model'
import { useT } from '@app/i18n'
import { fmtRelative, fmtTime, useAsync } from '@app/lib'
import { useState } from 'react'
import { Copyable } from './parts'
export interface CommitsTabProps {
refObj: PullRef
onOpenCommit: (sha: string) => void
}
/** 提交页签:head…base 区间内的提交(后端给 MergeCommitDto)。 */
export function CommitsTab({ refObj, onOpenCommit }: CommitsTabProps) {
const { t } = useT()
const [tick, setTick] = useState(0)
const commits = useAsync(() => listPullCommits(refObj), [refObj.space, refObj.repo, refObj.pull, tick])
const failure = commits.error as { code?: number; message?: string } | undefined
if (commits.loading && !commits.data) return <PanelNote text={t('pull.commits.loading')} />
if (failure)
return (
<ErrorPanel
status={failure.code ?? 0}
what={t('pull.commits.errorList')}
note={failure.message}
onRetry={() => setTick((tick) => tick + 1)}
/>
)
const rows = commits.data ?? []
if (!rows.length) return <PanelNote text={t('pull.commits.empty')} />
return (
<ul className="divide-y divide-shell-hairline rounded-xl border border-shell-hairline bg-shell-surface">
{rows.map((commit) => (
<li key={commit.sha} className="flex flex-wrap items-start gap-3 px-4 py-3">
<div className="min-w-0 flex-1">
<button
type="button"
onClick={() => onOpenCommit(commit.sha)}
className="block max-w-full truncate text-left text-[13.5px] font-medium leading-6 hover:underline"
title={commit.subject}
>
{commit.subject || t('pull.commits.noSubject')}
</button>
<p className="text-[12px] text-shell-ink-muted">
{commit.author_name || t('pull.commits.unknownAuthor')} &lt;{commit.author_email}&gt; ·{' '}
<span title={fmtTime(commit.author_at)}>{fmtRelative(commit.author_at)}</span>
</p>
{commit.parents.length > 1 ? (
<p className="mt-0.5 text-[11.5px] text-shell-ink-muted">
{t('pull.commits.mergeCommit', { count: commit.parents.length })}
</p>
) : null}
</div>
<span className="flex shrink-0 items-center gap-1.5">
<Copyable text={commit.sha} />
<button
type="button"
onClick={() => onOpenCommit(commit.sha)}
className="rounded-md border border-shell-hairline px-2 py-1 text-[11.5px] text-shell-ink-muted transition-colors hover:text-shell-ink"
>
{t('pull.commits.view')}
</button>
</span>
</li>
))}
</ul>
)
}