def user_profile(request, course_id, user_id): nr_transaction = newrelic.agent.current_transaction() #TODO: Allow sorting? course = get_course_with_access(request.user, course_id, 'load_forum') try: profiled_user = cc.User(id=user_id, course_id=course_id) query_params = { 'page': request.GET.get('page', 1), 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities } threads, page, num_pages = profiled_user.active_threads(query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': map(utils.safe_content, threads), 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), }) else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': saxutils.escape(json.dumps(threads), escapedict), 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def user_profile(request, course_key, user_id): """ Renders a response to display the user profile page (shown after clicking on a post author's username). """ nr_transaction = newrelic.agent.current_transaction() #TODO: Allow sorting? course = get_course_with_access(request.user, 'load_forum', course_key) try: query_params = { 'page': request.GET.get('page', 1), 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities } try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseBadRequest("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id profiled_user = cc.User(id=user_id, course_id=course_key, group_id=group_id) else: profiled_user = cc.User(id=user_id, course_id=course_key) threads, page, num_pages = profiled_user.active_threads(query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info) is_staff = cached_has_permission(request.user, 'openclose_thread', course.id) threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads] if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': threads, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'annotated_content_info': _attr_safe_json(annotated_content_info), }) else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': _attr_safe_json(threads), 'user_info': _attr_safe_json(user_info), 'annotated_content_info': _attr_safe_json(annotated_content_info), 'page': query_params['page'], 'num_pages': query_params['num_pages'], } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def followed_threads(request, course_id, user_id): course = get_course_with_access(request.user, course_id, 'load') try: profiled_user = cc.User(id=user_id, course_id=course_id) query_params = { 'page': request.GET.get('page', 1), 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': request.GET.get('sort_key', 'date'), 'sort_order': request.GET.get('sort_order', 'desc'), } threads, page, num_pages = profiled_user.subscribed_threads( query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) if request.is_ajax(): return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': map(utils.safe_content, threads), 'page': query_params['page'], 'num_pages': query_params['num_pages'], }) else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': saxutils.escape(json.dumps(threads), escapedict), 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), # 'content': content, } return render_to_response('discussion/user_profile.html', context) except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError, User.DoesNotExist): raise Http404
def inline_discussion(request, course_id, discussion_id): """ Renders JSON for DiscussionModules """ course = get_course_with_access(request.user, course_id, 'load_forum') try: threads, query_params = get_threads(request, course_id, discussion_id, per_page=INLINE_THREADS_PER_PAGE) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError): # TODO (vshnayder): since none of this code seems to be aware of the fact that # sometimes things go wrong, I suspect that the js client is also not # checking for errors on request. Check and fix as needed. log.error("Error loading inline discussion threads.") raise Http404 annotated_content_info = utils.get_metadata_for_threads(course_id, threads, request.user, user_info) allow_anonymous = course.allow_anonymous allow_anonymous_to_peers = course.allow_anonymous_to_peers #since inline is all one commentable, only show or allow the choice of cohorts #if the commentable is cohorted, otherwise everything is not cohorted #and no one has the option of choosing a cohort is_cohorted = is_course_cohorted(course_id) and is_commentable_cohorted(course_id, discussion_id) is_moderator = cached_has_permission(request.user, "see_all_cohorts", course_id) cohorts_list = list() if is_cohorted: cohorts_list.append({'name': 'All Groups', 'id': None}) #if you're a mod, send all cohorts and let you pick if is_moderator: cohorts = get_course_cohorts(course_id) for cohort in cohorts: cohorts_list.append({'name': cohort.name, 'id': cohort.id}) else: #students don't get to choose cohorts_list = None return utils.JsonResponse({ 'discussion_data': map(utils.safe_content, threads), 'user_info': user_info, 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'roles': utils.get_role_ids(course_id), 'allow_anonymous_to_peers': allow_anonymous_to_peers, 'allow_anonymous': allow_anonymous, 'cohorts': cohorts_list, 'is_moderator': is_moderator, 'is_cohorted': is_cohorted })
def forum_form_discussion(request, course_key): """ Renders the main Discussion page, potentially filtered by a search query """ course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) request.user.is_community_ta = utils.is_user_community_ta( request.user, course.id) if request.is_ajax(): user = cc.User.from_django_user(request.user) user_info = user.to_dict() try: unsafethreads, query_params = get_threads( request, course, user_info) # This might process a search query is_staff = has_permission(request.user, 'openclose_thread', course.id) threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in unsafethreads ] except cc.utils.CommentClientMaintenanceError: return HttpResponseServerError( 'Forum is in maintenance mode', status=status.HTTP_503_SERVICE_UNAVAILABLE) except ValueError: return HttpResponseServerError("Invalid group_id") with function_trace("get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) with function_trace("add_courseware_context"): add_courseware_context(threads, course, request.user) return utils.JsonResponse({ 'discussion_data': add_user_fullname_in_threads( threads ), # TODO: Standardize on 'discussion_data' vs 'threads' 'annotated_content_info': annotated_content_info, 'num_pages': query_params['num_pages'], 'page': query_params['page'], 'corrected_text': query_params['corrected_text'], }) else: course_id = unicode(course.id) tab_view = CourseTabView() return tab_view.get(request, course_id, 'discussion')
def inline_discussion(request, course_id, discussion_id): """ Renders JSON for DiscussionModules """ nr_transaction = newrelic.agent.current_transaction() course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id) course = get_course_with_access(request.user, 'load_forum', course_id) threads, query_params = get_threads(request, course_id, discussion_id, per_page=INLINE_THREADS_PER_PAGE) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads(course_id, threads, request.user, user_info) allow_anonymous = course.allow_anonymous allow_anonymous_to_peers = course.allow_anonymous_to_peers #since inline is all one commentable, only show or allow the choice of cohorts #if the commentable is cohorted, otherwise everything is not cohorted #and no one has the option of choosing a cohort is_cohorted = is_course_cohorted(course_id) and is_commentable_cohorted(course_id, discussion_id) is_moderator = cached_has_permission(request.user, "see_all_cohorts", course_id) cohorts_list = list() if is_cohorted: cohorts_list.append({'name': _('All Groups'), 'id': None}) #if you're a mod, send all cohorts and let you pick if is_moderator: cohorts = get_course_cohorts(course_id) for cohort in cohorts: cohorts_list.append({'name': cohort.name, 'id': cohort.id}) else: #students don't get to choose cohorts_list = None return utils.JsonResponse({ 'discussion_data': map(utils.safe_content, threads), 'user_info': user_info, 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'roles': utils.get_role_ids(course_id), 'allow_anonymous_to_peers': allow_anonymous_to_peers, 'allow_anonymous': allow_anonymous, 'cohorts': cohorts_list, 'is_moderator': is_moderator, 'is_cohorted': is_cohorted })
def inline_discussion(request, course_key, discussion_id): """ Renders JSON for DiscussionModules """ course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() try: threads, query_params = get_threads(request, course, user_info, discussion_id, per_page=INLINE_THREADS_PER_PAGE) except ValueError: return HttpResponseServerError("Invalid group_id") with function_trace("get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) is_staff = has_permission(request.user, 'openclose_thread', course.id) threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ] with function_trace("add_courseware_context"): add_courseware_context(threads, course, request.user) course_discussion_settings = get_course_discussion_settings(course.id) return utils.JsonResponse({ 'is_commentable_divided': is_commentable_divided(course_key, discussion_id), 'discussion_data': threads, 'user_info': user_info, 'user_group_id': get_group_id_for_user(request.user, course_discussion_settings), 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'roles': utils.get_role_ids(course_key), 'course_settings': make_course_settings(course, request.user) })
def single_thread(request, course_key, discussion_id, thread_id): """ Renders a response to display a single discussion thread. This could either be a page refresh after navigating to a single thread, a direct link to a single thread, or an AJAX call from the discussions UI loading the responses/comments for a single thread. Depending on the HTTP headers, we'll adjust our response accordingly. """ course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) request.user.is_community_ta = utils.is_user_community_ta( request.user, course.id) if request.is_ajax(): cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() is_staff = has_permission(request.user, 'openclose_thread', course.id) thread = _load_thread_for_viewing( request, course, discussion_id=discussion_id, thread_id=thread_id, raise_event=True, ) with function_trace("get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_key, thread, request.user, user_info=user_info) content = utils.prepare_content(thread.to_dict(), course_key, is_staff) with function_trace("add_courseware_context"): add_courseware_context([content], course, request.user) # [COLARAZ_CUSTOM] content = add_user_fullname_in_threads(content) if len(content) == 1: content = content[0] return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: course_id = unicode(course.id) tab_view = CourseTabView() return tab_view.get(request, course_id, 'discussion', discussion_id=discussion_id, thread_id=thread_id)
def single_thread(request, course_key, discussion_id, thread_id): """ Renders a response to display a single discussion thread. This could either be a page refresh after navigating to a single thread, a direct link to a single thread, or an AJAX call from the discussions UI loading the responses/comments for a single thread. Depending on the HTTP headers, we'll adjust our response accordingly. """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) if request.is_ajax(): cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() is_staff = has_permission(request.user, 'openclose_thread', course.id) thread = _find_thread(request, course, discussion_id=discussion_id, thread_id=thread_id) if not thread: raise Http404 with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_key, thread, request.user, user_info=user_info) content = utils.prepare_content(thread.to_dict(), course_key, is_staff) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context([content], course, request.user) return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: course_id = unicode(course.id) tab_view = CourseTabView() return tab_view.get(request, course_id, 'discussion', discussion_id=discussion_id, thread_id=thread_id)
def inline_discussion(request, course_key, discussion_id): """ Renders JSON for DiscussionModules """ with function_trace('get_course_and_user_info'): course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() try: with function_trace('get_threads'): threads, query_params = get_threads( request, course, user_info, discussion_id, per_page=INLINE_THREADS_PER_PAGE ) except ValueError: return HttpResponseServerError('Invalid group_id') with function_trace('get_metadata_for_threads'): annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info) with function_trace('determine_group_permissions'): is_staff = has_permission(request.user, 'openclose_thread', course.id) course_discussion_settings = get_course_discussion_settings(course.id) group_names_by_id = get_group_names_by_id(course_discussion_settings) course_is_divided = course_discussion_settings.division_scheme is not CourseDiscussionSettings.NONE with function_trace('prepare_content'): threads = [ utils.prepare_content( thread, course_key, is_staff, course_is_divided, group_names_by_id ) for thread in threads ] return utils.JsonResponse({ 'is_commentable_divided': is_commentable_divided(course_key, discussion_id), 'discussion_data': threads, 'user_info': user_info, 'user_group_id': get_group_id_for_user(request.user, course_discussion_settings), 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'roles': utils.get_role_ids(course_key), 'course_settings': make_course_settings(course, request.user, False) })
def inline_discussion(request, course_key, discussion_id): """ Renders JSON for DiscussionModules """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load_forum', course_key) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() try: threads, query_params = get_threads(request, course, discussion_id, per_page=INLINE_THREADS_PER_PAGE) except ValueError: return HttpResponseBadRequest("Invalid group_id") with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) is_staff = cached_has_permission(request.user, 'openclose_thread', course.id) threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ] with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course, request.user) return utils.JsonResponse({ 'is_commentable_cohorted': is_commentable_cohorted(course_key, discussion_id), 'discussion_data': threads, 'user_info': user_info, 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'roles': utils.get_role_ids(course_key), 'course_settings': make_course_settings(course, request.user) })
def user_profile(request, course_id, user_id): course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id) nr_transaction = newrelic.agent.current_transaction() #TODO: Allow sorting? course = get_course_with_access(request.user, 'load_forum', course_id) try: profiled_user = cc.User(id=user_id, course_id=course_id) query_params = { 'page': request.GET.get('page', 1), 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities } threads, page, num_pages = profiled_user.active_threads(query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads(course_id, threads, request.user, user_info) if request.is_ajax(): is_staff = cached_has_permission(request.user, 'openclose_thread', course.id) return utils.JsonResponse({ 'discussion_data': [utils.safe_content(thread, is_staff) for thread in threads], 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'annotated_content_info': _attr_safe_json(annotated_content_info), }) else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': _attr_safe_json(threads), 'user_info': _attr_safe_json(user_info), 'annotated_content_info': _attr_safe_json(annotated_content_info), 'page': query_params['page'], 'num_pages': query_params['num_pages'], # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def user_profile(request, course_key, user_id): """ Renders a response to display the user profile page (shown after clicking on a post author's username). """ try: context = create_user_profile_context(request, course_key, user_id) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': context['threads'], 'page': context['page'], 'num_pages': context['num_pages'], 'annotated_content_info': context['annotated_content_info'], }) else: tab_view = CourseTabView() return tab_view.get(request, unicode(course_key), 'discussion', profile_page_context=context) except User.DoesNotExist: raise Http404 except ValueError: return HttpResponseServerError("Invalid group_id")
def single_thread(request, course_key, discussion_id, thread_id): """ Renders a response to display a single discussion thread. """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_settings = make_course_settings(course, request.user) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() is_moderator = has_permission(request.user, "see_all_cohorts", course_key) # Verify that the student has access to this thread if belongs to a discussion module if discussion_id not in utils.get_discussion_categories_ids( course, request.user): raise Http404 # Currently, the front end always loads responses via AJAX, even for this # page; it would be a nice optimization to avoid that extra round trip to # the comments service. try: thread = cc.Thread.find(thread_id).retrieve( recursive=request.is_ajax(), user_id=request.user.id, response_skip=request.GET.get("resp_skip"), response_limit=request.GET.get("resp_limit")) except cc.utils.CommentClientRequestError as e: if e.status_code == 404: raise Http404 raise # verify that the thread belongs to the requesting student's cohort if is_commentable_cohorted(course_key, discussion_id) and not is_moderator: user_group_id = get_cohort_id(request.user, course_key) if getattr(thread, "group_id", None) is not None and user_group_id != thread.group_id: raise Http404 is_staff = has_permission(request.user, 'openclose_thread', course.id) if request.is_ajax(): with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_key, thread, request.user, user_info=user_info) content = utils.prepare_content(thread.to_dict(), course_key, is_staff) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context([content], course, request.user) return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: try: threads, query_params = get_threads(request, course) except ValueError: return HttpResponseBadRequest("Invalid group_id") threads.append(thread.to_dict()) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course, request.user) for thread in threads: # patch for backward compatibility with comments service if "pinned" not in thread: thread["pinned"] = False threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ] with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): user_cohort = get_cohort_id(request.user, course_key) context = { 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], 'init': '', # TODO: What is this? 'user_info': _attr_safe_json(user_info), 'annotated_content_info': _attr_safe_json(annotated_content_info), 'course': course, #'recent_active_threads': recent_active_threads, 'course_id': course.id.to_deprecated_string( ), # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, 'threads': _attr_safe_json(threads), 'roles': _attr_safe_json(utils.get_role_ids(course_key)), 'is_moderator': is_moderator, 'thread_pages': query_params['num_pages'], 'is_course_cohorted': is_course_cohorted(course_key), 'flag_moderator': (has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, 'staff', course)), 'cohorts': course_settings["cohorts"], 'user_cohort': user_cohort, 'sort_preference': cc_user.default_sort_key, 'category_map': course_settings["category_map"], 'course_settings': _attr_safe_json(course_settings) } return render_to_response('discussion/index.html', context)
def forum_form_discussion(request, course_id): """ Renders the main Discussion page, potentially filtered by a search query """ course = get_course_with_access(request.user, course_id, 'load') category_map = utils.get_discussion_category_map(course) try: unsafethreads, query_params = get_threads( request, course_id) # This might process a search query threads = [utils.safe_content(thread) for thread in unsafethreads] except cc.utils.CommentClientMaintenanceError: log.warning("Forum is in maintenance mode") return render_to_response('discussion/maintenance.html', {}) except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError) as err: log.error("Error loading forum discussion threads: %s", str(err)) raise Http404 user = cc.User.from_django_user(request.user) user_info = user.to_dict() annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) for thread in threads: courseware_context = get_courseware_context(thread, course) if courseware_context: thread.update(courseware_context) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': threads, # TODO: Standardize on 'discussion_data' vs 'threads' 'annotated_content_info': annotated_content_info, 'num_pages': query_params['num_pages'], 'page': query_params['page'], }) else: #recent_active_threads = cc.search_recent_active_threads( # course_id, # recursive=False, # query_params={'follower_id': request.user.id}, #) #trending_tags = cc.search_trending_tags( # course_id, #) cohorts = get_course_cohorts(course_id) cohorted_commentables = get_cohorted_commentables(course_id) user_cohort_id = get_cohort_id(request.user, course_id) context = { 'csrf': csrf(request)['csrf_token'], 'course': course, #'recent_active_threads': recent_active_threads, #'trending_tags': trending_tags, 'staff_access': has_access(request.user, course, 'staff'), 'threads': saxutils.escape(json.dumps(threads), escapedict), 'thread_pages': query_params['num_pages'], 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'flag_moderator': cached_has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, course, 'staff'), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course_id': course.id, 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), 'is_moderator': cached_has_permission(request.user, "see_all_cohorts", course_id), 'cohorts': cohorts, 'user_cohort': user_cohort_id, 'cohorted_commentables': cohorted_commentables, 'is_course_cohorted': is_course_cohorted(course_id) } # print "start rendering.." return render_to_response('discussion/index.html', context)
def _test_unicode_data(self, text): response = utils.JsonResponse(text) reparsed = json.loads(response.content) self.assertEqual(reparsed, text)
def forum_form_discussion(request, course_key): """ Renders the main Discussion page, potentially filtered by a search query """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_settings = make_course_settings(course, request.user) user = cc.User.from_django_user(request.user) user_info = user.to_dict() try: unsafethreads, query_params = get_threads( request, course) # This might process a search query is_staff = has_permission(request.user, 'openclose_thread', course.id) threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in unsafethreads ] except cc.utils.CommentClientMaintenanceError: log.warning("Forum is in maintenance mode") return render_to_response('discussion/maintenance.html', {}) except ValueError: return HttpResponseBadRequest("Invalid group_id") with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course, request.user) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': threads, # TODO: Standardize on 'discussion_data' vs 'threads' 'annotated_content_info': annotated_content_info, 'num_pages': query_params['num_pages'], 'page': query_params['page'], 'corrected_text': query_params['corrected_text'], }) else: with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): user_cohort_id = get_cohort_id(request.user, course_key) context = { 'csrf': csrf(request)['csrf_token'], 'course': course, #'recent_active_threads': recent_active_threads, 'staff_access': has_access(request.user, 'staff', course), 'threads': _attr_safe_json(threads), 'thread_pages': query_params['num_pages'], 'user_info': _attr_safe_json(user_info), 'flag_moderator': (has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, 'staff', course)), 'annotated_content_info': _attr_safe_json(annotated_content_info), 'course_id': course.id.to_deprecated_string(), 'roles': _attr_safe_json(utils.get_role_ids(course_key)), 'is_moderator': has_permission(request.user, "see_all_cohorts", course_key), 'cohorts': course_settings[ "cohorts"], # still needed to render _thread_list_template 'user_cohort': user_cohort_id, # read from container in NewPostView 'is_course_cohorted': is_course_cohorted( course_key), # still needed to render _thread_list_template 'sort_preference': user.default_sort_key, 'category_map': course_settings["category_map"], 'course_settings': _attr_safe_json(course_settings) } # print "start rendering.." return render_to_response('discussion/index.html', context)
def single_thread(request, course_id, discussion_id, thread_id): nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, course_id, 'load_forum') cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() # Currently, the front end always loads responses via AJAX, even for this # page; it would be a nice optimization to avoid that extra round trip to # the comments service. try: thread = cc.Thread.find(thread_id).retrieve( recursive=request.is_ajax(), user_id=request.user.id, response_skip=request.GET.get("resp_skip"), response_limit=request.GET.get("resp_limit")) except cc.utils.CommentClientRequestError as e: if e.status_code == 404: raise Http404 raise if request.is_ajax(): with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_id, thread, request.user, user_info=user_info) content = utils.safe_content(thread.to_dict()) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context([content], course) return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: with newrelic.agent.FunctionTrace(nr_transaction, "get_discussion_category_map"): category_map = utils.get_discussion_category_map(course) threads, query_params = get_threads(request, course_id) threads.append(thread.to_dict()) course = get_course_with_access(request.user, course_id, 'load_forum') with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course) for thread in threads: if thread.get('group_id') and not thread.get('group_name'): thread['group_name'] = get_cohort_by_id( course_id, thread.get('group_id')).name #patch for backward compatibility with comments service if not "pinned" in thread: thread["pinned"] = False threads = [utils.safe_content(thread) for thread in threads] with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): cohorts = get_course_cohorts(course_id) cohorted_commentables = get_cohorted_commentables(course_id) user_cohort = get_cohort_id(request.user, course_id) context = { 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], 'init': '', # TODO: What is this? 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course': course, #'recent_active_threads': recent_active_threads, 'course_id': course.id, # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, 'threads': saxutils.escape(json.dumps(threads), escapedict), 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), 'thread_pages': query_params['num_pages'], 'is_course_cohorted': is_course_cohorted(course_id), 'is_moderator': cached_has_permission(request.user, "see_all_cohorts", course_id), 'flag_moderator': cached_has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, course, 'staff'), 'cohorts': cohorts, 'user_cohort': get_cohort_id(request.user, course_id), 'cohorted_commentables': cohorted_commentables } return render_to_response('discussion/index.html', context)
def forum_form_discussion(request, course_id): """ Renders the main Discussion page, potentially filtered by a search query """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, course_id, 'load_forum') with newrelic.agent.FunctionTrace(nr_transaction, "get_discussion_category_map"): category_map = utils.get_discussion_category_map(course) try: unsafethreads, query_params = get_threads( request, course_id) # This might process a search query threads = [utils.safe_content(thread) for thread in unsafethreads] except cc.utils.CommentClientMaintenanceError: log.warning("Forum is in maintenance mode") return render_to_response('discussion/maintenance.html', {}) user = cc.User.from_django_user(request.user) user_info = user.to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': threads, # TODO: Standardize on 'discussion_data' vs 'threads' 'annotated_content_info': annotated_content_info, 'num_pages': query_params['num_pages'], 'page': query_params['page'], }) else: with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): cohorts = get_course_cohorts(course_id) cohorted_commentables = get_cohorted_commentables(course_id) user_cohort_id = get_cohort_id(request.user, course_id) context = { 'csrf': csrf(request)['csrf_token'], 'course': course, #'recent_active_threads': recent_active_threads, 'staff_access': has_access(request.user, course, 'staff'), 'threads': saxutils.escape(json.dumps(threads), escapedict), 'thread_pages': query_params['num_pages'], 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'flag_moderator': cached_has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, course, 'staff'), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course_id': course.id, 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), 'is_moderator': cached_has_permission(request.user, "see_all_cohorts", course_id), 'cohorts': cohorts, 'user_cohort': user_cohort_id, 'cohorted_commentables': cohorted_commentables, 'is_course_cohorted': is_course_cohorted(course_id) } # print "start rendering.." return render_to_response('discussion/index.html', context)
def followed_threads(request, course_id, user_id): course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load_forum', course_key) try: profiled_user = cc.User(id=user_id, course_id=course_key) default_query_params = { 'page': 1, 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': 'date', 'sort_order': 'desc', } query_params = merge_dict( default_query_params, strip_none( extract(request.GET, [ 'page', 'sort_key', 'sort_order', 'flagged', 'unread', 'unanswered', ]))) try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseBadRequest("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id threads, page, num_pages = profiled_user.subscribed_threads( query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) if request.is_ajax(): is_staff = cached_has_permission(request.user, 'openclose_thread', course.id) return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ], 'page': query_params['page'], 'num_pages': query_params['num_pages'], }) #TODO remove non-AJAX support, it does not appear to be used and does not appear to work. else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': _attr_safe_json(threads), 'user_info': _attr_safe_json(user_info), 'annotated_content_info': _attr_safe_json(annotated_content_info), # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def single_thread(request, course_id, discussion_id, thread_id): nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, course_id, 'load_forum') cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id) if request.is_ajax(): with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_id, thread, request.user, user_info=user_info) context = {'thread': thread.to_dict(), 'course_id': course_id} # TODO: Remove completely or switch back to server side rendering # html = render_to_string('discussion/_ajax_single_thread.html', context) content = utils.safe_content(thread.to_dict()) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context([content], course) return utils.JsonResponse({ #'html': html, 'content': content, 'annotated_content_info': annotated_content_info, }) else: with newrelic.agent.FunctionTrace(nr_transaction, "get_discussion_category_map"): category_map = utils.get_discussion_category_map(course) threads, query_params = get_threads(request, course_id) threads.append(thread.to_dict()) course = get_course_with_access(request.user, course_id, 'load_forum') with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course) for thread in threads: if thread.get('group_id') and not thread.get('group_name'): thread['group_name'] = get_cohort_by_id( course_id, thread.get('group_id')).name #patch for backward compatibility with comments service if not "pinned" in thread: thread["pinned"] = False threads = [utils.safe_content(thread) for thread in threads] #recent_active_threads = cc.search_recent_active_threads( # course_id, # recursive=False, # query_params={'follower_id': request.user.id}, #) #trending_tags = cc.search_trending_tags( # course_id, #) with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_id, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): cohorts = get_course_cohorts(course_id) cohorted_commentables = get_cohorted_commentables(course_id) user_cohort = get_cohort_id(request.user, course_id) context = { 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], 'init': '', # TODO: What is this? 'user_info': saxutils.escape(json.dumps(user_info), escapedict), 'annotated_content_info': saxutils.escape(json.dumps(annotated_content_info), escapedict), 'course': course, #'recent_active_threads': recent_active_threads, #'trending_tags': trending_tags, 'course_id': course.id, # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, 'threads': saxutils.escape(json.dumps(threads), escapedict), 'category_map': category_map, 'roles': saxutils.escape(json.dumps(utils.get_role_ids(course_id)), escapedict), 'thread_pages': query_params['num_pages'], 'is_course_cohorted': is_course_cohorted(course_id), 'is_moderator': cached_has_permission(request.user, "see_all_cohorts", course_id), 'flag_moderator': cached_has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, course, 'staff'), 'cohorts': cohorts, 'user_cohort': get_cohort_id(request.user, course_id), 'cohorted_commentables': cohorted_commentables } return render_to_response('discussion/single_thread.html', context)
def user_profile(request, course_key, user_id): """ Renders a response to display the user profile page (shown after clicking on a post author's username). """ user = cc.User.from_django_user(request.user) course = get_course_with_access(request.user, 'load_forum', course_key, check_if_enrolled=True) try: # If user is not enrolled in the course, do not proceed. django_user = User.objects.get(id=user_id) if not CourseEnrollment.is_enrolled(django_user, course.id): raise Http404 query_params = { 'page': request.GET.get('page', 1), 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities } try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseServerError("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id profiled_user = cc.User(id=user_id, course_id=course_key, group_id=group_id) else: profiled_user = cc.User(id=user_id, course_id=course_key) threads, page, num_pages = profiled_user.active_threads(query_params) query_params['page'] = page query_params['num_pages'] = num_pages with newrelic_function_trace("get_metadata_for_threads"): user_info = cc.User.from_django_user(request.user).to_dict() annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) is_staff = has_permission(request.user, 'openclose_thread', course.id) threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ] with newrelic_function_trace("add_courseware_context"): add_courseware_context(threads, course, request.user) if request.is_ajax(): return utils.JsonResponse({ 'discussion_data': threads, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'annotated_content_info': annotated_content_info, }) else: user_roles = django_user.roles.filter( course_id=course.id).order_by("name").values_list( "name", flat=True).distinct() with newrelic_function_trace("get_cohort_info"): course_discussion_settings = get_course_discussion_settings( course_key) user_group_id = get_group_id_for_user( request.user, course_discussion_settings) context = _create_base_discussion_view_context(request, course_key) context.update({ 'django_user': django_user, 'django_user_roles': user_roles, 'profiled_user': profiled_user.to_dict(), 'threads': threads, 'user_group_id': user_group_id, 'annotated_content_info': annotated_content_info, 'page': query_params['page'], 'num_pages': query_params['num_pages'], 'sort_preference': user.default_sort_key, 'learner_profile_page_url': reverse('learner_profile', kwargs={'username': django_user.username}), }) return render_to_response( 'discussion/discussion_profile_page.html', context) except User.DoesNotExist: raise Http404
def followed_threads(request, course_key, user_id): """ Ajax-only endpoint retrieving the threads followed by a specific user. """ course = get_course_with_access(request.user, 'load_forum', course_key, check_if_enrolled=True) try: profiled_user = cc.User(id=user_id, course_id=course_key) default_query_params = { 'page': 1, 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': 'date', } query_params = merge_dict( default_query_params, strip_none( extract(request.GET, [ 'page', 'sort_key', 'flagged', 'unread', 'unanswered', ]))) try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseServerError("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id paginated_results = profiled_user.subscribed_threads(query_params) print "\n \n \n paginated results \n \n \n " print paginated_results query_params['page'] = paginated_results.page query_params['num_pages'] = paginated_results.num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic_function_trace("get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, paginated_results.collection, request.user, user_info) if request.is_ajax(): is_staff = has_permission(request.user, 'openclose_thread', course.id) return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': [ utils.prepare_content(thread, course_key, is_staff) for thread in paginated_results.collection ], 'page': query_params['page'], 'num_pages': query_params['num_pages'], }) #TODO remove non-AJAX support, it does not appear to be used and does not appear to work. else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': paginated_results.collection, 'user_info': user_info, 'annotated_content_info': annotated_content_info, # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def single_thread(request, course_key, discussion_id, thread_id): """ Renders a response to display a single discussion thread. This could either be a page refresh after navigating to a single thread, a direct link to a single thread, or an AJAX call from the discussions UI loading the responses/comments for a single thread. Depending on the HTTP headers, we'll adjust our response accordingly. """ nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_settings = make_course_settings(course, request.user) cc_user = cc.User.from_django_user(request.user) user_info = cc_user.to_dict() is_moderator = has_permission(request.user, "see_all_cohorts", course_key) is_staff = has_permission(request.user, 'openclose_thread', course.id) try: thread = cc.Thread.find(thread_id).retrieve( with_responses=request.is_ajax(), recursive=request.is_ajax(), user_id=request.user.id, response_skip=request.GET.get("resp_skip"), response_limit=request.GET.get("resp_limit")) except cc.utils.CommentClientRequestError as error: if error.status_code == 404: raise Http404 raise # Verify that the student has access to this thread if belongs to a course discussion module thread_context = getattr(thread, "context", "course") if thread_context == "course" and not utils.discussion_category_id_access( course, request.user, discussion_id): raise Http404 # verify that the thread belongs to the requesting student's cohort if is_commentable_cohorted(course_key, discussion_id) and not is_moderator: user_group_id = get_cohort_id(request.user, course_key) if getattr(thread, "group_id", None) is not None and user_group_id != thread.group_id: raise Http404 if request.is_ajax(): with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): annotated_content_info = utils.get_annotated_content_infos( course_key, thread, request.user, user_info=user_info) content = utils.prepare_content(thread.to_dict(), course_key, is_staff) with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context([content], course, request.user) return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: # Since we're in page render mode, and the discussions UI will request the thread list itself, # we need only return the thread information for this one. threads = [thread.to_dict()] with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): add_courseware_context(threads, course, request.user) for thread in threads: # patch for backward compatibility with comments service if "pinned" not in thread: thread["pinned"] = False threads = [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ] with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): user_cohort = get_cohort_id(request.user, course_key) context = { 'discussion_id': discussion_id, 'csrf': csrf(request)['csrf_token'], 'init': '', # TODO: What is this? 'user_info': user_info, 'can_create_comment': has_permission(request.user, "create_comment", course.id), 'can_create_subcomment': has_permission(request.user, "create_sub_comment", course.id), 'can_create_thread': has_permission(request.user, "create_thread", course.id), 'annotated_content_info': annotated_content_info, 'course': course, #'recent_active_threads': recent_active_threads, 'course_id': course.id.to_deprecated_string( ), # TODO: Why pass both course and course.id to template? 'thread_id': thread_id, 'threads': threads, 'roles': utils.get_role_ids(course_key), 'is_moderator': is_moderator, 'thread_pages': 1, 'is_course_cohorted': is_course_cohorted(course_key), 'flag_moderator': bool( has_permission(request.user, 'openclose_thread', course.id) or has_access(request.user, 'staff', course)), 'cohorts': course_settings["cohorts"], 'user_cohort': user_cohort, 'sort_preference': cc_user.default_sort_key, 'category_map': course_settings["category_map"], 'course_settings': course_settings, 'disable_courseware_js': True, 'uses_pattern_library': True, } return render_to_response('discussion/discussion_board.html', context)