Skip to content

Commit f9eadad

Browse files
authored
Merge pull request gitroomhq#1 from iampearceman/notifications
Notifications
2 parents 8788461 + 1738183 commit f9eadad

File tree

10 files changed

+1472
-127
lines changed

10 files changed

+1472
-127
lines changed

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ AUTH_TRUST_HOST=""
66
MAILCHIMP_API_KEY=""
77
MAILCHIMP_LIST_ID=""
88
REDIS_URL=""
9+
NOVU_SECRET_KEY=""
10+
NOVU_BRIDGE_URL=""
11+

.github/workflows/novu.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# .github/workflows/novu.yml
2+
name: Novu Sync
3+
4+
on:
5+
workflow_dispatch:
6+
7+
jobs:
8+
deploy:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Sync State to Novu
12+
uses: novuhq/actions-novu-sync@v2
13+
with:
14+
secret-key: ${{ secrets.NOVU_SECRET_KEY }}
15+
bridge-url: <YOUR_DEPLOYED_BRIDGE_URL>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { serve } from "@novu/framework/next";
2+
import { workflows } from "../../workflows/all-workflows";
3+
4+
// the workflows collection can hold as many workflow definitions as you need
5+
export const { GET, POST, OPTIONS } = serve({
6+
workflows: workflows,
7+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { chatNotification } from "./chat-notification/workflow";
2+
3+
export const workflows = [
4+
chatNotification,
5+
];

apps/frontend/src/app/workflows/chat-notification/email-template/sample-email.tsx

Whitespace-only changes.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { z } from "zod";
2+
3+
export const payloadSchema = z.object({
4+
// Notification Fields
5+
Subject: z.string().default("New Notification"),
6+
Body: z.string().default("You have a new notification."),
7+
showInAppAvatar: z.boolean().default(true),
8+
Avatar: z.string().url().optional().default("https://example.com/default-avatar.png"),
9+
10+
// Primary Action Fields
11+
enablePrimaryAction: z.boolean().default(false),
12+
inAppPrimaryActionLabel: z.string().optional().default("View"),
13+
inAppPrimaryActionUrl: z.string().url().optional().default("https://example.com/action"),
14+
15+
// Secondary Action Fields
16+
enableSecondaryAction: z.boolean().default(false),
17+
inAppSecondaryActionLabel: z.string().optional().default("Dismiss"),
18+
inAppSecondaryActionUrl: z.string().url().optional().default("https://example.com/dismiss"),
19+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { workflow } from '@novu/framework';
2+
import { payloadSchema } from './payloadSchema';
3+
// import { renderEmail } from './email-template/sample-email';
4+
5+
// Define the name for your workflow
6+
const workflowName = 'chat-notification';
7+
8+
// Define the workflow
9+
export const chatNotification = workflow(
10+
workflowName,
11+
async ({ step, payload }) => {
12+
// Define the step for the workflow
13+
// -----------------------------------in-app step-------------------------------------------------------------------------
14+
await step.inApp('In App Step', async () => {
15+
const result: {
16+
subject: string;
17+
body: string;
18+
avatar?: string;
19+
primaryAction?: {
20+
label: string;
21+
url: string;
22+
};
23+
secondaryAction?: {
24+
label: string;
25+
url: string;
26+
};
27+
} = {
28+
subject: payload.Subject,
29+
body: payload.Body,
30+
};
31+
32+
if (payload.showInAppAvatar) {
33+
result.avatar = payload.Avatar;
34+
}
35+
36+
if (payload.enablePrimaryAction) {
37+
result.primaryAction = {
38+
label: payload.inAppPrimaryActionLabel,
39+
url: payload.inAppPrimaryActionUrl,
40+
};
41+
}
42+
43+
if (payload.enableSecondaryAction) {
44+
result.secondaryAction = {
45+
label: payload.inAppSecondaryActionLabel,
46+
url: payload.inAppSecondaryActionUrl,
47+
};
48+
}
49+
return result;
50+
});
51+
},
52+
{
53+
payloadSchema: payloadSchema,
54+
}
55+
);

apps/frontend/src/components/dashboard/chat.tsx

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { Button } from '@frontend/components/button';
44
import { FC, useCallback, useEffect, useRef, useState } from 'react';
5+
import { Novu } from '@novu/node';
56
import useSWR from 'swr';
67
import dayjs from 'dayjs';
78
import utc from 'dayjs/plugin/utc';
@@ -20,13 +21,35 @@ const SendMessage: FC<{ update: () => void }> = (props) => {
2021
const submit = useCallback(
2122
async (e: any) => {
2223
e.preventDefault();
23-
await fetch('/api/dashboard/messages', {
24-
method: 'POST',
25-
body: JSON.stringify({ message: value }),
26-
});
2724
if (value.length < 3) {
2825
return alert('You have to type at least 3 characters');
2926
}
27+
28+
const response = await fetch('/api/dashboard/messages', {
29+
method: 'POST',
30+
body: JSON.stringify({ message: value }),
31+
});
32+
const newMessage = await response.json();
33+
34+
// Trigger Novu notification
35+
const novu = new Novu(process.env['NOVU_SECRET_KEY']);
36+
await novu.trigger('chat-notification', {
37+
to: {
38+
subscriberId: '<user-subscriber-id>',
39+
email: '<user-email>' //optinal
40+
},
41+
payload: {
42+
id: newMessage.id,
43+
message: newMessage.message,
44+
createdAt: newMessage.createdAt,
45+
user: {
46+
name: newMessage.user.name,
47+
profilePicture: newMessage.user.profilePicture,
48+
handle: newMessage.user.handle
49+
}
50+
}
51+
});
52+
3053
setValue('');
3154
props.update();
3255
},

0 commit comments

Comments
 (0)