1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-04-28 03:10:45 +00:00

optimize notification (#7521)

* update

* update

---------

Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com>
This commit is contained in:
awu0403 2025-02-27 17:00:33 +08:00 committed by GitHub
parent 2fb65580e4
commit 3899577631
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 81 additions and 67 deletions

View File

@ -12,7 +12,7 @@ class Notification extends React.Component {
super(props);
this.state = {
showNotice: false,
unseenCount: 0,
totalUnseenCount: 0,
generalNoticeList: [],
discussionNoticeList: [],
currentTab: 'general',
@ -22,8 +22,11 @@ class Notification extends React.Component {
componentDidMount() {
seafileAPI.listAllNotifications().then(res => {
let unseen_count = res.data.general.unseen_count + res.data.discussion.unseen_count;
this.setState({ unseenCount: unseen_count });
this.setState({
totalUnseenCount: res.data.total_unseen_count,
generalNoticeListUnseen: res.data.general.unseen_count,
discussionNoticeListUnseen: res.data.discussion.unseen_count
});
});
}
@ -33,7 +36,7 @@ class Notification extends React.Component {
seafileAPI.updateNotifications();
this.setState({
showNotice: false,
unseenCount: 0
totalUnseenCount: 0
});
} else {
this.loadNotices();
@ -52,13 +55,17 @@ class Notification extends React.Component {
loadNotices = () => {
let page = 1;
let perPage = 5;
let perPage = 25;
seafileAPI.listAllNotifications(page, perPage).then(res => {
let generalNoticeList = res.data.general.notification_list;
let discussionNoticeList = res.data.discussion.notification_list;
let generalNoticeListUnseen = res.data.general.unseen_count;
let discussionNoticeListUnseen = res.data.discussion.unseen_count;
this.setState({
generalNoticeList: generalNoticeList,
discussionNoticeList: discussionNoticeList
discussionNoticeList: discussionNoticeList,
generalNoticeListUnseen: generalNoticeListUnseen,
discussionNoticeListUnseen: discussionNoticeListUnseen
});
});
};
@ -71,10 +78,12 @@ class Notification extends React.Component {
}
return item;
});
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
let totalUnseenCount = this.state.totalUnseenCount === 0 ? 0 : this.state.totalUnseenCount - 1;
let generalNoticeListUnseen = this.state.generalNoticeListUnseen === 0 ? 0 : this.state.generalNoticeListUnseen - 1;
this.setState({
generalNoticeList: noticeList,
unseenCount: unseenCount,
totalUnseenCount: totalUnseenCount,
generalNoticeListUnseen: generalNoticeListUnseen
});
seafileAPI.markNoticeAsRead(noticeItem.id);
}
@ -85,10 +94,12 @@ class Notification extends React.Component {
}
return item;
});
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
let totalUnseenCount = this.state.totalUnseenCount === 0 ? 0 : this.state.totalUnseenCount - 1;
let discussionNoticeListUnseen = this.state.discussionNoticeListUnseen === 0 ? 0 : this.state.discussionNoticeListUnseen - 1;
this.setState({
discussionNoticeList: noticeList,
unseenCount: unseenCount,
totalUnseenCount: totalUnseenCount,
discussionNoticeListUnseen: discussionNoticeListUnseen
});
seafileAPI.markSdocNoticeAsRead(noticeItem.id);
}
@ -111,26 +122,62 @@ class Notification extends React.Component {
};
onMarkAllNotifications = () => {
seafileAPI.updateAllNotifications().then(() => {
this.setState({
unseenCount: 0,
let generalNoticeListUnseen = this.state.generalNoticeListUnseen;
let discussionNoticeListUnseen = this.state.discussionNoticeListUnseen;
if (this.state.currentTab === 'general') {
seafileAPI.updateNotifications().then((res) => {
this.setState({
generalNoticeList: this.state.generalNoticeList.map(item => {
item.seen = true;
return item;
}),
generalNoticeListUnseen: 0,
totalUnseenCount: discussionNoticeListUnseen
});
}).catch((error) => {
this.setState({
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
});
});
}).catch((error) => {
this.setState({
errorMsg: Utils.getErrorMsg(error, true)
} else if (this.state.currentTab === 'discussion') {
seafileAPI.updateSdocNotifications().then((res) => {
this.setState({
discussionNoticeList: this.state.discussionNoticeList.map(item => {
item.seen = true;
return item;
}),
discussionNoticeListUnseen: 0,
totalUnseenCount: generalNoticeListUnseen
});
}).catch((error) => {
this.setState({
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
});
});
});
}
};
updateTotalUnseenCount = (noticeType) => {
if (noticeType === 'general') {
this.setState({
generalNoticeListUnseen: 0,
totalUnseenCount: this.state.discussionNoticeListUnseen
});
} else if (noticeType === 'discussion') {
this.setState({
discussionNoticeListUnseen: 0,
totalUnseenCount: this.state.generalNoticeListUnseen
});
}
};
render() {
const { unseenCount, currentTab, generalNoticeList, discussionNoticeList } = this.state;
const generalNoticeListUnseen = generalNoticeList.filter(item => !item.seen).length;
const discussionNoticeListUnseen = discussionNoticeList.filter(item => !item.seen).length;
const { totalUnseenCount, currentTab, generalNoticeList, discussionNoticeList, generalNoticeListUnseen, discussionNoticeListUnseen } = this.state;
return (
<div id="notifications">
<a href="#" onClick={this.onClick} className="no-deco" id="notice-icon" title={gettext('Notifications')} aria-label={gettext('Notifications')}>
<span className="sf2-icon-bell" id="notification-popover"></span>
<span className={`num ${unseenCount ? '' : 'hide'}`}>{unseenCount}</span>
<span className={`num ${totalUnseenCount ? '' : 'hide'}`}>{totalUnseenCount}</span>
</a>
{this.state.showNotice &&
<NotificationPopover
@ -170,6 +217,7 @@ class Notification extends React.Component {
onNotificationDialogToggle={this.onNotificationDialogToggle}
generalNoticeListUnseen={generalNoticeListUnseen}
discussionNoticeListUnseen={discussionNoticeListUnseen}
updateTotalUnseenCount={this.updateTotalUnseenCount}
/>
}
</div>

View File

@ -101,6 +101,7 @@ class UserNotificationsDialog extends React.Component {
return item;
})
});
this.props.updateTotalUnseenCount('general');
}).catch((error) => {
this.setState({
isLoading: false,
@ -115,6 +116,7 @@ class UserNotificationsDialog extends React.Component {
return item;
})
});
this.props.updateTotalUnseenCount('discussion');
}).catch((error) => {
this.setState({
isLoading: false,
@ -131,6 +133,7 @@ class UserNotificationsDialog extends React.Component {
this.setState({
items: []
});
this.props.updateTotalUnseenCount('general');
}).catch((error) => {
this.setState({
isLoading: false,
@ -142,6 +145,7 @@ class UserNotificationsDialog extends React.Component {
this.setState({
items: []
});
this.props.updateTotalUnseenCount('discussion');
}).catch((error) => {
this.setState({
isLoading: false,

View File

@ -12,7 +12,6 @@ from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.notifications.models import UserNotification
from seahub.notifications.models import get_cache_key_of_unseen_notifications
from seahub.notifications.utils import update_notice_detail
from seahub.utils.timeutils import datetime_to_isoformat_timestr
from seahub.api2.utils import api_error

View File

@ -7,13 +7,11 @@ from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from django.core.cache import cache
from seahub.api2.authentication import TokenAuthentication
from seahub.api2.throttling import UserRateThrottle
from seahub.notifications.models import UserNotification
from seahub.notifications.models import get_cache_key_of_unseen_notifications
from seahub.notifications.utils import update_notice_detail, update_sdoc_notice_detail
from seahub.api2.utils import api_error
from seahub.seadoc.models import SeadocNotification
@ -66,16 +64,8 @@ class NotificationsView(APIView):
notification_list.append(notice)
cache_key = get_cache_key_of_unseen_notifications(username)
unseen_count_from_cache = cache.get(cache_key, None)
# for case of count value is `0`
if unseen_count_from_cache is not None:
result['unseen_count'] = unseen_count_from_cache
else:
unseen_count = UserNotification.objects.filter(to_user=username, seen=False).count()
result['unseen_count'] = unseen_count
cache.set(cache_key, unseen_count)
unseen_count = UserNotification.objects.filter(to_user=username, seen=False).count()
result['unseen_count'] = unseen_count
total_count = UserNotification.objects.filter(to_user=username).count()
@ -98,9 +88,6 @@ class NotificationsView(APIView):
notice.seen = True
notice.save()
cache_key = get_cache_key_of_unseen_notifications(username)
cache.delete(cache_key)
return Response({'success': True})
def delete(self, request):
@ -113,9 +100,6 @@ class NotificationsView(APIView):
UserNotification.objects.remove_user_notifications(username)
cache_key = get_cache_key_of_unseen_notifications(username)
cache.delete(cache_key)
return Response({'success': True})
@ -160,9 +144,6 @@ class NotificationView(APIView):
notice.seen = True
notice.save()
cache_key = get_cache_key_of_unseen_notifications(username)
cache.delete(cache_key)
return Response({'success': True})
@ -310,10 +291,10 @@ class AllNotificationsView(APIView):
username = request.user.username
try:
per_page = int(request.GET.get('per_page', ''))
page = int(request.GET.get('page', ''))
per_page = int(request.GET.get('per_page', '25'))
page = int(request.GET.get('page', '1'))
except ValueError:
per_page = 5
per_page = 25
page = 1
if page < 1:
@ -353,16 +334,8 @@ class AllNotificationsView(APIView):
sdoc_notification_list.append(notice)
cache_key = get_cache_key_of_unseen_notifications(username)
unseen_count_from_cache = cache.get(cache_key, None)
# for case of count value is `0`
if unseen_count_from_cache is not None:
result['general']['unseen_count'] = unseen_count_from_cache
else:
unseen_count = UserNotification.objects.filter(to_user=username, seen=False).count()
result['general']['unseen_count'] = unseen_count
cache.set(cache_key, unseen_count)
unseen_count = UserNotification.objects.filter(to_user=username, seen=False).count()
result['general']['unseen_count'] = unseen_count
sdoc_unseen_count = SeadocNotification.objects.filter(username=username, seen=False).count()
result['discussion']['unseen_count'] = sdoc_unseen_count
@ -374,6 +347,7 @@ class AllNotificationsView(APIView):
result['discussion']['notification_list'] = sdoc_notification_list
result['general']['count'] = total_count
result['discussion']['count'] = sdoc_total_count
result['total_unseen_count'] = result['general']['unseen_count'] + result['discussion']['unseen_count']
return Response(result)
@ -394,7 +368,5 @@ class AllNotificationsView(APIView):
error_msg = 'Internal Server Error'
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
cache_key = get_cache_key_of_unseen_notifications(username)
cache.delete(cache_key)
return Response({'success': True})

View File

@ -81,7 +81,6 @@ MSG_TYPE_DELETED_FILES = 'deleted_files'
MSG_TYPE_SAML_SSO_FAILED = 'saml_sso_failed'
MSG_TYPE_FACE_CLUSTER = 'face_cluster'
USER_NOTIFICATION_COUNT_CACHE_PREFIX = 'USER_NOTIFICATION_COUNT_'
def file_uploaded_msg_to_json(file_name, repo_id, uploaded_to):
"""Encode file uploaded message to json string.
@ -156,11 +155,6 @@ def saml_sso_error_msg_to_json(error_msg):
return json.dumps({'error_msg': error_msg})
def get_cache_key_of_unseen_notifications(username):
return normalize_cache_key(username,
USER_NOTIFICATION_COUNT_CACHE_PREFIX)
class UserNotificationManager(models.Manager):
def _add_user_notification(self, to_user, msg_type, detail):
"""Add generic user notification.
@ -174,9 +168,6 @@ class UserNotificationManager(models.Manager):
to_user=to_user, msg_type=msg_type, detail=detail)
n.save()
cache_key = get_cache_key_of_unseen_notifications(to_user)
cache.delete(cache_key)
return n
def get_all_notifications(self, seen=None, time_since=None):