diff --git a/expose/api/src/Consumer/Handler/ZippyDownloadRequestHandler.php b/expose/api/src/Consumer/Handler/ZippyDownloadRequestHandler.php
index 854e37a9f..9bba02f90 100644
--- a/expose/api/src/Consumer/Handler/ZippyDownloadRequestHandler.php
+++ b/expose/api/src/Consumer/Handler/ZippyDownloadRequestHandler.php
@@ -5,7 +5,7 @@
namespace App\Consumer\Handler;
use Alchemy\CoreBundle\Util\DoctrineUtil;
-use Alchemy\NotifyBundle\src\NotifierInterface;
+use Alchemy\NotifyBundle\Notification\NotifierInterface;
use App\Entity\DownloadRequest;
use App\Security\Authentication\JWTManager;
use App\ZippyManager;
@@ -32,20 +32,22 @@ public function __invoke(ZippyDownloadRequest $message): void
// Trigger ZIP preparation
$this->zippyManager->getDownloadUrl($downloadRequest->getPublication());
+ $daysAvailable = 3;
$uri = $this->urlGenerator->generate('archive_download', [
'id' => $downloadRequest->getPublication()->getId(),
], UrlGeneratorInterface::ABSOLUTE_URL);
$downloadUrl = $this->JWTManager->signUri(
$uri,
- 259200 // 3 days
+ $daysAvailable * 3600 * 24,
);
$this->notifier->sendEmail(
$downloadRequest->getEmail(),
- 'expose/zippy_download_link',
- $downloadRequest->getLocale(),
+ 'expose-zippy-download-link',
[
- 'download_url' => $downloadUrl,
+ 'locale' => $downloadRequest->getLocale(),
+ 'downloadUrl' => $downloadUrl,
+ 'daysAvailable' => $daysAvailable,
]
);
}
diff --git a/novu/bridge/app/api/novu/route.ts b/novu/bridge/app/api/novu/route.ts
index 2cfcb43a8..e728a7444 100644
--- a/novu/bridge/app/api/novu/route.ts
+++ b/novu/bridge/app/api/novu/route.ts
@@ -1,10 +1,15 @@
import { serve } from "@novu/framework/next";
-import {uploaderCommitAcknowledged, welcomeOnboardingEmail} from "../../novu/workflows";
+import {
+ exposeDownloadLink,
+ exposeZippyDownloadLink,
+ uploaderCommitAcknowledged,
+} from "../../novu/workflows";
// the workflows collection can hold as many workflow definitions as you need
export const { GET, POST, OPTIONS } = serve({
workflows: [
- welcomeOnboardingEmail,
uploaderCommitAcknowledged,
+ exposeZippyDownloadLink,
+ exposeDownloadLink,
],
});
diff --git a/novu/bridge/app/novu/emails/CTAEmail.tsx b/novu/bridge/app/novu/emails/CTAEmail.tsx
new file mode 100644
index 000000000..8616e34be
--- /dev/null
+++ b/novu/bridge/app/novu/emails/CTAEmail.tsx
@@ -0,0 +1,68 @@
+import {Button, Section, Text} from "@react-email/components";
+import React from "react";
+import DefaultEmail, {
+ createEmailControlSchema,
+ CreateEmailControlSchemaProps,
+ styles
+} from "@/app/novu/emails/DefaultEmail";
+import {z, ZodDefault, ZodOptional, ZodString} from "zod";
+
+type Props = {
+ introText?: string;
+ outroText?: string;
+ linkUrl: string;
+ linkText: string;
+};
+
+export default function CTAEmail({
+ linkUrl,
+ linkText,
+ introText,
+ outroText,
+}: Props) {
+ return (
+
+
+ {introText ?
+ {introText}
+ : null}
+
+
+
+
+ {linkUrl}
+
+
+ {outroText ?
+ {outroText}
+ : null}
+
+
+ );
+}
+
+export type CreateCTAEEmailControlSchemaProps = {
+ defaultIntroText?: string | undefined;
+ defaultOutroText?: string | undefined;
+} & CreateEmailControlSchemaProps;
+
+export function createCTAEmailControlSchema({
+ defaultIntroText,
+ defaultOutroText,
+ ...rest
+}: CreateCTAEEmailControlSchemaProps) {
+ return createEmailControlSchema({
+ ...rest,
+ introText: createOptionalOrNotString(defaultIntroText),
+ outroText: createOptionalOrNotString(defaultOutroText),
+ });
+}
+
+function createOptionalOrNotString(defaultValue: string | undefined): ZodOptional | ZodDefault {
+ const string = z.string();
+ if (defaultValue) {
+ return string.default(defaultValue);
+ } else {
+ return string.optional();
+ }
+}
diff --git a/novu/bridge/app/novu/emails/DefaultEmail.tsx b/novu/bridge/app/novu/emails/DefaultEmail.tsx
new file mode 100644
index 000000000..1b2727af0
--- /dev/null
+++ b/novu/bridge/app/novu/emails/DefaultEmail.tsx
@@ -0,0 +1,80 @@
+import {Body, Container, Head, Html, Preview} from "@react-email/components";
+import React, {CSSProperties, PropsWithChildren} from "react";
+import {z} from "zod";
+import {ZodRawShape} from "zod/lib/types";
+
+type Props = PropsWithChildren<{}>;
+
+export default function DefaultEmail({
+ children,
+}: Props) {
+ return (
+
+
+ Dropbox reset your password
+
+
+ {children}
+
+
+
+ );
+}
+
+const main: CSSProperties = {
+ backgroundColor: "#abc5ff",
+ padding: "8px 0",
+};
+
+const container: CSSProperties = {
+ backgroundColor: "#ffffff",
+ border: "1px solid #f0f0f0",
+ padding: "45px",
+};
+
+export const text: CSSProperties = {
+ fontSize: "16px",
+ fontWeight: "300",
+ color: "#404040",
+ lineHeight: "26px",
+};
+const headingText: CSSProperties = {
+ fontWeight: "300",
+ lineHeight: "30px",
+}
+const button: CSSProperties = {
+ backgroundColor: "#007ee6",
+ borderRadius: "4px",
+ color: "#fff",
+ fontSize: "15px",
+ textDecoration: "none",
+ textAlign: "center" as const,
+ display: "block",
+ width: "210px",
+ padding: "14px 7px",
+};
+
+const anchor: CSSProperties = {
+ textDecoration: "underline",
+};
+
+export const styles: Record = {
+ text,
+ headingText: headingText,
+ button,
+ anchor,
+}
+
+export type CreateEmailControlSchemaProps = {
+ defaultEmailSubject: string;
+} & ZodRawShape;
+
+export function createEmailControlSchema({
+ defaultEmailSubject,
+ ...rest
+}: CreateEmailControlSchemaProps) {
+ return z.object({
+ emailSubject: z.string().default(defaultEmailSubject),
+ ...rest,
+ });
+}
diff --git a/novu/bridge/app/novu/emails/novu-onboarding-email.tsx b/novu/bridge/app/novu/emails/novu-onboarding-email.tsx
deleted file mode 100644
index 6dcff5dca..000000000
--- a/novu/bridge/app/novu/emails/novu-onboarding-email.tsx
+++ /dev/null
@@ -1,157 +0,0 @@
-import React from "react";
-import {
- Body,
- Button,
- CodeInline,
- Column,
- Container,
- Head,
- Heading,
- Html,
- Img,
- Preview,
- render,
- Row,
- Section,
- Tailwind,
- Text,
-} from "@react-email/components";
-
-import { ControlSchema, PayloadSchema } from "../workflows";
-
-type NovuWelcomeEmailProps = ControlSchema & PayloadSchema;
-
-export const NovuWelcomeEmail = ({
- components,
- userImage,
- teamImage,
- arrowImage,
- showHeader,
-}: NovuWelcomeEmailProps) => {
- return (
-
-
- Novu Welcome
-
-
- {showHeader ? (
-
- ) : null}
-
-
- {components?.map((component, componentIndex) => {
- return (
-
- {component.type === "heading" ? (
-
- ) : null}
-
- {component.type === "button" ? (
-
- ) : null}
-
- {component.type === "text" ? (
-
- ) : null}
-
- {component.type === "users" ? (
-
-
-
- {component.text}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ) : null}
- {component.type === "code" ? (
-
- ) : null}
-
- );
- })}
-
-
-
-
- Powered by Novu, the Code-First Notification Infrastructure
-
-
-
-
-
- );
-};
-
-export default NovuWelcomeEmail;
-
-export function renderEmail(controls: ControlSchema, payload: PayloadSchema) {
- return render();
-}
diff --git a/novu/bridge/app/novu/workflows/expose/download-link.ts b/novu/bridge/app/novu/workflows/expose/download-link.tsx
similarity index 62%
rename from novu/bridge/app/novu/workflows/expose/download-link.ts
rename to novu/bridge/app/novu/workflows/expose/download-link.tsx
index 32b093aa9..aa13cfdf9 100644
--- a/novu/bridge/app/novu/workflows/expose/download-link.ts
+++ b/novu/bridge/app/novu/workflows/expose/download-link.tsx
@@ -1,5 +1,7 @@
import {workflow} from "@novu/framework";
import {z} from "zod";
+import {render} from "@react-email/components";
+import CTAEmail from "@/app/novu/emails/CTAEmail";
export const exposeDownloadLink = workflow(
"expose-download-link",
@@ -7,7 +9,12 @@ export const exposeDownloadLink = workflow(
await step.email("Email", async () => {
return {
subject: `Your download link is ready!`,
- body: `You can download your file from the following link: ${payload.downloadUrl}`,
+ body: render(
+ ),
};
});
},
diff --git a/novu/bridge/app/novu/workflows/expose/index.ts b/novu/bridge/app/novu/workflows/expose/index.ts
new file mode 100644
index 000000000..49ddb11f1
--- /dev/null
+++ b/novu/bridge/app/novu/workflows/expose/index.ts
@@ -0,0 +1,2 @@
+export * from "./zippy-download-link";
+export * from "./download-link";
diff --git a/novu/bridge/app/novu/workflows/expose/zippy-download-link.tsx b/novu/bridge/app/novu/workflows/expose/zippy-download-link.tsx
new file mode 100644
index 000000000..8eb9af970
--- /dev/null
+++ b/novu/bridge/app/novu/workflows/expose/zippy-download-link.tsx
@@ -0,0 +1,38 @@
+import {workflow} from "@novu/framework";
+import {z} from "zod";
+import {
+ render,
+} from "@react-email/components";
+import CTAEmail, {createCTAEmailControlSchema} from "@/app/novu/emails/CTAEmail";
+
+export const exposeZippyDownloadLink = workflow(
+ 'expose-zippy-download-link',
+ async ({step, payload}) => {
+ await step.email("Email", async (controls) => {
+ return {
+ subject: controls.emailSubject,
+ body: render(
+ ),
+ };
+ }, {
+ controlSchema: createCTAEmailControlSchema({
+ defaultEmailSubject: 'Your file is ready!',
+ defaultIntroText: 'You can download your file from the following link:',
+ })
+ });
+ },
+ {
+ payloadSchema: z.object({
+ downloadUrl: z
+ .string()
+ .describe("The URL link to download the file"),
+ locale: z
+ .string()
+ .describe("The user's locale"),
+ })
+ },
+);
diff --git a/novu/bridge/app/novu/workflows/index.ts b/novu/bridge/app/novu/workflows/index.ts
index f5f5b1874..f39dabcb0 100644
--- a/novu/bridge/app/novu/workflows/index.ts
+++ b/novu/bridge/app/novu/workflows/index.ts
@@ -1,3 +1,2 @@
-export * from "./welcome-onboarding-email";
export * from "./uploader/commit-acknowledged";
-export * from "./expose/download-link";
+export * from "./expose";
diff --git a/novu/bridge/app/novu/workflows/welcome-onboarding-email/index.ts b/novu/bridge/app/novu/workflows/welcome-onboarding-email/index.ts
deleted file mode 100644
index bdb493600..000000000
--- a/novu/bridge/app/novu/workflows/welcome-onboarding-email/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from "./schemas";
-export * from "./types";
-export * from "./workflow";
diff --git a/novu/bridge/app/novu/workflows/welcome-onboarding-email/schemas.ts b/novu/bridge/app/novu/workflows/welcome-onboarding-email/schemas.ts
deleted file mode 100644
index 34376685b..000000000
--- a/novu/bridge/app/novu/workflows/welcome-onboarding-email/schemas.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-import { z } from "zod";
-
-// Learn more about zod at the official website: https://zod.dev/
-export const payloadSchema = z.object({
- inAppSubject: z
- .string()
- .describe("The subject of the notification")
- .default("**Welcome to Novu!**"),
- inAppBody: z
- .string()
- .describe("The body of the notification")
- .default("This is an in-app notification powered by Novu."),
- inAppAvatar: z
- .string()
- .describe("The avatar of the notification")
- .default("https://avatars.githubusercontent.com/u/77433905?s=200&v=4"),
- teamImage: z
- .string()
- .url()
- .default(
- "https://images.spr.so/cdn-cgi/imagedelivery/j42No7y-dcokJuNgXeA0ig/dca73b36-cf39-4e28-9bc7-8a0d0cd8ac70/standalone-gradient2x_2/w=128,quality=90,fit=scale-down",
- ),
- userImage: z
- .string()
- .url()
- .default(
- "https://react-email-demo-48zvx380u-resend.vercel.app/static/vercel-user.png",
- ),
- arrowImage: z
- .string()
- .url()
- .default(
- "https://react-email-demo-bdj5iju9r-resend.vercel.app/static/vercel-arrow.png",
- ),
-});
-
-export const emailControlSchema = z.object({
- subject: z.string().default("A Successful Test on Novu!"),
- showHeader: z.boolean().default(true),
- components: z
- .array(
- z.object({
- type: z.enum(["heading", "text", "button", "code", "users"]),
- text: z.string().default(""),
- align: z.enum(["left", "center", "right"]).default("left"),
- }),
- )
- .default([
- {
- type: "heading",
- text: "Welcome to Novu",
- align: "center",
- },
- {
- type: "text",
- text: "Congratulations on receiving your first notification email from Novu! Join the hundreds of thousands of developers worldwide who use Novu to build notification platforms for their products.",
- align: "left",
- },
- {
- type: "users",
- align: "center",
- text: "",
- },
- {
- type: "text",
- text: "Ready to get started? Click on the button below, and you will see first-hand how easily you can edit this email content.",
- align: "left",
- },
- {
- type: "button",
- text: "Edit Email",
- align: "center",
- },
- ]),
-});
diff --git a/novu/bridge/app/novu/workflows/welcome-onboarding-email/types.ts b/novu/bridge/app/novu/workflows/welcome-onboarding-email/types.ts
deleted file mode 100644
index 2953a6d3f..000000000
--- a/novu/bridge/app/novu/workflows/welcome-onboarding-email/types.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { z } from "zod";
-import { payloadSchema, emailControlSchema } from "./schemas";
-
-export type PayloadSchema = z.infer;
-export type ControlSchema = z.infer;
diff --git a/novu/bridge/app/novu/workflows/welcome-onboarding-email/workflow.ts b/novu/bridge/app/novu/workflows/welcome-onboarding-email/workflow.ts
deleted file mode 100644
index 890632608..000000000
--- a/novu/bridge/app/novu/workflows/welcome-onboarding-email/workflow.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { workflow } from "@novu/framework";
-import { renderEmail } from "../../emails/novu-onboarding-email";
-import { emailControlSchema, payloadSchema } from "./schemas";
-
-export const welcomeOnboardingEmail = workflow(
- "welcome-onboarding-email",
- async ({ step, payload }) => {
- await step.inApp("In-App Step", async () => {
- return {
- subject: payload.inAppSubject,
- body: payload.inAppBody,
- avatar: payload.inAppAvatar,
- };
- });
- },
- {
- payloadSchema,
- },
-);