Skip to content
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
27 changes: 22 additions & 5 deletions apps/web/app/(app)/automation/RuleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ import {
ActionType,
CategoryFilterType,
LogicalOperator,
SystemType,
} from "@prisma/client";
import { ConditionType } from "@/utils/config";
import { ConditionType, type CoreConditionType } from "@/utils/config";
import { createRuleAction, updateRuleAction } from "@/utils/actions/rule";
import {
type CreateRuleBody,
Expand Down Expand Up @@ -195,7 +196,7 @@ export function RuleForm({
ConditionType.STATIC,
ConditionType.CATEGORY,
].find((type) => !usedConditions.has(type)) as
| Exclude<ConditionType, "GROUP">
| CoreConditionType
| undefined;
}, [conditions]);

Expand Down Expand Up @@ -265,8 +266,17 @@ export function RuleForm({
/>
</div>

{showSystemTypeBadge(rule.systemType) && (
<div className="mt-2 flex items-center gap-2">
<Badge color="green">
This rule has special preset logic that may impact your conditions
</Badge>
</div>
)}

<div className="mt-6 flex items-end justify-between">
<TypographyH3>Conditions</TypographyH3>

<div className="flex items-center gap-1.5">
<DropdownMenu>
<DropdownMenuTrigger asChild>
Expand Down Expand Up @@ -801,9 +811,10 @@ function ReplyTrackerAction() {
return (
<div className="h-full flex items-center justify-center">
<div className="text-center text-sm text-muted-foreground max-w-sm">
Tracks conversations this rule applies to.{" "}
<Badge color="green">{NEEDS_REPLY_LABEL_NAME}</Badge> will be
automatically removed after you reply.
Used for reply tracking (Reply Zero). This action tracks emails this
rule is applied to and removes the{" "}
<Badge color="green">{NEEDS_REPLY_LABEL_NAME}</Badge> label after you
reply to the email.
</div>
</div>
);
Expand Down Expand Up @@ -963,3 +974,9 @@ function ActionField({
</div>
);
}

function showSystemTypeBadge(systemType?: SystemType | null): boolean {
if (systemType === SystemType.TO_REPLY) return true;
if (systemType === SystemType.CALENDAR) return true;
return false;
}
18 changes: 4 additions & 14 deletions apps/web/app/(app)/automation/examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ export function hasExampleParams(rule: {

const commonPrompts = [
"Label urgent emails as 'Urgent'",
"Label newsletters as 'Newsletter' and archive them",
"Label marketing emails as 'Marketing' and archive them",
"Label emails from @mycompany.com addresses as 'Team'",
"Label receipts as 'Receipt' and archive them",
];

const common = `${commonPrompts.map((prompt) => `* ${prompt}`).join(".\n")}.`;
Expand Down Expand Up @@ -53,9 +50,7 @@ const founderPrompt = `* If someone asks to set up a call, draft a reply with my
* Label emails from investors as "Investor".
* Label legal documents as "Legal".
* Label emails about travel as "Travel".
* Label recruitment related emails as "Hiring".
* Label marketing and newsletter emails as "Marketing" and archive them.
* Label receipts as 'Receipt' and archive them.`;
* Label recruitment related emails as "Hiring".`;

export const personas = {
founder: {
Expand All @@ -76,8 +71,7 @@ I've attached my media kit and pricing.
* Label emails about affiliate programs as "Affiliate" and archive them.
* Label collaboration requests as "Collab" and draft a reply asking about their audience size and engagement rates.
* Label brand partnership emails as "Brand Deal" and forward to manager@example.com
* Label media inquiries as "Press" and draft a reply a polite reply.
* Label marketing and newsletter emails as "Marketing" and archive them.`,
* Label media inquiries as "Press" and draft a reply a polite reply.`,
},
investor: {
label: "💰 Investor",
Expand All @@ -94,8 +88,7 @@ I've attached my media kit and pricing.
* Forward emails about industry research reports to research@vc.com
* If someone asks for a warm intro to a portfolio company, draft a reply asking for more context about why they want to connect.
* Label emails about fund administration as "Fund Admin".
* Label emails about speaking at investment conferences as "Speaking Opportunity".
* Label marketing and newsletter emails as "Marketing" and archive them.`,
* Label emails about speaking at investment conferences as "Speaking Opportunity".`,
},
assistant: {
label: "📋 Assistant",
Expand Down Expand Up @@ -197,10 +190,7 @@ I've attached my media kit and pricing.
* Label emails about exam schedules as "Exam".
* Label emails about campus events as "Event" and archive them.
* If someone asks for class notes, draft a reply with our shared Google Drive folder link: https://drive.google.com/drive/u/0/folders/1234567890.
* Label emails about tutoring opportunities as "Tutoring" and draft a reply with that my rate is $70/hour or $40/hour for group tutoring.

* Label newsletters as 'Newsletter' and archive them
* Label marketing emails as 'Marketing' and archive them`,
* Label emails about tutoring opportunities as "Tutoring" and draft a reply with that my rate is $70/hour or $40/hour for group tutoring.`,
},
reachout: {
label: "💬 Reachout",
Expand Down
6 changes: 4 additions & 2 deletions apps/web/app/(app)/automation/onboarding/CategoriesSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ import {
type CreateRulesOnboardingBody,
} from "@/utils/actions/rule.validation";
import { TooltipExplanation } from "@/components/TooltipExplanation";
import { ASSISTANT_ONBOARDING_COOKIE } from "@/utils/cookies";
import { markOnboardingAsCompleted } from "@/utils/cookies";
import {
ASSISTANT_ONBOARDING_COOKIE,
markOnboardingAsCompleted,
} from "@/utils/cookies";

const NEXT_URL = "/automation/onboarding/draft-replies";

Expand Down
26 changes: 15 additions & 11 deletions apps/web/app/(app)/automation/onboarding/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import { Card } from "@/components/ui/card";
import { CategoriesSetup } from "./CategoriesSetup";
import { auth } from "@/app/api/auth/[...nextauth]/auth";
import prisma from "@/utils/prisma";
import { ActionType, ColdEmailSetting, type Prisma } from "@prisma/client";
import {
ActionType,
ColdEmailSetting,
SystemType,
type Prisma,
} from "@prisma/client";
import type { CategoryAction } from "@/utils/actions/rule.validation";
import { RuleName } from "@/utils/rule/consts";

export default async function OnboardingPage() {
const session = await auth();
Expand All @@ -23,7 +27,7 @@ type UserPreferences = Prisma.UserGetPayload<{
select: {
rules: {
select: {
name: true;
systemType: true;
actions: {
select: { type: true };
};
Expand All @@ -39,7 +43,7 @@ async function getUserPreferences(userId: string) {
select: {
rules: {
select: {
name: true,
systemType: true,
actions: {
select: {
type: true,
Expand All @@ -55,11 +59,11 @@ async function getUserPreferences(userId: string) {
return {
toReply: getToReplySetting(user.rules),
coldEmails: getColdEmailSetting(user.coldEmailBlocker),
newsletter: getRuleSetting(RuleName.Newsletter, user.rules),
marketing: getRuleSetting(RuleName.Marketing, user.rules),
calendar: getRuleSetting(RuleName.Calendar, user.rules),
receipt: getRuleSetting(RuleName.Receipt, user.rules),
notification: getRuleSetting(RuleName.Notification, user.rules),
newsletter: getRuleSetting(SystemType.NEWSLETTER, user.rules),
marketing: getRuleSetting(SystemType.MARKETING, user.rules),
calendar: getRuleSetting(SystemType.CALENDAR, user.rules),
receipt: getRuleSetting(SystemType.RECEIPT, user.rules),
notification: getRuleSetting(SystemType.NOTIFICATION, user.rules),
};
}

Expand All @@ -75,10 +79,10 @@ function getToReplySetting(
}

function getRuleSetting(
name: string,
systemType: SystemType,
rules?: UserPreferences["rules"],
): CategoryAction | undefined {
const rule = rules?.find((rule) => rule.name === name);
const rule = rules?.find((rule) => rule.systemType === systemType);
if (!rule) return undefined;

if (rule.actions.some((action) => action.type === ActionType.ARCHIVE))
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/(app)/automation/rule/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { RuleForm } from "@/app/(app)/automation/RuleForm";
import { examples } from "@/app/(app)/automation/create/examples";
import { getEmptyCondition } from "@/utils/condition";
import { ActionType } from "@prisma/client";
import type { ConditionType } from "@/utils/config";
import type { CoreConditionType } from "@/utils/config";

export default async function CreateRulePage(props: {
searchParams: Promise<{
example?: string;
groupId?: string;
type?: Exclude<ConditionType, "GROUP">;
type?: CoreConditionType;
categoryId?: string;
label?: string;
}>;
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/api/user/rules/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import prisma from "@/utils/prisma";

export type RulesResponse = Awaited<ReturnType<typeof getRules>>;

async function getRules(options: { userId: string }) {
async function getRules({ userId }: { userId: string }) {
return await prisma.rule.findMany({
where: { userId: options.userId },
where: { userId },
include: {
actions: true,
group: { select: { name: true } },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Warnings:

- A unique constraint covering the columns `[userId,systemType]` on the table `Rule` will be added. If there are existing duplicate values, this will fail.

*/
-- CreateEnum
CREATE TYPE "SystemType" AS ENUM ('TO_REPLY', 'NEWSLETTER', 'MARKETING', 'CALENDAR', 'RECEIPT', 'NOTIFICATION');

-- AlterTable
ALTER TABLE "Rule" ADD COLUMN "systemType" "SystemType";

-- CreateIndex
CREATE UNIQUE INDEX "Rule_userId_systemType_key" ON "Rule"("userId", "systemType");
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
UPDATE "Rule" SET "systemType" = 'TO_REPLY' WHERE "name" = 'To Reply';
UPDATE "Rule" SET "systemType" = 'NEWSLETTER' WHERE "name" = 'Newsletter';
UPDATE "Rule" SET "systemType" = 'MARKETING' WHERE "name" = 'Marketing';
UPDATE "Rule" SET "systemType" = 'CALENDAR' WHERE "name" = 'Calendar';
UPDATE "Rule" SET "systemType" = 'RECEIPT' WHERE "name" = 'Receipt';
UPDATE "Rule" SET "systemType" = 'NOTIFICATION' WHERE "name" = 'Notification';
13 changes: 13 additions & 0 deletions apps/web/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ model Rule {
categoryFilterType CategoryFilterType?
categoryFilters Category[]

systemType SystemType?

@@unique([name, userId])
@@unique([userId, systemType])
}

model Action {
Expand Down Expand Up @@ -601,3 +604,13 @@ enum CleanAction {
ARCHIVE
MARK_READ
}

enum SystemType {
TO_REPLY
NEWSLETTER
MARKETING
CALENDAR
RECEIPT
NOTIFICATION
// COLD_EMAIL // handled separately. we may unify in the future
}
Loading