Example #1
0
    def test_tree_with_duplicate_targets(self):
        self.create_discussion("Chapter 1", "Discussion A")
        self.create_discussion("Chapter 1", "Discussion B")
        self.create_discussion("Chapter 1", "Discussion A")  # duplicate
        self.create_discussion("Chapter 1",
                               "Discussion A")  # another duplicate
        self.create_discussion("Chapter 2 / Section 1 / Subsection 1",
                               "Discussion")
        self.create_discussion("Chapter 2 / Section 1 / Subsection 1",
                               "Discussion")  # duplicate

        category_map = utils.get_discussion_category_map(
            self.course, self.user)

        chapter1 = category_map["subcategories"]["Chapter 1"]
        chapter1_discussions = set([
            "Discussion A", "Discussion B", "Discussion A (1)",
            "Discussion A (2)"
        ])
        self.assertEqual(set(chapter1["children"]), chapter1_discussions)
        self.assertEqual(set(chapter1["entries"].keys()), chapter1_discussions)

        chapter2 = category_map["subcategories"]["Chapter 2"]
        subsection1 = chapter2["subcategories"]["Section 1"]["subcategories"][
            "Subsection 1"]
        subsection1_discussions = set(["Discussion", "Discussion (1)"])
        self.assertEqual(set(subsection1["children"]), subsection1_discussions)
        self.assertEqual(set(subsection1["entries"].keys()),
                         subsection1_discussions)
Example #2
0
 def assert_category_map_equals(self, expected, cohorted_if_in_list=False, exclude_unstarted=True):  # pylint: disable=arguments-differ
     """
     Asserts the expected map with the map returned by get_discussion_category_map method.
     """
     self.assertEqual(
         utils.get_discussion_category_map(self.course, self.instructor, cohorted_if_in_list, exclude_unstarted),
         expected
     )
Example #3
0
 def assert_category_map_equals(self, expected, requesting_user=None):
     """
     Call `get_discussion_category_map`, and verify that it returns
     what is expected.
     """
     self.assertEqual(
         utils.get_discussion_category_map(self.course, requesting_user
                                           or self.user), expected)
 def assert_category_map_equals(self, expected, cohorted_if_in_list=False, exclude_unstarted=True):  # pylint: disable=arguments-differ
     """
     Asserts the expected map with the map returned by get_discussion_category_map method.
     """
     self.assertEqual(
         utils.get_discussion_category_map(self.course, self.instructor, cohorted_if_in_list, exclude_unstarted),
         expected
     )
Example #5
0
 def assert_category_map_equals(self, expected, requesting_user=None):
     """
     Call `get_discussion_category_map`, and verify that it returns
     what is expected.
     """
     self.assertEqual(
         utils.get_discussion_category_map(self.course, requesting_user or self.user),
         expected
     )
Example #6
0
def make_course_settings(course, user):
    """
    Generate a JSON-serializable model for course settings, which will be used to initialize a
    DiscussionCourseSettings object on the client.
    """
    return {
        'is_cohorted': is_course_cohorted(course.id),
        'allow_anonymous': course.allow_anonymous,
        'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
        'cohorts': [{"id": str(g.id), "name": g.name} for g in get_course_cohorts(course)],
        'category_map': utils.get_discussion_category_map(course, user)
    }
Example #7
0
def make_course_settings(course, user):
    """
    Generate a JSON-serializable model for course settings, which will be used to initialize a
    DiscussionCourseSettings object on the client.
    """
    return {
        'is_cohorted': is_course_cohorted(course.id),
        'allow_anonymous': course.allow_anonymous,
        'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
        'cohorts': [{"id": str(g.id), "name": g.name} for g in get_course_cohorts(course)],
        'category_map': utils.get_discussion_category_map(course, user)
    }
Example #8
0
def mobi_forum_course_discussion(request, course_id):
    """
    mobile api
    get all discussions about the course
    """
    course_id = course_id.replace('.', '/')
    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:
        return JsonResponse({'success': False, 'errmsg': 'errors occur!'})

    user = cc.User.from_django_user(request.user)
    user_info = user.to_dict()

    with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"):
        add_courseware_context(threads, course)

    page = request.GET.get('page') or 0

    num_pages = query_params['num_pages']
    threads_list = []

    if int(page) <= num_pages:
        for th in threads:

            def format_thread_info(thread_id):
                thread = cc.Thread.find(thread_id).to_dict()

                if thread:
                    return {
                        "id": thread['id'],
                        "course_id": thread['course_id'].replace('/', '.'),
                        "time": dateutil.parser.parse(thread['created_at']).strftime("%Y-%m-%d %H:%M:%S"),
                        "name": thread['title'],
                        "number": len(thread['children'])
                    }
                else:
                    raise Exception

            try:
                threads_list.append(format_thread_info(th['id']))
            except:
                continue

    return JsonResponse({'course_threads': threads_list, "success": True, 'page': page, 'num_pages': num_pages})
