Move src/ → apps/server/ and packages/web/ → apps/web/ to adopt standard monorepo conventions (apps/ for runnable apps, packages/ for reusable libraries). Update all config files, shared package imports, test fixtures, and documentation to reflect new paths. Key fixes: - Update workspace config to ["apps/*", "packages/*"] - Update tsconfig.json rootDir/include for apps/server/ - Add apps/web/** to vitest exclude list - Update drizzle.config.ts schema path - Fix ensure-schema.ts migration path detection (3 levels up in dev, 2 levels up in dist) - Fix tests/integration/cli-server.test.ts import paths - Update packages/shared imports to apps/server/ paths - Update all docs/ files with new paths
139 lines
3.8 KiB
TypeScript
139 lines
3.8 KiB
TypeScript
import { useRef, useEffect } from "react";
|
|
import { MessageSquarePlus } from "lucide-react";
|
|
import type { DiffLine, ReviewComment } from "./types";
|
|
import { CommentThread } from "./CommentThread";
|
|
import { CommentForm } from "./CommentForm";
|
|
|
|
interface LineWithCommentsProps {
|
|
line: DiffLine;
|
|
lineKey: number;
|
|
lineComments: ReviewComment[];
|
|
isCommenting: boolean;
|
|
onStartComment: () => void;
|
|
onCancelComment: () => void;
|
|
onSubmitComment: (body: string) => void;
|
|
onResolveComment: (commentId: string) => void;
|
|
onUnresolveComment: (commentId: string) => void;
|
|
}
|
|
|
|
export function LineWithComments({
|
|
line,
|
|
lineKey,
|
|
lineComments,
|
|
isCommenting,
|
|
onStartComment,
|
|
onCancelComment,
|
|
onSubmitComment,
|
|
onResolveComment,
|
|
onUnresolveComment,
|
|
}: LineWithCommentsProps) {
|
|
const formRef = useRef<HTMLTextAreaElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (isCommenting) {
|
|
formRef.current?.focus();
|
|
}
|
|
}, [isCommenting]);
|
|
|
|
const bgClass =
|
|
line.type === "added"
|
|
? "bg-green-50 dark:bg-green-950/20"
|
|
: line.type === "removed"
|
|
? "bg-red-50 dark:bg-red-950/20"
|
|
: "";
|
|
|
|
const gutterBgClass =
|
|
line.type === "added"
|
|
? "bg-green-100 dark:bg-green-950/40"
|
|
: line.type === "removed"
|
|
? "bg-red-100 dark:bg-red-950/40"
|
|
: "bg-muted/30";
|
|
|
|
const prefix =
|
|
line.type === "added" ? "+" : line.type === "removed" ? "-" : " ";
|
|
|
|
const textColorClass =
|
|
line.type === "added"
|
|
? "text-green-800 dark:text-green-300"
|
|
: line.type === "removed"
|
|
? "text-red-800 dark:text-red-300"
|
|
: "";
|
|
|
|
return (
|
|
<>
|
|
<tr
|
|
className={`group ${bgClass} hover:brightness-95 dark:hover:brightness-110`}
|
|
>
|
|
{/* Line numbers */}
|
|
<td
|
|
className={`w-[72px] min-w-[72px] select-none text-right text-muted-foreground pr-1 ${gutterBgClass} align-top`}
|
|
>
|
|
<div className="flex items-center justify-end gap-0">
|
|
<span className="w-8 inline-block text-right text-[11px] leading-5">
|
|
{line.oldLineNumber ?? ""}
|
|
</span>
|
|
<span className="w-8 inline-block text-right text-[11px] leading-5">
|
|
{line.newLineNumber ?? ""}
|
|
</span>
|
|
</div>
|
|
</td>
|
|
|
|
{/* Comment button gutter */}
|
|
<td className={`w-6 min-w-6 ${gutterBgClass} align-top`}>
|
|
<button
|
|
className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 hover:text-blue-600"
|
|
onClick={onStartComment}
|
|
title="Add comment"
|
|
>
|
|
<MessageSquarePlus className="h-3.5 w-3.5" />
|
|
</button>
|
|
</td>
|
|
|
|
{/* Code content */}
|
|
<td className="pl-1 pr-3 align-top">
|
|
<pre
|
|
className={`leading-5 whitespace-pre-wrap break-all ${textColorClass}`}
|
|
>
|
|
<span className="select-none text-muted-foreground/60">
|
|
{prefix}
|
|
</span>
|
|
{line.content}
|
|
</pre>
|
|
</td>
|
|
</tr>
|
|
|
|
{/* Existing comments on this line */}
|
|
{lineComments.length > 0 && (
|
|
<tr>
|
|
<td
|
|
colSpan={3}
|
|
className="px-3 py-2 bg-muted/20 border-y border-border/50"
|
|
>
|
|
<CommentThread
|
|
comments={lineComments}
|
|
onResolve={onResolveComment}
|
|
onUnresolve={onUnresolveComment}
|
|
/>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
|
|
{/* Inline comment form */}
|
|
{isCommenting && (
|
|
<tr>
|
|
<td
|
|
colSpan={3}
|
|
className="px-3 py-2 bg-blue-50/50 dark:bg-blue-950/20 border-y border-blue-200 dark:border-blue-900"
|
|
>
|
|
<CommentForm
|
|
ref={formRef}
|
|
onSubmit={onSubmitComment}
|
|
onCancel={onCancelComment}
|
|
/>
|
|
</td>
|
|
</tr>
|
|
)}
|
|
</>
|
|
);
|
|
}
|