Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
708d5cd
chore: update dependencies
mfts Nov 15, 2024
75b797c
fix: add missing isPreview flag
mfts Nov 15, 2024
069d749
fix: og-meta reset
mfts Nov 15, 2024
81ee33c
fix: export theme provider
mfts Nov 15, 2024
6dbdf23
feat: increase file size limit on pro and higher
mfts Nov 15, 2024
ac33543
docs: add free plan notice about document uploads
mfts Nov 15, 2024
42e9ab9
chore: cleanup
mfts Nov 15, 2024
0e82b37
feat: add in-document link explainer on free accounts
mfts Nov 15, 2024
fb0b1e0
feat: add visitor-useragent-placeholder
mfts Nov 15, 2024
2fbc584
fix:
mfts Nov 15, 2024
c18cef9
Merge pull request #1387 from mfts/chore/update-deps
mfts Nov 15, 2024
2080f9d
feat: add download-only file support
mfts Nov 18, 2024
2845792
feat: add fileSize to documentVersion
mfts Nov 18, 2024
4a689cc
feat: add visitor history types and add downloadedAt to history
mfts Nov 18, 2024
f0baf80
chore: update deps
mfts Nov 18, 2024
53923bf
fix: total average document duration
mfts Nov 18, 2024
befa2ab
feat: add download only icon to document and add missing fileSize
mfts Nov 18, 2024
3782af5
fix: properly return filteredViews from stats
mfts Nov 18, 2024
8904105
fix: missing fileSize
mfts Nov 18, 2024
6e940e2
Merge pull request #1389 from mfts/fix/total-average-duration
mfts Nov 18, 2024
b60261e
Merge pull request #1388 from mfts/feat/download-only
mfts Nov 18, 2024
ebb5103
fix: branding front page
mfts Nov 18, 2024
f701288
feat: add dataroom branding preview
mfts Nov 18, 2024
b17b976
refactor: move branding from settings
mfts Nov 18, 2024
42b6f56
Merge pull request #1390 from mfts/feat/dataroom-branding-preview
mfts Nov 19, 2024
a7dde0b
feat: add support for page-internal links
mfts Nov 19, 2024
a2b52fd
feat: make internal links jump work with scrolling
mfts Nov 19, 2024
e99654b
Merge pull request #1391 from mfts/feat/internal-links
mfts Nov 19, 2024
92ffa82
feat: add download document version to document tab
mfts Nov 19, 2024
86ad90f
Merge pull request #1392 from mfts/feat/download-document
mfts Nov 19, 2024
dbd67a6
style: add --warning color variable
mfts Nov 19, 2024
044dca1
feat: add new beta feature to feature flag
mfts Nov 19, 2024
2e10cd2
fix: simplify delete folder and dataroom
mfts Nov 20, 2024
328ca20
Merge pull request #1393 from mfts/fix/delete-modals
mfts Nov 20, 2024
b468ccb
fix: duplicate dataroom
mfts Nov 20, 2024
424b8c3
feat: add support for .xlsm files
mfts Nov 20, 2024
7231bff
Merge pull request #1394 from mfts/fix/dataroom-duplicate
mfts Nov 20, 2024
f905058
Merge branch 'main' into feat/dataroom-notifications
mfts Nov 20, 2024
1da5c43
chore: update dependencies
mfts Nov 20, 2024
f0a8121
Merge pull request #1395 from mfts/chore/updates
mfts Nov 20, 2024
810de81
fix: rollback react-notion-x version bump
mfts Nov 21, 2024
fae60a9
feat: add content disposition to s3 files
mfts Nov 21, 2024
08525ee
Merge pull request #1396 from mfts/refactor/convert-files
mfts Nov 21, 2024
74f5df4
fix: notion
mfts Nov 23, 2024
77f0634
Merge pull request #1397 from mfts/fix/notion
mfts Nov 23, 2024
74dd93d
Merge branch 'main' into feat/dataroom-notifications
mfts Nov 23, 2024
7ff9fda
feat: add dataroom notifications
mfts Nov 23, 2024
1f4f28b
feat: get delayed runs and cancel unsent runs
mfts Nov 23, 2024
5636e98
Merge pull request #1398 from mfts/feat/dataroom-notifications
mfts Nov 24, 2024
073e39a
feat: add dataroomId to add new document to dataroom automatically
mfts Nov 24, 2024
811ef58
Merge pull request #1399 from mfts/feat/extend-webhooks
mfts Nov 24, 2024
ec23fc1
fix: remove email regex
mfts Nov 25, 2024
d8586b9
Merge pull request #1400 from mfts/fix/email-pattern
mfts Nov 25, 2024
6e2e5a9
refactor: remove hashed ipAddress from verification token
mfts Nov 25, 2024
de94bd1
Merge pull request #1401 from mfts/fix/email-verification
mfts Nov 25, 2024
8fb917c
feat: add screen shield for discouraging screenshots
mfts Nov 26, 2024
3d4118d
chore: update deps
mfts Nov 26, 2024
867bdd0
refactor: remove hardcoded id
mfts Nov 26, 2024
e221114
feat: allow managers to create a token
mfts Nov 26, 2024
a456db4
Merge pull request #1403 from mfts/chore-remove-hardcoded-teamId
mfts Nov 26, 2024
b1ce6fd
Merge pull request #1402 from mfts/feat/screen-shield
mfts Nov 26, 2024
7117435
fix: update group permissions for deeply nested files
mfts Nov 28, 2024
06ba286
Merge pull request #1404 from mfts/fix/dataroom-group-custom-link
mfts Nov 28, 2024
cd40dd9
feat: add embeddable link
mfts Nov 28, 2024
9e96455
Merge pull request #1405 from mfts/feat/embeds
mfts Nov 28, 2024
9635dee
chore: cleanup
mfts Nov 28, 2024
e947ef0
feat: add delete domain modal
mfts Nov 28, 2024
18aadf5
Merge pull request #1406 from mfts/feat/delete-domain
mfts Nov 28, 2024
b7feb7e
feat: increase max file size limit
mfts Dec 3, 2024
6ee147a
chore: improve code readability
mfts Dec 8, 2024
3298d7f
refactor: add webhooks and rename incoming-webhooks
mfts Dec 8, 2024
14dd4ff
feat: add webhook events
mfts Dec 8, 2024
4ad2d23
feat: build in beta guards
mfts Dec 8, 2024
553867d
chore: cleanup
mfts Dec 8, 2024
870fe02
Merge pull request #1409 from mfts/feat/webhooks
mfts Dec 8, 2024
79b461b
feat: add dataroom-view to link.viewed trigger
mfts Dec 8, 2024
6e7df38
Merge pull request #1410 from mfts/feat/webhooks
mfts Dec 8, 2024
4f620fa
chore: update dependencies
mfts Dec 10, 2024
deaa9df
feat: add link name to email notification
mfts Dec 12, 2024
417d092
Merge pull request #1412 from mfts/feat/link-in-email
mfts Dec 12, 2024
5ca4ceb
feat: update unsubscribe route
mfts Dec 12, 2024
e6ab7f4
feat: add yir
mfts Dec 12, 2024
951e73a
feat: add prisma migration script
mfts Dec 12, 2024
605a9af
chore: update lint error
mfts Dec 12, 2024
8c47177
feat: update framer-motion to motion
mfts Dec 12, 2024
e07f32e
chore: update deps
mfts Dec 12, 2024
71fca8a
fix: lint error
mfts Dec 12, 2024
fdcebea
fix: error
mfts Dec 12, 2024
58b0e50
fix
mfts Dec 12, 2024
8b7029c
Merge pull request #1413 from mfts/feat/yir
mfts Dec 12, 2024
67057b0
feat: update fonts in og
mfts Dec 12, 2024
9f17d2b
Merge pull request #1411 from mfts/chore/deps
mfts Dec 13, 2024
9075aa0
fix: add contenttype and originalFile to agreements
mfts Dec 16, 2024
23d7735
Merge pull request #1414 from mfts/fix/agreement-originalfile
mfts Dec 16, 2024
2e7eee8
feat: add send-emails via cron
mfts Dec 18, 2024
7bcfdb3
Merge pull request #1415 from mfts/feat/yir
mfts Dec 18, 2024
3d28abc
chore: test
mfts Dec 18, 2024
2a1699c
Merge pull request #1416 from mfts/feat/yir
mfts Dec 18, 2024
78107f2
fix: generalize
mfts Dec 18, 2024
fa1dcfc
Merge pull request #1417 from mfts/feat/yir
mfts Dec 18, 2024
c11c9e0
chore: update deps
mfts Dec 19, 2024
6b52cee
Merge pull request #1418 from mfts/chore/dep
mfts Dec 19, 2024
f6146c4
feat: add location info to visitors in dataroom
mfts Dec 19, 2024
0d2eb64
feat(ee): add watermark on business
mfts Dec 20, 2024
815d767
Merge pull request #1419 from mfts/feat/dataroom-location
mfts Dec 20, 2024
8ad40ce
feat: improve export for document visits
mfts Dec 22, 2024
207b216
feat: add export visits for dataroom visits
mfts Dec 22, 2024
cc5b614
Merge pull request #1420 from mfts/feat/dataroom-location
mfts Dec 22, 2024
f262cd8
feat: add download-only button to document
mfts Dec 22, 2024
d56ffae
Merge pull request #1421 from mfts/feat/download-only
mfts Dec 22, 2024
e4a553a
fix: nda content
mfts Dec 22, 2024
098b577
chore: update notion styles
mfts Dec 22, 2024
85eaf0f
Merge pull request #1422 from mfts/fix/notion-style
mfts Dec 22, 2024
1fb52d5
fix: add style for divider component and adjust dark mode
mfts Dec 22, 2024
109770e
Merge pull request #1423 from mfts/fix/notion-style
mfts Dec 22, 2024
9c94a2f
feat: add better identifiers to posthog
mfts Jan 1, 2025
80a1f5e
Merge pull request #1427 from mfts/feat/posthog-add
mfts Jan 1, 2025
7045676
feat: add notion dark mode button
mfts Jan 2, 2025
c57509b
chore: update deps
mfts Jan 2, 2025
ce10363
Merge pull request #1428 from mfts/marc/pm-32-add-button-to-toggle-da…
mfts Jan 2, 2025
9e9ef5c
fix: import tailwind scrollbar hide
mfts Jan 3, 2025
a94d940
Merge pull request #1429 from mfts/marc/pm-59-update-dependencies
mfts Jan 3, 2025
b566139
fix: make watermark panel scrollable
mfts Jan 3, 2025
94f54f2
fix: make agreement panel scrollable
mfts Jan 3, 2025
513c908
refactor: change bottom padding on link sheet
mfts Jan 3, 2025
552a530
Merge pull request #1430 from mfts/marc/pm-27-save-watermark-button-n…
mfts Jan 3, 2025
3e8039f
feat: add search to visitors
mfts Jan 3, 2025
0b02b36
Merge pull request #1431 from mfts/marc/pm-60-search-by-email-address…
mfts Jan 3, 2025
32e0556
feat: update
ezralazuardy Jan 4, 2025
17153cf
feat: update
ezralazuardy Jan 4, 2025
da677fa
feat: update
ezralazuardy Jan 4, 2025
6840fc6
feat: update
ezralazuardy Jan 4, 2025
201b48e
feat: update
ezralazuardy Jan 4, 2025
4b7cab6
feat: update
ezralazuardy Jan 4, 2025
90631c0
feat: update
ezralazuardy Jan 4, 2025
2a12605
Merge branch 'lazuardytech:main' into main
ezralazuardy Jan 4, 2025
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
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,13 @@ lib/emails/marketing
.vscode

