1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-25 14:50:29 +00:00

[message] integrate group discussion into personal discussion listing page

This commit is contained in:
swpd
2014-03-02 00:29:52 -05:00
parent 8dbd1d6269
commit a47759e8d0
7 changed files with 163 additions and 49 deletions

View File

@@ -2703,7 +2703,7 @@ textarea:-moz-placeholder {/* for FF */
padding:2px; padding:2px;
margin-bottom:3px; margin-bottom:3px;
} }
#mass-email { #mass-receiver {
width:432px; width:432px;
} }
/* payments */ /* payments */

View File

@@ -1,24 +1,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from seahub.group.models import GroupMessage
from seahub.notifications.models import UserNotification, MSG_TYPE_GROUP_MSG
def msg_info_list(msgs, user): def user_msg_info_list(user_msgs, user):
"""Group message list by ``from_email`` or ``to_email`` and order by """Group message list by ``from_email`` or ``to_email`` and order by
message time. message time.
**Returns** **Returns**
[ {
(u'foo@foo.com', {'last_msg': u'test', 'not_read': 0, 'last_time': datetime.datetime(2013, 5, 27, 13, 26, 7, 423777)}), u'foo@foo.com': {'type': u'user', 'last_msg': u'test', 'not_read': 0, 'last_time': datetime.datetime(2013, 5, 27, 13, 26, 7, 423777)},
(u'bar@bar.com', {'last_msg': u'hello', 'not_read': 0, 'last_time': datetime.datetime(2013, 5, 27, 13, 10, 31, 811318)}), u'bar@bar.com', {'type': u'user', 'last_msg': u'hello', 'not_read': 0, 'last_time': datetime.datetime(2013, 5, 27, 13, 10, 31, 811318)},
... ...
] }
""" """
message = {} message = {}
for msg in msgs: for msg in user_msgs:
if (msg.from_email == user): # message user send to others if (msg.from_email == user): # message user send to others
if not message.has_key(msg.to_email): if not message.has_key(msg.to_email):
message.setdefault(msg.to_email,{}) message.setdefault(msg.to_email,{})
message[msg.to_email].setdefault('type', 'user')
message[msg.to_email].setdefault('not_read', 0) message[msg.to_email].setdefault('not_read', 0)
message[msg.to_email].setdefault('last_msg',msg.message) message[msg.to_email].setdefault('last_msg',msg.message)
message[msg.to_email].setdefault('last_time',msg.timestamp) message[msg.to_email].setdefault('last_time',msg.timestamp)
@@ -30,6 +33,7 @@ def msg_info_list(msgs, user):
else: # message others send to the user else: # message others send to the user
if not message.has_key(msg.from_email): if not message.has_key(msg.from_email):
message.setdefault(msg.from_email,{}) message.setdefault(msg.from_email,{})
message[msg.from_email].setdefault('type', 'user')
message[msg.from_email].setdefault('not_read',0) message[msg.from_email].setdefault('not_read',0)
message[msg.from_email].setdefault('last_msg',msg.message) message[msg.from_email].setdefault('last_msg',msg.message)
message[msg.from_email].setdefault('last_time',msg.timestamp) message[msg.from_email].setdefault('last_time',msg.timestamp)
@@ -41,7 +45,35 @@ def msg_info_list(msgs, user):
if not msg.ifread: if not msg.ifread:
message[msg.from_email]['not_read'] += 1 message[msg.from_email]['not_read'] += 1
sorted_msg = sorted(message.items(), key=lambda x: x[1]['last_time'],
reverse=True)
return sorted_msg return message
def group_msg_info_list(joined_groups, username):
"""
Group message of groups that user joined.
**Returns**
{
u'test_group': {'type': u'group', 'id': 1, 'not_read': 32, 'last_msg': u'hey', 'last_time': datetime.datetime(2013, 5, 27, 13, 12, 31, 343452)},
...
}
"""
message = {}
user_notices = UserNotification.objects.filter(to_user=username,
msg_type=MSG_TYPE_GROUP_MSG)
for g in joined_groups:
group_msg = GroupMessage.objects.filter(group_id=g.id).order_by('-timestamp')[:1]
if len(group_msg) > 0:
message.setdefault(g.group_name,{})
message[g.group_name].setdefault('type', 'group')
message[g.group_name].setdefault('id', g.id)
message[g.group_name].setdefault('not_read', 0)
message[g.group_name].setdefault('last_msg', group_msg[0].message)
message[g.group_name].setdefault('last_time', group_msg[0].timestamp)
for notice in user_notices:
gid = notice.group_message_detail_to_dict().get('group_id')
if gid == g.id:
if notice.seen is False:
message[g.group_name]['not_read'] += 1
return message

