예제 #1
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"]
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    #patch for backward compatibility to comments service
    if not 'pinned' in thread.attributes:
        thread['pinned'] = False

    if post.get('auto_subscribe', 'false').lower() == 'true':
        user = cc.User.from_django_user(request.user)
        user.follow(thread)
    data = thread.to_dict()
    add_thread_group_name(data, course_key)
    add_courseware_context([data], course)
    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(safe_content(data, course_key))
예제 #2
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"]
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    if post.get('auto_subscribe', 'false').lower() == 'true':
        user = cc.User.from_django_user(request.user)
        user.follow(thread)
    data = thread.to_dict()
    add_courseware_context([data], course)
    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #3
0
파일: views.py 프로젝트: jswope00/griffinx
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
예제 #4
0
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
예제 #5
0
파일: views.py 프로젝트: mreyk/edx-platform
def get_threads(request, course, user_info, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.

    Arguments:
        request (WSGIRequest): The user request.
        course (CourseDescriptorWithMixins): The course object.
        user_info (dict): The comment client User object as a dict.
        discussion_id (unicode): Optional discussion id/commentable id for context.
        per_page (int): Optional number of threads per page.

    Returns:
        (tuple of list, dict): A tuple of the list of threads and a dict of the
            query parameters used for the search.

    """
    default_query_params = {
        'page': 1,
        'per_page': per_page,
        'sort_key': 'activity',
        'text': '',
        'course_id': unicode(course.id),
        'user_id': request.user.id,
        'context': ThreadContext.COURSE,
        'group_id': get_group_id_for_comments_service(request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id
        # Use the discussion id/commentable id to determine the context we are going to pass through to the backend.
        if get_team(discussion_id) is not None:
            default_query_params['context'] = ThreadContext.STANDALONE

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        default_query_params['sort_key'] = user_info.get('default_sort_key') or default_query_params['sort_key']

    elif request.GET.get('sort_key') != user_info.get('default_sort_key'):
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = default_query_params.copy()
    query_params.update(
        strip_none(
            extract(
                request.GET,
                [
                    'page',
                    'sort_key',
                    'text',
                    'commentable_ids',
                    'flagged',
                    'unread',
                    'unanswered',
                ]
            )
        )
    )

    paginated_results = cc.Thread.search(query_params)
    threads = paginated_results.collection

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = paginated_results.page
    query_params['num_pages'] = paginated_results.num_pages
    query_params['corrected_text'] = paginated_results.corrected_text

    return threads, query_params
예제 #6
0
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)
    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)

        # 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 = 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 context
예제 #7
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST
    user = request.user

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers',
                                      'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    params = {
        'anonymous': anonymous,
        'anonymous_to_peers': anonymous_to_peers,
        'commentable_id': commentable_id,
        'course_id': course_key.to_deprecated_string(),
        'user_id': user.id,
        'thread_type': post["thread_type"],
        'body': post["body"],
        'title': post["title"],
    }

    # Check for whether this commentable belongs to a team, and add the right context
    if get_team(commentable_id) is not None:
        params['context'] = ThreadContext.STANDALONE
    else:
        params['context'] = ThreadContext.COURSE

    thread = cc.Thread(**params)

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key,
                                                     commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    thread_created.send(sender=None, user=user, post=thread)

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        cc_user = cc.User.from_django_user(user)
        cc_user.follow(thread)

    event_data = get_thread_created_event_data(thread, follow)
    data = thread.to_dict()

    add_courseware_context([data], course, user)

    track_forum_event(request, THREAD_CREATED_EVENT_NAME, course, thread,
                      event_data)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #8
0
def get_threads(request, course, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.
    """
    default_query_params = {
        'page': 1,
        'per_page': per_page,
        'sort_key': 'activity',
        'sort_order': 'desc',
        'text': '',
        'course_id': unicode(course.id),
        'user_id': request.user.id,
        'context': ThreadContext.COURSE,
        'group_id': get_group_id_for_comments_service(request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id
        # Use the discussion id/commentable id to determine the context we are going to pass through to the backend.
        if get_team(discussion_id) is not None:
            default_query_params['context'] = ThreadContext.STANDALONE

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be
        # user.default_sort_key because the service returns the default value
        default_query_params['sort_key'] = cc_user.get('default_sort_key') or default_query_params['sort_key']
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(
                request.GET,
                [
                    'page',
                    'sort_key',
                    'sort_order',
                    'text',
                    'commentable_ids',
                    'flagged',
                    'unread',
                    'unanswered',
                ]
            )
        )
    )

    paginated_results = cc.Thread.search(query_params)
    threads = paginated_results.collection

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = paginated_results.page
    query_params['num_pages'] = paginated_results.num_pages
    query_params['corrected_text'] = paginated_results.corrected_text

    return threads, query_params
예제 #9
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"]
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        user = cc.User.from_django_user(request.user)
        user.follow(thread)

    event_data = get_thread_created_event_data(thread, follow)
    data = thread.to_dict()

    # Calls to id map are expensive, but we need this more than once.
    # Prefetch it.
    id_map = get_discussion_id_map(course, request.user)

    add_courseware_context([data], course, request.user, id_map=id_map)

    track_forum_event(request, THREAD_CREATED_EVENT_NAME,
                      course, thread, event_data, id_map=id_map)

    
    try:
        role = Role.objects.get(name="E-tutor", course_id=course_id)
        etutors = role.users.all().order_by('username')     
        user= request.user
        """
        Send Notify to the Etutors !

        """
        subject = "nouveau message sur le forum"
        message = "Bonjour,\n\n Il y a un nouveau message sur Universite Talan.\n\n--------------------\n--------------------\n\n Auteur : "+ user.username +" \n Titre : "+ post["title"] + " \n Message : "+post["body"]
        from_email = "*****@*****.**"
        def extract_etutors_info(etutor):
            if etutor.email != user.email:
                send_mail("[UnivTalan] "+subject, message, from_email, [etutor.email])
                   
        map(extract_etutors_info, etutors)       
    except Role.DoesNotExist:
        etutors = [] 

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #10
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """
    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST
    user = request.user

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    params = {
        'anonymous': anonymous,
        'anonymous_to_peers': anonymous_to_peers,
        'commentable_id': commentable_id,
        'course_id': course_key.to_deprecated_string(),
        'user_id': user.id,
        'thread_type': post["thread_type"],
        'body': post["body"],
        'title': post["title"],
    }

    # Check for whether this commentable belongs to a team, and add the right context
    if get_team(commentable_id) is not None:
        params['context'] = ThreadContext.STANDALONE
    else:
        params['context'] = ThreadContext.COURSE

    thread = cc.Thread(**params)

    # Divide the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseServerError("Invalid group id for commentable")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    thread_created.send(sender=None, user=user, post=thread)

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        cc_user = cc.User.from_django_user(user)
        cc_user.follow(thread)
        thread_followed.send(sender=None, user=user, post=thread)

    data = thread.to_dict()

    add_courseware_context([data], course, user)

    track_thread_created_event(request, course, thread, follow)

    if thread.get('group_id'):
        # Send a notification message, if enabled, when anyone posts a new thread on
        # a cohorted/private discussion, except the poster him/herself
        _send_discussion_notification(
            'open-edx.lms.discussions.cohorted-thread-added',
            unicode(course_key),
            thread,
            request.user,
            excerpt=_get_excerpt(thread.body),
            recipient_group_id=thread.get('group_id'),
            recipient_exclude_user_ids=[request.user.id],
            is_anonymous_user=anonymous or anonymous_to_peers
        )

    add_thread_group_name(data, course_key)
    if thread.get('group_id') and not thread.get('group_name'):
        thread['group_name'] = get_cohort_by_id(course_key, thread.get('group_id')).name

    data = thread.to_dict()

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #11
0
파일: views.py 프로젝트: TURFU/edx-platform
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)
    post = request.POST
    user = request.user

    if course.allow_anonymous:
        anonymous = post.get("anonymous", "false").lower() == "true"
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get("anonymous_to_peers", "false").lower() == "true"
    else:
        anonymous_to_peers = False

    if "title" not in post or not post["title"].strip():
        return JsonError(_("Title can't be empty"))
    if "body" not in post or not post["body"].strip():
        return JsonError(_("Body can't be empty"))

    params = {
        "anonymous": anonymous,
        "anonymous_to_peers": anonymous_to_peers,
        "commentable_id": commentable_id,
        "course_id": course_key.to_deprecated_string(),
        "user_id": user.id,
        "thread_type": post["thread_type"],
        "body": post["body"],
        "title": post["title"],
    }

    # Check for whether this commentable belongs to a team, and add the right context
    if get_team(commentable_id) is not None:
        params["context"] = ThreadContext.STANDALONE
    else:
        params["context"] = ThreadContext.COURSE

    thread = cc.Thread(**params)

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    thread_created.send(sender=None, user=user, post=thread)

    # patch for backward compatibility to comments service
    if "pinned" not in thread.attributes:
        thread["pinned"] = False

    follow = post.get("auto_subscribe", "false").lower() == "true"

    if follow:
        cc_user = cc.User.from_django_user(user)
        cc_user.follow(thread)

    data = thread.to_dict()

    add_courseware_context([data], course, user)

    track_thread_created_event(request, course, thread, follow)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #12
0
def get_threads(request, course, user_info, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.

    Arguments:
        request (WSGIRequest): The user request.
        course (CourseDescriptorWithMixins): The course object.
        user_info (dict): The comment client User object as a dict.
        discussion_id (unicode): Optional discussion id/commentable id for context.
        per_page (int): Optional number of threads per page.

    Returns:
        (tuple of list, dict): A tuple of the list of threads and a dict of the
            query parameters used for the search.

    """
    default_query_params = {
        'page': 1,
        'per_page': per_page,
        'sort_key': 'activity',
        'text': '',
        'course_id': unicode(course.id),
        'user_id': request.user.id,
        'context': ThreadContext.COURSE,
        'group_id': get_group_id_for_comments_service(request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id
        # Use the discussion id/commentable id to determine the context we are going to pass through to the backend.
        if get_team(discussion_id) is not None:
            default_query_params['context'] = ThreadContext.STANDALONE

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        default_query_params['sort_key'] = user_info.get('default_sort_key') or default_query_params['sort_key']

    elif request.GET.get('sort_key') != user_info.get('default_sort_key'):
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    # there are 2 dimensions to consider when executing a search with respect to group id
    # is user a moderator
    # did the user request a group

    # if the user requested a group explicitly, give them that group, otherwise, if mod, show all, else if student, use cohort

    if discussion_id:
        is_cohorted = is_commentable_divided(course.id, discussion_id)
    else:
        is_cohorted = is_course_cohorted(course.id)

    if has_permission(request.user, "see_all_cohorts", course.id):
        group_id = request.GET.get('group_id')
        if group_id in ("all", "None"):
            group_id = None
    else:
        group_id = get_cohort_id(request.user, course.id)
        if not group_id:
            default_query_params['exclude_groups'] = True

    if group_id:
        group_id = int(group_id)
        try:
            CourseUserGroup.objects.get(course_id=course.id, id=group_id)
        except CourseUserGroup.DoesNotExist:
            if not is_cohorted:
                group_id = None
            else:
                raise ValueError("Invalid Group ID")
        default_query_params["group_id"] = group_id

    #so by default, a moderator sees all items, and a student sees his cohort

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(
                request.GET,
                [
                    'page',
                    'sort_key',
                    'text',
                    'commentable_ids',
                    'flagged',
                    'unread',
                    'unanswered',
                ]
            )
        )
    )

    if not is_cohorted:
        query_params.pop('group_id', None)

    paginated_results = cc.Thread.search(query_params)
    threads = paginated_results.collection

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = paginated_results.page
    query_params['num_pages'] = paginated_results.num_pages
    query_params['corrected_text'] = paginated_results.corrected_text

    return threads, query_params
예제 #13
0
파일: views.py 프로젝트: sdull/edx-platform
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, "load", course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get("anonymous", "false").lower() == "true"
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get("anonymous_to_peers", "false").lower() == "true"
    else:
        anonymous_to_peers = False

    if "title" not in post or not post["title"].strip():
        return JsonError(_("Title can't be empty"))
    if "body" not in post or not post["body"].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"],
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if "pinned" not in thread.attributes:
        thread["pinned"] = False

    follow = post.get("auto_subscribe", "false").lower() == "true"

    if follow:
        user = cc.User.from_django_user(request.user)
        user.follow(thread)

    event_data = get_thread_created_event_data(thread, follow)
    data = thread.to_dict()

    # Calls to id map are expensive, but we need this more than once.
    # Prefetch it.
    id_map = get_discussion_id_map(course, request.user)

    add_courseware_context([data], course, request.user, id_map=id_map)

    track_forum_event(request, THREAD_CREATED_EVENT_NAME, course, thread, event_data, id_map=id_map)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #14
0
def get_threads(request,
                course_key,
                discussion_id=None,
                per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.
    """
    default_query_params = {
        'page':
        1,
        'per_page':
        per_page,
        'sort_key':
        'date',
        'sort_order':
        'desc',
        'text':
        '',
        'commentable_id':
        discussion_id,
        'course_id':
        course_key.to_deprecated_string(),
        'user_id':
        request.user.id,
        'group_id':
        get_group_id_for_comments_service(
            request, course_key, discussion_id),  # may raise ValueError
    }

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be user.default_sort_key because the service returns the default value
        default_query_params['sort_key'] = cc_user.get(
            'default_sort_key') or default_query_params['sort_key']
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(request.GET, [
                'page',
                'sort_key',
                'sort_order',
                'text',
                'commentable_ids',
                'flagged',
                'unread',
                'unanswered',
            ])))

    threads, page, num_pages, corrected_text = cc.Thread.search(query_params)

    #now add the group name if the thread has a group id
    for thread in threads:
        add_thread_group_name(thread, course_key)

        #patch for backward compatibility to comments service
        if not 'pinned' in thread:
            thread['pinned'] = False

    query_params['page'] = page
    query_params['num_pages'] = num_pages
    query_params['corrected_text'] = corrected_text

    return threads, query_params
예제 #15
0
파일: views.py 프로젝트: GbalsaC/bitnamiP
def followed_threads(request, course_key, user_id):
    """
    Ajax-only endpoint retrieving the threads followed by a specific user.
    """

    #    nr_transaction = newrelic.agent.current_transaction()

    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)

        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 = 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
예제 #16
0
파일: views.py 프로젝트: GbalsaC/bitnamiP
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", course_key, check_if_enrolled=True)
    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 = 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:
            django_user = User.objects.get(id=user_id)
            context = {
                "course": course,
                "user": request.user,
                "django_user": django_user,
                "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"],
                "learner_profile_page_url": reverse("learner_profile", kwargs={"username": django_user.username}),
            }

            return render_to_response("discussion/user_profile.html", context)
    except User.DoesNotExist:
        raise Http404
예제 #17
0
def get_threads(request, course_key, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.
    """
    default_query_params = {
        'page': 1,
        'per_page': per_page,
        'sort_key': 'date',
        'sort_order': 'desc',
        'text': '',
        'commentable_id': discussion_id,
        'course_id': course_key.to_deprecated_string(),
        'user_id': request.user.id,
        'group_id': get_group_id_for_comments_service(request, course_key, discussion_id),  # may raise ValueError
    }

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be user.default_sort_key because the service returns the default value
        default_query_params['sort_key'] = cc_user.get('default_sort_key') or default_query_params['sort_key']
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(
                request.GET,
                [
                    'page',
                    'sort_key',
                    'sort_order',
                    'text',
                    'commentable_ids',
                    'flagged',
                    'unread',
                    'unanswered',
                ]
            )
        )
    )

    threads, page, num_pages, corrected_text = cc.Thread.search(query_params)

    for thread in threads:
        #patch for backward compatibility to comments service
        if not 'pinned' in thread:
            thread['pinned'] = False

    query_params['page'] = page
    query_params['num_pages'] = num_pages
    query_params['corrected_text'] = corrected_text

    return threads, query_params
