diff --git a/apps/web/pages/api/documents/[id]/recipients/index.ts b/apps/web/pages/api/documents/[id]/recipients/index.ts
index a99d69175..439211106 100644
--- a/apps/web/pages/api/documents/[id]/recipients/index.ts
+++ b/apps/web/pages/api/documents/[id]/recipients/index.ts
@@ -21,6 +21,10 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
return;
}
+ if (!body.email) {
+ res.status(400).send("Missing parameter email.");
+ }
+
const document: PrismaDocument = await getDocument(+documentId, req, res);
// todo encapsulate entity ownerships checks
@@ -28,15 +32,23 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
return res.status(401).send("User does not have access to this document.");
}
- await prisma.recipient.create({
- data: {
+ const upsert = await prisma.recipient.upsert({
+ where: {
+ email: body.email,
+ },
+ update: {
+ email: body.email,
+ name: body.name,
+ },
+ create: {
documentId: +documentId,
email: body.email,
+ name: body.name,
token: short.generate().toString(),
},
});
- return res.status(201).end();
+ return res.status(200).end();
}
export default defaultHandler({
diff --git a/apps/web/pages/documents.tsx b/apps/web/pages/documents.tsx
index fdddbf4da..8ff1fd1b0 100644
--- a/apps/web/pages/documents.tsx
+++ b/apps/web/pages/documents.tsx
@@ -8,6 +8,7 @@ import {
EnvelopeIcon,
EyeIcon,
PlusIcon,
+ SunIcon,
TrashIcon,
} from "@heroicons/react/24/outline";
import Link from "next/link";
@@ -135,28 +136,51 @@ const DocumentsPage: NextPageWithLayout = (props: any) => {
{document.Recipient.map((item: any) => (
+ {item.sendStatus === "NOT_SENT" ? (
+
+ {item.name
+ ? item.name + " <" + item.email + ">"
+ : item.email}
+
+ ) : (
+ ""
+ )}
{item.sendStatus === "SENT" &&
- item.readStatus !== "OPENED" &&
- item.signingStatus !== "SIGNED" ? (
+ item.readStatus !== "OPENED" ? (
- {item.email}
+
+ {item.name
+ ? item.name + " <" + item.email + ">"
+ : item.email}
+
) : (
""
)}
- {item.sendStatus === "SENT" &&
- item.readStatus === "OPENED" ? (
+ {item.readStatus === "OPENED" &&
+ item.signingStatus === "NOT_SIGNED" ? (
{" "}
- {item.email}
+
+ {item.name
+ ? item.name + " <" + item.email + ">"
+ : item.email}
+
) : (
""
)}
- {item.sendStatus === "SENT" &&
- item.readStatus === "OPENED" &&
- item.signingStatus === "SIGNED" ? (
+ {item.signingStatus === "SIGNED" ? (
{" "}
{item.email}
diff --git a/apps/web/pages/documents/[id]/recipients.tsx b/apps/web/pages/documents/[id]/recipients.tsx
index b18cd4388..f11868fd7 100644
--- a/apps/web/pages/documents/[id]/recipients.tsx
+++ b/apps/web/pages/documents/[id]/recipients.tsx
@@ -14,6 +14,7 @@ import { getUserFromToken } from "@documenso/lib/server";
import { getDocument } from "@documenso/lib/query";
import { Document as PrismaDocument } from "@prisma/client";
import { Breadcrumb, Button, IconButton } from "@documenso/ui";
+import toast from "react-hot-toast";
const RecipientsPage: NextPageWithLayout = (props: any) => {
const title: string =
@@ -91,7 +92,34 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
htmlFor="name"
className="block text-xs font-medium text-gray-900"
>
- Name
+ Email
+
+ {
+ const updatedSigners = [...signers];
+ updatedSigners[index].email = e.target.value;
+ setSigners(updatedSigners);
+ }}
+ onBlur={() => {
+ item.documentId = props.document.id;
+ upsertRecipient(item);
+ }}
+ onKeyDown={(event: any) => {
+ if (event.key === "Enter") upsertRecipient(item);
+ }}
+ className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 sm:text-sm outline-none bg-inherit"
+ placeholder="john.dorian@loremipsum.com"
+ />
+
+
+
{
updatedSigners[index].name = e.target.value;
setSigners(updatedSigners);
}}
- id="name"
+ onBlur={() => {
+ item.documentId = props.document.id;
+ upsertRecipient(item);
+ }}
+ onKeyDown={(event: any) => {
+ if (event.key === "Enter") upsertRecipient(item);
+ }}
className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 sm:text-sm outline-none bg-inherit"
placeholder="John Dorian"
/>
-
-
- {
- const updatedSigners = [...signers];
- updatedSigners[index].email = e.target.value;
- setSigners(updatedSigners);
- }}
- id="name"
- className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 sm:text-sm outline-none bg-inherit"
- placeholder="john.dorian@loremipsum.com"
- />
-
{
console.log("click");
// todo save to api
}}
- // className="group-hover:text-neon-dark"
+ className="group-hover:text-neon-dark"
>
@@ -167,6 +180,29 @@ const RecipientsPage: NextPageWithLayout = (props: any) => {
);
};
+async function upsertRecipient(recipient: any) {
+ toast.promise(
+ fetch("/api/documents/" + recipient.documentId + "/recipients", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(recipient),
+ }),
+ {
+ loading: "Saving...",
+ success: "Saved.",
+ error: "Could not save :/",
+ },
+ {
+ id: "saving",
+ style: {
+ minWidth: "200px",
+ },
+ }
+ );
+}
+
RecipientsPage.getLayout = function getLayout(page: ReactElement) {
return {page};
};
diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma
index 19936e176..1fa60c27a 100644
--- a/packages/prisma/schema.prisma
+++ b/packages/prisma/schema.prisma
@@ -20,7 +20,8 @@ model Document {
model Recipient {
id Int @id @default(autoincrement())
documentId Int
- email String @db.VarChar(255)
+ email String @unique @db.VarChar(255)
+ name String @default("") @db.VarChar(255)
token String
readStatus ReadStatus @default(NOT_OPENED)
signingStatus SigningStatus @default(NOT_SIGNED)
|