Merge branch 'main' into feat/separate-document-page

This commit is contained in:
Lucas Smith
2024-02-22 22:54:15 +11:00
committed by GitHub
16 changed files with 639 additions and 591 deletions

View File

@@ -166,6 +166,7 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
</div> </div>
</DropdownMenuLabel> </DropdownMenuLabel>
<div className="custom-scrollbar max-h-[40vh] overflow-auto">
{teams.map((team) => ( {teams.map((team) => (
<DropdownMenuItem asChild key={team.id}> <DropdownMenuItem asChild key={team.id}>
<Link href={formatRedirectUrlOnSwitch(team.url)}> <Link href={formatRedirectUrlOnSwitch(team.url)}>
@@ -182,6 +183,7 @@ export const MenuSwitcher = ({ user, teams: initialTeamsData }: MenuSwitcherProp
</Link> </Link>
</DropdownMenuItem> </DropdownMenuItem>
))} ))}
</div>
</> </>
) : ( ) : (
<DropdownMenuItem className="text-muted-foreground px-4 py-2" asChild> <DropdownMenuItem className="text-muted-foreground px-4 py-2" asChild>

View File

@@ -16,9 +16,8 @@ import { prisma } from '@documenso/prisma';
import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/client'; import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/client';
import type { Prisma } from '@documenso/prisma/client'; import type { Prisma } from '@documenso/prisma/client';
import { getDocumentWhereInput } from './get-document-by-id';
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
import { getDocumentWhereInput } from './get-document-by-id';
export type ResendDocumentOptions = { export type ResendDocumentOptions = {
documentId: number; documentId: number;
@@ -111,7 +110,8 @@ export const resendDocument = async ({
const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role]; const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role];
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
await mailer.sendMail({ await mailer.sendMail({
to: { to: {
address: email, address: email,
@@ -144,7 +144,9 @@ export const resendDocument = async ({
}, },
}), }),
}); });
}); },
{ timeout: 30_000 },
);
}), }),
); );
}; };

View File

