mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 21:49:25 +08:00
feat(notification): add "Mark all as read" functionality and improve message status toggling
This commit is contained in:
parent
04296bbac8
commit
e3caaee61c
@ -21,6 +21,7 @@ import {
|
|||||||
fetchMessages,
|
fetchMessages,
|
||||||
inboxVisible,
|
inboxVisible,
|
||||||
isFecthingMessageObs,
|
isFecthingMessageObs,
|
||||||
|
markAllMessagesAsRead,
|
||||||
selectedChannelNameObs,
|
selectedChannelNameObs,
|
||||||
selectedMessageListObs,
|
selectedMessageListObs,
|
||||||
showMsgLoadingMoreObs,
|
showMsgLoadingMoreObs,
|
||||||
@ -48,7 +49,15 @@ const MessageList = observer(() => {
|
|||||||
read: t('Read'),
|
read: t('Read'),
|
||||||
unread: t('Unread'),
|
unread: t('Unread'),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMarkAllReadClick = useCallback(() => {
|
||||||
|
if (selectedChannelName) {
|
||||||
|
markAllMessagesAsRead({ channelName: selectedChannelName });
|
||||||
|
}
|
||||||
|
}, [selectedChannelName]);
|
||||||
|
|
||||||
if (!selectedChannelName) return null;
|
if (!selectedChannelName) return null;
|
||||||
|
|
||||||
const onItemClicked = (message) => {
|
const onItemClicked = (message) => {
|
||||||
updateMessage({
|
updateMessage({
|
||||||
filterByTk: message.id,
|
filterByTk: message.id,
|
||||||
@ -88,9 +97,14 @@ const MessageList = observer(() => {
|
|||||||
components: { Badge: { dotSize: 8 } },
|
components: { Badge: { dotSize: 8 } },
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography.Title level={4} style={{ marginBottom: token.marginLG }}>
|
<div
|
||||||
|
style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: token.marginLG }}
|
||||||
|
>
|
||||||
|
<Typography.Title level={4} style={{ margin: 0 }}>
|
||||||
{title}
|
{title}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
|
<Button onClick={onMarkAllReadClick}>{t('Mark all as read')}</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{messages.length === 0 && isFecthingMessageObs.value ? (
|
{messages.length === 0 && isFecthingMessageObs.value ? (
|
||||||
<Spin style={{ width: '100%', marginTop: token.marginXXL }} />
|
<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('Datetime')}>{dayjs(message.receiveTimestamp).fromNow()}</Descriptions.Item>
|
||||||
<Descriptions.Item label={t('Status')}>
|
<Descriptions.Item label={t('Status')}>
|
||||||
<div style={{ height: token.controlHeight }}>
|
<div style={{ height: token.controlHeight }}>
|
||||||
{hoveredMessageId === message.id && message.status === 'unread' ? (
|
{hoveredMessageId === message.id ? (
|
||||||
<Button
|
<Button
|
||||||
type="link"
|
type="link"
|
||||||
size="small"
|
size="small"
|
||||||
@ -159,12 +173,12 @@ const MessageList = observer(() => {
|
|||||||
updateMessage({
|
updateMessage({
|
||||||
filterByTk: message.id,
|
filterByTk: message.id,
|
||||||
values: {
|
values: {
|
||||||
status: 'read',
|
status: message.status === 'read' ? 'unread' : 'read',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t('Mark as read')}
|
{t(message.status === 'unread' ? 'Mark as read' : 'Mark as unread')}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Tag color={message.status === 'unread' ? 'red' : 'green'}>{msgStatusDict[message.status]}</Tag>
|
<Tag color={message.status === 'unread' ? 'red' : 'green'}>{msgStatusDict[message.status]}</Tag>
|
||||||
|
@ -7,19 +7,18 @@
|
|||||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { observable, autorun } from '@formily/reactive';
|
import { autorun, observable } from '@formily/reactive';
|
||||||
import { Message } from '../../types';
|
import { merge } from '@nocobase/utils/client';
|
||||||
|
import { InAppMessagesDefinition, Message } from '../../types';
|
||||||
import { getAPIClient } from '../utils';
|
import { getAPIClient } from '../utils';
|
||||||
import {
|
import {
|
||||||
channelMapObs,
|
channelMapObs,
|
||||||
selectedChannelNameObs,
|
channelStatusFilterObs,
|
||||||
fetchChannels,
|
fetchChannels,
|
||||||
InappChannelStatusEnum,
|
InappChannelStatusEnum,
|
||||||
channelStatusFilterObs,
|
selectedChannelNameObs,
|
||||||
} from './channel';
|
} from './channel';
|
||||||
import { userIdObs } from './user';
|
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 messageMapObs = observable<{ value: Record<string, Message> }>({ value: {} });
|
||||||
export const isFecthingMessageObs = observable<{ value: boolean }>({ value: false });
|
export const isFecthingMessageObs = observable<{ value: boolean }>({ value: false });
|
||||||
@ -80,6 +79,22 @@ export const updateMessage = async (params: { filterByTk: any; values: Record<an
|
|||||||
updateUnreadMsgsCount();
|
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(() => {
|
autorun(() => {
|
||||||
if (selectedChannelNameObs.value) {
|
if (selectedChannelNameObs.value) {
|
||||||
fetchMessages({ filter: { channelName: selectedChannelNameObs.value } });
|
fetchMessages({ filter: { channelName: selectedChannelNameObs.value } });
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
"Details page for desktop": "Details page for desktop",
|
"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\".",
|
"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 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\".",
|
"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",
|
"Details page for mobile": "Details page for mobile",
|
||||||
"The message page has already been created.": "The message page has already been created.",
|
"The message page has already been created.": "The message page has already been created.",
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
"detail URL": "详情链接",
|
"detail URL": "详情链接",
|
||||||
"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\".": "支持两种链接类型:内部链接和外部链接。如果使用内部链接,链接以“/”开头,例如“/admin”。如果使用外部链接,链接以“http”开头,例如“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\".": "支持两种链接类型:内部链接和外部链接。如果使用内部链接,链接以“/”开头,例如“/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”。",
|
"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": "移动端详情页",
|
"Details page for mobile": "移动端详情页",
|
||||||
"The message page has already been created.": "站内信页面已创建。",
|
"The message page has already been created.": "站内信页面已创建。",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user