Example #9
0
def mobi_disscussion_search(request, course_id):
    nr_transaction = newrelic.agent.current_transaction()

    course_id = course_id.replace('.', '/')
    try:
        course = get_course_with_access(request.user, course_id, 'load_forum')
    except:
        return JsonResponse({"success": False, "errmsg": "can not find a course with " + course_id.replace('/', '.') + " id"})

    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', {})
        return JsonResponse({"success": False, "errmsg": "Forum is in maintenance mode"})

    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)

    search_list = []

    page = request.GET.get('page') or 0
    num_pages = query_params['num_pages']
    if int(page) <= num_pages:
        for thread in threads:
            thread = cc.Thread.find(thread['id']).to_dict()
            thread_info = {}
            if thread:
                thread_info['id'] = thread['id']
                thread_info['course_id'] = thread['course_id'].replace('/', '.')
                thread_info['name'] = thread['title']
                thread_info['time'] = dateutil.parser.parse(thread['created_at']).strftime("%Y-%m-%d %H:%M:%S")
                thread_info['number'] = len(thread['children'])

                search_list.append(thread_info)
            else:
                continue
    else:
        page = 0

    return JsonResponse({'count': len(search_list), 'search_results': search_list, 'success': True, 'page': page, 'num_pages': num_pages})
Example #10
0
def make_course_settings(course, user):
    """
    Generate a JSON-serializable model for course settings, which will be used to initialize a
    DiscussionCourseSettings object on the client.
    """
    course_discussion_settings = get_course_discussion_settings(course.id)
    group_names_by_id = get_group_names_by_id(course_discussion_settings)
    return {
        'is_discussion_division_enabled': course_discussion_division_enabled(course_discussion_settings),
        'allow_anonymous': course.allow_anonymous,
        'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
        'groups': [
            {"id": str(group_id), "name": group_name} for group_id, group_name in group_names_by_id.iteritems()
        ],
        'category_map': utils.get_discussion_category_map(course, user)
    }
Example #11
0
def make_course_settings(course, user):
    """
    Generate a JSON-serializable model for course settings, which will be used to initialize a
    DiscussionCourseSettings object on the client.
    """
    course_discussion_settings = get_course_discussion_settings(course.id)
    group_names_by_id = get_group_names_by_id(course_discussion_settings)
    return {
        'is_discussion_division_enabled': course_discussion_division_enabled(course_discussion_settings),
        'allow_anonymous': course.allow_anonymous,
        'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
        'groups': [
            {"id": str(group_id), "name": group_name} for group_id, group_name in group_names_by_id.iteritems()
        ],
        'category_map': utils.get_discussion_category_map(course, user)
    }
Example #12
0
    def test_tree_with_duplicate_targets(self):
        self.create_discussion("Chapter 1", "Discussion A")
        self.create_discussion("Chapter 1", "Discussion B")
        self.create_discussion("Chapter 1", "Discussion A")  # duplicate
        self.create_discussion("Chapter 1", "Discussion A")  # another duplicate
        self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion")
        self.create_discussion("Chapter 2 / Section 1 / Subsection 1", "Discussion")  # duplicate

        category_map = utils.get_discussion_category_map(self.course, self.user)

        chapter1 = category_map["subcategories"]["Chapter 1"]
        chapter1_discussions = set(["Discussion A", "Discussion B", "Discussion A (1)", "Discussion A (2)"])
        self.assertEqual(set(chapter1["children"]), chapter1_discussions)
        self.assertEqual(set(chapter1["entries"].keys()), chapter1_discussions)

        chapter2 = category_map["subcategories"]["Chapter 2"]
        subsection1 = chapter2["subcategories"]["Section 1"]["subcategories"]["Subsection 1"]
        subsection1_discussions = set(["Discussion", "Discussion (1)"])
        self.assertEqual(set(subsection1["children"]), subsection1_discussions)
        self.assertEqual(set(subsection1["entries"].keys()), subsection1_discussions)
