Merge branch 'main' into feat/separate-document-page
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user