예제 #18
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers',
                                      'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(anonymous=anonymous,
                       anonymous_to_peers=anonymous_to_peers,
                       commentable_id=commentable_id,
                       course_id=course_key.to_deprecated_string(),
                       user_id=request.user.id,
                       thread_type=post["thread_type"],
                       body=post["body"],
                       title=post["title"])

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key,
                                                     commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        user = cc.User.from_django_user(request.user)
        user.follow(thread)

    event_data = {
        'title': thread.title,
        'commentable_id': commentable_id,
        'options': {
            'followed': follow
        },
        'anonymous': anonymous,
        'thread_type': thread.thread_type,
        'group_id': group_id,
        'anonymous_to_peers': anonymous_to_peers,
        # There is a stated desire for an 'origin' property that will state
        # whether this thread was created via courseware or the forum.
        # However, the view does not contain that data, and including it will
        # likely require changes elsewhere.
    }
    data = thread.to_dict()

    # Calls to id map are expensive, but we need this more than once.
    # Prefetch it.
    id_map = get_discussion_id_map(course, request.user)

    add_courseware_context([data], course, request.user, id_map=id_map)

    track_forum_event(request,
                      'edx.forum.thread.created',
                      course,
                      thread,
                      event_data,
                      id_map=id_map)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #19
