diff --git a/media/css/seahub.css b/media/css/seahub.css
index 1b68377f9b..d9deefa0ea 100644
--- a/media/css/seahub.css
+++ b/media/css/seahub.css
@@ -9,7 +9,7 @@
* tags ..................reset styles of tags
*
* Helper
- * common class .......... common class
+ * common class ..........common class
*
* Widget
*
@@ -1226,28 +1226,19 @@ textarea:-moz-placeholder {/* for FF */
}
/**** discussions/comments ****/
.msg {
- padding:10px 0;
-}
-.msg-avatar {
- float:left;
- margin-left:10px;
+ padding:10px;
}
.msg-body {
- margin-left:54px;
-}
-.msg-header {
-}
-.msg-ops {
- float:right;
- margin-right:10px;
+ margin-left:44px;
}
.msg-op {
- cursor:pointer;
+ color:#aaa;
+ font-size:18px;
}
.msg-username {
-}
-.msg-content p:first-child {
- margin-top:0px;
+ display:inline-block;
+ vertical-align:bottom;
+ max-width:30%;
}
.msg-time {
font-size:11px;
@@ -1255,9 +1246,8 @@ textarea:-moz-placeholder {/* for FF */
margin-left:5px;
}
.msg-form {
+ padding:10px;
background:#f2f2f2;
- position:relative;
- padding-top:10px;
border-top: 1px solid #c9c9c9;
}
.msg-input {
@@ -1268,7 +1258,6 @@ textarea:-moz-placeholder {/* for FF */
color:#fff;
background:#4abb49;
border:1px solid #5cb25b;
- margin:0px 0 8px;
}
.msg-form .submit:hover {
background:#55ab22;
diff --git a/seahub/api2/endpoints/group_discussions.py b/seahub/api2/endpoints/group_discussions.py
index 8f841e452a..23b18ad4b6 100644
--- a/seahub/api2/endpoints/group_discussions.py
+++ b/seahub/api2/endpoints/group_discussions.py
@@ -80,7 +80,7 @@ class GroupDiscussions(APIView):
@api_check_group
def post(self, request, group_id, format=None):
- """Post a group discussions. Only group members can perform this op.
+ """Post a group discussion. Only group members can perform this op.
"""
content = request.data.get('content', '')
if not content:
@@ -93,19 +93,19 @@ class GroupDiscussions(APIView):
avatar_size = AVATAR_DEFAULT_SIZE
username = request.user.username
- discuss = GroupMessage.objects.create(group_id=group_id,
+ msg = GroupMessage.objects.create(group_id=group_id,
from_email=username,
message=content)
info = get_user_common_info(username, avatar_size)
- isoformat_timestr = datetime_to_isoformat_timestr(discuss.timestamp)
+ isoformat_timestr = datetime_to_isoformat_timestr(msg.timestamp)
return Response({
- "id": discuss.pk,
+ "id": msg.pk,
"group_id": group_id,
"user_name": info["name"],
"user_email": info["email"],
"user_login_id": info["login_id"],
"avatar_url": request.build_absolute_uri(info["avatar_url"]),
- "content": discuss.message,
+ "content": msg.message,
"created_at": isoformat_timestr
}, status=201)
diff --git a/seahub/group/utils.py b/seahub/group/utils.py
index 9f218c30de..1c1cb5a9bc 100644
--- a/seahub/group/utils.py
+++ b/seahub/group/utils.py
@@ -5,6 +5,7 @@ import logging
import seaserv
from seahub.utils import is_org_context
+from seahub.profile.models import Profile
from seahub.base.templatetags.seahub_tags import email2nickname
from seahub.avatar.settings import AVATAR_DEFAULT_SIZE
from seahub.avatar.templatetags.avatar_tags import api_avatar_url, \
diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html
index e9c17b6436..d3f4392945 100644
--- a/seahub/templates/js/templates.html
+++ b/seahub/templates/js/templates.html
@@ -982,17 +982,19 @@
diff --git a/seahub/templates/libraries.html b/seahub/templates/libraries.html
index 0dc0a8843e..0c367b5df7 100644
--- a/seahub/templates/libraries.html
+++ b/seahub/templates/libraries.html
@@ -160,19 +160,15 @@
-
-
{% blocktrans %}No discussion in this group yet.{% endblocktrans %}
-
+
{% trans "No discussion in this group yet." %}
diff --git a/static/scripts/app/views/group-discussion.js b/static/scripts/app/views/group-discussion.js
index c8936ec669..ccd86febc5 100644
--- a/static/scripts/app/views/group-discussion.js
+++ b/static/scripts/app/views/group-discussion.js
@@ -24,20 +24,33 @@ define([
initialize: function(options) {
this.listenTo(this.model, 'destroy', this.remove);
this.parentView = options.parentView;
+ this.is_group_owner = options.is_group_owner;
+ this.is_group_admin = options.is_group_admin;
},
render: function() {
var obj = this.model.attributes;
var m = Moment(obj['created_at']);
+ var can_delete_msg = false;
+ if (this.is_group_owner ||
+ this.is_group_admin ||
+ this.model.get('user_email') == app.pageOptions.username) {
+ can_delete_msg = true;
+ }
+
var user_profile_url = Common.getUrl({
'name': 'user_profile',
'username': encodeURIComponent(obj.user_email)
});
_.extend(obj, {
- 'content_marked': Marked(obj.content, { breaks: true }),
+ 'content_marked': Marked(obj.content, {
+ breaks: true,
+ sanitize: true
+ }),
'time': m.format('LLLL'),
'time_from_now': Common.getRelativeTimeStr(m),
+ 'can_delete_msg': can_delete_msg,
'user_profile_url': user_profile_url
});
this.$el.html(this.template(obj));
@@ -55,7 +68,7 @@ define([
},
reply: function() {
- this.parentView.beginReply(this.model.get("user_name"));
+ this.parentView.replyTo(this.model.get("user_name"));
},
delMessage: function() {
diff --git a/static/scripts/app/views/group-discussions.js b/static/scripts/app/views/group-discussions.js
index c6d1157bdc..f68628c38f 100644
--- a/static/scripts/app/views/group-discussions.js
+++ b/static/scripts/app/views/group-discussions.js
@@ -12,13 +12,14 @@ define([
el: '#group-discussions',
initialize: function(options) {
+ this.groupView = options.groupView;
+
this.collection = new GroupDiscussions();
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.reset);
this.$loadingTip = this.$('.loading-tip');
this.$listContainer = this.$('#group-discussion-list');
- this.$content = this.$('.popover-con');
this.$emptyTip = this.$('.no-discussion-tip');
this.$error = this.$('.error');
@@ -49,9 +50,11 @@ define([
addOne: function(item, collection, options) {
var view = new ItemView({
model: item,
+ is_group_owner: this.is_group_owner,
+ is_group_admin: this.is_group_admin,
parentView: this
});
- if (options.prepend == true) {
+ if (options.prepend) {
this.$listContainer.append(view.render().el);
} else {
this.$listContainer.prepend(view.render().el);
@@ -65,9 +68,8 @@ define([
if (this.collection.length) {
this.$emptyTip.hide();
this.collection.each(this.addOne, this);
- this.$listContainer.removeClass('hide');
this.$listContainer.show();
- this.$content.scrollTop(9999);
+ this.scrollConToBottom();
} else {
this.$emptyTip.show();
this.$listContainer.hide();
@@ -79,10 +81,21 @@ define([
this.$loadingTip.show();
var _this = this;
+
+ // the user's role in this group
+ this.is_group_owner = false;
+ this.is_group_admin = false;
+ if (app.pageOptions.username == this.groupView.group.owner) {
+ this.is_group_owner = true;
+ } else if ($.inArray(app.pageOptions.username, this.groupView.group.admins) != -1) {
+ this.is_group_admin = true;
+ }
+
this.collection.setGroupId(this.group_id);
this.collection.fetch({
cache: false,
reset: true,
+ data: {'avatar_size': 64},
success: function(collection, response, opts) {
},
error: function(collection, response, opts) {
@@ -108,10 +121,9 @@ define([
'max-height': $(window).height() - this.$el.offset().top
- this.$('.popover-hd').outerHeight(true)
- this.$('.popover-footer').outerHeight(true)
- - 2
- - 10
- }); // 2: top, bottom border width of $el,
- // 10: leave some margin at the bottom
+ - 2 // 2: top, bottom border width of $el,
+ - 10 // 10: leave some margin at the bottom
+ });
},
show: function(options) {
@@ -127,8 +139,11 @@ define([
app.router.navigate('group/' + this.group_id + '/');
},
- beginReply: function(to_user) {
- this.$('[name="message"]').val("@" + to_user + " ");
+ replyTo: function(to_user) {
+ var str = "@" + to_user + " ";
+ var $input = this.$('[name="message"]').val(str);
+ Common.setCaretPosition($input[0], str.length);
+ $input.focus();
},
formSubmit: function() {
@@ -139,7 +154,10 @@ define([
return false;
}
- this.collection.create({ content: content }, {
+ this.collection.create({
+ content: content,
+ avatar_size: 64
+ }, {
wait: true,
validate: true,
prepend: true,
@@ -147,6 +165,8 @@ define([
_this.$('[name="message"]').val('');
if (_this.collection.length == 1) {
_this.collection.reset(_this.collection.models);
+ } else {
+ _this.scrollConToBottom();
}
},
error: function(collection, response, options) {
@@ -161,6 +181,12 @@ define([
});
return false;
+ },
+
+ // scroll '.popover-con' to the bottom
+ scrollConToBottom: function() {
+ var $el = this.$('.popover-con');
+ $el.scrollTop($el[0].scrollHeight - $el[0].clientHeight);
}
});
diff --git a/static/scripts/app/views/group-settings.js b/static/scripts/app/views/group-settings.js
index 35fe88b92a..694c4bf727 100644
--- a/static/scripts/app/views/group-settings.js
+++ b/static/scripts/app/views/group-settings.js
@@ -52,7 +52,7 @@ define([
this.$listContainer.hide();
// the user's role in this group
- this.is_owner = false,
+ this.is_owner = false;
this.is_admin = false;
if (app.pageOptions.username == this.group.owner) {
diff --git a/static/scripts/app/views/group.js b/static/scripts/app/views/group.js
index 20d842faaf..7550eb4056 100644
--- a/static/scripts/app/views/group.js
+++ b/static/scripts/app/views/group.js
@@ -49,7 +49,9 @@ define([
this.settingsView = new GroupSettingsView({
groupView: this
});
- this.discussionsView = new GroupDiscussionsView();
+ this.discussionsView = new GroupDiscussionsView({
+ groupView: this
+ });
},
addOne: function(repo, collection, options) {
diff --git a/static/scripts/common.js b/static/scripts/common.js
index 4252f6eb7f..d9f684571e 100644
--- a/static/scripts/common.js
+++ b/static/scripts/common.js
@@ -829,6 +829,17 @@ define([
}
}
return group_name;
+ },
+
+ setCaretPosition:function(input, pos) {
+ var range;
+ if (document.selection) {
+ range = input.createTextRange();
+ range.move("character", pos);
+ return range.select();
+ } else {
+ return input.setSelectionRange(pos, pos);
+ }
}
}