diff --git a/frontend/src/components/common/notification.js b/frontend/src/components/common/notification.js
index 09104e36ab..67b1b86786 100644
--- a/frontend/src/components/common/notification.js
+++ b/frontend/src/components/common/notification.js
@@ -19,7 +19,8 @@ class Notification extends React.Component {
});
}
- onClick = () => {
+ onClick = (e) => {
+ e.preventDefault();
if (this.state.showNotice) {
seafileAPI.updateNotifications();
this.setState({
@@ -35,7 +36,7 @@ class Notification extends React.Component {
loadNotices = () => {
let page = 1;
let perPage = 5;
- seafileAPI.listPopupNotices(page, perPage).then(res => {
+ seafileAPI.listNotifications(page, perPage).then(res => {
let noticeList = res.data.notification_list;
this.setState({noticeList: noticeList});
});
@@ -61,7 +62,7 @@ class Notification extends React.Component {
return (
-
+
{this.state.unseenCount}
diff --git a/frontend/src/css/user-notifications.css b/frontend/src/css/user-notifications.css
new file mode 100644
index 0000000000..540240785f
--- /dev/null
+++ b/frontend/src/css/user-notifications.css
@@ -0,0 +1,17 @@
+body {
+ overflow: hidden;
+}
+#wrapper {
+ height: 100%;
+}
+.top-header {
+ background: #f4f4f7;
+ border-bottom: 1px solid #e8e8e8;
+ padding: .5rem 1rem;
+ flex-shrink: 0;
+}
+.op-bar {
+ padding: 9px 10px;
+ background: #f2f2f2;
+ border-radius: 2px;
+}
diff --git a/frontend/src/user-notifications.js b/frontend/src/user-notifications.js
new file mode 100644
index 0000000000..d6d1f154b3
--- /dev/null
+++ b/frontend/src/user-notifications.js
@@ -0,0 +1,215 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { navigate } from '@reach/router';
+import { Utils } from './utils/utils';
+import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants';
+import { seafileAPI } from './utils/seafile-api';
+import Loading from './components/loading';
+import Paginator from './components/paginator';
+import CommonToolbar from './components/toolbar/common-toolbar';
+import NoticeItem from './components/common/notice-item';
+
+import './css/toolbar.css';
+import './css/search.css';
+
+import './css/user-notifications.css';
+
+class UserNotifications extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isLoading: true,
+ errorMsg: '',
+ currentPage: 1,
+ perPage: 25,
+ hasNextPage: false,
+ items: []
+ };
+ }
+
+ componentDidMount() {
+ let urlParams = (new URL(window.location)).searchParams;
+ const {
+ currentPage, perPage
+ } = this.state;
+ this.setState({
+ perPage: parseInt(urlParams.get('per_page') || perPage),
+ currentPage: parseInt(urlParams.get('page') || currentPage)
+ }, () => {
+ this.getItems(this.state.currentPage);
+ });
+ }
+
+ getItems = (page) => {
+ const { perPage } = this.state;
+ seafileAPI.listNotifications(page, perPage).then((res) => {
+ this.setState({
+ isLoading: false,
+ items: res.data.notification_list,
+ currentPage: page,
+ hasNextPage: Utils.hasNextPage(page, perPage, res.data.count)
+ });
+ }).catch((error) => {
+ this.setState({
+ isLoading: false,
+ errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
+ });
+ });
+ }
+
+ resetPerPage = (perPage) => {
+ this.setState({
+ perPage: perPage
+ }, () => {
+ this.getItems(1);
+ });
+ }
+
+ onSearchedClick = (selectedItem) => {
+ if (selectedItem.is_dir === true) {
+ let url = siteRoot + 'library/' + selectedItem.repo_id + '/' + selectedItem.repo_name + selectedItem.path;
+ navigate(url, {repalce: true});
+ } else {
+ let url = siteRoot + 'lib/' + selectedItem.repo_id + '/file' + Utils.encodePath(selectedItem.path);
+ let newWindow = window.open('about:blank');
+ newWindow.location.href = url;
+ }
+ }
+
+ markAllRead = () => {
+ seafileAPI.updateNotifications().then((res) => {
+ this.setState({
+ 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 = () => {
+ seafileAPI.deleteNotifications().then((res) => {
+ this.setState({
+ items: []
+ });
+ }).catch((error) => {
+ this.setState({
+ isLoading: false,
+ errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
+ });
+ });
+ }
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
{gettext('Notifications')}
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+class Content extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.theadData = [
+ {width: '7%', text: ''},
+ {width: '73%', text: gettext('Message')},
+ {width: '20%', text: gettext('Time')}
+ ];
+ }
+
+ getPreviousPage = () => {
+ this.props.getListByPage(this.props.currentPage - 1);
+ }
+
+ getNextPage = () => {
+ this.props.getListByPage(this.props.currentPage + 1);
+ }
+
+ render() {
+ const {
+ isLoading, errorMsg, items,
+ curPerPage, currentPage, hasNextPage
+ } = this.props;
+
+ if (isLoading) {
+ return
;
+ }
+
+ if (errorMsg) {
+ return
{errorMsg}
;
+ }
+
+ return (
+
+
+
+
+ {this.theadData.map((item, index) => {
+ return {item.text} | ;
+ })}
+
+
+
+ {items.map((item, index) => {
+ return ();
+ })}
+
+
+ {items.length > 0 &&
+
+ }
+
+ );
+ }
+}
+
+ReactDOM.render(
+
,
+ document.getElementById('wrapper')
+);
diff --git a/media/css/seahub.css b/media/css/seahub.css
index c399e818e5..d16e3ef73c 100644
--- a/media/css/seahub.css
+++ b/media/css/seahub.css
@@ -2006,37 +2006,6 @@ a.sf-popover-item {
width:180px;
}
-/* notice page */
-#notices-table .unread {
- font-weight:bold;
-}
-#notices-table .avatar-cell {
- vertical-align:top;
- text-align:center;
- padding-top:8px;
-}
-#notices-table .avatar {
- border-radius:1000px;
-}
-#notices-table .brief,
-#notices-table .detail {
- margin:0.2em 100px .2em 0;
-}
-#notices-table .detail {
- color:#9d9b9c;
- cursor:pointer;
- font-weight:normal;
-}
-#notice-list .topic,
-#notices-table .topic {
- padding:4px 13px;
- border-left:3px solid #e0e0e0;
- margin-left:7px;
-}
-#notices-table a {
- font-weight:normal;
-}
-
/* pwd strength */
#pwd_strength {
margin:-15px 0 20px;
diff --git a/media/css/seahub_react.css b/media/css/seahub_react.css
index b19589c2bd..c3b6a7bc83 100644
--- a/media/css/seahub_react.css
+++ b/media/css/seahub_react.css
@@ -218,6 +218,16 @@ a:hover { color:#eb8205; }
cursor: pointer;
}
+.op-bar-btn {
+ border-color: #ccc;
+ border-radius: 2px;
+ height: 30px;
+ line-height: 28px;
+ font-weight: normal;
+ padding: 0 0.5rem;
+ min-width: 55px;
+}
+
/* UI Widget */
/**** caret ****/
diff --git a/seahub/notifications/templates/notifications/user_notification_list.html b/seahub/notifications/templates/notifications/user_notification_list.html
deleted file mode 100644
index 09e3339ce8..0000000000
--- a/seahub/notifications/templates/notifications/user_notification_list.html
+++ /dev/null
@@ -1,98 +0,0 @@
-{% extends "base_wide_page.html" %}
-{% load avatar_tags i18n seahub_tags %}
-
-{% block sub_title %}{% trans "Notices" %} - {% endblock %}
-
-{% block wide_page_content %}
-
-
-
-
-
-
-
-
-{% if notices %}
-
-
-
- |
- {% trans "Message"%} |
- {% trans "Time"%} |
-
-
-
- {% include "notifications/user_notification_tr.html" %}
-
-
-{% if notices_more %}
-
-
-
-
-
-{% endif %}
-{% endif %}
-{% endblock %}
-
-{% block extra_script %}
-
-{% endblock %}
diff --git a/seahub/notifications/templates/notifications/user_notification_list_react.html b/seahub/notifications/templates/notifications/user_notification_list_react.html
new file mode 100644
index 0000000000..999855561e
--- /dev/null
+++ b/seahub/notifications/templates/notifications/user_notification_list_react.html
@@ -0,0 +1,18 @@
+{% extends 'base_for_react.html' %}
+{% load seahub_tags i18n %}
+{% load render_bundle from webpack_loader %}
+
+{% block sub_title %}{% trans "Notifications" %} - {% endblock %}
+
+{% block extra_style %}
+{% render_bundle 'userNotifications' 'css' %}
+{% endblock %}
+
+{% block extra_script %}
+
+{% render_bundle 'userNotifications' 'js' %}
+{% endblock %}
diff --git a/seahub/notifications/templates/notifications/user_notification_tr.html b/seahub/notifications/templates/notifications/user_notification_tr.html
deleted file mode 100644
index 5e64b388db..0000000000
--- a/seahub/notifications/templates/notifications/user_notification_tr.html
+++ /dev/null
@@ -1,48 +0,0 @@
-{% load i18n seahub_tags avatar_tags %}
- {% for notice in notices %}
- {% if notice.seen %}
-
- {% else %}
-
- {% endif %}
-
-
- {% if notice.msg_from %}
- {% avatar notice.msg_from 32 %}
- {% else %}
-
- {% endif %}
- |
-
- {% if notice.is_file_uploaded_msg %}
- {{ notice.format_file_uploaded_msg|safe }}
-
- {% elif notice.is_repo_share_msg %}
- {{ notice.format_repo_share_msg|safe }}
-
- {% elif notice.is_repo_share_to_group_msg %}
- {{ notice.format_repo_share_to_group_msg|safe }}
-
- {% elif notice.is_group_join_request %}
- {{ notice.format_group_join_request|safe }}
-
- {% elif notice.is_file_comment_msg %}
- {{ notice.format_file_comment_msg|safe }}
-
- {% elif notice.is_draft_comment_msg %}
- {{ notice.format_draft_comment_msg|safe }}
-
- {% elif notice.is_draft_reviewer_msg %}
- {{ notice.format_draft_reviewer_msg|safe }}
-
- {% elif notice.is_guest_invitation_accepted_msg %}
- {{ notice.format_guest_invitation_accepted_msg|safe }}
-
- {% elif notice.is_add_user_to_group %}
- {{ notice.format_add_user_to_group|safe }}
-
- {% endif %}
- |
- {{ notice.timestamp|translate_seahub_time }} |
-
- {% endfor %}
diff --git a/seahub/notifications/urls.py b/seahub/notifications/urls.py
index da2bd72984..a120def7d5 100644
--- a/seahub/notifications/urls.py
+++ b/seahub/notifications/urls.py
@@ -5,6 +5,4 @@ from .views import *
urlpatterns = [
########## user notifications
url(r'^list/$', user_notification_list, name='user_notification_list'),
- url(r'^more/$', user_notification_more, name='user_notification_more'),
- url(r'^remove/$', user_notification_remove, name='user_notification_remove'),
]
diff --git a/seahub/notifications/views.py b/seahub/notifications/views.py
index 82baf0d25a..f9e3471464 100644
--- a/seahub/notifications/views.py
+++ b/seahub/notifications/views.py
@@ -22,74 +22,8 @@ logger = logging.getLogger(__name__)
########## user notifications
@login_required
def user_notification_list(request):
- """
-
- Arguments:
- - `request`:
- """
- username = request.user.username
- count = 25 # initial notification count
- limit = 25 # next a mount of notifications fetched by AJAX
-
- notices = UserNotification.objects.get_user_notifications(username)[:count]
-
- # Add 'msg_from' or 'default_avatar_url' to notice.
- notices = add_notice_from_info(notices)
-
- notices_more = True if len(notices) == count else False
-
- return render(request, "notifications/user_notification_list.html", {
- 'notices': notices,
- 'start': count,
- 'limit': limit,
- 'notices_more': notices_more,
- })
-
-@login_required_ajax
-def user_notification_more(request):
- """Fetch next ``limit`` notifications starts from ``start``.
-
- Arguments:
- - `request`:
- - `start`:
- - `limit`:
- """
- username = request.user.username
- start = int(request.GET.get('start', 0))
- limit = int(request.GET.get('limit', 0))
-
- notices = UserNotification.objects.get_user_notifications(username)[
- start: start+limit]
-
- # Add 'msg_from' or 'default_avatar_url' to notice.
- notices = add_notice_from_info(notices)
-
- notices_more = True if len(notices) == limit else False
- new_start = start+limit
-
- ctx = {'notices': notices}
- html = render_to_string("notifications/user_notification_tr.html", ctx)
-
- ct = 'application/json; charset=utf-8'
- return HttpResponse(json.dumps({
- 'html':html,
- 'notices_more':notices_more,
- 'new_start': new_start}), content_type=ct)
-
-@login_required
-def user_notification_remove(request):
- """
-
- Arguments:
- - `request`:
- """
- UserNotification.objects.remove_user_notifications(request.user.username)
-
- messages.success(request, _("Successfully cleared all notices."))
- next_page = request.META.get('HTTP_REFERER', None)
- if not next_page:
- next_page = settings.SITE_ROOT
- return HttpResponseRedirect(next_page)
+ return render(request, "notifications/user_notification_list_react.html", {
+ })
def add_notice_from_info(notices):
'''Add 'msg_from' or 'default_avatar_url' to notice.