From e311d3d1cb04f74f65ffdeeae95fd9b582c220ec Mon Sep 17 00:00:00 2001 From: EYHN Date: Thu, 27 Mar 2025 02:10:49 +0000 Subject: [PATCH] feat(core): more notification type (#11209) --- .../core/src/components/notification/list.tsx | 219 ++++++++++++++++-- .../i18n/src/i18n-completenesses.json | 32 +-- packages/frontend/i18n/src/i18n.gen.ts | 64 +++++ packages/frontend/i18n/src/resources/en.json | 8 + 4 files changed, 292 insertions(+), 31 deletions(-) diff --git a/packages/frontend/core/src/components/notification/list.tsx b/packages/frontend/core/src/components/notification/list.tsx index 7d06ad007..bfbb38f2d 100644 --- a/packages/frontend/core/src/components/notification/list.tsx +++ b/packages/frontend/core/src/components/notification/list.tsx @@ -18,6 +18,9 @@ import type { InvitationAcceptedNotificationBodyType, InvitationBlockedNotificationBodyType, InvitationNotificationBodyType, + InvitationReviewApprovedNotificationBodyType, + InvitationReviewDeclinedNotificationBodyType, + InvitationReviewRequestNotificationBodyType, MentionNotificationBodyType, } from '@affine/graphql'; import { i18nTime, Trans, useI18n } from '@affine/i18n'; @@ -118,6 +121,12 @@ const NotificationItem = ({ notification }: { notification: Notification }) => { ) : type === NotificationType.InvitationBlocked ? ( + ) : type === NotificationType.InvitationReviewRequest ? ( + + ) : type === NotificationType.InvitationReviewDeclined ? ( + + ) : type === NotificationType.InvitationReviewApproved ? ( + ) : (
@@ -194,6 +203,189 @@ const MentionNotificationItem = ({ ); }; +const InvitationReviewRequestNotificationItem = ({ + notification, +}: { + notification: Notification; +}) => { + const notificationListService = useService(NotificationListService); + const { jumpToWorkspaceSettings } = useNavigateHelper(); + const t = useI18n(); + const body = notification.body as InvitationReviewRequestNotificationBodyType; + const memberInactived = !body.createdByUser; + const workspaceInactived = !body.workspace; + const handleClick = useCallback(() => { + notificationListService.readNotification(notification.id).catch(err => { + console.error(err); + }); + if (!body.workspace?.id) { + return; + } + jumpToWorkspaceSettings(body.workspace.id, 'workspace:members'); + }, [body, jumpToWorkspaceSettings, notification, notificationListService]); + + return ( +
+ +
+ + + ), + 2: , + }} + values={{ + username: + body.createdByUser?.name ?? t['com.affine.inactive-member'](), + workspaceName: + body.workspace?.name ?? t['com.affine.inactive-workspace'](), + }} + /> + +
+ {i18nTime(notification.createdAt, { + relative: true, + })} +
+
+ +
+ ); +}; + +const InvitationReviewDeclinedNotificationItem = ({ + notification, +}: { + notification: Notification; +}) => { + const t = useI18n(); + const body = + notification.body as InvitationReviewDeclinedNotificationBodyType; + const memberInactived = !body.createdByUser; + const workspaceInactived = !body.workspace; + + return ( +
+ +
+ + + ), + 2: , + }} + values={{ + username: + body.createdByUser?.name ?? t['com.affine.inactive-member'](), + workspaceName: + body.workspace?.name ?? t['com.affine.inactive-workspace'](), + }} + /> + +
+ {i18nTime(notification.createdAt, { + relative: true, + })} +
+
+ +
+ ); +}; + +const InvitationReviewApprovedNotificationItem = ({ + notification, +}: { + notification: Notification; +}) => { + const notificationListService = useService(NotificationListService); + const { jumpToPage } = useNavigateHelper(); + const t = useI18n(); + const body = + notification.body as InvitationReviewApprovedNotificationBodyType; + const memberInactived = !body.createdByUser; + const workspaceInactived = !body.workspace; + + const handleClick = useCallback(() => { + notificationListService.readNotification(notification.id).catch(err => { + console.error(err); + }); + if (!body.workspace?.id) { + return; + } + jumpToPage(body.workspace.id, 'all'); + }, [body, jumpToPage, notification, notificationListService]); + + return ( +
+ +
+ + + ), + 2: , + }} + values={{ + username: + body.createdByUser?.name ?? t['com.affine.inactive-member'](), + workspaceName: + body.workspace?.name ?? t['com.affine.inactive-workspace'](), + }} + /> + + {!workspaceInactived && ( + + )} +
+ {i18nTime(notification.createdAt, { + relative: true, + })} +
+
+ +
+ ); +}; + const InvitationAcceptedNotificationItem = ({ notification, }: { @@ -320,21 +512,6 @@ const InvitationNotificationItem = ({ const [isAccepting, setIsAccepting] = useState(false); const { jumpToPage } = useNavigateHelper(); - const WorkspaceNameWithIcon = useCallback( - ({ - children, - ...props - }: React.PropsWithChildren>) => { - return ( - - - {children} - - ); - }, - [] - ); - const handleReadAndOpenWorkspace = useCallback(() => { notificationListService.readNotification(notification.id).catch(err => { console.error(err); @@ -473,3 +650,15 @@ const DeleteButton = ({ /> ); }; + +const WorkspaceNameWithIcon = ({ + children, + ...props +}: React.PropsWithChildren>) => { + return ( + + + {children} + + ); +}; diff --git a/packages/frontend/i18n/src/i18n-completenesses.json b/packages/frontend/i18n/src/i18n-completenesses.json index b6b479bcd..b0ad28913 100644 --- a/packages/frontend/i18n/src/i18n-completenesses.json +++ b/packages/frontend/i18n/src/i18n-completenesses.json @@ -1,26 +1,26 @@ { - "ar": 94, + "ar": 93, "ca": 4, "da": 4, - "de": 94, - "el-GR": 94, + "de": 93, + "el-GR": 93, "en": 100, - "es-AR": 94, + "es-AR": 93, "es-CL": 95, - "es": 94, - "fa": 94, - "fr": 94, + "es": 93, + "fa": 93, + "fr": 93, "hi": 2, - "it-IT": 94, + "it-IT": 93, "it": 1, - "ja": 94, + "ja": 93, "ko": 59, - "pl": 94, - "pt-BR": 94, - "ru": 94, - "sv-SE": 94, - "uk": 94, + "pl": 93, + "pt-BR": 93, + "ru": 93, + "sv-SE": 93, + "uk": 93, "ur": 2, - "zh-Hans": 94, - "zh-Hant": 94 + "zh-Hans": 93, + "zh-Hant": 93 } diff --git a/packages/frontend/i18n/src/i18n.gen.ts b/packages/frontend/i18n/src/i18n.gen.ts index 7697ab33f..c58f82531 100644 --- a/packages/frontend/i18n/src/i18n.gen.ts +++ b/packages/frontend/i18n/src/i18n.gen.ts @@ -7107,6 +7107,14 @@ export function useAFFiNEI18N(): { * `No new notifications` */ ["com.affine.notification.empty"](): string; + /** + * `Open workspace` + */ + ["com.affine.notification.invitation-review-approved.open-workspace"](): string; + /** + * `Accept & Join` + */ + ["com.affine.notification.invitation.accept"](): string; /** * `Tips` */ @@ -8474,6 +8482,62 @@ export const TypedTrans: { ["1"]: JSX.Element; ["2"]: JSX.Element; }>>; + /** + * `<1>{{username}} has accept your invitation` + */ + ["com.affine.notification.invitation-accepted"]: ComponentType>; + /** + * `<1>{{username}} has requested to join <2>{{workspaceName}}` + */ + ["com.affine.notification.invitation-review-request"]: ComponentType, { + ["1"]: JSX.Element; + ["2"]: JSX.Element; + }>>; + /** + * `<1>{{username}} has declined your request to join <2>{{workspaceName}}` + */ + ["com.affine.notification.invitation-review-declined"]: ComponentType, { + ["1"]: JSX.Element; + ["2"]: JSX.Element; + }>>; + /** + * `<1>{{username}} has approved your request to join <2>{{workspaceName}}` + */ + ["com.affine.notification.invitation-review-approved"]: ComponentType, { + ["1"]: JSX.Element; + ["2"]: JSX.Element; + }>>; + /** + * `There is an issue regarding your invitation to <1>{{workspaceName}} ` + */ + ["com.affine.notification.invitation-blocked"]: ComponentType>; + /** + * `<1>{{username}} invited you to join <2>{{workspaceName}}` + */ + ["com.affine.notification.invitation"]: ComponentType, { + ["1"]: JSX.Element; + ["2"]: JSX.Element; + }>>; /** * `Unable to join <1/> <2>{{workspaceName}} due to insufficient seats available.` */ diff --git a/packages/frontend/i18n/src/resources/en.json b/packages/frontend/i18n/src/resources/en.json index bb493a2d4..e2f7a0588 100644 --- a/packages/frontend/i18n/src/resources/en.json +++ b/packages/frontend/i18n/src/resources/en.json @@ -1767,6 +1767,14 @@ "com.affine.notification.unsupported": "Unsupported message", "com.affine.notification.mention": "<1>{{username}} mentioned you in <2>{{docTitle}}", "com.affine.notification.empty": "No new notifications", + "com.affine.notification.invitation-accepted": "<1>{{username}} has accept your invitation", + "com.affine.notification.invitation-review-request": "<1>{{username}} has requested to join <2>{{workspaceName}}", + "com.affine.notification.invitation-review-declined": "<1>{{username}} has declined your request to join <2>{{workspaceName}}", + "com.affine.notification.invitation-review-approved": "<1>{{username}} has approved your request to join <2>{{workspaceName}}", + "com.affine.notification.invitation-review-approved.open-workspace": "Open workspace", + "com.affine.notification.invitation-blocked": "There is an issue regarding your invitation to <1>{{workspaceName}} ", + "com.affine.notification.invitation": "<1>{{username}} invited you to join <2>{{workspaceName}}", + "com.affine.notification.invitation.accept": "Accept & Join", "tips": "Tips", "Template": "Template", "com.affine.template-list.delete": "Delete Template",