Skip to content

Commit

Permalink
Merge pull request #1470 from mfts/marc/pm-72-migrate-to-trigger-v3-f…
Browse files Browse the repository at this point in the history
…or-the-document-upload

feat: migrate to trigger v3
  • Loading branch information
mfts authored Feb 4, 2025
2 parents b71e99a + cd366b8 commit 0cab8ca
Show file tree
Hide file tree
Showing 20 changed files with 1,207 additions and 769 deletions.
211 changes: 122 additions & 89 deletions components/datarooms/dataroom-document-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { cn, nFormatter, timeAgo } from "@/lib/utils";
import { fileIcon } from "@/lib/utils/get-file-icon";

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

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

// Add state for document processing status
const [isProcessing, setIsProcessing] = useState(false);

// https://github.com/radix-ui/primitives/issues/1241#issuecomment-1888232392
useEffect(() => {
if (!moveFolderOpen) {
Expand Down Expand Up @@ -170,107 +174,136 @@ export default function DataroomDocumentCard({
<div
onClick={handleCardClick}
className={cn(
"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",
"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",
isDragging ? "cursor-grabbing" : "cursor-pointer",
isHovered && "bg-secondary ring-gray-300 dark:ring-gray-500",
)}
>
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
{!isSelected && !isHovered ? (
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
{fileIcon({
fileType: dataroomDocument.document.type ?? "",
className: "h-8 w-8",
isLight,
})}
</div>
) : (
<div className="mx-0.5 w-8 sm:mx-1"></div>
<div
className={cn(
"flex items-center justify-between p-3 sm:p-4",
isProcessing && "opacity-60",
)}
>
<div className="flex min-w-0 shrink items-center space-x-2 sm:space-x-4">
{!isSelected && !isHovered ? (
<div className="mx-0.5 flex w-8 items-center justify-center text-center sm:mx-1">
{fileIcon({
fileType: dataroomDocument.document.type ?? "",
className: "h-8 w-8",
isLight,
})}
</div>
) : (
<div className="mx-0.5 w-8 sm:mx-1"></div>
)}

<div className="flex-col">
<div className="flex items-center">
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
{dataroomDocument.document.name}
</h2>
</div>
<div className="mt-1 flex items-center space-x-1 text-xs leading-5 text-muted-foreground">
<p className="truncate">{timeAgo(dataroomDocument.createdAt)}</p>
{dataroomDocument.document._count.versions > 1 ? (
<>
<p></p>
<p className="truncate">{`${dataroomDocument.document._count.versions} Versions`}</p>
</>
) : null}
<div className="flex-col">
<div className="flex items-center">
<h2 className="min-w-0 max-w-[150px] truncate text-sm font-semibold leading-6 text-foreground sm:max-w-md">
{dataroomDocument.document.name}
</h2>
</div>
<div className="mt-1 flex items-center space-x-1 text-xs leading-5 text-muted-foreground">
<p className="truncate">
{timeAgo(dataroomDocument.createdAt)}
</p>
{dataroomDocument.document._count.versions > 1 ? (
<>
<p></p>
<p className="truncate">{`${dataroomDocument.document._count.versions} Versions`}</p>
</>
) : null}
</div>
</div>
</div>
</div>

<div className="flex flex-row space-x-2">
<Link
onClick={(e) => {
e.stopPropagation();
}}
href={`/documents/${dataroomDocument.document.id}`}
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"
>
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
{nFormatter(dataroomDocument.document._count.views)}
<span className="ml-1 hidden sm:inline-block">views</span>
</p>
</Link>
<div className="flex flex-row space-x-2">
<Link
onClick={(e) => {
e.stopPropagation();
}}
href={`/documents/${dataroomDocument.document.id}`}
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"
>
<BarChart className="h-3 w-3 text-muted-foreground sm:h-4 sm:w-4" />
<p className="whitespace-nowrap text-xs text-muted-foreground sm:text-sm">
{nFormatter(dataroomDocument.document._count.views)}
<span className="ml-1 hidden sm:inline-block">views</span>
</p>
</Link>

<DropdownMenu open={menuOpen} onOpenChange={handleMenuStateChange}>
<DropdownMenuTrigger asChild>
<Button
// size="icon"
variant="outline"
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"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" ref={dropdownRef}>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
setMoveFolderOpen(true);
}}
>
<FolderInputIcon className="mr-2 h-4 w-4" />
Move to folder
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
setAddDataRoomOpen(true);
}}
>
<BetweenHorizontalStartIcon className="mr-2 h-4 w-4" />
Copy to other dataroom
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenu open={menuOpen} onOpenChange={handleMenuStateChange}>
<DropdownMenuTrigger asChild>
<Button
// size="icon"
variant="outline"
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"
>
<span className="sr-only">Open menu</span>
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" ref={dropdownRef}>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
setMoveFolderOpen(true);
}}
>
<FolderInputIcon className="mr-2 h-4 w-4" />
Move to folder
</DropdownMenuItem>
<DropdownMenuItem
onClick={(e) => {
e.stopPropagation();
setAddDataRoomOpen(true);
}}
>
<BetweenHorizontalStartIcon className="mr-2 h-4 w-4" />
Copy to other dataroom
</DropdownMenuItem>
<DropdownMenuSeparator />

<DropdownMenuItem
onClick={(event) =>
handleButtonClick(event, dataroomDocument.id)
}
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really remove?"
) : (
<>
<ArchiveXIcon className="mr-2 h-4 w-4" /> Remove document
</>
)}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DropdownMenuItem
onClick={(event) =>
handleButtonClick(event, dataroomDocument.id)
}
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really remove?"
) : (
<>
<ArchiveXIcon className="mr-2 h-4 w-4" /> Remove document
</>
)}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>

{(teamInfo?.currentTeam?.id === "cluqtfmcr0001zkza4xcgqatw" ||
teamInfo?.currentTeam?.id === "clup33by90000oewh4rfvp2eg") &&
["pdf", "docs", "slides", "cad"].includes(
dataroomDocument.document.type,
) &&
!dataroomDocument.document.versions?.[0]?.hasPages &&
dataroomDocument.document.versions?.[0]?.id && (
<FileProcessStatusBar
documentVersionId={dataroomDocument.document.versions[0].id}
className="rounded-b-lg border-t border-gray-200 dark:border-gray-700"
mutateDocument={() => {
setIsProcessing(false);
mutate(
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms/${dataroomId}/documents`,
);
}}
onProcessingChange={(processing) => setIsProcessing(processing)}
/>
)}
</div>
{addDataRoomOpen ? (
<AddToDataroomModal
Expand Down
87 changes: 87 additions & 0 deletions components/documents/file-process-status-bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useEffect } from "react";

import useSWRImmutable from "swr/immutable";

import { Progress } from "@/components/ui/progress";

import { cn, fetcher } from "@/lib/utils";
import { useDocumentProgressStatus } from "@/lib/utils/use-progress-status";

export default function FileProcessStatusBar({
documentVersionId,
className,
mutateDocument,
onProcessingChange,
}: {
documentVersionId: string;
className?: string;
mutateDocument: () => void;
onProcessingChange?: (processing: boolean) => void;
}) {
const { data } = useSWRImmutable<{ publicAccessToken: string }>(
`/api/progress-token?documentVersionId=${documentVersionId}`,
fetcher,
);

const { status: progressStatus, error: progressError } =
useDocumentProgressStatus(documentVersionId, data?.publicAccessToken);

// Update processing state whenever status changes
useEffect(() => {
if (onProcessingChange) {
onProcessingChange(
progressStatus.state === "QUEUED" ||
progressStatus.state === "EXECUTING",
);
}
}, [progressStatus.state, onProcessingChange]);

if (progressStatus.state === "QUEUED") {
return (
<Progress
value={0}
text="Processing document..."
className={cn(
"w-full rounded-none text-[8px] font-semibold",
className,
)}
/>
);
}

if (
progressError ||
["FAILED", "CRASHED", "CANCELED", "SYSTEM_FAILURE"].includes(
progressStatus.state,
)
) {
return (
<Progress
value={0}
text={
progressError?.message ||
progressStatus.text ||
"Error processing document"
}
error={true}
className={cn(
"w-full rounded-none text-[8px] font-semibold",
className,
)}
/>
);
}

if (progressStatus.state === "COMPLETED") {
mutateDocument();
return null;
}

return (
<Progress
value={progressStatus.progress || 0}
text={progressStatus.text || "Processing document..."}
className={cn("w-full rounded-none text-[8px] font-semibold", className)}
/>
);
}
11 changes: 6 additions & 5 deletions components/documents/process-status-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Progress } from "@/components/ui/progress";

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

export default function ProcessStatusBar({
export default function FileProcessStatusBar({
documentVersionId,
className,
}: {
Expand All @@ -18,7 +18,7 @@ export default function ProcessStatusBar({
return (
<Progress
value={0}
text="Processing document..."
text="Processing file..."
className={cn(
"w-full rounded-none text-[8px] font-semibold",
className,
Expand All @@ -31,7 +31,8 @@ export default function ProcessStatusBar({
return (
<Progress
value={0}
text={error.message}
text={error?.message || "Error processing file"}
error={true}
className={cn(
"w-full rounded-none text-[8px] font-semibold",
className,
Expand All @@ -45,13 +46,13 @@ export default function ProcessStatusBar({
}

const progress = Number(statuses[0]?.data?.progress) * 100 || 0;
const text = String(statuses[0]?.data?.text) || "";
const text = String(statuses[0]?.data?.text) || "Processing file...";

if (run.status === "FAILURE") {
return (
<Progress
value={progress}
text={`Error processing document page ${Number(statuses[0]?.data?.currentPage)}`}
text="Error processing file"
error={true}
className={cn(
"w-full rounded-none text-[8px] font-semibold",
Expand Down
Loading

0 comments on commit 0cab8ca

Please sign in to comment.