mirror of
https://github.com/block/buzz.git
synced 2026-10-31 22:41:12 +00:00
Replace the body-plus-rail layout on tasks, reviews, and commits with a shared header, labeled meta rows, and collapsible sections, and add a sidebar Projects list with create, delete, and filter controls. Signed-off-by: Thomas Petersen <thomasp@squareup.com>
159 lines
5.5 KiB
TypeScript
159 lines
5.5 KiB
TypeScript
import { Calendar, GitCommitHorizontal, Hash } from "lucide-react";
|
|
|
|
import {
|
|
profileForCommit,
|
|
type ViewerGitIdentity,
|
|
} from "@/features/projects/lib/projectContributorMatching";
|
|
import {
|
|
resolveUserLabel,
|
|
type UserProfileLookup,
|
|
} from "@/features/profile/lib/identity";
|
|
import { commitDiscussionQuery } from "@/features/projects/lib/discussionChannels";
|
|
import type { ProjectRepoCommit, ProjectRepoDiff } from "@/shared/api/types";
|
|
import { DiscussedInChannels } from "./DiscussionChannels";
|
|
import { CopyCommitHashButton } from "./ProjectCommitCopyButton";
|
|
import {
|
|
ProjectDetailMetaList,
|
|
ProjectDetailMetaRow,
|
|
} from "./ProjectDetailMeta";
|
|
import { ProjectDetailSection } from "./ProjectDetailSection";
|
|
import { PROJECT_DETAIL_PANEL_CLASS } from "./projectPanelStyles";
|
|
import { ProfileIdentityButton } from "./ProjectProfileIdentity";
|
|
import { ProjectDiffFilesPanel } from "./ProjectPullRequestFilesChangedPanel";
|
|
import { ProjectOriginReference } from "./ProjectOriginReference";
|
|
import { ProjectRichContent } from "./ProjectRichContent";
|
|
|
|
function commitDateLabel(timestamp: number) {
|
|
return new Date(timestamp * 1_000).toLocaleString(undefined, {
|
|
dateStyle: "medium",
|
|
timeStyle: "short",
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Detail view for a single commit: title and meta header, then collapsible
|
|
* description and the commit-vs-parent diff.
|
|
*/
|
|
export function ProjectCommitDetailPanel({
|
|
commit,
|
|
commitAuthorPubkeys,
|
|
commitHash,
|
|
diff,
|
|
diffError,
|
|
diffLoading,
|
|
originAgentName,
|
|
originChannelId,
|
|
profiles,
|
|
viewerGitIdentity,
|
|
}: {
|
|
commit: ProjectRepoCommit | null;
|
|
/** Signed commit→pubkey mapping derived from pull request events. */
|
|
commitAuthorPubkeys?: Map<string, string>;
|
|
commitHash: string;
|
|
diff: ProjectRepoDiff | null | undefined;
|
|
diffError: unknown;
|
|
diffLoading: boolean;
|
|
originAgentName?: string | null;
|
|
originChannelId?: string | null;
|
|
profiles?: UserProfileLookup;
|
|
viewerGitIdentity?: ViewerGitIdentity | null;
|
|
}) {
|
|
const matchedProfile = commit
|
|
? profileForCommit(commit, profiles, commitAuthorPubkeys, viewerGitIdentity)
|
|
: null;
|
|
const authorLabel = matchedProfile
|
|
? resolveUserLabel({ pubkey: matchedProfile.pubkey, profiles })
|
|
: (commit?.authorName ?? commit?.authorEmail ?? "Unknown author");
|
|
const shortHash = commit?.shortHash ?? commitHash.slice(0, 7);
|
|
const fileCount = diff?.files.length;
|
|
|
|
return (
|
|
<div className={PROJECT_DETAIL_PANEL_CLASS} data-project-detail-panel>
|
|
<header className="space-y-1 px-4 pb-1 pt-3">
|
|
<h3 className="line-clamp-2 text-xl font-semibold text-foreground">
|
|
{commit?.subject ?? shortHash}
|
|
</h3>
|
|
<p className="flex flex-wrap items-center gap-x-1.5 gap-y-1 text-xs font-medium text-muted-foreground">
|
|
<ProfileIdentityButton
|
|
avatarClassName="shrink-0"
|
|
avatarSize="xs"
|
|
avatarUrl={matchedProfile?.profile.avatarUrl ?? null}
|
|
isAgent={matchedProfile?.profile.isAgent === true}
|
|
label={authorLabel}
|
|
pubkey={matchedProfile?.pubkey ?? null}
|
|
showLabel={false}
|
|
/>
|
|
<span className="font-medium text-foreground">{authorLabel}</span>
|
|
{commit ? (
|
|
<span
|
|
className="shrink-0 whitespace-nowrap"
|
|
title={commitDateLabel(commit.timestamp)}
|
|
>
|
|
{commitDateLabel(commit.timestamp)}
|
|
</span>
|
|
) : null}
|
|
<ProjectOriginReference
|
|
agentName={originAgentName}
|
|
channelId={originChannelId}
|
|
/>
|
|
</p>
|
|
</header>
|
|
<ProjectDetailMetaList>
|
|
<ProjectDetailMetaRow icon={Hash} label="Commit">
|
|
<span className="inline-flex min-w-0 items-center gap-1 font-mono text-xs">
|
|
{shortHash}
|
|
<CopyCommitHashButton
|
|
className="h-6 w-6"
|
|
hash={commit?.hash ?? commitHash}
|
|
/>
|
|
</span>
|
|
</ProjectDetailMetaRow>
|
|
{commit ? (
|
|
<ProjectDetailMetaRow icon={Calendar} label="Date">
|
|
<span className="text-muted-foreground">
|
|
{commitDateLabel(commit.timestamp)}
|
|
</span>
|
|
</ProjectDetailMetaRow>
|
|
) : null}
|
|
{diff ? (
|
|
<ProjectDetailMetaRow icon={GitCommitHorizontal} label="Changes">
|
|
<span className="flex items-center gap-1.5">
|
|
<span className="text-green-500">+{diff.additions}</span>
|
|
<span className="text-destructive">-{diff.deletions}</span>
|
|
</span>
|
|
</ProjectDetailMetaRow>
|
|
) : null}
|
|
</ProjectDetailMetaList>
|
|
{diff?.commitBody ? (
|
|
<ProjectDetailSection defaultOpen title="Description">
|
|
<ProjectRichContent
|
|
content={diff.commitBody}
|
|
hardLineBreaks={false}
|
|
/>
|
|
</ProjectDetailSection>
|
|
) : null}
|
|
<DiscussedInChannels
|
|
className="mx-4 mb-4"
|
|
entityLabel="this commit"
|
|
query={commitDiscussionQuery({
|
|
hash: commit?.hash ?? commitHash,
|
|
shortHash: commit?.shortHash,
|
|
})}
|
|
testId="commit-discussed-in"
|
|
/>
|
|
<ProjectDetailSection count={fileCount} defaultOpen title="Files changed">
|
|
<div className="-mx-4">
|
|
<ProjectDiffFilesPanel
|
|
diff={diff}
|
|
embedded
|
|
error={diffError}
|
|
headerLabel={`${commit?.subject ?? "Commit"} · ${shortHash}`}
|
|
isLoading={diffLoading}
|
|
subjectLabel="commit"
|
|
/>
|
|
</div>
|
|
</ProjectDetailSection>
|
|
</div>
|
|
);
|
|
}
|