mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-18 00:00:00 +00:00
update
This commit is contained in:
@@ -4,6 +4,7 @@ import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { processor } from '@seafile/seafile-editor';
|
||||
|
||||
const propTypes = {
|
||||
noticeItem: PropTypes.object.isRequired,
|
||||
@@ -35,7 +36,7 @@ class NoticeItem extends React.Component {
|
||||
let noticeItem = this.props.noticeItem;
|
||||
let noticeType = noticeItem.type;
|
||||
let detail = noticeItem.detail;
|
||||
console.log(detail, noticeItem, noticeType)
|
||||
|
||||
if (noticeType === MSG_TYPE_ADD_USER_TO_GROUP) {
|
||||
|
||||
let avatar_url = detail.group_staff_avatar_url;
|
||||
@@ -378,19 +379,23 @@ class NoticeItem extends React.Component {
|
||||
}
|
||||
|
||||
if (noticeType === MSG_TYPE_SEADOC_COMMENT) {
|
||||
let avatar_url = detail.share_from_user_avatar_url;
|
||||
let notice = '';
|
||||
console.log(111)
|
||||
notice = Utils.HTMLescape(notice);
|
||||
return { avatar_url, notice };
|
||||
let avatar_url = detail.avatar_url;
|
||||
let notice = detail.comment;
|
||||
let username = detail.user_name;
|
||||
processor.process(notice, (error, vfile) => {
|
||||
notice = String(vfile);
|
||||
});
|
||||
return { avatar_url, username, notice };
|
||||
}
|
||||
|
||||
if (noticeType === MSG_TYPE_SEADOC_REPLY) {
|
||||
let avatar_url = detail.share_from_user_avatar_url;
|
||||
let avatar_url = detail.avatar_url;
|
||||
let notice = detail.reply;
|
||||
notice = Utils.HTMLescape(notice);
|
||||
console.log(notice)
|
||||
return { avatar_url, notice };
|
||||
let username = detail.user_name;
|
||||
processor.process(notice, (error, vfile) => {
|
||||
notice = String(vfile);
|
||||
});
|
||||
return { avatar_url, username, notice };
|
||||
}
|
||||
|
||||
// if (noticeType === MSG_TYPE_GUEST_INVITATION_ACCEPTED) {
|
||||
@@ -410,8 +415,7 @@ class NoticeItem extends React.Component {
|
||||
|
||||
render() {
|
||||
let noticeItem = this.props.noticeItem;
|
||||
let { avatar_url, notice } = this.generatorNoticeInfo();
|
||||
|
||||
let { avatar_url, username, notice } = this.generatorNoticeInfo();
|
||||
if (!avatar_url && !notice) {
|
||||
return '';
|
||||
}
|
||||
@@ -432,9 +436,14 @@ class NoticeItem extends React.Component {
|
||||
<li onClick={this.onNoticeItemClick} className={noticeItem.seen ? 'read' : 'unread'}>
|
||||
<div className="notice-item">
|
||||
<div className="main-info">
|
||||
<div className="auther-info">
|
||||
<img src={avatar_url} width="32" height="32" className="avatar" alt=""/>
|
||||
<p>{username}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="brief" dangerouslySetInnerHTML={{ __html: notice }}></p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="time">{dayjs(noticeItem.time).fromNow()}</p>
|
||||
</div>
|
||||
</li>
|
||||
|
@@ -82,12 +82,11 @@ export default class NotificationPopover extends React.Component {
|
||||
<li className="nav-item" onClick={() => this.tabItemClick('discussion')}>
|
||||
<span className={`nav-link ${currentTab === 'discussion' ? 'active' : ''}`}>
|
||||
{gettext('Discussion')}
|
||||
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<span className="mark-all-read" onClick={this.onMarkAllNotifications}>
|
||||
{gettext('Mark all as read')}
|
||||
<span className="mark-all-read" onClick={this.props.onMarkAllNotifications}>
|
||||
{bodyText}
|
||||
</span>
|
||||
</div>
|
||||
{currentTab === 'general' &&
|
||||
|
@@ -62,7 +62,6 @@ class Notification extends React.Component {
|
||||
if (this.state.currentTab === 'discussion') {
|
||||
seafileAPI.listSdocNotifications(page, perPage).then(res => {
|
||||
let noticeList = res.data.notification_list;
|
||||
console.log(noticeList)
|
||||
this.setState({ noticeList: noticeList });
|
||||
});
|
||||
}
|
||||
@@ -76,7 +75,14 @@ class Notification extends React.Component {
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
if (this.state.currentTab === 'general') {
|
||||
seafileAPI.markNoticeAsRead(noticeItem.id);
|
||||
}
|
||||
if (this.state.currentTab === 'discussion') {
|
||||
seafileAPI.markSdocNoticeAsRead(noticeItem.id);
|
||||
}
|
||||
|
||||
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
|
||||
this.setState({
|
||||
noticeList: noticeList,
|
||||
|
@@ -1475,6 +1475,11 @@ class SeafileAPI {
|
||||
return this.req.put(url);
|
||||
}
|
||||
|
||||
updateSdocNotifications() {
|
||||
const url = this.server + '/api/v2.1/sdoc-notifications/';
|
||||
return this.req.put(url);
|
||||
}
|
||||
|
||||
deleteNotifications() {
|
||||
const url = this.server + '/api/v2.1/notifications/';
|
||||
return this.req.delete(url);
|
||||
@@ -1492,6 +1497,13 @@ class SeafileAPI {
|
||||
return this.req.put(url, from);
|
||||
}
|
||||
|
||||
markSdocNoticeAsRead(noticeId) {
|
||||
const url = this.server + '/api/v2.1/sdoc-notification/';
|
||||
let from = new FormData();
|
||||
from.append('notice_id', noticeId);
|
||||
return this.req.put(url, from);
|
||||
}
|
||||
|
||||
// ---- Linked Devices API
|
||||
listLinkedDevices() {
|
||||
const url = this.server + '/api2/devices/';
|
||||
|
@@ -13,6 +13,7 @@ from seahub.api2.authentication import TokenAuthentication
|
||||
from seahub.api2.throttling import UserRateThrottle
|
||||
from seahub.notifications.models import UserNotification
|
||||
|
||||
from seahub.seadoc.models import get_cache_key_of_unseen_sdoc_notifications
|
||||
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
|
||||
@@ -166,18 +167,13 @@ class NotificationView(APIView):
|
||||
return Response({'success': True})
|
||||
|
||||
|
||||
class SdocNotificationView(APIView):
|
||||
class SdocNotificationsView(APIView):
|
||||
def get(self, request):
|
||||
""" used for get sdoc notifications
|
||||
|
||||
Permission checking:
|
||||
1. login user.
|
||||
"""
|
||||
notice_type = request.GET.get('type', 'general')
|
||||
if notice_type not in NOTIF_TYPE:
|
||||
error_msg = 'notice_type invalid.'
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
result = {}
|
||||
|
||||
username = request.user.username
|
||||
@@ -205,7 +201,7 @@ class SdocNotificationView(APIView):
|
||||
notice['seen'] = i.seen
|
||||
|
||||
notification_list.append(notice)
|
||||
cache_key = get_cache_key_of_unseen_notifications(username)
|
||||
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||
unseen_count_from_cache = cache.get(cache_key, None)
|
||||
|
||||
# for case of count value is `0`
|
||||
@@ -222,3 +218,69 @@ class SdocNotificationView(APIView):
|
||||
result['count'] = total_count
|
||||
|
||||
return Response(result)
|
||||
|
||||
def put(self, request):
|
||||
""" currently only used for mark all notifications seen
|
||||
|
||||
Permission checking:
|
||||
1. login user.
|
||||
"""
|
||||
|
||||
username = request.user.username
|
||||
unseen_notices = SeadocNotification.objects.filter(username, seen=False)
|
||||
for notice in unseen_notices:
|
||||
notice.seen = True
|
||||
notice.save()
|
||||
|
||||
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||
cache.delete(cache_key)
|
||||
|
||||
return Response({'success': True})
|
||||
|
||||
|
||||
|
||||
class SdocNotificationView(APIView):
|
||||
|
||||
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
throttle_classes = (UserRateThrottle,)
|
||||
|
||||
def put(self, request):
|
||||
""" currently only used for mark a sdoc notification seen
|
||||
|
||||
Permission checking:
|
||||
1. login user.
|
||||
"""
|
||||
|
||||
notice_id = request.data.get('notice_id')
|
||||
|
||||
# argument check
|
||||
try:
|
||||
int(notice_id)
|
||||
except Exception as e:
|
||||
error_msg = 'notice_id invalid.'
|
||||
logger.error(e)
|
||||
return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
|
||||
|
||||
# resource check
|
||||
try:
|
||||
notice = SeadocNotification.objects.get(id=notice_id)
|
||||
except SeadocNotification.DoesNotExist as e:
|
||||
logger.error(e)
|
||||
error_msg = 'Notification %s not found.' % notice_id
|
||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||
|
||||
# permission check
|
||||
username = request.user.username
|
||||
if notice.username != username:
|
||||
error_msg = 'Permission denied.'
|
||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||
|
||||
if not notice.seen:
|
||||
notice.seen = True
|
||||
notice.save()
|
||||
|
||||
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||
cache.delete(cache_key)
|
||||
|
||||
return Response({'success': True})
|
@@ -2,6 +2,7 @@
|
||||
import os
|
||||
import json
|
||||
import logging
|
||||
import posixpath
|
||||
from django.core.cache import cache
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import gettext as _
|
||||
@@ -10,6 +11,7 @@ from seaserv import ccnet_api, seafile_api
|
||||
|
||||
from seahub.constants import CUSTOM_PERMISSION_PREFIX
|
||||
from seahub.notifications.models import Notification
|
||||
from seahub.tags.models import FileUUIDMap
|
||||
from seahub.notifications.settings import NOTIFICATION_CACHE_TIMEOUT
|
||||
from seahub.avatar.templatetags.avatar_tags import api_avatar_url
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname, email2contact_email
|
||||
@@ -403,17 +405,30 @@ def update_notice_detail(request, notices):
|
||||
|
||||
|
||||
def update_sdoc_notice_detail(request, notices):
|
||||
repo_dict = {}
|
||||
for notice in notices:
|
||||
if notice.is_comment():
|
||||
try:
|
||||
d = json.loads(notice.detail)
|
||||
uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(notice.doc_uuid)
|
||||
origin_file_path = posixpath.join(uuid.parent_path, uuid.filename)
|
||||
url, _, _ = api_avatar_url(d['author'])
|
||||
d['avatar_url'] = url
|
||||
d['sdoc_path'] = origin_file_path
|
||||
d['sdoc_name'] = uuid.filename
|
||||
d['repo_id'] = uuid.repo_id
|
||||
notice.detail = d
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
elif notice.is_reply():
|
||||
try:
|
||||
d = json.loads(notice.detail)
|
||||
uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid(notice.doc_uuid)
|
||||
origin_file_path = posixpath.join(uuid.parent_path, uuid.filename)
|
||||
url, _, _ = api_avatar_url(d['author'])
|
||||
d['avatar_url'] = url
|
||||
d['sdoc_path'] = origin_file_path
|
||||
d['sdoc_name'] = uuid.filename
|
||||
d['repo_id'] = uuid.repo_id
|
||||
notice.detail = d
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
@@ -7,7 +7,7 @@ from django.db import models
|
||||
from seahub.utils.timeutils import datetime_to_isoformat_timestr
|
||||
from seahub.base.templatetags.seahub_tags import email2nickname
|
||||
from seahub.seadoc.settings import SDOC_REVISIONS_DIR
|
||||
|
||||
from seahub.utils import normalize_cache_key
|
||||
|
||||
class SeadocHistoryNameManager(models.Manager):
|
||||
def update_name(self, doc_uuid, obj_id, name):
|
||||
@@ -251,6 +251,11 @@ class SeadocCommentReply(models.Model):
|
||||
### sdoc notification
|
||||
MSG_TYPE_REPLY = 'reply'
|
||||
MSG_TYPE_COMMENT = 'comment'
|
||||
SDOC_NOTIFICATION_COUNT_CACHE_PREFIX = 'SDOC_NOTIFICATION_COUNT_'
|
||||
|
||||
def get_cache_key_of_unseen_sdoc_notifications(username):
|
||||
return normalize_cache_key(username,
|
||||
SDOC_NOTIFICATION_COUNT_CACHE_PREFIX)
|
||||
|
||||
class SeadocNotificationManager(models.Manager):
|
||||
def total_count(self, doc_uuid, username):
|
||||
|
@@ -91,7 +91,7 @@ from seahub.api2.endpoints.invitations import InvitationsView, InvitationsBatchV
|
||||
from seahub.api2.endpoints.invitation import InvitationView, InvitationRevokeView
|
||||
from seahub.api2.endpoints.repo_share_invitations import RepoShareInvitationsView, RepoShareInvitationsBatchView
|
||||
from seahub.api2.endpoints.repo_share_invitation import RepoShareInvitationView
|
||||
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView, SdocNotificationView
|
||||
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView, SdocNotificationView, SdocNotificationsView
|
||||
from seahub.api2.endpoints.repo_file_uploaded_bytes import RepoFileUploadedBytesView
|
||||
from seahub.api2.endpoints.user_avatar import UserAvatarView
|
||||
from seahub.api2.endpoints.wikis import WikisView, WikiView
|
||||
@@ -522,7 +522,8 @@ urlpatterns = [
|
||||
|
||||
re_path(r'^api/v2.1/notifications/$', NotificationsView.as_view(), name='api-v2.1-notifications'),
|
||||
re_path(r'^api/v2.1/notification/$', NotificationView.as_view(), name='api-v2.1-notification'),
|
||||
re_path(r'^api/v2.1/sdoc-notifications/$', SdocNotificationView.as_view(), name='api-v2.1-sdoc-notifications'),
|
||||
re_path(r'^api/v2.1/sdoc-notifications/$', SdocNotificationsView.as_view(), name='api-v2.1-sdoc-notifications'),
|
||||
re_path(r'^api/v2.1/sdoc-notification/$', SdocNotificationView.as_view(), name='api-v2.1-notification'),
|
||||
|
||||
## user::invitations
|
||||
re_path(r'^api/v2.1/invitations/$', InvitationsView.as_view()),
|
||||
|
Reference in New Issue
Block a user