mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-17 07:41:26 +00:00
complete
This commit is contained in:
@@ -13,15 +13,17 @@ class Notification extends React.Component {
|
|||||||
this.state = {
|
this.state = {
|
||||||
showNotice: false,
|
showNotice: false,
|
||||||
unseenCount: 0,
|
unseenCount: 0,
|
||||||
noticeList: [],
|
generalNoticeList: [],
|
||||||
|
discussionNoticeList: [],
|
||||||
currentTab: 'general',
|
currentTab: 'general',
|
||||||
isShowNotificationDialog: this.getInitDialogState(),
|
isShowNotificationDialog: this.getInitDialogState(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
seafileAPI.getUnseenNotificationCount().then(res => {
|
seafileAPI.listAllNotifications().then(res => {
|
||||||
this.setState({ unseenCount: res.data.unseen_count });
|
let unseen_count = res.data.general_notification.unseen_count + res.data.discussion_notification.unseen_count;
|
||||||
|
this.setState({ unseenCount: unseen_count });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,50 +47,52 @@ class Notification extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
showNotice: true,
|
showNotice: true,
|
||||||
currentTab: tab
|
currentTab: tab
|
||||||
}, () => {
|
|
||||||
this.loadNotices();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
loadNotices = () => {
|
loadNotices = () => {
|
||||||
let page = 1;
|
let page = 1;
|
||||||
let perPage = 5;
|
let perPage = 5;
|
||||||
if (this.state.currentTab === 'general') {
|
seafileAPI.listAllNotifications(page, perPage).then(res => {
|
||||||
seafileAPI.listNotifications(page, perPage).then(res => {
|
let generalNoticeList = res.data.general_notification.notification_list;
|
||||||
let noticeList = res.data.notification_list;
|
let discussionNoticeList = res.data.discussion_notification.notification_list;
|
||||||
this.setState({ noticeList: noticeList });
|
this.setState({
|
||||||
|
generalNoticeList: generalNoticeList,
|
||||||
|
discussionNoticeList: discussionNoticeList
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
if (this.state.currentTab === 'discussion') {
|
|
||||||
seafileAPI.listSdocNotifications(page, perPage).then(res => {
|
|
||||||
let noticeList = res.data.notification_list;
|
|
||||||
this.setState({ noticeList: noticeList });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onNoticeItemClick = (noticeItem) => {
|
onNoticeItemClick = (noticeItem) => {
|
||||||
let noticeList = this.state.noticeList.map(item => {
|
|
||||||
if (item.id === noticeItem.id) {
|
|
||||||
item.seen = true;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.state.currentTab === 'general') {
|
if (this.state.currentTab === 'general') {
|
||||||
|
let noticeList = this.state.generalNoticeList.map(item => {
|
||||||
|
if (item.id === noticeItem.id) {
|
||||||
|
item.seen = true;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
|
||||||
|
this.setState({
|
||||||
|
generalNoticeList: noticeList,
|
||||||
|
unseenCount: unseenCount,
|
||||||
|
});
|
||||||
seafileAPI.markNoticeAsRead(noticeItem.id);
|
seafileAPI.markNoticeAsRead(noticeItem.id);
|
||||||
}
|
}
|
||||||
if (this.state.currentTab === 'discussion') {
|
if (this.state.currentTab === 'discussion') {
|
||||||
|
let noticeList = this.state.discussionNoticeList.map(item => {
|
||||||
|
if (item.id === noticeItem.id) {
|
||||||
|
item.seen = true;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
|
||||||
|
this.setState({
|
||||||
|
discussionNoticeList: noticeList,
|
||||||
|
unseenCount: unseenCount,
|
||||||
|
});
|
||||||
seafileAPI.markSdocNoticeAsRead(noticeItem.id);
|
seafileAPI.markSdocNoticeAsRead(noticeItem.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
let unseenCount = this.state.unseenCount === 0 ? 0 : this.state.unseenCount - 1;
|
|
||||||
this.setState({
|
|
||||||
noticeList: noticeList,
|
|
||||||
unseenCount: unseenCount,
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
getInitDialogState = () => {
|
getInitDialogState = () => {
|
||||||
@@ -137,15 +141,27 @@ class Notification extends React.Component {
|
|||||||
onMarkAllNotifications={this.onMarkAllNotifications}
|
onMarkAllNotifications={this.onMarkAllNotifications}
|
||||||
tabItemClick={this.tabItemClick}
|
tabItemClick={this.tabItemClick}
|
||||||
>
|
>
|
||||||
<ul className="notice-list list-unstyled" id="notice-popover">
|
{this.state.currentTab === 'general' &&
|
||||||
{this.state.noticeList.map(item => {
|
<ul className="notice-list list-unstyled" id="notice-popover">
|
||||||
return (<NoticeItem key={item.id} noticeItem={item} onNoticeItemClick={this.onNoticeItemClick}/>);
|
{this.state.generalNoticeList.map(item => {
|
||||||
})}
|
return (<NoticeItem key={item.id} noticeItem={item} onNoticeItemClick={this.onNoticeItemClick}/>);
|
||||||
</ul>
|
})}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
{this.state.currentTab === 'discussion' &&
|
||||||
|
<ul className="notice-list list-unstyled" id="notice-popover">
|
||||||
|
{this.state.discussionNoticeList.map(item => {
|
||||||
|
return (<NoticeItem key={item.id} noticeItem={item} onNoticeItemClick={this.onNoticeItemClick}/>);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
</NotificationPopover>
|
</NotificationPopover>
|
||||||
}
|
}
|
||||||
{this.state.isShowNotificationDialog &&
|
{this.state.isShowNotificationDialog &&
|
||||||
<UserNotificationsDialog onNotificationDialogToggle={this.onNotificationDialogToggle} />
|
<UserNotificationsDialog
|
||||||
|
onNotificationDialogToggle={this.onNotificationDialogToggle}
|
||||||
|
tabItemClick={this.tabItemClick}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -1,6 +1,16 @@
|
|||||||
import React from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Modal, ModalHeader, ModalBody, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
|
import {
|
||||||
|
Modal,
|
||||||
|
ModalHeader,
|
||||||
|
ModalBody,
|
||||||
|
Dropdown,
|
||||||
|
DropdownToggle,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownItem,
|
||||||
|
TabPane,
|
||||||
|
Nav, NavItem, NavLink, TabContent
|
||||||
|
} from 'reactstrap';
|
||||||
import { Utils } from './utils/utils';
|
import { Utils } from './utils/utils';
|
||||||
import { gettext } from './utils/constants';
|
import { gettext } from './utils/constants';
|
||||||
import { seafileAPI } from './utils/seafile-api';
|
import { seafileAPI } from './utils/seafile-api';
|
||||||
@@ -24,6 +34,7 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
hasNextPage: false,
|
hasNextPage: false,
|
||||||
items: [],
|
items: [],
|
||||||
isItemMenuShow: false,
|
isItemMenuShow: false,
|
||||||
|
activeTab: 'general',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,56 +48,132 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getItems = (page) => {
|
getItems = (page, is_scroll = false) => {
|
||||||
this.setState({ isLoading: true });
|
this.setState({ isLoading: true });
|
||||||
seafileAPI.listNotifications(page, PER_PAGE).then((res) => {
|
if (this.state.activeTab === 'general') {
|
||||||
this.setState({
|
seafileAPI.listNotifications(page, PER_PAGE).then((res) => {
|
||||||
isLoading: false,
|
if (is_scroll) {
|
||||||
items: [...this.state.items, ...res.data.notification_list],
|
this.setState({
|
||||||
currentPage: page,
|
isLoading: false,
|
||||||
hasNextPage: Utils.hasNextPage(page, PER_PAGE, res.data.count)
|
items: [...this.state.items, ...res.data.notification_list],
|
||||||
|
currentPage: page,
|
||||||
|
hasNextPage: Utils.hasNextPage(page, PER_PAGE, res.data.count)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
items: [...res.data.notification_list],
|
||||||
|
currentPage: page,
|
||||||
|
hasNextPage: Utils.hasNextPage(page, PER_PAGE, res.data.count)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).catch((error) => {
|
} else if (this.state.activeTab === 'discussion') {
|
||||||
this.setState({
|
seafileAPI.listSdocNotifications(page, PER_PAGE).then((res) => {
|
||||||
isLoading: false,
|
if (is_scroll) {
|
||||||
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
items: [...this.state.items, ...res.data.notification_list],
|
||||||
|
currentPage: page,
|
||||||
|
hasNextPage: Utils.hasNextPage(page, PER_PAGE, res.data.count)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
items: [...res.data.notification_list],
|
||||||
|
currentPage: page,
|
||||||
|
hasNextPage: Utils.hasNextPage(page, PER_PAGE, res.data.count)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
markAllRead = () => {
|
markAllRead = () => {
|
||||||
seafileAPI.updateNotifications().then((res) => {
|
if (this.state.activeTab === 'general') {
|
||||||
this.setState({
|
seafileAPI.updateNotifications().then((res) => {
|
||||||
items: this.state.items.map(item => {
|
this.setState({
|
||||||
item.seen = true;
|
items: this.state.items.map(item => {
|
||||||
return item;
|
item.seen = true;
|
||||||
})
|
return item;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).catch((error) => {
|
} else if (this.state.activeTab === 'discussion') {
|
||||||
this.setState({
|
seafileAPI.updateSdocNotifications().then((res) => {
|
||||||
isLoading: false,
|
this.setState({
|
||||||
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
items: this.state.items.map(item => {
|
||||||
|
item.seen = true;
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
clearAll = () => {
|
clearAll = () => {
|
||||||
seafileAPI.deleteNotifications().then((res) => {
|
if (this.state.activeTab === 'general') {
|
||||||
this.setState({
|
seafileAPI.deleteNotifications().then((res) => {
|
||||||
items: []
|
this.setState({
|
||||||
|
items: []
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).catch((error) => {
|
} else if (this.state.activeTab === 'discussion') {
|
||||||
this.setState({
|
seafileAPI.deleteSdocNotifications().then((res) => {
|
||||||
isLoading: false,
|
this.setState({
|
||||||
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
items: []
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
toggle = () => {
|
toggle = () => {
|
||||||
this.props.onNotificationDialogToggle();
|
this.props.onNotificationDialogToggle();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
tabItemClick = (e) => {
|
||||||
|
let tab = e.target.getAttribute('value');
|
||||||
|
this.setState({
|
||||||
|
activeTab: tab,
|
||||||
|
currentPage: 1
|
||||||
|
}, () => {
|
||||||
|
this.getItems(this.state.currentPage);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
toggleDropDownMenu = () => {
|
toggleDropDownMenu = () => {
|
||||||
this.setState({ isItemMenuShow: !this.state.isItemMenuShow });
|
this.setState({ isItemMenuShow: !this.state.isItemMenuShow });
|
||||||
};
|
};
|
||||||
@@ -96,7 +183,7 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.notificationTableRef.offsetHeight + this.notificationTableRef.scrollTop + 1 >= this.tableRef.offsetHeight) {
|
if (this.notificationTableRef.offsetHeight + this.notificationTableRef.scrollTop + 1 >= this.tableRef.offsetHeight) {
|
||||||
this.getItems(this.state.currentPage + 1);
|
this.getItems(this.state.currentPage + 1, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -130,6 +217,49 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
renderNoticeContent = (content) => {
|
||||||
|
let activeTab = this.state.activeTab;
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<div className="notice-dialog-side">
|
||||||
|
<Nav pills>
|
||||||
|
<NavItem role="tab" aria-selected={activeTab === 'general'} aria-controls="general-notice-panel">
|
||||||
|
<NavLink className={activeTab === 'general' ? 'active' : ''} onClick={this.tabItemClick} tabIndex="0" value="general">
|
||||||
|
{gettext('General')}
|
||||||
|
</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
<NavItem role="tab" aria-selected={activeTab === 'discussion'} aria-controls="discussion-notice-panel">
|
||||||
|
<NavLink className={activeTab === 'discussion' ? 'active' : ''} onClick={this.tabItemClick} tabIndex="1" value="discussion">
|
||||||
|
{gettext('Discussion')}
|
||||||
|
</NavLink>
|
||||||
|
</NavItem>
|
||||||
|
</Nav>
|
||||||
|
</div>
|
||||||
|
<div className="notice-dialog-main">
|
||||||
|
<TabContent activeTab={this.state.activeTab}>
|
||||||
|
{activeTab === 'general' &&
|
||||||
|
<TabPane tabId="general" role="tabpanel" id="general-notice-panel">
|
||||||
|
<div className="notification-dialog-body" ref={ref => this.notificationTableRef = ref}
|
||||||
|
onScroll={this.onHandleScroll}>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</TabPane>
|
||||||
|
}
|
||||||
|
{activeTab === 'discussion' &&
|
||||||
|
<TabPane tabId="discussion" role="tabpanel" id="discussion-notice-panel">
|
||||||
|
<div className="notification-dialog-body" ref={ref => this.notificationTableRef = ref}
|
||||||
|
onScroll={this.onHandleScroll}>
|
||||||
|
{content}
|
||||||
|
</div>
|
||||||
|
</TabPane>
|
||||||
|
}
|
||||||
|
</TabContent>
|
||||||
|
</div>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isLoading, errorMsg, items } = this.state;
|
const { isLoading, errorMsg, items } = this.state;
|
||||||
let content;
|
let content;
|
||||||
@@ -173,9 +303,7 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
zIndex={1046}>
|
zIndex={1046}>
|
||||||
<ModalHeader close={this.renderHeaderRowBtn()} toggle={this.toggle}>{gettext('Notifications')}</ModalHeader>
|
<ModalHeader close={this.renderHeaderRowBtn()} toggle={this.toggle}>{gettext('Notifications')}</ModalHeader>
|
||||||
<ModalBody className="notification-modal-body">
|
<ModalBody className="notification-modal-body">
|
||||||
<div className="notification-dialog-body" ref={ref => this.notificationTableRef = ref} onScroll={this.onHandleScroll}>
|
{this.renderNoticeContent(content)}
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
@@ -184,6 +312,7 @@ class UserNotificationsDialog extends React.Component {
|
|||||||
|
|
||||||
UserNotificationsDialog.propTypes = {
|
UserNotificationsDialog.propTypes = {
|
||||||
onNotificationDialogToggle: PropTypes.func.isRequired,
|
onNotificationDialogToggle: PropTypes.func.isRequired,
|
||||||
|
tabItemClick: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UserNotificationsDialog;
|
export default UserNotificationsDialog;
|
||||||
|
@@ -1451,6 +1451,15 @@ class SeafileAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ---- Notification API
|
// ---- Notification API
|
||||||
|
listAllNotifications(page, perPage) {
|
||||||
|
const url = this.server + '/api/v2.1/all-notifications/';
|
||||||
|
let params = {
|
||||||
|
page: page,
|
||||||
|
per_page: perPage
|
||||||
|
};
|
||||||
|
return this.req.get(url, { params: params });
|
||||||
|
}
|
||||||
|
|
||||||
listNotifications(page, perPage) {
|
listNotifications(page, perPage) {
|
||||||
const url = this.server + '/api/v2.1/notifications/';
|
const url = this.server + '/api/v2.1/notifications/';
|
||||||
let params = {
|
let params = {
|
||||||
@@ -1485,6 +1494,11 @@ class SeafileAPI {
|
|||||||
return this.req.delete(url);
|
return this.req.delete(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deleteSdocNotifications() {
|
||||||
|
const url = this.server + '/api/v2.1/sdoc-notifications/';
|
||||||
|
return this.req.delete(url);
|
||||||
|
}
|
||||||
|
|
||||||
getUnseenNotificationCount() {
|
getUnseenNotificationCount() {
|
||||||
const url = this.server + '/api/v2.1/notifications/';
|
const url = this.server + '/api/v2.1/notifications/';
|
||||||
return this.req.get(url);
|
return this.req.get(url);
|
||||||
|
@@ -227,7 +227,7 @@ class SdocNotificationsView(APIView):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
username = request.user.username
|
username = request.user.username
|
||||||
unseen_notices = SeadocNotification.objects.filter(username, seen=False)
|
unseen_notices = SeadocNotification.objects.filter(username=username, seen=False)
|
||||||
for notice in unseen_notices:
|
for notice in unseen_notices:
|
||||||
notice.seen = True
|
notice.seen = True
|
||||||
notice.save()
|
notice.save()
|
||||||
@@ -236,6 +236,21 @@ class SdocNotificationsView(APIView):
|
|||||||
cache.delete(cache_key)
|
cache.delete(cache_key)
|
||||||
|
|
||||||
return Response({'success': True})
|
return Response({'success': True})
|
||||||
|
|
||||||
|
def delete(self, request):
|
||||||
|
""" delete a sdoc notification by username
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
1. login user.
|
||||||
|
"""
|
||||||
|
username = request.user.username
|
||||||
|
|
||||||
|
SeadocNotification.objects.remove_user_notifications(username)
|
||||||
|
|
||||||
|
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||||
|
cache.delete(cache_key)
|
||||||
|
|
||||||
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -283,4 +298,97 @@ class SdocNotificationView(APIView):
|
|||||||
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||||
cache.delete(cache_key)
|
cache.delete(cache_key)
|
||||||
|
|
||||||
return Response({'success': True})
|
return Response({'success': True})
|
||||||
|
|
||||||
|
|
||||||
|
class AllNotificationsView(APIView):
|
||||||
|
|
||||||
|
authentication_classes = (TokenAuthentication, SessionAuthentication)
|
||||||
|
permission_classes = (IsAuthenticated,)
|
||||||
|
throttle_classes = (UserRateThrottle,)
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
""" used for get all notifications
|
||||||
|
general and discussion
|
||||||
|
|
||||||
|
Permission checking:
|
||||||
|
1. login user.
|
||||||
|
"""
|
||||||
|
result = {
|
||||||
|
'general_notification': {},
|
||||||
|
'discussion_notification': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
username = request.user.username
|
||||||
|
|
||||||
|
try:
|
||||||
|
per_page = int(request.GET.get('per_page', ''))
|
||||||
|
page = int(request.GET.get('page', ''))
|
||||||
|
except ValueError:
|
||||||
|
per_page = 25
|
||||||
|
page = 1
|
||||||
|
|
||||||
|
start = (page - 1) * per_page
|
||||||
|
end = page * per_page
|
||||||
|
|
||||||
|
notice_list = UserNotification.objects.get_user_notifications(username)[start:end]
|
||||||
|
sdoc_notice_list = SeadocNotification.objects.list_all_by_user(username, start, end)
|
||||||
|
|
||||||
|
result_notices = update_notice_detail(request, notice_list)
|
||||||
|
sdoc_result_notices = update_sdoc_notice_detail(request, sdoc_notice_list)
|
||||||
|
|
||||||
|
notification_list = []
|
||||||
|
sdoc_notification_list = []
|
||||||
|
|
||||||
|
for i in result_notices:
|
||||||
|
if i.detail is not None:
|
||||||
|
notice = {}
|
||||||
|
notice['id'] = i.id
|
||||||
|
notice['type'] = i.msg_type
|
||||||
|
notice['detail'] = i.detail
|
||||||
|
notice['time'] = datetime_to_isoformat_timestr(i.timestamp)
|
||||||
|
notice['seen'] = i.seen
|
||||||
|
|
||||||
|
notification_list.append(notice)
|
||||||
|
|
||||||
|
for i in sdoc_result_notices:
|
||||||
|
if i.detail is not None:
|
||||||
|
notice = {}
|
||||||
|
notice['id'] = i.id
|
||||||
|
notice['type'] = i.msg_type
|
||||||
|
notice['detail'] = i.detail
|
||||||
|
notice['time'] = datetime_to_isoformat_timestr(i.created_at)
|
||||||
|
notice['seen'] = i.seen
|
||||||
|
|
||||||
|
sdoc_notification_list.append(notice)
|
||||||
|
|
||||||
|
cache_key = get_cache_key_of_unseen_notifications(username)
|
||||||
|
unseen_count_from_cache = cache.get(cache_key, None)
|
||||||
|
|
||||||
|
sdoc_cache_key = get_cache_key_of_unseen_sdoc_notifications(username)
|
||||||
|
sdoc_unseen_count_from_cache = cache.get(sdoc_cache_key, None)
|
||||||
|
|
||||||
|
# for case of count value is `0`
|
||||||
|
if unseen_count_from_cache is not None:
|
||||||
|
result['general_notification']['unseen_count'] = unseen_count_from_cache
|
||||||
|
else:
|
||||||
|
unseen_count = UserNotification.objects.filter(to_user=username, seen=False).count()
|
||||||
|
result['general_notification']['unseen_count'] = unseen_count
|
||||||
|
cache.set(cache_key, unseen_count)
|
||||||
|
|
||||||
|
if sdoc_unseen_count_from_cache is not None:
|
||||||
|
result['discussion_notification']['unseen_count'] = sdoc_unseen_count_from_cache
|
||||||
|
else:
|
||||||
|
sdoc_unseen_count = SeadocNotification.objects.filter(username=username, seen=False).count()
|
||||||
|
result['discussion_notification']['unseen_count'] = sdoc_unseen_count
|
||||||
|
cache.set(sdoc_cache_key, sdoc_unseen_count)
|
||||||
|
|
||||||
|
total_count = UserNotification.objects.filter(to_user=username).count()
|
||||||
|
sdoc_total_count = SeadocNotification.objects.filter(username=username).count()
|
||||||
|
|
||||||
|
result['general_notification']['notification_list'] = notification_list
|
||||||
|
result['discussion_notification']['notification_list'] = sdoc_notification_list
|
||||||
|
result['general_notification']['count'] = total_count
|
||||||
|
result['discussion_notification']['count'] = sdoc_total_count
|
||||||
|
|
||||||
|
return Response(result)
|
@@ -272,6 +272,10 @@ class SeadocNotificationManager(models.Manager):
|
|||||||
|
|
||||||
def list_all_by_user(self, username, start, end):
|
def list_all_by_user(self, username, start, end):
|
||||||
return self.filter(username=username).order_by('-created_at')[start: end]
|
return self.filter(username=username).order_by('-created_at')[start: end]
|
||||||
|
|
||||||
|
def remove_user_notifications(self, username):
|
||||||
|
""""Remove all user notifications."""
|
||||||
|
self.filter(username=username).delete()
|
||||||
|
|
||||||
|
|
||||||
class SeadocNotification(models.Model):
|
class SeadocNotification(models.Model):
|
||||||
|
@@ -91,7 +91,7 @@ from seahub.api2.endpoints.invitations import InvitationsView, InvitationsBatchV
|
|||||||
from seahub.api2.endpoints.invitation import InvitationView, InvitationRevokeView
|
from seahub.api2.endpoints.invitation import InvitationView, InvitationRevokeView
|
||||||
from seahub.api2.endpoints.repo_share_invitations import RepoShareInvitationsView, RepoShareInvitationsBatchView
|
from seahub.api2.endpoints.repo_share_invitations import RepoShareInvitationsView, RepoShareInvitationsBatchView
|
||||||
from seahub.api2.endpoints.repo_share_invitation import RepoShareInvitationView
|
from seahub.api2.endpoints.repo_share_invitation import RepoShareInvitationView
|
||||||
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView, SdocNotificationView, SdocNotificationsView
|
from seahub.api2.endpoints.notifications import NotificationsView, NotificationView, SdocNotificationView, SdocNotificationsView, AllNotificationsView
|
||||||
from seahub.api2.endpoints.repo_file_uploaded_bytes import RepoFileUploadedBytesView
|
from seahub.api2.endpoints.repo_file_uploaded_bytes import RepoFileUploadedBytesView
|
||||||
from seahub.api2.endpoints.user_avatar import UserAvatarView
|
from seahub.api2.endpoints.user_avatar import UserAvatarView
|
||||||
from seahub.api2.endpoints.wikis import WikisView, WikiView
|
from seahub.api2.endpoints.wikis import WikisView, WikiView
|
||||||
@@ -524,6 +524,7 @@ urlpatterns = [
|
|||||||
re_path(r'^api/v2.1/notification/$', NotificationView.as_view(), name='api-v2.1-notification'),
|
re_path(r'^api/v2.1/notification/$', NotificationView.as_view(), name='api-v2.1-notification'),
|
||||||
re_path(r'^api/v2.1/sdoc-notifications/$', SdocNotificationsView.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'),
|
re_path(r'^api/v2.1/sdoc-notification/$', SdocNotificationView.as_view(), name='api-v2.1-notification'),
|
||||||
|
re_path(r'^api/v2.1/all-notifications/$', AllNotificationsView.as_view(), name='api-v2.1-all-notification'),
|
||||||
|
|
||||||
## user::invitations
|
## user::invitations
|
||||||
re_path(r'^api/v2.1/invitations/$', InvitationsView.as_view()),
|
re_path(r'^api/v2.1/invitations/$', InvitationsView.as_view()),
|
||||||
|
Reference in New Issue
Block a user