Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
106 changes: 0 additions & 106 deletions apps/web/__tests__/ai-example-matches.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { Table, TableBody, TableRow, TableCell } from "@/components/ui/table";
import { Card } from "@/components/ui/card";
import type { RunRulesResult } from "@/utils/ai/choose-rule/run-rules";
import { SearchForm } from "@/components/SearchForm";
import { Badge } from "@/components/Badge";
import type { BatchExecutedRulesResponse } from "@/app/api/user/executed-rules/batch/route";
import {
isAIRule,
Expand Down Expand Up @@ -370,9 +369,6 @@ function ProcessRulesRow({
{result ? (
<>
<div className="flex max-w-xs flex-col justify-center gap-0.5 whitespace-nowrap">
{result.existing && (
<Badge color="yellow">Already processed</Badge>
)}
<ProcessResultDisplay
result={result}
emailAccountId={emailAccountId}
Expand Down
8 changes: 6 additions & 2 deletions apps/web/app/(app)/[emailAccountId]/clean/onboarding/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Card } from "@/components/ui/card";
import { Card, CardTitle } from "@/components/ui/card";
import { IntroStep } from "@/app/(app)/[emailAccountId]/clean/IntroStep";
import { ActionSelectionStep } from "@/app/(app)/[emailAccountId]/clean/ActionSelectionStep";
import { CleanInstructionsStep } from "@/app/(app)/[emailAccountId]/clean/CleanInstructionsStep";
Expand Down Expand Up @@ -35,9 +35,13 @@ export default async function CleanPage(props: {
},
});

if (!emailAccount) {
return <CardTitle>Email account not found</CardTitle>;
}

const emailProvider = await createEmailProvider({
emailAccountId,
provider: emailAccount?.account.provider ?? null,
provider: emailAccount.account.provider,
});
Comment thread
elie222 marked this conversation as resolved.
const { unhandledCount } = await getUnhandledCount(emailProvider);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ function Row({
mutate: () => void;
selected: Map<string, boolean>;
onToggleSelect: (id: string) => void;
markNotColdEmail: (input: { sender: string }) => Promise<any>;
markNotColdEmail: (input: { sender: string }) => Promise<unknown>;
isExecuting: boolean;
}) {
return (
Expand Down
6 changes: 1 addition & 5 deletions apps/web/app/(app)/[emailAccountId]/stats/Stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,7 @@ export function Stats() {

<RuleStatsChart
dateRange={dateRange}
title={
isAccountOwner
? "Your email workload breakdown"
: "Email workload breakdown"
}
title="Assistant processed emails"
/>
</div>

Expand Down
11 changes: 8 additions & 3 deletions apps/web/app/(app)/accounts/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useAction } from "next-safe-action/hooks";
import Link from "next/link";
import { Trash2, ArrowRight } from "lucide-react";
import { Trash2, ArrowRight, BotIcon } from "lucide-react";
Comment thread
elie222 marked this conversation as resolved.
import { ConfirmDialog } from "@/components/ConfirmDialog";
import { LoadingContent } from "@/components/LoadingContent";
import { Button } from "@/components/ui/button";
Expand Down Expand Up @@ -90,8 +90,13 @@ function AccountItem({
</div>
</CardHeader>
<CardContent className="flex justify-end gap-2">
<Button variant="outline" size="sm" Icon={ArrowRight} asChild>
<Link href={prefixPath(emailAccount.id, "/setup")}>View</Link>
<Button variant="outline" size="sm" Icon={BotIcon}>
<Link href={prefixPath(emailAccount.id, "/automation")}>
Assistant
</Link>
</Button>
<Button variant="outline" size="sm" Icon={ArrowRight}>
<Link href={prefixPath(emailAccount.id, "/setup")}>Setup</Link>
</Button>
Comment thread
elie222 marked this conversation as resolved.
{!emailAccount.isPrimary && (
<ConfirmDialog
Expand Down
11 changes: 4 additions & 7 deletions apps/web/app/api/google/watch/all/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { NextResponse } from "next/server";
import { getGmailClientWithRefresh } from "@/utils/gmail/client";
import prisma from "@/utils/prisma";
import { watchEmails } from "@/app/api/google/watch/controller";
import { hasCronSecret, hasPostCronSecret } from "@/utils/cron";
import { withError } from "@/utils/middleware";
import { captureException } from "@/utils/error";
import { hasAiAccess } from "@/utils/premium";
import { createScopedLogger } from "@/utils/logger";
import { createEmailProvider } from "@/utils/email/provider";

const logger = createScopedLogger("api/google/watch/all");

Expand Down Expand Up @@ -99,14 +98,12 @@ async function watchAllEmails() {
continue;
}

const gmail = await getGmailClientWithRefresh({
accessToken: emailAccount.account.access_token,
refreshToken: emailAccount.account.refresh_token,
expiresAt: emailAccount.account.expires_at?.getTime() || null,
const emailProvider = await createEmailProvider({
emailAccountId: emailAccount.id,
provider: "google",
Comment thread
elie222 marked this conversation as resolved.
});

await watchEmails({ emailAccountId: emailAccount.id, gmail });
await emailProvider.watchEmails();
} catch (error) {
if (error instanceof Error) {
const warn = [
Expand Down
30 changes: 9 additions & 21 deletions apps/web/app/api/google/watch/controller.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import type { gmail_v1 } from "@googleapis/gmail";
import prisma from "@/utils/prisma";
import { getGmailClientWithRefresh } from "@/utils/gmail/client";
import { captureException } from "@/utils/error";
import { createScopedLogger } from "@/utils/logger";
import { watchGmail, unwatchGmail } from "@/utils/gmail/watch";
import type { EmailProvider } from "@/utils/email/types";

const logger = createScopedLogger("google/watch");

export async function watchEmails({
emailAccountId,
gmail,
emailProvider,
}: {
emailAccountId: string;
gmail: gmail_v1.Gmail;
emailProvider: EmailProvider;
}) {
logger.info("Watching emails", { emailAccountId });
const res = await watchGmail(gmail);
const res = await emailProvider.watchEmails();

if (res.expiration) {
const expirationDate = new Date(+res.expiration);
if (res?.expirationDate) {
const expirationDate = new Date(res.expirationDate);
await prisma.emailAccount.update({
where: { id: emailAccountId },
data: { watchEmailsExpirationDate: expirationDate },
Expand All @@ -30,24 +28,14 @@ export async function watchEmails({

export async function unwatchEmails({
emailAccountId,
accessToken,
refreshToken,
expiresAt,
emailProvider,
}: {
emailAccountId: string;
accessToken: string | null;
refreshToken: string | null;
expiresAt: number | null;
emailProvider: EmailProvider;
}) {
try {
logger.info("Unwatching emails", { emailAccountId });
const gmail = await getGmailClientWithRefresh({
accessToken,
refreshToken,
expiresAt,
emailAccountId,
});
await unwatchGmail(gmail);
await emailProvider.unwatchEmails();
} catch (error) {
if (error instanceof Error && error.message.includes("invalid_grant")) {
logger.warn("Error unwatching emails, invalid grant", { emailAccountId });
Expand Down
12 changes: 9 additions & 3 deletions apps/web/app/api/google/watch/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { NextResponse } from "next/server";
import { watchEmails } from "./controller";
import { withAuth } from "@/utils/middleware";
import { createScopedLogger } from "@/utils/logger";
import { getGmailClientForEmailId } from "@/utils/account";
import prisma from "@/utils/prisma";
import { createEmailProvider } from "@/utils/email/provider";

export const dynamic = "force-dynamic";

Expand All @@ -27,8 +27,14 @@ export const GET = withAuth(async (request) => {

for (const { id: emailAccountId } of emailAccounts) {
try {
const gmail = await getGmailClientForEmailId({ emailAccountId });
const expirationDate = await watchEmails({ emailAccountId, gmail });
const emailProvider = await createEmailProvider({
emailAccountId,
provider: "google",
Comment thread
elie222 marked this conversation as resolved.
});
const expirationDate = await watchEmails({
emailAccountId,
emailProvider,
});

if (expirationDate) {
results.push({
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/api/resend/digest/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ async function sendEmail({

const emailProvider = await createEmailProvider({
emailAccountId,
provider: emailAccount?.account.provider ?? null,
provider: emailAccount.account.provider,
});
Comment thread
elie222 marked this conversation as resolved.

const digestScheduleData = await getDigestSchedule({ emailAccountId });
Expand Down
2 changes: 2 additions & 0 deletions apps/web/app/api/threads/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const threadsQuery = z.object({
type: z.string().nullish(),
nextPageToken: z.string().nullish(),
labelId: z.string().nullish(), // For Google
labelIds: z.array(z.string()).nullish(), // For Google
excludeLabelNames: z.array(z.string()).nullish(), // For Google
after: z.coerce.date().nullish(),
before: z.coerce.date().nullish(),
isUnread: z.coerce.boolean().nullish(),
Expand Down
Loading
Loading