Example #13
0
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)
Example #14
0
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)
Example #15
0
def mobi_forum_course_discussion(request, course_id):
    """
    mobile api
    get all discussions about the course
    """
    course_id = course_id.replace('.', '/')
    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:
        return JsonResponse({'success': False, 'errmsg': 'errors occur!'})

    user = cc.User.from_django_user(request.user)
    user_info = user.to_dict()

    with newrelic.agent.FunctionTrace(nr_transaction,
                                      "add_courseware_context"):
        add_courseware_context(threads, course)

    page = request.GET.get('page') or 0

    num_pages = query_params['num_pages']
    threads_list = []

    if int(page) <= num_pages:
        for th in threads:

            def format_thread_info(thread_id):
                thread = cc.Thread.find(thread_id).to_dict()

                if thread:
                    return {
                        "id":
                        thread['id'],
                        "course_id":
                        thread['course_id'].replace('/', '.'),
                        "time":
                        dateutil.parser.parse(thread['created_at']).strftime(
                            "%Y-%m-%d %H:%M:%S"),
                        "name":
                        thread['title'],
                        "number":
                        len(thread['children'])
                    }
                else:
                    raise Exception

            try:
                threads_list.append(format_thread_info(th['id']))
            except:
                continue

    return JsonResponse({
        'course_threads': threads_list,
        "success": True,
        'page': page,
        'num_pages': num_pages
    })
Example #16
0
def mobi_disscussion_search(request, course_id):
    nr_transaction = newrelic.agent.current_transaction()

    course_id = course_id.replace('.', '/')
    try:
        course = get_course_with_access(request.user, course_id, 'load_forum')
    except:
        return JsonResponse({
            "success":
            False,
            "errmsg":
            "can not find a course with " + course_id.replace('/', '.') + " id"
        })

    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', {})
        return JsonResponse({
            "success": False,
            "errmsg": "Forum is in maintenance mode"
        })

    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)

    search_list = []

    page = request.GET.get('page') or 0
    num_pages = query_params['num_pages']
    if int(page) <= num_pages:
        for thread in threads:
            thread = cc.Thread.find(thread['id']).to_dict()
            thread_info = {}
            if thread:
                thread_info['id'] = thread['id']
                thread_info['course_id'] = thread['course_id'].replace(
                    '/', '.')
                thread_info['name'] = thread['title']
                thread_info['time'] = dateutil.parser.parse(
                    thread['created_at']).strftime("%Y-%m-%d %H:%M:%S")
                thread_info['number'] = len(thread['children'])

                search_list.append(thread_info)
            else:
                continue
    else:
        page = 0

    return JsonResponse({
        'count': len(search_list),
        'search_results': search_list,
        'success': True,
        'page': page,
        'num_pages': num_pages
    })
Example #17
0
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()

    try:
        thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id)
    except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError):
        log.error("Error loading single thread.")
        raise

    if request.is_ajax():
        with newrelic.agent.FunctionTrace(nr_transaction, "get_courseware_context"):
            courseware_context = get_courseware_context(thread, course)
        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())
        if courseware_context:
            content.update(courseware_context)
        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)

        try:
            threads, query_params = get_threads(request, course_id)
            threads.append(thread.to_dict())
        except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError):
            log.error("Error loading single thread.")
            raise

        course = get_course_with_access(request.user, course_id, 'load_forum')

        with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context_to_threads"):
            for thread in threads:
                courseware_context = get_courseware_context(thread, course)
                if courseware_context:
                    thread.update(courseware_context)
                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 single_thread(request, course_id, discussion_id, thread_id):
    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()
    try:
        thread = cc.Thread.find(thread_id).retrieve(recursive=True, user_id=request.user.id)
    except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError):
        log.error("Error loading single thread.")
        context = {'window_title':'Message',
                   'error_title':'',
                   'error_message':"This discussion has been deleted. <a href='/dashboard'>Click here</a> to go back to your dashboard. \
                                    For additional help contact <a href='mailto:[email protected]'>[email protected]</a>."}
        return render_to_response('error.html', context)
        # raise Http404
    
    if len(thread.get('children'))<1:
        create_comment_auto_load(request, course_id, thread_id,User.objects.get(id=thread.get("user_id")))
    if request.is_ajax():
        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())
        #courseware_context = get_courseware_context(thread, course)
        #if courseware_context:
        #    content.update(courseware_context)
        if thread.get('tags')[0]!='portfolio':
            id_map = get_discussion_id_map(course)
            id = content['commentable_id']
            content_info = None
            if id in id_map:
                location = id_map[id]["location"].url()
                title = id_map[id]["title"]

                url = reverse('jump_to', kwargs={"course_id": course.location.course_id,
                          "location": location})

                content.update({"courseware_url": url, "courseware_title": title})
        return utils.JsonResponse({
            #'html': html,
            'content': content,
            'annotated_content_info': annotated_content_info,
        })

    else:
        category_map = utils.get_discussion_category_map(course)
        id_map = get_discussion_id_map(course)
        try:
            threads, query_params = get_threads_tags(request, course_id)
            threads.append(thread.to_dict())
        except (cc.utils.CommentClientError, cc.utils.CommentClientUnknownError):
            log.error("Error loading single thread.")
            raise Http404

        course = get_course_with_access(request.user, course_id, 'load_forum')
        thread_output = []
        for thread in threads:
            #courseware_context = get_courseware_context(thread, course)
            #if courseware_context:
            #    thread.update(courseware_context)
            id = thread['commentable_id']
            content_info = None
            if id in id_map:
                location = id_map[id]["location"].url()
                title = id_map[id]["title"]

                url = reverse('jump_to', kwargs={"course_id": course.location.course_id,
                          "location": location})

                thread.update({"courseware_url": url, "courseware_title": title})
            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
            if len(thread.get('tags'))>0:
                #if thread.get('tags')[0]!='portfolio' and str(thread.get('courseware_url')).find('__am')<0:
                if thread.get('tags')[0]!='portfolio' and thread.get('tags')[0]!='aboutme':
                    thread_output.append(thread)
        thread_output = [utils.safe_content(thread) for thread in thread_output]

        #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,
        #)

        annotated_content_info = utils.get_metadata_for_threads(course_id, thread_output, request.user, user_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(thread_output), 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)
