feat(notification): add "Mark all as read" functionality and improve message status toggling

This commit is contained in:
Sheldon Guo 2025-04-24 09:33:36 +08:00
parent 04296bbac8
commit e3caaee61c
4 changed files with 46 additions and 13 deletions

View File

@ -21,6 +21,7 @@ import {
fetchMessages,
inboxVisible,
isFecthingMessageObs,
markAllMessagesAsRead,
selectedChannelNameObs,
selectedMessageListObs,
showMsgLoadingMoreObs,
@ -48,7 +49,15 @@ const MessageList = observer(() => {
read: t('Read'),
unread: t('Unread'),
};
const onMarkAllReadClick = useCallback(() => {
if (selectedChannelName) {
markAllMessagesAsRead({ channelName: selectedChannelName });
}
}, [selectedChannelName]);
if (!selectedChannelName) return null;
const onItemClicked = (message) => {
updateMessage({
filterByTk: message.id,
@ -88,9 +97,14 @@ const MessageList = observer(() => {
components: { Badge: { dotSize: 8 } },
}}
>
<Typography.Title level={4} style={{ marginBottom: token.marginLG }}>
{title}
</Typography.Title>
<div
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: token.marginLG }}
>
<Typography.Title level={4} style={{ margin: 0 }}>
{title}
</Typography.Title>
<Button onClick={onMarkAllReadClick}>{t('Mark all as read')}</Button>
</div>
{messages.length === 0 && isFecthingMessageObs.value ? (
<Spin style={{ width: '100%', marginTop: token.marginXXL }} />
@ -150,7 +164,7 @@ const MessageList = observer(() => {
<Descriptions.Item label={t('Datetime')}>{dayjs(message.receiveTimestamp).fromNow()}</Descriptions.Item>
<Descriptions.Item label={t('Status')}>
<div style={{ height: token.controlHeight }}>
{hoveredMessageId === message.id && message.status === 'unread' ? (
{hoveredMessageId === message.id ? (
<Button
type="link"
size="small"
@ -159,12 +173,12 @@ const MessageList = observer(() => {
updateMessage({
filterByTk: message.id,
values: {
status: 'read',
status: message.status === 'read' ? 'unread' : 'read',
},
});
}}
>
{t('Mark as read')}
{t(message.status === 'unread' ? 'Mark as read' : 'Mark as unread')}
</Button>
) : (
<Tag color={message.status === 'unread' ? 'red' : 'green'}>{msgStatusDict[message.status]}</Tag>

View File

@ -7,19 +7,18 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { observable, autorun } from '@formily/reactive';
import { Message } from '../../types';
import { autorun, observable } from '@formily/reactive';
import { merge } from '@nocobase/utils/client';
import { InAppMessagesDefinition, Message } from '../../types';
import { getAPIClient } from '../utils';
import {
channelMapObs,
selectedChannelNameObs,
channelStatusFilterObs,
fetchChannels,
InappChannelStatusEnum,
channelStatusFilterObs,
selectedChannelNameObs,
} from './channel';
import { userIdObs } from './user';
import { InAppMessagesDefinition } from '../../types';
import { merge } from '@nocobase/utils/client';
export const messageMapObs = observable<{ value: Record<string, Message> }>({ value: {} });
export const isFecthingMessageObs = observable<{ value: boolean }>({ value: false });
@ -80,6 +79,22 @@ export const updateMessage = async (params: { filterByTk: any; values: Record<an
updateUnreadMsgsCount();
};
export const markAllMessagesAsRead = async ({ channelName }: { channelName: string }) => {
const apiClient = getAPIClient();
await apiClient.request({
resource: InAppMessagesDefinition.name,
action: 'update',
method: 'post',
params: { filter: { status: 'unread', channelName: channelName }, values: { status: 'read' } },
});
Object.values(messageMapObs.value).forEach((message) => {
if (message.channelName === channelName && message.status === 'unread') {
message.status = 'read';
}
});
updateUnreadMsgsCount();
};
autorun(() => {
if (selectedChannelNameObs.value) {
fetchMessages({ filter: { channelName: selectedChannelNameObs.value } });

View File

@ -22,6 +22,8 @@
"Details page for desktop": "Details page for desktop",
"Support two types of links: internal links and external links. If using an internal link, the link starts with\"/\", for example, \"/admin\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".": "Support two types of links: internal links and external links. If using an internal link, the link starts with \"/\", for example, \"/admin\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".",
"Mark as read": "Mark as read",
"Mark as unread": "Mark as unread",
"Mark all as read": "Mark all as read",
"Support two types of links: internal links and external links. If using an internal link, the link starts with\"/\", for example, \"/m\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".": "Support two types of links: internal links and external links. If using an internal link, the link starts with \"/\", for example, \"/m\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".",
"Details page for mobile": "Details page for mobile",
"The message page has already been created.": "The message page has already been created.",

View File

@ -21,7 +21,9 @@
"detail URL": "详情链接",
"Details page for desktop": "桌面端详情页",
"Support two types of links: internal links and external links. If using an internal link, the link starts with\"/\", for example, \"/admin\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".": "支持两种链接类型:内部链接和外部链接。如果使用内部链接,链接以“/”开头,例如“/admin”。如果使用外部链接链接以“http”开头例如“https://example.com”。",
"Mark as read": "标记为已读",
"Mark as read": "标为已读",
"Mark as unread": "标为未读",
"Mark all as read": "全部标为已读",
"Support two types of links: internal links and external links. If using an internal link, the link starts with\"/\", for example, \"/m\". If using an external link, the link starts with \"http\", for example, \"https://example.com\".": "支持两种链接类型:内部链接和外部链接。如果使用内部链接,链接以“/”开头,例如“/m”。如果使用外部链接链接以“http”开头例如“https://example.com”。",
"Details page for mobile": "移动端详情页",
"The message page has already been created.": "站内信页面已创建。",