1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-19 10:26:17 +00:00

Added innpub messages

This commit is contained in:
xiez
2012-09-14 22:15:14 +08:00
parent c8d708980c
commit 32f7463a1d
9 changed files with 396 additions and 20 deletions

View File

@@ -1,6 +1,14 @@
import datetime
import re
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from seaserv import get_emailusers
from shortcuts import get_first_object_or_none
from notifications.models import UserNotification
from profile.models import Profile
class UuidObjidMap(models.Model):
"""
@@ -24,3 +32,105 @@ class FileComment(models.Model):
class Meta:
ordering = ['-timestamp']
class InnerPubMsg(models.Model):
"""
Model used for leave message on inner pub page.
"""
from_email = models.EmailField()
message = models.CharField(max_length=500)
timestamp = models.DateTimeField(default=datetime.datetime.now)
class Meta:
ordering = ['-timestamp']
class InnerPubMsgReply(models.Model):
reply_to = models.ForeignKey(InnerPubMsg)
from_email = models.EmailField()
message = models.CharField(max_length=150)
timestamp = models.DateTimeField(default=datetime.datetime.now)
at_pattern = re.compile(r'(\s|^)(@\w+)', flags=re.U)
@receiver(post_save, sender=InnerPubMsgReply)
def msgreply_save_handler(sender, instance, **kwargs):
"""
Handle sending notification to '@<user>' when reply messages.
"""
from_email = instance.from_email
reply_msg = instance.message
innerpub_msg = instance.reply_to
to_user = ''
m = re.match(at_pattern, reply_msg)
if m:
nickname_or_emailprefix = m.group()[1:]
for member in get_emailusers(-1, -1):
# For every user, get his username and nickname if
# it exists, check whether match.
username = member.email
if username == from_email:
continue
p = get_first_object_or_none(
Profile.objects.filter(user=username))
nickname = p.nickname if p else ''
if nickname == nickname_or_emailprefix or \
username.split('@')[0] == nickname_or_emailprefix:
to_user = username
break
if to_user:
# Send notification to the user if he replies someone else'
# message.
try:
UserNotification.objects.get(to_user=to_user,
msg_type='innerpubmsg_reply',
detail=innerpub_msg.id)
except UserNotification.DoesNotExist:
n = UserNotification(to_user=to_user,
msg_type='innerpubmsg_reply',
detail=innerpub_msg.id)
n.save()
@receiver(post_save, sender=InnerPubMsg)
def innerpub_msg_added_cb(sender, instance, **kwargs):
from_email = instance.from_email
users = get_emailusers(-1, -1)
for u in users:
if u.email == from_email:
continue
try:
UserNotification.objects.get(to_user=u.email,
msg_type='innerpub_msg')
except UserNotification.DoesNotExist:
n = UserNotification(to_user=u.email, msg_type='innerpub_msg',
detail='')
n.save()
@receiver(post_save, sender=InnerPubMsgReply)
def innerpubmsg_reply_added_cb(sender, instance, **kwargs):
innerpub_msg = instance.reply_to
from_email = instance.from_email
msg_id = innerpub_msg.id
if from_email == innerpub_msg.from_email:
# No need to send notification when reply own message.
return
try:
innerpub_msg = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
pass
try:
UserNotification.objects.get(to_user=innerpub_msg.from_email,
msg_type='innerpubmsg_reply',
detail=msg_id)
except UserNotification.DoesNotExist:
n = UserNotification(to_user=innerpub_msg.from_email,
msg_type='innerpubmsg_reply',
detail=msg_id)
n.save()

View File

@@ -2,7 +2,7 @@ from seaserv import ccnet_threaded_rpc
from signals import grpmsg_added
from models import GroupMessage
from seahub.notifications.models import UserNotification
from notifications.models import UserNotification
def grpmsg_added_cb(sender, **kwargs):
group_id = kwargs['group_id']

View File

@@ -6,14 +6,6 @@
{% block nav_group_class %}class="cur"{% endblock %}
{% block main_panel %}
{% if messages %}
<ul class="messages hide">
{% for message in messages %}
<li class="info">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<h2>{{ group.group_name }}</h2>
<div class="side fright">
@@ -125,7 +117,7 @@
{{ msg.message|seahub_urlize|find_at|linebreaksbr }}
</p>
<button class="reply op" data="{{ msg.id }}"><span class="reply-cnt">{% if msg.reply_cnt != 0 %}{{ msg.reply_cnt }} {% endif %}</span>回复</button>
<button class="reply op" data="{% url 'msg_reply' msg.id %}"><span class="reply-cnt">{% if msg.reply_cnt != 0 %}{{ msg.reply_cnt }} {% endif %}</span>回复</button>
<button class="replyclose op hide">收起回复</button>
<div class="reply-bd"></div>
</div>

View File

@@ -8,7 +8,7 @@ $('.reply, .replyclose').hover(
);
$('.reply').click(function() {
var myself = $(this),
msg_id = $(this).attr('data'),
msg_reply_url = $(this).attr('data'),
msg_bd = $(this).parent(),
reply_cnt = msg_bd.find('.reply-cnt'),
reply_bd = msg_bd.children('.reply-bd');
@@ -30,7 +30,7 @@ $('.reply').click(function() {
if (reply && reply.length <= 150) {
$.ajax({
type: "POST",
url: '{{ SITE_ROOT }}group/reply/' + msg_id + '/',
url: msg_reply_url,
dataType: 'json',
cache: false,
contentType: 'application/json; charset=utf-8',
@@ -56,7 +56,7 @@ $('.reply').click(function() {
} else {
reply_bd.html('<img src="{{MEDIA_URL}}img/loading-icon.gif" alt="加载中..." />');
$.ajax({
url: '{{ SITE_ROOT }}group/reply/' + msg_id + '/',
url: msg_reply_url,
dataType: 'json',
success: function(data) {
reply_bd.html(data['html']).attr('class', 'reply-bd');

View File

@@ -30,6 +30,12 @@
{% if grpmsg_reply_list %}
<li><a href="{{ SITE_ROOT }}group/reply/new/" class="no-bold">{{ grpmsg_reply_list|length }}条留言有新回复</a></li>
{% endif %}
{% if new_innerpub_msg %}
<li><a href="{% url 'public_home' %}" class="no-bold">公共页面有新留言</a></li>
{% endif %}
{% if innerpubmsg_reply_list %}
<li><a href="{% url 'innerpub_msg_reply_new' %}" class="no-bold">{{ innerpubmsg_reply_list|length }}条留言有新回复</a></li>
{% endif %}
{% if orgmsg_list %}
<li><a href="{% url 'org_msg' %}" class="no-bold">{{ orgmsg_list|length }}条团体消息</a></li>
{% endif %}

View File

@@ -0,0 +1,95 @@
{% extends "myhome_base.html" %}
{% load seahub_tags avatar_tags %}
{% load url from future %}
{% block right_panel %}
{% if innerpub_msgs %}
<ul class="msg-list">
{% for msg in innerpub_msgs %}
<li class="msg w100 ovhd">
<div class="pic fleft">
<a href="{% url 'user_profile' msg.from_email %}">{% avatar msg.from_email 48 %}</a>
</div>
<div class="txt fright">
<div class="msg-hd">
<span class="time">{{ msg.timestamp|translate_commit_time }}</span>
<a href="{% url 'user_profile' msg.from_email %}">{{ msg.from_email|email2nickname }}</a>
<span class="group">留言所属:<a href="{% url 'public_home' %}">公共页面</a></span>
</div>
<div class="msg-bd">
<p>
{{ msg.message|seahub_urlize|find_at|linebreaksbr }}
</p>
<button class="reply op hide" data="{% url 'innerpub_msg_reply' msg.id %}"><span class="reply-cnt">{{ msg.reply_cnt }} </span>回复</a>
<button class="replyclose op">收起回复</button>
<div class="reply-bd">
<ul class="reply-list">
{% for reply in msg.reply_list %}
<li class="w100 ovhd">
<a href="{% url 'user_profile' reply.from_email %}" class="pic fleft">{% avatar reply.from_email 28 %}</a>
<div class="txt fright">
<a href="{% url 'user_profile' reply.from_email %}">{{ reply.from_email|email2nickname }}</a> : {{ reply.message|seahub_urlize|find_at }} --
<button class="reply-at op" data="{{ reply.from_email|email2nickname }}">回复</button>
</div>
</li>
{% endfor %}
</ul>
<textarea name="message" class="reply-input"></textarea>
<button class="submit">回复</button>
<p class="error hide">输入不能为空且应少于150个字符。</p>
</div>
</div>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<p>暂无</p>
{% endif %}
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
{% include 'group/msg_reply_js.html' %}
$('.reply-at').click(function() {
var reply_input = $(this).parent().parent().parent().next();
reply_input.val('@' + $(this).attr('data') + ' ');
var pos = reply_input.val().length;
setCaretPos(reply_input[0], pos);
reply_input.focus();
});
$('.reply-bd .submit').click(function() {
var msg_bd = $(this).parent().parent(),
msg_reply_url = msg_bd.find('.reply').attr('data'),
reply_cnt = msg_bd.find('.reply-cnt'),
reply_input = $(this).prev(),
reply = $.trim(reply_input.val()),
error = $(this).next();
if (reply && reply.length <= 150) {
$.ajax({
type: "POST",
url: msg_reply_url,
dataType: 'json',
cache: false,
contentType: 'application/json; charset=utf-8',
beforeSend: prepareCSRFToken,
data: "message=" + reply,
success: function(data) {
msg_bd.find('.reply-list').append(data['html']);
reply_input.val('');
error.attr('class', 'error hide');
reply_cnt.html(parseInt(reply_cnt.html()) + 1 + ' ');
msg_bd.find('.reply-at').click(function() {
reply_input.val('@' + $(this).attr('data') + ' ');
var pos = reply_input.val().length;
setCaretPos(reply_input[0], pos);
reply_input.focus();
});
}
});
} else {
error.removeClass('hide');
}
});
</script>
{% endblock %}

View File

@@ -56,8 +56,54 @@
{% endfor %}
</table>
{% endif %}
</div>
<!-- 信息栏 -->
<div id="innerpub-msg">
<h3>信息栏</h3>
<form id="innerpub-msg-form" action="" method="post">
<textarea name="message" id="message">{{ form.data.message }}</textarea><br />
{% for error in form.message.errors %}
<p class="error">{{ error|escape }}</p>
{% endfor %}
<input type="submit" value="提交" class="submit" />
</form>
</div>
{% if innerpub_msgs %}
<ul class="msg-list">
{% for msg in innerpub_msgs %}
<li class="msg w100 ovhd">
<div class="pic fleft">
<a href="{{ SITE_ROOT }}profile/{{ msg.from_email }}/">{% avatar msg.from_email 48 %}</a>
</div>
<div class="txt fright">
<div class="msg-hd">
<span class="time">{{ msg.timestamp|translate_commit_time }}</span>
<a href="{{ SITE_ROOT }}profile/{{ msg.from_email }}/" title="{{ msg.from_email }}">{{ msg.from_email|email2nickname }}</a>
</div>
<div class="msg-bd">
<p>
{{ msg.message|seahub_urlize|find_at|linebreaksbr }}
</p>
<button class="reply op" data="{% url 'innerpub_msg_reply' msg.id %}"><span class="reply-cnt">{% if msg.reply_cnt != 0 %}{{ msg.reply_cnt }} {% endif %}</span>回复</button>
<button class="replyclose op hide">收起回复</button>
<div class="reply-bd"></div>
</div>
</div>
</li>
{% endfor %}
</ul>
{% endif %}
<div id="paginator">
{% if current_page != 1 %}
<a href="{{ SITE_ROOT }}group/{{ group.id}}/?page={{ prev_page }}&per_page={{ per_page }}">上一页</a>
{% endif %}
{% if page_next %}
<a href="{{ SITE_ROOT }}group/{{ group.id }}/?page={{ next_page }}&per_page={{ per_page }}">下一页</a>
{% endif %}
</div>
<!-- /信息栏 -->
</div>
<!-- /.main -->
{% include "snippets/repo_share_form.html" %}
{% include "snippets/repo_create_form.html" %}
{% include "snippets/user_profile_html.html" %}
@@ -72,5 +118,7 @@
{% with post_url=repo_create_url %}
{% include "snippets/repo_create_js.html" %}
{% endwith %}
{% include 'group/msg_reply_js.html' %}
</script>
{% endblock %}

View File

@@ -28,6 +28,8 @@ urlpatterns = patterns('',
#url(r'^home/$', direct_to_template, { 'template': 'home.html' } ),
url(r'^home/my/$', myhome, name='myhome'),
url(r'^home/public/$', public_home, name='public_home'),
url(r'^home/public/reply/(?P<msg_id>[\d]+)/$', innerpub_msg_reply, name='innerpub_msg_reply'),
url(r'^home/public/reply/new/$', innerpub_msg_reply_new, name='innerpub_msg_reply_new'),
url(r'^home/owner/(?P<owner_name>[^/]+)/$', ownerhome, name='ownerhome'),
(r'^share/', include('share.urls')),

133
views.py
View File

@@ -20,6 +20,7 @@ from django.http import HttpResponse, HttpResponseBadRequest, Http404, \
HttpResponseRedirect
from django.shortcuts import render_to_response, redirect
from django.template import Context, loader, RequestContext
from django.template.loader import render_to_string
from django.utils.hashcompat import md5_constructor
from django.views.decorators.csrf import csrf_protect
from django.views.generic.base import TemplateView, TemplateResponseMixin
@@ -43,12 +44,14 @@ from pysearpc import SearpcError
from base.accounts import User
from base.decorators import sys_staff_required, ctx_switch_required
from base.mixins import LoginRequiredMixin, CtxSwitchRequiredMixin
from seahub.base.models import UuidObjidMap, FileComment
from seahub.contacts.models import Contact
from seahub.contacts.signals import mail_sended
from base.models import UuidObjidMap, FileComment, InnerPubMsg, InnerPubMsgReply
from contacts.models import Contact
from contacts.signals import mail_sended
from group.forms import MessageForm, MessageReplyForm
from group.models import GroupMessage, MessageAttachment
from group.signals import grpmsg_added
from seahub.notifications.models import UserNotification
from notifications.models import UserNotification
from profile.models import Profile
from forms import AddUserForm, FileLinkShareForm, RepoCreateForm, \
RepoNewDirForm, RepoNewFileForm, FileCommentForm, RepoRenameFileForm, \
RepoPassowrdForm
@@ -59,7 +62,6 @@ from utils import render_permission_error, render_error, list_to_string, \
get_file_revision_id_size, get_ccnet_server_addr_port, \
gen_file_get_url, string2list, MAX_INT, \
gen_file_upload_url, check_and_get_org_by_repo
from seahub.profile.models import Profile
try:
from settings import DOCUMENT_CONVERTOR_ROOT
if DOCUMENT_CONVERTOR_ROOT[-1:] != '/':
@@ -695,6 +697,8 @@ def myhome(request):
grpmsg_reply_list = []
orgmsg_list = []
notes = UserNotification.objects.filter(to_user=request.user.username)
new_innerpub_msg = False
innerpubmsg_reply_list = []
for n in notes:
if n.msg_type == 'group_msg':
grp = get_group(n.detail)
@@ -705,6 +709,10 @@ def myhome(request):
grpmsg_reply_list.append(n.detail)
elif n.msg_type == 'org_join_msg':
orgmsg_list.append(n.detail)
elif n.msg_type == 'innerpub_msg':
new_innerpub_msg = True
elif n.msg_type == 'innerpubmsg_reply':
innerpubmsg_reply_list.append(n.detail)
# my groups
groups = get_personal_groups(email)
@@ -732,6 +740,8 @@ def myhome(request):
"grpmsg_list": grpmsg_list,
"grpmsg_reply_list": grpmsg_reply_list,
"orgmsg_list": orgmsg_list,
"new_innerpub_msg": new_innerpub_msg,
"innerpubmsg_reply_list": innerpubmsg_reply_list,
}, context_instance=RequestContext(request))
@login_required
@@ -739,12 +749,125 @@ def public_home(request):
"""
Show public home page when CLOUD_MODE is False.
"""
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
msg = InnerPubMsg()
msg.from_email = request.user.username
msg.message = form.cleaned_data['message']
msg.save()
return HttpResponseRedirect(reverse('public_home'))
else:
form = MessageForm()
users = get_emailusers(-1, -1)
public_repos = list_inner_pub_repos()
"""inner pub messages"""
# Make sure page request is an int. If not, deliver first page.
try:
current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '15'))
except ValueError:
current_page = 1
per_page = 15
msgs_plus_one = InnerPubMsg.objects.all()[per_page*(current_page-1) :
per_page*current_page+1]
if len(msgs_plus_one) == per_page + 1:
page_next = True
else:
page_next = False
innerpub_msgs = msgs_plus_one[:per_page]
msg_replies = InnerPubMsgReply.objects.filter(reply_to__in=innerpub_msgs)
reply_to_list = [ r.reply_to_id for r in msg_replies ]
for msg in innerpub_msgs:
msg.reply_cnt = reply_to_list.count(msg.id)
# remove user notifications
UserNotification.objects.filter(to_user=request.user.username,
msg_type='innerpub_msg').delete()
return render_to_response('public_home.html', {
'users': users,
'public_repos': public_repos,
'form': form,
'innerpub_msgs': innerpub_msgs,
'current_page': current_page,
'prev_page': current_page-1,
'next_page': current_page+1,
'per_page': per_page,
'page_next': page_next,
}, context_instance=RequestContext(request))
@login_required
def innerpub_msg_reply(request, msg_id):
"""Show inner pub message replies, and process message reply in ajax"""
content_type = 'application/json; charset=utf-8'
if request.is_ajax():
ctx = {}
if request.method == 'POST':
form = MessageReplyForm(request.POST)
# TODO: invalid form
if form.is_valid():
msg = form.cleaned_data['message']
try:
innerpub_msg = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
return HttpResponseBadRequest(content_type=content_type)
msg_reply = InnerPubMsgReply()
msg_reply.reply_to = innerpub_msg
msg_reply.from_email = request.user.username
msg_reply.message = msg
msg_reply.save()
ctx['reply'] = msg_reply
html = render_to_string("group/group_reply_new.html", ctx)
else:
try:
msg = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
raise HttpResponse(status=400)
replies = InnerPubMsgReply.objects.filter(reply_to=msg)
ctx['replies'] = replies
html = render_to_string("group/group_reply_list.html", ctx)
serialized_data = json.dumps({"html": html})
return HttpResponse(serialized_data, content_type=content_type)
else:
return HttpResponseBadRequest(content_type=content_type)
@login_required
def innerpub_msg_reply_new(request):
notes = UserNotification.objects.filter(to_user=request.user.username)
innerpub_reply_list = [ n.detail for n in notes if \
n.msg_type == 'innerpubmsg_reply']
innerpub_msgs = []
for msg_id in innerpub_reply_list:
try:
m = InnerPubMsg.objects.get(id=msg_id)
except InnerPubMsg.DoesNotExist:
continue
else:
m.reply_list = InnerPubMsgReply.objects.filter(reply_to=m)
m.reply_cnt = m.reply_list.count()
innerpub_msgs.append(m)
# remove new innerpub msg reply notification
UserNotification.objects.filter(to_user=request.user.username,
msg_type='innerpubmsg_reply').delete()
return render_to_response("new_innerpubmsg_reply.html", {
'innerpub_msgs': innerpub_msgs,
}, context_instance=RequestContext(request))
@login_required