Example #19
0
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)
Example #20
0
def discussion_topics(request, course_key_string):
    """
    The handler for divided discussion categories requests.
    This will raise 404 if user is not staff.

    Returns the JSON representation of discussion topics w.r.t categories for the course.

    Example:
        >>> example = {
        >>>               "course_wide_discussions": {
        >>>                   "entries": {
        >>>                       "General": {
        >>>                           "sort_key": "General",
        >>>                           "is_divided": True,
        >>>                           "id": "i4x-edx-eiorguegnru-course-foobarbaz"
        >>>                       }
        >>>                   }
        >>>                   "children": ["General", "entry"]
        >>>               },
        >>>               "inline_discussions" : {
        >>>                   "subcategories": {
        >>>                       "Getting Started": {
        >>>                           "subcategories": {},
        >>>                           "children": [
        >>>                               ["Working with Videos", "entry"],
        >>>                               ["Videos on edX", "entry"]
        >>>                           ],
        >>>                           "entries": {
        >>>                               "Working with Videos": {
        >>>                                   "sort_key": None,
        >>>                                   "is_divided": False,
        >>>                                   "id": "d9f970a42067413cbb633f81cfb12604"
        >>>                               },
        >>>                               "Videos on edX": {
        >>>                                   "sort_key": None,
        >>>                                   "is_divided": False,
        >>>                                   "id": "98d8feb5971041a085512ae22b398613"
        >>>                               }
        >>>                           }
        >>>                       },
        >>>                       "children": ["Getting Started", "subcategory"]
        >>>                   },
        >>>               }
        >>>          }
    """
    course_key = CourseKey.from_string(course_key_string)
    course = get_course_with_access(request.user, 'staff', course_key)

    discussion_topics = {}
    discussion_category_map = utils.get_discussion_category_map(
        course, request.user, divided_only_if_explicit=True, exclude_unstarted=False
    )

    # We extract the data for the course wide discussions from the category map.
    course_wide_entries = discussion_category_map.pop('entries')

    course_wide_children = []
    inline_children = []

    for name, c_type in discussion_category_map['children']:
        if name in course_wide_entries and c_type == TYPE_ENTRY:
            course_wide_children.append([name, c_type])
        else:
            inline_children.append([name, c_type])

    discussion_topics['course_wide_discussions'] = {
        'entries': course_wide_entries,
        'children': course_wide_children
    }

    discussion_category_map['children'] = inline_children
    discussion_topics['inline_discussions'] = discussion_category_map

    return JsonResponse(discussion_topics)
Example #21
0
 def test_empty(self):
     self.assertEqual(
         utils.get_discussion_category_map(self.course),
         {"entries": {}, "subcategories": {}, "children": []}
     )
Example #22
0
 def assertCategoryMapEquals(self, expected):
     self.assertEqual(
         utils.get_discussion_category_map(self.course),
         expected
     )
