Compare commits

..

1 Commits

Author SHA1 Message Date
11d9bde8f8 fix: improve sealing speed (#2210) 2025-11-19 14:15:12 +11:00
8 changed files with 164 additions and 257 deletions

View File

@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useLingui } from '@lingui/react'; import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro'; import { Trans } from '@lingui/react/macro';
import type { EnvelopeItem, FieldType } from '@prisma/client'; import type { DocumentData, FieldType } from '@prisma/client';
import { ReadStatus, type Recipient, SendStatus, SigningStatus } from '@prisma/client'; import { ReadStatus, type Recipient, SendStatus, SigningStatus } from '@prisma/client';
import { base64 } from '@scure/base'; import { base64 } from '@scure/base';
import { ChevronsUpDown } from 'lucide-react'; import { ChevronsUpDown } from 'lucide-react';
@ -40,8 +40,7 @@ const DEFAULT_WIDTH_PX = MIN_WIDTH_PX * 2.5;
export type ConfigureFieldsViewProps = { export type ConfigureFieldsViewProps = {
configData: TConfigureEmbedFormSchema; configData: TConfigureEmbedFormSchema;
presignToken?: string | undefined; documentData?: DocumentData;
envelopeItem?: Pick<EnvelopeItem, 'id' | 'envelopeId'>;
defaultValues?: Partial<TConfigureFieldsFormSchema>; defaultValues?: Partial<TConfigureFieldsFormSchema>;
onBack?: (data: TConfigureFieldsFormSchema) => void; onBack?: (data: TConfigureFieldsFormSchema) => void;
onSubmit: (data: TConfigureFieldsFormSchema) => void; onSubmit: (data: TConfigureFieldsFormSchema) => void;
@ -49,8 +48,7 @@ export type ConfigureFieldsViewProps = {
export const ConfigureFieldsView = ({ export const ConfigureFieldsView = ({
configData, configData,
presignToken, documentData,
envelopeItem,
defaultValues, defaultValues,
onBack, onBack,
onSubmit, onSubmit,
@ -84,12 +82,12 @@ export const ConfigureFieldsView = ({
}, []); }, []);
const normalizedDocumentData = useMemo(() => { const normalizedDocumentData = useMemo(() => {
if (envelopeItem) { if (documentData) {
return undefined; return documentData.data;
} }
if (!configData.documentData) { if (!configData.documentData) {
return undefined; return null;
} }
return base64.encode(configData.documentData.data); return base64.encode(configData.documentData.data);
@ -536,55 +534,56 @@ export const ConfigureFieldsView = ({
)} )}
<Form {...form}> <Form {...form}>
{normalizedDocumentData || {normalizedDocumentData && (
(envelopeItem && ( <div>
<div> <PDFViewer
<PDFViewer overrideData={normalizedDocumentData}
presignToken={presignToken} envelopeItem={{
overrideData={normalizedDocumentData} id: '',
envelopeItem={envelopeItem} envelopeId: '',
token={undefined} }}
version="signed" token={undefined}
/> version="signed"
/>
<ElementVisible <ElementVisible
target={`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${highestPageNumber}"]`} target={`${PDF_VIEWER_PAGE_SELECTOR}[data-page-number="${highestPageNumber}"]`}
> >
{localFields.map((field, index) => { {localFields.map((field, index) => {
const recipientIndex = recipients.findIndex( const recipientIndex = recipients.findIndex(
(r) => r.id === field.recipientId, (r) => r.id === field.recipientId,
); );
return ( return (
<FieldItem <FieldItem
key={field.formId} key={field.formId}
field={field} field={field}
minHeight={MIN_HEIGHT_PX} minHeight={MIN_HEIGHT_PX}
minWidth={MIN_WIDTH_PX} minWidth={MIN_WIDTH_PX}
defaultHeight={DEFAULT_HEIGHT_PX} defaultHeight={DEFAULT_HEIGHT_PX}
defaultWidth={DEFAULT_WIDTH_PX} defaultWidth={DEFAULT_WIDTH_PX}
onResize={(node) => onFieldResize(node, index)} onResize={(node) => onFieldResize(node, index)}
onMove={(node) => onFieldMove(node, index)} onMove={(node) => onFieldMove(node, index)}
onRemove={() => remove(index)} onRemove={() => remove(index)}
onDuplicate={() => onFieldCopy(null, { duplicate: true })} onDuplicate={() => onFieldCopy(null, { duplicate: true })}
onDuplicateAllPages={() => onFieldCopy(null, { duplicateAll: true })} onDuplicateAllPages={() => onFieldCopy(null, { duplicateAll: true })}
onFocus={() => setLastActiveField(field)} onFocus={() => setLastActiveField(field)}
onBlur={() => setLastActiveField(null)} onBlur={() => setLastActiveField(null)}
onAdvancedSettings={() => { onAdvancedSettings={() => {
setCurrentField(field); setCurrentField(field);
setShowAdvancedSettings(true); setShowAdvancedSettings(true);
}} }}
recipientIndex={recipientIndex} recipientIndex={recipientIndex}
active={activeFieldId === field.formId} active={activeFieldId === field.formId}
onFieldActivate={() => setActiveFieldId(field.formId)} onFieldActivate={() => setActiveFieldId(field.formId)}
onFieldDeactivate={() => setActiveFieldId(null)} onFieldDeactivate={() => setActiveFieldId(null)}
disabled={selectedRecipient?.id !== field.recipientId} disabled={selectedRecipient?.id !== field.recipientId}
/> />
); );
})} })}
</ElementVisible> </ElementVisible>
</div> </div>
))} )}
</Form> </Form>
</div> </div>
</div> </div>

View File

@ -75,7 +75,6 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
})); }));
return { return {
token,
document: { document: {
...document, ...document,
fields, fields,
@ -87,7 +86,7 @@ export default function EmbeddingAuthoringDocumentEditPage() {
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
const { document, token } = useLoaderData<typeof loader>(); const { document } = useLoaderData<typeof loader>();
const [hasFinishedInit, setHasFinishedInit] = useState(false); const [hasFinishedInit, setHasFinishedInit] = useState(false);
@ -322,8 +321,7 @@ export default function EmbeddingAuthoringDocumentEditPage() {
<ConfigureFieldsView <ConfigureFieldsView
configData={configuration!} configData={configuration!}
presignToken={token} documentData={document.documentData}
envelopeItem={document.envelopeItems[0]}
defaultValues={fields ?? undefined} defaultValues={fields ?? undefined}
onBack={canGoBack ? handleBackToConfig : undefined} onBack={canGoBack ? handleBackToConfig : undefined}
onSubmit={handleConfigureFieldsSubmit} onSubmit={handleConfigureFieldsSubmit}

View File

@ -75,7 +75,6 @@ export const loader = async ({ request, params }: Route.LoaderArgs) => {
})); }));
return { return {
token,
template: { template: {
...template, ...template,
fields, fields,
@ -87,7 +86,7 @@ export default function EmbeddingAuthoringTemplateEditPage() {
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
const { template, token } = useLoaderData<typeof loader>(); const { template } = useLoaderData<typeof loader>();
const [hasFinishedInit, setHasFinishedInit] = useState(false); const [hasFinishedInit, setHasFinishedInit] = useState(false);
@ -322,8 +321,7 @@ export default function EmbeddingAuthoringTemplateEditPage() {
<ConfigureFieldsView <ConfigureFieldsView
configData={configuration!} configData={configuration!}
presignToken={token} documentData={template.templateDocumentData}
envelopeItem={template.envelopeItems[0]}
defaultValues={fields ?? undefined} defaultValues={fields ?? undefined}
onBack={canGoBack ? handleBackToConfig : undefined} onBack={canGoBack ? handleBackToConfig : undefined}
onSubmit={handleConfigureFieldsSubmit} onSubmit={handleConfigureFieldsSubmit}

View File

@ -5,7 +5,6 @@ import { Hono } from 'hono';
import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session'; import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session';
import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app'; import { APP_DOCUMENT_UPLOAD_SIZE_LIMIT } from '@documenso/lib/constants/app';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { verifyEmbeddingPresignToken } from '@documenso/lib/server-only/embedding-presign/verify-embedding-presign-token';
import { getTeamById } from '@documenso/lib/server-only/team/get-team'; import { getTeamById } from '@documenso/lib/server-only/team/get-team';
import { putNormalizedPdfFileServerSide } from '@documenso/lib/universal/upload/put-file.server'; import { putNormalizedPdfFileServerSide } from '@documenso/lib/universal/upload/put-file.server';
import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions'; import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions';
@ -17,7 +16,6 @@ import {
type TGetPresignedPostUrlResponse, type TGetPresignedPostUrlResponse,
ZGetEnvelopeItemFileDownloadRequestParamsSchema, ZGetEnvelopeItemFileDownloadRequestParamsSchema,
ZGetEnvelopeItemFileRequestParamsSchema, ZGetEnvelopeItemFileRequestParamsSchema,
ZGetEnvelopeItemFileRequestQuerySchema,
ZGetEnvelopeItemFileTokenDownloadRequestParamsSchema, ZGetEnvelopeItemFileTokenDownloadRequestParamsSchema,
ZGetEnvelopeItemFileTokenRequestParamsSchema, ZGetEnvelopeItemFileTokenRequestParamsSchema,
ZGetPresignedPostUrlRequestSchema, ZGetPresignedPostUrlRequestSchema,
@ -70,24 +68,12 @@ export const filesRoute = new Hono<HonoEnv>()
.get( .get(
'/envelope/:envelopeId/envelopeItem/:envelopeItemId', '/envelope/:envelopeId/envelopeItem/:envelopeItemId',
sValidator('param', ZGetEnvelopeItemFileRequestParamsSchema), sValidator('param', ZGetEnvelopeItemFileRequestParamsSchema),
sValidator('query', ZGetEnvelopeItemFileRequestQuerySchema),
async (c) => { async (c) => {
const { envelopeId, envelopeItemId } = c.req.valid('param'); const { envelopeId, envelopeItemId } = c.req.valid('param');
const { token } = c.req.query();
const session = await getOptionalSession(c); const session = await getOptionalSession(c);
let userId = session.user?.id; if (!session.user) {
if (token) {
const presignToken = await verifyEmbeddingPresignToken({
token,
}).catch(() => undefined);
userId = presignToken?.userId;
}
if (!userId) {
return c.json({ error: 'Unauthorized' }, 401); return c.json({ error: 'Unauthorized' }, 401);
} }
@ -118,7 +104,7 @@ export const filesRoute = new Hono<HonoEnv>()
} }
const team = await getTeamById({ const team = await getTeamById({
userId: userId, userId: session.user.id,
teamId: envelope.teamId, teamId: envelope.teamId,
}).catch((error) => { }).catch((error) => {
console.error(error); console.error(error);

View File

@ -36,14 +36,6 @@ export type TGetEnvelopeItemFileRequestParams = z.infer<
typeof ZGetEnvelopeItemFileRequestParamsSchema typeof ZGetEnvelopeItemFileRequestParamsSchema
>; >;
export const ZGetEnvelopeItemFileRequestQuerySchema = z.object({
token: z.string().optional(),
});
export type TGetEnvelopeItemFileRequestQuery = z.infer<
typeof ZGetEnvelopeItemFileRequestQuerySchema
>;
export const ZGetEnvelopeItemFileTokenRequestParamsSchema = z.object({ export const ZGetEnvelopeItemFileTokenRequestParamsSchema = z.object({
token: z.string().min(1), token: z.string().min(1),
envelopeItemId: z.string().min(1), envelopeItemId: z.string().min(1),

View File

@ -25,7 +25,6 @@ import { signPdf } from '@documenso/signing';
import { AppError, AppErrorCode } from '../../../errors/app-error'; import { AppError, AppErrorCode } from '../../../errors/app-error';
import { sendCompletedEmail } from '../../../server-only/document/send-completed-email'; import { sendCompletedEmail } from '../../../server-only/document/send-completed-email';
import PostHogServerClient from '../../../server-only/feature-flags/get-post-hog-server-client';
import { getAuditLogsPdf } from '../../../server-only/htmltopdf/get-audit-logs-pdf'; import { getAuditLogsPdf } from '../../../server-only/htmltopdf/get-audit-logs-pdf';
import { getCertificatePdf } from '../../../server-only/htmltopdf/get-certificate-pdf'; import { getCertificatePdf } from '../../../server-only/htmltopdf/get-certificate-pdf';
import { addRejectionStampToPdf } from '../../../server-only/pdf/add-rejection-stamp-to-pdf'; import { addRejectionStampToPdf } from '../../../server-only/pdf/add-rejection-stamp-to-pdf';
@ -62,171 +61,120 @@ export const run = async ({
}) => { }) => {
const { documentId, sendEmail = true, isResealing = false, requestMetadata } = payload; const { documentId, sendEmail = true, isResealing = false, requestMetadata } = payload;
const envelope = await prisma.envelope.findFirstOrThrow({ const { envelopeId, envelopeStatus, isRejected } = await io.runTask('seal-document', async () => {
where: { const envelope = await prisma.envelope.findFirstOrThrow({
type: EnvelopeType.DOCUMENT, where: {
secondaryId: mapDocumentIdToSecondaryId(documentId), type: EnvelopeType.DOCUMENT,
}, secondaryId: mapDocumentIdToSecondaryId(documentId),
include: { },
documentMeta: true, include: {
recipients: true, documentMeta: true,
envelopeItems: { recipients: true,
include: { envelopeItems: {
documentData: true, include: {
field: { documentData: true,
include: { field: {
signature: true, include: {
signature: true,
},
}, },
}, },
}, },
}, },
},
});
if (envelope.envelopeItems.length === 0) {
throw new Error('At least one envelope item required');
}
const settings = await getTeamSettings({
userId: envelope.userId,
teamId: envelope.teamId,
});
const isComplete =
envelope.recipients.some((recipient) => recipient.signingStatus === SigningStatus.REJECTED) ||
envelope.recipients.every((recipient) => recipient.signingStatus === SigningStatus.SIGNED);
if (!isComplete) {
throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
message: 'Document is not complete',
}); });
}
// Seems silly but we need to do this in case the job is re-ran if (envelope.envelopeItems.length === 0) {
// after it has already run through the update task further below. throw new Error('At least one envelope item required');
// eslint-disable-next-line @typescript-eslint/require-await }
const documentStatus = await io.runTask('get-document-status', async () => {
return envelope.status;
});
// This is the same case as above. const settings = await getTeamSettings({
let envelopeItems = await io.runTask( userId: envelope.userId,
'get-document-data-id', teamId: envelope.teamId,
// eslint-disable-next-line @typescript-eslint/require-await });
async () => {
// eslint-disable-next-line unused-imports/no-unused-vars
return envelope.envelopeItems.map(({ field, ...rest }) => ({
...rest,
}));
},
);
if (envelopeItems.length < 1) { const isComplete =
throw new Error(`Document ${envelope.id} has no envelope items`); envelope.recipients.some((recipient) => recipient.signingStatus === SigningStatus.REJECTED) ||
} envelope.recipients.every((recipient) => recipient.signingStatus === SigningStatus.SIGNED);
const recipients = await prisma.recipient.findMany({ if (!isComplete) {
where: { throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
envelopeId: envelope.id, message: 'Document is not complete',
role: { });
not: RecipientRole.CC, }
},
},
});
// Determine if the document has been rejected by checking if any recipient has rejected it let envelopeItems = envelope.envelopeItems;
const rejectedRecipient = recipients.find(
(recipient) => recipient.signingStatus === SigningStatus.REJECTED,
);
const isRejected = Boolean(rejectedRecipient); if (envelopeItems.length < 1) {
throw new Error(`Document ${envelope.id} has no envelope items`);
}
// Get the rejection reason from the rejected recipient const recipients = await prisma.recipient.findMany({
const rejectionReason = rejectedRecipient?.rejectionReason ?? '';
const fields = await prisma.field.findMany({
where: {
envelopeId: envelope.id,
},
include: {
signature: true,
},
});
// Skip the field check if the document is rejected
if (!isRejected && fieldsContainUnsignedRequiredField(fields)) {
throw new Error(`Document ${envelope.id} has unsigned required fields`);
}
if (isResealing) {
// If we're resealing we want to use the initial data for the document
// so we aren't placing fields on top of eachother.
envelopeItems = envelopeItems.map((envelopeItem) => ({
...envelopeItem,
documentData: {
...envelopeItem.documentData,
data: envelopeItem.documentData.initialData,
},
}));
}
if (!envelope.qrToken) {
await prisma.envelope.update({
where: { where: {
id: envelope.id, envelopeId: envelope.id,
}, role: {
data: { not: RecipientRole.CC,
qrToken: prefixedId('qr'), },
}, },
}); });
}
const legacyDocumentId = mapSecondaryIdToDocumentId(envelope.secondaryId); // Determine if the document has been rejected by checking if any recipient has rejected it
const rejectedRecipient = recipients.find(
(recipient) => recipient.signingStatus === SigningStatus.REJECTED,
);
const { certificateData, auditLogData } = await getCertificateAndAuditLogData({ const isRejected = Boolean(rejectedRecipient);
legacyDocumentId,
documentMeta: envelope.documentMeta,
settings,
});
// !: The commented out code is our desired implementation but we're seemingly // Get the rejection reason from the rejected recipient
// !: running into issues with inngest parallelism in production. const rejectionReason = rejectedRecipient?.rejectionReason ?? '';
// !: Until this is resolved we will do this sequentially which is slower but
// !: will actually work.
// const decoratePromises: Array<Promise<{ oldDocumentDataId: string; newDocumentDataId: string }>> =
// [];
// for (const envelopeItem of envelopeItems) { const fields = await prisma.field.findMany({
// const task = io.runTask(`decorate-${envelopeItem.id}`, async () => { where: {
// const envelopeItemFields = envelope.envelopeItems.find( envelopeId: envelope.id,
// (item) => item.id === envelopeItem.id, },
// )?.field; include: {
signature: true,
},
});
// if (!envelopeItemFields) { // Skip the field check if the document is rejected
// throw new Error(`Envelope item fields not found for envelope item ${envelopeItem.id}`); if (!isRejected && fieldsContainUnsignedRequiredField(fields)) {
// } throw new Error(`Document ${envelope.id} has unsigned required fields`);
}
// return decorateAndSignPdf({ if (isResealing) {
// envelope, // If we're resealing we want to use the initial data for the document
// envelopeItem, // so we aren't placing fields on top of eachother.
// envelopeItemFields, envelopeItems = envelopeItems.map((envelopeItem) => ({
// isRejected, ...envelopeItem,
// rejectionReason, documentData: {
// certificateData, ...envelopeItem.documentData,
// auditLogData, data: envelopeItem.documentData.initialData,
// }); },
// }); }));
}
// decoratePromises.push(task); if (!envelope.qrToken) {
// } await prisma.envelope.update({
where: {
id: envelope.id,
},
data: {
qrToken: prefixedId('qr'),
},
});
}
// const newDocumentData = await Promise.all(decoratePromises); const legacyDocumentId = mapSecondaryIdToDocumentId(envelope.secondaryId);
// TODO: Remove once parallelization is working const { certificateData, auditLogData } = await getCertificateAndAuditLogData({
const newDocumentData: Array<{ oldDocumentDataId: string; newDocumentDataId: string }> = []; legacyDocumentId,
documentMeta: envelope.documentMeta,
settings,
});
for (const envelopeItem of envelopeItems) { const newDocumentData: Array<{ oldDocumentDataId: string; newDocumentDataId: string }> = [];
const result = await io.runTask(`decorate-${envelopeItem.id}`, async () => {
for (const envelopeItem of envelopeItems) {
const envelopeItemFields = envelope.envelopeItems.find( const envelopeItemFields = envelope.envelopeItems.find(
(item) => item.id === envelopeItem.id, (item) => item.id === envelopeItem.id,
)?.field; )?.field;
@ -235,7 +183,7 @@ export const run = async ({
throw new Error(`Envelope item fields not found for envelope item ${envelopeItem.id}`); throw new Error(`Envelope item fields not found for envelope item ${envelopeItem.id}`);
} }
return decorateAndSignPdf({ const result = await decorateAndSignPdf({
envelope, envelope,
envelopeItem, envelopeItem,
envelopeItemFields, envelopeItemFields,
@ -244,25 +192,10 @@ export const run = async ({
certificateData, certificateData,
auditLogData, auditLogData,
}); });
});
newDocumentData.push(result); newDocumentData.push(result);
} }
const postHog = PostHogServerClient();
if (postHog) {
postHog.capture({
distinctId: nanoid(),
event: 'App: Document Sealed',
properties: {
documentId: envelope.id,
isRejected,
},
});
}
await io.runTask('update-document', async () => {
await prisma.$transaction(async (tx) => { await prisma.$transaction(async (tx) => {
for (const { oldDocumentDataId, newDocumentDataId } of newDocumentData) { for (const { oldDocumentDataId, newDocumentDataId } of newDocumentData) {
const newData = await tx.documentData.findFirstOrThrow({ const newData = await tx.documentData.findFirstOrThrow({
@ -304,18 +237,24 @@ export const run = async ({
}), }),
}); });
}); });
return {
envelopeId: envelope.id,
envelopeStatus: envelope.status,
isRejected,
};
}); });
await io.runTask('send-completed-email', async () => { await io.runTask('send-completed-email', async () => {
let shouldSendCompletedEmail = sendEmail && !isResealing && !isRejected; let shouldSendCompletedEmail = sendEmail && !isResealing && !isRejected;
if (isResealing && !isDocumentCompleted(envelope.status)) { if (isResealing && !isDocumentCompleted(envelopeStatus)) {
shouldSendCompletedEmail = sendEmail; shouldSendCompletedEmail = sendEmail;
} }
if (shouldSendCompletedEmail) { if (shouldSendCompletedEmail) {
await sendCompletedEmail({ await sendCompletedEmail({
id: { type: 'envelopeId', id: envelope.id }, id: { type: 'envelopeId', id: envelopeId },
requestMetadata, requestMetadata,
}); });
} }
@ -323,7 +262,7 @@ export const run = async ({
const updatedEnvelope = await prisma.envelope.findFirstOrThrow({ const updatedEnvelope = await prisma.envelope.findFirstOrThrow({
where: { where: {
id: envelope.id, id: envelopeId,
}, },
include: { include: {
documentMeta: true, documentMeta: true,

View File

@ -8,17 +8,15 @@ export type EnvelopeItemPdfUrlOptions =
envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>; envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>;
token: string | undefined; token: string | undefined;
version: 'original' | 'signed'; version: 'original' | 'signed';
presignToken?: undefined;
} }
| { | {
type: 'view'; type: 'view';
envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>; envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>;
token: string | undefined; token: string | undefined;
presignToken?: string | undefined;
}; };
export const getEnvelopeItemPdfUrl = (options: EnvelopeItemPdfUrlOptions) => { export const getEnvelopeItemPdfUrl = (options: EnvelopeItemPdfUrlOptions) => {
const { envelopeItem, token, type, presignToken } = options; const { envelopeItem, token, type } = options;
const { id, envelopeId } = envelopeItem; const { id, envelopeId } = envelopeItem;
@ -26,11 +24,11 @@ export const getEnvelopeItemPdfUrl = (options: EnvelopeItemPdfUrlOptions) => {
const version = options.version; const version = options.version;
return token return token
? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}/download/${version}${presignToken ? `?presignToken=${presignToken}` : ''}` ? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}/download/${version}`
: `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/envelope/${envelopeId}/envelopeItem/${id}/download/${version}`; : `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/envelope/${envelopeId}/envelopeItem/${id}/download/${version}`;
} }
return token return token
? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}${presignToken ? `?presignToken=${presignToken}` : ''}` ? `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/token/${token}/envelopeItem/${id}`
: `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/envelope/${envelopeId}/envelopeItem/${id}`; : `${NEXT_PUBLIC_WEBAPP_URL()}/api/files/envelope/${envelopeId}/envelopeItem/${id}`;
}; };

View File

@ -56,7 +56,6 @@ export type PDFViewerProps = {
className?: string; className?: string;
envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>; envelopeItem: Pick<EnvelopeItem, 'id' | 'envelopeId'>;
token: string | undefined; token: string | undefined;
presignToken?: string | undefined;
version: 'original' | 'signed'; version: 'original' | 'signed';
onDocumentLoad?: (_doc: LoadedPDFDocument) => void; onDocumentLoad?: (_doc: LoadedPDFDocument) => void;
onPageClick?: OnPDFViewerPageClick; onPageClick?: OnPDFViewerPageClick;
@ -68,7 +67,6 @@ export const PDFViewer = ({
className, className,
envelopeItem, envelopeItem,
token, token,
presignToken,
version, version,
onDocumentLoad, onDocumentLoad,
onPageClick, onPageClick,
@ -168,7 +166,6 @@ export const PDFViewer = ({
type: 'view', type: 'view',
envelopeItem: envelopeItem, envelopeItem: envelopeItem,
token, token,
presignToken,
}); });
const bytes = await fetch(documentUrl).then(async (res) => await res.arrayBuffer()); const bytes = await fetch(documentUrl).then(async (res) => await res.arrayBuffer());