Skip to content

Commit 7c199af

Browse files
rajat1saxenaRajat
andauthored
Notifications system (#727)
* Notifications * Updated lockfile --------- Co-authored-by: Rajat <hi@rajatsaxena.dev>
1 parent ae04384 commit 7c199af

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+3515
-729
lines changed

AGENTS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
- When working with forms, always use refs to keep the current state of the form's data and use it to enable/disable the form submit button.
1010
- Check the name field inside each package's package.json to confirm the right name—skip the top-level one.
1111
- While working with forms, always use zod and react-hook-form to validate the form. Take reference implementation from `apps/web/components/admin/settings/sso/new.tsx`.
12+
- `packages/scripts` is meant to contain maintenance scripts which can be re-used over and over, not one-off migrations. One-off migrations should be in `apps/web/.migrations`.
13+
- `packages/utils` should be the place for containing utilities which are used in more than one package.
14+
- `apps/web` and `apps/queue` can share business logic and db models. Common business logic should be moved to `packages/common-logic`. Common DB related functionality should be moved to `packages/orm-models`.
15+
- For migrations (located in `apps/web/.migrations`), follow the "Gold Standard" pattern:
16+
- Use **Cursors** (`.cursor()`) to stream data from MongoDB, ensuring the script remains memory-efficient regardless of dataset size.
17+
- Use **Batching** with `bulkWrite` (e.g., batches of 500) to maximize performance and minimize network roundtrips.
18+
- Ensure **Idempotency** (safe to re-run) by using upserts or `$setOnInsert` where applicable.
1219

1320
## Documentation tips
1421

161 KB
Loading

apps/docs/src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export const SIDEBAR: Sidebar = {
122122
Users: [
123123
{ text: "Introduction", link: "en/users/introduction" },
124124
{ text: "Manage users", link: "en/users/manage" },
125+
{ text: "Customize notifications", link: "en/users/notifications" },
125126
{ text: "User permissions", link: "en/users/permissions" },
126127
{ text: "Filter users", link: "en/users/filters" },
127128
{ text: "Segment users", link: "en/users/segments" },
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Customize notifications
3+
description: Customize app and email notifications
4+
layout: ../../../layouts/MainLayout.astro
5+
---
6+
7+
CourseLit lets each user control how they receive notifications for different activities.
8+
9+
> This feature is currently in beta, which means you may encounter bugs. Please report them in our <a href="https://discord.com/invite/GR4bQsN" target="_blank">Discord</a> group if you run into any issues.
10+
11+
## Open notification settings
12+
13+
1. Log in to your school.
14+
2. Open `Dashboard`.
15+
3. Click on your avatar (in the bottom-left corner) to open up the user menu.
16+
4. Click on `Notifications`.
17+
18+
![Notifications hub](/assets/users/notifications-hub.png)
19+
20+
## Understand notification groups
21+
22+
Notification preferences are shown in groups based on activity type:
23+
24+
- **General**
25+
- **Product**
26+
- **User**
27+
- **Community**
28+
29+
General notification preferences are available to all users.
30+
31+
## Choose channels
32+
33+
Each activity row has two channels:
34+
35+
- **App**: sends notifications inside your CourseLit dashboard.
36+
- **Email**: sends notifications to your email inbox.
37+
38+
Tick or untick the checkboxes to turn each channel on or off for that activity. Changes are saved immediately.
39+
40+
## Stuck somewhere?
41+
42+
We are always here for you. Come chat with us in our <a href="https://discord.com/invite/GR4bQsN" target="_blank">Discord</a> channel or send a tweet at <a href="https://twitter.com/courselit" target="_blank">@CourseLit</a>.

apps/queue/AGENTS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
## Development Tips
2+
3+
- The code is organised domain wise. All related resources for a domain are kept in a folder under `src/<domain-name>`.
4+
- Inside `src/<domain-name>` folder, you will find `model`, `queue`, `routes`, `services`, `utils` folders/files.
5+
- `model` contains the mongoose models for the domain.
6+
- `queue` contains the bullmq queues for the domain.
7+
- `worker` contains the bullmq workers for the domain.
8+
- `routes` contains the express routes for the domain.
9+
- `services` contains the services for the domain.
10+
- `utils` contains the utils for the domain.

apps/queue/jest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const config = {
77
"@courselit/common-logic": "<rootDir>/../../packages/common-logic/src",
88
"@courselit/common-models":
99
"<rootDir>/../../packages/common-models/src",
10+
"@courselit/orm-models": "<rootDir>/../../packages/orm-models/src",
1011
"@courselit/email-editor":
1112
"<rootDir>/__mocks__/@courselit/email-editor.ts",
1213
nanoid: "<rootDir>/__mocks__/nanoid.ts",

apps/queue/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
{
22
"name": "@courselit/queue",
33
"version": "0.25.10",
4+
"type": "module",
45
"private": true,
56
"packageManager": "pnpm@9.14.2",
67
"scripts": {
78
"build": "tsup",
89
"tsc:build": "tsc",
910
"check-types": "tsc --noEmit",
10-
"start": "node dist/index.mjs",
11+
"start": "node dist/index.js",
1112
"build:dev": "tsup --watch",
12-
"dev": "node --env-file .env.local --watch dist/index.mjs"
13+
"dev": "node --watch --env-file .env.local --import tsx src/index.ts"
1314
},
1415
"dependencies": {
1516
"@courselit/common-logic": "workspace:^",
1617
"@courselit/common-models": "workspace:^",
1718
"@courselit/email-editor": "workspace:^",
19+
"@courselit/orm-models": "workspace:^",
1820
"@courselit/utils": "workspace:^",
1921
"@types/jsdom": "^21.1.7",
2022
"bullmq": "^4.14.0",
@@ -37,6 +39,7 @@
3739
"ts-jest": "^29.4.4",
3840
"tsconfig": "workspace:^",
3941
"tsup": "^7.2.0",
42+
"tsx": "^4.21.0",
4043
"typescript": "^5.9.3",
4144
"typescript-eslint": "^8.46.4"
4245
}

apps/queue/src/domain/handler.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
import type { MailJob } from "./model/mail-job";
2-
import notificationQueue from "./notification-queue";
32
import mailQueue from "./queue";
43

5-
export async function addMailJob({ to, subject, body, from }: MailJob) {
4+
export async function addMailJob({
5+
to,
6+
subject,
7+
body,
8+
from,
9+
headers,
10+
}: MailJob) {
611
for (const recipient of to) {
712
await mailQueue.add("mail", {
813
to: recipient,
914
subject,
1015
body,
1116
from,
17+
headers,
1218
});
1319
}
1420
}
15-
16-
export async function addNotificationJob(notification) {
17-
await notificationQueue.add("notification", notification);
18-
}

apps/queue/src/domain/model/mail-job.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export const MailJob = z.object({
55
from: z.string(),
66
subject: z.string(),
77
body: z.string(),
8+
headers: z.record(z.string()).optional(),
89
});
910

1011
export type MailJob = z.infer<typeof MailJob>;

apps/queue/src/domain/model/notification.ts

Lines changed: 0 additions & 89 deletions
This file was deleted.

0 commit comments

Comments
 (0)