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) try: _check_team_discussion_access(request, course, discussion_id) except TeamDiscussionHiddenFromUserException: return HttpResponseForbidden(TEAM_PERMISSION_MESSAGE) 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, request.user.is_community_ta) with function_trace("add_courseware_context"): add_courseware_context([content], course, request.user) return utils.JsonResponse({ 'content': content, 'annotated_content_info': annotated_content_info, }) else: course_id = str(course.id) tab_view = CourseTabView() return tab_view.get(request, course_id, 'discussion', discussion_id=discussion_id, thread_id=thread_id)
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, request.user.is_community_ta) 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': 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 = str(course.id) tab_view = CourseTabView() return tab_view.get(request, course_id, 'discussion')
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) 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 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': 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 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', course_key, check_if_enrolled=True) try: profiled_user = cc.User(id=user_id, course_id=course_key) query_params = { 'page': 1, 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': 'date', } query_params.update( 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 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) is_community_ta = utils.is_user_community_ta( request.user, course.id) return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': [ utils.prepare_content(thread, course_key, is_staff, is_community_ta) 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(request, 'discussion/user_profile.html', context) except User.DoesNotExist: raise Http404 # lint-amnesty, pylint: disable=raise-missing-from
def create_user_profile_context(request, course_key, user_id): """ Generate a context dictionary for the user profile. """ user = cc.User.from_django_user(request.user) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) # 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 } group_id = get_group_id_for_comments_service(request, course_key) 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 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) is_community_ta = utils.is_user_community_ta(request.user, course.id) threads = [ utils.prepare_content(thread, course_key, is_staff, is_community_ta) for thread in threads ] with function_trace("add_courseware_context"): add_courseware_context(threads, course, request.user) # TODO: LEARNER-3854: If we actually implement Learner Analytics code, this # code was original protected to not run in user_profile() if is_ajax(). # Someone should determine if that is still necessary (i.e. was that ever # called as is_ajax()) and clean this up as necessary. user_roles = django_user.roles.filter( course_id=course.id).order_by("name").values_list( "name", flat=True).distinct() with function_trace("get_cohort_info"): course_discussion_settings = CourseDiscussionSettings.get( 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 context
def _create_discussion_board_context(request, base_context, thread=None): """ Returns the template context for rendering the discussion board. """ context = base_context.copy() course = context['course'] course_key = course.id thread_id = thread.id if thread else None discussion_id = thread.commentable_id if thread else None course_settings = context['course_settings'] user = context['user'] cc_user = cc.User.from_django_user(user) user_info = context['user_info'] if thread: _check_team_discussion_access(request, course, discussion_id) # 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()] for thread in threads: # lint-amnesty, pylint: disable=redefined-argument-from-local # patch for backward compatibility with comments service if "pinned" not in thread: thread["pinned"] = False thread_pages = 1 root_url = reverse('forum_form_discussion', args=[str(course.id)]) else: threads, query_params = get_threads( request, course, user_info) # This might process a search query thread_pages = query_params['num_pages'] root_url = request.path is_staff = has_permission(user, 'openclose_thread', course.id) is_community_ta = utils.is_user_community_ta(request.user, course.id) threads = [ utils.prepare_content(thread, course_key, is_staff, is_community_ta) for thread in threads ] with function_trace("get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, user, user_info) with function_trace("add_courseware_context"): add_courseware_context(threads, course, user) with function_trace("get_cohort_info"): course_discussion_settings = CourseDiscussionSettings.get(course_key) user_group_id = get_group_id_for_user(user, course_discussion_settings) context.update({ 'root_url': root_url, 'discussion_id': discussion_id, 'thread_id': thread_id, 'threads': threads, 'thread_pages': thread_pages, 'annotated_content_info': annotated_content_info, 'is_moderator': has_permission(user, "see_all_cohorts", course_key), 'groups': course_settings[ "groups"], # still needed to render _thread_list_template 'user_group_id': user_group_id, # read from container in NewPostView 'sort_preference': cc_user.default_sort_key, 'category_map': course_settings["category_map"], 'course_settings': course_settings, 'is_commentable_divided': is_commentable_divided(course_key, discussion_id, course_discussion_settings), # If the default topic id is None the front-end code will look for a topic that contains "General" 'discussion_default_topic_id': _get_discussion_default_topic_id(course), 'enable_daily_digest': is_forum_daily_digest_enabled() }) context.update(get_experiment_user_metadata_context( course, user, )) return context
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') except TeamDiscussionHiddenFromUserException: return HttpResponseForbidden(TEAM_PERMISSION_MESSAGE) 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) is_community_ta = utils.is_user_community_ta(request.user, course.id) course_discussion_settings = CourseDiscussionSettings.get(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, is_community_ta, 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) })