Commit 790d4cab by Rocky Duan

display mentioned user links in front end

parent 7a606f2b
...@@ -28,20 +28,32 @@ def shared_key_auth_required(fn): ...@@ -28,20 +28,32 @@ def shared_key_auth_required(fn):
return fn(request, *args, **kwargs) return fn(request, *args, **kwargs)
return wrapper return wrapper
def format_time(t):
return t.strftime("%m/%d/%y %H:%M %p")
def users_description(grouped_replies):
first_user = grouped_replies[0]['info']['actor_username'] or 'Anonymous'
if len(grouped_replies) == 1:
return first_user
else:
return "{0} and {1} other user(s)".format(first_user, len(grouped_replies) - 1)
def process_replies(replies): def process_replies(replies):
def processor(wrapped_info): def processor(wrapped_info):
thread_id, grouped_replies = wrapped_info thread_id, grouped_replies = wrapped_info
grouped_replies = list(grouped_replies) grouped_replies = list(grouped_replies)
course_id = grouped_replies[0]['course_id'] course_id = grouped_replies[0]['course_id']
commentable_id = grouped_replies[0]['info']['commentable_id'] commentable_id = grouped_replies[0]['info']['commentable_id']
return { processed = {
'post_reply': True, 'post_reply': True,
'replies_count': len(grouped_replies), 'users_description': users_description(grouped_replies),
'thread_url': reverse('django_comment_client.forum.views.single_thread', 'thread_url': reverse('django_comment_client.forum.views.single_thread',
args=[course_id, commentable_id, thread_id]), args=[course_id, commentable_id, thread_id]),
'happened_at': min(map(lambda x: x['happened_at'], grouped_replies)), 'happened_at': min(map(lambda x: x['happened_at'], grouped_replies)),
'thread_title': grouped_replies[0]['info']['thread_title'], 'thread_title': grouped_replies[0]['info']['thread_title'],
} }
processed['str_time'] = format_time(processed['happened_at'])
return processed
replies = groupby(replies, lambda x: x['info']['thread_id']) replies = groupby(replies, lambda x: x['info']['thread_id'])
return map(processor, [(k, list(v)) for k, v in replies]) return map(processor, [(k, list(v)) for k, v in replies])
...@@ -50,15 +62,16 @@ def process_topics(topics): ...@@ -50,15 +62,16 @@ def process_topics(topics):
thread_id = notification['info']['thread_id'] thread_id = notification['info']['thread_id']
course_id = notification['course_id'] course_id = notification['course_id']
commentable_id = notification['info']['commentable_id'] commentable_id = notification['info']['commentable_id']
return { processed = {
'post_topic': True, 'post_topic': True,
'user_id': notification['info']['actor_id'], 'users_description': notification['info']['actor_username'] or 'Anonymous',
'username': notification['info']['actor_username'],
'thread_url': reverse('django_comment_client.forum.views.single_thread', 'thread_url': reverse('django_comment_client.forum.views.single_thread',
args=[course_id, commentable_id, thread_id]), args=[course_id, commentable_id, thread_id]),
'happened_at': notification['happened_at'], 'happened_at': notification['happened_at'],
'thread_title': notification['info']['thread_title'], 'thread_title': notification['info']['thread_title'],
} }
processed['str_time'] = format_time(processed['happened_at'])
return processed
return map(process, topics) return map(process, topics)
def process_at_users(at_users): def process_at_users(at_users):
...@@ -67,18 +80,18 @@ def process_at_users(at_users): ...@@ -67,18 +80,18 @@ def process_at_users(at_users):
course_id = notification['course_id'] course_id = notification['course_id']
commentable_id = notification['info']['commentable_id'] commentable_id = notification['info']['commentable_id']
content_type = notification['info']['content_type'] content_type = notification['info']['content_type']
data = { processed = {
'at_user_in_' + content_type: True, 'at_user_in_' + content_type: True,
'user_id': notification['info']['actor_id'], 'users_description': notification['info']['actor_username'] or 'Anonymous',
'username': notification['info']['actor_username'],
'thread_url': reverse('django_comment_client.forum.views.single_thread', 'thread_url': reverse('django_comment_client.forum.views.single_thread',
args=[course_id, commentable_id, thread_id]), args=[course_id, commentable_id, thread_id]),
'happened_at': notification['happened_at'], 'happened_at': notification['happened_at'],
'thread_title': notification['info']['thread_title'], 'thread_title': notification['info']['thread_title'],
} }
if content_type == "comment": if content_type == "comment":
data['comment_url'] = data['thread_url'] + "#" + notification['info']['comment_id'] processed['comment_url'] = processed['thread_url'] + "#" + notification['info']['comment_id']
return data processed['str_time'] = format_time(processed['happened_at'])
return processed
return map(process, at_users) return map(process, at_users)
@require_POST @require_POST
...@@ -91,7 +104,7 @@ def notifications_callback(request): ...@@ -91,7 +104,7 @@ def notifications_callback(request):
raw_notifications = json.loads(request.POST['json_notifications']) raw_notifications = json.loads(request.POST['json_notifications'])
if len(raw_notifications) == 0: if len(raw_notifications) == 0:
return return JsonResponse({'status': 'success'})
timezone = pytz.timezone(settings.TIME_ZONE) timezone = pytz.timezone(settings.TIME_ZONE)
...@@ -105,7 +118,7 @@ def notifications_callback(request): ...@@ -105,7 +118,7 @@ def notifications_callback(request):
notifications = process_replies(replies) + process_topics(topics) + process_at_users(at_users) notifications = process_replies(replies) + process_topics(topics) + process_at_users(at_users)
notifications = sorted(notifications, key=lambda x: x['happened_at']) notifications = sorted(notifications, key=lambda x: x['happened_at'])
since_time = notifications[0]['happened_at'].strftime("%H:%M %p") since_time = format_time(notifications[0]['happened_at'])
for user_id in user_ids: for user_id in user_ids:
try: try:
......
...@@ -252,6 +252,7 @@ def safe_content(content): ...@@ -252,6 +252,7 @@ def safe_content(content):
'created_at', 'updated_at', 'depth', 'type', 'created_at', 'updated_at', 'depth', 'type',
'commentable_id', 'comments_count', 'at_position_list', 'commentable_id', 'comments_count', 'at_position_list',
'children', 'highlighted_title', 'highlighted_body', 'children', 'highlighted_title', 'highlighted_body',
'marked_title', 'marked_body',
] ]
if content.get('anonymous') is False: if content.get('anonymous') is False:
......
...@@ -12,6 +12,7 @@ class Comment(models.Model): ...@@ -12,6 +12,7 @@ class Comment(models.Model):
'username', 'votes', 'user_id', 'closed', 'username', 'votes', 'user_id', 'closed',
'created_at', 'updated_at', 'depth', 'created_at', 'updated_at', 'depth',
'at_position_list', 'type', 'commentable_id', 'at_position_list', 'type', 'commentable_id',
'marked_body',
] ]
updatable_fields = [ updatable_fields = [
......
...@@ -12,6 +12,7 @@ class Thread(models.Model): ...@@ -12,6 +12,7 @@ class Thread(models.Model):
'created_at', 'updated_at', 'comments_count', 'created_at', 'updated_at', 'comments_count',
'at_position_list', 'children', 'type', 'at_position_list', 'children', 'type',
'highlighted_title', 'highlighted_body', 'highlighted_title', 'highlighted_body',
'marked_body', 'marked_title',
] ]
updatable_fields = [ updatable_fields = [
......
...@@ -8,7 +8,7 @@ class User(models.Model): ...@@ -8,7 +8,7 @@ class User(models.Model):
accessible_fields = ['username', 'email', 'follower_ids', 'upvoted_ids', 'downvoted_ids', accessible_fields = ['username', 'email', 'follower_ids', 'upvoted_ids', 'downvoted_ids',
'id', 'external_id', 'subscribed_user_ids', 'children', 'course_id', 'id', 'external_id', 'subscribed_user_ids', 'children', 'course_id',
'subscribed_thread_ids', 'subscribed_commentable_ids', 'subscribed_thread_ids', 'subscribed_commentable_ids',
'threads_count', 'comments_count', 'subscribed_course_ids', 'threads_count', 'comments_count',
] ]
updatable_fields = ['username', 'external_id', 'email'] updatable_fields = ['username', 'external_id', 'email']
......
...@@ -277,10 +277,12 @@ if Backbone? ...@@ -277,10 +277,12 @@ if Backbone?
edit: (event) -> edit: (event) ->
@$(".discussion-content-wrapper").hide() @$(".discussion-content-wrapper").hide()
console.log @$el
$editView = @$(".discussion-content-edit") $editView = @$(".discussion-content-edit")
if $editView.length if $editView.length
$editView.show() $editView.show()
else else
console.log "regenerating edit view"
view = {} view = {}
view.id = @model.id view.id = @model.id
if @model.get('type') == 'thread' if @model.get('type') == 'thread'
...@@ -385,20 +387,57 @@ if Backbone? ...@@ -385,20 +387,57 @@ if Backbone?
@model.view = @ @model.view = @
@model.bind('change', @renderPartial, @) @model.bind('change', @renderPartial, @)
initAtUsers: ->
#@model.get('title').replace AT_NOTIFICATION_REGEX
#console.log @model.get('at_position_list')
S_LT = "\\&lt\\;"
S_GT = "\\&gt\\;"
S_QUOTE = "\\&\\#x27\\;"
S_BKSLASH = "\\&\\#x2F\\;"
RE_MENTIONED_USER = ///
#{S_LT} span \s* class= #{S_QUOTE} mentioned_user #{S_QUOTE}
\s* user_id= #{S_QUOTE} (\w+) #{S_QUOTE} #{S_GT}
(@[A-Za-z0-9_]+)
#{S_LT} #{S_BKSLASH} span #{S_GT}
///g
initMarkedContent: ->
console.log "initializing"
_escape = (text) ->
_.escape(text).replace RE_MENTIONED_USER, ($0, $1, $2) ->
"<span class='mentioned_user' user_id='#{$1}'>#{$2}</span>"
if @model.get('marked_title')
@$(".thread-title").html(_escape(@model.get('marked_title')))
if @model.get('marked_body')
@$(".content-body").html(_escape(@model.get('marked_body')))
@$(".mentioned_user").each (index, elem) =>
userId = $(elem).attr("user_id")
href = DiscussionUtil.urlFor('user_profile', userId)
$(elem).replaceWith($("<a>").attr("href", href).html($(elem).html()))
initialize: -> initialize: ->
@initBindings() @initBindings()
@initLocal() @initLocal()
@initTimeago() @initTimeago()
@initTitle() @initTitle()
@initBody() @initBody()
@initMarkedContent()
@initAtUsers()
@initCommentViews() @initCommentViews()
reconstruct: -> reconstruct: ->
@_discussionContent = null
@_showComments = null
@initBindings() @initBindings()
@initLocal() @initLocal()
@initTimeago() @initTimeago()
@initTitle() @initTitle()
@initBody() @initBody()
@initMarkedContent()
@initAtUsers()
@delegateEvents() @delegateEvents()
class @Thread extends @Content class @Thread extends @Content
......
...@@ -64,6 +64,7 @@ class @DiscussionUtil ...@@ -64,6 +64,7 @@ class @DiscussionUtil
openclose_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/close" openclose_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/close"
permanent_link_thread : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}" permanent_link_thread : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}"
permanent_link_comment : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}##{param2}" permanent_link_comment : "/courses/#{$$course_id}/discussion/forum/#{param}/threads/#{param1}##{param2}"
user_profile : "/courses/#{$$course_id}/discussion/forum/users/#{param}"
}[name] }[name]
@safeAjax: (params) -> @safeAjax: (params) ->
......
<ul> <ul>
{{#notifications}} {{#notifications}}
{{#post_reply}} {{#post_reply}}
<li>{{replies_count}} user(s) replied to the post <a href="{{thread_url}}">{{thread_title}}</a></li> <li>{{users_description}} replied to the post <a href="{{thread_url}}">{{thread_title}}</a> ({{str_time}})</li>
{{/post_reply}} {{/post_reply}}
{{#post_topic}} {{#post_topic}}
<li>{{username}} wrote a new post: <a href="{{thread_url}}">{{thread_title}}</a></li> <li>{{users_description}} wrote a new post: <a href="{{thread_url}}">{{thread_title}}</a> ({{str_time}})</li>
{{/post_topic}} {{/post_topic}}
{{#at_user_in_comment}} {{#at_user_in_comment}}
<li>{{username}} mentioned you in the comment to the post <a href="{{comment_url}}">{{thread_title}}</a></li> <li>{{users_description}} mentioned you in the comment to the post <a href="{{comment_url}}">{{thread_title}}</a> ({{str_time}})</li>
{{/at_user_in_comment}} {{/at_user_in_comment}}
{{#at_user_in_thread}} {{#at_user_in_thread}}
<li>{{username}} mentioned you in the comment to the post <a href="{{thread_url}}">{{thread_title}}</a></li> <li>{{users_description}} mentioned you in the post <a href="{{thread_url}}">{{thread_title}}</a> ({{str_time}})</li>
{{/at_user_in_thread}} {{/at_user_in_thread}}
{{/notifications}} {{/notifications}}
</ul> </ul>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment