Commit fdab215e by Rocky Duan

moved django_comment_client into edx

parent 616eaf25
/Users/dementrock/coding/cs_comments_client_python/djangoapp
\ No newline at end of file
from django.conf.urls.defaults import url, patterns
import django_comment_client.base.views
urlpatterns = patterns('django_comment_client.base.views',
url(r'(?P<commentable_id>[\w\-]+)/threads/create$', 'create_thread', name='create_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/update$', 'update_thread', name='update_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/reply$', 'create_comment', name='create_comment'),
url(r'threads/(?P<thread_id>[\w\-]+)/delete', 'delete_thread', name='delete_thread'),
url(r'comments/(?P<comment_id>[\w\-]+)/update$', 'update_comment', name='update_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/endorse$', 'endorse_comment', name='endorse_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/reply$', 'create_sub_comment', name='create_sub_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/delete$', 'delete_comment', name='delete_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/upvote$', 'vote_for_comment', {'value': 'up'}, name='upvote_comment'),
url(r'comments/(?P<comment_id>[\w\-]+)/downvote$', 'vote_for_comment', {'value': 'down'}, name='downvote_comment'),
url(r'threads/(?P<thread_id>[\w\-]+)/upvote$', 'vote_for_thread', {'value': 'up'}, name='upvote_thread'),
url(r'threads/(?P<thread_id>[\w\-]+)/downvote$', 'vote_for_thread', {'value': 'down'}, name='downvote_thread'),
)
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST, require_GET
from django.http import HttpResponse
from django.utils import simplejson
import comment_client
class JsonResponse(HttpResponse):
def __init__(self, data=None):
content = simplejson.dumps(data,
indent=2,
ensure_ascii=False)
super(JsonResponse, self).__init__(content,
mimetype='application/json; charset=utf8')
class JsonError(HttpResponse):
def __init__(self, status, error_message=""):
content = simplejson.dumps({'errors': error_message},
indent=2,
ensure_ascii=False)
super(JsonError, self).__init__(content,
status=status,
mimetype='application/json; charset=utf8')
def thread_author_only(fn):
def verified_fn(request, *args, **kwargs):
thread_id = args.get('thread_id', False) or \
kwargs.get('thread_id', False)
thread = comment_client.get_thread(thread_id)
if request.user.id == thread['user_id']:
return fn(request, *args, **kwargs)
else:
return JsonError(400, "unauthorized")
return verified_fn
def comment_author_only(fn):
def verified_fn(request, *args, **kwargs):
comment_id = args.get('comment_id', False) or \
kwargs.get('comment_id', False)
comment = comment_client.get_comment(comment_id)
if request.user.id == comment['user_id']:
return fn(request, *args, **kwargs)
else:
return JsonError(400, "unauthorized")
return verified_fn
def instructor_only(fn): #TODO add instructor verification
return fn
def extract(dic, keys):
return {k: dic[k] for k in keys}
@login_required
@require_POST
def create_thread(request, 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
response = comment_client.create_thread(commentable_id, attributes)
return JsonResponse(response)
@thread_author_only
@login_required
@require_POST
def update_thread(request, 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):
attributes = extract(request.POST, ['body'])
attributes['user_id'] = request.user.id
attributes['course_id'] = "1" # TODO either remove this or pass this parameter somehow
response = comment_client.create_comment(thread_id, attributes)
return JsonResponse(response)
@thread_author_only
@login_required
@require_POST
def delete_thread(request, 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):
attributes = extract(request.POST, ['body'])
response = comment_client.update_comment(comment_id, attributes)
return JsonResponse(response)
@instructor_only
@login_required
@require_POST
def endorse_comment(request, 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):
attributes = extract(request.POST, ['body'])
attributes['user_id'] = request.user.id
attributes['course_id'] = "1" # TODO either remove this or pass this parameter somehow
response = comment_client.create_sub_comment(comment_id, attributes)
return JsonResponse(response)
@comment_author_only
@login_required
@require_POST
def delete_comment(request, comment_id):
response = comment_client.delete_comment(comment_id)
return JsonResponse(response)
@login_required
@require_POST
def vote_for_comment(request, 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):
user_id = request.user.id
response = comment_client.vote_for_thread(thread_id, user_id, value)
return JsonResponse(response)
#undo vote: disabled for now
@login_required
@require_GET
def search(request):
text = request.GET.get('text', None)
commentable_id = request.GET.get('commentable_id', None)
response = comment_client.search(text, commentable_id)
return JsonResponse(response)
from django.conf.urls.defaults import url, patterns
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'),
)
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
from django.http import HttpResponse
from django.utils import simplejson
from django.core.context_processors import csrf
from mitxmako.shortcuts import render_to_response, render_to_string
from courseware.courses import check_course
from courseware.models import StudentModuleCache
from courseware.module_render import get_module, get_section
from xmodule.modulestore import Location
from xmodule.modulestore.django import modulestore
from importlib import import_module
from django.conf import settings
import comment_client
import dateutil
from dateutil.tz import tzlocal
from datehelper import time_ago_in_words
import operator
import itertools
_FULLMODULES = None
_DISCUSSIONINFO = None
def get_full_modules():
global _FULLMODULES
if not _FULLMODULES:
class_path = settings.MODULESTORE['default']['ENGINE']
module_path, _, class_name = class_path.rpartition('.')
class_ = getattr(import_module(module_path), class_name)
modulestore = class_(eager=True, **settings.MODULESTORE['default']['OPTIONS'])
_FULLMODULES = modulestore.modules
return _FULLMODULES
def get_categorized_discussion_info(request, user, course, course_name, url_course_id):
"""
return a dict of the form {category: modules}
"""
global _DISCUSSIONINFO
if not _DISCUSSIONINFO:
_is_course_discussion = lambda x: x[0].dict()['category'] == 'discussion' \
and x[0].dict()['course'] == course_name
_get_module_descriptor = operator.itemgetter(1)
def _get_module(module_descriptor):
print module_descriptor
module = get_module(user, request, module_descriptor.location, student_module_cache)[0]
return module
def _extract_info(module):
return {
'title': module.title,
'discussion_id': module.discussion_id,
'category': module.category,
}
discussion_module_descriptors = map(_get_module_descriptor,
filter(_is_course_discussion,
get_full_modules().items()))
student_module_cache = StudentModuleCache(user, course)
discussion_info = map(_extract_info, map(_get_module, discussion_module_descriptors))
_DISCUSSIONINFO = dict((category, list(l)) \
for category, l in itertools.groupby(discussion_info, operator.itemgetter('category')))
_DISCUSSIONINFO['General'] = [{
'title': 'General discussion',
'discussion_id': url_course_id,
'category': 'General',
}]
return _DISCUSSIONINFO
def render_accordion(request, course, discussion_info, discussion_id):
context = dict([
('course', course),
('discussion_info', discussion_info),
('active', discussion_id), # TODO change this later
('csrf', csrf(request)['csrf_token'])])
return render_to_string('discussion/accordion.html', context)
def render_discussion(request, threads, discussion_id=None, search_text=''):
context = {
'threads': threads,
'time_ago_in_words': time_ago_in_words,
'parse': dateutil.parser.parse,
'discussion_id': discussion_id,
'search_bar': render_search_bar(request, discussion_id, text=search_text),
}
return render_to_string('discussion/inline.html', context)
def render_search_bar(request, discussion_id=None, text=''):
if not discussion_id:
return ''
context = {
'discussion_id': discussion_id,
'text': text,
}
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('/')
url_course_id = course_id.replace('/', '_').replace('.', '_')
discussion_info = get_categorized_discussion_info(request, request.user, course, course_name, url_course_id)
search_text = request.GET.get('text', '')
if len(search_text) > 0:
threads = comment_client.search(search_text, discussion_id)
else:
threads = comment_client.get_threads(discussion_id, recursive=False)
context = {
'csrf': csrf(request)['csrf_token'],
'COURSE_TITLE': course.title,
'course': course,
'init': '',
'content': render_discussion(request, 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):
context = {
'thread': comment_client.get_thread(thread_id, recursive=True),
'time_ago_in_words': time_ago_in_words,
'parse': dateutil.parser.parse,
}
return render_to_string('discussion/single_thread.html', context)
def single_thread(request, thread_id):
context = {
'csrf': csrf(request)['csrf_token'],
'init': '',
'content': render_single_thread(request, thread_id),
'accordion': '',
}
return render_to_response('discussion/index.html', context)
def search(request):
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),
'accordion': '',
}
return render_to_response('discussion/index.html', context)
from django.conf.urls.defaults import url, patterns, include
urlpatterns = patterns('',
url(r'forum/', include('django_comment_client.forum.urls')),
url(r'', include('django_comment_client.base.urls')),
)
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