Skip to content

Commit 0cab8ca

Browse files
authored
Merge pull request #1470 from mfts/marc/pm-72-migrate-to-trigger-v3-for-the-document-upload
feat: migrate to trigger v3
2 parents b71e99a + cd366b8 commit 0cab8ca

20 files changed

Lines changed: 1207 additions & 769 deletions

File tree

components/datarooms/dataroom-document-card.tsx

Lines changed: 122 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { cn, nFormatter, timeAgo } from "@/lib/utils";
3232
import { fileIcon } from "@/lib/utils/get-file-icon";
3333

3434
import { AddToDataroomModal } from "../documents/add-document-to-dataroom-modal";
35+
import FileProcessStatusBar from "../documents/file-process-status-bar";
3536
import { MoveToDataroomFolderModal } from "./move-dataroom-folder-modal";
3637

3738
type DocumentsCardProps = {
@@ -64,6 +65,9 @@ export default function DataroomDocumentCard({
6465
/** current folder name */
6566
const currentFolderPath = router.query.name as string[] | undefined;
6667

68+
// Add state for document processing status
69+
const [isProcessing, setIsProcessing] = useState(false);
70+
6771
// https://github.com/radix-ui/primitives/issues/1241#issuecomment-1888232392
6872
useEffect(() => {
6973
if (!moveFolderOpen) {
@@ -170,107 +174,136 @@ export default function DataroomDocumentCard({
170174
<div
171175
onClick={handleCardClick}
172176
className={cn(
173-
"group/row relative flex items-center justify-between rounded-lg border-0 bg-white p-3 ring-1 ring-gray-200 transition-all hover:bg-secondary hover:ring-gray-300 dark:bg-secondary dark:ring-gray-700 hover:dark:ring-gray-500 sm:p-4",
177+
"group/row relative flex flex-col rounded-lg border-0 bg-white ring-1 ring-gray-200 transition-all hover:bg-secondary hover:ring-gray-300 dark:bg-secondary dark:ring-gray-700 hover:dark:ring-gray-500",
174178
isDragging ? "cursor-grabbing" : "cursor-pointer",
175179
isHovered && "bg-secondary ring-gray-300 dark:ring-gray-500",
176180
)}
177181
>
178-
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
179-
{!isSelected && !isHovered ? (
180-
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
181-
{fileIcon({
182-
fileType: dataroomDocument.document.type ?? "",
183-
className: "h-8 w-8",
184-
isLight,
185-
})}
186-
</div>
187-
) : (
188-
<div className="mx-0.5 w-8 sm:mx-1"></div>
182+
<div
183+
className={cn(
184+
"flex items-center justify-between p-3 sm:p-4",
185+
isProcessing && "opacity-60",
189186
)}
187+
>
188+
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
189+
{!isSelected && !isHovered ? (
190+
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
191+
{fileIcon({
192+
fileType: dataroomDocument.document.type ?? "",
193+
className: "h-8 w-8",
194+
isLight,
195+
})}
196+
</div>
197+
) : (
198+
<div className="mx-0.5 w-8 sm:mx-1"></div>
199+
)}
190200

191-
<div className="flex-col">
192-
<div className="flex items-center">
193-
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
194-
{dataroomDocument.document.name}
195-
</h2>
196-
</div>
197-
<div className="mt-1 flex items-center space-x-1 text-xs leading-5 text-muted-foreground">
198-
<p className="truncate">{timeAgo(dataroomDocument.createdAt)}</p>
199-
{dataroomDocument.document._count.versions > 1 ? (
200-
<>
201-
<p></p>
202-
<p className="truncate">{`${dataroomDocument.document._count.versions} Versions`}</p>
203-
</>
204-
) : null}
201+
<div className="flex-col">
202+
<div className="flex items-center">
203+
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
204+
{dataroomDocument.document.name}
205+
</h2>
206+
</div>
207+
<div className="mt-1 flex items-center space-x-1 text-xs leading-5 text-muted-foreground">
208+
<p className="truncate">
209+
{timeAgo(dataroomDocument.createdAt)}
210+
</p>
211+
{dataroomDocument.document._count.versions > 1 ? (
212+
<>
213+
<p></p>
214+
<p className="truncate">{`${dataroomDocument.document._count.versions} Versions`}</p>
215+
</>
216+
) : null}
217+
</div>
205218
</div>
206219
</div>
207-
</div>
208220

209-
<div className="flex flex-row space-x-2">
210-
<Link
211-
onClick={(e) => {
212-
e.stopPropagation();
213-
}}
214-
href={`/documents/${dataroomDocument.document.id}`}
215-
className="z-10 flex items-center space-x-1 rounded-md bg-gray-200 px-1.5 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100 dark:bg-gray-700 sm:px-2"
216-
>
217-
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
218-
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
219-
{nFormatter(dataroomDocument.document._count.views)}
220-
<span className="ml-1 hidden sm:inline-block">views</span>
221-
</p>
222-
</Link>
221+
<div className="flex flex-row space-x-2">
222+
<Link
223+
onClick={(e) => {
224+
e.stopPropagation();
225+
}}
226+
href={`/documents/${dataroomDocument.document.id}`}
227+
className="z-10 flex items-center space-x-1 rounded-md bg-gray-200 px-1.5 py-0.5 transition-all duration-75 hover:scale-105 active:scale-100 dark:bg-gray-700 sm:px-2"
228+
>
229+
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
230+
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
231+
{nFormatter(dataroomDocument.document._count.views)}
232+
<span className="ml-1 hidden sm:inline-block">views</span>
233+
</p>
234+
</Link>
223235

224-
<DropdownMenu open={menuOpen} onOpenChange={handleMenuStateChange}>
225-
<DropdownMenuTrigger asChild>
226-
<Button
227-
// size="icon"
228-
variant="outline"
229-
className="z-10 h-8 w-8 border-gray-200 bg-transparent p-0 hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
230-
>
231-
<span className="sr-only">Open menu</span>
232-
<MoreVertical className="h-4 w-4" />
233-
</Button>
234-
</DropdownMenuTrigger>
235-
<DropdownMenuContent align="end" ref={dropdownRef}>
236-
<DropdownMenuLabel>Actions</DropdownMenuLabel>
237-
<DropdownMenuItem
238-
onClick={(e) => {
239-
e.stopPropagation();
240-
setMoveFolderOpen(true);
241-
}}
242-
>
243-
<FolderInputIcon className="mr-2 h-4 w-4" />
244-
Move to folder
245-
</DropdownMenuItem>
246-
<DropdownMenuItem
247-
onClick={(e) => {
248-
e.stopPropagation();
249-
setAddDataRoomOpen(true);
250-
}}
251-
>
252-
<BetweenHorizontalStartIcon className="mr-2 h-4 w-4" />
253-
Copy to other dataroom
254-
</DropdownMenuItem>
255-
<DropdownMenuSeparator />
236+
<DropdownMenu open={menuOpen} onOpenChange={handleMenuStateChange}>
237+
<DropdownMenuTrigger asChild>
238+
<Button
239+
// size="icon"
240+
variant="outline"
241+
className="z-10 h-8 w-8 border-gray-200 bg-transparent p-0 hover:bg-gray-200 dark:border-gray-700 hover:dark:bg-gray-700 lg:h-9 lg:w-9"
242+
>
243+
<span className="sr-only">Open menu</span>
244+
<MoreVertical className="h-4 w-4" />
245+
</Button>
246+
</DropdownMenuTrigger>
247+
<DropdownMenuContent align="end" ref={dropdownRef}>
248+
<DropdownMenuLabel>Actions</DropdownMenuLabel>
249+
<DropdownMenuItem
250+
onClick={(e) => {
251+
e.stopPropagation();
252+
setMoveFolderOpen(true);
253+
}}
254+
>
255+
<FolderInputIcon className="mr-2 h-4 w-4" />
256+
Move to folder
257+
</DropdownMenuItem>
258+
<DropdownMenuItem
259+
onClick={(e) => {
260+
e.stopPropagation();
261+
setAddDataRoomOpen(true);
262+
}}
263+
>
264+
<BetweenHorizontalStartIcon className="mr-2 h-4 w-4" />
265+
Copy to other dataroom
266+
</DropdownMenuItem>
267+
<DropdownMenuSeparator />
256268

257-
<DropdownMenuItem
258-
onClick={(event) =>
259-
handleButtonClick(event, dataroomDocument.id)
260-
}
261-
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
262-
>
263-
{isFirstClick ? (
264-
"Really remove?"
265-
) : (
266-
<>
267-
<ArchiveXIcon className="mr-2 h-4 w-4" /> Remove document
268-
</>
269-
)}
270-
</DropdownMenuItem>
271-
</DropdownMenuContent>
272-
</DropdownMenu>
269+
<DropdownMenuItem
270+
onClick={(event) =>
271+
handleButtonClick(event, dataroomDocument.id)
272+
}
273+
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
274+
>
275+
{isFirstClick ? (
276+
"Really remove?"
277+
) : (
278+
<>
279+
<ArchiveXIcon className="mr-2 h-4 w-4" /> Remove document
280+
</>
281+
)}
282+
</DropdownMenuItem>
283+
</DropdownMenuContent>
284+
</DropdownMenu>
285+
</div>
273286
</div>
287+
288+
{(teamInfo?.currentTeam?.id === "cluqtfmcr0001zkza4xcgqatw" ||
289+
teamInfo?.currentTeam?.id === "clup33by90000oewh4rfvp2eg") &&
290+
["pdf", "docs", "slides", "cad"].includes(
291+
dataroomDocument.document.type,
292+
) &&
293+
!dataroomDocument.document.versions?.[0]?.hasPages &&
294+
dataroomDocument.document.versions?.[0]?.id && (
295+
<FileProcessStatusBar
296+
documentVersionId={dataroomDocument.document.versions[0].id}
297+
className="rounded-b-lg border-t border-gray-200 dark:border-gray-700"
298+
mutateDocument={() => {
299+
setIsProcessing(false);
300+
mutate(
301+
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms/${dataroomId}/documents`,
302+
);
303+
}}
304+
onProcessingChange={(processing) => setIsProcessing(processing)}
305+
/>
306+
)}
274307
</div>
275308
{addDataRoomOpen ? (
276309
<AddToDataroomModal
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { useEffect } from "react";
2+
3+
import useSWRImmutable from "swr/immutable";
4+
5+
import { Progress } from "@/components/ui/progress";
6+
7+
import { cn, fetcher } from "@/lib/utils";
8+
import { useDocumentProgressStatus } from "@/lib/utils/use-progress-status";
9+
10+
export default function FileProcessStatusBar({
11+
documentVersionId,
12+
className,
13+
mutateDocument,
14+
onProcessingChange,
15+
}: {
16+
documentVersionId: string;
17+
className?: string;
18+
mutateDocument: () => void;
19+
onProcessingChange?: (processing: boolean) => void;
20+
}) {
21+
const { data } = useSWRImmutable<{ publicAccessToken: string }>(
22+
`/api/progress-token?documentVersionId=${documentVersionId}`,
23+
fetcher,
24+
);
25+
26+
const { status: progressStatus, error: progressError } =
27+
useDocumentProgressStatus(documentVersionId, data?.publicAccessToken);
28+
29+
// Update processing state whenever status changes
30+
useEffect(() => {
31+
if (onProcessingChange) {
32+
onProcessingChange(
33+
progressStatus.state === "QUEUED" ||
34+
progressStatus.state === "EXECUTING",
35+
);
36+
}
37+
}, [progressStatus.state, onProcessingChange]);
38+
39+
if (progressStatus.state === "QUEUED") {
40+
return (
41+
<Progress
42+
value={0}
43+
text="Processing document..."
44+
className={cn(
45+
"w-full rounded-none text-[8px] font-semibold",
46+
className,
47+
)}
48+
/>
49+
);
50+
}
51+
52+
if (
53+
progressError ||
54+
["FAILED", "CRASHED", "CANCELED", "SYSTEM_FAILURE"].includes(
55+
progressStatus.state,
56+
)
57+
) {
58+
return (
59+
<Progress
60+
value={0}
61+
text={
62+
progressError?.message ||
63+
progressStatus.text ||
64+
"Error processing document"
65+
}
66+
error={true}
67+
className={cn(
68+
"w-full rounded-none text-[8px] font-semibold",
69+
className,
70+
)}
71+
/>
72+
);
73+
}
74+
75+
if (progressStatus.state === "COMPLETED") {
76+
mutateDocument();
77+
return null;
78+
}
79+
80+
return (
81+
<Progress
82+
value={progressStatus.progress || 0}
83+
text={progressStatus.text || "Processing document..."}
84+
className={cn("w-full rounded-none text-[8px] font-semibold", className)}
85+
/>
86+
);
87+
}

components/documents/process-status-bar.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Progress } from "@/components/ui/progress";
44

55
import { cn } from "@/lib/utils";
66

7-
export default function ProcessStatusBar({
7+
export default function FileProcessStatusBar({
88
documentVersionId,
99
className,
1010
}: {
@@ -18,7 +18,7 @@ export default function ProcessStatusBar({
1818
return (
1919
<Progress
2020
value={0}
21-
text="Processing document..."
21+
text="Processing file..."
2222
className={cn(
2323
"w-full rounded-none text-[8px] font-semibold",
2424
className,
@@ -31,7 +31,8 @@ export default function ProcessStatusBar({
3131
return (
3232
<Progress
3333
value={0}
34-
text={error.message}
34+
text={error?.message || "Error processing file"}
35+
error={true}
3536
className={cn(
3637
"w-full rounded-none text-[8px] font-semibold",
3738
className,
@@ -45,13 +46,13 @@ export default function ProcessStatusBar({
4546
}
4647

4748
const progress = Number(statuses[0]?.data?.progress) * 100 || 0;
48-
const text = String(statuses[0]?.data?.text) || "";
49+
const text = String(statuses[0]?.data?.text) || "Processing file...";
4950

5051
if (run.status === "FAILURE") {
5152
return (
5253
<Progress
5354
value={progress}
54-
text={`Error processing document page ${Number(statuses[0]?.data?.currentPage)}`}
55+
text="Error processing file"
5556
error={true}
5657
className={cn(
5758
"w-full rounded-none text-[8px] font-semibold",

0 commit comments

Comments
 (0)