mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 00:32:43 +10:00
document status, dashboard
This commit is contained in:
@ -39,18 +39,14 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
// todo handle sending to single recipient even though more exist
|
// todo handle sending to single recipient even though more exist
|
||||||
|
|
||||||
const recipients = prisma.recipient.findMany({
|
const recipients = prisma.recipient.findMany({
|
||||||
where: { documentId: +documentId },
|
where: {
|
||||||
|
documentId: +documentId,
|
||||||
|
sendStatus: SendStatus.NOT_SENT,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
(await recipients).forEach(async (recipient) => {
|
(await recipients).forEach(async (recipient) => {
|
||||||
await sendSigningRequestMail(recipient, document);
|
await sendSigningRequestMail(recipient, document);
|
||||||
await prisma.recipient.updateMany({
|
|
||||||
where: {
|
|
||||||
id: recipient.id,
|
|
||||||
sendStatus: SendStatus.NOT_SENT,
|
|
||||||
},
|
|
||||||
data: { sendStatus: SendStatus.SENT },
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).end();
|
return res.status(200).end();
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import {
|
|||||||
} from "@documenso/lib/server";
|
} from "@documenso/lib/server";
|
||||||
import prisma from "@documenso/prisma";
|
import prisma from "@documenso/prisma";
|
||||||
import { NextApiRequest, NextApiResponse } from "next";
|
import { NextApiRequest, NextApiResponse } from "next";
|
||||||
import { SigningStatus } from "@prisma/client";
|
import { SigningStatus, DocumentStatus } from "@prisma/client";
|
||||||
|
|
||||||
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
const existingUser = await getUserFromToken(req, res);
|
const existingUser = await getUserFromToken(req, res);
|
||||||
@ -33,7 +33,24 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
|
|
||||||
if (!document) res.status(404).end(`No document found.`);
|
if (!document) res.status(404).end(`No document found.`);
|
||||||
|
|
||||||
// todo sign ui
|
// todo sign stuff
|
||||||
|
|
||||||
|
const unsignedRecipients = await prisma.recipient.findMany({
|
||||||
|
where: {
|
||||||
|
signingStatus: SigningStatus.NOT_SIGNED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (unsignedRecipients.length === 0) {
|
||||||
|
await prisma.document.update({
|
||||||
|
where: {
|
||||||
|
id: recipient.documentId,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
status: DocumentStatus.COMPLETED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await prisma.recipient.update({
|
await prisma.recipient.update({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@ -57,6 +57,7 @@ async function getHandler(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
select: {
|
select: {
|
||||||
id: true,
|
id: true,
|
||||||
title: true,
|
title: true,
|
||||||
|
status: true,
|
||||||
Recipient: true,
|
Recipient: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -18,12 +18,20 @@ import Router from "next/router";
|
|||||||
import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib";
|
import { NEXT_PUBLIC_WEBAPP_URL } from "@documenso/lib";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { uploadDocument } from "@documenso/features";
|
import { uploadDocument } from "@documenso/features";
|
||||||
|
import prisma from "@documenso/prisma";
|
||||||
|
import {
|
||||||
|
ReadStatus,
|
||||||
|
SendStatus,
|
||||||
|
SigningStatus,
|
||||||
|
DocumentStatus,
|
||||||
|
} from "@prisma/client";
|
||||||
|
import { getUserFromToken } from "@documenso/lib/server";
|
||||||
|
|
||||||
type FormValues = {
|
type FormValues = {
|
||||||
document: File;
|
document: File;
|
||||||
};
|
};
|
||||||
|
|
||||||
const DashboardPage: NextPageWithLayout = () => {
|
const DashboardPage: NextPageWithLayout = (props: any) => {
|
||||||
const stats = [
|
const stats = [
|
||||||
{
|
{
|
||||||
name: "Draft",
|
name: "Draft",
|
||||||
@ -86,7 +94,7 @@ const DashboardPage: NextPageWithLayout = () => {
|
|||||||
{item.name}
|
{item.name}
|
||||||
</dt>
|
</dt>
|
||||||
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
|
<dd className="mt-1 text-3xl font-semibold tracking-tight text-gray-900">
|
||||||
{item.stat}
|
{getStat(item.name, props)}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
@ -136,4 +144,56 @@ DashboardPage.getLayout = function getLayout(page: ReactElement) {
|
|||||||
return <Layout>{page}</Layout>;
|
return <Layout>{page}</Layout>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getStat(name: string, props: any) {
|
||||||
|
if (name === "Draft") return props.dashboard.drafts;
|
||||||
|
if (name === "Sent") return props.dashboard.sent;
|
||||||
|
if (name === "Viewed") return props.dashboard.viewed;
|
||||||
|
if (name === "Signed") return props.dashboard.signed;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getServerSideProps(context: any) {
|
||||||
|
const user = await getUserFromToken(context.req, context.res);
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
const drafts = await prisma.document.findMany({
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
status: DocumentStatus.DRAFT,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const sent = await prisma.recipient.groupBy({
|
||||||
|
by: ["documentId"],
|
||||||
|
where: {
|
||||||
|
sendStatus: SendStatus.SENT,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const opened = await prisma.recipient.groupBy({
|
||||||
|
by: ["documentId"],
|
||||||
|
where: {
|
||||||
|
readStatus: ReadStatus.OPENED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const completed = await prisma.document.findMany({
|
||||||
|
where: {
|
||||||
|
userId: user.id,
|
||||||
|
status: DocumentStatus.COMPLETED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
dashboard: {
|
||||||
|
drafts: drafts.length,
|
||||||
|
sent: sent.length,
|
||||||
|
viewed: opened.length,
|
||||||
|
signed: completed.length,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default DashboardPage;
|
export default DashboardPage;
|
||||||
|
|||||||
@ -34,6 +34,8 @@ export async function getServerSideProps(context: any) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// todo sign ui
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {},
|
props: {},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export { sendSigningRequestMail } from "./sendSigningRequestMail";
|
export { sendSigningRequest as sendSigningRequestMail } from "./sendSigningRequestMail";
|
||||||
export { sendSignedMail } from "./sendSignedMail";
|
export { sendSignedMail } from "./sendSignedMail";
|
||||||
|
|||||||
@ -1,8 +1,26 @@
|
|||||||
|
import prisma from "@documenso/prisma";
|
||||||
import { sendMail } from "./sendMail";
|
import { sendMail } from "./sendMail";
|
||||||
export const sendSigningRequestMail = async (recipient: any, document: any) => {
|
import { SendStatus, DocumentStatus } from "@prisma/client";
|
||||||
|
|
||||||
|
export const sendSigningRequest = async (recipient: any, document: any) => {
|
||||||
|
// todo errror handling
|
||||||
await sendMail(
|
await sendMail(
|
||||||
recipient.email,
|
recipient.email,
|
||||||
`Please sign ${document.title}`,
|
`Please sign ${document.title}`,
|
||||||
`${document.User.name} has sent you a document to sign. Click <b><a href="${process.env.NEXT_PUBLIC_WEBAPP_URL}/documents/${document.id}/sign">SIGN DOCUMENT</a></b> to sign it now.`
|
`${document.User.name} has sent you a document to sign. Click <b><a href="${process.env.NEXT_PUBLIC_WEBAPP_URL}/documents/${document.id}/sign">SIGN DOCUMENT</a></b> to sign it now.`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await prisma.recipient.update({
|
||||||
|
where: {
|
||||||
|
id: recipient.id,
|
||||||
|
},
|
||||||
|
data: { sendStatus: SendStatus.SENT },
|
||||||
|
});
|
||||||
|
|
||||||
|
await prisma.document.update({
|
||||||
|
where: {
|
||||||
|
id: document.id,
|
||||||
|
},
|
||||||
|
data: { status: DocumentStatus.PENDING },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -12,6 +12,7 @@ model Document {
|
|||||||
userId Int
|
userId Int
|
||||||
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
User User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
title String
|
title String
|
||||||
|
status DocumentStatus @default(DRAFT)
|
||||||
document String
|
document String
|
||||||
Recipient Recipient[]
|
Recipient Recipient[]
|
||||||
}
|
}
|
||||||
@ -85,3 +86,9 @@ enum SigningStatus {
|
|||||||
NOT_SIGNED
|
NOT_SIGNED
|
||||||
SIGNED
|
SIGNED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DocumentStatus {
|
||||||
|
DRAFT
|
||||||
|
PENDING
|
||||||
|
COMPLETED
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user