mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
feat(core): more notification type (#11209)
This commit is contained in:
@@ -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 }) => {
|
||||
<InvitationNotificationItem notification={notification} />
|
||||
) : type === NotificationType.InvitationBlocked ? (
|
||||
<InvitationBlockedNotificationItem notification={notification} />
|
||||
) : type === NotificationType.InvitationReviewRequest ? (
|
||||
<InvitationReviewRequestNotificationItem notification={notification} />
|
||||
) : type === NotificationType.InvitationReviewDeclined ? (
|
||||
<InvitationReviewDeclinedNotificationItem notification={notification} />
|
||||
) : type === NotificationType.InvitationReviewApproved ? (
|
||||
<InvitationReviewApprovedNotificationItem notification={notification} />
|
||||
) : (
|
||||
<div className={styles.itemContainer}>
|
||||
<Avatar size={22} />
|
||||
@@ -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 (
|
||||
<div className={styles.itemContainer} onClick={handleClick}>
|
||||
<Avatar
|
||||
size={22}
|
||||
name={body.createdByUser?.name}
|
||||
url={body.createdByUser?.avatarUrl}
|
||||
/>
|
||||
<div className={styles.itemMain}>
|
||||
<span>
|
||||
<Trans
|
||||
i18nKey={'com.affine.notification.invitation-review-request'}
|
||||
components={{
|
||||
1: (
|
||||
<b
|
||||
className={styles.itemNameLabel}
|
||||
data-inactived={memberInactived}
|
||||
/>
|
||||
),
|
||||
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||
}}
|
||||
values={{
|
||||
username:
|
||||
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||
workspaceName:
|
||||
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
<div className={styles.itemDate}>
|
||||
{i18nTime(notification.createdAt, {
|
||||
relative: true,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<DeleteButton notification={notification} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const InvitationReviewDeclinedNotificationItem = ({
|
||||
notification,
|
||||
}: {
|
||||
notification: Notification;
|
||||
}) => {
|
||||
const t = useI18n();
|
||||
const body =
|
||||
notification.body as InvitationReviewDeclinedNotificationBodyType;
|
||||
const memberInactived = !body.createdByUser;
|
||||
const workspaceInactived = !body.workspace;
|
||||
|
||||
return (
|
||||
<div className={styles.itemContainer}>
|
||||
<Avatar
|
||||
size={22}
|
||||
name={body.createdByUser?.name}
|
||||
url={body.createdByUser?.avatarUrl}
|
||||
/>
|
||||
<div className={styles.itemMain}>
|
||||
<span>
|
||||
<Trans
|
||||
i18nKey={'com.affine.notification.invitation-review-declined'}
|
||||
components={{
|
||||
1: (
|
||||
<b
|
||||
className={styles.itemNameLabel}
|
||||
data-inactived={memberInactived}
|
||||
/>
|
||||
),
|
||||
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||
}}
|
||||
values={{
|
||||
username:
|
||||
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||
workspaceName:
|
||||
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
<div className={styles.itemDate}>
|
||||
{i18nTime(notification.createdAt, {
|
||||
relative: true,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<DeleteButton notification={notification} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<div className={styles.itemContainer}>
|
||||
<Avatar
|
||||
size={22}
|
||||
name={body.createdByUser?.name}
|
||||
url={body.createdByUser?.avatarUrl}
|
||||
/>
|
||||
<div className={styles.itemMain}>
|
||||
<span>
|
||||
<Trans
|
||||
i18nKey={'com.affine.notification.invitation-review-approved'}
|
||||
components={{
|
||||
1: (
|
||||
<b
|
||||
className={styles.itemNameLabel}
|
||||
data-inactived={memberInactived}
|
||||
/>
|
||||
),
|
||||
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||
}}
|
||||
values={{
|
||||
username:
|
||||
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||
workspaceName:
|
||||
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
{!workspaceInactived && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
className={styles.itemActionButton}
|
||||
onClick={handleClick}
|
||||
>
|
||||
{t[
|
||||
'com.affine.notification.invitation-review-approved.open-workspace'
|
||||
]()}
|
||||
</Button>
|
||||
)}
|
||||
<div className={styles.itemDate}>
|
||||
{i18nTime(notification.createdAt, {
|
||||
relative: true,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<DeleteButton notification={notification} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const InvitationAcceptedNotificationItem = ({
|
||||
notification,
|
||||
}: {
|
||||
@@ -320,21 +512,6 @@ const InvitationNotificationItem = ({
|
||||
const [isAccepting, setIsAccepting] = useState(false);
|
||||
const { jumpToPage } = useNavigateHelper();
|
||||
|
||||
const WorkspaceNameWithIcon = useCallback(
|
||||
({
|
||||
children,
|
||||
...props
|
||||
}: React.PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>) => {
|
||||
return (
|
||||
<b className={styles.itemNameLabel} {...props}>
|
||||
<CollaborationIcon width={20} height={20} />
|
||||
{children}
|
||||
</b>
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleReadAndOpenWorkspace = useCallback(() => {
|
||||
notificationListService.readNotification(notification.id).catch(err => {
|
||||
console.error(err);
|
||||
@@ -473,3 +650,15 @@ const DeleteButton = ({
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const WorkspaceNameWithIcon = ({
|
||||
children,
|
||||
...props
|
||||
}: React.PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>) => {
|
||||
return (
|
||||
<b className={styles.itemNameLabel} {...props}>
|
||||
<CollaborationIcon width={20} height={20} />
|
||||
{children}
|
||||
</b>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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}}</1> has accept your invitation`
|
||||
*/
|
||||
["com.affine.notification.invitation-accepted"]: ComponentType<TypedTransProps<{
|
||||
readonly username: string;
|
||||
}, {
|
||||
["1"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `<1>{{username}}</1> has requested to join <2>{{workspaceName}}</2>`
|
||||
*/
|
||||
["com.affine.notification.invitation-review-request"]: ComponentType<TypedTransProps<Readonly<{
|
||||
username: string;
|
||||
workspaceName: string;
|
||||
}>, {
|
||||
["1"]: JSX.Element;
|
||||
["2"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `<1>{{username}}</1> has declined your request to join <2>{{workspaceName}}</2>`
|
||||
*/
|
||||
["com.affine.notification.invitation-review-declined"]: ComponentType<TypedTransProps<Readonly<{
|
||||
username: string;
|
||||
workspaceName: string;
|
||||
}>, {
|
||||
["1"]: JSX.Element;
|
||||
["2"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `<1>{{username}}</1> has approved your request to join <2>{{workspaceName}}</2>`
|
||||
*/
|
||||
["com.affine.notification.invitation-review-approved"]: ComponentType<TypedTransProps<Readonly<{
|
||||
username: string;
|
||||
workspaceName: string;
|
||||
}>, {
|
||||
["1"]: JSX.Element;
|
||||
["2"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `There is an issue regarding your invitation to <1>{{workspaceName}}</1> `
|
||||
*/
|
||||
["com.affine.notification.invitation-blocked"]: ComponentType<TypedTransProps<{
|
||||
readonly workspaceName: string;
|
||||
}, {
|
||||
["1"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `<1>{{username}}</1> invited you to join <2>{{workspaceName}}</2>`
|
||||
*/
|
||||
["com.affine.notification.invitation"]: ComponentType<TypedTransProps<Readonly<{
|
||||
username: string;
|
||||
workspaceName: string;
|
||||
}>, {
|
||||
["1"]: JSX.Element;
|
||||
["2"]: JSX.Element;
|
||||
}>>;
|
||||
/**
|
||||
* `Unable to join <1/> <2>{{workspaceName}}</2> due to insufficient seats available.`
|
||||
*/
|
||||
|
||||
@@ -1767,6 +1767,14 @@
|
||||
"com.affine.notification.unsupported": "Unsupported message",
|
||||
"com.affine.notification.mention": "<1>{{username}}</1> mentioned you in <2>{{docTitle}}</2>",
|
||||
"com.affine.notification.empty": "No new notifications",
|
||||
"com.affine.notification.invitation-accepted": "<1>{{username}}</1> has accept your invitation",
|
||||
"com.affine.notification.invitation-review-request": "<1>{{username}}</1> has requested to join <2>{{workspaceName}}</2>",
|
||||
"com.affine.notification.invitation-review-declined": "<1>{{username}}</1> has declined your request to join <2>{{workspaceName}}</2>",
|
||||
"com.affine.notification.invitation-review-approved": "<1>{{username}}</1> has approved your request to join <2>{{workspaceName}}</2>",
|
||||
"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}}</1> ",
|
||||
"com.affine.notification.invitation": "<1>{{username}}</1> invited you to join <2>{{workspaceName}}</2>",
|
||||
"com.affine.notification.invitation.accept": "Accept & Join",
|
||||
"tips": "Tips",
|
||||
"Template": "Template",
|
||||
"com.affine.template-list.delete": "Delete Template",
|
||||
|
||||
Reference in New Issue
Block a user