diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index f273778a3c..4d0e5867da 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -4,6 +4,8 @@ import logging import urllib import itertools +from functools import partial + from django.conf import settings from django.core.context_processors import csrf from django.core.urlresolvers import reverse @@ -20,6 +22,7 @@ from module_render import toc_for_course, get_module, get_section from models import StudentModuleCache from student.models import UserProfile from multicourse import multicourse_settings +from django_comment_client.utils import get_discussion_title from util.cache import cache, cache_if_anonymous from student.models import UserTestGroup, CourseEnrollment @@ -27,6 +30,11 @@ from courseware import grades from courseware.courses import check_course from xmodule.modulestore.django import modulestore +import comment_client + + + + log = logging.getLogger("mitx.courseware") template_imports = {'urllib': urllib} @@ -259,7 +267,6 @@ def course_info(request, course_id): return render_to_response('info.html', {'course': course}) - @ensure_csrf_cookie @cache_if_anonymous def course_about(request, course_id): @@ -287,3 +294,24 @@ def university_profile(request, org_id): template_file = "university_profile/{0}.html".format(org_id).lower() return render_to_response(template_file, context) + +def render_notifications(request, course, notifications): + context = { + 'notifications': notifications, + 'get_discussion_title': partial(get_discussion_title, request=request, course=course), + 'course': course, + } + return render_to_string('notifications.html', context) + +@login_required +def news(request, course_id): + course = check_course(course_id) + + notifications = comment_client.get_notifications(request.user.id) + + context = { + 'course': course, + 'content': render_notifications(request, course, notifications), + } + + return render_to_response('news.html', context) diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index a148d80020..85e76bad55 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -71,8 +71,11 @@ def update_thread(request, course_id, thread_id): @require_POST def create_comment(request, course_id, thread_id): attributes = extract(request.POST, ['body']) - attributes['user_id'] = request.user.id + if request.POST.get('anonymous', 'false').lower() == 'false': + attributes['user_id'] = request.user.id attributes['course_id'] = course_id + attributes['auto_subscribe'] = bool(request.POST.get('autowatch', False)) + print attributes response = comment_client.create_comment(thread_id, attributes) return JsonResponse(response) @@ -103,8 +106,10 @@ def endorse_comment(request, course_id, comment_id): @require_POST 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 + if request.POST.get('anonymous', 'false').lower() == 'false': + attributes['user_id'] = request.user.id + attributes['course_id'] = course_id + attributes['auto_subscribe'] = bool(request.POST.get('autowatch', False)) response = comment_client.create_sub_comment(comment_id, attributes) return JsonResponse(response) diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index c2a136d6cf..bde1ed7f51 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -6,80 +6,16 @@ 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 +from django_comment_client.utils import get_categorized_discussion_info + import json -_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.discussion_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 = { 'course': course, @@ -118,7 +54,7 @@ def forum_form_discussion(request, course_id, discussion_id): url_course_id = course_id.replace('/', '_').replace('.', '_') - discussion_info = get_categorized_discussion_info(request, request.user, course, course_name, url_course_id) + discussion_info = get_categorized_discussion_info(request, course)#request.user, course, course_name, url_course_id) search_text = request.GET.get('text', '') diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py new file mode 100644 index 0000000000..24f4f5115a --- /dev/null +++ b/lms/djangoapps/django_comment_client/utils.py @@ -0,0 +1,93 @@ +from importlib import import_module +from courseware.models import StudentModuleCache +from courseware.module_render import get_module +from xmodule.modulestore import Location +from xmodule.modulestore.django import modulestore + +from django.conf import settings +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, course): + """ + return a dict of the form {category: modules} + """ + global _DISCUSSIONINFO + if not _DISCUSSIONINFO: + initialize_discussion_info(request, course) + return _DISCUSSIONINFO['categorized'] + +def get_discussion_title(request, course, discussion_id): + global _DISCUSSIONINFO + if not _DISCUSSIONINFO: + initialize_discussion_info(request, course) + title = _DISCUSSIONINFO['by_id'].get(discussion_id, {}).get('title', '(no title)') + if title == '(no title)': + print "title shouldn't be none" + import pdb; pdb.set_trace() + return title + +def initialize_discussion_info(request, course): + + global _DISCUSSIONINFO + if _DISCUSSIONINFO: + return + + course_id = course.id + _, course_name, _ = course_id.split('/') + user = request.user + url_course_id = course_id.replace('/', '_').replace('.', '_') + + _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.discussion_category, + } + + def _pack_with_id(info): + return (info['discussion_id'], info) + + 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 = {} + + _DISCUSSIONINFO['by_id'] = dict(map(_pack_with_id, discussion_info)) + + _DISCUSSIONINFO['categorized'] = dict((category, list(l)) \ + for category, l in itertools.groupby(discussion_info, operator.itemgetter('category'))) + + _DISCUSSIONINFO['categorized']['General'] = [{ + 'title': 'General discussion', + 'discussion_id': url_course_id, + 'category': 'General', + }] diff --git a/lms/static/coffee/src/discussion.coffee b/lms/static/coffee/src/discussion.coffee index 44aebb7241..51420f38cc 100644 --- a/lms/static/coffee/src/discussion.coffee +++ b/lms/static/coffee/src/discussion.coffee @@ -122,6 +122,8 @@ Discussion = $discussionContent = $content.children(".discussion-content") $local = generateLocal($discussionContent) + id = $content.attr("_id") + discussionContentHoverIn = -> status = $discussionContent.attr("status") || "normal" if status == "normal" @@ -138,15 +140,32 @@ Discussion = $discussionContent.hover(discussionContentHoverIn, discussionContentHoverOut) - - handleReply = (elem) -> editView = $local(".discussion-content-edit") if editView.length editView.show() else editView = $("