Skip to content

Commit 46198a8

Browse files
authored
enhance(notifications): enhance notification handling and styling (#24)
- Updated the NotificationContent component to handle milestone due reminders, providing specific messages based on the notification's status. - Adjusted the NotificationBell component's styling for system announcements to improve visual consistency. - Modified emailWorker to support raw HTML content for system announcements, enhancing email formatting options. - Improved the CODE_OF_CONDUCT.md by clarifying reporting guidelines and updating contact information formatting.
1 parent 761a7eb commit 46198a8

4 files changed

Lines changed: 82 additions & 15 deletions

File tree

CODE_OF_CONDUCT.md

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ representative at an online or offline event.
6060

6161
Instances of abusive, harassing, or otherwise unacceptable behavior may be
6262
reported to the community leaders responsible for enforcement at
63-
conduct@testplanit.com. All complaints will be reviewed and investigated promptly
63+
<conduct@testplanit.com>. All complaints will be reviewed and investigated promptly
6464
and fairly.
6565

6666
All community leaders are obligated to respect the privacy and security of the
@@ -150,25 +150,27 @@ In addition to the Contributor Covenant, the TestPlanIt community upholds these
150150
### Reporting Guidelines
151151

152152
When reporting violations, please include:
153-
- Date and time of the incident
154-
- Location (GitHub issue, Discord channel, etc.)
155-
- Description of the incident
156-
- Screenshots or links if applicable
157-
- Any additional context
153+
154+
* Date and time of the incident
155+
* Location (GitHub issue, Discord channel, etc.)
156+
* Description of the incident
157+
* Screenshots or links if applicable
158+
* Any additional context
158159

159160
Reports will be handled with discretion and confidentiality.
160161

161162
### Response Time
162163

163164
The TestPlanIt team commits to:
164-
- Acknowledging receipt of reports within 24 hours
165-
- Providing an initial assessment within 72 hours
166-
- Resolving issues within 7 days when possible
165+
166+
* Acknowledging receipt of reports within 24 hours
167+
* Providing an initial assessment within 72 hours
168+
* Resolving issues within 7 days when possible
167169

168170
### Appeals Process
169171

170-
If you disagree with an enforcement decision, you may appeal by emailing appeals@testplanit.com within 14 days of the decision. Appeals will be reviewed by a different team member when possible.
172+
If you disagree with an enforcement decision, you may appeal by emailing <appeals@testplanit.com> within 14 days of the decision. Appeals will be reviewed by a different team member when possible.
171173

172174
---
173175

174-
*Last updated: November 2024*
176+
#### *Last updated: November 2024*

testplanit/components/NotificationBell.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function NotificationItem({
8080
className={cn(
8181
"p-3 border-b last:border-0 hover:bg-muted/50 transition-colors",
8282
!notification.isRead && "bg-primary/20",
83-
notification.type === "SYSTEM_ANNOUNCEMENT" && "bg-blue-50 dark:bg-blue-950/20"
83+
!notification.isRead && notification.type === "SYSTEM_ANNOUNCEMENT" && "bg-accent"
8484
)}
8585
data-notification-item
8686
data-state={notification.isRead ? "read" : "unread"}

testplanit/components/NotificationContent.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export function NotificationContent({
2121
}: NotificationContentProps) {
2222
const locale = useLocale();
2323
const t = useTranslations("components.notifications.content");
24+
const tMilestones = useTranslations("milestones.notifications");
2425

2526
// Get notification data (Prisma automatically deserializes JSON fields)
2627
const data = notification.data || {};
@@ -61,6 +62,7 @@ export function NotificationContent({
6162
<ProjectNameCell
6263
projectId={data.projectId}
6364
value={data.projectName}
65+
size="sm"
6466
/>
6567
</div>
6668
</div>
@@ -116,6 +118,7 @@ export function NotificationContent({
116118
<ProjectNameCell
117119
projectId={group.projectId}
118120
value={group.projectName}
121+
size="sm"
119122
/>
120123
</div>
121124
</div>
@@ -159,6 +162,7 @@ export function NotificationContent({
159162
<ProjectNameCell
160163
projectId={data.projectId}
161164
value={data.projectName}
165+
size="sm"
162166
/>
163167
</div>
164168
</div>
@@ -254,6 +258,7 @@ export function NotificationContent({
254258
<ProjectNameCell
255259
projectId={data.projectId}
256260
value={data.projectName}
261+
size="sm"
257262
/>
258263
</div>
259264
</div>
@@ -270,6 +275,63 @@ export function NotificationContent({
270275
);
271276
}
272277

278+
// Handle milestone due reminders
279+
if (notification.type === "MILESTONE_DUE_REMINDER") {
280+
// Check if we have the data structure with all IDs
281+
if (data.projectId && data.milestoneId) {
282+
const milestoneLink = `/projects/milestones/${data.projectId}/${data.milestoneId}`;
283+
const isOverdue = data.isOverdue;
284+
const dueDate = data.dueDate
285+
? new Date(data.dueDate).toLocaleDateString(locale)
286+
: "";
287+
288+
return (
289+
<div className="space-y-2">
290+
<h4 className="font-medium text-sm">
291+
{isOverdue ? t("milestoneOverdueTitle") : t("milestoneDueSoonTitle")}
292+
</h4>
293+
<div className="text-sm text-muted-foreground space-y-1">
294+
<div className="flex items-center gap-1 flex-wrap">
295+
<Link
296+
href={milestoneLink}
297+
className="font-medium text-primary hover:underline inline-flex items-center gap-1"
298+
>
299+
<MilestoneNameDisplay
300+
milestone={{
301+
id: data.milestoneId,
302+
name: data.milestoneName,
303+
milestoneTypeIconName: data.milestoneTypeIconName,
304+
}}
305+
showIcon={true}
306+
/>
307+
<ExternalLink className="h-3 w-3" />
308+
</Link>
309+
<span>{t("inProject")}</span>
310+
<ProjectNameCell
311+
projectId={data.projectId}
312+
value={data.projectName}
313+
size="sm"
314+
/>
315+
</div>
316+
<div className="text-xs">
317+
{isOverdue
318+
? tMilestones("overdue", { name: data.milestoneName, dueDate })
319+
: tMilestones("dueSoon", { name: data.milestoneName, dueDate })}
320+
</div>
321+
</div>
322+
</div>
323+
);
324+
}
325+
326+
// Fallback for old notifications without full data
327+
return (
328+
<div className="space-y-1">
329+
<h4 className="font-medium text-sm">{notification.title}</h4>
330+
<p className="text-sm text-muted-foreground">{notification.message}</p>
331+
</div>
332+
);
333+
}
334+
273335
// Handle system announcements
274336
if (notification.type === "SYSTEM_ANNOUNCEMENT") {
275337
const hasRichContent = notification.data?.richContent;
@@ -278,7 +340,7 @@ export function NotificationContent({
278340
return (
279341
<div className="space-y-2">
280342
<div className="flex items-center gap-2">
281-
<Megaphone className="h-4 w-4 text-blue-500" />
343+
<Megaphone className="h-4 w-4 text-primary" />
282344
<h4 className="font-medium text-sm">{notification.title}</h4>
283345
</div>
284346
<div className="space-y-1">

testplanit/workers/emailWorker.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,11 @@ const processor = async (job: Job) => {
143143
}
144144
}
145145
} else if (notification.type === "SYSTEM_ANNOUNCEMENT") {
146-
// For system announcements, check if we have rich content
147-
if (data.richContent && isTipTapContent(data.richContent)) {
146+
// For system announcements, check if we have rich content or raw HTML
147+
if (data.htmlContent) {
148+
// Use raw HTML content (e.g., from upgrade notifications)
149+
htmlMessage = data.htmlContent;
150+
} else if (data.richContent && isTipTapContent(data.richContent)) {
148151
htmlMessage = tiptapToHtml(data.richContent);
149152
}
150153
// Add sender info to the message if not using HTML

0 commit comments

Comments
 (0)