From 38bdcabe53778f71dca2778987e7aed7259d5fde Mon Sep 17 00:00:00 2001 From: Rocky Duan Date: Mon, 13 Aug 2012 23:23:13 -0700 Subject: [PATCH] reply now works again --- .../django_comment_client/base/views.py | 1 + lms/lib/comment_client/comment.py | 44 ++++++ lms/lib/comment_client/comment_client.py | 137 +----------------- lms/lib/comment_client/commentable.py | 9 ++ lms/lib/comment_client/models.py | 37 +++-- lms/lib/comment_client/settings.py | 3 + lms/lib/comment_client/thread.py | 62 ++++++++ lms/lib/comment_client/user.py | 61 ++++++++ lms/lib/comment_client/utils.py | 5 +- .../coffee/src/discussion/content.coffee | 2 +- .../coffee/src/discussion/discussion.coffee | 9 +- lms/static/sass/_discussion.scss | 2 +- 12 files changed, 220 insertions(+), 152 deletions(-) create mode 100644 lms/lib/comment_client/comment.py create mode 100644 lms/lib/comment_client/commentable.py create mode 100644 lms/lib/comment_client/settings.py create mode 100644 lms/lib/comment_client/thread.py create mode 100644 lms/lib/comment_client/user.py diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index efb9d84b88..0890ccac0e 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -47,6 +47,7 @@ def create_thread(request, course_id, commentable_id): post = request.POST thread = cc.Thread(**extract(post, ['body', 'title', 'tags'])) thread.anonymous = post.get('anonymous', 'false').lower() == 'true' + thread.commentable_id = commentable_id thread.course_id = course_id thread.user_id = request.user.id thread.save() diff --git a/lms/lib/comment_client/comment.py b/lms/lib/comment_client/comment.py new file mode 100644 index 0000000000..7e560a638d --- /dev/null +++ b/lms/lib/comment_client/comment.py @@ -0,0 +1,44 @@ +from utils import * + +import models +import settings + +class Comment(models.Model): + + accessible_fields = [ + 'id', 'body', 'anonymous', 'course_id', + 'endorsed', 'parent_id', 'thread_id', + 'username', 'votes', 'user_id', 'closed', + 'created_at', 'updated_at', 'depth', + 'at_position_list', + ] + + updatable_fields = [ + 'body', 'anonymous', 'course_id', 'closed', + 'user_id', 'endorsed', + ] + + initializable_fields = updatable_fields + + base_url = "{prefix}/comments".format(prefix=settings.PREFIX) + type = 'comment' + + @classmethod + def url_for_comments(cls, params={}): + if params.get('thread_id'): + return _url_for_thread_comments(params['thread_id']) + else: + return _url_for_comment(params['parent_id']) + + @classmethod + def url(cls, action, params={}): + if action in ['post']: + return cls.url_for_comments(params) + else: + return super(Comment, cls).url(action, params) + +def _url_for_thread_comments(thread_id): + return "{prefix}/threads/{thread_id}/comments".format(prefix=settings.PREFIX, thread_id=thread_id) + +def _url_for_comment(comment_id): + return "{prefix}/comments/{comment_id}".format(prefix=settings.PREFIX, comment_id=comment_id) diff --git a/lms/lib/comment_client/comment_client.py b/lms/lib/comment_client/comment_client.py index d8d4f68f3b..5ee2b9c68e 100644 --- a/lms/lib/comment_client/comment_client.py +++ b/lms/lib/comment_client/comment_client.py @@ -1,123 +1,11 @@ -import requests -import json -import models +from comment import Comment +from thread import Thread +from user import User +from commentable import Commentable from utils import * -SERVICE_HOST = 'http://localhost:4567' - -PREFIX = SERVICE_HOST + '/api/v1' - -class Comment(models.Model): - accessible_fields = [ - 'id', 'body', 'anonymous', 'course_id', - 'endorsed', 'parent_id', 'thread_id', - 'username', 'votes', 'user_id', 'closed', - 'created_at', 'updated_at', 'depth', - 'at_position_list', - ] - base_url = "{prefix}/comments".format(prefix=PREFIX) - type = 'comment' - - -class Thread(models.Model): - accessible_fields = [ - 'id', 'title', 'body', 'anonymous', - 'course_id', 'closed', 'tags', 'votes', - 'commentable_id', 'username', 'user_id', - 'created_at', 'updated_at', 'comments_count', - 'at_position_list', 'children', - ] - base_url = "{prefix}/threads".format(prefix=PREFIX) - default_retrieve_params = {'recursive': False} - type = 'thread' - - @classmethod - def search(cls, query_params, *args, **kwargs): - default_params = {'page': 1, - 'per_page': 20, - 'course_id': query_params['course_id'], - 'recursive': False} - params = merge_dict(default_params, strip_none(query_params)) - if query_params['text'] or query_params['tags']: - url = cls.url(action='search') - else: - url = cls.url(action='get_all', commentable_id=params['commentable_id']) - del params['commentable_id'] - response = perform_request('get', url, params, *args, **kwargs) - return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1) - - @classmethod - def url_for_threads(cls, *args, **kwargs): - return "{prefix}/{commentable_id}/threads".format(prefix=PREFIX, commentable_id=kwargs.get('commentable_id')) - - @classmethod - def url_for_search_threads(cls, *args, **kwargs): - return "{prefix}/search/threads".format(prefix=PREFIX) - - @classmethod - def url(cls, *args, **kwargs): - action = kwargs.get('action') - if action in ['get_all', 'post']: - return cls.url_for_threads(commentable_id=kwargs.get('commentable_id')) - elif action == 'search': - return cls.url_for_search_threads() - else: - return super(Thread, cls).url(*args, **kwargs) - - def _retrieve(self, *args, **kwargs): - url = self.url(action='get', id=self.id) - response = perform_request('get', url, {'recursive': kwargs.get('recursive')}) - self.update_attributes(**response) - -class Commentable(models.Model): - - base_url = "{prefix}/commentables".format(prefix=PREFIX) - type = 'commentable' - -class User(models.Model): - - accessible_fields = ['username', 'follower_ids', 'upvoted_ids', 'downvoted_ids', - 'id', 'external_id', 'subscribed_user_ids', 'children', - 'subscribed_thread_ids', 'subscribed_commentable_ids', - ] - base_url = "{prefix}/users".format(prefix=PREFIX) - default_retrieve_params = {'complete': True} - type = 'user' - - @classmethod - def from_django_user(cls, user): - return cls(id=str(user.id)) - - def follow(self, source): - params = {'source_type': source.type, 'source_id': source.id} - response = perform_request('post', _url_for_subscription(self.id), params) - - def unfollow(self, source): - params = {'source_type': source.type, 'source_id': source.id} - response = perform_request('delete', _url_for_subscription(self.id), params) - - def vote(self, voteable, value): - if voteable.type == 'thread': - url = _url_for_vote_thread(voteable.id) - elif voteable.type == 'comment': - url = _url_for_vote_comment(voteable.id) - else: - raise CommentClientError("Can only vote / unvote for threads or comments") - params = {'user_id': self.id, 'value': value} - request = perform_request('put', url, params) - voteable.update_attributes(request) - - def unvote(self, voteable): - if voteable.type == 'thread': - url = _url_for_vote_thread(voteable.id) - elif voteable.type == 'comment': - url = _url_for_vote_comment(voteable.id) - else: - raise CommentClientError("Can only vote / unvote for threads or comments") - params = {'user_id': self.id} - request = perform_request('delete', url, params) - voteable.update_attributes(request) +import settings def search_similar_threads(course_id, recursive=False, query_params={}, *args, **kwargs): default_params = {'course_id': course_id, 'recursive': recursive} @@ -135,19 +23,10 @@ def search_trending_tags(course_id, query_params={}, *args, **kwargs): return perform_request('get', _url_for_search_trending_tags(), attributes, *args, **kwargs) def _url_for_search_similar_threads(): - return "{prefix}/search/threads/more_like_this".format(prefix=PREFIX) + return "{prefix}/search/threads/more_like_this".format(prefix=settings.PREFIX) def _url_for_search_recent_active_threads(): - return "{prefix}/search/threads/recent_active".format(prefix=PREFIX) + return "{prefix}/search/threads/recent_active".format(prefix=settings.PREFIX) def _url_for_search_trending_tags(): - return "{prefix}/search/tags/trending".format(prefix=PREFIX) - -def _url_for_subscription(user_id): - return "{prefix}/users/{user_id}/subscriptions".format(prefix=PREFIX, user_id=user_id) - -def _url_for_vote_comment(comment_id): - return "{prefix}/comments/{comment_id}/votes".format(prefix=PREFIX, comment_id=comment_id) - -def _url_for_vote_thread(thread_id): - return "{prefix}/threads/{thread_id}/votes".format(prefix=PREFIX, thread_id=thread_id) + return "{prefix}/search/tags/trending".format(prefix=settings.PREFIX) diff --git a/lms/lib/comment_client/commentable.py b/lms/lib/comment_client/commentable.py new file mode 100644 index 0000000000..8f91bfc93d --- /dev/null +++ b/lms/lib/comment_client/commentable.py @@ -0,0 +1,9 @@ +from utils import * + +import models +import settings + +class Commentable(models.Model): + + base_url = "{prefix}/commentables".format(prefix=settings.PREFIX) + type = 'commentable' diff --git a/lms/lib/comment_client/models.py b/lms/lib/comment_client/models.py index 8d1349040f..414dd0ced1 100644 --- a/lms/lib/comment_client/models.py +++ b/lms/lib/comment_client/models.py @@ -3,6 +3,8 @@ from utils import * class Model(object): accessible_fields = ['id'] + updatable_fields = ['id'] + initializable_fields = ['id'] base_url = None default_retrieve_params = {} @@ -55,7 +57,7 @@ class Model(object): return self def _retrieve(self, *args, **kwargs): - url = self.url(action='get', id=self.id) + url = self.url(action='get', params=self.attributes) response = perform_request('get', url, self.default_retrieve_params) self.update_attributes(**response) @@ -69,38 +71,41 @@ class Model(object): self.__setattr__(k, v) else: raise AttributeError("Field {0} does not exist".format(k)) + + def updatable_attribtes(self): + return extract(self.attributes, self.updatable_fields) + + def initializable_attributes(self): + return extract(self.attributes, self.initializable_fields) def save(self): if self.id: # if we have id already, treat this as an update - url = self.url(action='put', id=self.id) - response = perform_request('put', url, self.attributes) + url = self.url(action='put', params=self.attributes) + response = perform_request('put', url, self.updatable_attributes()) else: # otherwise, treat this as an insert - url = self.url(action='post', id=self.id) - response = perform_request('post', url, self.attributes) + url = self.url(action='post', params=self.attributes) + response = perform_request('post', url, self.initializable_attributes()) self.retrieved = True self.update_attributes(**response) @classmethod - def url_with_id(cls, *args, **kwargs): - return cls.base_url + '/' + str(kwargs.get('id')) + def url_with_id(cls, params={}): + return cls.base_url + '/' + str(params['id']) @classmethod - def url_without_id(cls, *args, **kwargs): + def url_without_id(cls, params={}): return cls.base_url @classmethod - def url(cls, *args, **kwargs): + def url(cls, action, params={}): if cls.base_url is None: raise CommentClientError("Must provide base_url when using default url function") - id = kwargs.get('id') - action = kwargs.get('action') - if not action: - raise CommentClientError("Must provide action") - elif action not in cls.DEFAULT_ACTIONS: + if action not in cls.DEFAULT_ACTIONS: raise ValueError("Invalid action {0}. The supported action must be in {1}".format(action, str(cls.DEFAULT_ACTIONS))) elif action in cls.DEFAULT_ACTIONS_WITH_ID: - if not id: + try: + return cls.url_with_id(params) + except KeyError: raise CommentClientError("Cannot perform action {0} without id".format(action)) - return cls.url_with_id(id=id) else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now return cls.url_without_id() diff --git a/lms/lib/comment_client/settings.py b/lms/lib/comment_client/settings.py new file mode 100644 index 0000000000..df896204ce --- /dev/null +++ b/lms/lib/comment_client/settings.py @@ -0,0 +1,3 @@ +SERVICE_HOST = 'http://localhost:4567' + +PREFIX = SERVICE_HOST + '/api/v1' diff --git a/lms/lib/comment_client/thread.py b/lms/lib/comment_client/thread.py new file mode 100644 index 0000000000..510432e2f9 --- /dev/null +++ b/lms/lib/comment_client/thread.py @@ -0,0 +1,62 @@ +from utils import * + +import models +import settings + +class Thread(models.Model): + + accessible_fields = [ + 'id', 'title', 'body', 'anonymous', + 'course_id', 'closed', 'tags', 'votes', + 'commentable_id', 'username', 'user_id', + 'created_at', 'updated_at', 'comments_count', + 'at_position_list', 'children', + ] + + updatable_fields = [ + 'title', 'body', 'anonymous', 'course_id', + 'closed', 'tags', 'user_id', 'commentable_id', + ] + + initializable_fields = updatable_fields + + base_url = "{prefix}/threads".format(prefix=settings.PREFIX) + default_retrieve_params = {'recursive': False} + type = 'thread' + + @classmethod + def search(cls, query_params, *args, **kwargs): + default_params = {'page': 1, + 'per_page': 20, + 'course_id': query_params['course_id'], + 'recursive': False} + params = merge_dict(default_params, strip_none(query_params)) + if query_params['text'] or query_params['tags']: + url = cls.url(action='search') + else: + url = cls.url(action='get_all', params=extract(params, 'commentable_id')) + del params['commentable_id'] + response = perform_request('get', url, params, *args, **kwargs) + return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1) + + @classmethod + def url_for_threads(cls, params={}): + return "{prefix}/{commentable_id}/threads".format(prefix=settings.PREFIX, commentable_id=params['commentable_id']) + + @classmethod + def url_for_search_threads(cls, params={}): + return "{prefix}/search/threads".format(prefix=settings.PREFIX) + + @classmethod + def url(cls, action, params={}): + if action in ['get_all', 'post']: + return cls.url_for_threads(params) + elif action == 'search': + return cls.url_for_search_threads(params) + else: + return super(Thread, cls).url(action, params) + + def _retrieve(self, *args, **kwargs): + url = self.url(action='get', params=self.attributes) + response = perform_request('get', url, {'recursive': kwargs.get('recursive')}) + self.update_attributes(**response) diff --git a/lms/lib/comment_client/user.py b/lms/lib/comment_client/user.py new file mode 100644 index 0000000000..e26528f363 --- /dev/null +++ b/lms/lib/comment_client/user.py @@ -0,0 +1,61 @@ +from utils import * + +import models +import settings + +class User(models.Model): + + accessible_fields = ['username', 'email', 'follower_ids', 'upvoted_ids', 'downvoted_ids', + 'id', 'external_id', 'subscribed_user_ids', 'children', + 'subscribed_thread_ids', 'subscribed_commentable_ids', + ] + + updatable_fields = ['username', 'external_id', 'email'] + initializable_fields = updatable_fields + + base_url = "{prefix}/users".format(prefix=settings.PREFIX) + default_retrieve_params = {'complete': True} + type = 'user' + + @classmethod + def from_django_user(cls, user): + return cls(id=str(user.id)) + + def follow(self, source): + params = {'source_type': source.type, 'source_id': source.id} + response = perform_request('post', _url_for_subscription(self.id), params) + + def unfollow(self, source): + params = {'source_type': source.type, 'source_id': source.id} + response = perform_request('delete', _url_for_subscription(self.id), params) + + def vote(self, voteable, value): + if voteable.type == 'thread': + url = _url_for_vote_thread(voteable.id) + elif voteable.type == 'comment': + url = _url_for_vote_comment(voteable.id) + else: + raise CommentClientError("Can only vote / unvote for threads or comments") + params = {'user_id': self.id, 'value': value} + request = perform_request('put', url, params) + voteable.update_attributes(request) + + def unvote(self, voteable): + if voteable.type == 'thread': + url = _url_for_vote_thread(voteable.id) + elif voteable.type == 'comment': + url = _url_for_vote_comment(voteable.id) + else: + raise CommentClientError("Can only vote / unvote for threads or comments") + params = {'user_id': self.id} + request = perform_request('delete', url, params) + voteable.update_attributes(request) + +def _url_for_vote_comment(comment_id): + return "{prefix}/comments/{comment_id}/votes".format(prefix=settings.PREFIX, comment_id=comment_id) + +def _url_for_vote_thread(thread_id): + return "{prefix}/threads/{thread_id}/votes".format(prefix=settings.PREFIX, thread_id=thread_id) + +def _url_for_subscription(user_id): + return "{prefix}/users/{user_id}/subscriptions".format(prefix=settings.PREFIX, user_id=user_id) diff --git a/lms/lib/comment_client/utils.py b/lms/lib/comment_client/utils.py index c3ad4b612e..7e696bb99d 100644 --- a/lms/lib/comment_client/utils.py +++ b/lms/lib/comment_client/utils.py @@ -7,7 +7,10 @@ def strip_none(dic): return dict([(k, v) for k, v in dic.iteritems() if not _is_none(v)]) def extract(dic, keys): - return strip_none({k: dic.get(k) for k in keys}) + if isinstance(keys, str): + return strip_none({keys: dic.get(keys)}) + else: + return strip_none({k: dic.get(k) for k in keys}) def merge_dict(dic1, dic2): return dict(dic1.items() + dic2.items()) diff --git a/lms/static/coffee/src/discussion/content.coffee b/lms/static/coffee/src/discussion/content.coffee index c8a54775e6..06f7b9f03d 100644 --- a/lms/static/coffee/src/discussion/content.coffee +++ b/lms/static/coffee/src/discussion/content.coffee @@ -281,7 +281,7 @@ initializeFollowThread = (thread) -> type: "GET" dataType: 'json' success: (response, textStatus) -> - Discussion.extendContentInfo response.content['id'], response['annotated_content_info'] + Discussion.bulkExtendContentInfo response['annotated_content_info'] $content.append(response['html']) $content.find(".comment").each (index, comment) -> Discussion.initializeContent(comment) diff --git a/lms/static/coffee/src/discussion/discussion.coffee b/lms/static/coffee/src/discussion/discussion.coffee index 4d502c85d7..c7e3e5ab8d 100644 --- a/lms/static/coffee/src/discussion/discussion.coffee +++ b/lms/static/coffee/src/discussion/discussion.coffee @@ -93,7 +93,7 @@ initializeFollowDiscussion = (discussion) -> $wrapper.hide() $title.attr("prev-text", text) - initializeNewPost = (elem) -> + initializeNewPost = -> #newPostForm = $local(".new-post-form") #$newPostButton = $local(".discussion-new-post") view = { discussion_id: id } @@ -104,9 +104,10 @@ initializeFollowDiscussion = (discussion) -> if newPostBody.length Discussion.makeWmdEditor $discussion, $local, "new-post-body" - $input = Discussion.getWmdInput($discussion, $local, "new-post-body") - $input.attr("placeholder", "post a new topic...").bind 'focus', (e) -> - $local(".new-post-form").removeClass('collapsed') + $input = Discussion.getWmdInput($discussion, $local, "new-post-body") + $input.attr("placeholder", "post a new topic...").bind 'focus', (e) -> + console.log "triggered" + $local(".new-post-form").removeClass('collapsed') $local(".new-post-tags").tagsInput Discussion.tagsInputOptions() diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 510c0ef2c0..21e0638316 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -573,7 +573,7 @@ $tag-text-color: #5b614f; display: block !important; font: inherit; font-style: normal; - width: $discussion-input-width !important; + //width: $discussion-input-width !important; } .discussion-errors {