def _create_comment(request, course_id, thread_id=None, parent_id=None): """ given a course_id, thread_id, and parent_id, create a comment, called from create_comment to do the actual creation """ post = request.POST comment = cc.Comment(**extract(post, ['body'])) course = get_course_with_access(request.user, course_id, 'load') 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 comment.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': request.user.id, 'course_id': course_id, 'thread_id': thread_id, 'parent_id': parent_id, }) comment.save() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict()) else: return JsonResponse(utils.safe_content(comment.to_dict()))
def update_thread(request, course_id, thread_id, thread_data): """ Given a course id and thread id, update a existing thread, used for both static and ajax submissions """ thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(thread_data, ['body', 'title', 'tags'])) thread.save()
def _create_comment(request, course_id, thread_id=None, parent_id=None): """ given a course_id, thread_id, and parent_id, create a comment, called from create_comment to do the actual creation """ post = request.POST comment = cc.Comment(**extract(post, ['body'])) course = get_course_with_access(request.user, course_id, 'load') 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 comment.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': request.user.id, 'course_id': course_id, 'thread_id': thread_id, 'parent_id': parent_id, }) comment.save() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict(), 'discussion/ajax_create_comment.html') else: return JsonResponse(utils.safe_content(comment.to_dict()))
def mobi_create_comment(request, course_id, thread_id): course_id = course_id.replace('.', '/') if cc_settings.MAX_COMMENT_DEPTH is not None: if cc_settings.MAX_COMMENT_DEPTH < 0: return JsonResponse({ 'success': False, 'errmsg': 'Comment level too deep' }) post = request.POST if 'body' not in post or not post['body'].strip(): return JsonResponse({ "success": False, 'errmsg': 'Body can not be None' }) comment = cc.Comment(**extract(post, ['body'])) try: course = get_course_with_access(request.user, course_id, 'load') except: return JsonResponse({ "success": False, "errmsg": "can not find a course with " + course_id.replace("/", ".") + ' id' }) 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 comment.update_attributes( **{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': request.user.id, 'course_id': course_id, 'thread_id': thread_id, }) comment.save() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) return JsonResponse({"success": True})
def update_thread(request, course_id, thread_id): """ Given a course id and thread id, update a existing thread, used for both static and ajax submissions """ thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(request.POST, ['body', 'title', 'tags'])) thread.save() if request.is_ajax(): return ajax_content_response(request, course_id, thread.to_dict()) else: return JsonResponse(utils.safe_content(thread.to_dict()))
def update_thread(request, course_id, thread_id): """ Given a course id and thread id, update a existing thread, used for both static and ajax submissions """ thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(request.POST, ['body', 'title'])) thread.save() if request.is_ajax(): return ajax_content_response(request, course_id, thread.to_dict()) else: return JsonResponse(utils.safe_content(thread.to_dict()))
def update_comment(request, course_id, comment_id): """ given a course_id and comment_id, update the comment with payload attributes handles static and ajax submissions """ comment = cc.Comment.find(comment_id) comment.update_attributes(**extract(request.POST, ['body'])) comment.save() if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict(), 'discussion/ajax_update_comment.html') else: return JsonResponse(utils.safe_content(comment.to_dict()))
def update_comment(request, course_id, comment_id): """ given a course_id and comment_id, update the comment with payload attributes handles static and ajax submissions """ comment = cc.Comment.find(comment_id) comment.update_attributes(**extract(request.POST, ['body'])) comment.save() if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict()) else: return JsonResponse(utils.safe_content(comment.to_dict()))
def update_comment(request, course_id, comment_id): """ given a course_id and comment_id, update the comment with payload attributes handles static and ajax submissions """ comment = cc.Comment.find(comment_id) if 'body' not in request.POST or not request.POST['body'].strip(): return JsonError(_("Body can't be empty")) comment.update_attributes(**filterdict(extract(request.POST, ['body']))) comment.save() if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict()) else: return JsonResponse(utils.safe_content(comment.to_dict()))
def update_comment(request, course_id, comment_id): """ given a course_id and comment_id, update the comment with payload attributes handles static and ajax submissions """ comment = cc.Comment.find(comment_id) if 'body' not in request.POST or not request.POST['body'].strip(): return JsonError(_("Body can't be empty")) comment.update_attributes(**extract(request.POST, ['body'])) comment.save() if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict()) else: return JsonResponse(utils.safe_content(comment.to_dict()))
def update_thread(request, course_id, thread_id): """ Given a course id and thread id, update a existing thread, used for both static and ajax submissions """ if 'title' not in request.POST or not request.POST['title'].strip(): return JsonError(_("Title can't be empty")) if 'body' not in request.POST or not request.POST['body'].strip(): return JsonError(_("Body can't be empty")) thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(request.POST, ['body', 'title'])) thread.save() if request.is_ajax(): return ajax_content_response(request, course_id, thread.to_dict()) else: return JsonResponse(utils.safe_content(thread.to_dict()))
def mobi_create_comment(request, course_id, thread_id): course_id = course_id.replace('.', '/') if cc_settings.MAX_COMMENT_DEPTH is not None: if cc_settings.MAX_COMMENT_DEPTH < 0: return JsonResponse({'success': False, 'errmsg': 'Comment level too deep'}) post = request.POST if 'body' not in post or not post['body'].strip(): return JsonResponse({"success": False, 'errmsg': 'Body can not be None'}) comment = cc.Comment(**extract(post, ['body'])) try: course = get_course_with_access(request.user, course_id, 'load') except: return JsonResponse({"success": False, "errmsg": "can not find a course with " + course_id.replace("/", ".") + ' id'}) 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 comment.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': request.user.id, 'course_id': course_id, 'thread_id': thread_id, }) comment.save() if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) return JsonResponse({"success": True})
def _create_comment(request, course_id, thread_id=None, parent_id=None): """ given a course_id, thread_id, and parent_id, create a comment, called from create_comment to do the actual creation """ post = request.POST if "body" not in post or not post["body"].strip(): return JsonError(_("Body can't be empty")) comment = cc.Comment(**extract(post, ["body"])) course = get_course_with_access(request.user, course_id, "load") 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 comment.update_attributes( **{ "anonymous": anonymous, "anonymous_to_peers": anonymous_to_peers, "user_id": request.user.id, "course_id": course_id, "thread_id": thread_id, "parent_id": parent_id, } ) comment.save() if post.get("auto_subscribe", "false").lower() == "true": user = cc.User.from_django_user(request.user) user.follow(comment.thread) if request.is_ajax(): return ajax_content_response(request, course_id, comment.to_dict()) else: return JsonResponse(utils.safe_content(comment.to_dict()))
def create_comment(request, course_id, comment_data, portfolio_user, thread_id=None, parent_id=None): """ given a course_id, thread_id, and parent_id, create a comment, called from create_comment to do the actual creation """ comment = cc.Comment(**extract(comment_data, ['body'])) course = get_course_with_access(portfolio_user, course_id, 'load') anonymous = False anonymous_to_peers = False comment.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': portfolio_user.id, 'course_id': course_id, 'thread_id': thread_id, 'parent_id': parent_id, }) comment.save() user = cc.User.from_django_user(portfolio_user) user.follow(comment.thread)
def create_comment_auto(request, course_id, thread_id=None, parent_id=None): """ given a course_id, thread_id, and parent_id, create a comment, called from create_comment to do the actual creation """ #post = request.POST comment_data={"body":"Let's discuss!"} comment = cc.Comment(**extract(comment_data, ['body'])) course = get_course_with_access(request.user, course_id, 'load') ''' 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 ''' anonymous = False anonymous_to_peers = False comment.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'user_id': request.user.id, 'course_id': course_id, 'thread_id': thread_id, 'parent_id': parent_id, }) comment.save() ''' if post.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(comment.thread) ''' user = cc.User.from_django_user(request.user) user.follow(comment.thread)
def update_thread(request, course_id, thread_id): """ Given a course id and thread id, update a existing thread, used for both static and ajax submissions """ thread = cc.Thread.find(thread_id) thread.update_attributes(**extract(request.POST, ['body', 'title', 'tags'])) thread.update_attributes(**{ 'tags':'default', }) thread.save() course = get_course_with_access(request.user, course_id, 'load') courseware_context = get_courseware_context(thread, course) if courseware_context: if str(courseware_context.get('courseware_url')).find('__am')>0: thread.update_attributes(**{ 'tags':'aboutme', }) thread.save() if request.is_ajax(): return ajax_content_response(request, course_id, thread.to_dict(), 'discussion/ajax_update_thread.html') else: return JsonResponse(utils.safe_content(thread.to_dict()))
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
def create_thread(request, course_id, commentable_id, thread_data): """ Given a course and commentble ID, create the thread """ course = get_course_with_access(request.user, course_id, 'load') if course.allow_anonymous: anonymous = thread_data.get('anonymous', 'false').lower() == 'true' else: anonymous = False if course.allow_anonymous_to_peers: anonymous_to_peers = thread_data.get('anonymous_to_peers', 'false').lower() == 'true' else: anonymous_to_peers = False thread = cc.Thread(**extract(thread_data, ['body', 'title', 'tags'])) thread.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'commentable_id': commentable_id, 'course_id': course_id, 'user_id': request.user.id, }) user = cc.User.from_django_user(request.user) #kevinchugh because the new requirement is that all groups will be determined #by the group id in the request this all goes away #not anymore, only for admins # Cohort the thread if the commentable is cohorted. if is_commentable_cohorted(course_id, commentable_id): user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as group_id = thread_data.get('group_id', user_group_id) else: # regular users always post with their own id. group_id = user_group_id if group_id: thread.update_attributes(group_id=group_id) thread.save() #patch for backward compatibility to comments service if not 'pinned' in thread.attributes: thread['pinned'] = False if thread_data.get('auto_subscribe', 'false').lower() == 'true': user = cc.User.from_django_user(request.user) user.follow(thread) courseware_context = get_courseware_context(thread, course) data = thread.to_dict() if courseware_context: data.update(courseware_context) return ajax_content_response(request, course_id, data, 'discussion/ajax_create_thread.html') '''
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
def followed_threads(request, course_id, user_id): course_key = SlashSeparatedCourseKey.from_deprecated_string(course_id) nr_transaction = newrelic.agent.current_transaction() course = get_course_with_access(request.user, 'load_forum', course_key) try: profiled_user = cc.User(id=user_id, course_id=course_key) default_query_params = { 'page': 1, 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': 'date', 'sort_order': 'desc', } query_params = merge_dict( default_query_params, strip_none( extract(request.GET, [ 'page', 'sort_key', 'sort_order', 'flagged', 'unread', 'unanswered', ]))) try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseBadRequest("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id threads, page, num_pages = profiled_user.subscribed_threads( query_params) query_params['page'] = page query_params['num_pages'] = num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, threads, request.user, user_info) if request.is_ajax(): is_staff = cached_has_permission(request.user, 'openclose_thread', course.id) return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': [ utils.prepare_content(thread, course_key, is_staff) for thread in threads ], 'page': query_params['page'], 'num_pages': query_params['num_pages'], }) #TODO remove non-AJAX support, it does not appear to be used and does not appear to work. else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': _attr_safe_json(threads), 'user_info': _attr_safe_json(user_info), 'annotated_content_info': _attr_safe_json(annotated_content_info), # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def 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 = get_course_with_access(request.user, course_id, 'load') 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(**extract(post, ['body', 'title'])) thread.update_attributes( **{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'commentable_id': commentable_id, 'course_id': course_id, 'user_id': request.user.id, }) user = cc.User.from_django_user(request.user) #kevinchugh because the new requirement is that all groups will be determined #by the group id in the request this all goes away #not anymore, only for admins # Cohort the thread if the commentable is cohorted. if is_commentable_cohorted(course_id, commentable_id): user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as group_id = post.get('group_id', user_group_id) else: # regular users always post with their own id. group_id = user_group_id if group_id: thread.update_attributes(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_courseware_context([data], course) if request.is_ajax(): return ajax_content_response(request, course_id, data) else: return JsonResponse(utils.safe_content(data))
def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAGE): """ This may raise an appropriate subclass of cc.utils.CommentClientError if something goes wrong. """ default_query_params = { 'page': 1, 'per_page': per_page, 'sort_key': 'date', 'sort_order': 'desc', 'text': '', 'commentable_id': discussion_id, 'course_id': course_id, 'user_id': request.user.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, othewrise, if mod, show all, else if student, use cohort group_id = request.GET.get('group_id') if group_id == "all": group_id = None if not group_id: if not cached_has_permission(request.user, "see_all_cohorts", course_id): group_id = get_cohort_id(request.user, course_id) if 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']))) threads, page, num_pages = cc.Thread.search(query_params) #now add the group name if the thread has a group id for thread in threads: if thread.get('group_id'): thread['group_name'] = get_cohort_by_id(course_id, thread.get('group_id')).name thread['group_string'] = "This post visible only to Group %s." % (thread['group_name']) else: thread['group_name'] = "" thread['group_string'] = "This post visible to everyone." #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 return threads, query_params
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
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
def followed_threads(request, course_key, user_id): """ Ajax-only endpoint retrieving the threads followed by a specific user. """ course = get_course_with_access(request.user, 'load_forum', course_key, check_if_enrolled=True) try: profiled_user = cc.User(id=user_id, course_id=course_key) default_query_params = { 'page': 1, 'per_page': THREADS_PER_PAGE, # more than threads_per_page to show more activities 'sort_key': 'date', } query_params = merge_dict( default_query_params, strip_none( extract(request.GET, [ 'page', 'sort_key', 'flagged', 'unread', 'unanswered', ]))) try: group_id = get_group_id_for_comments_service(request, course_key) except ValueError: return HttpResponseServerError("Invalid group_id") if group_id is not None: query_params['group_id'] = group_id paginated_results = profiled_user.subscribed_threads(query_params) print "\n \n \n paginated results \n \n \n " print paginated_results query_params['page'] = paginated_results.page query_params['num_pages'] = paginated_results.num_pages user_info = cc.User.from_django_user(request.user).to_dict() with newrelic_function_trace("get_metadata_for_threads"): annotated_content_info = utils.get_metadata_for_threads( course_key, paginated_results.collection, request.user, user_info) if request.is_ajax(): is_staff = has_permission(request.user, 'openclose_thread', course.id) return utils.JsonResponse({ 'annotated_content_info': annotated_content_info, 'discussion_data': [ utils.prepare_content(thread, course_key, is_staff) for thread in paginated_results.collection ], 'page': query_params['page'], 'num_pages': query_params['num_pages'], }) #TODO remove non-AJAX support, it does not appear to be used and does not appear to work. else: context = { 'course': course, 'user': request.user, 'django_user': User.objects.get(id=user_id), 'profiled_user': profiled_user.to_dict(), 'threads': paginated_results.collection, 'user_info': user_info, 'annotated_content_info': annotated_content_info, # 'content': content, } return render_to_response('discussion/user_profile.html', context) except User.DoesNotExist: raise Http404
def 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
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
def get_threads(request, course_id, discussion_id=None, per_page=THREADS_PER_PAGE): """ This may raise an appropriate subclass of cc.utils.CommentClientError if something goes wrong. """ default_query_params = { 'page': 1, 'per_page': per_page, 'sort_key': 'date', 'sort_order': 'desc', 'text': '', 'commentable_id': discussion_id, 'course_id': course_id, 'user_id': request.user.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, othewrise, if mod, show all, else if student, use cohort group_id = request.GET.get('group_id') if group_id == "all": group_id = None if not group_id: if not cached_has_permission(request.user, "see_all_cohorts", course_id): group_id = get_cohort_id(request.user, course_id) if 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' ]))) threads, page, num_pages = cc.Thread.search(query_params) #now add the group name if the thread has a group id for thread in threads: if thread.get('group_id'): thread['group_name'] = get_cohort_by_id( course_id, thread.get('group_id')).name thread['group_string'] = "This post visible only to Group %s." % ( thread['group_name']) else: thread['group_name'] = "" thread['group_string'] = "This post visible to everyone." #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 return threads, query_params
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
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 = get_course_with_access(request.user, course_id, 'load') 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(**extract(post, ['body', 'title'])) thread.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'commentable_id': commentable_id, 'course_id': course_id, 'user_id': request.user.id, }) user = cc.User.from_django_user(request.user) #kevinchugh because the new requirement is that all groups will be determined #by the group id in the request this all goes away #not anymore, only for admins # Cohort the thread if the commentable is cohorted. if is_commentable_cohorted(course_id, commentable_id): user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as group_id = post.get('group_id', user_group_id) else: # regular users always post with their own id. group_id = user_group_id if group_id: thread.update_attributes(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_courseware_context([data], course) if request.is_ajax(): return ajax_content_response(request, course_id, data) else: return JsonResponse(utils.safe_content(data))
def mobi_create_thread(request, course_id, topic_id): """ Given a course and commentable_id from mobile. create the thread """ course_id = course_id.replace('.', '/') log.debug("Creating new thread in %r, id %r", course_id, topic_id) course = get_course_with_access(request.user, course_id, 'load') 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 JsonResponse({'success': False, 'errmsg': "Title can't be empty"}) if 'body' not in post or not post['body'].strip(): return JsonResponse({'success': False, 'errmsg': "Body can't be empty"}) thread = cc.Thread(**extract(post, ['body', 'title'])) user = cc.User.from_django_user(request.user) thread.update_attributes(**{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'commentable_id': topic_id, 'course_id': course_id, 'user_id': request.user.id, }) if is_commentable_cohorted(course_id, topic_id): user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as group_id = post.get('group_id', user_group_id) else: # regular users always post with their own id. group_id = user_group_id if group_id: thread.update_attributes(group_id=group_id) thread.save() 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) return JsonResponse({"success": True})
def test_extract(self): d = {'cats': 'meow', 'dogs': 'woof'} k = ['cats', 'dogs', 'hamsters'] expected = {'cats': 'meow', 'dogs': 'woof', 'hamsters': None} self.assertEqual(utils.extract(d, k), expected)
def mobi_create_thread(request, course_id, topic_id): """ Given a course and commentable_id from mobile. create the thread """ course_id = course_id.replace('.', '/') log.debug("Creating new thread in %r, id %r", course_id, topic_id) course = get_course_with_access(request.user, course_id, 'load') 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 JsonResponse({ 'success': False, 'errmsg': "Title can't be empty" }) if 'body' not in post or not post['body'].strip(): return JsonResponse({ 'success': False, 'errmsg': "Body can't be empty" }) thread = cc.Thread(**extract(post, ['body', 'title'])) user = cc.User.from_django_user(request.user) thread.update_attributes( **{ 'anonymous': anonymous, 'anonymous_to_peers': anonymous_to_peers, 'commentable_id': topic_id, 'course_id': course_id, 'user_id': request.user.id, }) if is_commentable_cohorted(course_id, topic_id): user_group_id = get_cohort_id(user, course_id) # TODO (vshnayder): once we have more than just cohorts, we'll want to # change this to a single get_group_for_user_and_commentable function # that can do different things depending on the commentable_id if cached_has_permission(request.user, "see_all_cohorts", course_id): # admins can optionally choose what group to post as group_id = post.get('group_id', user_group_id) else: # regular users always post with their own id. group_id = user_group_id if group_id: thread.update_attributes(group_id=group_id) thread.save() 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) return JsonResponse({"success": True})
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
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
def test_extract(self): d = {"cats": "meow", "dogs": "woof"} k = ["cats", "dogs", "hamsters"] expected = {"cats": "meow", "dogs": "woof", "hamsters": None} self.assertEqual(utils.extract(d, k), expected)
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
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
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
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