Commit bedeac3a by Rocky Duan

make course id available in xmodule

parent f485167b
......@@ -19,6 +19,7 @@ class DiscussionModule(XModule):
'discussion_id': self.discussion_id,
'search_bar': '',
'user_info': comment_client.get_user_info(self.user_id, raw=True),
'course_id': self.course_id,
}
return self.system.render_template('discussion/inline.html', context)
......@@ -30,8 +31,9 @@ class DiscussionModule(XModule):
xml_data = etree.fromstring(definition['data'])
self.discussion_id = xml_data.attrib['id']
self.title = xml_data.attrib['for']
self.category = xml_data.attrib['category']
self.discussion_category = xml_data.attrib['discussion_category']
self.user_id = instance_state['user_id']
self.course_id = instance_state['course_id']
class DiscussionDescriptor(RawDescriptor):
module_class = DiscussionModule
......@@ -200,6 +200,13 @@ def get_module(user, request, location, student_module_cache, position=None):
'''
descriptor = modulestore().get_item(location)
user_id = user.id
import re
course_id = re.search(r'^/courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/', request.path)
if course_id:
course_id = course_id.group('course_id')
instance_module = student_module_cache.lookup(descriptor.category, descriptor.location.url())
shared_state_key = getattr(descriptor, 'shared_state_key', None)
if shared_state_key is not None:
......@@ -207,8 +214,12 @@ def get_module(user, request, location, student_module_cache, position=None):
else:
shared_module = None
instance_state = instance_module.state if instance_module is not None else None
instance_state = json.dumps(dict(json.loads(instance_state).items() + [("user_id", user.id)]))
instance_state = instance_module.state if instance_module is not None else {}
instance_hash = json.loads(instance_state) if isinstance(instance_state, str) or isinstance(instance_state, unicode) \
else instance_state
instance_state = json.dumps(dict(instance_hash.items() + [("user_id", user.id), ("course_id", course_id)]))
shared_state = shared_module.state if shared_module is not None else None
# Setup system context for module instance
......
......@@ -52,41 +52,41 @@ def extract(dic, keys):
@login_required
@require_POST
def create_thread(request, commentable_id):
def create_thread(request, course_id, commentable_id):
attributes = extract(request.POST, ['body', 'title'])
attributes['user_id'] = request.user.id
attributes['course_id'] = "1" # TODO either remove this or pass this parameter somehow
attributes['course_id'] = course_id
response = comment_client.create_thread(commentable_id, attributes)
return JsonResponse(response)
@thread_author_only
@login_required
@require_POST
def update_thread(request, thread_id):
def update_thread(request, course_id, thread_id):
attributes = extract(request.POST, ['body', 'title'])
response = comment_client.update_thread(thread_id, attributes)
return JsonResponse(response)
@login_required
@require_POST
def create_comment(request, thread_id):
def create_comment(request, course_id, thread_id):
attributes = extract(request.POST, ['body'])
attributes['user_id'] = request.user.id
attributes['course_id'] = "1" # TODO either remove this or pass this parameter somehow
attributes['course_id'] = course_id
response = comment_client.create_comment(thread_id, attributes)
return JsonResponse(response)
@thread_author_only
@login_required
@require_POST
def delete_thread(request, thread_id):
def delete_thread(request, course_id, thread_id):
response = comment_client.delete_thread(thread_id)
return JsonResponse(response)
@thread_author_only
@login_required
@require_POST
def update_comment(request, comment_id):
def update_comment(request, course_id, comment_id):
attributes = extract(request.POST, ['body'])
response = comment_client.update_comment(comment_id, attributes)
return JsonResponse(response)
......@@ -94,14 +94,14 @@ def update_comment(request, comment_id):
@instructor_only
@login_required
@require_POST
def endorse_comment(request, comment_id):
def endorse_comment(request, course_id, comment_id):
attributes = extract(request.POST, ['endorsed'])
response = comment_client.update_comment(comment_id, attributes)
return JsonResponse(response)
@login_required
@require_POST
def create_sub_comment(request, comment_id):
def create_sub_comment(request, course_id, comment_id):
attributes = extract(request.POST, ['body'])
attributes['user_id'] = request.user.id
attributes['course_id'] = "1" # TODO either remove this or pass this parameter somehow
......@@ -111,69 +111,69 @@ def create_sub_comment(request, comment_id):
@comment_author_only
@login_required
@require_POST
def delete_comment(request, comment_id):
def delete_comment(request, course_id, comment_id):
response = comment_client.delete_comment(comment_id)
return JsonResponse(response)
@login_required
@require_POST
def vote_for_comment(request, comment_id, value):
def vote_for_comment(request, course_id, comment_id, value):
user_id = request.user.id
response = comment_client.vote_for_comment(comment_id, user_id, value)
return JsonResponse(response)
@login_required
@require_POST
def vote_for_thread(request, thread_id, value):
def vote_for_thread(request, course_id, thread_id, value):
user_id = request.user.id
response = comment_client.vote_for_thread(thread_id, user_id, value)
return JsonResponse(response)
@login_required
@require_POST
def watch_thread(request, thread_id):
def watch_thread(request, course_id, thread_id):
user_id = request.user.id
response = comment_client.subscribe_thread(user_id, thread_id)
return JsonResponse(response)
@login_required
@require_POST
def watch_commentable(request, commentable_id):
def watch_commentable(request, course_id, commentable_id):
user_id = request.user.id
response = comment_client.subscribe_commentable(user_id, commentable_id)
return JsonResponse(response)
@login_required
@require_POST
def follow(request, followed_user_id):
def follow(request, course_id, followed_user_id):
user_id = request.user.id
response = comment_client.follow(user_id, followed_user_id)
return JsonResponse(response)
@login_required
@require_POST
def unwatch_thread(request, thread_id):
def unwatch_thread(request, course_id, thread_id):
user_id = request.user.id
response = comment_client.unsubscribe_thread(user_id, thread_id)
return JsonResponse(response)
@login_required
@require_POST
def unwatch_commentable(request, commentable_id):
def unwatch_commentable(request, course_id, commentable_id):
user_id = request.user.id
response = comment_client.unsubscribe_commentable(user_id, commentable_id)
return JsonResponse(response)
@login_required
@require_POST
def unfollow(request, followed_user_id):
def unfollow(request, course_id, followed_user_id):
user_id = request.user.id
response = comment_client.unfollow(user_id, followed_user_id)
return JsonResponse(response)
@login_required
@require_GET
def search(request):
def search(request, course_id):
text = request.GET.get('text', None)
commentable_id = request.GET.get('commentable_id', None)
response = comment_client.search(text, commentable_id)
......
......@@ -4,5 +4,5 @@ import django_comment_client.forum.views
urlpatterns = patterns('django_comment_client.forum.views',
url(r'search$', 'search', name='search'),
url(r'threads/(?P<thread_id>\w+)$', 'single_thread', name='single_thread'),
url(r'(?P<course_id>[\w\.\-]+)/(?P<discussion_id>\w+)$', 'forum_form_discussion', name='forum_form_discussion'),
url(r'(?P<discussion_id>\w+)$', 'forum_form_discussion', name='forum_form_discussion'),
)
......@@ -58,7 +58,7 @@ def get_categorized_discussion_info(request, user, course, course_name, url_cour
return {
'title': module.title,
'discussion_id': module.discussion_id,
'category': module.category,
'category': module.discussion_category,
}
discussion_module_descriptors = map(_get_module_descriptor,
......@@ -90,27 +90,28 @@ def render_accordion(request, course, discussion_info, discussion_id):
return render_to_string('discussion/accordion.html', context)
def render_discussion(request, threads, discussion_id=None, search_text=''):
def render_discussion(request, course_id, threads, discussion_id=None, search_text=''):
context = {
'threads': threads,
'discussion_id': discussion_id,
'search_bar': render_search_bar(request, discussion_id, text=search_text),
'search_bar': render_search_bar(request, course_id, discussion_id, text=search_text),
'user_info': comment_client.get_user_info(request.user.id, raw=True),
'course_id': course_id,
}
return render_to_string('discussion/inline.html', context)
def render_search_bar(request, discussion_id=None, text=''):
def render_search_bar(request, course_id, discussion_id=None, text=''):
if not discussion_id:
return ''
context = {
'discussion_id': discussion_id,
'text': text,
'course_id': course_id,
}
return render_to_string('discussion/search_bar.html', context)
def forum_form_discussion(request, course_id, discussion_id):
course_id = course_id.replace('-', '/')
course = check_course(course_id)
_, course_name, _ = course_id.split('/')
......@@ -131,39 +132,46 @@ def forum_form_discussion(request, course_id, discussion_id):
'COURSE_TITLE': course.title,
'course': course,
'init': '',
'content': render_discussion(request, threads, discussion_id, search_text),
'content': render_discussion(request, course_id, threads, discussion_id, search_text),
'accordion': render_accordion(request, course, discussion_info, discussion_id),
}
return render_to_response('discussion/index.html', context)
def render_single_thread(request, thread_id):
def render_single_thread(request, course_id, thread_id):
context = {
'thread': comment_client.get_thread(thread_id, recursive=True),
'user_info': comment_client.get_user_info(request.user.id, raw=True),
'course_id': course_id,
}
return render_to_string('discussion/single_thread.html', context)
def single_thread(request, thread_id):
def single_thread(request, course_id, thread_id):
course = check_course(course_id)
context = {
'csrf': csrf(request)['csrf_token'],
'init': '',
'content': render_single_thread(request, thread_id),
'content': render_single_thread(request, course_id, thread_id),
'accordion': '',
'user_info': comment_client.get_user_info(request.user.id, raw=True),
'course': course,
}
return render_to_response('discussion/index.html', context)
def search(request):
def search(request, course_id):
course = check_course(course_id)
text = request.GET.get('text', None)
threads = comment_client.search(text)
context = {
'csrf': csrf(request)['csrf_token'],
'init': '',
'content': render_discussion(request, threads, search_text=text),
'content': render_discussion(request, course_id, threads, search_text=text),
'accordion': '',
'course': course,
}
return render_to_response('discussion/index.html', context)
......@@ -26,23 +26,23 @@ Discussion =
urlFor: (name, param) ->
{
watch_commentable : "/discussions/#{param}/watch"
unwatch_commentable : "/discussions/#{param}/unwatch"
create_thread : "/discussions/#{param}/threads/create"
update_thread : "/discussions/threads/#{param}/update"
create_comment : "/discussions/threads/#{param}/reply"
delete_thread : "/discussions/threads/#{param}/delete"
upvote_thread : "/discussions/threads/#{param}/upvote"
downvote_thread : "/discussions/threads/#{param}/downvote"
watch_thread : "/discussions/threads/#{param}/watch"
unwatch_thread : "/discussions/threads/#{param}/unwatch"
update_comment : "/discussions/comments/#{param}/update"
endorse_comment : "/discussions/comments/#{param}/endorse"
create_sub_comment : "/discussions/comments/#{param}/reply"
delete_comment : "/discussions/comments/#{param}/delete"
upvote_comment : "/discussions/comments/#{param}/upvote"
downvote_comment : "/discussions/comments/#{param}/downvote"
search : "/discussions/forum/search"
watch_commentable : "/courses/#{$$course_id}/discussion/#{param}/watch"
unwatch_commentable : "/courses/#{$$course_id}/discussion/#{param}/unwatch"
create_thread : "/courses/#{$$course_id}/discussion/#{param}/threads/create"
update_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/update"
create_comment : "/courses/#{$$course_id}/discussion/threads/#{param}/reply"
delete_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/delete"
upvote_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/upvote"
downvote_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/downvote"
watch_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/watch"
unwatch_thread : "/courses/#{$$course_id}/discussion/threads/#{param}/unwatch"
update_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/update"
endorse_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/endorse"
create_sub_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/reply"
delete_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/delete"
upvote_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/upvote"
downvote_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/downvote"
search : "/courses/#{$$course_id}/discussion/forum/search"
}[name]
handleAnchorAndReload: (response) ->
......@@ -54,11 +54,36 @@ Discussion =
$content = $(content)
$local = generateLocal($content.children(".discussion-content"))
id = $content.attr("_id")
if id in user_info.upvoted_ids
if id in $$user_info.upvoted_ids
$local(".discussion-vote-up").addClass("voted")
else if id in user_info.downvoted_ids
else if id in $$user_info.downvoted_ids
$local(".discussion-vote-down").addClass("voted")
initializeWatchDiscussion = (discussion) ->
$discussion = $(discussion)
id = $discussion.attr("_id")
$local = generateLocal($discussion.children(".discussion-non-content"))
handleWatchDiscussion = (elem) ->
url = Discussion.urlFor('watch_commentable', id)
$.post url, {}, (response, textStatus) ->
if textStatus == "success"
Discussion.handleAnchorAndReload(response)
, 'json'
handleUnwatchDiscussion = (elem) ->
url = Discussion.urlFor('unwatch_commentable', id)
$.post url, {}, (response, textStatus) ->
if textStatus == "success"
Discussion.handleAnchorAndReload(response)
, 'json'
if id in $$user_info.subscribed_commentable_ids
unwatchDiscussion = generateDiscussionLink("discussion-unwatch-discussion", "Unwatch", handleUnwatchDiscussion)
$local(".discussion-title-wrapper").append(unwatchDiscussion)
else
watchDiscussion = generateDiscussionLink("discussion-watch-discussion", "Watch", handleWatchDiscussion)
$local(".discussion-title-wrapper").append(watchDiscussion)
initializeWatchThreads = (index, thread) ->
$thread = $(thread)
......@@ -67,7 +92,6 @@ Discussion =
handleWatchThread = (elem) ->
url = Discussion.urlFor('watch_thread', id)
console.log url
$.post url, {}, (response, textStatus) ->
if textStatus == "success"
Discussion.handleAnchorAndReload(response)
......@@ -80,16 +104,17 @@ Discussion =
Discussion.handleAnchorAndReload(response)
, 'json'
if id in user_info.subscribed_thread_ids
if id in $$user_info.subscribed_thread_ids
unwatchThread = generateDiscussionLink("discussion-unwatch-thread", "Unwatch", handleUnwatchThread)
$local(".info").append(unwatchThread)
else
watchThread = generateDiscussionLink("discussion-watch-thread", "Watch", handleWatchThread)
$local(".info").append(watchThread)
if user_info?
if $$user_info?
$(discussion).find(".comment").each(initializeVote)
$(discussion).find(".thread").each(initializeVote).each(initializeWatchThreads)
initializeWatchDiscussion(discussion)
bindContentEvents: (content) ->
......
......@@ -37,6 +37,7 @@ $discussion_input_width: 60%;
@include discussion-font;
}
}
.discussion-title {
@include discussion-font;
@include discussion-clickable;
......@@ -45,6 +46,22 @@ $discussion_input_width: 60%;
margin-bottom: 20px;
display: block;
}
.discussion-title-wrapper {
.discussion-watch-discussion, .discussion-unwatch-discussion {
display: none;
@include discussion-font;
margin-left: 5px;
font-size: $comment_info_size;
}
.discussion-title {
display: inline-block;
}
&:hover {
.discussion-watch-discussion, .discussion-unwatch-discussion {
display: inline-block;
}
}
}
.discussion-votes {
margin-right: 8px;
margin-top: 5px;
......
......@@ -15,7 +15,7 @@ def url_class(url):
<li class="info"><a href="${reverse('info', args=[course.id])}" class="${url_class('info')}">Course Info</a></li>
% if user.is_authenticated():
<li class="book"><a href="${reverse('book', args=[course.id])}" class="${url_class('book')}">Textbook</a></li>
<li class="discussion"><a href="${reverse('django_comment_client.forum.views.forum_form_discussion', args=[course.id.replace('/', '-'), course.id.replace('/', '_').replace('.', '_')])}" class="${url_class('discussion')}">Discussion</a></li>
<li class="discussion"><a href="${reverse('django_comment_client.forum.views.forum_form_discussion', args=[course.id, course.id.replace('/', '_').replace('.', '_')])}" class="${url_class('discussion')}">Discussion</a></li>
% endif
<li class="wiki"><a href="${reverse('wiki_root', args=[course.id])}" class="${url_class('wiki')}">Wiki</a></li>
% if user.is_authenticated():
......
<%! from django.core.urlresolvers import reverse %>
<%
def url_for(board):
return reverse('django_comment_client.forum.views.forum_form_discussion', args=[course.id.replace('/', '-'), board['discussion_id']])
def url_for(commentable):
return reverse('django_comment_client.forum.views.forum_form_discussion', args=[course.id, commentable['discussion_id']])
%>
<%def name="make_category(category, boards)">
<%def name="make_category(category, commentables)">
<h3><a href="#">${category}</a></h3>
<ul>
% for board in boards:
<li${' class="active"' if active == board['discussion_id'] else ''}>
<a href="${url_for(board)}">
<p>${board['title']}</p>
% for commentable in commentables:
<li${' class="active"' if active == commentable['discussion_id'] else ''}>
<a href="${url_for(commentable)}">
<p>${commentable['title']}</p>
</a>
% endfor
</ul>
</%def>
% for category, boards in discussion_info.items():
${make_category(category, boards)}
% for category, commentables in discussion_info.items():
${make_category(category, commentables)}
% endfor
......@@ -10,7 +10,7 @@
<%block name="js_extra">
</%block>
##<%include file="../course_navigation.html" args="active_page='discussion'" />
<%include file="../course_navigation.html" args="active_page='discussion'" />
<section class="container">
<div class="course-wrapper">
......
<%namespace name="renderer" file="thread.html"/>
<section class="discussion">
<section class="discussion" _id="${discussion_id}">
<div class="discussion-non-content">
<a class="discussion-title" href="javascript:void(0)">Discussion</a>
<div class="discussion-title-wrapper">
<a class="discussion-title" href="javascript:void(0)">Discussion</a>
</div>
${search_bar}
<form class="new-post-form" _id="${discussion_id}">
<input type="text" class="new-post-title" placeholder="Title"/>
......@@ -11,11 +13,11 @@
</form>
</div>
% for thread in threads:
${renderer.render_thread(thread, edit_thread=False, show_comments=False)}
${renderer.render_thread(course_id, thread, edit_thread=False, show_comments=False)}
% endfor
</section>
<script type="text/javascript">
var user_info = JSON.parse('${user_info}');
var $$user_info = JSON.parse('${user_info}');
var $$course_id = "${course_id}";
</script>
......@@ -2,7 +2,7 @@
<%
def url_for_search():
return reverse('django_comment_client.forum.views.search')
return reverse('django_comment_client.forum.views.search', args=[course_id])
%>
<form action="${url_for_search()}" method="get" class="discussion-search-form">
......
......@@ -2,10 +2,10 @@
<section class="discussion">
<a class="discussion-title" href="javascript:void(0)">Discussion</a>
${renderer.render_thread(thread, edit_thread=True, show_comments=True)}
${renderer.render_thread(course_id, thread, edit_thread=True, show_comments=True)}
</section>
<script type="text/javascript">
var user_info = JSON.parse('${user_info}');
var $$user_info = JSON.parse('${user_info}');
var $$course_id = "${course_id}";
</script>
......@@ -2,13 +2,13 @@
<%! from datehelper import time_ago_in_words %>
<%! from dateutil.parser import parse %>
<%def name="render_thread(thread, edit_thread=False, show_comments=False)">
<%def name="render_thread(course_id, thread, edit_thread=False, show_comments=False)">
<%
if show_comments:
url_for_thread = ""
else:
thread_id = thread['id']
url_for_thread = reverse('django_comment_client.forum.views.single_thread', args=[thread_id])
url_for_thread = reverse('django_comment_client.forum.views.single_thread', args=[course_id, thread_id])
%>
<div class="thread" _id="${thread['id']}">
<div class="discussion-content">
......
......@@ -130,6 +130,10 @@ if settings.COURSEWARE_ENABLED:
'courseware.views.profile', name="profile"),
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/profile/(?P<student_id>[^/]*)/$',
'courseware.views.profile'),
# discussion
url(r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/discussion/',
include('django_comment_client.urls')),
)
# Multicourse wiki
......@@ -154,8 +158,6 @@ if settings.ASKBOT_ENABLED:
# url(r'^robots.txt$', include('robots.urls')),
)
# discussion
urlpatterns += (url(r'^discussions/', include('django_comment_client.urls')), )
if settings.DEBUG:
## Jasmine
......
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