@@ -49,7 +49,8 @@ export const sendCompletedEmail = async ({ documentId, requestMetadata }: SendDo
downloadLink: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${token}/complete`, downloadLink: `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${token}/complete`,
}); });
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
await mailer.sendMail({ await mailer.sendMail({
to: { to: {
address: email, address: email,
@@ -86,7 +87,9 @@ export const sendCompletedEmail = async ({ documentId, requestMetadata }: SendDo
}, },
}), }),
}); });
}); },
{ timeout: 30_000 },
);
}), }),
); );
}; };

View File

@@ -108,7 +108,8 @@ export const sendDocument = async ({
const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role]; const { actionVerb } = RECIPIENT_ROLES_DESCRIPTION[recipient.role];
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
await mailer.sendMail({ await mailer.sendMail({
to: { to: {
address: email, address: email,
@@ -150,7 +151,9 @@ export const sendDocument = async ({
}, },
}), }),
}); });
}); },
{ timeout: 30_000 },
);
}), }),
); );

View File

@@ -24,8 +24,7 @@ export const updateTitle = async ({
}, },
}); });
return await prisma.$transaction(async (tx) => { const document = await prisma.document.findFirstOrThrow({
const document = await tx.document.findFirstOrThrow({
where: { where: {
id: documentId, id: documentId,
OR: [ OR: [
@@ -49,9 +48,14 @@ export const updateTitle = async ({
return document; return document;
} }
return await prisma.$transaction(async (tx) => {
// Instead of doing everything in a transaction we can use our knowledge
// of the current document title to ensure we aren't performing a conflicting
// update.
const updatedDocument = await tx.document.update({ const updatedDocument = await tx.document.update({
where: { where: {
id: documentId, id: documentId,
title: document.title,
}, },
data: { data: {
title, title,

View File

@@ -9,7 +9,8 @@ export type AcceptTeamInvitationOptions = {
}; };
export const acceptTeamInvitation = async ({ userId, teamId }: AcceptTeamInvitationOptions) => { export const acceptTeamInvitation = async ({ userId, teamId }: AcceptTeamInvitationOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const user = await tx.user.findFirstOrThrow({ const user = await tx.user.findFirstOrThrow({
where: { where: {
id: userId, id: userId,
@@ -59,5 +60,7 @@ export const acceptTeamInvitation = async ({ userId, teamId }: AcceptTeamInvitat
quantity: numberOfSeats, quantity: numberOfSeats,
}); });
} }
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -28,7 +28,8 @@ export const createTeamEmailVerification = async ({
data, data,
}: CreateTeamEmailVerificationOptions) => { }: CreateTeamEmailVerificationOptions) => {
try { try {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findFirstOrThrow({ const team = await tx.team.findFirstOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -77,7 +78,9 @@ export const createTeamEmailVerification = async ({
}); });
await sendTeamEmailVerificationEmail(data.email, token, team.name, team.url); await sendTeamEmailVerificationEmail(data.email, token, team.name, team.url);
}); },
{ timeout: 30_000 },
);
} catch (err) { } catch (err) {
console.error(err); console.error(err);

View File

@@ -27,7 +27,8 @@ export const deleteTeamMembers = async ({
teamId, teamId,
teamMemberIds, teamMemberIds,
}: DeleteTeamMembersOptions) => { }: DeleteTeamMembersOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
// Find the team and validate that the user is allowed to remove members. // Find the team and validate that the user is allowed to remove members.
const team = await tx.team.findFirstOrThrow({ const team = await tx.team.findFirstOrThrow({
where: { where: {
@@ -54,7 +55,9 @@ export const deleteTeamMembers = async ({
}); });
const currentTeamMember = team.members.find((member) => member.userId === userId); const currentTeamMember = team.members.find((member) => member.userId === userId);
const teamMembersToRemove = team.members.filter((member) => teamMemberIds.includes(member.id)); const teamMembersToRemove = team.members.filter((member) =>
teamMemberIds.includes(member.id),
);
if (!currentTeamMember) { if (!currentTeamMember) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team member record does not exist'); throw new AppError(AppErrorCode.NOT_FOUND, 'Team member record does not exist');
@@ -98,5 +101,7 @@ export const deleteTeamMembers = async ({
quantity: numberOfSeats, quantity: numberOfSeats,
}); });
} }
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -9,7 +9,8 @@ export type DeleteTeamOptions = {
}; };
export const deleteTeam = async ({ userId, teamId }: DeleteTeamOptions) => { export const deleteTeam = async ({ userId, teamId }: DeleteTeamOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findFirstOrThrow({ const team = await tx.team.findFirstOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -38,5 +39,7 @@ export const deleteTeam = async ({ userId, teamId }: DeleteTeamOptions) => {
ownerUserId: userId, ownerUserId: userId,
}, },
}); });
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -15,7 +15,8 @@ export type LeaveTeamOptions = {
}; };
export const leaveTeam = async ({ userId, teamId }: LeaveTeamOptions) => { export const leaveTeam = async ({ userId, teamId }: LeaveTeamOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findFirstOrThrow({ const team = await tx.team.findFirstOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -55,5 +56,7 @@ export const leaveTeam = async ({ userId, teamId }: LeaveTeamOptions) => {
quantity: numberOfSeats, quantity: numberOfSeats,
}); });
} }
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -44,7 +44,8 @@ export const requestTeamOwnershipTransfer = async ({
// Todo: Clear payment methods disabled for now. // Todo: Clear payment methods disabled for now.
const clearPaymentMethods = false; const clearPaymentMethods = false;
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findFirstOrThrow({ const team = await tx.team.findFirstOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -102,5 +103,7 @@ export const requestTeamOwnershipTransfer = async ({
html: render(template), html: render(template),
text: render(template, { plainText: true }), text: render(template, { plainText: true }),
}); });
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -17,7 +17,8 @@ export const resendTeamEmailVerification = async ({
userId, userId,
teamId, teamId,
}: ResendTeamMemberInvitationOptions) => { }: ResendTeamMemberInvitationOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findUniqueOrThrow({ const team = await tx.team.findUniqueOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -61,5 +62,7 @@ export const resendTeamEmailVerification = async ({
}); });
await sendTeamEmailVerificationEmail(emailVerification.email, token, team.name, team.url); await sendTeamEmailVerificationEmail(emailVerification.email, token, team.name, team.url);
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -35,7 +35,8 @@ export const resendTeamMemberInvitation = async ({
teamId, teamId,
invitationId, invitationId,
}: ResendTeamMemberInvitationOptions) => { }: ResendTeamMemberInvitationOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const team = await tx.team.findUniqueOrThrow({ const team = await tx.team.findUniqueOrThrow({
where: { where: {
id: teamId, id: teamId,
@@ -72,5 +73,7 @@ export const resendTeamMemberInvitation = async ({
teamUrl: team.url, teamUrl: team.url,
senderName: userName, senderName: userName,
}); });
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -11,7 +11,8 @@ export type TransferTeamOwnershipOptions = {
}; };
export const transferTeamOwnership = async ({ token }: TransferTeamOwnershipOptions) => { export const transferTeamOwnership = async ({ token }: TransferTeamOwnershipOptions) => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(
async (tx) => {
const teamTransferVerification = await tx.teamTransferVerification.findFirstOrThrow({ const teamTransferVerification = await tx.teamTransferVerification.findFirstOrThrow({
where: { where: {
token, token,
@@ -84,5 +85,7 @@ export const transferTeamOwnership = async ({ token }: TransferTeamOwnershipOpti
}, },
}, },
}); });
}); },
{ timeout: 30_000 },
);
}; };

View File

@@ -53,7 +53,8 @@ export const createUser = async ({ name, email, password, signature }: CreateUse
await Promise.allSettled( await Promise.allSettled(
acceptedTeamInvites.map(async (invite) => acceptedTeamInvites.map(async (invite) =>
prisma prisma
.$transaction(async (tx) => { .$transaction(
async (tx) => {
await tx.teamMember.create({ await tx.teamMember.create({
data: { data: {
teamId: invite.teamId, teamId: invite.teamId,
@@ -93,7 +94,9 @@ export const createUser = async ({ name, email, password, signature }: CreateUse
quantity: team.members.length, quantity: team.members.length,
}); });
} }
}) },
{ timeout: 30_000 },
)
.catch(async () => { .catch(async () => {
await prisma.teamMemberInvite.update({ await prisma.teamMemberInvite.update({
where: { where: {

View File

@@ -233,10 +233,8 @@ export const PDFViewer = ({
{Array(numPages) {Array(numPages)
.fill(null) .fill(null)
.map((_, i) => ( .map((_, i) => (
<div <div key={i} className="last:-mb-2">
key={i} <div className="border-border overflow-hidden rounded border will-change-transform">
className="border-border my-8 overflow-hidden rounded border will-change-transform first:mt-0 last:mb-0"
>
<PDFPage <PDFPage
pageNumber={i + 1} pageNumber={i + 1}
width={width} width={width}
@@ -246,6 +244,10 @@ export const PDFViewer = ({
onClick={(e) => onDocumentPageClick(e, i + 1)} onClick={(e) => onDocumentPageClick(e, i + 1)}
/> />
</div> </div>
<p className="text-muted-foreground/80 my-2 text-center text-[11px]">
Page {i + 1} of {numPages}
</p>
</div>
))} ))}
</PDFDocument> </PDFDocument>