diff --git a/common/lib/xmodule/xmodule/discussion_module.py b/common/lib/xmodule/xmodule/discussion_module.py
index 8ae7f9ad93..89bd27a9c7 100644
--- a/common/lib/xmodule/xmodule/discussion_module.py
+++ b/common/lib/xmodule/xmodule/discussion_module.py
@@ -1,5 +1,7 @@
from pkg_resources import resource_string
+import json
+from xblock.core import XBlock
from xmodule.x_module import XModule
from xmodule.raw_module import RawDescriptor
from xmodule.editing_module import MetadataOnlyEditingDescriptor
@@ -41,7 +43,20 @@ class DiscussionFields(object):
sort_key = String(scope=Scope.settings)
+def has_permission(user, permission, course_id):
+ """
+ Copied from django_comment_client/permissions.py because I can't import
+ that file from here. It causes the xmodule_assets command to fail.
+ """
+ return any(role.has_permission(permission)
+ for role in user.roles.filter(course_id=course_id))
+
+
+@XBlock.wants('user')
class DiscussionModule(DiscussionFields, XModule):
+ """
+ XModule for discussion forums.
+ """
js = {
'coffee': [
resource_string(__name__, 'js/src/discussion/display.coffee')
@@ -53,9 +68,26 @@ class DiscussionModule(DiscussionFields, XModule):
js_module_name = "InlineDiscussion"
def get_html(self):
+ course = self.get_course()
+ user = None
+ user_service = self.runtime.service(self, 'user')
+ if user_service:
+ user = user_service._django_user # pylint: disable=protected-access
+ if user:
+ course_key = course.id # pylint: disable=no-member
+ can_create_comment = has_permission(user, "create_comment", course_key)
+ can_create_subcomment = has_permission(user, "create_sub_comment", course_key)
+ can_create_thread = has_permission(user, "create_thread", course_key)
+ else:
+ can_create_comment = False
+ can_create_subcomment = False
+ can_create_thread = False
context = {
'discussion_id': self.discussion_id,
- 'course': self.get_course(),
+ 'course': course,
+ 'can_create_comment': json.dumps(can_create_comment),
+ 'can_create_subcomment': json.dumps(can_create_subcomment),
+ 'can_create_thread': can_create_thread,
}
if getattr(self.system, 'is_author_mode', False):
template = 'discussion/_discussion_module_studio.html'
diff --git a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee
index 8d094c49d0..c969f7edd0 100644
--- a/common/static/coffee/spec/discussion/discussion_spec_helper.coffee
+++ b/common/static/coffee/spec/discussion/discussion_spec_helper.coffee
@@ -37,560 +37,34 @@ class @DiscussionSpecHelper
)
@setUnderscoreFixtures = ->
- for templateName in ['thread-show']
+ templateNames = [
+ 'thread', 'thread-show', 'thread-edit',
+ 'thread-response', 'thread-response-show', 'thread-response-edit',
+ 'response-comment-show', 'response-comment-edit',
+ 'thread-list-item', 'discussion-home', 'search-alert',
+ 'new-post', 'thread-type', 'new-post-menu-entry',
+ 'new-post-menu-category', 'topic', 'post-user-display',
+ ]
+ templateNamesNoTrailingTemplate = [
+ 'forum-action-endorse', 'forum-action-answer', 'forum-action-follow',
+ 'forum-action-vote', 'forum-action-report', 'forum-action-pin',
+ 'forum-action-close', 'forum-action-edit', 'forum-action-delete',
+ 'forum-actions',
+ ]
+
+ for templateName in templateNames
templateFixture = readFixtures('common/templates/discussion/' + templateName + '.underscore')
appendSetFixtures($('
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-""")
+
+
+ """)
diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee
index b30efed581..c2dc5f78dd 100644
--- a/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee
+++ b/common/static/coffee/spec/discussion/view/discussion_thread_list_view_spec.coffee
@@ -415,7 +415,7 @@ describe "DiscussionThreadListView", ->
it "for answered question", ->
renderSingleThreadWithProps({thread_type: "question", endorsed: true})
- expect($(".forum-nav-thread-wrapper-0 .icon")).toHaveClass("fa-check")
+ expect($(".forum-nav-thread-wrapper-0 .icon")).toHaveClass("fa-check-square-o")
expect($(".forum-nav-thread-wrapper-0 .sr")).toHaveText("answered question")
it "for unanswered question", ->
diff --git a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee
index 6757d000f2..85fb7ad760 100644
--- a/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee
+++ b/common/static/coffee/spec/discussion/view/discussion_thread_view_spec.coffee
@@ -80,16 +80,16 @@ describe "DiscussionThreadView", ->
expect(view.$('.display-vote').is(":visible")).toBe(not originallyClosed)
_.each(["tab", "inline"], (mode) =>
- it 'Test that in #{mode} mode when a closed thread is opened the comment form is displayed', ->
+ it "Test that in #{mode} mode when a closed thread is opened the comment form is displayed", ->
checkCommentForm(true, mode)
- it 'Test that in #{mode} mode when a open thread is closed the comment form is hidden', ->
+ it "Test that in #{mode} mode when a open thread is closed the comment form is hidden", ->
checkCommentForm(false, mode)
- it 'Test that in #{mode} mode when a closed thread is opened the vote button is displayed and vote count is hidden', ->
+ it "Test that in #{mode} mode when a closed thread is opened the vote button is displayed and vote count is hidden", ->
checkVoteDisplay(true, mode)
- it 'Test that in #{mode} mode when a open thread is closed the vote button is hidden and vote count is displayed', ->
+ it "Test that in #{mode} mode when a open thread is closed the vote button is hidden and vote count is displayed", ->
checkVoteDisplay(false, mode)
)
diff --git a/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee b/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee
index e6dd3013a9..6458c3cb3d 100644
--- a/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee
+++ b/common/static/coffee/spec/discussion/view/new_post_view_spec.coffee
@@ -180,7 +180,7 @@ describe "NewPostView", ->
eventSpy = jasmine.createSpy('eventSpy')
view.listenTo(view, "newPost:cancel", eventSpy)
view.$(".post-errors").html("Title can't be empty ")
- view.$("label[for$='post-type-discussion']").click()
+ view.$("label[for$='post-type-question']").click()
view.$(".js-post-title").val("Test Title")
view.$(".js-post-body textarea").val("Test body")
view.$(".wmd-preview p").html("Test body")
@@ -192,8 +192,8 @@ describe "NewPostView", ->
view.$(".cancel").click()
expect(eventSpy).toHaveBeenCalled()
expect(view.$(".post-errors").html()).toEqual("");
- expect($("input[id$='post-type-question']")).toBeChecked()
- expect($("input[id$='post-type-discussion']")).not.toBeChecked()
+ expect($("input[id$='post-type-discussion']")).toBeChecked()
+ expect($("input[id$='post-type-question']")).not.toBeChecked()
expect(view.$(".js-post-title").val()).toEqual("");
expect(view.$(".js-post-body textarea").val()).toEqual("");
expect(view.$(".js-follow")).toBeChecked()
diff --git a/common/static/coffee/src/discussion/main.coffee b/common/static/coffee/src/discussion/main.coffee
index 67c15d1e34..5c663ffa21 100644
--- a/common/static/coffee/src/discussion/main.coffee
+++ b/common/static/coffee/src/discussion/main.coffee
@@ -5,6 +5,7 @@ if Backbone?
DiscussionUtil.loadRolesFromContainer()
element = $(elem)
window.$$course_id = element.data("course-id")
+ window.courseName = element.data("course-name")
user_info = element.data("user-info")
sort_preference = element.data("sort-preference")
threads = element.data("threads")
diff --git a/common/static/coffee/src/discussion/views/discussion_thread_list_view.coffee b/common/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
index 9ac93798ec..a01ef013d2 100644
--- a/common/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
+++ b/common/static/coffee/src/discussion/views/discussion_thread_list_view.coffee
@@ -248,7 +248,7 @@ if Backbone?
@$(".forum-nav-thread[data-id='#{thread_id}'] .forum-nav-thread-link").addClass("is-active").find(".forum-nav-thread-wrapper-1").prepend('' + gettext("Current conversation") + ' ')
goHome: ->
- @template = _.template($("#discussion-home").html())
+ @template = _.template($("#discussion-home-template").html())
$(".forum-content").html(@template)
$(".forum-nav-thread-list a").removeClass("is-active").find(".sr").remove()
$("input.email-setting").bind "click", @updateEmailNotifications
diff --git a/common/static/coffee/src/discussion/views/discussion_thread_view.coffee b/common/static/coffee/src/discussion/views/discussion_thread_view.coffee
index ce893c38e7..f369cf6619 100644
--- a/common/static/coffee/src/discussion/views/discussion_thread_view.coffee
+++ b/common/static/coffee/src/discussion/views/discussion_thread_view.coffee
@@ -50,7 +50,13 @@ if Backbone?
renderTemplate: ->
@template = _.template($("#thread-template").html())
- @template(@model.toJSON())
+ templateData = @model.toJSON()
+ container = $("#discussion-container")
+ if !container.length
+ # inline discussion
+ container = $(".discussion-module")
+ templateData.can_create_comment = container.data("user-create-comment")
+ @template(templateData)
render: ->
@$el.html(@renderTemplate())
diff --git a/common/static/coffee/src/discussion/views/thread_response_view.coffee b/common/static/coffee/src/discussion/views/thread_response_view.coffee
index 7418f80e28..a299738d6f 100644
--- a/common/static/coffee/src/discussion/views/thread_response_view.coffee
+++ b/common/static/coffee/src/discussion/views/thread_response_view.coffee
@@ -19,6 +19,11 @@ if Backbone?
templateData = @model.toJSON()
templateData.wmdId = @model.id ? (new Date()).getTime()
+ container = $("#discussion-container")
+ if !container.length
+ # inline discussion
+ container = $(".discussion-module")
+ templateData.create_sub_comment = container.data("user-create-subcomment")
@template(templateData)
render: ->
diff --git a/common/static/common/templates/discussion/discussion-home.underscore b/common/static/common/templates/discussion/discussion-home.underscore
new file mode 100644
index 0000000000..d06a4205fc
--- /dev/null
+++ b/common/static/common/templates/discussion/discussion-home.underscore
@@ -0,0 +1,59 @@
+
+
+
+ <% if (window.ENABLE_DISCUSSION_HOME_PANEL) { %>
+
+ <%- interpolate(gettext("How to use %(platform_name)s discussions"), {platform_name: window.PLATFORM_NAME}, true) %>
+
+
+ <% } %>
+
diff --git a/common/static/common/templates/discussion/forum-action-answer.underscore b/common/static/common/templates/discussion/forum-action-answer.underscore
new file mode 100644
index 0000000000..6f10e860ed
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-answer.underscore
@@ -0,0 +1,10 @@
+
+
+ <%- gettext("Mark as Answer") %>
+
+ <%- gettext("Mark as Answer") %>
+ <%- gettext("Unmark as Answer") %>
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-close.underscore b/common/static/common/templates/discussion/forum-action-close.underscore
new file mode 100644
index 0000000000..61fd9af230
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-close.underscore
@@ -0,0 +1,12 @@
+
+
+ <%- gettext("Close") %>
+
+ <%- gettext("Close") %>
+ <%- gettext("Open") %>
+
+
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-delete.underscore b/common/static/common/templates/discussion/forum-action-delete.underscore
new file mode 100644
index 0000000000..facf308c61
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-delete.underscore
@@ -0,0 +1,6 @@
+
+
+ <%- gettext("Delete") %>
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-edit.underscore b/common/static/common/templates/discussion/forum-action-edit.underscore
new file mode 100644
index 0000000000..1a67c97d90
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-edit.underscore
@@ -0,0 +1,6 @@
+
+
+ <%- gettext("Edit") %>
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-endorse.underscore b/common/static/common/templates/discussion/forum-action-endorse.underscore
new file mode 100644
index 0000000000..98d3fd174b
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-endorse.underscore
@@ -0,0 +1,10 @@
+
+
+ <%- gettext("Endorse") %>
+
+ <%- gettext("Endorse") %>
+ <%- gettext("Unendorse") %>
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-follow.underscore b/common/static/common/templates/discussion/forum-action-follow.underscore
new file mode 100644
index 0000000000..c4adc7aa9f
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-follow.underscore
@@ -0,0 +1,10 @@
+
+
+ <%- gettext("Follow") %>
+
+ <%- gettext("Follow") %>
+ <%- gettext("Unfollow") %>
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-pin.underscore b/common/static/common/templates/discussion/forum-action-pin.underscore
new file mode 100644
index 0000000000..a4b3117bcd
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-pin.underscore
@@ -0,0 +1,12 @@
+
+
+ <%- gettext("Pin") %>
+
+ <%- gettext("Pin") %>
+ <%- gettext("Unpin") %>
+
+
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-report.underscore b/common/static/common/templates/discussion/forum-action-report.underscore
new file mode 100644
index 0000000000..dfc52eaa7b
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-report.underscore
@@ -0,0 +1,12 @@
+
+
+ <%- gettext("Report abuse") %>
+
+ <%- gettext("Report") %>
+ <%- gettext("Unreport") %>
+
+
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-action-vote.underscore b/common/static/common/templates/discussion/forum-action-vote.underscore
new file mode 100644
index 0000000000..b837236e21
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-action-vote.underscore
@@ -0,0 +1,18 @@
+
+
+
+
+
+ <% // Vote counts are populated by JS %>
+ <%- gettext("Vote for this post,") %>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/common/static/common/templates/discussion/forum-actions.underscore b/common/static/common/templates/discussion/forum-actions.underscore
new file mode 100644
index 0000000000..9fd9714a3e
--- /dev/null
+++ b/common/static/common/templates/discussion/forum-actions.underscore
@@ -0,0 +1,16 @@
+
+ <% _.each(primaryActions, function(action) { print(_.template($('#forum-action-' + action).html(), {})) }) %>
+
+
+
+
diff --git a/common/static/common/templates/discussion/new-post-menu-category.underscore b/common/static/common/templates/discussion/new-post-menu-category.underscore
new file mode 100644
index 0000000000..f10d07638f
--- /dev/null
+++ b/common/static/common/templates/discussion/new-post-menu-category.underscore
@@ -0,0 +1,4 @@
+
diff --git a/common/static/common/templates/discussion/new-post-menu-entry.underscore b/common/static/common/templates/discussion/new-post-menu-entry.underscore
new file mode 100644
index 0000000000..bad96e0078
--- /dev/null
+++ b/common/static/common/templates/discussion/new-post-menu-entry.underscore
@@ -0,0 +1,3 @@
+
diff --git a/common/static/common/templates/discussion/new-post.underscore b/common/static/common/templates/discussion/new-post.underscore
new file mode 100644
index 0000000000..7f155841f7
--- /dev/null
+++ b/common/static/common/templates/discussion/new-post.underscore
@@ -0,0 +1,52 @@
+
diff --git a/common/static/common/templates/discussion/post-user-display.underscore b/common/static/common/templates/discussion/post-user-display.underscore
new file mode 100644
index 0000000000..515538fce3
--- /dev/null
+++ b/common/static/common/templates/discussion/post-user-display.underscore
@@ -0,0 +1,10 @@
+<% if (username) { %>
+<%- username %>
+ <% if (is_community_ta) { %>
+
+ <% } else if (is_staff) { %>
+ <%- gettext("Staff") %>
+ <% } %>
+<% } else { %>
+ <%- gettext('anonymous') %>
+<% } %>
diff --git a/common/static/common/templates/discussion/response-comment-edit.underscore b/common/static/common/templates/discussion/response-comment-edit.underscore
new file mode 100644
index 0000000000..5dff8ec978
--- /dev/null
+++ b/common/static/common/templates/discussion/response-comment-edit.underscore
@@ -0,0 +1,9 @@
+
diff --git a/common/static/common/templates/discussion/response-comment-show.underscore b/common/static/common/templates/discussion/response-comment-show.underscore
new file mode 100644
index 0000000000..5f15338f1e
--- /dev/null
+++ b/common/static/common/templates/discussion/response-comment-show.underscore
@@ -0,0 +1,32 @@
+
diff --git a/common/static/common/templates/discussion/search-alert.underscore b/common/static/common/templates/discussion/search-alert.underscore
new file mode 100644
index 0000000000..e75fc65cfd
--- /dev/null
+++ b/common/static/common/templates/discussion/search-alert.underscore
@@ -0,0 +1,9 @@
+
diff --git a/common/static/common/templates/discussion/thread-edit.underscore b/common/static/common/templates/discussion/thread-edit.underscore
new file mode 100644
index 0000000000..a3d83bea03
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-edit.underscore
@@ -0,0 +1,12 @@
+<%- gettext("Editing post") %>
+
+
+
+ <%- gettext("Edit post title") %>
+
+
+
+ ">
+<%- gettext("Cancel") %>
diff --git a/common/static/common/templates/discussion/thread-list-item.underscore b/common/static/common/templates/discussion/thread-list-item.underscore
new file mode 100644
index 0000000000..335085fbc3
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-list-item.underscore
@@ -0,0 +1,97 @@
+ is-unread<% } %>">
+
+
+ <%
+ var icon_class, sr_text;
+ if (thread_type === "discussion") {
+ icon_class = "fa-comments";
+ // Translators: This is a label for a Discussion forum thread
+ sr_text = gettext("discussion");
+ } else if (endorsed) {
+ icon_class = "fa-check-square-o";
+ // Translators: This is a label for a Question forum thread with a marked answer
+ sr_text = gettext("answered question");
+ } else {
+ icon_class = "fa-question";
+ // Translators: This is a label for a Question forum thread without a marked answer
+ sr_text = gettext("unanswered question");
+ }
+ %>
+ <%= sr_text %>
+
+
+
<%- title %>
+ <% if(typeof(subscribed) === "undefined") { var subscribed = null; } %>
+ <% if(pinned || subscribed || staff_authored || community_ta_authored) { %>
+
+ <% if (pinned) { %>
+
+
+ <% // Translators: This is a label for a forum thread that has been pinned %>
+ <%- gettext("Pinned") %>
+
+ <% } %>
+ <% if (subscribed) { %>
+
+
+ <% // Translators: This is a label for a forum thread that the user is subscribed to %>
+ <%- gettext("Following") %>
+
+ <% } %>
+ <% if (staff_authored) { %>
+
+
+ <% // Translators: This is a label for a forum thread that was authored by a member of the course staff %>
+ <%- gettext("By: Staff") %>
+
+ <% } %>
+ <% if (community_ta_authored) { %>
+
+ <% } %>
+
+ <% } %>
+
+ <%
+ // Translators: 'votes_count' is a numerical placeholder for a specific discussion thread; 'span_start' and 'span_end' placeholders refer to HTML markup. Please translate the word 'votes'.
+ var fmt = ngettext(
+ "%(votes_count)s%(span_start)s vote %(span_end)s",
+ "%(votes_count)s%(span_start)s votes %(span_end)s",
+ votes['up_count']
+ );
+ %>
+
+ +<%- interpolate(fmt, {
+ votes_count: votes['up_count'],
+ span_start: '',
+ span_end: ' '
+ }, true)
+ %>
+
+
+
+
+
+
diff --git a/common/static/common/templates/discussion/thread-response-edit.underscore b/common/static/common/templates/discussion/thread-response-edit.underscore
new file mode 100644
index 0000000000..ce3f4c6535
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-response-edit.underscore
@@ -0,0 +1,9 @@
+
diff --git a/common/static/common/templates/discussion/thread-response-show.underscore b/common/static/common/templates/discussion/thread-response-show.underscore
new file mode 100644
index 0000000000..d43fd2d8aa
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-response-show.underscore
@@ -0,0 +1,59 @@
+
+
+<%- body %>
diff --git a/common/static/common/templates/discussion/thread-response.underscore b/common/static/common/templates/discussion/thread-response.underscore
new file mode 100644
index 0000000000..7e3aeffde2
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-response.underscore
@@ -0,0 +1,27 @@
+
+
+
diff --git a/common/static/common/templates/discussion/thread-type.underscore b/common/static/common/templates/discussion/thread-type.underscore
new file mode 100644
index 0000000000..4ba9fa4d70
--- /dev/null
+++ b/common/static/common/templates/discussion/thread-type.underscore
@@ -0,0 +1,23 @@
+
diff --git a/common/static/common/templates/discussion/thread.underscore b/common/static/common/templates/discussion/thread.underscore
new file mode 100644
index 0000000000..3212105475
--- /dev/null
+++ b/common/static/common/templates/discussion/thread.underscore
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+ <%- gettext("Add a Response") %>
+
+
+
+
+
+ <%- gettext("This thread is closed.") %>
+
+ <% if (can_create_comment) { %>
+
+ <% } %>
+
+
+
+
diff --git a/common/static/common/templates/discussion/topic.underscore b/common/static/common/templates/discussion/topic.underscore
new file mode 100644
index 0000000000..b59fd8e771
--- /dev/null
+++ b/common/static/common/templates/discussion/topic.underscore
@@ -0,0 +1,19 @@
+<% // Using div here instead of label because we are using a non-native control %>
+
+
<%- gettext("Topic Area:") %>
+
+ <%- gettext("Add your post to a relevant topic to help others find it.") %>
+
diff --git a/lms/djangoapps/courseware/tests/test_discussion_module.py b/lms/djangoapps/courseware/tests/test_discussion_module.py
new file mode 100644
index 0000000000..d9eb826514
--- /dev/null
+++ b/lms/djangoapps/courseware/tests/test_discussion_module.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+"""Test for Discussion Xmodule functional logic."""
+from mock import Mock
+from . import BaseTestXmodule
+from courseware.module_render import get_module_for_descriptor_internal
+
+
+class DiscussionModuleTest(BaseTestXmodule):
+ """Logic tests for Discussion Xmodule."""
+ CATEGORY = "discussion"
+
+ def test_html_with_user(self):
+ discussion = get_module_for_descriptor_internal(
+ user=self.users[0],
+ descriptor=self.item_descriptor,
+ student_data=Mock(name='student_data'),
+ course_id=self.course.id,
+ track_function=Mock(name='track_function'),
+ xqueue_callback_url_prefix=Mock(name='xqueue_callback_url_prefix'),
+ request_token='request_token',
+ )
+
+ fragment = discussion.render('student_view')
+ html = fragment.content
+ self.assertIn('data-user-create-comment="false"', html)
+ self.assertIn('data-user-create-subcomment="false"', html)
diff --git a/lms/djangoapps/django_comment_client/forum/views.py b/lms/djangoapps/django_comment_client/forum/views.py
index 0b2e1249c7..1521b0d303 100644
--- a/lms/djangoapps/django_comment_client/forum/views.py
+++ b/lms/djangoapps/django_comment_client/forum/views.py
@@ -277,6 +277,11 @@ def forum_form_discussion(request, course_key):
'threads': _attr_safe_json(threads),
'thread_pages': query_params['num_pages'],
'user_info': _attr_safe_json(user_info),
+ 'can_create_comment': _attr_safe_json(
+ has_permission(request.user, "create_comment", course.id)),
+ 'can_create_subcomment': _attr_safe_json(
+ has_permission(request.user, "create_sub_comment", course.id)),
+ 'can_create_thread': has_permission(request.user, "create_thread", course.id),
'flag_moderator': bool(
has_permission(request.user, 'openclose_thread', course.id) or
has_access(request.user, 'staff', course)
@@ -376,6 +381,11 @@ def single_thread(request, course_key, discussion_id, thread_id):
'csrf': csrf(request)['csrf_token'],
'init': '', # TODO: What is this?
'user_info': _attr_safe_json(user_info),
+ 'can_create_comment': _attr_safe_json(
+ has_permission(request.user, "create_comment", course.id)),
+ 'can_create_subcomment': _attr_safe_json(
+ has_permission(request.user, "create_sub_comment", course.id)),
+ 'can_create_thread': has_permission(request.user, "create_thread", course.id),
'annotated_content_info': _attr_safe_json(annotated_content_info),
'course': course,
#'recent_active_threads': recent_active_threads,
diff --git a/lms/templates/discussion/_discussion_module.html b/lms/templates/discussion/_discussion_module.html
index 8789a7492d..aedf007343 100644
--- a/lms/templates/discussion/_discussion_module.html
+++ b/lms/templates/discussion/_discussion_module.html
@@ -1,12 +1,11 @@
<%include file="_underscore_templates.html" />
<%!
from django.utils.translation import ugettext as _
-from django_comment_client.permissions import has_permission
%>
-
+
diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html
index cab9ef174c..35e35785d3 100644
--- a/lms/templates/discussion/_underscore_templates.html
+++ b/lms/templates/discussion/_underscore_templates.html
@@ -1,608 +1,20 @@
<%namespace name='static' file='../static_content.html'/>
-<%!
-from django.utils.translation import ugettext as _
-from django.template.defaultfilters import escapejs
-from django_comment_client.permissions import has_permission
-%>
+<%! import json %>
-## IMPORTANT: In order to keep js tests valid and relevant, please be sure to update the appropriate HTML in
-## common/static/coffee/spec/discussion_spec_helper.coffee is changed and regenerated, whenever this one changes.
-
-% for template_name in ['thread-show']:
+% for template_name in ['thread', 'thread-show', 'thread-edit', 'thread-response', 'thread-response-show', 'thread-response-edit', 'response-comment-show', 'response-comment-edit', 'thread-list-item', 'discussion-home', 'search-alert', 'new-post', 'thread-type', 'new-post-menu-entry', 'new-post-menu-category', 'topic', 'post-user-display']:
% endfor
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<%def name="primaryAction(action_class, icon, sr_label, unchecked_label, checked_label)">
-
-%def>
-
-${primaryAction("endorse", "check", _("Endorse"), _("Endorse"), _("Unendorse"))}
-${primaryAction("answer", "check", _("Mark as Answer"), _("Mark as Answer"), _("Unmark as Answer"))}
-${primaryAction("follow", "star", _("Follow"), _("Follow"), _("Unfollow"))}
-
-
-
-<%def name="secondaryStateAction(action_class, icon, sr_label, unchecked_label, checked_label)">
-
-%def>
-
-${secondaryStateAction("report", "flag", _("Report abuse"), _("Report"), _("Unreport"))}
-${secondaryStateAction("pin", "thumb-tack", _("Pin"), _("Pin"), _("Unpin"))}
-${secondaryStateAction("close", "lock", _("Close"), _("Close"), _("Open"))}
-
-<%def name="secondaryAction(action_class, icon, label)">
-
-%def>
-
-${secondaryAction("edit", "pencil", _("Edit"))}
-${secondaryAction("delete", "remove", _("Delete"))}
-
-
-
-
+% endfor
diff --git a/lms/templates/discussion/index.html b/lms/templates/discussion/index.html
index 9586ba3cef..53497a48a2 100644
--- a/lms/templates/discussion/index.html
+++ b/lms/templates/discussion/index.html
@@ -28,7 +28,10 @@ from django.core.urlresolvers import reverse
-
+