Skip to content

Commit 1de2658

Browse files
authored
Merge pull request #620 from johanbook/blog-post-event-handler
feat(web-ui): add blog post event handler
2 parents e1be2a6 + f79b771 commit 1de2658

File tree

13 files changed

+67
-48
lines changed

13 files changed

+67
-48
lines changed

services/api/src/core/notifications/application/contracts/dtos/notification-meta.dto.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export enum NotificationEventNames {
77

88
export class NotificationWebSocketDetails {
99
description!: string;
10-
data?: NotificationData;
10+
data!: NotificationData;
1111
message!: string;
1212
resourcePath!: string;
1313
type!: NotificationEventsConstants;

services/api/src/core/notifications/client/gateways/notification.gateway.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ export class NotificationGateway
6363
return false;
6464
}
6565

66-
const notificationDto = map(NotificationWebSocketDetails, notification);
66+
const notificationDto = map(NotificationWebSocketDetails, {
67+
data: {},
68+
...notification,
69+
});
6770

6871
socket.emit(NotificationEventNames.Notification, notificationDto);
6972

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export abstract class BaseEvent {}
2+
3+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
4+
type Constructor<T> = new (...props: any) => T;
5+
6+
export function dispatchEvent<T extends BaseEvent>(event: T) {
7+
const customEvent = new CustomEvent(event.constructor.name, {
8+
detail: event,
9+
});
10+
document.dispatchEvent(customEvent);
11+
}
12+
13+
export function addEventListener<T extends BaseEvent>(
14+
event: Constructor<T>,
15+
onEvent: (event: T) => void
16+
): void {
17+
document.addEventListener(event.name, (event) => {
18+
const customEvent = event as CustomEvent<T>;
19+
onEvent(customEvent.detail);
20+
});
21+
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1 @@
1-
export enum NotificationEventsConstants {
2-
ADDED_TO_ORGANIZATION = "added_to_organization",
3-
NEW_BLOG_POST = "new_blog_post",
4-
NEW_BLOG_POST_COMMENT = "new_blog_post_comment",
5-
NEW_CHAT_MESSAGE = "new_chat_message",
6-
}
1+
export { NotificationWebSocketDetailsTypeEnum as NotificationEventsConstants } from "src/api";

services/web-ui/src/core/notifications/hooks/useHandleNotification.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import React from "react";
1+
import { useContext, useEffect } from "react";
22

33
import { NotificationEventsConstants } from "../constants/notification-events.constants";
44
import { NotificationContext } from "../notification.provider";
5-
import { INotification } from "../types/notification.interface";
5+
import { INotification } from "../types";
66

77
interface UseHandleNotificationProps<
88
T extends NotificationEventsConstants,
@@ -21,9 +21,9 @@ export function useHandleNotification<
2121
onNotification,
2222
type,
2323
}: UseHandleNotificationProps<T, V>): void {
24-
const notificationHandler = React.useContext(NotificationContext);
24+
const notificationHandler = useContext(NotificationContext);
2525

26-
React.useEffect(() => {
26+
useEffect(() => {
2727
if (!notificationHandler) {
2828
throw new Error(
2929
"Unable to register notification handler. Make sure the NotificationProvider is correctly setup."

services/web-ui/src/core/notifications/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export { NotificationEventsConstants } from "./constants/notification-events.con
22
export { useHandleNotification } from "./hooks/useHandleNotification";
33
export { useNotifications } from "./hooks/useNotifications";
44
export { NotificationProvider } from "./notification.provider";
5+
export { INotification } from "./types";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { BaseEvent } from "src/core/events";
2+
3+
import { INotification } from "./types";
4+
5+
export class NotificationEvent extends BaseEvent {
6+
constructor(public readonly notification: INotification) {
7+
super();
8+
}
9+
}

services/web-ui/src/core/notifications/notificationEvent.handler.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import { v4 as uuid } from "uuid";
44
import { NotificationMetaDetailsWsEventNamesEnum } from "src/api";
55
import { Logger } from "src/core/logging";
66

7+
import { dispatchEvent } from "../events";
78
import { NotificationEventsConstants } from "./constants/notification-events.constants";
8-
import { INotification } from "./types/notification.interface";
9+
import { NotificationEvent } from "./notification.event";
10+
import { INotification } from "./types";
911

1012
const eventName = NotificationMetaDetailsWsEventNamesEnum.Notification;
1113

@@ -31,10 +33,10 @@ export class NotificationEventHandler {
3133
NotificationEventsConstants,
3234
Record<string, Handler>
3335
> = {
34-
[NotificationEventsConstants.ADDED_TO_ORGANIZATION]: {},
35-
[NotificationEventsConstants.NEW_BLOG_POST]: {},
36-
[NotificationEventsConstants.NEW_BLOG_POST_COMMENT]: {},
37-
[NotificationEventsConstants.NEW_CHAT_MESSAGE]: {},
36+
[NotificationEventsConstants.AddedToOrganization]: {},
37+
[NotificationEventsConstants.NewBlogPost]: {},
38+
[NotificationEventsConstants.NewBlogPostComment]: {},
39+
[NotificationEventsConstants.NewChatMessage]: {},
3840
};
3941

4042
private readonly socket: Socket;
@@ -79,10 +81,8 @@ export class NotificationEventHandler {
7981

8082
this.logger.trace("Received notification", { notification });
8183

82-
const event = new CustomEvent(eventName, {
83-
detail: notification,
84-
});
85-
document.dispatchEvent(event);
84+
const event = new NotificationEvent(notification);
85+
dispatchEvent(event);
8686

8787
let eventWasHandled = false;
8888

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { NotificationWebSocketDetails } from "src/api";
2+
3+
export type INotification = NotificationWebSocketDetails;

services/web-ui/src/core/notifications/types/notification.interface.ts

-15
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { addEventListener } from "src/core/events";
2+
import { NotificationEvent } from "src/core/notifications/notification.event";
3+
import { CacheKeysConstants } from "src/core/query";
4+
import { QUERY_CLIENT } from "src/queryQlient";
5+
6+
addEventListener(NotificationEvent, (event) => {
7+
if (event.notification.type === "new_blog_post") {
8+
QUERY_CLIENT.invalidateQueries([CacheKeysConstants.BlogPosts]);
9+
}
10+
});

services/web-ui/src/pages/BlogPostListPage/BlogPostListPage.container.tsx

+1-10
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ import { blogsApi } from "src/apis";
66
import { ErrorMessage } from "src/components/ui/ErrorMessage";
77
import { useTranslation } from "src/core/i18n";
88
import { InteractionObserver } from "src/core/infinite-scroll";
9-
import {
10-
NotificationEventsConstants,
11-
useHandleNotification,
12-
} from "src/core/notifications";
139
import { CacheKeysConstants, useInfiniteQuery } from "src/core/query";
1410

1511
import { BlogPostPageComponent } from "./BlogPostListPage.component";
@@ -22,7 +18,7 @@ const ITEMS_PER_PAGE = 10;
2218
export function BlogPostListPageContainer(): ReactElement {
2319
const { t } = useTranslation("blog");
2420

25-
const { error, data, isLoading, fetchNextPage, hasNextPage, refetch } =
21+
const { error, data, isLoading, fetchNextPage, hasNextPage } =
2622
useInfiniteQuery(
2723
[CacheKeysConstants.BlogPosts],
2824
({ pageParam = 0 }) =>
@@ -41,11 +37,6 @@ export function BlogPostListPageContainer(): ReactElement {
4137
}
4238
);
4339

44-
useHandleNotification({
45-
onNotification: () => refetch(),
46-
type: NotificationEventsConstants.NEW_BLOG_POST,
47-
});
48-
4940
if (error) {
5041
return (
5142
<>

services/web-ui/src/pages/ChatPage/ChatPage.container.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ export function ChatPageContainer(): React.ReactElement {
2525
);
2626

2727
useHandleNotification({
28-
onCondition: (event) => String(event.data.senderId) === id,
28+
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
29+
onCondition: (event: any) => String(event.data.senderId) === id,
2930
onNotification: () => refetch(),
30-
type: NotificationEventsConstants.NEW_CHAT_MESSAGE,
31+
type: NotificationEventsConstants.NewChatMessage,
3132
});
3233

3334
if (!id) {

0 commit comments

Comments
 (0)