Skip to content

Commit e97261f

Browse files
authored
Merge pull request #360 from mfts/feat/shareable-folders
[staging]: feat: shareable folders / dataroom
2 parents b037068 + c7bd707 commit e97261f

59 files changed

Lines changed: 3903 additions & 157 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Pipfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ verify_ssl = true
44
name = "pypi"
55

66
[packages]
7-
tinybird-cli = "3.3.0"
7+
tinybird-cli = "*"
88

99
[dev-packages]
1010

Pipfile.lock

Lines changed: 35 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/Sidebar.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ import {
2020
PlusIcon,
2121
FolderIcon as FolderLucideIcon,
2222
FolderOpenIcon,
23+
ServerIcon,
2324
} from "lucide-react";
2425
import SiderbarFolders from "./sidebar-folders";
25-
import { AddFolderModal } from "./documents/add-folder-modal";
26+
import { AddFolderModal } from "./folders/add-folder-modal";
2627
import { ScrollArea } from "./ui/scroll-area";
2728

2829
export default function Sidebar() {
@@ -97,6 +98,14 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
9798
active: router.pathname.includes("documents"),
9899
disabled: false,
99100
},
101+
{
102+
name: "Datarooms",
103+
href: "/datarooms",
104+
icon: ServerIcon,
105+
current: router.pathname.includes("datarooms"),
106+
active: false,
107+
disabled: false,
108+
},
100109
{
101110
name: "Branding",
102111
href: "/settings/branding",
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { Button } from "@/components/ui/button";
2+
import {
3+
Dialog,
4+
DialogContent,
5+
DialogDescription,
6+
DialogFooter,
7+
DialogHeader,
8+
DialogTitle,
9+
} from "@/components/ui/dialog";
10+
import { useTeam } from "@/context/team-context";
11+
import { useState } from "react";
12+
import { toast } from "sonner";
13+
import { mutate } from "swr";
14+
import { SidebarFolderTreeSelection } from "@/components/sidebar-folders";
15+
import { useRouter } from "next/router";
16+
17+
export function AddDataroomDocumentModal({
18+
open,
19+
setOpen,
20+
dataroomId,
21+
documentName,
22+
}: {
23+
open: boolean;
24+
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
25+
dataroomId?: string;
26+
documentName?: string;
27+
}) {
28+
const router = useRouter();
29+
const [folderId, setFolderId] = useState<string>("");
30+
const [documentId, setDocumentId] = useState<string>("");
31+
const [loading, setLoading] = useState<boolean>(false);
32+
33+
const teamInfo = useTeam();
34+
35+
/** current folder name */
36+
const currentFolderPath = router.query.name as string[] | undefined;
37+
38+
const handleSubmit = async (event: any) => {
39+
event.preventDefault();
40+
event.stopPropagation();
41+
42+
if (folderId === "") return;
43+
44+
setLoading(true);
45+
try {
46+
const response = await fetch(
47+
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms/${dataroomId}/documents`,
48+
{
49+
method: "POST",
50+
headers: {
51+
"Content-Type": "application/json",
52+
},
53+
body: JSON.stringify({
54+
documentId: documentId,
55+
folderPathName: currentFolderPath?.join("/"),
56+
}),
57+
},
58+
);
59+
60+
if (!response.ok) {
61+
const { message } = await response.json();
62+
setLoading(false);
63+
toast.error(message);
64+
return;
65+
}
66+
67+
const { newPath, oldPath } = (await response.json()) as {
68+
newPath: string;
69+
oldPath: string;
70+
};
71+
72+
toast.success("Document moved successfully!");
73+
74+
// mutate(`/api/teams/${teamInfo?.currentTeam?.id}/folders`);
75+
// mutate(`/api/teams/${teamInfo?.currentTeam?.id}/folders${oldPath}`);
76+
// mutate(`/api/teams/${teamInfo?.currentTeam?.id}/folders${newPath}`).then(
77+
// () => {
78+
// router.push(`/documents/tree${newPath}`);
79+
// },
80+
// );
81+
} catch (error) {
82+
console.error("Error moving document", error);
83+
toast.error("Failed to move document. Try again.");
84+
} finally {
85+
setLoading(false);
86+
setOpen(false);
87+
}
88+
};
89+
90+
return (
91+
<Dialog open={open} onOpenChange={setOpen}>
92+
<DialogContent className="sm:max-w-[425px]">
93+
<DialogHeader className="text-start">
94+
<DialogTitle>Add Document</DialogTitle>
95+
<DialogDescription>Add your document to dataroom</DialogDescription>
96+
</DialogHeader>
97+
<form>
98+
<div className="mb-2">
99+
<SidebarFolderTreeSelection
100+
selectedFolderId={folderId}
101+
setFolderId={setFolderId}
102+
/>
103+
</div>
104+
105+
<DialogFooter>
106+
<Button
107+
onClick={handleSubmit}
108+
className="w-full h-9"
109+
loading={loading}
110+
>
111+
Add to dataroom
112+
</Button>
113+
</DialogFooter>
114+
</form>
115+
</DialogContent>
116+
</Dialog>
117+
);
118+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { Button } from "@/components/ui/button";
2+
import {
3+
Dialog,
4+
DialogContent,
5+
DialogDescription,
6+
DialogFooter,
7+
DialogHeader,
8+
DialogTitle,
9+
DialogTrigger,
10+
} from "@/components/ui/dialog";
11+
import { Input } from "@/components/ui/input";
12+
import { Label } from "@/components/ui/label";
13+
import { useTeam } from "@/context/team-context";
14+
import { useState } from "react";
15+
import { toast } from "sonner";
16+
import { UpgradePlanModal } from "../billing/upgrade-plan-modal";
17+
import { usePlan } from "@/lib/swr/use-billing";
18+
import { useAnalytics } from "@/lib/analytics";
19+
import { mutate } from "swr";
20+
21+
export function AddDataroomModal({ children }: { children?: React.ReactNode }) {
22+
const [dataroomName, setDataroomName] = useState<string>("");
23+
const [loading, setLoading] = useState<boolean>(false);
24+
const [open, setOpen] = useState<boolean>(false);
25+
26+
const teamInfo = useTeam();
27+
const { plan } = usePlan();
28+
const analytics = useAnalytics();
29+
30+
const handleSubmit = async (event: any) => {
31+
event.preventDefault();
32+
event.stopPropagation();
33+
34+
if (dataroomName == "") return;
35+
36+
setLoading(true);
37+
38+
try {
39+
const response = await fetch(
40+
`/api/teams/${teamInfo?.currentTeam?.id}/datarooms`,
41+
{
42+
method: "POST",
43+
headers: {
44+
"Content-Type": "application/json",
45+
},
46+
body: JSON.stringify({
47+
name: dataroomName,
48+
}),
49+
},
50+
);
51+
52+
if (!response.ok) {
53+
const { message } = await response.json();
54+
setLoading(false);
55+
toast.error(message);
56+
return;
57+
}
58+
59+
analytics.capture("Dataroom Created", { dataroomName: dataroomName });
60+
toast.success("Dataroom successfully created! 🎉");
61+
62+
mutate(`/api/teams/${teamInfo?.currentTeam?.id}/datarooms`);
63+
} catch (error) {
64+
setLoading(false);
65+
toast.error("Error adding folder. Please try again.");
66+
return;
67+
} finally {
68+
setLoading(false);
69+
setOpen(false);
70+
}
71+
};
72+
73+
// If the team is on a free plan, show the upgrade modal
74+
if (plan && plan.plan === "free") {
75+
if (children) {
76+
return (
77+
<UpgradePlanModal clickedPlan="Pro" trigger={"add_dataroom_overview"}>
78+
{children}
79+
</UpgradePlanModal>
80+
);
81+
}
82+
}
83+
84+
return (
85+
<Dialog open={open} onOpenChange={setOpen}>
86+
<DialogTrigger asChild>{children}</DialogTrigger>
87+
<DialogContent className="sm:max-w-[425px]">
88+
<DialogHeader className="text-start">
89+
<DialogTitle>Create dataroom</DialogTitle>
90+
<DialogDescription>
91+
Start creating a dataroom with a name.
92+
</DialogDescription>
93+
</DialogHeader>
94+
<form onSubmit={handleSubmit}>
95+
<Label htmlFor="dataroom-name" className="opacity-80">
96+
Dataroom Name
97+
</Label>
98+
<Input
99+
id="dataroom-name"
100+
placeholder="ACME Aquisition"
101+
className="w-full mt-1 mb-4"
102+
onChange={(e) => setDataroomName(e.target.value)}
103+
/>
104+
<DialogFooter>
105+
<Button type="submit" className="w-full h-9" loading={loading}>
106+
Add new dataroom
107+
</Button>
108+
</DialogFooter>
109+
</form>
110+
</DialogContent>
111+
</Dialog>
112+
);
113+
}

0 commit comments

Comments
 (0)