0
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
예제 #20
0
def get_threads(request,
                course,
                user_info,
                discussion_id=None,
                per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.

    Arguments:
        request (WSGIRequest): The user request.
        course (CourseDescriptorWithMixins): The course object.
        user_info (dict): The comment client User object as a dict.
        discussion_id (unicode): Optional discussion id/commentable id for context.
        per_page (int): Optional number of threads per page.

    Returns:
        (tuple of list, dict): A tuple of the list of threads and a dict of the
            query parameters used for the search.

    """
    default_query_params = {
        'page':
        1,
        'per_page':
        per_page,
        'sort_key':
        'activity',
        'text':
        '',
        'course_id':
        unicode(course.id),
        'user_id':
        request.user.id,
        'context':
        ThreadContext.COURSE,
        'group_id':
        get_group_id_for_comments_service(
            request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id
        # Use the discussion id/commentable id to determine the context we are going to pass through to the backend.
        if get_team(discussion_id) is not None:
            default_query_params['context'] = ThreadContext.STANDALONE

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        default_query_params['sort_key'] = user_info.get(
            'default_sort_key') or default_query_params['sort_key']

    elif request.GET.get('sort_key') != user_info.get('default_sort_key'):
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    # if the user requested a group explicitly, give them that group, otherwise, if mod, show all, else if student, use cohort

    if discussion_id:
        is_cohorted = is_commentable_divided(course.id, discussion_id)
    else:
        is_cohorted = is_course_cohorted(course.id)

    if has_permission(request.user, "see_all_cohorts", course.id):
        group_id = request.GET.get('group_id')
        if group_id in ("all", "None"):
            group_id = None
    else:
        group_id = get_cohort_id(request.user, course.id)
        if not group_id:
            default_query_params['exclude_groups'] = True

    if group_id:
        group_id = int(group_id)
        try:
            CourseUserGroup.objects.get(course_id=course.id, id=group_id)
        except CourseUserGroup.DoesNotExist:
            if not is_cohorted:
                group_id = None
            else:
                raise ValueError("Invalid Group ID")
        default_query_params["group_id"] = group_id

    #so by default, a moderator sees all items, and a student sees his cohort

    query_params = default_query_params.copy()
    query_params.update(
        strip_none(
            extract(request.GET, [
                'page',
                'sort_key',
                'text',
                'commentable_ids',
                'flagged',
                'unread',
                'unanswered',
            ])))

    if not is_cohorted:
        query_params.pop('group_id', None)

    paginated_results = cc.Thread.search(query_params)
    threads = paginated_results.collection

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(
            utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = paginated_results.page
    query_params['num_pages'] = paginated_results.num_pages
    query_params['corrected_text'] = paginated_results.corrected_text

    return threads, query_params
예제 #21
0
파일: views.py 프로젝트: svejk/edx-platform
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', 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
예제 #22
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """
    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST
    user = request.user

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers',
                                      'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    params = {
        'anonymous': anonymous,
        'anonymous_to_peers': anonymous_to_peers,
        'commentable_id': commentable_id,
        'course_id': course_key.to_deprecated_string(),
        'user_id': user.id,
        'thread_type': post["thread_type"],
        'body': post["body"],
        'title': post["title"],
    }

    # Check for whether this commentable belongs to a team, and add the right context
    if get_team(commentable_id) is not None:
        params['context'] = ThreadContext.STANDALONE
    else:
        params['context'] = ThreadContext.COURSE

    thread = cc.Thread(**params)

    # Divide the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key,
                                                     commentable_id)
    except ValueError:
        return HttpResponseServerError("Invalid group id for commentable")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    thread_created.send(sender=None, user=user, post=thread)

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        cc_user = cc.User.from_django_user(user)
        cc_user.follow(thread)
        thread_followed.send(sender=None, user=user, post=thread)

    data = thread.to_dict()

    add_courseware_context([data], course, user)

    track_thread_created_event(request, course, thread, follow)

    if thread.get('group_id'):
        # Send a notification message, if enabled, when anyone posts a new thread on
        # a cohorted/private discussion, except the poster him/herself
        _send_discussion_notification(
            'open-edx.lms.discussions.cohorted-thread-added',
            unicode(course_key),
            thread,
            request.user,
            excerpt=_get_excerpt(thread.body),
            recipient_group_id=thread.get('group_id'),
            recipient_exclude_user_ids=[request.user.id],
            is_anonymous_user=anonymous or anonymous_to_peers)

    add_thread_group_name(data, course_key)
    if thread.get('group_id') and not thread.get('group_name'):
        thread['group_name'] = get_cohort_by_id(course_key,
                                                thread.get('group_id')).name

    data = thread.to_dict()

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #23
0
def get_threads(request,
                course,
                discussion_id=None,
                per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.
    """
    default_query_params = {
        'page':
        1,
        'per_page':
        per_page,
        'sort_key':
        'date',
        'sort_order':
        'desc',
        'text':
        '',
        'course_id':
        unicode(course.id),
        'user_id':
        request.user.id,
        'group_id':
        get_group_id_for_comments_service(
            request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be user.default_sort_key because the service returns the default value
        default_query_params['sort_key'] = cc_user.get(
            'default_sort_key') or default_query_params['sort_key']
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(request.GET, [
                'page',
                'sort_key',
                'sort_order',
                'text',
                'commentable_ids',
                'flagged',
                'unread',
                'unanswered',
            ])))

    threads, page, num_pages, corrected_text = cc.Thread.search(query_params)

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(
            utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = page
    query_params['num_pages'] = num_pages
    query_params['corrected_text'] = corrected_text

    return threads, query_params
예제 #24
0
def get_threads(request, course, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong. It may also raise ValueError if the group_id is invalid.
    """
    default_query_params = {
        'page': 1,
        'per_page': per_page,
        'sort_key': 'date',
        'sort_order': 'desc',
        'text': '',
        'course_id': unicode(course.id),
        'commentable_id': discussion_id,
        'user_id': request.user.id,
        'group_id': get_group_id_for_comments_service(request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be user.default_sort_key because the service returns the default value
        default_query_params['sort_key'] = cc_user.get('default_sort_key') or default_query_params['sort_key']
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    #if the user requested a group explicitly, give them that group, otherwise, if mod, show all, else if student, use cohort

    is_cohorted = is_commentable_cohorted(course.id, discussion_id)

    if has_permission(request.user, "see_all_cohorts", course.id):
        group_id = request.GET.get('group_id')
        if group_id in ("all", "None"):
            group_id = None
    else:
        group_id = get_cohort_id(request.user, course.id)
        if not group_id:
            default_query_params['exclude_groups'] = True

    if group_id:
        group_id = int(group_id)
        try:
            CourseUserGroup.objects.get(course_id=course.id, id=group_id)
        except CourseUserGroup.DoesNotExist:
            if not is_cohorted:
                group_id = None
            else:
                raise ValueError("Invalid Group ID")
        default_query_params["group_id"] = group_id

    #so by default, a moderator sees all items, and a student sees his cohort

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(
                request.GET,
                [
                    'page',
                    'sort_key',
                    'sort_order',
                    'text',
                    'commentable_ids',
                    'flagged',
                    'unread',
                    'unanswered',
                ]
            )
        )
    )

    if not is_cohorted:
        query_params.pop('group_id', None)

    threads, page, num_pages, corrected_text = cc.Thread.search(query_params)
    threads = _set_group_names(course.id, threads)

    query_params['page'] = page
    query_params['num_pages'] = num_pages
    query_params['corrected_text'] = corrected_text

    return threads, query_params
예제 #25
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentable ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = CourseKey.from_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST
    user = request.user

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    params = {
        'anonymous': anonymous,
        'anonymous_to_peers': anonymous_to_peers,
        'commentable_id': commentable_id,
        'course_id': text_type(course_key),
        'user_id': user.id,
        'thread_type': post["thread_type"],
        'body': post["body"],
        'title': post["title"],
    }

    # Check for whether this commentable belongs to a team, and add the right context
    if get_team(commentable_id) is not None:
        params['context'] = ThreadContext.STANDALONE
    else:
        params['context'] = ThreadContext.COURSE

    thread = cc.Thread(**params)

    # Divide the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseServerError("Invalid group id for commentable")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    thread_created.send(sender=None, user=user, post=thread)

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        cc_user = cc.User.from_django_user(user)
        cc_user.follow(thread)
        thread_followed.send(sender=None, user=user, post=thread)

    data = thread.to_dict()

    add_courseware_context([data], course, user)

    track_thread_created_event(request, course, thread, follow)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #26
0
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"]
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'

    if follow:
        user = cc.User.from_django_user(request.user)
        user.follow(thread)

    event_data = {
        'title': thread.title,
        'commentable_id': commentable_id,
        'options': {'followed': follow},
        'anonymous': anonymous,
        'thread_type': thread.thread_type,
        'group_id': group_id,
        'anonymous_to_peers': anonymous_to_peers,
        # There is a stated desire for an 'origin' property that will state
        # whether this thread was created via courseware or the forum.
        # However, the view does not contain that data, and including it will
        # likely require changes elsewhere.
    }
    data = thread.to_dict()

    # Calls to id map are expensive, but we need this more than once.
    # Prefetch it.
    id_map = get_discussion_id_map(course, request.user)

    add_courseware_context([data], course, request.user, id_map=id_map)

    track_forum_event(request, 'edx.forum.thread.created',
                      course, thread, event_data, id_map=id_map)

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #27
0
파일: views.py 프로젝트: mreyk/edx-platform
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)
            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
