mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-13 05:39:59 +00:00
[discuss to grp] use ajax, show discusstions & replies
* manually merged some code from zx's branch 'file_discuss'
This commit is contained in:
@@ -8,6 +8,7 @@ from seaserv import get_emailusers
|
|||||||
|
|
||||||
from shortcuts import get_first_object_or_none
|
from shortcuts import get_first_object_or_none
|
||||||
from base.templatetags.seahub_tags import at_pattern
|
from base.templatetags.seahub_tags import at_pattern
|
||||||
|
from group.models import GroupMessage
|
||||||
from notifications.models import UserNotification
|
from notifications.models import UserNotification
|
||||||
from profile.models import Profile
|
from profile.models import Profile
|
||||||
|
|
||||||
@@ -34,6 +35,21 @@ class FileComment(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['-timestamp']
|
ordering = ['-timestamp']
|
||||||
|
|
||||||
|
class FileDiscuss(models.Model):
|
||||||
|
"""
|
||||||
|
Model used to represents the relationship between group message and file/dir.
|
||||||
|
"""
|
||||||
|
group_message = models.ForeignKey(GroupMessage)
|
||||||
|
repo_id = models.CharField(max_length=36)
|
||||||
|
path = models.TextField()
|
||||||
|
path_hash = models.CharField(max_length=12, db_index=True)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.path_hash:
|
||||||
|
from seahub.utils import calc_file_path_hash
|
||||||
|
self.path_hash = calc_file_path_hash(self.path)
|
||||||
|
super(FileDiscuss, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class FileContributors(models.Model):
|
class FileContributors(models.Model):
|
||||||
"""(repo_id, file path, file_id, contributors)"""
|
"""(repo_id, file path, file_id, contributors)"""
|
||||||
|
|
||||||
|
@@ -73,7 +73,7 @@
|
|||||||
{% for msg in group_msgs.object_list %}
|
{% for msg in group_msgs.object_list %}
|
||||||
<li class="msg w100 ovhd">
|
<li class="msg w100 ovhd">
|
||||||
<a href="{% url 'user_profile' msg.from_email|email2id %}" class="pic fleft">{% avatar msg.from_email 48 %}</a>
|
<a href="{% url 'user_profile' msg.from_email|email2id %}" class="pic fleft">{% avatar msg.from_email 48 %}</a>
|
||||||
<div class="txt fright">
|
<div class="txt">
|
||||||
<div class="msg-main">
|
<div class="msg-main">
|
||||||
<div class="msg-hd w100 ovhd">
|
<div class="msg-hd w100 ovhd">
|
||||||
{% if is_staff or msg.from_email == request.user.username %}
|
{% if is_staff or msg.from_email == request.user.username %}
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<li class="reply w100 ovhd">
|
<li class="reply w100 ovhd">
|
||||||
{% with id=r.from_email|email2id name=r.from_email|email2nickname %}
|
{% with id=r.from_email|email2id name=r.from_email|email2nickname %}
|
||||||
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar r.from_email 28 %}</a>
|
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar r.from_email 28 %}</a>
|
||||||
<div class="txt fright">
|
<div class="txt">
|
||||||
<a href="{% url 'user_profile' id %}">{{ name }}</a>
|
<a href="{% url 'user_profile' id %}">{{ name }}</a>
|
||||||
<span class="time">{{ r.timestamp|translate_seahub_time }}</span>
|
<span class="time">{{ r.timestamp|translate_seahub_time }}</span>
|
||||||
<span class="reply-at op vh" data="{{ name }}">{% trans 'Reply' %}</span>
|
<span class="reply-at op vh" data="{{ name }}">{% trans 'Reply' %}</span>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
{% with id=r.from_email|email2id name=r.from_email|email2nickname %}
|
{% with id=r.from_email|email2id name=r.from_email|email2nickname %}
|
||||||
<li class="reply w100 ovhd">
|
<li class="reply w100 ovhd">
|
||||||
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar r.from_email 28 %}</a>
|
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar r.from_email 28 %}</a>
|
||||||
<div class="txt fright">
|
<div class="txt">
|
||||||
<a href="{% url 'user_profile' id %}">{{ name }}</a>
|
<a href="{% url 'user_profile' id %}">{{ name }}</a>
|
||||||
<span class="time">{{ r.timestamp|translate_seahub_time }}</span>
|
<span class="time">{{ r.timestamp|translate_seahub_time }}</span>
|
||||||
<span class="reply-at op vh" data="{{ name }}">{% trans 'Reply' %}</span>
|
<span class="reply-at op vh" data="{{ name }}">{% trans 'Reply' %}</span>
|
||||||
|
135
group/views.py
135
group/views.py
@@ -15,6 +15,7 @@ from django.shortcuts import render_to_response, redirect
|
|||||||
from django.template import Context, loader, RequestContext
|
from django.template import Context, loader, RequestContext
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.encoding import smart_str
|
from django.utils.encoding import smart_str
|
||||||
|
from django.utils import datetime_safe
|
||||||
from django.utils.hashcompat import md5_constructor
|
from django.utils.hashcompat import md5_constructor
|
||||||
from django.utils.http import urlquote
|
from django.utils.http import urlquote
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
@@ -42,6 +43,7 @@ from signals import grpmsg_added, grpmsg_reply_added
|
|||||||
from settings import GROUP_MEMBERS_DEFAULT_DISPLAY
|
from settings import GROUP_MEMBERS_DEFAULT_DISPLAY
|
||||||
from base.decorators import sys_staff_required
|
from base.decorators import sys_staff_required
|
||||||
from base.mixins import LoginRequiredMixin
|
from base.mixins import LoginRequiredMixin
|
||||||
|
from base.models import FileDiscuss
|
||||||
from seahub.contacts.models import Contact
|
from seahub.contacts.models import Contact
|
||||||
from seahub.contacts.signals import mail_sended
|
from seahub.contacts.signals import mail_sended
|
||||||
from seahub.notifications.models import UserNotification
|
from seahub.notifications.models import UserNotification
|
||||||
@@ -55,6 +57,7 @@ from seahub.utils import render_error, render_permission_error, \
|
|||||||
from seahub.utils.paginator import Paginator
|
from seahub.utils.paginator import Paginator
|
||||||
from seahub.utils.slugify import slugify
|
from seahub.utils.slugify import slugify
|
||||||
from seahub.utils.file_types import IMAGE
|
from seahub.utils.file_types import IMAGE
|
||||||
|
from seahub.utils import calc_file_path_hash
|
||||||
from seahub.views import is_registered_user
|
from seahub.views import is_registered_user
|
||||||
from seahub.forms import RepoCreateForm, SharedRepoCreateForm
|
from seahub.forms import RepoCreateForm, SharedRepoCreateForm
|
||||||
|
|
||||||
@@ -748,66 +751,108 @@ def group_unshare_repo(request, repo_id, group_id, from_email):
|
|||||||
def group_recommend(request):
|
def group_recommend(request):
|
||||||
"""
|
"""
|
||||||
Recommend a file or directory to a group.
|
Recommend a file or directory to a group.
|
||||||
now changed to 'post a discussion'
|
now changed to 'Discuss'
|
||||||
|
for ajax post/get
|
||||||
"""
|
"""
|
||||||
if request.method != 'POST':
|
content_type = 'application/json; charset=utf-8'
|
||||||
raise Http404
|
result = {}
|
||||||
|
if request.method == 'POST':
|
||||||
|
|
||||||
next = request.META.get('HTTP_REFERER', None)
|
form = GroupRecommendForm(request.POST)
|
||||||
if not next:
|
if form.is_valid():
|
||||||
next = SITE_ROOT
|
repo_id = form.cleaned_data['repo_id']
|
||||||
|
attach_type = form.cleaned_data['attach_type']
|
||||||
|
path = form.cleaned_data['path']
|
||||||
|
message = form.cleaned_data['message']
|
||||||
|
groups = request.POST.getlist('groups') # groups is a group_id list, e.g. [u'1', u'7']
|
||||||
|
username = request.user.username
|
||||||
|
|
||||||
form = GroupRecommendForm(request.POST)
|
groups_not_in = []
|
||||||
if form.is_valid():
|
groups_posted_to = []
|
||||||
repo_id = form.cleaned_data['repo_id']
|
for group_id in groups:
|
||||||
attach_type = form.cleaned_data['attach_type']
|
# Check group id format
|
||||||
path = form.cleaned_data['path']
|
try:
|
||||||
message = form.cleaned_data['message']
|
group_id = int(group_id)
|
||||||
groups = request.POST.getlist('groups') # groups is a group_id list, e.g. [u'1', u'7']
|
except ValueError:
|
||||||
username = request.user.username
|
result['err'] = _(u'Error: wrong group id')
|
||||||
|
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
|
||||||
|
|
||||||
for group_id in groups:
|
group = get_group(group_id)
|
||||||
# Check group id format
|
if not group:
|
||||||
try:
|
result['err'] = _(u'Error: the group does not exist.')
|
||||||
group_id = int(group_id)
|
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
|
||||||
except ValueError:
|
|
||||||
messages.error(request, _(u'Error: wrong group id'))
|
|
||||||
return HttpResponseRedirect(next)
|
|
||||||
|
|
||||||
# Get that group
|
# TODO: Check whether repo is in the group and Im in the group
|
||||||
group = get_group(group_id)
|
if not is_group_user(group_id, username):
|
||||||
if not group:
|
groups_not_in.append(group.group_name)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# TODO: Check whether repo is in the group and Im in the group
|
# save message to group
|
||||||
if not is_group_user(group_id, username):
|
gm = GroupMessage(group_id=group_id, from_email=username,
|
||||||
err_msg = _(u'Error: you are not in group %s.')
|
|
||||||
messages.error(request, err_msg % group.group_name)
|
|
||||||
continue
|
|
||||||
|
|
||||||
# save message to group
|
|
||||||
gm = GroupMessage(group_id=group_id, from_email=username,
|
|
||||||
message=message)
|
message=message)
|
||||||
gm.save()
|
gm.save()
|
||||||
|
|
||||||
# send signal
|
# send signal
|
||||||
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
|
grpmsg_added.send(sender=GroupMessage, group_id=group_id,
|
||||||
from_email=request.user.username)
|
from_email=request.user.username)
|
||||||
|
|
||||||
# save attachment
|
# save attachment
|
||||||
ma = MessageAttachment(group_message=gm, repo_id=repo_id,
|
ma = MessageAttachment(group_message=gm, repo_id=repo_id,
|
||||||
attach_type=attach_type, path=path,
|
attach_type=attach_type, path=path,
|
||||||
src='recommend')
|
src='recommend')
|
||||||
ma.save()
|
ma.save()
|
||||||
|
|
||||||
group_url = reverse('group_discuss', args=[group_id])
|
# save discussion
|
||||||
msg = _(u'Successfully posted to <a href="%(url)s" target="_blank">%(name)s</a>.') %\
|
fd = FileDiscuss(group_message=gm, repo_id=repo_id, path=path)
|
||||||
{'url':group_url, 'name':group.group_name}
|
fd.save()
|
||||||
messages.add_message(request, messages.INFO, msg)
|
|
||||||
|
|
||||||
|
group_url = reverse('group_discuss', args=[group_id])
|
||||||
|
groups_posted_to.append(u'<a href="%(url)s" target="_blank">%(name)s</a>' % \
|
||||||
|
{'url':group_url, 'name':group.group_name})
|
||||||
|
|
||||||
|
if len(groups_posted_to) > 0:
|
||||||
|
result['success'] = _(u'Successfully posted to %(groups)s.') % {'groups': ', '.join(groups_posted_to)}
|
||||||
|
|
||||||
|
if len(groups_not_in) > 0:
|
||||||
|
result['err'] = _(u'Error: you are not in group %s.') % (', '.join(groups_not_in))
|
||||||
|
|
||||||
|
else:
|
||||||
|
result['err'] = _(u'Failed')
|
||||||
|
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
|
||||||
|
|
||||||
|
# request.method == 'GET'
|
||||||
else:
|
else:
|
||||||
messages.add_message(request, messages.ERROR, _(u'Failed.'))
|
repo_id = request.GET.get('repo_id')
|
||||||
return HttpResponseRedirect(next)
|
path = request.GET.get('path', None)
|
||||||
|
repo = get_repo(repo_id)
|
||||||
|
if not repo:
|
||||||
|
result['err'] = _(u'Error: the library does not exist.')
|
||||||
|
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
|
||||||
|
if path is None:
|
||||||
|
result['err'] = _(u'Error: no path.')
|
||||||
|
return HttpResponse(json.dumps(result), status=400, content_type=content_type)
|
||||||
|
|
||||||
|
# get discussions & replies
|
||||||
|
path_hash = calc_file_path_hash(path)
|
||||||
|
discussions = FileDiscuss.objects.filter(path_hash=path_hash, repo_id=repo_id)
|
||||||
|
msg_ids = [ e.group_message_id for e in discussions ]
|
||||||
|
|
||||||
|
grp_msgs = GroupMessage.objects.filter(id__in=msg_ids).order_by('-timestamp')
|
||||||
|
msg_replies = MessageReply.objects.filter(reply_to__in=grp_msgs)
|
||||||
|
for msg in grp_msgs:
|
||||||
|
msg.replies = []
|
||||||
|
for reply in msg_replies:
|
||||||
|
if msg.id == reply.reply_to_id:
|
||||||
|
msg.replies.append(reply)
|
||||||
|
msg.reply_cnt = len(msg.replies)
|
||||||
|
msg.replies = msg.replies[-3:]
|
||||||
|
|
||||||
|
ctx = {}
|
||||||
|
ctx['messages'] = grp_msgs
|
||||||
|
html = render_to_string("snippets/discussion_list.html", ctx)
|
||||||
|
result['html'] = html
|
||||||
|
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def create_group_repo(request, group_id):
|
def create_group_repo(request, group_id):
|
||||||
|
@@ -1497,7 +1497,7 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
margin:15px 0 20px;
|
margin:15px 0 20px;
|
||||||
}
|
}
|
||||||
.msg .txt {
|
.msg .txt {
|
||||||
width:576px;
|
margin-left:64px;
|
||||||
}
|
}
|
||||||
.msg a {
|
.msg a {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
@@ -1545,7 +1545,7 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
margin-left:5px;
|
margin-left:5px;
|
||||||
}
|
}
|
||||||
.msg-hd .group,
|
.msg-hd .group,
|
||||||
.comment-hd .time {
|
.discussion-to-grp .time {
|
||||||
color: #808080;
|
color: #808080;
|
||||||
}
|
}
|
||||||
.msg-hd .group {
|
.msg-hd .group {
|
||||||
@@ -1595,7 +1595,7 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
margin-bottom:15px;
|
margin-bottom:15px;
|
||||||
}
|
}
|
||||||
.reply .txt {
|
.reply .txt {
|
||||||
width: 93%;
|
margin-left:38px;
|
||||||
}
|
}
|
||||||
.reply-con {
|
.reply-con {
|
||||||
font-size:12px;
|
font-size:12px;
|
||||||
@@ -1899,10 +1899,8 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
background:#646464;
|
background:#646464;
|
||||||
margin-left:5px;
|
margin-left:5px;
|
||||||
}
|
}
|
||||||
/* File comment */
|
|
||||||
#file-comment,
|
|
||||||
#to-group,
|
#to-group,
|
||||||
#discuss-to-group-form {
|
#discuss-to-group {
|
||||||
width:400px;
|
width:400px;
|
||||||
padding:0 15px;
|
padding:0 15px;
|
||||||
position:fixed;
|
position:fixed;
|
||||||
@@ -1913,27 +1911,19 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
-moz-box-shadow: -1px 1px 1px rgba(0,0,0,.2);
|
-moz-box-shadow: -1px 1px 1px rgba(0,0,0,.2);
|
||||||
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2);
|
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2);
|
||||||
}
|
}
|
||||||
#comment-input {
|
#discuss-to-group {
|
||||||
width:315px;
|
padding-bottom:10px;
|
||||||
padding-left:1px;
|
|
||||||
height:3em;
|
|
||||||
}
|
}
|
||||||
.comment {
|
#discussions-to-grp {
|
||||||
|
height:auto;
|
||||||
|
overflow:auto;
|
||||||
|
}
|
||||||
|
#discussions-to-grp .msg {
|
||||||
width:380px;
|
width:380px;
|
||||||
padding:15px 0;
|
|
||||||
border-top:1px solid #e8e8e8;
|
|
||||||
}
|
}
|
||||||
.comment .txt {
|
#discussions-to-grp .reply-input {
|
||||||
width:318px;
|
width:272px;
|
||||||
}
|
}
|
||||||
#file-comment-form {
|
|
||||||
width:380px;
|
|
||||||
margin:15px 0;
|
|
||||||
}
|
|
||||||
.comment-bd {
|
|
||||||
word-wrap:break-word;
|
|
||||||
}
|
|
||||||
#comment-caret,
|
|
||||||
#to-group-caret,
|
#to-group-caret,
|
||||||
#discuss-to-group-caret {
|
#discuss-to-group-caret {
|
||||||
width:28px;
|
width:28px;
|
||||||
@@ -1953,8 +1943,11 @@ textarea:-moz-placeholder {/* for FF */
|
|||||||
text-decoration:none;
|
text-decoration:none;
|
||||||
}
|
}
|
||||||
/*discuss to group*/
|
/*discuss to group*/
|
||||||
#discuss-to-group-form {
|
#discuss-to-group-form .checkbox-label {
|
||||||
padding-bottom:10px;
|
display:inline-block;
|
||||||
|
white-space:nowrap;
|
||||||
|
padding-right:3px;
|
||||||
|
margin-right:10px;
|
||||||
}
|
}
|
||||||
#discuss-to-group-form .input {
|
#discuss-to-group-form .input {
|
||||||
padding:5px;
|
padding:5px;
|
||||||
|
@@ -6,30 +6,103 @@ $('#main-panel').css('margin-bottom', $('#bottom-bar').outerHeight() + 2);
|
|||||||
$('#footer').addClass('hide');
|
$('#footer').addClass('hide');
|
||||||
|
|
||||||
{% if groups %}
|
{% if groups %}
|
||||||
|
function getAndHandleDiscussions(data_html) {
|
||||||
|
$('#discussions-to-grp').html(data_html).css({'max-height':$(window).height() * 0.9 - $('#bottom-bar').height() - $('#discuss-to-group-caret').height() - $('#discuss-to-group-form').outerHeight()}).removeClass('hide');
|
||||||
|
{% include 'group/msg_js.html' %}
|
||||||
|
}
|
||||||
$('#discuss').click(function() {
|
$('#discuss').click(function() {
|
||||||
var form = $('#discuss-to-group-form');
|
var popup = $('#discuss-to-group');
|
||||||
var caret = $('#discuss-to-group-caret');
|
var caret = $('#discuss-to-group-caret');
|
||||||
if (form.hasClass('hide')) {
|
if (popup.hasClass('hide')) {
|
||||||
form.removeClass('hide');
|
popup.removeClass('hide');
|
||||||
caret.removeClass('hide');
|
caret.removeClass('hide');
|
||||||
caret.css({'left': $(this).offset().left});
|
caret.css({'left': $(this).offset().left});
|
||||||
|
$.ajax({
|
||||||
|
url:$('#discuss-to-group-form').attr('action'),
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json; charset=utf-8',
|
||||||
|
data: {
|
||||||
|
'repo_id': '{{ repo.id }}',
|
||||||
|
'path': '{{ path }}'
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
getAndHandleDiscussions(data['html']);
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
|
var err_str = '';
|
||||||
|
if (jqXHR.responseText) {
|
||||||
|
err_str = $.parseJSON(jqXHR.responseText).err;
|
||||||
|
feedback(err_str, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
form.addClass('hide');
|
popup.addClass('hide');
|
||||||
caret.addClass('hide');
|
caret.addClass('hide');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$(document).click(function(e) {
|
$(document).click(function(e) {
|
||||||
var target = e.target || event.srcElement;
|
var target = e.target || event.srcElement;
|
||||||
if (!$('#discuss, #discuss-to-group-form, #discuss-to-group-caret').is(target) && !($('#discuss-to-group-form, #discuss-to-group-caret').find('*').is(target))) {
|
if (!$('#discuss, #discuss-to-group, #discuss-to-group-caret').is(target) && !($('#discuss-to-group, #discuss-to-group-caret').find('*').is(target))) {
|
||||||
$('#discuss-to-group-form, #discuss-to-group-caret').addClass('hide');
|
$('#discuss-to-group, #discuss-to-group-caret').addClass('hide');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#discuss-submit').click(function() {
|
$('#discuss-submit').click(function() {
|
||||||
if (!$.trim($('#discuss-to-group-form .input').val())) {
|
var form = $('#discuss-to-group-form'),
|
||||||
apply_form_error('discuss-to-group-form', '{% trans "Please input a discussion." %}');
|
form_id = form.attr('id');
|
||||||
|
|
||||||
|
if (form.find('.checkbox-checked').length == 0) {
|
||||||
|
apply_form_error(form_id, '{% trans "Please select at least 1 group." %}');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$.trim($('#discuss-to-group-form .input').val())) {
|
||||||
|
apply_form_error(form_id, '{% trans "Please input a discussion." %}');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
form.find('.error').addClass('hide');
|
||||||
|
|
||||||
|
var groups = [];
|
||||||
|
form.find('.checkbox-checked .checkbox-orig').each(function() {
|
||||||
|
groups.push($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: form.attr('action'),
|
||||||
|
type: 'POST',
|
||||||
|
dataType: 'json',
|
||||||
|
contentType: 'application/json; charset=utf-8',
|
||||||
|
beforeSend: prepareCSRFToken,
|
||||||
|
traditional: true,
|
||||||
|
data: {
|
||||||
|
'groups': groups,
|
||||||
|
'message': form.find('.input').val(),
|
||||||
|
'repo_id': '{{ repo.id }}',
|
||||||
|
'path': '{{ path }}',
|
||||||
|
'attach_type': form.find('[name="attach_type"]').val()
|
||||||
|
},
|
||||||
|
success: function(data) {
|
||||||
|
if(data['success']) {
|
||||||
|
feedback(data['success'], 'success');
|
||||||
|
getAndHandleDiscussions(data['html']);
|
||||||
|
form.find('.input').val('');
|
||||||
|
}
|
||||||
|
if(data['err']) {
|
||||||
|
feedback(data['err'], 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(jqXHR, textStatus, errorThrown) {
|
||||||
|
var err_str = '';
|
||||||
|
if (jqXHR.responseText) {
|
||||||
|
err_str = $.parseJSON(jqXHR.responseText).err;
|
||||||
|
} else {
|
||||||
|
err_str = '{% trans "Failed. Please check the network." %}';
|
||||||
|
}
|
||||||
|
apply_form_error(form_id, err_str);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#main').append('<div id="to-group" class="hide">{{ repo_group_str|escapejs }}</div><div id="to-group-caret" class="hide"><div class="outer-caret"><div class="inner-caret"></div></div></div>');
|
$('#main').append('<div id="to-group" class="hide">{{ repo_group_str|escapejs }}</div><div id="to-group-caret" class="hide"><div class="outer-caret"><div class="inner-caret"></div></div></div>');
|
||||||
@@ -64,5 +137,5 @@ $(document).click(function(e) {
|
|||||||
$(function() {
|
$(function() {
|
||||||
var btn_height = $('#bottom-bar button').outerHeight();
|
var btn_height = $('#bottom-bar button').outerHeight();
|
||||||
$('#discuss-to-group-caret, #to-group-caret, #comment-caret').css({'bottom': btn_height + 1});
|
$('#discuss-to-group-caret, #to-group-caret, #comment-caret').css({'bottom': btn_height + 1});
|
||||||
$('#file-comment, #to-group, #discuss-to-group-form').css({'bottom': btn_height + 1 + $('.outer-caret').outerHeight()});
|
$('#file-comment, #to-group, #discuss-to-group').css({'bottom': btn_height + 1 + $('.outer-caret').outerHeight()});
|
||||||
});
|
});
|
||||||
|
46
templates/snippets/discussion_list.html
Normal file
46
templates/snippets/discussion_list.html
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{% load i18n seahub_tags avatar_tags%}
|
||||||
|
{% load url from future %}
|
||||||
|
|
||||||
|
{% for msg in messages %}
|
||||||
|
<li class="msg ovhd">
|
||||||
|
<a class="pic fleft" href="{% url 'user_profile' msg.from_email|email2id %}">{% avatar msg.from_email 48 %}</a>
|
||||||
|
<div class="txt">
|
||||||
|
<div class="msg-main">
|
||||||
|
<a href="{% url 'user_profile' msg.from_email|email2id %}" class="fleft">{{ msg.from_email|email2nickname }}</a>
|
||||||
|
<span class="time">{{ msg.timestamp|translate_seahub_time }}</span>
|
||||||
|
<p class="msg-con">{{ msg.message|seahub_urlize|find_at|linebreaksbr }}</p>
|
||||||
|
<span class="say"></span>
|
||||||
|
</div>
|
||||||
|
<div class="msg-op">
|
||||||
|
<div class="replies-op{% if msg.reply_cnt < 4 %} hide{% endif %}" data-rstatus="hide">
|
||||||
|
<span class="unfold-replies" data-url="{% url 'msg_reply' msg.id %}">{% blocktrans with amount=msg.reply_cnt %}{{ amount }} replies{% endblocktrans %}</span>
|
||||||
|
<span class="fold-replies hide">{% trans "Hide replies" %}</span>
|
||||||
|
</div>
|
||||||
|
{% if msg.reply_cnt == 0 %}
|
||||||
|
<ul class="reply-list hide"></ul>
|
||||||
|
{% else %}
|
||||||
|
<ul class="reply-list">
|
||||||
|
{% for r in msg.replies %}
|
||||||
|
<li class="reply w100 ovhd">
|
||||||
|
{% with id=r.from_email|email2id name=r.from_email|email2nickname %}
|
||||||
|
<a href="{% url 'user_profile' id %}" class="pic fleft">{% avatar r.from_email 28 %}</a>
|
||||||
|
<div class="txt">
|
||||||
|
<a href="{% url 'user_profile' id %}">{{ name }}</a>
|
||||||
|
<span class="time">{{ r.timestamp|translate_seahub_time }}</span>
|
||||||
|
<span class="reply-at op vh" data="{{ name }}">{% trans 'Reply' %}</span>
|
||||||
|
<p class="reply-con">{{ r.message|seahub_urlize|find_at }}</p>
|
||||||
|
</div>
|
||||||
|
{% endwith %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
<textarea placeholder="{% trans "Add a reply..." %}" name="message" class="reply-input"></textarea>
|
||||||
|
<p class="error hide">{% trans "It can not be blank and should be no more than 150 characters." %}</p>
|
||||||
|
<button type="button" class="reply-submit hide" data-url="{% url 'msg_reply' msg.id %}">{% trans "Submit" %}</button>
|
||||||
|
<button type="button" class="reply-cancel hide">{% trans "Cancel" %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
|
@@ -1,6 +1,7 @@
|
|||||||
{% load seahub_tags i18n %}
|
{% load seahub_tags i18n %}
|
||||||
{% load url from future %}
|
{% load url from future %}
|
||||||
<form action="{% url 'group_recommend' %}" method="post" id="discuss-to-group-form" class="hide">{% csrf_token %}
|
<div id="discuss-to-group" class="hide">
|
||||||
|
<form action="{% url 'group_recommend' %}" method="post" id="discuss-to-group-form">{% csrf_token %}
|
||||||
<h3>{% trans "Post a discussion to group" %}</h3>
|
<h3>{% trans "Post a discussion to group" %}</h3>
|
||||||
<div class="groups">
|
<div class="groups">
|
||||||
{% for group in groups %}
|
{% for group in groups %}
|
||||||
@@ -31,6 +32,8 @@
|
|||||||
<p class="error hide"></p>
|
<p class="error hide"></p>
|
||||||
<input type="submit" id="discuss-submit" class="submit" value="{% trans "Submit"%}" />
|
<input type="submit" id="discuss-submit" class="submit" value="{% trans "Submit"%}" />
|
||||||
</form>
|
</form>
|
||||||
|
<ul id="discussions-to-grp" class="hide"></ul>
|
||||||
|
</div>
|
||||||
<div id="discuss-to-group-caret" class="hide">
|
<div id="discuss-to-group-caret" class="hide">
|
||||||
<div class="outer-caret">
|
<div class="outer-caret">
|
||||||
<div class="inner-caret"></div>
|
<div class="inner-caret"></div>
|
||||||
|
Reference in New Issue
Block a user