View File

@@ -1,12 +1,21 @@
{% load avatar_tags i18n seahub_tags %} {% load avatar_tags group_avatar_tags i18n seahub_tags %}
{% for key,value in msgs %} {% for key,value in msgs %}
{% with not_read=value.not_read %} {% with not_read=value.not_read %}
{% if value.type == 'user' %}
<tr data-href="{% url 'user_msg_list' key|id_or_email %}" class="{% if not_read > 0 %}bold{% endif %}"> <tr data-href="{% url 'user_msg_list' key|id_or_email %}" class="{% if not_read > 0 %}bold{% endif %}">
<td class="alc">{% avatar key 20 %}</td> <td class="alc">{% avatar key 20 %}</td>
<td>{{ key|email2nickname }}{% if not_read > 0%}({{not_read}}){% endif %}</td> <td>{{ key|email2nickname }}{% if not_read > 0%}({{not_read}}){% endif %}</td>
<td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td> <td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td>
<td>{{ value.last_time|translate_seahub_time }}</td> <td>{{ value.last_time|translate_seahub_time }}</td>
</tr> </tr>
{% else %}
<tr data-href="{{ SITE_ROOT }}group/{{ value.id }}/discuss/" class="{% if not_read > 0 %}bold{% endif %}">
<td class="alc">{% grp_avatar value.id 20 %}</td>
<td>{{ key }}{% if not_read > 0 %}({{not_read}}){% endif %}</td>
<td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td>
<td>{{ value.last_time|translate_seahub_time }}</td>
</tr>
{% endif %}
{% endwith %} {% endwith %}
{% endfor %} {% endfor %}

View File