예제 #28
0
파일: views.py 프로젝트: kotky/edx-platform
def create_thread(request, course_id, commentable_id):
    """
    Given a course and commentble ID, create the thread
    """

    log.debug("Creating new thread in %r, id %r", course_id, commentable_id)
    course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id)
    course = get_course_with_access(request.user, 'load', course_key)
    post = request.POST

    if course.allow_anonymous:
        anonymous = post.get('anonymous', 'false').lower() == 'true'
    else:
        anonymous = False

    if course.allow_anonymous_to_peers:
        anonymous_to_peers = post.get('anonymous_to_peers', 'false').lower() == 'true'
    else:
        anonymous_to_peers = False

    if 'title' not in post or not post['title'].strip():
        return JsonError(_("Title can't be empty"))
    if 'body' not in post or not post['body'].strip():
        return JsonError(_("Body can't be empty"))

    thread = cc.Thread(
        anonymous=anonymous,
        anonymous_to_peers=anonymous_to_peers,
        commentable_id=commentable_id,
        course_id=course_key.to_deprecated_string(),
        user_id=request.user.id,
        thread_type=post["thread_type"],
        body=post["body"],
        title=post["title"]
    )

    # Cohort the thread if required
    try:
        group_id = get_group_id_for_comments_service(request, course_key, commentable_id)
    except ValueError:
        return HttpResponseBadRequest("Invalid cohort id")
    if group_id is not None:
        thread.group_id = group_id

    thread.save()

    # patch for backward compatibility to comments service
    if 'pinned' not in thread.attributes:
        thread['pinned'] = False

    follow = post.get('auto_subscribe', 'false').lower() == 'true'
    user = cc.User.from_django_user(request.user)

    if follow:
        user.follow(thread)

    event_data = get_thread_created_event_data(thread, follow)
    data = thread.to_dict()

    # Calls to id map are expensive, but we need this more than once.
    # Prefetch it.
    id_map = get_discussion_id_map(course, request.user)

    add_courseware_context([data], course, request.user, id_map=id_map)

    track_forum_event(request, THREAD_CREATED_EVENT_NAME,
                      course, thread, event_data, id_map=id_map)

    if thread.get('group_id'):
        # Send a notification message, if enabled, when anyone posts a new thread on
        # a cohorted/private discussion, except the poster him/herself
        _send_discussion_notification(
            'open-edx.lms.discussions.cohorted-thread-added',
            unicode(course_key),
            thread,
            request.user,
            excerpt=_get_excerpt(thread.body),
            recipient_group_id=thread.get('group_id'),
            recipient_exclude_user_ids=[request.user.id],
            is_anonymous_user=anonymous or anonymous_to_peers
        )

    # call into the social_engagement django app to
    # rescore this user
    _update_user_engagement_score(course_key, request.user.id)

    add_thread_group_name(data, course_key)
    if thread.get('group_id') and not thread.get('group_name'):
        thread['group_name'] = get_cohort_by_id(course_key, thread.get('group_id')).name

    data = thread.to_dict()

    if request.is_ajax():
        return ajax_content_response(request, course_key, data)
    else:
        return JsonResponse(prepare_content(data, course_key))
