From 00a6526fd098842a1c958f9e9debea9530b84c41 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Wed, 5 Sep 2012 17:58:18 -0700 Subject: [PATCH 01/19] Make voting render properly in inline discussions. Also might have fixed following if it wasn't working before. --- .../django_comment_client/base/views.py | 15 ++++++------- .../django_comment_client/forum/views.py | 6 +++++ lms/djangoapps/django_comment_client/utils.py | 22 +++++++++---------- .../src/discussion/discussion_module.coffee | 2 +- .../discussion_thread_inline_view.coffee | 4 ---- .../mustache/_inline_thread.mustache | 12 ++++++++-- 6 files changed, 35 insertions(+), 26 deletions(-) diff --git a/lms/djangoapps/django_comment_client/base/views.py b/lms/djangoapps/django_comment_client/base/views.py index 68250a035e..2fee03c5bd 100644 --- a/lms/djangoapps/django_comment_client/base/views.py +++ b/lms/djangoapps/django_comment_client/base/views.py @@ -38,11 +38,10 @@ def permitted(fn): else: content = None return content - if check_permissions_by_view(request.user, kwargs['course_id'], fetch_content(), request.view_name): return fn(request, *args, **kwargs) else: - return JsonError("unauthorized") + return JsonError("unauthorized", status=401) return wrapper def ajax_content_response(request, course_id, content, template_name): @@ -214,7 +213,7 @@ def undo_vote_for_thread(request, course_id, thread_id): thread = cc.Thread.find(thread_id) user.unvote(thread) return JsonResponse(utils.safe_content(thread.to_dict())) - + @require_POST @login_required @@ -288,7 +287,7 @@ def update_moderator_status(request, course_id, user_id): course = get_course_with_access(request.user, course_id, 'load') discussion_user = cc.User(id=user_id, course_id=course_id) context = { - 'course': course, + 'course': course, 'course_id': course_id, 'user': request.user, 'django_user': user, @@ -327,7 +326,7 @@ def tags_autocomplete(request, course_id): @require_POST @login_required @csrf.csrf_exempt -def upload(request, course_id):#ajax upload file to a question or answer +def upload(request, course_id):#ajax upload file to a question or answer """view that handles file upload via Ajax """ @@ -337,7 +336,7 @@ def upload(request, course_id):#ajax upload file to a question or answer new_file_name = '' try: # TODO authorization - #may raise exceptions.PermissionDenied + #may raise exceptions.PermissionDenied #if request.user.is_anonymous(): # msg = _('Sorry, anonymous users cannot upload files') # raise exceptions.PermissionDenied(msg) @@ -357,7 +356,7 @@ def upload(request, course_id):#ajax upload file to a question or answer new_file_name = str( time.time() ).replace( - '.', + '.', str(random.randint(0,100000)) ) + file_extension @@ -386,7 +385,7 @@ def upload(request, course_id):#ajax upload file to a question or answer parsed_url = urlparse.urlparse(file_url) file_url = urlparse.urlunparse( urlparse.ParseResult( - parsed_url.scheme, + parsed_url.scheme, parsed_url.netloc, parsed_url.path, '', '', '' diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py index af896f6f80..c21bfcbd6f 100644 --- a/lms/djangoapps/django_comment_client/forum/views.py +++ b/lms/djangoapps/django_comment_client/forum/views.py @@ -136,10 +136,16 @@ def inline_discussion(request, course_id, discussion_id): # html = render_inline_discussion(request, course_id, threads, discussion_id=discussion_id, \ # query_params=query_params) user_info = cc.User.from_django_user(request.user).to_dict() + + def infogetter(thread): + return utils.get_annotated_content_infos(course_id, thread, request.user, user_info) + + annotated_content_info = reduce(merge_dict, map(infogetter, threads), {}) return utils.JsonResponse({ # 'html': html, 'discussion_data': map(utils.safe_content, threads), 'user_info': user_info, + 'annotated_content_info': annotated_content_info }) def render_search_bar(request, course_id, discussion_id=None, text=''): diff --git a/lms/djangoapps/django_comment_client/utils.py b/lms/djangoapps/django_comment_client/utils.py index b0a570caad..1c99cdc72b 100644 --- a/lms/djangoapps/django_comment_client/utils.py +++ b/lms/djangoapps/django_comment_client/utils.py @@ -100,24 +100,24 @@ def initialize_discussion_info(course): unexpanded_category_map[category].append({"title": title, "id": id, "sort_key": sort_key}) - category_map = {"entries": defaultdict(dict), "subcategories": defaultdict(dict)} + category_map = {"entries": defaultdict(dict), "subcategories": defaultdict(dict)} for category_path, entries in unexpanded_category_map.items(): node = category_map["subcategories"] path = [x.strip() for x in category_path.split("/")] for level in path[:-1]: if level not in node: - node[level] = {"subcategories": defaultdict(dict), + node[level] = {"subcategories": defaultdict(dict), "entries": defaultdict(dict), - "sort_key": level} + "sort_key": level} node = node[level]["subcategories"] level = path[-1] if level not in node: - node[level] = {"subcategories": defaultdict(dict), - "entries": defaultdict(dict), + node[level] = {"subcategories": defaultdict(dict), + "entries": defaultdict(dict), "sort_key": level} for entry in entries: - node[level]["entries"][entry["title"]] = {"id": entry["id"], + node[level]["entries"][entry["title"]] = {"id": entry["id"], "sort_key": entry["sort_key"]} for topic, entry in course.metadata.get('discussion_topics', {}).items(): @@ -134,7 +134,7 @@ def initialize_discussion_info(course): def get_courseware_context(content, course): id_map = get_discussion_id_map(course) - id = content['commentable_id'] + id = content['commentable_id'] content_info = None if id in id_map: location = id_map[id]["location"].url() @@ -149,21 +149,21 @@ class JsonResponse(HttpResponse): mimetype='application/json; charset=utf8') class JsonError(HttpResponse): - def __init__(self, error_messages=[]): + def __init__(self, error_messages=[], status=400): if isinstance(error_messages, str): error_messages = [error_messages] content = simplejson.dumps({'errors': error_messages}, indent=2, ensure_ascii=False) super(JsonError, self).__init__(content, - mimetype='application/json; charset=utf8', status=400) + mimetype='application/json; charset=utf8', status=status) class HtmlResponse(HttpResponse): def __init__(self, html=''): super(HtmlResponse, self).__init__(html, content_type='text/plain') -class ViewNameMiddleware(object): - def process_view(self, request, view_func, view_args, view_kwargs): +class ViewNameMiddleware(object): + def process_view(self, request, view_func, view_args, view_kwargs): request.view_name = view_func.__name__ class QueryCountDebugMiddleware(object): diff --git a/lms/static/coffee/src/discussion/discussion_module.coffee b/lms/static/coffee/src/discussion/discussion_module.coffee index 360a3a2535..c7e433b440 100644 --- a/lms/static/coffee/src/discussion/discussion_module.coffee +++ b/lms/static/coffee/src/discussion/discussion_module.coffee @@ -23,8 +23,8 @@ if Backbone? type: "GET" dataType: 'json' success: (response, textStatus) => - #@$el.append(response.html) window.user = new DiscussionUser(response.user_info) + Content.loadContentInfos(response.annotated_content_info) $(event.target).html("Hide Discussion") discussion = new Discussion() discussion.reset(response.discussion_data, {silent: false}) diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee index 30f0ff8cfc..011ac3f0fc 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee @@ -21,10 +21,6 @@ class @DiscussionThreadInlineView extends DiscussionContentView @model.on "change", @updateModelDetails render: -> - #TODO: Debugging, remove when done - if not window.$disc - window.$disc = [] - window.$disc.push(@) if not @model.has('abbreviatedBody') @abbreviateBody() @$el.html(Mustache.render(@template(), $.extend(@model.toJSON(),{expanded: @expanded}) )) diff --git a/lms/templates/discussion/mustache/_inline_thread.mustache b/lms/templates/discussion/mustache/_inline_thread.mustache index cd33f2130e..57ed1436c8 100644 --- a/lms/templates/discussion/mustache/_inline_thread.mustache +++ b/lms/templates/discussion/mustache/_inline_thread.mustache @@ -2,11 +2,14 @@
- + {{votes.up_count}} + + {{votes.up_count}}

{{title}}

- sometime by + {{created_at}} by {{username}} +

