reply now works again
This commit is contained in:
@@ -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()
|
||||
|
||||
44
lms/lib/comment_client/comment.py
Normal file
44
lms/lib/comment_client/comment.py
Normal file
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
9
lms/lib/comment_client/commentable.py
Normal file
9
lms/lib/comment_client/commentable.py
Normal file
@@ -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'
|
||||
@@ -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()
|
||||
|
||||
3
lms/lib/comment_client/settings.py
Normal file
3
lms/lib/comment_client/settings.py
Normal file
@@ -0,0 +1,3 @@
|
||||
SERVICE_HOST = 'http://localhost:4567'
|
||||
|
||||
PREFIX = SERVICE_HOST + '/api/v1'
|
||||
62
lms/lib/comment_client/thread.py
Normal file
62
lms/lib/comment_client/thread.py
Normal file
@@ -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)
|
||||
61
lms/lib/comment_client/user.py
Normal file
61
lms/lib/comment_client/user.py
Normal file
@@ -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)
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user