Commit a8e23dcc by Rocky Duan

Merge branch 'master' into discussion2

Conflicts:
	lms/templates/discussion/_forum.html
	lms/templates/discussion/_inline.html
parents b2ddef99 9a31d7a9
...@@ -15,7 +15,7 @@ from django.core.files.storage import get_storage_class ...@@ -15,7 +15,7 @@ from django.core.files.storage import get_storage_class
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings from django.conf import settings
from django_comment_client.utils import JsonResponse, JsonError from django_comment_client.utils import JsonResponse, JsonError, extract
def thread_author_only(fn): def thread_author_only(fn):
def verified_fn(request, *args, **kwargs): def verified_fn(request, *args, **kwargs):
...@@ -45,8 +45,7 @@ def instructor_only(fn): #TODO add instructor verification ...@@ -45,8 +45,7 @@ def instructor_only(fn): #TODO add instructor verification
return fn(request, *args, **kwargs) return fn(request, *args, **kwargs)
return verified_fn return verified_fn
def extract(dic, keys):
return {k: dic[k] for k in keys}
@login_required @login_required
@require_POST @require_POST
......
...@@ -11,7 +11,7 @@ from courseware.courses import check_course ...@@ -11,7 +11,7 @@ from courseware.courses import check_course
from dateutil.tz import tzlocal from dateutil.tz import tzlocal
from datehelper import time_ago_in_words from datehelper import time_ago_in_words
from django_comment_client.utils import get_categorized_discussion_info from django_comment_client.utils import get_categorized_discussion_info, extract, strip_none
from urllib import urlencode from urllib import urlencode
import json import json
...@@ -39,57 +39,67 @@ def render_accordion(request, course, discussion_id): ...@@ -39,57 +39,67 @@ def render_accordion(request, course, discussion_id):
return render_to_string('discussion/_accordion.html', context) return render_to_string('discussion/_accordion.html', context)
def render_discussion(request, course_id, threads, discussion_id=None, with_search_bar=True, def render_discussion(request, course_id, threads, discussion_id=None, with_search_bar=True, \
search_text='', discussion_type='inline', page=1, num_pages=None, discussion_type='inline', query_params={}):
per_page=THREADS_PER_PAGE):
template = { template = {
'inline': 'discussion/_inline.html', 'inline': 'discussion/_inline.html',
'forum': 'discussion/_forum.html', 'forum': 'discussion/_forum.html',
}[discussion_type] }[discussion_type]
def _url_for_inline_page(page, per_page): base_url = {
raw_url = reverse('django_comment_client.forum.views.inline_discussion', args=[course_id, discussion_id]) 'inline': (lambda: reverse('django_comment_client.forum.views.inline_discussion', args=[course_id, discussion_id])),
return raw_url + '?' + urlencode({'page': page, 'per_page': per_page}) 'forum': (lambda: reverse('django_comment_client.forum.views.forum_form_discussion', args=[course_id, discussion_id])),
}[discussion_type]()
def _url_for_forum_page(page, per_page):
raw_url = reverse('django_comment_client.forum.views.forum_form_discussion', args=[course_id, discussion_id])
return raw_url + '?' + urlencode({'page': page, 'per_page': per_page})
url_for_page = {
'inline': _url_for_inline_page,
'forum': _url_for_forum_page,
}[discussion_type]
context = { context = {
'threads': threads, 'threads': threads,
'discussion_id': discussion_id, 'discussion_id': discussion_id,
'search_bar': '' if not with_search_bar \ 'search_bar': '' if not with_search_bar \
else render_search_bar(request, course_id, discussion_id, text=search_text), else render_search_bar(request, course_id, discussion_id, text=query_params.get('text', '')),
'user_info': comment_client.get_user_info(request.user.id, raw=True), 'user_info': comment_client.get_user_info(request.user.id, raw=True),
'course_id': course_id, 'course_id': course_id,
'request': request, 'request': request,
'page': page,
'per_page': per_page,
'num_pages': num_pages,
'pages_nearby_delta': PAGES_NEARBY_DELTA, 'pages_nearby_delta': PAGES_NEARBY_DELTA,
'discussion_type': discussion_type, 'discussion_type': discussion_type,
'url_for_page': url_for_page, 'base_url': base_url,
'query_params': strip_none(extract(query_params, ['page', 'sort_key', 'sort_order', 'tags', 'text'])),
} }
context = dict(context.items() + query_params.items())
return render_to_string(template, context) return render_to_string(template, context)
def render_inline_discussion(*args, **kwargs): def render_inline_discussion(*args, **kwargs):
return render_discussion(discussion_type='inline', *args, **kwargs) return render_discussion(discussion_type='inline', *args, **kwargs)
def render_forum_discussion(*args, **kwargs): def render_forum_discussion(*args, **kwargs):
return render_discussion(discussion_type='forum', *args, **kwargs) return render_discussion(discussion_type='forum', *args, **kwargs)
def get_threads(request, course_id, discussion_id):
query_params = {
'page': request.GET.get('page', 1),
'per_page': THREADS_PER_PAGE, #TODO maybe change this later
'sort_key': request.GET.get('sort_key', None),
'sort_order': request.GET.get('sort_order', None),
'text': request.GET.get('text', None),
'tags': request.GET.get('tags', None),
}
if query_params['text'] or query_params['tags']: #TODO do tags search without sunspot
query_params['commentable_id'] = discussion_id
threads, page, num_pages = comment_client.search_threads(course_id, recursive=False, query_params=query_params)
else:
threads, page, num_pages = comment_client.get_threads(discussion_id, recursive=False, query_params=query_params)
query_params['page'] = page
query_params['num_pages'] = num_pages
return threads, query_params
# discussion per page is fixed for now # discussion per page is fixed for now
def inline_discussion(request, course_id, discussion_id): def inline_discussion(request, course_id, discussion_id):
page = request.GET.get('page', 1) threads, query_params = get_threads(request, course_id, discussion_id)
threads, page, per_page, num_pages = comment_client.get_threads(discussion_id, recursive=False, page=page, per_page=THREADS_PER_PAGE) html = render_inline_discussion(request, course_id, threads, discussion_id=discussion_id, \
html = render_inline_discussion(request, course_id, threads, discussion_id=discussion_id, num_pages=num_pages, page=page, per_page=per_page) query_params=query_params)
return HtmlResponse(html) return HtmlResponse(html)
def render_search_bar(request, course_id, discussion_id=None, text=''): def render_search_bar(request, course_id, discussion_id=None, text=''):
...@@ -103,38 +113,19 @@ def render_search_bar(request, course_id, discussion_id=None, text=''): ...@@ -103,38 +113,19 @@ def render_search_bar(request, course_id, discussion_id=None, text=''):
return render_to_string('discussion/_search_bar.html', context) return render_to_string('discussion/_search_bar.html', context)
def forum_form_discussion(request, course_id, discussion_id): def forum_form_discussion(request, course_id, discussion_id):
course = check_course(course_id) course = check_course(course_id)
search_text = request.GET.get('text', '') threads, query_params = get_threads(request, course_id, discussion_id)
page = request.GET.get('page', 1) content = render_forum_discussion(request, course_id, threads, discussion_id=discussion_id, \
query_params=query_params)
if len(search_text) > 0:
threads, page, per_page, num_pages = comment_client.search_threads({
'text': search_text,
'commentable_id': discussion_id,
'course_id': course_id,
'page': page,
'per_page': THREADS_PER_PAGE,
})
else:
threads, page, per_page, num_pages = comment_client.get_threads(discussion_id, recursive=False, page=page, per_page=THREADS_PER_PAGE)
context = { context = {
'csrf': csrf(request)['csrf_token'], 'csrf': csrf(request)['csrf_token'],
'course': course, 'course': course,
'content': render_forum_discussion(request, course_id, threads, 'content': content,
discussion_id=discussion_id,
search_text=search_text,
num_pages=num_pages,
per_page=per_page,
page=page),
'accordion': render_accordion(request, course, discussion_id), 'accordion': render_accordion(request, course, discussion_id),
} }
return render_to_response('discussion/index.html', context) return render_to_response('discussion/index.html', context)
def render_single_thread(request, course_id, thread_id): def render_single_thread(request, course_id, thread_id):
def get_annotated_content_info(thread, user_id): def get_annotated_content_info(thread, user_id):
infos = {} infos = {}
def _annotate(content): def _annotate(content):
......
...@@ -13,6 +13,12 @@ import itertools ...@@ -13,6 +13,12 @@ import itertools
_FULLMODULES = None _FULLMODULES = None
_DISCUSSIONINFO = None _DISCUSSIONINFO = None
def extract(dic, keys):
return {k: dic[k] for k in keys}
def strip_none(dic):
return dict([(k, v) for k, v in dic.iteritems() if v is not None])
def get_full_modules(): def get_full_modules():
global _FULLMODULES global _FULLMODULES
if not _FULLMODULES: if not _FULLMODULES:
......
...@@ -15,9 +15,19 @@ class CommentClientUnknownError(CommentClientError): ...@@ -15,9 +15,19 @@ class CommentClientUnknownError(CommentClientError):
def delete_threads(commentable_id, *args, **kwargs): def delete_threads(commentable_id, *args, **kwargs):
return _perform_request('delete', _url_for_commentable_threads(commentable_id), *args, **kwargs) return _perform_request('delete', _url_for_commentable_threads(commentable_id), *args, **kwargs)
def get_threads(commentable_id, recursive=False, page=1, per_page=20, *args, **kwargs): def get_threads(commentable_id, recursive=False, query_params={}, *args, **kwargs):
response = _perform_request('get', _url_for_threads(commentable_id), {'recursive': recursive, 'page': page, 'per_page': per_page}, *args, **kwargs) default_params = {'page': 1, 'per_page': 20}
return response['collection'], response['page'], response['per_page'], response['num_pages'] attributes = dict(default_params.items() + query_params.items())
response = _perform_request('get', _url_for_threads(commentable_id), \
attributes, *args, **kwargs)
return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1)
def search_threads(course_id, recursive=False, query_params={}, *args, **kwargs):
default_params = {'page': 1, 'per_page': 20, 'course_id': course_id}
attributes = dict(default_params.items() + query_params.items())
response = _perform_request('get', _url_for_search_threads(), \
attributes, *args, **kwargs)
return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1)
def get_threads_tags(*args, **kwargs): def get_threads_tags(*args, **kwargs):
return _perform_request('get', _url_for_threads_tags(), {}, *args, **kwargs) return _perform_request('get', _url_for_threads_tags(), {}, *args, **kwargs)
...@@ -98,10 +108,7 @@ def unsubscribe_thread(user_id, thread_id, *args, **kwargs): ...@@ -98,10 +108,7 @@ def unsubscribe_thread(user_id, thread_id, *args, **kwargs):
def unsubscribe_commentable(user_id, commentable_id, *args, **kwargs): def unsubscribe_commentable(user_id, commentable_id, *args, **kwargs):
return unsubscribe(user_id, {'source_type': 'other', 'source_id': commentable_id}) return unsubscribe(user_id, {'source_type': 'other', 'source_id': commentable_id})
def search_threads(attributes, *args, **kwargs):
default_attributes = {'page': 1, 'per_page': 20}
attributes = dict(default_attributes.items() + attributes.items())
return _perform_request('get', _url_for_search_threads(), attributes, *args, **kwargs)
def _perform_request(method, url, data_or_params=None, *args, **kwargs): def _perform_request(method, url, data_or_params=None, *args, **kwargs):
if method in ['post', 'put', 'patch']: if method in ['post', 'put', 'patch']:
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
<div class="discussion-new-post control-button" href="javascript:void(0)">New Post</div> <div class="discussion-new-post control-button" href="javascript:void(0)">New Post</div>
</div> </div>
<%include file="_sort.html" />
% for thread in threads: % for thread in threads:
${renderer.render_thread(course_id, thread, edit_thread=False, show_comments=False)} ${renderer.render_thread(course_id, thread, edit_thread=False, show_comments=False)}
% endfor % endfor
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
</div> </div>
<div class="discussion-new-post control-button" href="javascript:void(0)">New Post</div> <div class="discussion-new-post control-button" href="javascript:void(0)">New Post</div>
</div> </div>
<%include file="_sort.html" />
% for thread in threads: % for thread in threads:
${renderer.render_thread(course_id, thread, edit_thread=False, show_comments=False)} ${renderer.render_thread(course_id, thread, edit_thread=False, show_comments=False)}
% endfor % endfor
......
<%! from urllib import urlencode %>
<%
def merge(dic1, dic2):
return dict(dic1.items() + dic2.items())
def url_for_page(_page):
return base_url + '?' + urlencode(merge(query_params, {'page': _page}))
%>
<%def name="link_to_page(_page)"> <%def name="link_to_page(_page)">
% if _page != page: % if _page != page:
<div class="page-link"> <div class="page-link">
<a href="${url_for_page(_page, per_page)}">${_page}</a> <a href="${url_for_page(_page)}">${_page}</a>
</div> </div>
% else: % else:
<div class="page-link">${_page}</div> <div class="page-link">${_page}</div>
...@@ -25,7 +36,7 @@ ...@@ -25,7 +36,7 @@
<div class="discussion-${discussion_type}-paginator discussion-paginator"> <div class="discussion-${discussion_type}-paginator discussion-paginator">
<div class="prev-page"> <div class="prev-page">
% if page > 1: % if page > 1:
<a href="${url_for_page(page - 1, per_page)}">&lt; Previous page</a> <a href="${url_for_page(page - 1)}">&lt; Previous page</a>
% else: % else:
&lt; Previous page &lt; Previous page
% endif % endif
...@@ -44,7 +55,7 @@ ...@@ -44,7 +55,7 @@
% endif % endif
<div class="next-page"> <div class="next-page">
% if page < num_pages: % if page < num_pages:
<a href="${url_for_page(page + 1, per_page)}">Next page &gt;</a> <a href="${url_for_page(page + 1)}">Next page &gt;</a>
% else: % else:
Next page &gt; Next page &gt;
% endif % endif
......
<%! from urllib import urlencode %>
<%def name="link_to_sort(key, title)">
% if key == sort_key:
% if sort_order.lower() == 'desc':
${_link_to_sort(key, 'asc', title + ' (desc)')}
% else:
${_link_to_sort(key, 'desc', title + '(asc)')}
% endif
% else:
${_link_to_sort(key, 'desc', title)}
% endif
</%def>
<%def name="_link_to_sort(key, order, title)">
<%
def merge(dic1, dic2):
return dict(dic1.items() + dic2.items())
def url_for_sort(key, order):
return base_url + '?' + urlencode(merge(query_params, {'page': 1, 'sort_key': key, 'sort_order': order}))
%>
<a href="${url_for_sort(key, order)}">${title}</a>
</%def>
<div class="discussion-sort">
Sort by:
${link_to_sort('date', 'Date')}
${link_to_sort('votes', 'Votes')}
${link_to_sort('comments', 'Comments')}
</div>
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