Enhance email composer functionality and UI improvements. Updated draft handling to clean email addresses and format message content. Implemented auto-save feature for drafts and improved state management in sidebar components. Cleaned up unused imports and adjusted styling for better consistency.

This commit is contained in:
Aj Wazzan
2025-04-30 15:35:19 -07:00
parent 678a074a61
commit e1deecc95c
6 changed files with 935 additions and 42 deletions

View File

@@ -112,8 +112,22 @@ export function EmailComposer({
useEffect(() => {
if (draft) {
if (draft.to) form.setValue('to', draft.to);
if (draft.content) form.setValue('message', draft.content);
if (draft.to)
form.setValue(
'to',
draft.to.map((email) => email.replace(/[<>]/g, '')),
);
if (draft.content) {
editor.commands.setContent({
type: 'doc',
content: draft.content.split(/\r?\n/).map((line) => {
return {
type: 'paragraph',
content: line.trim().length === 0 ? [] : [{ type: 'text', text: line }],
};
}),
});
}
if (draft.subject) form.setValue('subject', draft.subject);
}
}, [draft]);
@@ -252,6 +266,7 @@ export function EmailComposer({
initialValue: initialMessage,
isReadOnly: isLoading,
onLengthChange: (length) => {
setHasUnsavedChanges(true);
setMessageLength(length);
},
onModEnter: () => {
@@ -316,21 +331,23 @@ export function EmailComposer({
const handleGenerateReply = async () => {};
const saveDraft = useCallback(async () => {
console.log('trying to save email');
if (!hasUnsavedChanges) return;
if (!toEmails.length || !subjectInput || !messageContent) return;
const saveDraft = async () => {
const values = getValues();
if (!hasUnsavedChanges) return;
const messageText = editor.getText();
console.log(values, messageText);
if (!values.to.length || !values.subject.length || !messageText.length) return;
try {
setIsLoading(true);
const draftData = {
to: values?.to?.join(', '),
cc: values?.cc?.join(', '),
bcc: values?.bcc?.join(', '),
subject: values?.subject,
message: values?.message,
attachments: values?.attachments,
to: values.to.join(', '),
cc: values.cc?.join(', '),
bcc: values.bcc?.join(', '),
subject: values.subject,
message: messageText,
attachments: values.attachments,
id: draftId,
};
@@ -339,21 +356,20 @@ export function EmailComposer({
if (response?.id && response.id !== draftId) {
setDraftId(response.id);
}
setHasUnsavedChanges(false);
// toast.success(`Draft saved successfully: ${response.id}`);
} catch (error) {
console.error('Error saving draft:', error);
toast.error('Failed to save draft');
} finally {
setIsLoading(false);
setHasUnsavedChanges(false);
}
}, [toEmails, subjectInput, messageContent, attachments, draftId, hasUnsavedChanges]);
};
useEffect(() => {
if (!hasUnsavedChanges) return;
const autoSaveTimer = setTimeout(() => {
console.log('timeout set');
saveDraft();
}, 3000);

View File

@@ -76,7 +76,9 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
{...props}
className={`flex select-none flex-col items-center ${state === 'collapsed' ? '' : ''}`}
>
<div className={`relative z-20 flex w-full flex-col ${state === 'collapsed' ? 'px-0' : 'md:px-2'}`}>
<div
className={`relative z-20 flex w-full flex-col ${state === 'collapsed' ? 'px-0' : 'md:px-2'}`}
>
<SidebarHeader className="flex flex-col gap-2 pt-[18px]">
<NavUser />
<AnimatePresence mode="wait">
@@ -130,13 +132,15 @@ function ComposeButton() {
const [dialogOpen, setDialogOpen] = useQueryState('isComposeOpen');
const [, setDraftId] = useQueryState('draftId');
const [, setTo] = useQueryState('to');
const [, setActiveReplyId] = useQueryState('activeReplyId');
const [, setMode] = useQueryState('mode');
const handleOpenChange = (open: boolean) => {
setDialogOpen(open ? 'true' : null);
if (!open) {
setDraftId(null);
setTo(null);
}
setDraftId(null);
setTo(null);
setActiveReplyId(null);
setMode(null);
};
return (
<Dialog open={!!dialogOpen} onOpenChange={handleOpenChange}>
@@ -156,7 +160,7 @@ function ComposeButton() {
</button>
</DialogTrigger>
<DialogContent className="h-screen w-screen max-w-none border-none bg-[#FAFAFA] dark:bg-[#141414] p-0 shadow-none">
<DialogContent className="h-screen w-screen max-w-none border-none bg-[#FAFAFA] p-0 shadow-none dark:bg-[#141414]">
<CreateEmail />
</DialogContent>
</Dialog>

View File

@@ -30,6 +30,7 @@ import { useSearchValue } from '@/hooks/use-search-value';
import { clearBulkSelectionAtom } from '../mail/use-mail';
import { Label as UILabel } from '@/components/ui/label';
import { type MessageKey } from '@/config/navigation';
import { Command, SettingsIcon } from 'lucide-react';
import { type NavItem } from '@/config/navigation';
import { createLabel } from '@/hooks/use-labels';
import { Button } from '@/components/ui/button';
@@ -39,7 +40,7 @@ import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { GoldenTicketModal } from '../golden';
import { useStats } from '@/hooks/use-stats';
import { Command, SettingsIcon } from 'lucide-react';
import { CurvedArrow } from '../icons/icons';
import { useTranslations } from 'next-intl';
import { useRef, useCallback } from 'react';
import { BASE_URL } from '@/lib/constants';
@@ -51,7 +52,6 @@ import { useAtom } from 'jotai';
import { toast } from 'sonner';
import * as React from 'react';
import Link from 'next/link';
import { CurvedArrow } from '../icons/icons';
interface IconProps extends React.SVGProps<SVGSVGElement> {
ref?: React.Ref<SVGSVGElement>;
@@ -95,7 +95,7 @@ export function NavMain({ items }: NavMainProps) {
const formColor = form.watch('color');
const { labels } = useLabels();
const { labels, mutate } = useLabels();
const { state } = useSidebar();
// Check if these are bottom navigation items by looking at the first section's title
@@ -216,6 +216,9 @@ export function NavMain({ items }: NavMainProps) {
loading: 'Creating label...',
success: 'Label created successfully',
error: 'Failed to create label',
finally: () => {
mutate();
},
});
} catch (error) {
console.error('Error creating label:', error);
@@ -287,12 +290,16 @@ export function NavMain({ items }: NavMainProps) {
<DialogTitle>Create New Label</DialogTitle>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4" onKeyDown={(e) => {
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
form.handleSubmit(onSubmit)();
}
}}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-4"
onKeyDown={(e) => {
if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
e.preventDefault();
form.handleSubmit(onSubmit)();
}
}}
>
<div className="space-y-4 py-4">
<div className="space-y-2">
<FormField
@@ -315,27 +322,54 @@ export function NavMain({ items }: NavMainProps) {
<div className="grid grid-cols-7 gap-4">
{[
// Row 1 - Grayscale
'#000000', '#434343', '#666666', '#999999', '#cccccc', '#ffffff',
'#000000',
'#434343',
'#666666',
'#999999',
'#cccccc',
'#ffffff',
// Row 2 - Warm colors
'#fb4c2f', '#ffad47', '#fad165', '#ff7537', '#cc3a21', '#8a1c0a',
'#fb4c2f',
'#ffad47',
'#fad165',
'#ff7537',
'#cc3a21',
'#8a1c0a',
// Row 3 - Cool colors
'#16a766', '#43d692', '#4a86e8', '#285bac', '#3c78d8', '#0d3472',
'#16a766',
'#43d692',
'#4a86e8',
'#285bac',
'#3c78d8',
'#0d3472',
// Row 4 - Purple tones
'#a479e2', '#b99aff', '#653e9b', '#3d188e', '#f691b3', '#994a64',
'#a479e2',
'#b99aff',
'#653e9b',
'#3d188e',
'#f691b3',
'#994a64',
// Row 5 - Pastels
'#f6c5be', '#ffe6c7', '#c6f3de', '#c9daf8',
'#f6c5be',
'#ffe6c7',
'#c6f3de',
'#c9daf8',
].map((color) => (
<button
key={color}
type="button"
className={`h-10 w-10 rounded-[4px] border-[0.5px] border-white/10 ${
formColor?.backgroundColor === color ? 'ring-2 ring-blue-500' : ''
formColor?.backgroundColor === color
? 'ring-2 ring-blue-500'
: ''
}`}
style={{ backgroundColor: color }}
onClick={() => form.setValue('color', {
backgroundColor: color,
textColor: '#ffffff'
})}
onClick={() =>
form.setValue('color', {
backgroundColor: color,
textColor: '#ffffff',
})
}
/>
))}
</div>
@@ -353,7 +387,7 @@ export function NavMain({ items }: NavMainProps) {
</Button>
<Button className="h-8" type="submit">
Create Label
<div className="flex h-5 items-center justify-center gap- rounded-sm bg-white/10 px-1 dark:bg-black/10">
<div className="gap- flex h-5 items-center justify-center rounded-sm bg-white/10 px-1 dark:bg-black/10">
<Command className="h-2 w-2 text-white dark:text-[#929292]" />
<CurvedArrow className="mt-1.5 h-3 w-3 fill-white dark:fill-[#929292]" />
</div>

View File

@@ -0,0 +1,10 @@
CREATE TABLE "mail0_writing_style_matrix" (
"connectionId" text NOT NULL,
"numMessages" integer NOT NULL,
"style" jsonb NOT NULL,
"updatedAt" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "mail0_writing_style_matrix_connectionId_pk" PRIMARY KEY("connectionId")
);
--> statement-breakpoint
ALTER TABLE "mail0_user_settings" ALTER COLUMN "settings" SET DEFAULT '{"language":"en","timezone":"UTC","dynamicContent":false,"externalImages":true,"customPrompt":"","trustedSenders":[],"isOnboarded":false,"colorTheme":"system"}'::jsonb;--> statement-breakpoint
ALTER TABLE "mail0_writing_style_matrix" ADD CONSTRAINT "mail0_writing_style_matrix_connectionId_mail0_connection_id_fk" FOREIGN KEY ("connectionId") REFERENCES "public"."mail0_connection"("id") ON DELETE no action ON UPDATE no action;

View File

@@ -0,0 +1,822 @@
{
"id": "813a611e-fc31-496c-bbc8-fa9bf294be62",
"prevId": "48978eb5-c4ac-4240-b3e1-d407666cb354",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.mail0_account": {
"name": "mail0_account",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"account_id": {
"name": "account_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token_expires_at": {
"name": "access_token_expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"refresh_token_expires_at": {
"name": "refresh_token_expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"mail0_account_user_id_mail0_user_id_fk": {
"name": "mail0_account_user_id_mail0_user_id_fk",
"tableFrom": "mail0_account",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_connection": {
"name": "mail0_connection",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"picture": {
"name": "picture",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider_id": {
"name": "provider_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"mail0_connection_user_id_mail0_user_id_fk": {
"name": "mail0_connection_user_id_mail0_user_id_fk",
"tableFrom": "mail0_connection",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"mail0_connection_user_id_email_unique": {
"name": "mail0_connection_user_id_email_unique",
"nullsNotDistinct": false,
"columns": [
"user_id",
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_early_access": {
"name": "mail0_early_access",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"is_early_access": {
"name": "is_early_access",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"has_used_ticket": {
"name": "has_used_ticket",
"type": "text",
"primaryKey": false,
"notNull": false,
"default": "''"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"mail0_early_access_email_unique": {
"name": "mail0_early_access_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_note": {
"name": "mail0_note",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"thread_id": {
"name": "thread_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": true
},
"color": {
"name": "color",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'default'"
},
"is_pinned": {
"name": "is_pinned",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"order": {
"name": "order",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"mail0_note_user_id_mail0_user_id_fk": {
"name": "mail0_note_user_id_mail0_user_id_fk",
"tableFrom": "mail0_note",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_session": {
"name": "mail0_session",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"ip_address": {
"name": "ip_address",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_agent": {
"name": "user_agent",
"type": "text",
"primaryKey": false,
"notNull": false
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"mail0_session_user_id_mail0_user_id_fk": {
"name": "mail0_session_user_id_mail0_user_id_fk",
"tableFrom": "mail0_session",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"mail0_session_token_unique": {
"name": "mail0_session_token_unique",
"nullsNotDistinct": false,
"columns": [
"token"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_summary": {
"name": "mail0_summary",
"schema": "",
"columns": {
"message_id": {
"name": "message_id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"connection_id": {
"name": "connection_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"saved": {
"name": "saved",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"tags": {
"name": "tags",
"type": "text",
"primaryKey": false,
"notNull": false
},
"suggested_reply": {
"name": "suggested_reply",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_user": {
"name": "mail0_user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"email_verified": {
"name": "email_verified",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"default_connection_id": {
"name": "default_connection_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"custom_prompt": {
"name": "custom_prompt",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"mail0_user_email_unique": {
"name": "mail0_user_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_user_hotkeys": {
"name": "mail0_user_hotkeys",
"schema": "",
"columns": {
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"shortcuts": {
"name": "shortcuts",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"mail0_user_hotkeys_user_id_mail0_user_id_fk": {
"name": "mail0_user_hotkeys_user_id_mail0_user_id_fk",
"tableFrom": "mail0_user_hotkeys",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_user_settings": {
"name": "mail0_user_settings",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"settings": {
"name": "settings",
"type": "jsonb",
"primaryKey": false,
"notNull": true,
"default": "'{\"language\":\"en\",\"timezone\":\"UTC\",\"dynamicContent\":false,\"externalImages\":true,\"customPrompt\":\"\",\"trustedSenders\":[],\"isOnboarded\":false,\"colorTheme\":\"system\"}'::jsonb"
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"mail0_user_settings_user_id_mail0_user_id_fk": {
"name": "mail0_user_settings_user_id_mail0_user_id_fk",
"tableFrom": "mail0_user_settings",
"tableTo": "mail0_user",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"mail0_user_settings_user_id_unique": {
"name": "mail0_user_settings_user_id_unique",
"nullsNotDistinct": false,
"columns": [
"user_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_verification": {
"name": "mail0_verification",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"updated_at": {
"name": "updated_at",
"type": "timestamp",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.mail0_writing_style_matrix": {
"name": "mail0_writing_style_matrix",
"schema": "",
"columns": {
"connectionId": {
"name": "connectionId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"numMessages": {
"name": "numMessages",
"type": "integer",
"primaryKey": false,
"notNull": true
},
"style": {
"name": "style",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"mail0_writing_style_matrix_connectionId_mail0_connection_id_fk": {
"name": "mail0_writing_style_matrix_connectionId_mail0_connection_id_fk",
"tableFrom": "mail0_writing_style_matrix",
"tableTo": "mail0_connection",
"columnsFrom": [
"connectionId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"mail0_writing_style_matrix_connectionId_pk": {
"name": "mail0_writing_style_matrix_connectionId_pk",
"columns": [
"connectionId"
]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -162,6 +162,13 @@
"when": 1744482381255,
"tag": "0022_round_violations",
"breakpoints": true
},
{
"idx": 23,
"version": "7",
"when": 1746049703463,
"tag": "0023_narrow_maria_hill",
"breakpoints": true
}
]
}