Commit 5dad2afa by Brian Jacobel

Squashed minor issue fixes in inline discussion view

Make this selector more specific, was getting overrides

Fix Teams implementation of inline discussion

Fix LMS tests

Work on pagination support

Jasmine tests for this feature

Focus works when navigating between list and detail

Fix safe template violations
parent a099d600
......@@ -19,11 +19,28 @@
}
},
page_re: /\?discussion_page=(\d+)/,
initialize: function(options) {
var match;
this.$el = options.el;
this.showByDefault = options.showByDefault || false;
this.toggleDiscussionBtn = this.$('.discussion-show');
this.newPostForm = this.$el.find('.new-post-article');
this.listenTo(this.newPostView, 'newPost:cancel', this.hideNewPost);
this.listenTo(this.model, 'change', this.render);
match = this.page_re.exec(window.location.href);
if (match) {
this.page = parseInt(match[1], 10);
} else {
this.page = 1;
}
// By default the view is displayed in a hidden state. If you want it to be shown by default (e.g. in Teams)
// pass showByDefault as an option. This code will open it on initialization.
if (this.showByDefault) {
this.toggleDiscussion();
}
},
loadDiscussions: function($elem, error) {
......@@ -46,7 +63,7 @@
},
renderDiscussion: function($elem, response, textStatus, discussionId) {
var $discussion,
var discussionHtml,
user = new DiscussionUser(response.user_info),
self = this;
......@@ -59,21 +76,21 @@
this.course_settings = new DiscussionCourseSettings(response.course_settings);
this.discussion = new Discussion();
this.discussion = new Discussion(undefined, {pages: response.num_pages});
this.discussion.reset(response.discussion_data, {
silent: false
});
$discussion = _.template($('#inline-discussion-template').html())({
discussionHtml = edx.HtmlUtils.template($('#inline-discussion-template').html())({
threads: response.discussion_data,
read_only: this.readOnly,
discussionId: discussionId
});
if (this.$('section.discussion').length) {
this.$('section.discussion').replaceWith($discussion);
edx.HtmlUtils.setHtml(this.$el, discussionHtml);
} else {
this.$el.append($discussion);
edx.HtmlUtils.append(this.$el, discussionHtml);
}
this.threadListView = new DiscussionThreadListView({
......@@ -138,6 +155,9 @@
// Show the thread list view
this.threadListView.$el.removeClass('is-hidden');
// Set focus to thread list item that was saved as active
this.threadListView.$('.is-active').focus();
},
toggleDiscussion: function() {
......@@ -147,9 +167,10 @@
this.hideDiscussion();
} else {
this.toggleDiscussionBtn.addClass('shown');
this.toggleDiscussionBtn.find('.button-text').html(gettext('Hide Discussion'));
this.toggleDiscussionBtn.find('.button-text').text(gettext('Hide Discussion'));
if (this.retrieved) {
this.$('section.discussion').slideDown();
this.$('section.discussion').removeClass('is-hidden');
this.showed = true;
} else {
this.loadDiscussions(this.$el, function() {
......@@ -165,8 +186,9 @@
hideDiscussion: function() {
this.$('section.discussion').slideUp();
this.$('section.discussion').addClass('is-hidden');
this.toggleDiscussionBtn.removeClass('shown');
this.toggleDiscussionBtn.find('.button-text').html(gettext('Show Discussion'));
this.toggleDiscussionBtn.find('.button-text').text(gettext('Show Discussion'));
this.showed = false;
},
......@@ -182,13 +204,15 @@
} else {
this.newPostForm.show().focus();
}
this.newPostView.$el.removeClass('is-hidden');
this.toggleDiscussionBtn.addClass('shown');
this.toggleDiscussionBtn.find('.button-text').html(gettext('Hide Discussion'));
this.toggleDiscussionBtn.find('.button-text').text(gettext('Hide Discussion'));
this.$('section.discussion').slideDown();
this.showed = true;
},
hideNewPost: function() {
this.newPostView.$el.addClass('is-hidden');
return this.newPostForm.slideUp(300);
}
});
......
/* globals
_, Discussion, DiscussionCourseSettings, DiscussionViewSpecHelper, DiscussionSpecHelper,
DiscussionInlineView, DiscussionUtil, DiscussionThreadShowView, Thread
*/
(function() {
'use strict';
describe('DiscussionInlineView', function() {
var createTestView, showDiscussion, setNextAjaxResult,
TEST_THREAD_TITLE = 'Test thread title';
beforeEach(function() {
DiscussionSpecHelper.setUpGlobals();
setFixtures(
'<div class="discussion-module" data-discussion-id="test-discussion-id"' +
' data-user-create-comment="true"' +
' data-user-create-subcomment="true"' +
' data-read-only="false">' +
' <div class="discussion-module-header">' +
' <h3 class="discussion-module-title">Test Discussion</h3>' +
' <div class="inline-discussion-topic">' +
' <span class="inline-discussion-topic-title">Topic:</span> Category / Target ' +
' </div>' +
' </div>' +
' <button class="discussion-show btn btn-brand" data-discussion-id="test-discussion-id">' +
' <span class="button-text">Show Discussion</span>' +
' </button>' +
'</div>'
);
DiscussionSpecHelper.setUnderscoreFixtures();
this.ajaxSpy = spyOn($, 'ajax');
// Don't attempt to render markdown
spyOn(DiscussionUtil, 'makeWmdEditor');
spyOn(DiscussionThreadShowView.prototype, 'convertMath');
});
createTestView = function() {
var testView = new DiscussionInlineView({
el: $('.discussion-module')
});
testView.render();
return testView;
};
showDiscussion = function(test, testView) {
setNextAjaxResult(test, {
user_info: DiscussionSpecHelper.getTestUserInfo(),
roles: DiscussionSpecHelper.getTestRoleInfo(),
course_settings: DiscussionSpecHelper.createTestCourseSettings().attributes,
discussion_data: DiscussionViewSpecHelper.makeThreadWithProps({
commentable_id: 'test-topic',
title: TEST_THREAD_TITLE
}),
page: 1,
num_pages: 1
});
testView.$('.discussion-show').click();
};
setNextAjaxResult = function(test, result) {
test.ajaxSpy.and.callFake(function(params) {
var deferred = $.Deferred();
deferred.resolve();
params.success(result);
return deferred;
});
};
describe('inline discussion', function() {
it('is shown after "Show Discussion" is clicked', function() {
var testView = createTestView(this),
showButton = testView.$('.discussion-show');
showDiscussion(this, testView);
// Verify that the discussion is now shown
expect(showButton).toHaveClass('shown');
expect(showButton.text().trim()).toEqual('Hide Discussion');
expect(testView.$('.inline-discussion:visible')).not.toHaveClass('is-hidden');
});
it('is hidden after "Hide Discussion" is clicked', function() {
var testView = createTestView(this),
showButton = testView.$('.discussion-show');
showDiscussion(this, testView);
// Hide the discussion by clicking the toggle button again
testView.$('.discussion-show').click();
// Verify that the discussion is now hidden
expect(showButton).not.toHaveClass('shown');
expect(showButton.text().trim()).toEqual('Show Discussion');
expect(testView.$('.inline-discussion:visible')).toHaveClass('is-hidden');
});
});
describe('new post form', function() {
it('should not be visible when the discussion is first shown', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
expect(testView.$('.new-post-article')).toHaveClass('is-hidden');
});
it('should be shown when the "Add a Post" button is clicked', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
testView.$('.new-post-btn').click();
expect(testView.$('.new-post-article')).not.toHaveClass('is-hidden');
});
it('should be hidden when the "Cancel" button is clicked', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
testView.$('.new-post-btn').click();
testView.$('.forum-new-post-form .cancel').click();
expect(testView.$('.new-post-article')).toHaveClass('is-hidden');
});
});
describe('thread listing', function() {
it('builds a view that lists the threads', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
expect(testView.$('.forum-nav-thread-title').text()).toBe(TEST_THREAD_TITLE);
});
});
describe('thread post drill down', function() {
it('can drill down to a thread', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
testView.$('.forum-nav-thread-link').click();
// Verify that the list of threads is hidden
expect(testView.$('.inline-threads')).toHaveClass('is-hidden');
// Verify that the individual thread is shown
expect(testView.$('.group-visibility-label').text().trim()).toBe('This post is visible to everyone.');
});
it('can go back to the list of threads', function() {
var testView = createTestView(this);
showDiscussion(this, testView);
testView.$('.forum-nav-thread-link').click();
testView.$('.all-posts-btn').click();
// Verify that the list of threads is shown
expect(testView.$('.inline-threads')).not.toHaveClass('is-hidden');
// Verify that the individual thread is no longer shown
expect(testView.$('.group-visibility-label').length).toBe(0);
});
});
});
}());
/* global Content, Discussion, DiscussionCourseSettings, DiscussionUtil, DiscussionUser */
/* global _, Content, Discussion, DiscussionCourseSettings, DiscussionUtil, DiscussionUser */
(function() {
'use strict';
this.DiscussionSpecHelper = (function() {
......@@ -51,8 +51,9 @@
return jasmine.createSpyObj('event', ['preventDefault', 'target']);
};
DiscussionSpecHelper.createTestCourseSettings = function() {
return new DiscussionCourseSettings({
DiscussionSpecHelper.createTestCourseSettings = function(options) {
var context = _.extend(
{
category_map: {
children: [['Test Topic', 'entry'], ['Other Topic', 'entry']],
entries: {
......@@ -66,8 +67,13 @@
}
}
},
is_cohorted: true
});
is_cohorted: true,
allow_anonymous: false,
allow_anonymous_to_peers: false
},
options || {}
);
return new DiscussionCourseSettings(context);
};
DiscussionSpecHelper.createTestDiscussion = function(options) {
......
<section class="discussion inline-discussion" data-discussion-id="<%= discussionId %>">
<section class="discussion inline-discussion" data-discussion-id="<%- discussionId %>">
<div class="add_post_btn_container">
<button class="btn-link new-post-btn <%if (read_only) {%>is-hidden<%} %>"><%- gettext("Add a Post") %></button>
</div>
<article class="new-post-article"></article>
<article class="new-post-article is-hidden"></article>
<section class="inline-threads">
</section>
......@@ -19,3 +19,4 @@
</div>
</div>
</section>
......@@ -504,7 +504,7 @@ class InlineDiscussionPage(PageObject):
).fulfill()
def get_num_displayed_threads(self):
return len(self._find_within(".discussion-thread"))
return len(self._find_within(".forum-nav-thread"))
def has_thread(self, thread_id):
"""Returns true if this page is showing the thread with the specified id."""
......
......@@ -1067,6 +1067,20 @@ class InlineDiscussionTest(UniqueCourseTest, DiscussionResponsePaginationTestMix
# Check if 'thread-wrapper' is focused after expanding thread
self.assertFalse(thread_page.check_if_selector_is_focused(selector='.thread-wrapper'))
@attr('a11y')
def test_inline_a11y(self):
"""
Tests Inline Discussion for accessibility issues.
"""
self.setup_multiple_inline_threads(thread_count=3)
self.discussion_page.expand_discussion()
self.discussion_page.a11y_audit.config.set_rules({
'ignore': [
'section'
]
})
self.discussion_page.a11y_audit.check_for_accessibility_errors()
def test_add_a_post_is_present_if_can_create_thread_when_expanded(self):
self.discussion_page.expand_discussion()
# Add a Post link is present
......
......@@ -82,7 +82,7 @@ DiscussionBoardFactory({
</aside>
<main id="main" aria-label="Content" tabindex="-1" class="discussion-column layout-col layout-col-b">
<article class="new-post-article" style="display: none" tabindex="-1" aria-label="${_("New topic form")}"></article>
<article class="new-post-article is-hidden" style="display: none" tabindex="-1" aria-label="${_("New topic form")}"></article>
<div class="forum-content"></div>
</main>
</div>
......
......@@ -101,7 +101,7 @@ define([
it('can render itself', function() {
var requests = AjaxHelpers.requests(this),
view = createTeamProfileView(requests, {});
expect(view.$('.discussion-thread').length).toEqual(3);
expect(view.$('.forum-nav-thread').length).toEqual(3);
});
it('shows New Post button when user joins a team', function() {
......
......@@ -12,7 +12,8 @@
render: function() {
var discussionInlineView = new DiscussionInlineView({
el: this.$el
el: this.$el,
showByDefault: true
});
discussionInlineView.render();
return this;
......
## mako
<%page expression_filter="h"/>
<%! import json %>
<%!
from django.utils.translation import ugettext as _
......@@ -55,3 +58,4 @@ from openedx.core.djangolib.js_utils import (
</%block>
<%include file="../discussion/_underscore_templates.html" />
<%include file="../discussion/_thread_list_template.html" />
......@@ -323,8 +323,8 @@ body.discussion {
.add_post_btn_container {
@include text-align(right);
position: relative;
top: -25px;
width: flex-grid(12);
height: (2 * $baseline);
}
div.add-response.post-extended-content {
......@@ -356,8 +356,6 @@ section.discussion {
}
.new-post-article {
display: none;
.inner-wrapper {
max-width: 1180px;
min-width: 760px;
......
......@@ -194,10 +194,14 @@
}
}
// Overrides underspecific style from courseware css:
// https://github.com/edx/edx-platform/blob/master/lms/static/sass/course/courseware/_courseware.scss#L402
.course-wrapper .course-content .forum-nav-thread-list li {
// Overrides underspecific styles from courseware css
.course-wrapper .course-content .forum-nav-thread-list-wrapper .forum-nav-thread-list {
@include padding-left(0);
list-style: none;
li {
margin: 0;
}
}
.forum-nav-thread {
......@@ -229,7 +233,25 @@
background-color: $forum-color-hover-thread;
}
&.is-active {
.forum-nav-thread-unread-comments-count {
display: inline-block;
font-size: $forum-small-font-size;
white-space: nowrap;
}
}
.discussion:not(.inline-discussion)
&.never-read {
.forum-nav-thread-link {
@include border-left(3px solid $forum-color-never-read-post);
color: $forum-color-never-read-post;
}
}
}
.discussion:not(.inline-discussion) .forum-nav-thread {
.forum-nav-thread-link.is-active {
color: $forum-color-background;
background-color: $forum-color-reading-thread;
......@@ -258,20 +280,6 @@
color: $forum-color-background;
}
}
.forum-nav-thread-unread-comments-count {
display: inline-block;
font-size: $forum-small-font-size;
white-space: nowrap;
}
}
&.never-read {
.forum-nav-thread-link {
@include border-left(3px solid $forum-color-never-read-post);
color: $forum-color-never-read-post;
}
}
}
%forum-nav-thread-wrapper {
......
// forums - inline discussion styling
// ====================
.inline-discussion {
padding-top: $baseline * 1.5;
.discussion.inline-discussion {
padding-top: $baseline;
.inline-threads {
border: 1px solid $forum-color-border;
......@@ -23,8 +23,20 @@
.forum-content {
padding: $baseline / 2;
max-height: 500px;
overflow-y: auto;
}
}
.wmd-preview-container {
@include discussion-new-post-wmd-preview-container;
margin-bottom: $baseline;
}
.wmd-preview-label {
@include discussion-wmd-preview-label;
}
.wmd-preview {
@include discussion-wmd-preview;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment