Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dataroom): remove docs / folders from dataroom #541

Merged
merged 5 commits into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions components/billing/upgrade-plan-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useRouter } from "next/router";

import { useEffect, useMemo, useState } from "react";
import React from "react";

Expand All @@ -13,6 +15,7 @@ import { useAnalytics } from "@/lib/analytics";
import { STAGGER_CHILD_VARIANTS } from "@/lib/constants";
import { getStripe } from "@/lib/stripe/client";
import { PLANS } from "@/lib/stripe/utils";
import { usePlan } from "@/lib/swr/use-billing";
import { capitalize } from "@/lib/utils";

import { DataroomTrialModal } from "../datarooms/dataroom-trial-modal";
Expand All @@ -31,12 +34,14 @@ export function UpgradePlanModal({
setOpen?: React.Dispatch<React.SetStateAction<boolean>>;
children?: React.ReactNode;
}) {
const router = useRouter();
const [plan, setPlan] = useState<"Pro" | "Business" | "Data Rooms">(
clickedPlan,
);
const [period, setPeriod] = useState<"yearly" | "monthly">("yearly");
const [clicked, setClicked] = useState<boolean>(false);
const teamInfo = useTeam();
const { plan: teamPlan } = usePlan();
const analytics = useAnalytics();

const features = useMemo(() => {
Expand Down Expand Up @@ -238,6 +243,23 @@ export function UpgradePlanModal({
// @ts-ignore
// prettier-ignore

if (teamPlan !== "free") {
fetch(
`/api/teams/${teamInfo?.currentTeam?.id}/billing/manage`,
{
method: "POST",
},
)
.then(async (res) => {
const url = await res.json();
router.push(url);
})
.catch((err) => {
alert(err);
setClicked(false);
});
} else {

fetch(
`/api/teams/${
teamInfo?.currentTeam?.id
Expand Down Expand Up @@ -265,6 +287,7 @@ export function UpgradePlanModal({
alert(err);
setClicked(false);
});
}
}}
>{`Upgrade to ${plan} ${capitalize(period)}`}</Button>
<div className="flex items-center justify-center space-x-2">
Expand Down
119 changes: 105 additions & 14 deletions components/datarooms/dataroom-document-card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Image from "next/image";
import Link from "next/link";
import { useRouter } from "next/router";

import { useEffect, useRef, useState } from "react";

Expand Down Expand Up @@ -34,21 +35,26 @@ import { MoveToDataroomFolderModal } from "./move-dataroom-folder-modal";
type DocumentsCardProps = {
document: DataroomFolderDocument;
teamInfo: TeamContextType | null;
dataroomId: string;
};
export default function DataroomDocumentCard({
document: dataroomDocument,
teamInfo,
dataroomId,
}: DocumentsCardProps) {
const { theme, systemTheme } = useTheme();
const isLight =
theme === "light" || (theme === "system" && systemTheme === "light");
const router = useRouter();

const { isCopied, copyToClipboard } = useCopyToClipboard({});
const [isFirstClick, setIsFirstClick] = useState<boolean>(false);
const [menuOpen, setMenuOpen] = useState<boolean>(false);
const [moveFolderOpen, setMoveFolderOpen] = useState<boolean>(false);
const dropdownRef = useRef<HTMLDivElement | null>(null);

/** current folder name */
const currentFolderPath = router.query.name as string[] | undefined;

// https://github.com/radix-ui/primitives/issues/1241#issuecomment-1888232392
useEffect(() => {
if (!moveFolderOpen) {
Expand All @@ -58,6 +64,89 @@ export default function DataroomDocumentCard({
}
}, [moveFolderOpen]);

useEffect(() => {
function handleClickOutside(event: { target: any }) {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setMenuOpen(false);
setIsFirstClick(false);
}
}

document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);

const handleButtonClick = (event: any, documentId: string) => {
event.stopPropagation();
event.preventDefault();

console.log("isFirstClick", isFirstClick);
if (isFirstClick) {
handleRemoveDocument(documentId);
setIsFirstClick(false);
setMenuOpen(false); // Close the dropdown after deleting
} else {
setIsFirstClick(true);
}
};

const handleRemoveDocument = async (documentId: string) => {
// Prevent the first click from deleting the document
if (!isFirstClick) {
setIsFirstClick(true);
return;
}

const endpoint = currentFolderPath
? `/folders/documents/${currentFolderPath.join("/")}`
: "/documents";

toast.promise(
fetch(
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms/${dataroomId}/documents/${documentId}`,
{
method: "DELETE",
},
).then(() => {
mutate(
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms/${dataroomId}${endpoint}`,
null,
{
populateCache: (_, docs) => {
return docs.filter(
(doc: DocumentWithLinksAndLinkCountAndViewCount) =>
doc.id !== documentId,
);
},
revalidate: false,
},
);
}),
{
loading: "Removing document...",
success: "Document removed successfully.",
error: "Failed to remove document. Try again.",
},
);
};

const handleMenuStateChange = (open: boolean) => {
if (isFirstClick) {
setMenuOpen(true); // Keep the dropdown open on the first click
return;
}

// If the menu is closed, reset the isFirstClick state
if (!open) {
setIsFirstClick(false);
setMenuOpen(false); // Ensure the dropdown is closed
} else {
setMenuOpen(true); // Open the dropdown
}
};

return (
<>
<li className="group/row relative flex items-center justify-between rounded-lg border-0 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">
Expand Down Expand Up @@ -114,7 +203,7 @@ export default function DataroomDocumentCard({
</p>
</Link>

<DropdownMenu>
<DropdownMenu open={menuOpen} onOpenChange={handleMenuStateChange}>
<DropdownMenuTrigger asChild>
<Button
// size="icon"
Expand All @@ -133,18 +222,20 @@ export default function DataroomDocumentCard({
</DropdownMenuItem>
<DropdownMenuSeparator />

{/* <DropdownMenuItem
onClick={(event) => handleButtonClick(event, prismaDocument.id)}
className="text-destructive focus:bg-destructive focus:text-destructive-foreground duration-200"
>
{isFirstClick ? (
"Really delete?"
) : (
<>
<TrashIcon className="w-4 h-4 mr-2" /> Delete document
</>
)}
</DropdownMenuItem> */}
<DropdownMenuItem
onClick={(event) =>
handleButtonClick(event, dataroomDocument.id)
}
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really remove?"
) : (
<>
<TrashIcon className="mr-2 h-4 w-4" /> Remove document
</>
)}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
Expand Down
27 changes: 26 additions & 1 deletion components/documents/document-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from "react";

import { useTeam } from "@/context/team-context";
import { Document, DocumentVersion } from "@prisma/client";
import { Sparkles, TrashIcon } from "lucide-react";
import { BetweenHorizontalStartIcon, Sparkles, TrashIcon } from "lucide-react";
import { usePlausible } from "next-plausible";
import { useTheme } from "next-themes";
import { toast } from "sonner";
Expand All @@ -32,6 +32,7 @@ import { cn, getExtension } from "@/lib/utils";
import PortraitLandscape from "../shared/icons/portrait-landscape";
import LoadingSpinner from "../ui/loading-spinner";
import { AddDocumentModal } from "./add-document-modal";
import { AddToDataroomModal } from "./move-dataroom-modal";

export default function DocumentHeader({
prismaDocument,
Expand All @@ -54,6 +55,7 @@ export default function DocumentHeader({
const [menuOpen, setMenuOpen] = useState<boolean>(false);
const [isFirstClick, setIsFirstClick] = useState<boolean>(false);
const [orientationLoading, setOrientationLoading] = useState<boolean>(false);
const [addDataroomOpen, setAddDataroomOpen] = useState<boolean>(false);

const nameRef = useRef<HTMLHeadingElement>(null);
const enterPressedRef = useRef<boolean>(false);
Expand All @@ -68,6 +70,15 @@ export default function DocumentHeader({

const plausible = usePlausible();

// https://github.com/radix-ui/primitives/issues/1241#issuecomment-1888232392
useEffect(() => {
if (!addDataroomOpen) {
setTimeout(() => {
document.body.style.pointerEvents = "";
});
}
}, [addDataroomOpen]);

const handleNameSubmit = async () => {
if (enterPressedRef.current) {
enterPressedRef.current = false;
Expand Down Expand Up @@ -442,6 +453,11 @@ export default function DocumentHeader({
</DropdownMenuItem>
))}

<DropdownMenuItem onClick={() => setAddDataroomOpen(true)}>
<BetweenHorizontalStartIcon className="mr-2 h-4 w-4" />
Add to dataroom
</DropdownMenuItem>

<DropdownMenuSeparator />

<DropdownMenuItem
Expand All @@ -455,6 +471,15 @@ export default function DocumentHeader({
</DropdownMenuContent>
</DropdownMenu>
</div>

{addDataroomOpen ? (
<AddToDataroomModal
open={addDataroomOpen}
setOpen={setAddDataroomOpen}
documentId={prismaDocument.id}
documentName={prismaDocument.name}
/>
) : null}
</header>
);
}
1 change: 1 addition & 0 deletions components/documents/documents-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export function DocumentsList({
key={document.id}
document={document as DataroomFolderDocument}
teamInfo={teamInfo}
dataroomId={dataroomId}
/>
);
} else {
Expand Down
15 changes: 10 additions & 5 deletions components/documents/folder-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function FolderCard({
},
),
{
loading: "Deleting folder...",
loading: isDataroom ? "Removing folder..." : "Deleting folder...",
success: () => {
mutate(
`/api/teams/${teamInfo?.currentTeam?.id}/${endpointTargetType}?root=true`,
Expand All @@ -114,9 +114,13 @@ export default function FolderCard({
mutate(
`/api/teams/${teamInfo?.currentTeam?.id}/${endpointTargetType}${parentFolderPath}`,
);
return "Folder deleted successfully.";
return isDataroom
? "Folder removed successfully."
: "Folder deleted successfully.";
},
error: "Failed to delete folder. Move documents first.",
error: isDataroom
? "Failed to remove folder."
: "Failed to delete folder. Move documents first.",
},
);
};
Expand Down Expand Up @@ -242,10 +246,11 @@ export default function FolderCard({
className="text-destructive duration-200 focus:bg-destructive focus:text-destructive-foreground"
>
{isFirstClick ? (
"Really delete?"
`Really ${isDataroom ? "remove" : "delete"}?`
) : (
<>
<TrashIcon className="mr-2 h-4 w-4" /> Delete Folder
<TrashIcon className="mr-2 h-4 w-4" />{" "}
{isDataroom ? "Remove Folder" : "Delete Folder"}
</>
)}
</DropdownMenuItem>
Expand Down
6 changes: 6 additions & 0 deletions pages/api/teams/[teamId]/billing/manage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getServerSession } from "next-auth/next";
import { errorhandler } from "@/lib/errorHandler";
import prisma from "@/lib/prisma";
import { stripe } from "@/lib/stripe";
import { CustomUser } from "@/lib/types";

import { authOptions } from "../../../auth/[...nextauth]";

Expand All @@ -25,6 +26,11 @@ export default async function handle(
const team = await prisma.team.findUnique({
where: {
id: teamId,
users: {
some: {
userId: (session.user as CustomUser).id,
},
},
},
select: {
stripeId: true,
Expand Down
Loading