예제 #29
0
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
예제 #30
0
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
예제 #31
0
def get_threads(request,
                course,
                user_info,
                discussion_id=None,
                per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.

    Arguments:
        request (WSGIRequest): The user request.
        course (CourseDescriptorWithMixins): The course object.
        user_info (dict): The comment client User object as a dict.
        discussion_id (unicode): Optional discussion id/commentable id for context.
        per_page (int): Optional number of threads per page.

    Returns:
        (tuple of list, dict): A tuple of the list of threads and a dict of the
            query parameters used for the search.

    """
    default_query_params = {
        'page':
        1,
        'per_page':
        per_page,
        'sort_key':
        'activity',
        'text':
        '',
        'course_id':
        unicode(course.id),
        'user_id':
        request.user.id,
        'context':
        ThreadContext.COURSE,
        'group_id':
        get_group_id_for_comments_service(
            request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params['commentable_id'] = discussion_id
        # Use the discussion id/commentable id to determine the context we are going to pass through to the backend.
        if get_team(discussion_id) is not None:
            default_query_params['context'] = ThreadContext.STANDALONE

    if not request.GET.get('sort_key'):
        # If the user did not select a sort key, use their last used sort key
        default_query_params['sort_key'] = user_info.get(
            'default_sort_key') or default_query_params['sort_key']

    elif request.GET.get('sort_key') != user_info.get('default_sort_key'):
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get('sort_key')
        cc_user.save()

    #there are 2 dimensions to consider when executing a search with respect to group id
    #is user a moderator
    #did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(request.GET, [
                'page',
                'sort_key',
                'text',
                'commentable_ids',
                'flagged',
                'unread',
                'unanswered',
            ])))

    paginated_results = cc.Thread.search(query_params)
    threads = paginated_results.collection

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(
            utils.get_discussion_categories_ids(course, request.user))
        threads = [
            thread for thread in threads
            if thread.get('commentable_id') in discussion_category_ids
        ]

    for thread in threads:
        # patch for backward compatibility to comments service
        if 'pinned' not in thread:
            thread['pinned'] = False

    query_params['page'] = paginated_results.page
    query_params['num_pages'] = paginated_results.num_pages
    query_params['corrected_text'] = paginated_results.corrected_text

    return threads, query_params
예제 #32
0
파일: views.py 프로젝트: GbalsaC/bitnamiP
def get_threads(request, course, discussion_id=None, per_page=THREADS_PER_PAGE):
    """
    This may raise an appropriate subclass of cc.utils.CommentClientError
    if something goes wrong, or ValueError if the group_id is invalid.
    """
    default_query_params = {
        "page": 1,
        "per_page": per_page,
        "sort_key": "date",
        "sort_order": "desc",
        "text": "",
        "course_id": unicode(course.id),
        "user_id": request.user.id,
        "group_id": get_group_id_for_comments_service(request, course.id, discussion_id),  # may raise ValueError
    }

    # If provided with a discussion id, filter by discussion id in the
    # comments_service.
    if discussion_id is not None:
        default_query_params["commentable_id"] = discussion_id

    if not request.GET.get("sort_key"):
        # If the user did not select a sort key, use their last used sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.retrieve()
        # TODO: After the comment service is updated this can just be user.default_sort_key because the service returns the default value
        default_query_params["sort_key"] = cc_user.get("default_sort_key") or default_query_params["sort_key"]
    else:
        # If the user clicked a sort key, update their default sort key
        cc_user = cc.User.from_django_user(request.user)
        cc_user.default_sort_key = request.GET.get("sort_key")
        cc_user.save()

    # there are 2 dimensions to consider when executing a search with respect to group id
    # is user a moderator
    # did the user request a group

    query_params = merge_dict(
        default_query_params,
        strip_none(
            extract(
                request.GET,
                ["page", "sort_key", "sort_order", "text", "commentable_ids", "flagged", "unread", "unanswered"],
            )
        ),
    )

    threads, page, num_pages, corrected_text = cc.Thread.search(query_params)

    # If not provided with a discussion id, filter threads by commentable ids
    # which are accessible to the current user.
    if discussion_id is None:
        discussion_category_ids = set(utils.get_discussion_categories_ids(course, request.user))
        threads = [thread for thread in threads if thread.get("commentable_id") in discussion_category_ids]

    for thread in threads:
        # patch for backward compatibility to comments service
        if "pinned" not in thread:
            thread["pinned"] = False

    query_params["page"] = page
    query_params["num_pages"] = num_pages
    query_params["corrected_text"] = corrected_text

    return threads, query_params