mirror of
https://github.com/haiwen/seahub.git
synced 2025-06-25 22:54:07 +00:00
Add notification at info-bar, and fix bug in visiting register/login page when user is already logged in.
This commit is contained in:
parent
28dbc2ad73
commit
f9c72b57a4
@ -1,5 +1,10 @@
|
|||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
from seaserv import get_binding_peerids
|
from seaserv import get_binding_peerids
|
||||||
|
|
||||||
|
from seahub.notifications.models import Notification
|
||||||
|
from seahub.notifications.utils import refresh_cache
|
||||||
|
|
||||||
class UseridMiddleware(object):
|
class UseridMiddleware(object):
|
||||||
"""Store ccnet user ids in request.user.userid_list"""
|
"""Store ccnet user ids in request.user.userid_list"""
|
||||||
|
|
||||||
@ -16,3 +21,30 @@ class UseridMiddleware(object):
|
|||||||
|
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
class InfobarMiddleware(object):
|
||||||
|
"""Query info bar close status, and store into reqeust."""
|
||||||
|
|
||||||
|
def get_from_db(self):
|
||||||
|
ret = Notification.objects.all().filter(primary=1)
|
||||||
|
refresh_cache()
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def process_request(self, request):
|
||||||
|
topinfo_close = request.COOKIES.get('topinfo', '')
|
||||||
|
|
||||||
|
cur_note = cache.get('CUR_TOPINFO') if cache.get('CUR_TOPINFO') else \
|
||||||
|
self.get_from_db()
|
||||||
|
if not cur_note:
|
||||||
|
request.cur_note = None
|
||||||
|
else:
|
||||||
|
if str(cur_note[0].id) in topinfo_close.split(','):
|
||||||
|
request.cur_note = None
|
||||||
|
else:
|
||||||
|
request.cur_note = cur_note[0]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_response(self, request, response):
|
||||||
|
return response
|
||||||
|
|
||||||
|
@ -127,6 +127,12 @@ table img {
|
|||||||
width:680px;
|
width:680px;
|
||||||
}
|
}
|
||||||
#footer { color:#999; padding-top:2px; margin:25px auto; border-top:1px solid #DDD; }
|
#footer { color:#999; padding-top:2px; margin:25px auto; border-top:1px solid #DDD; }
|
||||||
|
|
||||||
|
/* info-bar */
|
||||||
|
#info-bar { height: 30px; color: #fff; background: #000; }
|
||||||
|
#info-bar .info { margin: 5px 0 auto 1em; float: left; }
|
||||||
|
#info-bar .close { margin: 7px 5px auto 0; float: right; background: url(../img/close-16.png); height: 16px; width:16px; }
|
||||||
|
|
||||||
/* top-bar */
|
/* top-bar */
|
||||||
#top-bar { height:20px; padding-bottom:21px; background:#fff url('../img/dropshadow.png') repeat-x center bottom; }
|
#top-bar { height:20px; padding-bottom:21px; background:#fff url('../img/dropshadow.png') repeat-x center bottom; }
|
||||||
.top-bar { height:20px; color:#fff; text-align:right; font-weight:bold; background:#606; }
|
.top-bar { height:20px; color:#fff; text-align:right; font-weight:bold; background:#606; }
|
||||||
@ -331,3 +337,6 @@ h2.repo-history {
|
|||||||
background:transparent url('../img/add.png') scroll no-repeat left 50%;
|
background:transparent url('../img/add.png') scroll no-repeat left 50%;
|
||||||
margin-top:2px;
|
margin-top:2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* notification admin */
|
||||||
|
.cur-note { color: red; font-size: 75%; }
|
||||||
|
0
notifications/__init__.py
Normal file
0
notifications/__init__.py
Normal file
18
notifications/models.py
Normal file
18
notifications/models.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.forms import ModelForm, Textarea
|
||||||
|
|
||||||
|
class Notification(models.Model):
|
||||||
|
message = models.CharField(max_length=512)
|
||||||
|
primary = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
class NotificationForm(ModelForm):
|
||||||
|
"""
|
||||||
|
Form for adding notification.
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
model = Notification
|
||||||
|
fields = ('message', 'primary')
|
||||||
|
widgets = {
|
||||||
|
'message': Textarea(),
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
|||||||
|
{% extends "admin_base.html" %}
|
||||||
|
{% block title %}添加通知{% endblock %}
|
||||||
|
{% block nav_notificationadmin_class %}class="cur"{% endblock %}
|
||||||
|
{% block main_panel %}
|
||||||
|
<div class="narrow-panel">
|
||||||
|
<h3>添加通知</h3>
|
||||||
|
<form action="" method="post">
|
||||||
|
<label for="id_message">通知:</label>
|
||||||
|
{{ form.message }}
|
||||||
|
<input type="submit" value="提交" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
74
notifications/templates/notifications/notification_list.html
Normal file
74
notifications/templates/notifications/notification_list.html
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{% extends "admin_base.html" %}
|
||||||
|
{% block nav_notificationadmin_class %}class="cur"{% endblock %}
|
||||||
|
|
||||||
|
{% block left_panel %}
|
||||||
|
<h3>操作</h3>
|
||||||
|
<ul class="with-bg">
|
||||||
|
<li><a href="{{ SITE_ROOT }}notification/add/">添加新通知</a></li>
|
||||||
|
</ul>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block right_panel %}
|
||||||
|
<h3>所有通知</h3>
|
||||||
|
{% if notes %}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th width="75%">内容</th>
|
||||||
|
<th width="25%">操作</th>
|
||||||
|
</tr>
|
||||||
|
{% for note in notes %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ note.message }}
|
||||||
|
{% if note.primary == 1 %}
|
||||||
|
<span class="cur-note">(当前通知)</span>
|
||||||
|
{% endif %}
|
||||||
|
<td>
|
||||||
|
{% if note.primary != 1 %}
|
||||||
|
<button data="{{ SITE_ROOT }}notification/set-primary/{{ note.id }}/" class="note-change-btn">设为当前通知</button>
|
||||||
|
{% endif %}
|
||||||
|
<button data="{{ SITE_ROOT }}notification/delete/{{ note.id }}/" class="note-delete-btn">删除</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
<!--
|
||||||
|
<div id="paginator">
|
||||||
|
{% if current_page != 1 %}
|
||||||
|
<a href="{{ SITE_ROOT }}seafadmin/?page={{ prev_page }}&per_page={{ per_page }}">上一页</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if page_next %}
|
||||||
|
<a href="{{ SITE_ROOT }}seafadmin/?page={{ next_page }}&per_page={{ per_page }}">下一页</a>
|
||||||
|
{% endif %}
|
||||||
|
<span>每页:</span>
|
||||||
|
{% if per_page == 25 %}
|
||||||
|
<span> 25 </span>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ SITE_ROOT }}seafadmin/?per_page=25" class="per-page">25</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if per_page == 50 %}
|
||||||
|
<span> 50 </span>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ SITE_ROOT }}seafadmin/?per_page=50" class="per-page">50</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if per_page == 100 %}
|
||||||
|
<span> 100 </span>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ SITE_ROOT }}seafadmin/?per_page=100" class="per-page">100</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
{% else %}
|
||||||
|
<p>暂无</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
addConfirmTo($('.note-delete-btn'));
|
||||||
|
|
||||||
|
$('.note-change-btn').click(function() {
|
||||||
|
window.location = $(this).attr('data');
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
16
notifications/tests.py
Normal file
16
notifications/tests.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
This file demonstrates writing tests using the unittest module. These will pass
|
||||||
|
when you run "manage.py test".
|
||||||
|
|
||||||
|
Replace this with more appropriate tests for your application.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleTest(TestCase):
|
||||||
|
def test_basic_addition(self):
|
||||||
|
"""
|
||||||
|
Tests that 1 + 1 always equals 2.
|
||||||
|
"""
|
||||||
|
self.assertEqual(1 + 1, 2)
|
11
notifications/urls.py
Normal file
11
notifications/urls.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from django.conf.urls.defaults import patterns, url
|
||||||
|
|
||||||
|
urlpatterns = patterns('notifications.views',
|
||||||
|
# url(r'^$', 'notification_list', name='notification_list'),
|
||||||
|
url(r'^add/$', 'notification_add', name='notification_add'),
|
||||||
|
url(r'^delete/(?P<nid>[\d]+)/$', 'notification_delete', name='notification_delete'),
|
||||||
|
url(r'^set-primary/(?P<nid>[\d]+)/$', 'set_primary', name='set_primary'),
|
||||||
|
url(r'^close/(?P<note_id>[\d]+)/$', 'notification_close', name='notification_close'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
11
notifications/utils.py
Normal file
11
notifications/utils.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
|
from seahub.notifications.models import Notification
|
||||||
|
|
||||||
|
def refresh_cache():
|
||||||
|
"""
|
||||||
|
Function to be called when change primary notification.
|
||||||
|
"""
|
||||||
|
cache.set('CUR_TOPINFO', Notification.objects.all().filter(primary=1),
|
||||||
|
24*60*60)
|
||||||
|
|
68
notifications/views.py
Normal file
68
notifications/views.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import datetime
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.http import HttpResponseRedirect, Http404
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from django.template import RequestContext
|
||||||
|
|
||||||
|
from auth.decorators import login_required
|
||||||
|
|
||||||
|
from seahub.notifications.models import Notification, NotificationForm
|
||||||
|
from seahub.notifications.utils import refresh_cache
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def notification_close(request, note_id):
|
||||||
|
note_id += ','
|
||||||
|
topinfo_close = request.COOKIES.get('topinfo', '')
|
||||||
|
topinfo_close += note_id
|
||||||
|
|
||||||
|
res = HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||||
|
res.set_cookie("topinfo", topinfo_close, max_age=14*24*60*60)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def notification_list(request):
|
||||||
|
if not request.user.is_staff:
|
||||||
|
raise Http404
|
||||||
|
notes = Notification.objects.all().order_by('-id')
|
||||||
|
|
||||||
|
return render_to_response('notifications/notification_list.html', {
|
||||||
|
'notes': notes,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def notification_add(request):
|
||||||
|
if not request.user.is_staff:
|
||||||
|
raise Http404
|
||||||
|
if request.method == 'POST':
|
||||||
|
f = NotificationForm(request.POST)
|
||||||
|
f.save()
|
||||||
|
return HttpResponseRedirect(reverse('notification_list', args=[]))
|
||||||
|
else:
|
||||||
|
form = NotificationForm()
|
||||||
|
|
||||||
|
return render_to_response("notifications/add_notification_form.html", {
|
||||||
|
'form': form,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def notification_delete(request, nid):
|
||||||
|
if not request.user.is_staff:
|
||||||
|
raise Http404
|
||||||
|
Notification.objects.filter(id=nid).delete()
|
||||||
|
refresh_cache()
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('notification_list', args=[]))
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def set_primary(request, nid):
|
||||||
|
if not request.user.is_staff:
|
||||||
|
raise Http404
|
||||||
|
|
||||||
|
# TODO: use transaction?
|
||||||
|
Notification.objects.filter(primary=1).update(primary=0)
|
||||||
|
Notification.objects.filter(id=nid).update(primary=1)
|
||||||
|
|
||||||
|
refresh_cache()
|
||||||
|
|
||||||
|
return HttpResponseRedirect(reverse('notification_list', args=[]))
|
@ -66,6 +66,7 @@ MIDDLEWARE_CLASSES = (
|
|||||||
'django.middleware.csrf.CsrfResponseMiddleware',
|
'django.middleware.csrf.CsrfResponseMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'auth.middleware.AuthenticationMiddleware',
|
'auth.middleware.AuthenticationMiddleware',
|
||||||
|
'seahub.base.middleware.InfobarMiddleware',
|
||||||
# 'seahub.base.middleware.UseridMiddleware',
|
# 'seahub.base.middleware.UseridMiddleware',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -100,6 +101,7 @@ INSTALLED_APPS = (
|
|||||||
# 'django.contrib.admin',
|
# 'django.contrib.admin',
|
||||||
'registration',
|
'registration',
|
||||||
'avatar',
|
'avatar',
|
||||||
|
'seahub.notifications',
|
||||||
'seahub.base',
|
'seahub.base',
|
||||||
'seahub.profile',
|
'seahub.profile',
|
||||||
'seahub.contacts',
|
'seahub.contacts',
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a href="{{ SITE_ROOT }}groupadmin/" {% block nav_groupadmin_class %}{% endblock %}>小组管理</a>
|
<a href="{{ SITE_ROOT }}groupadmin/" {% block nav_groupadmin_class %}{% endblock %}>小组管理</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ SITE_ROOT }}notificationadmin/" {% block nav_notificationadmin_class %}{% endblock %}>通知管理</a>
|
||||||
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
{% if request.user.is_authenticated and request.cur_note %}
|
||||||
|
<div id="info-bar">
|
||||||
|
<span class="info">{{ request.cur_note.message|urlize }}</span>
|
||||||
|
<a href="{{ SITE_ROOT }}notification/close/{{ request.cur_note.id }}/"><span class="close"></span></a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
<div class="top-bar">
|
<div class="top-bar">
|
||||||
<div class="top-bar-in ovhd">
|
<div class="top-bar-in ovhd">
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
{% block title %}注册{% endblock %}
|
{% block title %}注册{% endblock %}
|
||||||
{% block main_panel %}
|
{% block main_panel %}
|
||||||
<div class="narrow-panel">
|
<div class="narrow-panel">
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
<h2>欢迎回来,您已登录。</h2>
|
||||||
|
{% else %}
|
||||||
<h2>注册</h2>
|
<h2>注册</h2>
|
||||||
<form action="" method="post">
|
<form action="" method="post">
|
||||||
<label for="id_email">邮箱:</label>
|
<label for="id_email">邮箱:</label>
|
||||||
@ -16,6 +19,7 @@
|
|||||||
{{ form.password2.errors }}
|
{{ form.password2.errors }}
|
||||||
<input type="submit" value="提交" />
|
<input type="submit" value="提交" />
|
||||||
</form>
|
</form>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -23,10 +23,14 @@ from seaserv import get_ccnetuser
|
|||||||
@csrf_protect
|
@csrf_protect
|
||||||
@never_cache
|
@never_cache
|
||||||
def login(request, template_name='registration/login.html',
|
def login(request, template_name='registration/login.html',
|
||||||
|
redirect_if_logged_in=None,
|
||||||
redirect_field_name=REDIRECT_FIELD_NAME,
|
redirect_field_name=REDIRECT_FIELD_NAME,
|
||||||
authentication_form=AuthenticationForm):
|
authentication_form=AuthenticationForm):
|
||||||
"""Displays the login form and handles the login action."""
|
"""Displays the login form and handles the login action."""
|
||||||
|
|
||||||
|
if request.user.is_authenticated() and redirect_if_logged_in:
|
||||||
|
return HttpResponseRedirect(reverse(redirect_if_logged_in))
|
||||||
|
|
||||||
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
redirect_to = request.REQUEST.get(redirect_field_name, '')
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
|
@ -30,7 +30,8 @@ from auth import views as auth_views
|
|||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^login/$',
|
url(r'^login/$',
|
||||||
auth_views.login,
|
auth_views.login,
|
||||||
{'template_name': 'registration/login.html'},
|
{'template_name': 'registration/login.html',
|
||||||
|
'redirect_if_logged_in': 'myhome'},
|
||||||
name='auth_login'),
|
name='auth_login'),
|
||||||
url(r'^logout/$',
|
url(r'^logout/$',
|
||||||
auth_views.logout,
|
auth_views.logout,
|
||||||
|
3
urls.py
3
urls.py
@ -9,6 +9,7 @@ from seahub.views import root, peers, myhome, \
|
|||||||
user_info, repo_set_access_property, repo_access_file, \
|
user_info, repo_set_access_property, repo_access_file, \
|
||||||
repo_add_share, repo_list_share, repo_remove_share, repo_download, \
|
repo_add_share, repo_list_share, repo_remove_share, repo_download, \
|
||||||
seafile_access_check, back_local, group_admin, repo_history_changes
|
seafile_access_check, back_local, group_admin, repo_history_changes
|
||||||
|
from seahub.notifications.views import notification_list
|
||||||
|
|
||||||
# Uncomment the next two lines to enable the admin:
|
# Uncomment the next two lines to enable the admin:
|
||||||
#from django.contrib import admin
|
#from django.contrib import admin
|
||||||
@ -59,6 +60,8 @@ urlpatterns = patterns('',
|
|||||||
(r'^useradmin/activate/(?P<user_id>[^/]+)/$', activate_user),
|
(r'^useradmin/activate/(?P<user_id>[^/]+)/$', activate_user),
|
||||||
|
|
||||||
(r'^avatar/', include('avatar.urls')),
|
(r'^avatar/', include('avatar.urls')),
|
||||||
|
(r'^notification/', include('notifications.urls')),
|
||||||
|
url(r'^notificationadmin/', notification_list, name='notification_list'),
|
||||||
(r'^contacts/', include('contacts.urls')),
|
(r'^contacts/', include('contacts.urls')),
|
||||||
(r'^group/', include('seahub.group.urls')),
|
(r'^group/', include('seahub.group.urls')),
|
||||||
url(r'^groupadmin/$', group_admin, name='group_admin'),
|
url(r'^groupadmin/$', group_admin, name='group_admin'),
|
||||||
|
Loading…
Reference in New Issue
Block a user