mirror of
https://github.com/mfts/papermark.git
synced 2025-12-20 01:03:24 +08:00
feat: add trial onboarding emails
This commit is contained in:
@@ -40,6 +40,9 @@ NEXT_PUBLIC_HANKO_TENANT_ID=add-your-hanko-tenent-id
|
||||
TRIGGER_API_KEY=
|
||||
TRIGGER_API_URL=https://api.trigger.dev
|
||||
NEXT_PUBLIC_TRIGGER_PUBLIC_API_KEY=
|
||||
# Trigger v3
|
||||
TRIGGER_SECRET_KEY=
|
||||
TRIGGER_API_URL=https://api.trigger.dev
|
||||
|
||||
# [[STORAGE]]
|
||||
# Defines the storage transport to use. Available options: vercel (default) | s3
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -55,3 +55,6 @@ lib/emails/marketing
|
||||
|
||||
# vscode configs
|
||||
.vscode
|
||||
|
||||
# trigger.dev
|
||||
.trigger
|
||||
@@ -36,11 +36,10 @@ const Onboarding3Email = () => {
|
||||
<li>Share data rooms with one link</li>
|
||||
<li>Upload unlimited files</li>
|
||||
<li>Create unlimited folders and subfolders</li>
|
||||
<li>Invite unlimited team members</li>
|
||||
<li>
|
||||
Connect your <strong>custom domain 💫</strong>{" "}
|
||||
</li>
|
||||
<li>Create fully branded expereince </li>
|
||||
<li>Create fully branded experience </li>
|
||||
<li>Use advanced link settings</li>
|
||||
<li>Create full whitelabeling</li>
|
||||
<li>Build self-hosted expereince</li>
|
||||
@@ -60,14 +59,14 @@ const Onboarding3Email = () => {
|
||||
<Section className="mb-[32px] mt-[32px] text-center">
|
||||
<Button
|
||||
className="rounded bg-black text-center text-xs font-semibold text-white no-underline"
|
||||
href={`https://app.papermark.io/documents?utm_source=onboarding&utm_medium=email&utm_campaign=20240723&utm_content=upload_documents`}
|
||||
href={`https://app.papermark.io/datarooms?utm_source=dataroom-info&utm_medium=email&utm_campaign=20240723&utm_content=upload_documents`}
|
||||
style={{ padding: "12px 20px" }}
|
||||
>
|
||||
Create new data room
|
||||
</Button>
|
||||
</Section>
|
||||
<Text className="text-sm">
|
||||
If you want to sel-host Papermark, and build fully customizable
|
||||
If you want to self-host Papermark, and build fully customizable
|
||||
experience{" "}
|
||||
<a
|
||||
href="https://cal.com/marcseitz/papermark"
|
||||
@@ -90,7 +89,7 @@ const Onboarding3Email = () => {
|
||||
</a>
|
||||
</Text>
|
||||
<Text className="text-xs">
|
||||
This is a last onboaridng email. If you have any feedback or
|
||||
This is a last onboarding email. If you have any feedback or
|
||||
questions about this email, simply reply to it. I'd love to
|
||||
hear from you!{" "}
|
||||
</Text>
|
||||
|
||||
26
lib/emails/send-dataroom-info.ts
Normal file
26
lib/emails/send-dataroom-info.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import Onboarding5Email from "@/components/emails/onboarding-5";
|
||||
|
||||
import { sendEmail } from "@/lib/resend";
|
||||
|
||||
import { CreateUserEmailProps } from "../types";
|
||||
|
||||
export const sendDataroomInfoEmail = async (params: CreateUserEmailProps) => {
|
||||
const { email } = params.user;
|
||||
|
||||
let emailTemplate;
|
||||
let subject;
|
||||
|
||||
emailTemplate = Onboarding5Email();
|
||||
subject = "Virtual Data Rooms";
|
||||
|
||||
try {
|
||||
await sendEmail({
|
||||
to: email as string,
|
||||
subject,
|
||||
react: emailTemplate,
|
||||
test: process.env.NODE_ENV === "development",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
57
lib/trigger/send-scheduled-email.ts
Normal file
57
lib/trigger/send-scheduled-email.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { logger, task } from "@trigger.dev/sdk/v3";
|
||||
|
||||
import { sendDataroomInfoEmail } from "@/lib/emails/send-dataroom-info";
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export const sendDataroomTrialInfoEmailTask = task({
|
||||
id: "send-dataroom-trial-info-email",
|
||||
retry: { maxAttempts: 3 },
|
||||
run: async (payload: { to: string }) => {
|
||||
await sendDataroomInfoEmail({ user: { email: payload.to, name: "Marc" } });
|
||||
logger.info("Email sent", { to: payload.to });
|
||||
},
|
||||
});
|
||||
|
||||
export const sendDataroomTrialExpiredEmailTask = task({
|
||||
id: "send-dataroom-trial-expired-email",
|
||||
retry: { maxAttempts: 3 },
|
||||
run: async (payload: { to: string; teamId: string }) => {
|
||||
const team = await prisma.team.findUnique({
|
||||
where: {
|
||||
id: payload.teamId,
|
||||
},
|
||||
select: {
|
||||
plan: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!team) {
|
||||
logger.error("Team not found", { teamId: payload.teamId });
|
||||
return;
|
||||
}
|
||||
|
||||
if (team.plan.includes("drtrial")) {
|
||||
await sendDataroomInfoEmail({
|
||||
user: { email: payload.to, name: "Marc" },
|
||||
});
|
||||
logger.info("Email sent", { to: payload.to, teamId: payload.teamId });
|
||||
|
||||
await prisma.team.update({
|
||||
where: {
|
||||
id: payload.teamId,
|
||||
},
|
||||
data: {
|
||||
plan: team.plan.replace("+drtrial", ""),
|
||||
},
|
||||
});
|
||||
logger.info("Trial removed", { teamId: payload.teamId });
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Team upgraded - no further action", {
|
||||
teamId: payload.teamId,
|
||||
plan: team.plan,
|
||||
});
|
||||
return;
|
||||
},
|
||||
});
|
||||
1769
package-lock.json
generated
1769
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
||||
"@next-auth/prisma-adapter": "^1.0.7",
|
||||
"@pdf-lib/fontkit": "^1.1.1",
|
||||
"@prisma/client": "^5.19.1",
|
||||
"@prisma/instrumentation": "^5.19.1",
|
||||
"@radix-ui/react-accordion": "^1.2.0",
|
||||
"@radix-ui/react-avatar": "^1.1.0",
|
||||
"@radix-ui/react-checkbox": "^1.1.1",
|
||||
@@ -54,9 +55,9 @@
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@teamhanko/passkeys-next-auth-provider": "^0.2.7",
|
||||
"@tremor/react": "^3.18.0",
|
||||
"@trigger.dev/nextjs": "^2.3.19",
|
||||
"@trigger.dev/react": "^2.3.19",
|
||||
"@trigger.dev/sdk": "^2.3.19",
|
||||
"@trigger.dev/nextjs": "3.0.0-beta.56",
|
||||
"@trigger.dev/react": "3.0.0-beta.56",
|
||||
"@trigger.dev/sdk": "3.0.0-beta.56",
|
||||
"@tus/s3-store": "^1.5.0",
|
||||
"@tus/server": "^1.7.0",
|
||||
"@tus/utils": "^0.3.0",
|
||||
|
||||
@@ -7,6 +7,11 @@ import { getServerSession } from "next-auth/next";
|
||||
import { sendDataroomTrialWelcome } from "@/lib/emails/send-dataroom-trial";
|
||||
import { newId } from "@/lib/id-helper";
|
||||
import prisma from "@/lib/prisma";
|
||||
import {
|
||||
sendDataroomTrialExpiredEmailTask,
|
||||
sendDataroomTrialInfoEmailTask,
|
||||
sendScheduledEmailTask,
|
||||
} from "@/lib/trigger/send-scheduled-email";
|
||||
import { CustomUser } from "@/lib/types";
|
||||
import { log } from "@/lib/utils";
|
||||
|
||||
@@ -96,6 +101,18 @@ export default async function handle(
|
||||
};
|
||||
|
||||
waitUntil(sendDataroomTrialWelcome({ fullName, to: email! }));
|
||||
waitUntil(
|
||||
sendDataroomTrialInfoEmailTask.trigger(
|
||||
{ to: email! },
|
||||
{ delay: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000) },
|
||||
),
|
||||
);
|
||||
waitUntil(
|
||||
sendDataroomTrialExpiredEmailTask.trigger(
|
||||
{ to: email!, teamId: teamId },
|
||||
{ delay: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) },
|
||||
),
|
||||
);
|
||||
|
||||
res.status(201).json(dataroomWithCount);
|
||||
} catch (error) {
|
||||
|
||||
22
trigger.config.ts
Normal file
22
trigger.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { PrismaInstrumentation } from "@prisma/instrumentation";
|
||||
import type { TriggerConfig } from "@trigger.dev/sdk/v3";
|
||||
|
||||
export const config: TriggerConfig = {
|
||||
project: "proj_plmsfqvqunboixacjjus",
|
||||
triggerDirectories: ["./lib/trigger"],
|
||||
instrumentations: [new PrismaInstrumentation()],
|
||||
retries: {
|
||||
enabledInDev: false,
|
||||
default: {
|
||||
maxAttempts: 3,
|
||||
minTimeoutInMs: 1000,
|
||||
maxTimeoutInMs: 10000,
|
||||
factor: 2,
|
||||
randomize: true,
|
||||
},
|
||||
},
|
||||
dependenciesToBundle: ["nanoid"],
|
||||
additionalFiles: ["./prisma/schema.prisma"],
|
||||
additionalPackages: ["prisma@5.11.0"],
|
||||
postInstall: "npm exec --package prisma -- prisma generate",
|
||||
};
|
||||
@@ -24,6 +24,12 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts",
|
||||
"trigger.config.ts"
|
||||
],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user