@@ -1,5 +1,5 @@
{% extends "home_base.html" %} {% extends "home_base.html" %}
{% load avatar_tags i18n seahub_tags %} {% load avatar_tags group_avatar_tags i18n seahub_tags %}
{% block sub_title %}{% trans "Messages" %}{% if total_unread > 0%}({{total_unread}}){%endif%} - {% endblock %} {% block sub_title %}{% trans "Messages" %}{% if total_unread > 0%}({{total_unread}}){%endif%} - {% endblock %}
{% block extra_style %} {% block extra_style %}
@@ -25,12 +25,21 @@
{% if msgs %} {% if msgs %}
{% for key,value in msgs %} {% for key,value in msgs %}
{% with not_read=value.not_read %} {% with not_read=value.not_read %}
{% if value.type == 'user' %}
<tr data-href="{% url 'user_msg_list' key|id_or_email %}" class="{% if not_read > 0 %}bold{% endif %}"> <tr data-href="{% url 'user_msg_list' key|id_or_email %}" class="{% if not_read > 0 %}bold{% endif %}">
<td class="alc">{% avatar key 20 %}</td> <td class="alc">{% avatar key 20 %}</td>
<td>{{ key|email2nickname }}{% if not_read > 0%}({{not_read}}){% endif %}</td> <td>{{ key|email2nickname }}{% if not_read > 0%}({{not_read}}){% endif %}</td>
<td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td> <td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td>
<td>{{ value.last_time|translate_seahub_time }}</td> <td>{{ value.last_time|translate_seahub_time }}</td>
</tr> </tr>
{% else %}
<tr data-href="{{ SITE_ROOT }}group/{{ value.id }}/discuss/" class="{% if not_read > 0 %}bold{% endif %}">
<td class="alc">{% grp_avatar value.id 20 %}</td>
<td>{{ key }}{% if not_read > 0 %}({{not_read}}){% endif %}</td>
<td>{{ value.last_msg|seahub_urlize|truncatewords_html:12 }}</td>
<td>{{ value.last_time|translate_seahub_time }}</td>
</tr>
{% endif %}
{% endwith %} {% endwith %}
{% endfor %} {% endfor %}
{% endif %} {% endif %}
@@ -40,7 +49,7 @@
<img src="{{MEDIA_URL}}img/loading-icon.gif" class="loading-tip" /> <img src="{{MEDIA_URL}}img/loading-icon.gif" class="loading-tip" />
<form id="send-msg-form" action="{% url 'message_send' %}?from=all" method="post" name="send-msg-form" class="hide">{% csrf_token %} <form id="send-msg-form" action="{% url 'message_send' %}?from=all" method="post" name="send-msg-form" class="hide">{% csrf_token %}
<textarea id="mass-msg" name="mass_msg" placeholder="{% trans "message..." %}"></textarea><br/> <textarea id="mass-msg" name="mass_msg" placeholder="{% trans "message..." %}"></textarea><br/>
<select id="mass-email" name="mass_email" multiple="multiple"></select><br/> <select id="mass-receiver" name="mass_receiver" multiple="multiple"></select><br/>
<div id="msg-file-share"> <div id="msg-file-share">
<button type="button" id="msg-file-share-btn"><span class="icon-plus-sign-alt"></span> {% trans "Add files" %}</button> <button type="button" id="msg-file-share-btn"><span class="icon-plus-sign-alt"></span> {% trans "Add files" %}</button>
<div id="msg-file-tree" class="hide"></div> <div id="msg-file-tree" class="hide"></div>
@@ -73,26 +82,38 @@ $('#add-msg').click(function() {
} }
popup.removeClass('hide'); popup.removeClass('hide');
$.ajax({ $.ajax({
url:'{% url 'get_contacts' %}', url:'{% url 'get_contacts_and_groups' %}',
cache: false, cache: false,
dataType: 'json', dataType: 'json',
success: function(data) { success: function(data) {
var contacts = data['contacts'], var contacts = data['contacts'],
groups = data['groups'],
opts = '', opts = '',
email; email,
name;
if (contacts.length > 0) { if (contacts.length > 0) {
popup.find('.loading-tip').remove(); popup.find('.loading-tip').remove();
$('#send-msg-form').removeClass('hide'); $('#send-msg-form').removeClass('hide');
for(var i = 0, len = contacts.length; i < len; i++) { var contact_len = contacts.length, group_len = groups.length;
for(var i = 0; i < contact_len; i++) {
email = contacts[i].email; email = contacts[i].email;
opts += '<option value="' + email + '" data-index="' + i + '">' + email + '</option>'; opts += '<option value="' + email + '" data-index="' + i + '" data-type="email">' + email + '</option>';
}
for (var i = 0; i < group_len; i++) {
name = groups[i].name;
opts += '<option value="' + groups[i].id + '" data-index="' + (i + contact_len) + '" data-type="group">' + name + '</option>';
} }
var format = function(item) { var format = function(item) {
return contacts[$(item.element).data('index')].avatar + '<span class="vam">' + item.text + '</span>'; var idx = $(item.element).data('index');
if (idx < contact_len) {
return contacts[idx].avatar + '<span class="vam">' + item.text + '</span>';
} else {
return groups[idx - contact_len].avatar + '<span class="vam">' + item.text + '</span>';
} }
$('#mass-email').html(opts).select2({ }
placeholder: "{% trans "send to: click to select contacts" %}", $('#mass-receiver').html(opts).select2({
placeholder: "{% trans "send to: click to select contacts/groups" %}",
formatResult: format, formatResult: format,
formatSelection: format, formatSelection: format,
escapeMarkup: function(m) { return m; } escapeMarkup: function(m) { return m; }
@@ -102,7 +123,7 @@ $('#add-msg').click(function() {
} }
}, },
error: function() { error: function() {
popup.html('<p class="error">' + "{% trans "Failed to get your contacts for sending a message." %}" + '</p>'); popup.html('<p class="error">' + "{% trans "Failed to get your contacts/groups for sending a message." %}" + '</p>');
} }
}); });
}); });
@@ -158,14 +179,25 @@ $('#send-msg-form').submit(function() {
form_id = form.attr('id'), form_id = form.attr('id'),
msg_input = $('[name="mass_msg"]', form), msg_input = $('[name="mass_msg"]', form),
msg = $.trim(msg_input.val()), msg = $.trim(msg_input.val()),
emails = $('[name="mass_email"]', form).val(); receivers = $('[name="mass_receiver"] option:selected', form);
var emails = [],
groups = [];
receivers.each(function() {
var type = $(this).data('type');
if (type == "email") {
emails.push($(this).val());
} else if (type == "group") {
groups.push($(this).val());
}
});
if (!msg) { if (!msg) {
apply_form_error(form_id, "{% trans "message is required" %}"); apply_form_error(form_id, "{% trans "message is required" %}");
return false; return false;
} }
if (!emails) { // val is null or ['xx',...] if (!emails && !groups) { // val is null or ['xx',...]
apply_form_error(form_id, "{% trans "contact is required" %}"); apply_form_error(form_id, "{% trans "contact/group is required" %}");
return false; return false;
} }
@@ -185,7 +217,7 @@ $('#send-msg-form').submit(function() {
type: 'POST', type: 'POST',
dataType: 'json', dataType: 'json',
beforeSend: prepareCSRFToken, beforeSend: prepareCSRFToken,
data: { 'mass_msg': msg, 'mass_email': emails, 'selected': selected }, data: { 'mass_msg': msg, 'mass_email': emails, 'mass_group': groups, 'selected': selected },
traditional: true, traditional: true,
success: function(data) { success: function(data) {
msg_input.val(''); msg_input.val('');

View File

@@ -14,8 +14,10 @@ from django.utils.translation import ugettext as _
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from models import UserMessage, UserMsgAttachment from models import UserMessage, UserMsgAttachment
from message import msg_info_list from seahub.group.models import GroupMessage, MessageAttachment
from seaserv import get_repo from seahub.group.signals import grpmsg_added
from message import user_msg_info_list, group_msg_info_list
from seaserv import get_repo, get_group, is_group_user, get_personal_groups_by_user
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
from seahub.base.accounts import User from seahub.base.accounts import User
from seahub.views import is_registered_user from seahub.views import is_registered_user
@@ -32,13 +34,16 @@ def message_list(request):
""" """
username = request.user.username username = request.user.username
messages = UserMessage.objects.get_messages_related_to_user(username) related_user_msgs = UserMessage.objects.get_messages_related_to_user(username)
msgs = msg_info_list(messages, username) user_msgs = user_msg_info_list(related_user_msgs, username)
total_unread = 0 total_unread = 0
for msg in msgs: for msg in user_msgs.items():
total_unread += msg[1]['not_read'] total_unread += msg[1]['not_read']
joined_groups = get_personal_groups_by_user(username)
group_msgs = group_msg_info_list(joined_groups, username)
msgs = sorted(user_msgs.items() + group_msgs.items(), key=lambda x: x[1]['last_time'], reverse=True)
return render_to_response('message/all_msg_list.html', { return render_to_response('message/all_msg_list.html', {
'msgs': msgs, 'msgs': msgs,
'total_unread': total_unread, 'total_unread': total_unread,
@@ -111,7 +116,7 @@ def user_msg_list(request, id_or_email):
@login_required @login_required
@require_POST @require_POST
def message_send(request): def message_send(request):
"""Handle POST request to send message to user(s). """Handle POST request to send message to user(s)/group(s).
""" """
if not request.is_ajax() or request.method != 'POST': if not request.is_ajax() or request.method != 'POST':
@@ -129,12 +134,13 @@ def message_send(request):
mass_msg = request.POST.get('mass_msg') mass_msg = request.POST.get('mass_msg')
mass_emails = request.POST.getlist('mass_email') # e.g: [u'1@1.com, u'2@1.com'] mass_emails = request.POST.getlist('mass_email') # e.g: [u'1@1.com, u'2@1.com']
mass_group_ids = [int(x) for x in request.POST.getlist('mass_group')]
if not mass_msg: if not mass_msg:
result['error'] = [_(u'message is required')] result['error'] = [_(u'message is required')]
return HttpResponse(json.dumps(result), content_type=content_type) return HttpResponse(json.dumps(result), content_type=content_type)
if not mass_emails: if not mass_emails and not mass_group_ids:
result['error'] = [_(u'contact is required')] result['error'] = [_(u'contact/group is required')]
return HttpResponse(json.dumps(result), content_type=content_type) return HttpResponse(json.dumps(result), content_type=content_type)
# attachment # attachment
@@ -150,9 +156,11 @@ def message_send(request):
att['path'] = item[36:] att['path'] = item[36:]
attached_items.append(att) attached_items.append(att)
email_sended = [] email_sent = []
group_sent = []
errors = [] errors = []
msgs = [] user_msgs = []
group_msgs = []
for to_email in mass_emails: for to_email in mass_emails:
to_email = to_email.strip() to_email = to_email.strip()
if not to_email or not is_valid_username(to_email): if not to_email or not is_valid_username(to_email):
@@ -166,26 +174,54 @@ def message_send(request):
errors.append(_(u'Failed to send message to %s, user not found.') % to_email) errors.append(_(u'Failed to send message to %s, user not found.') % to_email)
continue continue
usermsg = UserMessage.objects.add_unread_message(username, to_email, mass_msg) user_msg = UserMessage.objects.add_unread_message(username, to_email, mass_msg)
msgs.append(usermsg) user_msgs.append(user_msg)
if len(attached_items) > 0: if len(attached_items) > 0:
for att_item in attached_items: for att_item in attached_items:
repo_id = att_item['repo_id'] repo_id = att_item['repo_id']
path = att_item['path'] path = att_item['path']
pfds = PrivateFileDirShare.objects.add_read_only_priv_file_share( pfds = PrivateFileDirShare.objects.add_read_only_priv_file_share(
username, to_email, repo_id, path) username, to_email, repo_id, path)
UserMsgAttachment.objects.add_user_msg_attachment(usermsg, pfds) UserMsgAttachment.objects.add_user_msg_attachment(user_msg, pfds)
email_sended.append(to_email) email_sent.append(to_email)
joined_groups = []
for group_id in mass_group_ids:
group = get_group(group_id)
if not group:
continue
joined_groups.append(group)
if not is_group_user(group_id, username):
errors.append(_(u'You can not send message to group %s, you didn\'t join in.') % group.name)
continue
group_msg = GroupMessage(group_id=group_id, from_email=username, message=mass_msg)
group_msg.save()
grpmsg_added.send(sender=GroupMessage, group_id=group_id, from_email=username)
group_msgs.append(group_msg)
if len(attached_items) > 0:
for att_item in attached_items:
repo_id = att_item['repo_id']
path = att_item['path']
ma = MessageAttachment(group_message=group_msg, repo_id=repo_id,
attach_type='file', path=path,
src='recommend')
ma.save()
group_sent.append(group_id)
html = '' html = ''
if email_sended: if email_sent or group_sent:
ctx = {} ctx = {}
if fr == 'all': # from 'all_msg_list' page if fr == 'all': # from 'all_msg_list' page
ctx['msgs'] = msg_info_list(msgs, username) user_msgs = user_msg_info_list(user_msgs, username)
html = render_to_string('message/all_msg.html', ctx) group_msgs = group_msg_info_list(joined_groups, username)
ctx['msgs'] = sorted(user_msgs.items() + group_msgs.items(), key=lambda x: x[1]['last_time'], reverse=True)
html = render_to_string('message/all_msg.html', ctx, context_instance=RequestContext(request))
else: else:
ctx['msg'] = msgs[0] ctx['msg'] = user_msgs[0]
html = render_to_string('message/user_msg.html', ctx) html = render_to_string('message/user_msg.html', ctx)
return HttpResponse(json.dumps({"html": html, "error": errors}), content_type=content_type) return HttpResponse(json.dumps({"html": html, "error": errors}), content_type=content_type)
else: else:

View File

@@ -144,7 +144,7 @@ urlpatterns = patterns('',
url(r'^ajax/my-unenc-repos/$', get_my_unenc_repos, name='get_my_unenc_repos'), url(r'^ajax/my-unenc-repos/$', get_my_unenc_repos, name='get_my_unenc_repos'),
url(r'^ajax/unenc-rw-repos/$', unenc_rw_repos, name='unenc_rw_repos'), url(r'^ajax/unenc-rw-repos/$', unenc_rw_repos, name='unenc_rw_repos'),
url(r'^ajax/contacts/$', get_contacts, name='get_contacts'), url(r'^ajax/contacts_and_groups/$', get_contacts_and_groups, name='get_contacts_and_groups'),
url(r'^ajax/upload-file-done/$', upload_file_done, name='upload_file_done'), url(r'^ajax/upload-file-done/$', upload_file_done, name='upload_file_done'),
url(r'^ajax/unseen-notices-count/$', unseen_notices_count, name='unseen_notices_count'), url(r'^ajax/unseen-notices-count/$', unseen_notices_count, name='unseen_notices_count'),
url(r'^ajax/space_and_traffic/$', space_and_traffic, name='space_and_traffic'), url(r'^ajax/space_and_traffic/$', space_and_traffic, name='space_and_traffic'),

View File

@@ -15,7 +15,7 @@ import seaserv
from seaserv import seafile_api, seafserv_rpc, \ from seaserv import seafile_api, seafserv_rpc, \
get_related_users_by_repo, get_related_users_by_org_repo, \ get_related_users_by_repo, get_related_users_by_org_repo, \
is_org_repo_owner, CALC_SHARE_USAGE, seafserv_threaded_rpc, \ is_org_repo_owner, CALC_SHARE_USAGE, seafserv_threaded_rpc, \
get_user_quota_usage, get_user_share_usage get_user_quota_usage, get_user_share_usage, get_personal_groups_by_user
from pysearpc import SearpcError from pysearpc import SearpcError
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
@@ -899,7 +899,7 @@ def repo_unstar_file(request, repo_id):
########## contacts related ########## contacts related
@login_required @login_required
def get_contacts(request): def get_contacts_and_groups(request):
if not request.is_ajax(): if not request.is_ajax():
raise Http404 raise Http404
@@ -912,7 +912,12 @@ def get_contacts(request):
for c in contacts: for c in contacts:
contact_list.append({"email": c.contact_email, "avatar": avatar(c.contact_email, 16)}) contact_list.append({"email": c.contact_email, "avatar": avatar(c.contact_email, 16)})
return HttpResponse(json.dumps({"contacts":contact_list}), content_type=content_type) joined_groups = get_personal_groups_by_user(username)
group_list = []
from seahub.avatar.templatetags.group_avatar_tags import grp_avatar
for g in joined_groups:
group_list.append({"id": g.id, "name": g.group_name, "avatar": grp_avatar(g.id, 16)})
return HttpResponse(json.dumps({"contacts":contact_list, "groups":group_list}), content_type=content_type)
@login_required @login_required
def get_current_commit(request, repo_id): def get_current_commit(request, repo_id):