chore: code changes based of review

This commit is contained in:
Ephraim Atta-Duncan
2024-11-21 21:21:42 +00:00
parent 31dc403500
commit 2b1b042097
10 changed files with 61 additions and 54 deletions

View File

@ -100,9 +100,7 @@ export const ResendDocumentActionItem = ({
}); });
setIsOpen(false); setIsOpen(false);
} catch (err) { } catch {
console.log(err);
toast({ toast({
title: _(msg`Something went wrong`), title: _(msg`Something went wrong`),
description: _(msg`This document could not be re-sent at this time. Please try again.`), description: _(msg`This document could not be re-sent at this time. Please try again.`),

View File

@ -2,7 +2,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { msg } from '@lingui/macro'; import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react'; import { useLingui } from '@lingui/react';
import { Input } from '@documenso/ui/primitives/input'; import { Input } from '@documenso/ui/primitives/input';
@ -25,12 +25,14 @@ export const DocumentExpirySettings = ({ onChange }: DocumentExpirySettingsProps
const handleExpiryValueChange = (value: string) => { const handleExpiryValueChange = (value: string) => {
const parsedValue = parseInt(value, 10); const parsedValue = parseInt(value, 10);
if (isNaN(parsedValue)) {
if (Number.isNaN(parsedValue) || parsedValue <= 0) {
setExpiryValue(undefined); setExpiryValue(undefined);
return;
} else { } else {
setExpiryValue(parsedValue); setExpiryValue(parsedValue);
onChange(parsedValue, expiryUnit);
} }
onChange(parsedValue, expiryUnit);
}; };
const handleExpiryUnitChange = (value: 'day' | 'week' | 'month') => { const handleExpiryUnitChange = (value: 'day' | 'week' | 'month') => {
@ -50,12 +52,18 @@ export const DocumentExpirySettings = ({ onChange }: DocumentExpirySettingsProps
/> />
<Select value={expiryUnit} onValueChange={handleExpiryUnitChange}> <Select value={expiryUnit} onValueChange={handleExpiryUnitChange}>
<SelectTrigger className="text-muted-foreground"> <SelectTrigger className="text-muted-foreground">
<SelectValue placeholder="Select..." /> <SelectValue placeholder={_(msg`Select...`)} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="day">Day</SelectItem> <SelectItem value="day">
<SelectItem value="week">Week</SelectItem> <Trans>Day</Trans>
<SelectItem value="month">Month</SelectItem> </SelectItem>
<SelectItem value="week">
<Trans>Week</Trans>
</SelectItem>
<SelectItem value="month">
<Trans>Month</Trans>
</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>

View File

@ -106,23 +106,6 @@ export const resendDocument = async ({
return; return;
} }
let newExpiryDate: Date | null = null;
if (recipient.expired) {
const durationInMs = recipient.expired.getTime() - document.updatedAt.getTime();
newExpiryDate = new Date(Date.now() + durationInMs);
await prisma.recipient.update({
where: { id: recipient.id },
data: {
expired: newExpiryDate,
signingStatus:
recipient.signingStatus === SigningStatus.EXPIRED
? SigningStatus.NOT_SIGNED
: recipient.signingStatus,
},
});
}
const i18n = await getI18nInstance(document.documentMeta?.language); const i18n = await getI18nInstance(document.documentMeta?.language);
const recipientEmailType = RECIPIENT_ROLE_TO_EMAIL_TYPE[recipient.role]; const recipientEmailType = RECIPIENT_ROLE_TO_EMAIL_TYPE[recipient.role];
@ -183,6 +166,22 @@ export const resendDocument = async ({
await prisma.$transaction( await prisma.$transaction(
async (tx) => { async (tx) => {
if (recipient.expired) {
const durationInMs = recipient.expired.getTime() - document.updatedAt.getTime();
const newExpiryDate = new Date(Date.now() + durationInMs);
await tx.recipient.update({
where: { id: recipient.id },
data: {
expired: newExpiryDate,
signingStatus:
recipient.signingStatus === SigningStatus.EXPIRED
? SigningStatus.NOT_SIGNED
: recipient.signingStatus,
},
});
}
const [html, text] = await Promise.all([ const [html, text] = await Promise.all([
renderEmailWithI18N(template, { renderEmailWithI18N(template, {
lang: document.documentMeta?.language, lang: document.documentMeta?.language,

View File

@ -31,26 +31,24 @@ export const updateExpiredRecipients = async (documentId: number) => {
}, },
}); });
await Promise.all( await prisma.documentAuditLog.createMany({
expiredRecipients.map(async (recipient) => data: expiredRecipients.map((recipient) =>
prisma.documentAuditLog.create({ createDocumentAuditLogData({
data: createDocumentAuditLogData({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED,
type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED, documentId,
documentId, user: {
user: { name: recipient.name,
name: recipient.name, email: recipient.email,
email: recipient.email, },
}, data: {
data: { recipientName: recipient.name,
recipientEmail: recipient.email, recipientRole: recipient.role,
recipientName: recipient.name, recipientId: recipient.id,
recipientId: recipient.id, recipientEmail: recipient.email,
recipientRole: recipient.role, },
},
}),
}), }),
), ),
); });
} }
return expiredRecipients; return expiredRecipients;

View File

@ -1,3 +1,5 @@
import { DateTime } from 'luxon';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { SigningStatus } from '@documenso/prisma/client'; import { SigningStatus } from '@documenso/prisma/client';
@ -16,8 +18,8 @@ export const isRecipientExpired = async ({ token }: IsRecipientExpiredOptions) =
throw new Error('Recipient not found'); throw new Error('Recipient not found');
} }
const now = new Date(); const now = DateTime.now();
const hasExpired = recipient.expired && new Date(recipient.expired) <= now; const hasExpired = recipient.expired && DateTime.fromJSDate(recipient.expired) <= now;
if (hasExpired && recipient.signingStatus !== SigningStatus.EXPIRED) { if (hasExpired && recipient.signingStatus !== SigningStatus.EXPIRED) {
await prisma.recipient.update({ await prisma.recipient.update({

View File

@ -103,9 +103,9 @@ export const setRecipientExpiry = async ({
}, },
}), }),
}); });
return persisted;
} }
return persisted;
}); });
return updatedRecipient; return updatedRecipient;

View File

@ -375,7 +375,7 @@ export const formatDocumentAuditLogAction = (
.with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED }, () => { .with({ type: DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_EXPIRED }, () => {
const userName = prefix || _(msg`Recipient`); const userName = prefix || _(msg`Recipient`);
const result = msg`${userName} expired`; const result = msg`${userName}'s signing period has expired`;
return { return {
anonymous: result, anonymous: result,

View File

@ -84,7 +84,7 @@ export type TRejectDocumentWithTokenMutationSchema = z.infer<
export const ZSetSignerExpirySchema = z.object({ export const ZSetSignerExpirySchema = z.object({
documentId: z.number(), documentId: z.number(),
signerId: z.number(), signerId: z.number(),
expiry: z.date(), expiry: z.date().min(new Date(), { message: 'Expiry date must be in the future' }),
teamId: z.number().optional(), teamId: z.number().optional(),
}); });

View File

@ -15,7 +15,7 @@ export const ZAddSignerSchema = z.object({
.min(1), .min(1),
name: z.string(), name: z.string(),
role: z.nativeEnum(RecipientRole), role: z.nativeEnum(RecipientRole),
expiry: z.date().optional(), expiry: z.date().min(new Date(), { message: 'Expiry date must be in the future' }).optional(),
signingOrder: z.number().optional(), signingOrder: z.number().optional(),
actionAuth: ZMapNegativeOneToUndefinedSchema.pipe(ZRecipientActionAuthTypesSchema.optional()), actionAuth: ZMapNegativeOneToUndefinedSchema.pipe(ZRecipientActionAuthTypesSchema.optional()),
}); });

View File

@ -164,6 +164,8 @@ export function DocumentExpiryDialog({
case 'months': case 'months':
expiryDate = addMonths(now, values.amount); expiryDate = addMonths(now, values.amount);
break; break;
default:
throw new Error(`Invalid unit: ${values.unit}`);
} }
} }
@ -173,10 +175,10 @@ export function DocumentExpiryDialog({
expiry: expiryDate, expiry: expiryDate,
}); });
// TODO: Implement logic to update expiry when resending document // TODO: Duncan => Implement logic to update expiry when resending document
// This should be handled on the server-side when a document is resent // This should be handled on the server-side when a document is resent
// TODO: Implement logic to mark recipients as expired // TODO: Duncan => Implement logic to mark recipients as expired
// This should be a scheduled task or part of the completion process on the server // This should be a scheduled task or part of the completion process on the server
}; };