Skip to content

Commit

Permalink
refactor: pg-boss jobs and esign (#493)
Browse files Browse the repository at this point in the history
* feat: add queue utility

* feat: add QUEUE_DATABASE_URL

* feat: update member invite email

* feat: update password reset email

* feat: update share update email

* feat: update data room email job

* feat: update reinvite job

* feat: register jobs

* feat: add eSignNotificationWorker

* feat: add authVerificationEmailWorker

* feat: add esign confirmation job

* feat: add esign pdf worker

* feat: refactor name

* refactor: move lib

* feat: update

* feat: use singleton

* feat: split and register

* chore: fix connection

* fix: type

* chore: fix type

* chore: upgrade pg-boss

* chore: fix type

* fix: types

* feat:  move audit inside handler

* feat: refactor sign-template

* fix: remove sent status

* feat: add status complete

* feat: add new enums

* fix: status map

* fix: status

* fix: job

* feat: refactor esign

* fix: status enum

* feat: changes

* chore: upgrade react email

* feat: use render method
  • Loading branch information
G3root authored Sep 19, 2024
1 parent 2e3fdfb commit b63006f
Show file tree
Hide file tree
Showing 40 changed files with 1,095 additions and 2,097 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toolbar": "^1.0.4",
"@radix-ui/react-tooltip": "^1.1.2",
"@react-email/components": "0.0.22",
"@react-email/components": "0.0.25",
"@react-pdf/renderer": "^3.4.4",
"@remixicon/react": "^4.0.1",
"@scalar/nextjs-api-reference": "^0.4.18",
Expand Down Expand Up @@ -96,7 +96,7 @@
"nodemailer": "^6.9.14",
"papaparse": "^5.4.1",
"pdf-lib": "^1.17.1",
"pg-boss": "^9.0.3",
"pg-boss": "^10.1.1",
"pino": "^9.3.1",
"pino-pretty": "^11.2.2",
"prisma-extension-pagination": "^0.7.4",
Expand All @@ -105,7 +105,7 @@
"react": "18.3.1",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
"react-email": "2.1.6",
"react-email": "3.0.1",
"react-hook-form": "^7.52.1",
"react-number-format": "^5.3.4",
"react-pdf": "^8.0.2",
Expand Down
1,495 changes: 198 additions & 1,297 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions prisma/migrations/20240906132847_add_new_status/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
Warnings:
- The values [SENT,WAITING] on the enum `TemplateStatus` will be removed. If these variants are still used in the database, this will fail.
*/
-- AlterEnum
BEGIN;
CREATE TYPE "TemplateStatus_new" AS ENUM ('DRAFT', 'COMPLETE', 'PENDING', 'CANCELLED');
ALTER TABLE "Template" ALTER COLUMN "status" DROP DEFAULT;
ALTER TABLE "Template" ALTER COLUMN "status" TYPE "TemplateStatus_new" USING ("status"::text::"TemplateStatus_new");
ALTER TYPE "TemplateStatus" RENAME TO "TemplateStatus_old";
ALTER TYPE "TemplateStatus_new" RENAME TO "TemplateStatus";
DROP TYPE "TemplateStatus_old";
ALTER TABLE "Template" ALTER COLUMN "status" SET DEFAULT 'DRAFT';
COMMIT;
3 changes: 1 addition & 2 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -602,8 +602,7 @@ model TemplateField {
enum TemplateStatus {
DRAFT
COMPLETE
SENT
WAITING
PENDING
CANCELLED
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Alert, AlertDescription } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { serverAccessControl } from "@/lib/rbac/access-control";
import type { TemplateStatus } from "@/prisma/enums";
import { TemplateSigningFieldProvider } from "@/providers/template-signing-field-provider";
import { api } from "@/trpc/server";
import { RiCheckFill } from "@remixicon/react";
Expand All @@ -14,6 +15,13 @@ type BadgeVariant =
| "secondary"
| "destructive";

const variantMap: Record<TemplateStatus, BadgeVariant> = {
CANCELLED: "destructive",
COMPLETE: "success",
DRAFT: "info",
PENDING: "secondary",
};

export default async function TemplateDetailViewPage({
params: { templatePublicId },
}: {
Expand All @@ -36,29 +44,12 @@ export default async function TemplateDetailViewPage({
),
]);

const badgeVariant = (): BadgeVariant => {
let result: BadgeVariant = "warning";

if (status === "DRAFT") {
result = "warning";
} else if (status === "SENT") {
result = "info";
} else if (status === "COMPLETE") {
result = "success";
} else if (status === "WAITING") {
result = "secondary";
} else if (status === "CANCELLED") {
result = "destructive";
}
return result;
};

return (
<TemplateSigningFieldProvider fields={fields}>
<div className="flex min-h-screen bg-gray-50">
<div className="flex h-full flex-grow flex-col">
<div className="col-span-12 flex align-middle">
<Badge variant={badgeVariant()} className="h-7 align-middle">
<Badge variant={variantMap[status]} className="h-7 align-middle">
{status}
</Badge>
<span className="ml-2 align-middle text-xl font-semibold">
Expand Down
4 changes: 2 additions & 2 deletions src/app/updates/[publicId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import UpdateRenderer from "@/components/update/renderer";
import { type JWTVerifyResult, decode } from "@/lib/jwt";
import { UpdateStatusEnum } from "@/prisma/enums";
import { db } from "@/server/db";
import { renderAsync } from "@react-email/components";
import { render } from "@react-email/components";
import { RiLock2Line } from "@remixicon/react";
import { notFound } from "next/navigation";
import { Fragment } from "react";
Expand Down Expand Up @@ -100,7 +100,7 @@ const PublicUpdatePage = async ({

const company = update?.company;
const author = update?.author;
const html = await renderAsync(<UpdateRenderer html={update.html} />);
const html = await render(<UpdateRenderer html={update.html} />);

return (
<SharePageLayout
Expand Down
2 changes: 1 addition & 1 deletion src/components/template/canavs-toolbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function CanvasToolbar({ recipients }: CanvasToolbarProps) {
// biome-ignore lint/correctness/useExhaustiveDependencies: reason
const onSignatureRequest = useCallback((canSubmit: boolean) => {
if (canSubmit && submitRef.current) {
setValue("status", "COMPLETE");
setValue("status", "PENDING");
submitRef.current.click();
}
}, []);
Expand Down
2 changes: 1 addition & 1 deletion src/components/template/template-field-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const TemplateFieldForm = ({
toast.error(`${title}, ${message}`);
}

if (status === "COMPLETE") {
if (status === "PENDING") {
router.push(`/${companyPublicId}/documents/esign`);
}
},
Expand Down
2 changes: 1 addition & 1 deletion src/constants/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ export const JOB_TYPES = {
"esign-confirmation",
"esign-notification",
],
generate: ["esign-pdf"],
esign: ["generate-pdf", "complete-pdf"],
} as const;
4 changes: 2 additions & 2 deletions src/emails/EsignConfirmationEmail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import {
Text,
} from "@react-email/components";

import type { ConfirmationEmailPayloadType } from "../jobs/esign-confirmation-email";
import type { TSchema } from "../jobs/esign-confirmation-email";

type Payload = Omit<ConfirmationEmailPayloadType, "fileUrl">;
type Payload = Omit<TSchema, "fileUrl">;

const ESignConfirmationEmail = ({
documentName,
Expand Down
9 changes: 7 additions & 2 deletions src/emails/EsignEmail.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { EsignEmailPayloadType } from "@/jobs/esign-email";
import type { TESignNotificationEmailJobInput } from "@/jobs/esign-email";
import {
Body,
Button,
Expand All @@ -21,7 +21,12 @@ import {
UserAvatarIcon,
} from "../components/common/icons";

type TEsignEmailProps = EsignEmailPayloadType & { signingLink: string };
type TEsignEmailProps = Omit<
TESignNotificationEmailJobInput,
"token" | "email" | "userAgent" | "requestIp" | "companyId"
> & {
signingLink: string;
};

const EsignEmail = ({
signingLink,
Expand Down
6 changes: 6 additions & 0 deletions src/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export const env = createEnv({
// sentry
SENTRY_ORG: z.string().optional(),
SENTRY_PROJECT: z.string().optional(),

//job queue
QUEUE_DATABASE_URL: z.string().optional(),
},

/**
Expand Down Expand Up @@ -116,6 +119,9 @@ export const env = createEnv({
NEXT_PUBLIC_SENTRY_DSN: readRuntimePublicEnvVariable(
"NEXT_PUBLIC_SENTRY_DSN",
),

/// job queue
WORKER_DATABASE_URL: process.env.WORKER_DATABASE_URL,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
Expand Down
5 changes: 3 additions & 2 deletions src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { isSentryEnabled } from "@/constants/sentry";

export async function register() {
if (process.env.NEXT_RUNTIME === "nodejs") {
const { startJobs } = await import("@/jobs/start");
await startJobs();
const { registerJobs } = await import("@/jobs/register");

await registerJobs();

if (isSentryEnabled) {
await import("../sentry.server.config");
Expand Down
36 changes: 15 additions & 21 deletions src/jobs/auth-verification-email.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import AccountVerificationEmail from "@/emails/AccountVerificationEmail";
import { env } from "@/env";
import { BaseJob } from "@/jobs/base";
import { sendMail } from "@/server/mailer";
import { renderAsync } from "@react-email/components";
import type { Job } from "pg-boss";
import { render } from "@react-email/components";
import { z } from "zod";
import { defineJob, defineWorker, defineWorkerConfig } from "../lib/queue";

export type AuthVerificationPayloadType = {
email: string;
token: string;
};
const config = defineWorkerConfig({
name: "email.auth-verify",
schema: z.object({
email: z.string(),
token: z.string(),
}),
});

export const sendAuthVerificationEmail = async (
payload: AuthVerificationPayloadType,
) => {
const { email, token } = payload;
export const authVerificationEmailJob = defineJob(config);
export const authVerificationEmailWorker = defineWorker(config, async (job) => {
const { email, token } = job.data;
const baseUrl = env.NEXT_PUBLIC_BASE_URL;
const confirmLink = `${baseUrl}/verify-email/${token}`;

const html = await renderAsync(
const html = await render(
AccountVerificationEmail({
verifyLink: confirmLink,
}),
Expand All @@ -28,12 +30,4 @@ export const sendAuthVerificationEmail = async (
subject: "Confirm your email",
html,
});
};

export class AuthVerificationEmailJob extends BaseJob<AuthVerificationPayloadType> {
readonly type = "email.auth-verify";

async work(job: Job<AuthVerificationPayloadType>): Promise<void> {
await sendAuthVerificationEmail(job.data);
}
}
});
106 changes: 0 additions & 106 deletions src/jobs/base.ts

This file was deleted.

Loading

0 comments on commit b63006f

Please sign in to comment.