Expand... @@ -16,6 +19,11 @@
{{abbreviatedBody}}
+
  1. From 2eb763e4ce27bea553d165836acf84eaf1da0f73 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 00:25:54 -0700 Subject: [PATCH 02/19] New post form on inline discussion, works, with some bugs in styling. --- .../src/discussion/discussion_module.coffee | 50 ++++-- .../views/new_post_inline_vew.coffee | 55 ++++++ lms/static/sass/_discussion.scss | 164 +++++++++++++++++- .../discussion/_discussion_module.html | 2 +- .../discussion/_inline_new_post.html | 29 ++++ .../mustache/_inline_discussion.mustache | 35 +++- 6 files changed, 311 insertions(+), 24 deletions(-) create mode 100644 lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee create mode 100644 lms/templates/discussion/_inline_new_post.html diff --git a/lms/static/coffee/src/discussion/discussion_module.coffee b/lms/static/coffee/src/discussion/discussion_module.coffee index c7e433b440..1bbac70396 100644 --- a/lms/static/coffee/src/discussion/discussion_module.coffee +++ b/lms/static/coffee/src/discussion/discussion_module.coffee @@ -2,7 +2,20 @@ if Backbone? class @DiscussionModuleView extends Backbone.View events: "click .discussion-show": "toggleDiscussion" + "click .new-post-btn": "toggleNewPost" + "click .new-post-cancel": "hideNewPost" + initialize: -> + + toggleNewPost: (event) -> + if @newPostForm.is(':hidden') + @newPostForm.slideDown(300) + else + @newPostForm.slideUp(300) + hideNewPost: (event) -> + @newPostForm.slideUp(300) + toggleDiscussion: (event) -> + console.log "doing stuff yo" if @showed @$("section.discussion").hide() $(event.target).html("Show Discussion") @@ -22,18 +35,25 @@ if Backbone? url: url type: "GET" dataType: 'json' - success: (response, textStatus) => - window.user = new DiscussionUser(response.user_info) - Content.loadContentInfos(response.annotated_content_info) - $(event.target).html("Hide Discussion") - discussion = new Discussion() - discussion.reset(response.discussion_data, {silent: false}) - $discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data}) - $(".discussion-module").append($discussion) - discussion.each (thread) -> - element = $("article#thread_#{thread.id}") - dtv = new DiscussionThreadInlineView el: element, model: thread - dtv.render() - DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info) - @retrieved = true - @showed = true + success: (response, textStatus, jqXHR) => @createDiscussion(event, response, textStatus) + + createDiscussion: (event, response, textStatus) => + console.log "HI" + console.log response + window.user = new DiscussionUser(response.user_info) + Content.loadContentInfos(response.annotated_content_info) + console.log "infod" + $(event.target).html("Hide Discussion") + discussion = new Discussion() + discussion.reset(response.discussion_data, {silent: false}) + $discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data}) + $(".discussion-module").append($discussion) + @newPostForm = $('.new-post-article') + discussion.each (thread) -> + element = $("article#thread_#{thread.id}") + dtv = new DiscussionThreadInlineView el: element, model: thread + dtv.render() + DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info) + @newPostView = new NewPostInlineView el: $('.new-post-article'), collection: discussion + @retrieved = true + @showed = true diff --git a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee new file mode 100644 index 0000000000..f64454252c --- /dev/null +++ b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee @@ -0,0 +1,55 @@ +class @NewPostInlineView extends Backbone.View + + initialize: () -> + + @topicId = @$(".topic").first().data("discussion_id") + + @maxNameWidth = 100 + + DiscussionUtil.makeWmdEditor @$el, $.proxy(@$, @), "new-post-body" + @$(".new-post-tags").tagsInput DiscussionUtil.tagsInputOptions() + + events: + "submit .new-post-form": "createPost" + + # Because we want the behavior that when the body is clicked the menu is + # closed, we need to ignore clicks in the search field and stop propagation. + # Without this, clicking the search field would also close the menu. + ignoreClick: (event) -> + event.stopPropagation() + + createPost: (event) -> + event.preventDefault() + title = @$(".new-post-title").val() + body = @$(".new-post-body").find(".wmd-input").val() + tags = @$(".new-post-tags").val() + + anonymous = false || @$("input.discussion-anonymous").is(":checked") + follow = false || @$("input.discussion-follow").is(":checked") + + url = DiscussionUtil.urlFor('create_thread', @topicId) + + DiscussionUtil.safeAjax + $elem: $(event.target) + $loading: $(event.target) if event + url: url + type: "POST" + dataType: 'json' + async: false # TODO when the rest of the stuff below is made to work properly.. + data: + title: title + body: body + tags: tags + anonymous: anonymous + auto_subscribe: follow + error: DiscussionUtil.formErrorHandler(@$(".new-post-form-errors")) + success: (response, textStatus) => + # TODO: Move this out of the callback, this makes it feel sluggish + thread = new Thread response['content'] + DiscussionUtil.clearFormErrors(@$(".new-post-form-errors")) + @$el.hide() + @$(".new-post-title").val("").attr("prev-text", "") + @$(".new-post-body").val("").attr("prev-text", "") + @$(".new-post-tags").val("") + @$(".new-post-tags").importTags("") + @collection.add thread diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 62b4c66db4..110dd9b11a 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -1472,14 +1472,10 @@ body.discussion { } .discussion-module { - @extend .discussion-body -} + @extend .discussion-body; -/* For some reason I have to do this to get the SCSS to compile, can't stick it under the above .discussion-module */ -.discussion-module { section.discussion { - /* Course content p has a default margin-bottom of 1.416, this is just to reset that */ - + /* Course content p has a default margin-bottom of 1.416em, this is just to reset that */ .discussion-thread { padding: 0.5em; @@ -1535,5 +1531,161 @@ body.discussion { } } + .new-post-article { + display: none; + margin-top: 20px; + .inner-wrapper { + max-width: 1180px; + min-width: 760px; + margin: auto; + } + + .new-post-form { + width: 100%; + margin-bottom: 20px; + border-radius: 3px; + background: rgba(0, 0, 0, .55); + color: #fff; + box-shadow: 0 1px 2px rgba(0, 0, 0, .5) inset, 0 1px 0 rgba(255, 255, 255, .5); + @include clearfix; + + .form-row { + margin-bottom: 20px; + } + + .new-post-body .wmd-input { + @include discussion-wmd-input; + position: relative; + width: 100%; + height: 200px; + z-index: 1; + padding: 10px; + box-sizing: border-box; + border: 1px solid #333; + border-radius: 3px 3px 0 0; + background: #fff; + font-family: 'Monaco', monospace; + font-size: 13px; + line-height: 1.6; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) inset; + } + + .new-post-body .wmd-preview { + @include discussion-wmd-preview; + position: relative; + width: 100%; + //height: 50px; + margin-top: -1px; + padding: 25px 20px 10px 20px; + box-sizing: border-box; + border: 1px solid #333; + border-radius: 0 0 3px 3px; + background: #e6e6e6; + color: #333; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) inset; + } + + .new-post-preview-label { + position: absolute; + top: 4px; + left: 4px; + font-size: 11px; + color: #aaa; + text-transform: uppercase; + } + + .new-post-title, + .new-post-tags { + width: 100%; + height: 40px; + padding: 0 10px; + box-sizing: border-box; + border-radius: 3px; + border: 1px solid #333; + font-size: 16px; + font-family: 'Open Sans', sans-serif; + color: #333; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) inset; + } + + .new-post-title { + font-weight: 700; + } + + .submit { + @include blue-button; + float: left; + height: 37px; + margin-top: 10px; + padding-bottom: 2px; + border-color: #333; + + &:hover { + border-color: #222; + } + } + + .new-post-cancel { + @include white-button; + float: left; + margin: 10px 0 0 15px; + } + + .options { + margin-top: 40px; + + label { + display: inline; + margin-left: 8px; + font-size: 15px; + color: #fff; + text-shadow: none; + } + } + .wmd-button { + background: none; + } + + .wmd-button span { + background: url(../images/new-post-icons-full.png) no-repeat; + } + } + + .thread-tags { + margin-top: 20px; + } + + .thread-tag { + padding: 3px 10px 6px; + border-radius: 3px; + color: #333; + background: #c5eeff; + border: 1px solid #90c4d7; + font-size: 13px; + } + + .thread-title { + display: block; + margin-bottom: 20px; + font-size: 21px; + color: #333; + font-weight: 700; + } + } + + .new-post-btn { + @include blue-button; + font-size: 13px; + margin-right: 4px; + } + + .new-post-icon { + display: block; + float: left; + width: 16px; + height: 17px; + margin: 8px 7px 0 0; + background: url(../images/new-post-icon.png) no-repeat; + } } diff --git a/lms/templates/discussion/_discussion_module.html b/lms/templates/discussion/_discussion_module.html index 99c0602b41..fb3cda4a85 100644 --- a/lms/templates/discussion/_discussion_module.html +++ b/lms/templates/discussion/_discussion_module.html @@ -1,5 +1,5 @@ <%include file="_underscore_templates.html" /> diff --git a/lms/templates/discussion/_inline_new_post.html b/lms/templates/discussion/_inline_new_post.html new file mode 100644 index 0000000000..7bc17d4467 --- /dev/null +++ b/lms/templates/discussion/_inline_new_post.html @@ -0,0 +1,29 @@ +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    + + Cancel +
    +
    +
    +
    diff --git a/lms/templates/discussion/mustache/_inline_discussion.mustache b/lms/templates/discussion/mustache/_inline_discussion.mustache index f82b3810e5..ed1fc65ab9 100644 --- a/lms/templates/discussion/mustache/_inline_discussion.mustache +++ b/lms/templates/discussion/mustache/_inline_discussion.mustache @@ -1,6 +1,37 @@
    - {{#threads}} + New Post + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    + + Cancel +
    + +
    + +
    +
    +
    +
    +
    + + + {{#threads}}
    - {{/threads}} + {{/threads}}
    From 00d21acd790bfaf28acd579e25ee229b027bbd01 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 01:33:40 -0700 Subject: [PATCH 03/19] Add newly posted threads to the inline thread list. --- ...e.coffee => discussion_module_view.coffee} | 27 +++++++++++-------- .../mustache/_inline_discussion.mustache | 11 ++++---- 2 files changed, 22 insertions(+), 16 deletions(-) rename lms/static/coffee/src/discussion/{discussion_module.coffee => discussion_module_view.coffee} (67%) diff --git a/lms/static/coffee/src/discussion/discussion_module.coffee b/lms/static/coffee/src/discussion/discussion_module_view.coffee similarity index 67% rename from lms/static/coffee/src/discussion/discussion_module.coffee rename to lms/static/coffee/src/discussion/discussion_module_view.coffee index 1bbac70396..2018518785 100644 --- a/lms/static/coffee/src/discussion/discussion_module.coffee +++ b/lms/static/coffee/src/discussion/discussion_module_view.coffee @@ -15,7 +15,6 @@ if Backbone? @newPostForm.slideUp(300) toggleDiscussion: (event) -> - console.log "doing stuff yo" if @showed @$("section.discussion").hide() $(event.target).html("Show Discussion") @@ -38,22 +37,28 @@ if Backbone? success: (response, textStatus, jqXHR) => @createDiscussion(event, response, textStatus) createDiscussion: (event, response, textStatus) => - console.log "HI" - console.log response window.user = new DiscussionUser(response.user_info) Content.loadContentInfos(response.annotated_content_info) - console.log "infod" $(event.target).html("Hide Discussion") - discussion = new Discussion() - discussion.reset(response.discussion_data, {silent: false}) + @discussion = new Discussion() + @discussion.reset(response.discussion_data, {silent: false}) $discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data}) $(".discussion-module").append($discussion) @newPostForm = $('.new-post-article') - discussion.each (thread) -> - element = $("article#thread_#{thread.id}") - dtv = new DiscussionThreadInlineView el: element, model: thread - dtv.render() + @threadviews = @discussion.map (thread) -> + new DiscussionThreadInlineView el: @$("article#thread_#{thread.id}"), model: thread + _.each @threadviews, (dtv) -> dtv.render() DiscussionUtil.bulkUpdateContentInfo(window.$$annotated_content_info) - @newPostView = new NewPostInlineView el: $('.new-post-article'), collection: discussion + @newPostView = new NewPostInlineView el: @$('.new-post-article'), collection: @discussion + @discussion.on "add", @addThread @retrieved = true @showed = true + + addThread: (thread, collection, options) => + # TODO: When doing pagination, this will need to repaginate + article = $("
    ") + @$('section.discussion > .threads').prepend(article) + threadView = new DiscussionThreadInlineView el: article, model: thread + threadView.render() + @threadviews.unshift threadView + diff --git a/lms/templates/discussion/mustache/_inline_discussion.mustache b/lms/templates/discussion/mustache/_inline_discussion.mustache index ed1fc65ab9..a82e25ac51 100644 --- a/lms/templates/discussion/mustache/_inline_discussion.mustache +++ b/lms/templates/discussion/mustache/_inline_discussion.mustache @@ -29,9 +29,10 @@
- - {{#threads}} -
-
- {{/threads}} +
+ {{#threads}} +
+
+ {{/threads}} +
From 2811822b9354f76ecf2b2d19a3fa99ed034dde30 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 02:11:47 -0700 Subject: [PATCH 04/19] Attach the discussion_id to posts made from the embedded discussion forum. --- .../src/discussion/discussion_module_view.coffee | 10 +++++----- .../src/discussion/views/new_post_inline_vew.coffee | 2 +- lms/templates/discussion/_discussion_module.html | 2 +- .../discussion/mustache/_inline_discussion.mustache | 3 ++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lms/static/coffee/src/discussion/discussion_module_view.coffee b/lms/static/coffee/src/discussion/discussion_module_view.coffee index 2018518785..06ed320623 100644 --- a/lms/static/coffee/src/discussion/discussion_module_view.coffee +++ b/lms/static/coffee/src/discussion/discussion_module_view.coffee @@ -26,23 +26,23 @@ if Backbone? @showed = true else $elem = $(event.target) - discussion_id = $elem.attr("discussion_id") - url = DiscussionUtil.urlFor 'retrieve_discussion', discussion_id + discussionId = $elem.data("discussion-id") + url = DiscussionUtil.urlFor 'retrieve_discussion', discussionId DiscussionUtil.safeAjax $elem: $elem $loading: $elem url: url type: "GET" dataType: 'json' - success: (response, textStatus, jqXHR) => @createDiscussion(event, response, textStatus) + success: (response, textStatus, jqXHR) => @createDiscussion(event, response, textStatus, discussionId) - createDiscussion: (event, response, textStatus) => + createDiscussion: (event, response, textStatus, discussionId) => window.user = new DiscussionUser(response.user_info) Content.loadContentInfos(response.annotated_content_info) $(event.target).html("Hide Discussion") @discussion = new Discussion() @discussion.reset(response.discussion_data, {silent: false}) - $discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data}) + $discussion = $(Mustache.render $("script#_inline_discussion").html(), {'threads':response.discussion_data, 'discussionId': discussionId}) $(".discussion-module").append($discussion) @newPostForm = $('.new-post-article') @threadviews = @discussion.map (thread) -> diff --git a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee index f64454252c..044c61d40b 100644 --- a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee +++ b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee @@ -2,7 +2,7 @@ class @NewPostInlineView extends Backbone.View initialize: () -> - @topicId = @$(".topic").first().data("discussion_id") + @topicId = @$(".topic").first().data("discussion-id") @maxNameWidth = 100 diff --git a/lms/templates/discussion/_discussion_module.html b/lms/templates/discussion/_discussion_module.html index fb3cda4a85..de4a9222e4 100644 --- a/lms/templates/discussion/_discussion_module.html +++ b/lms/templates/discussion/_discussion_module.html @@ -1,5 +1,5 @@ <%include file="_underscore_templates.html" /> diff --git a/lms/templates/discussion/mustache/_inline_discussion.mustache b/lms/templates/discussion/mustache/_inline_discussion.mustache index a82e25ac51..8d55f9949b 100644 --- a/lms/templates/discussion/mustache/_inline_discussion.mustache +++ b/lms/templates/discussion/mustache/_inline_discussion.mustache @@ -1,7 +1,8 @@ -
+
New Post
+
From 4354afe1b5430847165983649f5a4c93b0b9f200 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 03:40:10 -0700 Subject: [PATCH 05/19] Fix markdown in thread bodies and comments. --- .../src/discussion/views/discussion_thread_inline_view.coffee | 2 +- .../coffee/src/discussion/views/discussion_thread_view.coffee | 2 +- .../coffee/src/discussion/views/response_comment_view.coffee | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee index 011ac3f0fc..371ebcaac3 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee @@ -54,7 +54,7 @@ class @DiscussionThreadInlineView extends DiscussionContentView convertMath: -> element = @$(".post-body") - element.html DiscussionUtil.postMathJaxProcessor(element.html()) + element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html() MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]] renderResponses: -> diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee index 84c99796ee..db2689772f 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee @@ -49,7 +49,7 @@ class @DiscussionThreadView extends DiscussionContentView convertMath: -> element = @$(".post-body") - element.html DiscussionUtil.postMathJaxProcessor(element.html()) + element.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight element.html() MathJax.Hub.Queue ["Typeset", MathJax.Hub, element[0]] renderResponses: -> diff --git a/lms/static/coffee/src/discussion/views/response_comment_view.coffee b/lms/static/coffee/src/discussion/views/response_comment_view.coffee index 3131912ced..262617eb84 100644 --- a/lms/static/coffee/src/discussion/views/response_comment_view.coffee +++ b/lms/static/coffee/src/discussion/views/response_comment_view.coffee @@ -2,6 +2,7 @@ class @ResponseCommentView extends DiscussionContentView tagName: "li" template: _.template($("#response-comment-template").html()) initLocal: -> + # TODO .response-local is the parent of the comments so @$local is null, not sure what was intended here... @$local = @$el.find(".response-local") @$delegateElement = @$local @@ -14,8 +15,9 @@ class @ResponseCommentView extends DiscussionContentView @convertMath() @ convertMath: -> - body = @$(".response-body") + body = @$el.find(".response-body") body.html DiscussionUtil.postMathJaxProcessor DiscussionUtil.markdownWithHighlight body.html() + # This removes paragraphs so that comments are more compact body.children("p").each (index, elem) -> $(elem).replaceWith($(elem).html()) MathJax.Hub.Queue ["Typeset", MathJax.Hub, body[0]] From e77e5a4e520b74d6abae9af184c2f9a90e26a212 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 04:12:29 -0700 Subject: [PATCH 06/19] Modify jquery.tagsinput plugin to allow filtering tags, and filter tags by converting them to lowercase so the service doesn't just error when you submit. --- lms/static/coffee/src/discussion/utils.coffee | 4 + lms/static/js/jquery.tagsinput.js | 150 +++++++++--------- 2 files changed, 82 insertions(+), 72 deletions(-) diff --git a/lms/static/coffee/src/discussion/utils.coffee b/lms/static/coffee/src/discussion/utils.coffee index 392aa04538..746cc308cf 100644 --- a/lms/static/coffee/src/discussion/utils.coffee +++ b/lms/static/coffee/src/discussion/utils.coffee @@ -107,6 +107,9 @@ class @DiscussionUtil [event, selector] = eventSelector.split(' ') $local(selector).unbind(event)[event] handler + @processTag: (text) -> + text.toLowerCase() + @tagsInputOptions: -> autocomplete_url: @urlFor('tags_autocomplete') autocomplete: @@ -116,6 +119,7 @@ class @DiscussionUtil width: '100%' defaultText: "Tag your post: press enter after each tag" removeWithBackspace: true + preprocessTag: @processTag @formErrorHandler: (errorsField) -> (xhr, textStatus, error) -> diff --git a/lms/static/js/jquery.tagsinput.js b/lms/static/js/jquery.tagsinput.js index b05a87ca99..563567ac46 100644 --- a/lms/static/js/jquery.tagsinput.js +++ b/lms/static/js/jquery.tagsinput.js @@ -1,12 +1,12 @@ /* jQuery Tags Input Plugin 1.3.3 - + Copyright (c) 2011 XOXCO, Inc - + Documentation for this plugin lives here: http://xoxco.com/clickable/jquery-tags-input - + Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php @@ -24,9 +24,9 @@ val = '', input = $(this), testSubject = $('#'+$(this).data('tester_id')); - + if (val === (val = input.val())) {return;} - + // Enter new content into testSubject var escaped = val.replace(/&/g, '&').replace(/\s/g,' ').replace(//g, '>'); testSubject.html(escaped); @@ -36,7 +36,7 @@ currentWidth = input.width(), isValidWidthChange = (newWidth < currentWidth && newWidth >= minWidth) || (newWidth > minWidth && newWidth < maxWidth); - + // Animate width if (isValidWidthChange) { input.width(newWidth); @@ -72,19 +72,24 @@ input.data('tester_id', testerId); input.css('width', minWidth); }; - + $.fn.addTag = function(value,options) { options = jQuery.extend({focus:false,callback:true},options); - this.each(function() { + this.each(function() { var id = $(this).attr('id'); var tagslist = $(this).val().split(delimiter[id]); - if (tagslist[0] == '') { + if (tagslist[0] == '') { tagslist = new Array(); } value = jQuery.trim(value); - + + if (options.callback && tags_callbacks[id] && tags_callbacks[id]['preprocessTag']) { + var f = tags_callbacks[id]['preprocessTag']; + value = f.call(this, value); + } + if (options.unique) { var skipTag = $(this).tagExist(value); if(skipTag == true) { @@ -92,10 +97,10 @@ $('#'+id+'_tag').addClass('not_valid'); } } else { - var skipTag = false; + var skipTag = false; } - - if (value !='' && skipTag != true) { + + if (value !='' && skipTag != true) { $('').addClass('tag').append( $('').text(value).append('  '), $('', { @@ -108,16 +113,16 @@ ).insertBefore('#' + id + '_addTag'); tagslist.push(value); - + $('#'+id+'_tag').val(''); if (options.focus) { $('#'+id+'_tag').focus(); - } else { + } else { $('#'+id+'_tag').blur(); } - + $.fn.tagsInput.updateTagsField(this,tagslist); - + if (options.callback && tags_callbacks[id] && tags_callbacks[id]['onAddTag']) { var f = tags_callbacks[id]['onAddTag']; f.call(this, value); @@ -127,29 +132,29 @@ var i = tagslist.length; var f = tags_callbacks[id]['onChange']; f.call(this, $(this), tagslist[i-1]); - } + } } - - }); - + + }); + return false; }; - - $.fn.removeTag = function(value) { + + $.fn.removeTag = function(value) { value = unescape(value); - this.each(function() { + this.each(function() { var id = $(this).attr('id'); - + var old = $(this).val().split(delimiter[id]); - + $('#'+id+'_tagsinput .tag').remove(); str = ''; - for (i=0; i< old.length; i++) { - if (old[i]!=value) { + for (i=0; i< old.length; i++) { + if (old[i]!=value) { str = str + delimiter[id] +old[i]; } } - + $.fn.tagsInput.importTags(this,str); if (tags_callbacks[id] && tags_callbacks[id]['onRemoveTag']) { @@ -157,24 +162,24 @@ f.call(this, value); } }); - + return false; }; - + $.fn.tagExist = function(val) { var id = $(this).attr('id'); var tagslist = $(this).val().split(delimiter[id]); return (jQuery.inArray(val, tagslist) >= 0); //true when tag exists, false when not }; - + // clear all existing tags and import new ones from a string $.fn.importTags = function(str) { id = $(this).attr('id'); $('#'+id+'_tagsinput .tag').remove(); $.fn.tagsInput.importTags(this,str); } - - $.fn.tagsInput = function(options) { + + $.fn.tagsInput = function(options) { var settings = jQuery.extend({ interactive:true, defaultText:'add a tag', @@ -192,15 +197,15 @@ inputPadding: 6*2 },options); - this.each(function() { - if (settings.hide) { - $(this).hide(); + this.each(function() { + if (settings.hide) { + $(this).hide(); } var id = $(this).attr('id'); if (!id || delimiter[$(this).attr('id')]) { id = $(this).attr('id', 'tags' + new Date().getTime()).attr('id'); } - + var data = jQuery.extend({ pid:id, real_input: '#'+id, @@ -208,57 +213,58 @@ input_wrapper: '#'+id+'_addTag', fake_input: '#'+id+'_tag' },settings); - + delimiter[id] = data.delimiter; - - if (settings.onAddTag || settings.onRemoveTag || settings.onChange) { + + if (settings.onAddTag || settings.onRemoveTag || settings.onChange || settings.preprocessTag) { tags_callbacks[id] = new Array(); tags_callbacks[id]['onAddTag'] = settings.onAddTag; tags_callbacks[id]['onRemoveTag'] = settings.onRemoveTag; tags_callbacks[id]['onChange'] = settings.onChange; + tags_callbacks[id]['preprocessTag'] = settings.preprocessTag; } - + var markup = '
'; - + if (settings.interactive) { markup = markup + ''; } - + markup = markup + '
'; - + $(markup).insertAfter(this); - + $(data.holder).css('width',settings.width); $(data.holder).css('min-height',settings.height); $(data.holder).css('height','100%'); - - if ($(data.real_input).val()!='') { + + if ($(data.real_input).val()!='') { $.fn.tagsInput.importTags($(data.real_input),$(data.real_input).val()); - } - if (settings.interactive) { + } + if (settings.interactive) { $(data.fake_input).val($(data.fake_input).attr('data-default')); $(data.fake_input).css('color',settings.placeholderColor); $(data.fake_input).resetAutosize(settings); - + $(data.fake_input).doAutosize(settings); $(data.holder).bind('click',data,function(event) { $(event.data.fake_input).focus(); }); - + $(data.fake_input).bind('focus',data,function(event) { - if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('data-default')) { + if ($(event.data.fake_input).val()==$(event.data.fake_input).attr('data-default')) { $(event.data.fake_input).val(''); } - $(event.data.fake_input).css('color','#000000'); + $(event.data.fake_input).css('color','#000000'); }); - + if (settings.autocomplete_url != undefined) { autocomplete_options = {source: settings.autocomplete_url}; - for (attrname in settings.autocomplete) { - autocomplete_options[attrname] = settings.autocomplete[attrname]; + for (attrname in settings.autocomplete) { + autocomplete_options[attrname] = settings.autocomplete[attrname]; } - + if (jQuery.Autocompleter !== undefined) { onSelectCallback = settings.autocomplete.onItemSelect; settings.autocomplete.onItemSelect = function() { @@ -278,18 +284,18 @@ $(data.fake_input).autocomplete(autocomplete_options); $(data.fake_input).bind('autocompleteselect',data,function(event,ui) { $(event.data.real_input).addTag(ui.item.value,{focus:true,unique:(settings.unique)}); - + return false; }); } - - + + } else { // if a user tabs out of the field, create a new tag // this is only available if autocomplete is not used. - $(data.fake_input).bind('blur',data,function(event) { + $(data.fake_input).bind('blur',data,function(event) { var d = $(this).attr('data-default'); - if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) { + if ($(event.data.fake_input).val()!='' && $(event.data.fake_input).val()!=d) { if( (event.data.minChars <= $(event.data.fake_input).val().length) && (!event.data.maxChars || (event.data.maxChars >= $(event.data.fake_input).val().length)) ) $(event.data.real_input).addTag($(event.data.fake_input).val(),{focus:true,unique:(settings.unique)}); } else { @@ -298,7 +304,7 @@ } return false; }); - + } // if user types a comma, create a new tag $(data.fake_input).bind('keypress',data,function(event) { @@ -326,7 +332,7 @@ } }); $(data.fake_input).blur(); - + //Removes the not_valid class when user changes the value of the fake input if(data.unique) { $(data.fake_input).keydown(function(event){ @@ -337,21 +343,21 @@ } } // if settings.interactive }); - + return this; - + }; - - $.fn.tagsInput.updateTagsField = function(obj,tagslist) { + + $.fn.tagsInput.updateTagsField = function(obj,tagslist) { var id = $(obj).attr('id'); $(obj).val(tagslist.join(delimiter[id])); }; - - $.fn.tagsInput.importTags = function(obj,val) { + + $.fn.tagsInput.importTags = function(obj,val) { $(obj).val(''); var id = $(obj).attr('id'); var tags = val.split(delimiter[id]); - for (i=0; i Date: Thu, 6 Sep 2012 04:49:38 -0700 Subject: [PATCH 07/19] Fix follow dogear causing page to scroll up on click. --- lms/templates/discussion/mustache/_inline_thread.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/templates/discussion/mustache/_inline_thread.mustache b/lms/templates/discussion/mustache/_inline_thread.mustache index 57ed1436c8..417cc67189 100644 --- a/lms/templates/discussion/mustache/_inline_thread.mustache +++ b/lms/templates/discussion/mustache/_inline_thread.mustache @@ -1,5 +1,5 @@
-
+
+ {{votes.up_count}} From 32f79abd9fb4628c0ac2e5c3a102860588339fb5 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 11:27:46 -0400 Subject: [PATCH 08/19] added sidebar styling for staff posts and responses --- lms/static/images/staff-icons.png | Bin 0 -> 1126 bytes lms/static/sass/_discussion.scss | 39 +++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lms/static/images/staff-icons.png diff --git a/lms/static/images/staff-icons.png b/lms/static/images/staff-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..7efb9a8cd1dc844c5dca05dc1b6a19211b47ab7f GIT binary patch literal 1126 zcmaJ=TWHfz7>-W1IaGY`IvgG|2Tp9$v`yNEb=}%zTV)xgD>~eROOvxTY`K`6*>3Ei z^M><59EeZiU38*?iVrH@u!-ohvGTIqb{rT9O#vGoaFRwAJTwHw_iD_M|eRE#tPaZT!hNhm1;+aAF> zf+$(5raDlE*viR<=9U~EcTO`gnjq>TIa88*Ap&XGqv~Pu`;FTqP?a#bnGrpr8G{+M zWzd4{gKa5!uvZQ#WTYO{sMUD(5A59mnBxpcd_$iPEewp0_Th7KG?DQ)zlFo~5;rl6VA zw7NZ2CR{KoCz%xO_BbgO9Yyi~u9`OOZKEXot9M3XJ2hZJDhX|)-;#0Tx~rW~CKt1y zgbXWX7=6VmCNc&x?2KW8SUU^WiIS}9j-hq}A&OjFw~?gFFwTcb%;8p5g$vP4s7YW1 zA<6`3TA+h`faQa1fbn^K!6rIX#PWvRuR$FZu?og|f_|Q*V}2nT@Xv^KhCwrNWFA`T zcBnL2h6W~*=G57>#AeqriB)FMGL;8EE0)4yD5tgmw7O`*^W$u%2NxfvM<42V-Yq=X z_qyNi#Fye_oNr9!UZ;PLk4H*EVCY@s#EXk4o$gxmVDW({nV-8ja;IkG>8|la>-n0p zAGKZSW2^3L7(H`Z_;TpYybtx@bMxkh(c^;e+0cp7`%fDB$_lH;KAq&jt>MCLqHyfs zsj|X_LTOd?l8+@%hhNTrPv2DyXST&aaHl%F5awK!LtaI+A&Ru$W%lpi6Zp+#I n%g$BbOw?RnyW;Tf^$qzsg!(qIuJY*fea_8~3vK+xXxENE?tye$ literal 0 HcmV?d00001 diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 110dd9b11a..3c914d42db 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -906,7 +906,7 @@ body.discussion { position: relative; display: block; height: 36px; - padding: 0 10px; + padding: 0 10px 0 18px; margin-bottom: 1px; margin-right: -1px; @include linear-gradient(top, rgba(255, 255, 255, .7), rgba(255, 255, 255, 0)); @@ -917,6 +917,35 @@ body.discussion { background-color: #eee; } + &.staff-post.staff-response { + .staff-post-icon { + top: 5px; + } + + .staff-response-icon { + top: 18px; + } + } + + .staff-post-icon, + .staff-response-icon { + position: absolute; + top: 11px; + left: 3px; + width: 13px; + height: 13px; + background: url(../images/staff-icons.png) no-repeat; + } + + .staff-post-icon { + left: 2px; + background-position: 0 0; + } + + .staff-response-icon { + background-position: -13px 0; + } + .title { font-size: 13px; font-weight: 700; @@ -958,6 +987,14 @@ body.discussion { color: #333; } + .staff-post-icon { + background-position: 0 -13px; + } + + .staff-response-icon { + background-position: -13px -13px; + } + .votes-count, .comments-count { @include linear-gradient(top, #3994c7, #4da7d3); From 5304c9cb99a22cbb2802ad5eda25e4ebc08317c2 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 11:39:23 -0400 Subject: [PATCH 09/19] delegated tooltips --- lms/static/js/discussions-temp.js | 10 +------- lms/static/sass/_discussion.scss | 32 -------------------------- lms/static/sass/course/base/_base.scss | 29 +++++++++++++++++++++++ 3 files changed, 30 insertions(+), 41 deletions(-) diff --git a/lms/static/js/discussions-temp.js b/lms/static/js/discussions-temp.js index b0ce231eb5..d788739d0f 100644 --- a/lms/static/js/discussions-temp.js +++ b/lms/static/js/discussions-temp.js @@ -58,7 +58,7 @@ $(document).ready(function() { $('.new-post-btn').bind('click', newPost); $('.new-post-cancel').bind('click', closeNewPost); - $('[data-tooltip]').bind({ + $body.delegate('[data-tooltip]', { 'mouseover': showTooltip, 'mousemove': moveTooltip, 'mouseout': hideTooltip, @@ -66,14 +66,6 @@ $(document).ready(function() { }); $body.delegate('.browse-topic-drop-search-input, .form-topic-drop-search-input', 'keyup', filterDrop); - -// $(window).bind('resize', updateSidebar); -// $(window).bind('scroll', updateSidebar); -// $('.discussion-column').bind("input", function (e) { -// console.log("resized"); -// updateSidebar(); -// }) -// updateSidebar(); }); function filterDrop(e) { diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 3c914d42db..3b511047af 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -1400,38 +1400,6 @@ body.discussion { - - .tooltip { - position: absolute; - top: 0; - left: 0; - z-index: 99999; - padding: 0 10px; - border-radius: 3px; - background: rgba(0, 0, 0, .85); - font-size: 11px; - font-weight: 400; - line-height: 26px; - color: #fff; - pointer-events: none; - opacity: 0; - @include transition(opacity .1s); - - &:after { - content: '▾'; - display: block; - position: absolute; - bottom: -14px; - left: 50%; - margin-left: -7px; - font-size: 20px; - color: rgba(0, 0, 0, .85); - } - } - - - - .main-article.new { display: none; padding: 50px; diff --git a/lms/static/sass/course/base/_base.scss b/lms/static/sass/course/base/_base.scss index 1edb9aa7ba..6e502c7852 100644 --- a/lms/static/sass/course/base/_base.scss +++ b/lms/static/sass/course/base/_base.scss @@ -102,3 +102,32 @@ img { background: #444; color: #fff; } + + +.tooltip { + position: absolute; + top: 0; + left: 0; + z-index: 99999; + padding: 0 10px; + border-radius: 3px; + background: rgba(0, 0, 0, .85); + font-size: 11px; + font-weight: 400; + line-height: 26px; + color: #fff; + pointer-events: none; + opacity: 0; + @include transition(opacity .1s); + + &:after { + content: '▾'; + display: block; + position: absolute; + bottom: -14px; + left: 50%; + margin-left: -7px; + font-size: 20px; + color: rgba(0, 0, 0, .85); + } +} \ No newline at end of file From 92e9edc05b0cff99cda30630394431970bcdba54 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 11:49:57 -0400 Subject: [PATCH 10/19] focus search on drop --- .../discussion/views/discussion_thread_list_view.coffee | 9 +++++---- .../coffee/src/discussion/views/new_post_view.coffee | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee index 6b3a17b4c4..cc9a1c55bf 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee @@ -137,12 +137,13 @@ class @DiscussionThreadListView extends Backbone.View @$(".browse").toggleClass('is-dropped') if @$(".browse").hasClass('is-dropped') @$(".browse-topic-drop-menu-wrapper").show() - $('body').bind 'click', @toggleTopicDrop - $('body').bind 'keydown', @setActiveItem + $(".browse-topic-drop-search-input").focus() + $("body").bind "click", @toggleTopicDrop + $("body").bind "keydown", @setActiveItem else @$(".browse-topic-drop-menu-wrapper").hide() - $('body').unbind 'click', @toggleTopicDrop - $('body').unbind 'keydown', @setActiveItem + $("body").unbind "click", @toggleTopicDrop + $("body").unbind "keydown", @setActiveItem setTopic: (event) -> item = $(event.target).closest('a') diff --git a/lms/static/coffee/src/discussion/views/new_post_view.coffee b/lms/static/coffee/src/discussion/views/new_post_view.coffee index e1a859b62a..f56abb2c51 100644 --- a/lms/static/coffee/src/discussion/views/new_post_view.coffee +++ b/lms/static/coffee/src/discussion/views/new_post_view.coffee @@ -38,9 +38,10 @@ class @NewPostView extends Backbone.View @menuOpen = true @dropdownButton.addClass('dropped') @topicMenu.show() + $(".form-topic-drop-search-input").focus() - $('body').bind 'keydown', @setActiveItem - $('body').bind 'click', @hideTopicDropdown + $("body").bind "keydown", @setActiveItem + $("body").bind "click", @hideTopicDropdown # Set here because 1) the window might get resized and things could # change and 2) can't set in initialize because the button is hidden @@ -52,8 +53,8 @@ class @NewPostView extends Backbone.View @dropdownButton.removeClass('dropped') @topicMenu.hide() - $('body').unbind 'keydown', @setActiveItem - $('body').unbind 'click', @hideTopicDropdown + $("body").unbind "keydown", @setActiveItem + $("body").unbind "click", @hideTopicDropdown setTopic: (event) -> $target = $(event.target) From 2b5718a98b1292a841e8a5971082837c020e2a85 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 14:02:23 -0400 Subject: [PATCH 11/19] fixed blank slate sidebar resize glitch --- .../views/discussion_thread_list_view.coffee | 51 ++++++++++++++++--- lms/templates/discussion/index.html | 2 +- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee index cc9a1c55bf..ed4a956977 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee @@ -15,6 +15,7 @@ class @DiscussionThreadListView extends Backbone.View @collection.on "add", @addAndSelectThread @sidebar_padding = 10 @sidebar_header_height = 87 + @boardName reloadDisplayedCollection: (thread) => thread_id = thread.get('id') @@ -41,8 +42,8 @@ class @DiscussionThreadListView extends Backbone.View windowHeight = $(window).height(); discussionBody = $(".discussion-article") - discussionsBodyTop = if discussionBody[0] then discussionBody.offset().top; - discussionsBodyBottom = discussionsBodyTop + discussionBody.outerHeight(); + discussionsBodyTop = if discussionBody[0] then discussionBody.offset().top + discussionsBodyBottom = discussionsBodyTop + discussionBody.outerHeight() sidebar = $(".sidebar") if scrollTop > discussionsBodyTop - @sidebar_padding @@ -62,10 +63,11 @@ class @DiscussionThreadListView extends Backbone.View amount = Math.max(topOffset - discussionBottomOffset, 0) sidebarHeight = sidebarHeight - @sidebar_padding - amount - sidebar.css 'height', Math.min(Math.max(sidebarHeight, 400), discussionBody.outerHeight()) + sidebarHeight = Math.min(Math.max(sidebarHeight, 400), discussionBody.outerHeight()) + sidebar.css 'height', sidebarHeight postListWrapper = @$('.post-list-wrapper') - postListWrapper.css('height', (sidebarHeight - @sidebar_header_height - 4) + 'px'); + postListWrapper.css('height', (sidebarHeight - @sidebar_header_height - 4) + 'px') # Because we want the behavior that when the body is clicked the menu is @@ -150,16 +152,53 @@ class @DiscussionThreadListView extends Backbone.View boardName = item.find(".board-name").html() _.each item.parents('ul').not('.browse-topic-drop-menu'), (parent) -> boardName = $(parent).siblings('a').find('.board-name').html() + ' / ' + boardName - @$(".current-board").html(boardName) + @$(".current-board").html(@fitName(boardName)) fontSize = 16 @$(".current-board").css('font-size', '16px') - while @$(".current-board").width() > (@$el.width() * .8) - 40 fontSize-- if fontSize < 11 break @$(".current-board").css('font-size', fontSize + 'px') + setSelectedTopic: (name) -> + @$(".current-board").html(@fitName(name)) + + getNameWidth: (name) -> + test = $("
") + test.css + "font-size": @$(".current-board").css('font-size') + opacity: 0 + position: 'absolute' + left: -1000 + top: -1000 + $("body").append(test) + test.html(name) + width = test.width() + test.remove() + return width + + fitName: (name) -> + width = @getNameWidth(name) + if width < @maxNameWidth + return name + path = (x.replace /^\s+|\s+$/g, "" for x in name.split("/")) + while path.length > 1 + path.shift() + partialName = "... / " + path.join(" / ") + if @getNameWidth(partialName) < @maxNameWidth + return partialName + + rawName = path[0] + + name = "... / " + rawName + + while @getNameWidth(name) > @maxNameWidth + rawName = rawName[0...rawName.length-1] + name = "... / " + rawName + " ..." + + return name + filterTopic: (event) -> @setTopic(event) item = $(event.target).closest('li') diff --git a/lms/templates/discussion/index.html b/lms/templates/discussion/index.html index 40284638f3..53cbe2d9ed 100644 --- a/lms/templates/discussion/index.html +++ b/lms/templates/discussion/index.html @@ -27,7 +27,7 @@
-
+

${course.title} discussions

From 8529ef35a9af3bd2b6fac70cc992df7207692521 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 14:57:37 -0400 Subject: [PATCH 12/19] added title focus on new post; tweaked tag input styles --- lms/static/js/discussions-temp.js | 1 + lms/static/sass/_discussion.scss | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lms/static/js/discussions-temp.js b/lms/static/js/discussions-temp.js index d788739d0f..dd6af6ef14 100644 --- a/lms/static/js/discussions-temp.js +++ b/lms/static/js/discussions-temp.js @@ -268,6 +268,7 @@ function setTopic(e) { function newPost(e) { $newPost.slideDown(300); + $('.new-post-title').focus(); } function closeNewPost(e) { diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 3b511047af..0f4bc9f7e9 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -393,6 +393,22 @@ body.discussion { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) inset; } + .tagsinput { + padding: 10px; + box-sizing: border-box; + border: 1px solid #333; + border-radius: 3px; + background: #fff; + font-family: 'Monaco', monospace; + font-size: 13px; + line-height: 1.6; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3) inset; + + span.tag { + margin-bottom: 0; + } + } + .new-post-body .wmd-preview { @include discussion-wmd-preview; position: relative; From 9923323fdcecd79b7a701f65f84206aef0502a9e Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 17:22:00 -0400 Subject: [PATCH 13/19] styled new post error messages --- lms/static/coffee/src/discussion/utils.coffee | 2 +- lms/static/images/white-error-icon.png | Bin 0 -> 1107 bytes lms/static/sass/_discussion.scss | 22 ++++++++++++++++++ lms/templates/discussion/_new_post.html | 5 ++-- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 lms/static/images/white-error-icon.png diff --git a/lms/static/coffee/src/discussion/utils.coffee b/lms/static/coffee/src/discussion/utils.coffee index 746cc308cf..22adcff4b7 100644 --- a/lms/static/coffee/src/discussion/utils.coffee +++ b/lms/static/coffee/src/discussion/utils.coffee @@ -127,7 +127,7 @@ class @DiscussionUtil if response.errors? and response.errors.length > 0 errorsField.empty() for error in response.errors - errorsField.append($("
  • ").addClass("new-post-form-error").html(error)) + errorsField.append($("
  • ").addClass("new-post-form-error").html(error)).show() @clearFormErrors: (errorsField) -> errorsField.empty() diff --git a/lms/static/images/white-error-icon.png b/lms/static/images/white-error-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6204f4451349d143934c9425e75eabf91d4cbe68 GIT binary patch literal 1107 zcmaJ=TWHfz7*1EW>DY9lqSdO$DB@&InqJa2w6f;vyOb^0(3NzOSx|M&ghe>oR=x{tOr z?QEhbswLMY=E>ShzD?^J$p4dloF$6~XN$NO_2G(aK`O1H5(GJ2?uU6OtHWn!VVt7e z2ed*F7o}r@f^QJ{gw$l9_>Jt!u=B zy(8TPWn@5!sdVxPh*t$dphGN!sy=AgLN!4z@d{+`m{}Sux!{2Wy)3FI^?(erAP6%- zpW^2@!1D|j3iCYI4g!8I!1~F{`?!!0=7m56tUNS{W~qHbUhG_nMNSF2jIk-OY^73R zDnSNW{VW%Y#T<@6z(+iM_OOBFs?V_Z*BC@-E0$(r4H>{;luKv`CupK{IR)KZr8Vr8 zGLeF@RoP@Y#_yz5bCjh2yXyL?w~h1gkKQ$j?ZU7L**vt-kfo5u_3d{;nL@^bGDcPb zp}|@ed&&qSyNpbb>E*#8Nmew&F|;iqBuU5_HkJ(q=EMX|I2cV+g=jbujD*BYwj-V9 zxGWbHBfJ>pBjI2m813X@HLQq~AsrgHhE@My#eZU*VbDzyS%j8$4yv6N(!o;Fg0_Yh ze>5cWT!!#PLThVT#;R**S;1!iiDiix)@kiut*)8K{5ady!6k>)(T4_^cZ&?RH$C@~ zT#D(Om@ZV`m3}NPCf$3$x~XHS9}N?A2fg#xQulY?{1R?maFuem4yTz%;}buhtlM?_ z#`N{KUy{b0G((*L55}L2zE3?Ldofy4-z?A_k9V}Zraz`Pifv$00nLZUiknZhV>h>V zbAwrTHhI_eHRYX6#XmQe&=psEDqery
    -
    -
    -
    +
    @@ -46,6 +44,7 @@
    +
      From 1d06a0feda9ef4b396f100eb48c3cfbc732a3fc3 Mon Sep 17 00:00:00 2001 From: Tom Giannattasio Date: Thu, 6 Sep 2012 17:41:47 -0400 Subject: [PATCH 14/19] fixed 1px drop menu glitch --- lms/static/sass/_discussion.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lms/static/sass/_discussion.scss b/lms/static/sass/_discussion.scss index 41706e283c..62534f48c6 100644 --- a/lms/static/sass/_discussion.scss +++ b/lms/static/sass/_discussion.scss @@ -751,7 +751,9 @@ body.discussion { width: 100%; background: #737373; border: 1px solid #4b4b4b; + border-left: none; border-radius: 0 0 3px 3px; + @include box-shadow(1px 0 0 #4b4b4b inset); .browse-topic-drop-menu { max-height: 400px; From 366e9c674bbde7db0e926a9b9d21c1f6d9cf3200 Mon Sep 17 00:00:00 2001 From: Matthew Mongeau Date: Thu, 6 Sep 2012 17:45:48 -0400 Subject: [PATCH 15/19] Code for displaying endorsed checkmark. --- lms/lib/comment_client/thread.py | 1 + .../src/discussion/views/discussion_thread_list_view.coffee | 2 ++ .../src/discussion/views/discussion_thread_view.coffee | 5 +++++ .../coffee/src/discussion/views/thread_response_view.coffee | 1 + 4 files changed, 9 insertions(+) diff --git a/lms/lib/comment_client/thread.py b/lms/lib/comment_client/thread.py index 1f6d081f7f..e4ada77499 100644 --- a/lms/lib/comment_client/thread.py +++ b/lms/lib/comment_client/thread.py @@ -12,6 +12,7 @@ class Thread(models.Model): 'created_at', 'updated_at', 'comments_count', 'at_position_list', 'children', 'type', 'highlighted_title', 'highlighted_body', + 'endorsed' ] updatable_fields = [ diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee index ed4a956977..08f9fb754f 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_list_view.coffee @@ -103,6 +103,8 @@ class @DiscussionThreadListView extends Backbone.View content = $(_.template($("#thread-list-item-template").html())(thread.toJSON())) if thread.get('subscribed') content.addClass("followed") + if thread.get('endorsed') + content.addClass("resolved") @highlight(content) diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee index db2689772f..8f1054a310 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_view.coffee @@ -66,12 +66,17 @@ class @DiscussionThreadView extends DiscussionContentView response.set('thread', @model) view = new ThreadResponseView(model: response) view.on "comment:add", @addComment + view.on "comment:endorse", @endorseThread view.render() @$el.find(".responses").append(view.el) addComment: => @model.comment() + endorseThread: (endorsed) => + is_endorsed = @$el.find(".is-endorsed").length + @model.set 'endorsed', is_endorsed + toggleVote: (event) -> event.preventDefault() if window.user.voted(@model) diff --git a/lms/static/coffee/src/discussion/views/thread_response_view.coffee b/lms/static/coffee/src/discussion/views/thread_response_view.coffee index fc7d9d56e4..86deb82e6d 100644 --- a/lms/static/coffee/src/discussion/views/thread_response_view.coffee +++ b/lms/static/coffee/src/discussion/views/thread_response_view.coffee @@ -109,6 +109,7 @@ class @ThreadResponseView extends DiscussionContentView endorsed = @model.get('endorsed') data = { endorsed: not endorsed } @model.set('endorsed', not endorsed) + @trigger "comment:endorse", not endorsed DiscussionUtil.safeAjax $elem: $elem url: url From 0022efb7e43364943aca0ff39dc772cd056c34b8 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 18:08:28 -0700 Subject: [PATCH 16/19] Add loading animation to discussion module. --- lms/static/coffee/src/discussion/utils.coffee | 2 +- .../discussion/views/discussion_thread_inline_view.coffee | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/lms/static/coffee/src/discussion/utils.coffee b/lms/static/coffee/src/discussion/utils.coffee index 22adcff4b7..7c388d6d20 100644 --- a/lms/static/coffee/src/discussion/utils.coffee +++ b/lms/static/coffee/src/discussion/utils.coffee @@ -3,7 +3,7 @@ $ -> window.$$contents = {} $.fn.extend loading: -> - @$_loading = $("") + @$_loading = $("
      ") $(this).after(@$_loading) loaded: -> @$_loading.remove() diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee index 371ebcaac3..b7ce771eeb 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee @@ -34,8 +34,6 @@ class @DiscussionThreadInlineView extends DiscussionContentView if @expanded @makeWmdEditor "reply-body" @renderResponses() -# @highlight @$(".post-body") -# @highlight @$("h1") @ renderDogear: -> @@ -60,6 +58,7 @@ class @DiscussionThreadInlineView extends DiscussionContentView renderResponses: -> DiscussionUtil.safeAjax url: "/courses/#{$$course_id}/discussion/forum/#{@model.get('commentable_id')}/threads/#{@model.id}" + $loading: @$el success: (data, textStatus, xhr) => @$el.find(".loading").remove() Content.loadContentInfos(data['annotated_content_info']) @@ -188,11 +187,8 @@ class @DiscussionThreadInlineView extends DiscussionContentView success: (response, textStatus) => @model.set('endorsed', not endorsed) - highlight: (el) -> - el.html(el.html().replace(/<mark>/g, "").replace(/<\/mark>/g, "")) - abbreviateBody: -> - abbreviated = DiscussionUtil.abbreviateString @model.get('body'), 140 # Because twitter + abbreviated = DiscussionUtil.abbreviateString @model.get('body'), 140 @model.set('abbreviatedBody', abbreviated) expandPost: (event) -> From c4c956dbbbd9465447be5bd5184167dd2386abe4 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 18:09:09 -0700 Subject: [PATCH 17/19] Fix accidental code formatting of abbreviated posts and put administrative buttons in the expanded content. --- lms/templates/discussion/mustache/_inline_thread.mustache | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lms/templates/discussion/mustache/_inline_thread.mustache b/lms/templates/discussion/mustache/_inline_thread.mustache index 417cc67189..b45f3ff47b 100644 --- a/lms/templates/discussion/mustache/_inline_thread.mustache +++ b/lms/templates/discussion/mustache/_inline_thread.mustache @@ -16,10 +16,8 @@ Collapse...
    • -
      - {{abbreviatedBody}} -
      -
        +
        {{abbreviatedBody}}
        +
        • Edit
        • Delete
        • Close
        • From b33ef47d20f90ae42a7c82b2dcb624c9b02aafd6 Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 18:35:03 -0700 Subject: [PATCH 18/19] Clear body textarea after a successful post. --- .../coffee/src/discussion/views/new_post_inline_vew.coffee | 2 +- lms/static/coffee/src/discussion/views/new_post_view.coffee | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee index 044c61d40b..f3b04d14ce 100644 --- a/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee +++ b/lms/static/coffee/src/discussion/views/new_post_inline_vew.coffee @@ -49,7 +49,7 @@ class @NewPostInlineView extends Backbone.View DiscussionUtil.clearFormErrors(@$(".new-post-form-errors")) @$el.hide() @$(".new-post-title").val("").attr("prev-text", "") - @$(".new-post-body").val("").attr("prev-text", "") + @$(".new-post-body textarea").val("").attr("prev-text", "") @$(".new-post-tags").val("") @$(".new-post-tags").importTags("") @collection.add thread diff --git a/lms/static/coffee/src/discussion/views/new_post_view.coffee b/lms/static/coffee/src/discussion/views/new_post_view.coffee index f56abb2c51..927aa76536 100644 --- a/lms/static/coffee/src/discussion/views/new_post_view.coffee +++ b/lms/static/coffee/src/discussion/views/new_post_view.coffee @@ -143,7 +143,7 @@ class @NewPostView extends Backbone.View DiscussionUtil.clearFormErrors(@$(".new-post-form-errors")) @$el.hide() @$(".new-post-title").val("").attr("prev-text", "") - @$(".new-post-body").val("").attr("prev-text", "") + @$(".new-post-body textarea").val("").attr("prev-text", "") @$(".new-post-tags").val("") @$(".new-post-tags").importTags("") @collection.add thread @@ -169,7 +169,7 @@ class @NewPostView extends Backbone.View itemTop = $(items[index]).parent().offset().top scrollTop = $(".topic_menu").scrollTop() - itemFromTop = $(".topic_menu").offset().top - itemTop + itemFromTop = $(".topic_menu").offset().top - itemTop scrollTarget = Math.min(scrollTop - itemFromTop, scrollTop) scrollTarget = Math.max(scrollTop - itemFromTop - $(".topic_menu").height() + $(items[index]).height() + 20, scrollTarget) $(".topic_menu").scrollTop(scrollTarget) From a40c8fad2d78df49e6353addaf2d15528eb2a55d Mon Sep 17 00:00:00 2001 From: Ibrahim Awwal Date: Thu, 6 Sep 2012 19:04:56 -0700 Subject: [PATCH 19/19] Fix inline thread rendering when expanding and contracting. --- lms/static/coffee/src/discussion/discussion.coffee | 9 ++++----- .../views/discussion_thread_inline_view.coffee | 2 ++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lms/static/coffee/src/discussion/discussion.coffee b/lms/static/coffee/src/discussion/discussion.coffee index 002593855c..2944449f61 100644 --- a/lms/static/coffee/src/discussion/discussion.coffee +++ b/lms/static/coffee/src/discussion/discussion.coffee @@ -7,7 +7,6 @@ if Backbone? item.discussion = @ @comparator = @sortByDateRecentFirst @on "thread:remove", (thread) => - console.log "remove triggered" @remove(thread) find: (id) -> @@ -24,8 +23,8 @@ if Backbone? sortByDateRecentFirst: (thread) -> -(new Date(thread.get("created_at")).getTime()) - #return String.fromCharCode.apply(String, - # _.map(thread.get("created_at").split(""), + #return String.fromCharCode.apply(String, + # _.map(thread.get("created_at").split(""), # ((c) -> return 0xffff - c.charChodeAt())) #) @@ -134,7 +133,7 @@ if Backbone? @$(".discussion-submit-post").click $.proxy(@submitNewPost, @) @$(".discussion-cancel-post").click $.proxy(@cancelNewPost, @) - + @$el.children(".blank").hide() @$(".new-post-form").show() @@ -177,7 +176,7 @@ if Backbone? threadView = new ThreadView el: $thread[0], model: thread thread.updateInfo response.annotated_content_info @cancelNewPost() - + cancelNewPost: (event) -> if @$el.hasClass("inline-discussion") diff --git a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee index b7ce771eeb..76037d7341 100644 --- a/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee +++ b/lms/static/coffee/src/discussion/views/discussion_thread_inline_view.coffee @@ -194,6 +194,7 @@ class @DiscussionThreadInlineView extends DiscussionContentView expandPost: (event) -> @expanded = true @$el.find('.post-body').html(@model.get('body')) + @convertMath() @$el.find('.expand-post').hide() @$el.find('.collapse-post').show() @$el.find('.post-extended-content').show() @@ -204,6 +205,7 @@ class @DiscussionThreadInlineView extends DiscussionContentView collapsePost: (event) -> @expanded = false @$el.find('.post-body').html(@model.get('abbreviatedBody')) + @convertMath() @$el.find('.collapse-post').hide() @$el.find('.post-extended-content').hide() @$el.find('.expand-post').show()