# trigger.dev
.trigger
.trigger

# python venv
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
6 changes: 3 additions & 3 deletions app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";

import { cn } from "@/lib/utils";
import { simpleEmailRegex, validateEmail } from "@/lib/utils/validate-email";
import { validateEmail } from "@/lib/utils/validate-email";

export default function Login() {
const { next } = useParams as { next?: string };
Expand Down Expand Up @@ -91,7 +91,7 @@ export default function Login() {
autoComplete="email"
autoCorrect="off"
disabled={clickedMethod === "email"}
pattern={simpleEmailRegex.source}
// pattern={patternSimpleEmailRegex}
value={email}
onChange={(e) => setEmail(e.target.value)}
className={cn(
Expand Down Expand Up @@ -221,7 +221,7 @@ export default function Login() {
<div className="mb-4 h-64 w-64">
<img
className="h-full w-full rounded-2xl object-cover shadow-2xl"
src="https://www.papermark.io/_static/testimonials/jaski.jpeg"
src="/_static/testimonials/jaski.jpeg"
alt="Jaski"
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/(auth)/verify/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export default function VerifyPage({
<div className="mb-4 h-64 w-64">
<img
className="h-full w-full rounded-2xl object-cover shadow-2xl"
src="https://www.papermark.io/_static/testimonials/jaski.jpeg"
src="/_static/testimonials/jaski.jpeg"
alt="Jaski"
/>
</div>
Expand Down
33 changes: 33 additions & 0 deletions app/api/cron/year-in-review/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { NextResponse } from "next/server";

import { receiver } from "@/lib/cron";
import { log } from "@/lib/utils";
import { processEmailQueue } from "@/lib/year-in-review/send-emails";

// Runs every hour (0 * * * *)
export const maxDuration = 300; // 5 minutes in seconds

export async function POST(req: Request) {
const body = await req.json();
if (process.env.VERCEL === "1") {
const isValid = await receiver.verify({
signature: req.headers.get("Upstash-Signature") || "",
body: JSON.stringify(body),
});
if (!isValid) {
return new Response("Unauthorized", { status: 401 });
}
}

try {
await processEmailQueue();
return NextResponse.json({ success: true });
} catch (error) {
await log({
message: `Year in review email cron failed. \n\nError: ${(error as Error).message}`,
type: "cron",
mention: true,
});
return NextResponse.json({ error: (error as Error).message });
}
}
16 changes: 16 additions & 0 deletions app/api/csp-report/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NextResponse } from "next/server";

export async function POST(request: Request) {
const report = await request.json();

// Log the report or send to your logging service
// console.log("CSP Violation:", report);

// You could send this to your logging service
// await fetch('your-logging-service', {
// method: 'POST',
// body: JSON.stringify(report)
// })

return NextResponse.json({ success: true });
}
100 changes: 100 additions & 0 deletions app/api/og/yir/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { ImageResponse } from "next/og";
import { NextRequest } from "next/server";

export const runtime = "edge";

export async function GET(req: NextRequest) {
const inter = await fetch(
new URL("@/styles/Inter-Regular.ttf", import.meta.url),
).then((res) => res.arrayBuffer());

const interBold = await fetch(
new URL("@/public/_static/Inter-Bold.ttf", import.meta.url),
).then((res) => res.arrayBuffer());

const year = req.nextUrl.searchParams.get("year") || "2024";
const minutesSpentOnDocs =
req.nextUrl.searchParams.get("minutesSpentOnDocs") || "1000";
const uploadedDocuments =
req.nextUrl.searchParams.get("uploadedDocuments") || "100";
const sharedLinks = req.nextUrl.searchParams.get("sharedLinks") || "10";
const receivedViews = req.nextUrl.searchParams.get("receivedViews") || "1000";

return new ImageResponse(
(
<div
tw="flex bg-black w-full h-full items-center justify-between"
style={{ padding: "48px" }}
>
{/* Left Side Text */}
<div tw="flex flex-col text-white" style={{ marginLeft: "48px" }}>
<div tw="flex text-7xl font-bold mb-4 tracking-tighter">
Papermark
</div>
<div tw="flex text-5xl mb-4">Year in Review</div>
<div tw="flex text-7xl font-bold">{year}</div>
</div>

{/* Ticket Container */}
<div
tw="flex flex-col bg-[#fb7a00] rounded-3xl relative overflow-hidden justify-between"
style={{
width: "400px",
height: "480px",
marginRight: "48px",
boxShadow: "0 0 100px -15px rgba(251, 122, 0, 0.3)",
border: "1px solid rgba(255, 255, 255, 0.1)",
}}
>
{/* Header Section */}
<div tw="flex items-start p-8 items-center">
<div tw="flex text-2xl font-bold text-white tracking-tighter">
Papermark
</div>
</div>

{/* Main Content */}
<div tw="flex flex-col p-8 border-t border-white/20 h-[240px] justify-center">
<div tw="flex text-7xl font-bold text-white mb-2">
{minutesSpentOnDocs}
</div>
<div tw="flex text-2xl font-normal text-white/80">
minutes viewed
</div>
</div>

{/* Year */}
<div tw="flex p-8 text-xl text-white/80 border-t border-white/20 items-center">
{year}
</div>

{/* Footer */}
<div tw="flex p-8 text-sm text-white/60 border-t border-white/20 items-center">
YEAR IN REVIEW
</div>
</div>
</div>
),
{
width: 1200,
height: 630,
headers: {
"Cache-Control": "public, max-age=3600, immutable",
},
fonts: [
{
name: "Inter",
data: inter,
weight: 400,
style: "normal",
},
{
name: "Inter",
data: interBold,
weight: 700,
style: "normal",
},
],
},
);
}
44 changes: 44 additions & 0 deletions app/api/webhooks/callback/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { receiver } from "@/lib/cron";
import { recordWebhookEvent } from "@/lib/tinybird/publish";
import {
webhookCallbackSchema,
webhookPayloadSchema,
} from "@/lib/zod/schemas/webhooks";

// POST /api/webhooks/callback – listen to webhooks status from QStash
export const POST = async (req: Request) => {
const rawBody = await req.json();

const isValid = await receiver.verify({
signature: req.headers.get("Upstash-Signature") || "",
body: JSON.stringify(rawBody),
});
if (!isValid) {
return new Response("Unauthorized", { status: 401 });
}

const { url, status, body, sourceBody, sourceMessageId } =
webhookCallbackSchema.parse(rawBody);

const request = Buffer.from(sourceBody, "base64").toString("utf-8");
const response = Buffer.from(body, "base64").toString("utf-8");

const { id: eventId, event } = webhookPayloadSchema.parse(
JSON.parse(request),
);

const webhookId = new URL(req.url).searchParams.get("webhookId");

await recordWebhookEvent({
url,
event,
event_id: eventId,
http_status: status,
webhook_id: webhookId || "",
request_body: request,
response_body: response,
message_id: sourceMessageId,
});

return new Response("OK");
};
6 changes: 4 additions & 2 deletions components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,11 @@ export const SidebarComponent = ({ className }: { className?: string }) => {
},
{
name: "Branding",
href: "/settings/branding",
href: "/branding",
icon: PaletteIcon,
current: router.pathname.includes("branding"),
current:
router.pathname.includes("branding") &&
!router.pathname.includes("datarooms"),
active: false,
disabled: false,
},
Expand Down
12 changes: 1 addition & 11 deletions components/billing/upgrade-plan-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@ import { useEffect, useMemo, useState } from "react";
import React from "react";

import { useTeam } from "@/context/team-context";
import { motion } from "framer-motion";
import { CheckIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { Switch } from "@/components/ui/switch";

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";
import { Badge } from "../ui/badge";

export function UpgradePlanModal({
clickedPlan,
trigger,
Expand All @@ -37,17 +31,13 @@ export function UpgradePlanModal({
children?: React.ReactNode;
}) {
const router = useRouter();
const [plan, setPlan] = useState<"Pro" | "Business" | "Data Rooms">(
clickedPlan,
);

const [period, setPeriod] = useState<"yearly" | "monthly">("yearly");
const [selectedPlan, setSelectedPlan] = useState<string | null>(null); // Track the clicked plan
const teamInfo = useTeam();
const { plan: teamPlan, trial, isCustomer, isOldAccount } = usePlan();
const analytics = useAnalytics();

const isTrial = !!trial;

const planFeatures = useMemo(
() => ({
Pro: {
Expand Down
2 changes: 1 addition & 1 deletion components/datarooms/dataroom-items-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import {
useSensor,
useSensors,
} from "@dnd-kit/core";
import { motion } from "framer-motion";
import {
ArchiveXIcon,
FileIcon,
FolderIcon,
FolderInputIcon,
XIcon,
} from "lucide-react";
import { motion } from "motion/react";

import { EmptyDocuments } from "@/components/documents/empty-document";
import FolderCard from "@/components/documents/folder-card";
Expand Down
59 changes: 28 additions & 31 deletions components/datarooms/groups/group-permissions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -453,37 +453,34 @@ export default function ExpandableTable({

// Ensure all parent folders are viewable if the item is being set to viewable
// and downloadable if the item is being set to downloadable
// if (updatedPermissions.view || updatedPermissions.download) {
// parents.forEach((parent) => {
// changes[parent.id] = {
// view: updatedPermissions.view || parent.permissions.view,
// download:
// updatedPermissions.download || parent.permissions.download,
// itemType: parent.itemType,
// };
// });

// } else {
// If turning off view, recalculate parent permissions
[...parents].reverse().forEach((parent) => {
const someSubItemViewable = parent.subItems?.some((subItem) =>
subItem.id === item.id
? updatedPermissions.view
: subItem.permissions.view,
);
const someSubItemDownloadable = parent.subItems?.some((subItem) =>
subItem.id === item.id
? updatedPermissions.download
: subItem.permissions.download,
);

changes[parent.id] = {
view: someSubItemViewable || false,
download: someSubItemDownloadable || false,
itemType: parent.itemType,
};
});
// }
if (updatedPermissions.view) {
parents.forEach((parent) => {
changes[parent.id] = {
view: true, // Always enable view for parent folders
download: parent.permissions.download, // Maintain existing download permission
itemType: parent.itemType,
};
});
} else {
// If turning off view, recalculate parent permissions
[...parents].reverse().forEach((parent) => {
const otherChildren =
parent.subItems?.filter((subItem) => subItem.id !== item.id) ||
[];
const someSubItemViewable = otherChildren.some(
(subItem) => subItem.permissions.view,
);
const someSubItemDownloadable = otherChildren.some(
(subItem) => subItem.permissions.download,
);

changes[parent.id] = {
view: someSubItemViewable,
download: someSubItemDownloadable,
itemType: parent.itemType,
};
});
}

return changes;
};
Expand Down
Loading
Loading