Example #23
0
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)
Example #24
0
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.
    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")
    )

    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]

        #recent_active_threads = cc.search_recent_active_threads(
        #    course_id,
        #    recursive=False,
        #    query_params={'follower_id': request.user.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,
            '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
    """

    from student.models import UserTestGroup, CourseEnrollment
    registered=CourseEnrollment.is_enrolled(request.user, course_id)
    if not registered:
        return redirect(reverse('cabout', args=[course_id]))
    
    course = get_course_with_access(request.user, course_id, 'load_forum')
    category_map = utils.get_discussion_category_map(course)
    id_map = get_discussion_id_map(course)
    try:
        unsafethreads, query_params = get_threads_tags(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()

    thread_output = []
    for thread in threads:
        #courseware_context = get_courseware_context(thread, course)
        #if courseware_context:
        #    thread.update(courseware_context)   
        id = thread['commentable_id']
        content_info = None
        if id in id_map:
            location = id_map[id]["location"].url()
            title = id_map[id]["title"]

            url = reverse('jump_to', kwargs={"course_id": course.location.course_id,
                      "location": location})

            thread.update({"courseware_url": url, "courseware_title": title})
        if len(thread.get('tags'))>0:
            #if thread.get('tags')[0]!='portfolio' and str(thread.get('courseware_url')).find('__am')<0:
            if thread.get('tags')[0]!='portfolio' and thread.get('tags')[0]!='aboutme':
                thread_output.append(thread)
    annotated_content_info = utils.get_metadata_for_threads(course_id, thread_output, request.user, user_info)
    if request.is_ajax():
        return utils.JsonResponse({
            'discussion_data': thread_output,   # 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)
        if request.GET.get('pf_id') != None:
            curr_user = User.objects.get(id=int(request.GET.get('pf_id')))
        else:
            curr_user = None
        context = {
            'curr_user':curr_user,
            '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(thread_output), 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)
Example #26
0
def discussion_topics(request, course_key_string):
    """
    The handler for divided discussion categories requests.
    This will raise 404 if user is not staff.

    Returns the JSON representation of discussion topics w.r.t categories for the course.

    Example:
        >>> example = {
        >>>               "course_wide_discussions": {
        >>>                   "entries": {
        >>>                       "General": {
        >>>                           "sort_key": "General",
        >>>                           "is_divided": True,
        >>>                           "id": "i4x-edx-eiorguegnru-course-foobarbaz"
        >>>                       }
        >>>                   }
        >>>                   "children": ["General", "entry"]
        >>>               },
        >>>               "inline_discussions" : {
        >>>                   "subcategories": {
        >>>                       "Getting Started": {
        >>>                           "subcategories": {},
        >>>                           "children": [
        >>>                               ["Working with Videos", "entry"],
        >>>                               ["Videos on edX", "entry"]
        >>>                           ],
        >>>                           "entries": {
        >>>                               "Working with Videos": {
        >>>                                   "sort_key": None,
        >>>                                   "is_divided": False,
        >>>                                   "id": "d9f970a42067413cbb633f81cfb12604"
        >>>                               },
        >>>                               "Videos on edX": {
        >>>                                   "sort_key": None,
        >>>                                   "is_divided": False,
        >>>                                   "id": "98d8feb5971041a085512ae22b398613"
        >>>                               }
        >>>                           }
        >>>                       },
        >>>                       "children": ["Getting Started", "subcategory"]
        >>>                   },
        >>>               }
        >>>          }
    """
    course_key = CourseKey.from_string(course_key_string)
    course = get_course_with_access(request.user, 'staff', course_key)

    discussion_topics = {}
    discussion_category_map = utils.get_discussion_category_map(
        course,
        request.user,
        divided_only_if_explicit=True,
        exclude_unstarted=False)

    # We extract the data for the course wide discussions from the category map.
    course_wide_entries = discussion_category_map.pop('entries')

    course_wide_children = []
    inline_children = []

    for name, c_type in discussion_category_map['children']:
        if name in course_wide_entries and c_type == TYPE_ENTRY:
            course_wide_children.append([name, c_type])
        else:
            inline_children.append([name, c_type])

    discussion_topics['course_wide_discussions'] = {
        'entries': course_wide_entries,
        'children': course_wide_children
    }

    discussion_category_map['children'] = inline_children
    discussion_topics['inline_discussions'] = discussion_category_map

    return JsonResponse(discussion_topics)
Example #27
0
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:
        #recent_active_threads = cc.search_recent_active_threads(
        #    course_id,
        #    recursive=False,
        #    query_params={'follower_id': request.user.id},
        #)

        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)