Commit a60d456f by Brian Jacobel

Add breadcrumbs to discussion forums header

parent 6c540351
...@@ -392,10 +392,10 @@ ...@@ -392,10 +392,10 @@
}; };
DiscussionThreadListView.prototype.threadSelected = function(e) { DiscussionThreadListView.prototype.threadSelected = function(e) {
var thread_id; var threadId;
thread_id = $(e.target).closest('.forum-nav-thread').attr('data-id'); threadId = $(e.target).closest('.forum-nav-thread').attr('data-id');
this.setActiveThread(thread_id); this.setActiveThread(threadId);
this.trigger('thread:selected', thread_id); this.trigger('thread:selected', threadId);
return false; return false;
}; };
...@@ -479,6 +479,22 @@ ...@@ -479,6 +479,22 @@
return pathTitles.join(' / '); return pathTitles.join(' / ');
}; };
DiscussionThreadListView.prototype.getBreadcrumbText = function($item) {
var subTopic = $('.forum-nav-browse-title', $item).first().text().trim(),
$parentSubMenus = $item.parents('.forum-nav-browse-submenu'),
crumbs = [];
$parentSubMenus.each(function(i, el) {
crumbs.push($(el).siblings('.forum-nav-browse-title').first().text().trim());
});
if (subTopic !== 'All Discussions') {
crumbs.push(subTopic);
}
return crumbs;
};
DiscussionThreadListView.prototype.filterTopics = function(event) { DiscussionThreadListView.prototype.filterTopics = function(event) {
var items, query, var items, query,
self = this; self = this;
...@@ -568,25 +584,28 @@ ...@@ -568,25 +584,28 @@
}; };
DiscussionThreadListView.prototype.selectTopic = function($target) { DiscussionThreadListView.prototype.selectTopic = function($target) {
var allItems, discussionIds, item; var allItems, discussionIds, $item;
this.hideBrowseMenu(); this.hideBrowseMenu();
this.clearSearch(); this.clearSearch();
item = $target.closest('.forum-nav-browse-menu-item'); $item = $target.closest('.forum-nav-browse-menu-item');
this.setCurrentTopicDisplay(this.getPathText(item));
if (item.hasClass('forum-nav-browse-menu-all')) { this.setCurrentTopicDisplay(this.getPathText($item));
this.trigger('topic:selected', this.getBreadcrumbText($item));
if ($item.hasClass('forum-nav-browse-menu-all')) {
this.discussionIds = ''; this.discussionIds = '';
this.$('.forum-nav-filter-cohort').show(); this.$('.forum-nav-filter-cohort').show();
return this.retrieveAllThreads(); return this.retrieveAllThreads();
} else if (item.hasClass('forum-nav-browse-menu-following')) { } else if ($item.hasClass('forum-nav-browse-menu-following')) {
this.retrieveFollowed(); this.retrieveFollowed();
return this.$('.forum-nav-filter-cohort').hide(); return this.$('.forum-nav-filter-cohort').hide();
} else { } else {
allItems = item.find('.forum-nav-browse-menu-item').andSelf(); allItems = $item.find('.forum-nav-browse-menu-item').andSelf();
discussionIds = allItems.filter('[data-discussion-id]').map(function(i, elem) { discussionIds = allItems.filter('[data-discussion-id]').map(function(i, elem) {
return $(elem).data('discussion-id'); return $(elem).data('discussion-id');
}).get(); }).get();
this.retrieveDiscussions(discussionIds); this.retrieveDiscussions(discussionIds);
return this.$('.forum-nav-filter-cohort').toggle(item.data('cohorted') === true); return this.$('.forum-nav-filter-cohort').toggle($item.data('cohorted') === true);
} }
}; };
......
...@@ -218,6 +218,57 @@ class DiscussionHomePageTest(UniqueCourseTest): ...@@ -218,6 +218,57 @@ class DiscussionHomePageTest(UniqueCourseTest):
@attr(shard=2) @attr(shard=2)
class DiscussionNavigationTest(BaseDiscussionTestCase):
"""
Tests for breadcrumbs navigation in the Discussions page nav bar
"""
def setUp(self):
super(DiscussionNavigationTest, self).setUp()
AutoAuthPage(self.browser, course_id=self.course_id).visit()
thread_id = "test_thread_{}".format(uuid4().hex)
thread_fixture = SingleThreadViewFixture(
Thread(
id=thread_id,
body=THREAD_CONTENT_WITH_LATEX,
commentable_id=self.discussion_id
)
)
thread_fixture.push()
self.thread_page = DiscussionTabSingleThreadPage(
self.browser,
self.course_id,
self.discussion_id,
thread_id
)
self.thread_page.visit()
def test_breadcrumbs_push_topic(self):
topic_button = self.thread_page.q(
css=".forum-nav-browse-menu-item[data-discussion-id='{}']".format(self.discussion_id)
)
self.assertTrue(topic_button.visible)
topic_button.click()
# Verify the thread's topic has been pushed to breadcrumbs
breadcrumbs = self.thread_page.q(css=".breadcrumbs .nav-item")
self.assertEqual(len(breadcrumbs), 2)
self.assertEqual(breadcrumbs[1].text, "Test Discussion Topic")
def test_breadcrumbs_back_to_all_topics(self):
topic_button = self.thread_page.q(
css=".forum-nav-browse-menu-item[data-discussion-id='{}']".format(self.discussion_id)
)
self.assertTrue(topic_button.visible)
topic_button.click()
# Verify clicking the first breadcrumb takes you back to all topics
self.thread_page.q(css=".breadcrumbs .nav-item")[0].click()
self.assertEqual(len(self.thread_page.q(css=".breadcrumbs .nav-item")), 1)
@attr(shard=2)
class DiscussionTabSingleThreadTest(BaseDiscussionTestCase, DiscussionResponsePaginationTestMixin): class DiscussionTabSingleThreadTest(BaseDiscussionTestCase, DiscussionResponsePaginationTestMixin):
""" """
Tests for the discussion page displaying a single thread Tests for the discussion page displaying a single thread
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
'jquery', 'jquery',
'backbone', 'backbone',
'discussion/js/discussion_router', 'discussion/js/discussion_router',
'discussion/js/views/discussion_fake_breadcrumbs',
'common/js/discussion/views/new_post_view' 'common/js/discussion/views/new_post_view'
], ],
function($, Backbone, DiscussionRouter, NewPostView) { function($, Backbone, DiscussionRouter, DiscussionFakeBreadcrumbs, NewPostView) {
return function(options) { return function(options) {
var userInfo = options.user_info, var userInfo = options.user_info,
sortPreference = options.sort_preference, sortPreference = options.sort_preference,
...@@ -19,7 +20,10 @@ ...@@ -19,7 +20,10 @@
discussion, discussion,
courseSettings, courseSettings,
newPostView, newPostView,
router; router,
breadcrumbs,
BreadcrumbsModel;
// TODO: Perhaps eliminate usage of global variables when possible // TODO: Perhaps eliminate usage of global variables when possible
window.DiscussionUtil.loadRoles(options.roles); window.DiscussionUtil.loadRoles(options.roles);
window.$$course_id = options.courseId; window.$$course_id = options.courseId;
...@@ -27,6 +31,7 @@ ...@@ -27,6 +31,7 @@
window.DiscussionUtil.setUser(user); window.DiscussionUtil.setUser(user);
window.user = user; window.user = user;
window.Content.loadContentInfos(contentInfo); window.Content.loadContentInfos(contentInfo);
discussion = new window.Discussion(threads, {pages: threadPages, sort: sortPreference}); discussion = new window.Discussion(threads, {pages: threadPages, sort: sortPreference});
courseSettings = new window.DiscussionCourseSettings(options.course_settings); courseSettings = new window.DiscussionCourseSettings(options.course_settings);
...@@ -47,6 +52,30 @@ ...@@ -47,6 +52,30 @@
newPostView: newPostView newPostView: newPostView
}); });
router.start(); router.start();
BreadcrumbsModel = Backbone.Model.extend({
defaults: {
contents: [],
}
});
breadcrumbs = new DiscussionFakeBreadcrumbs({
el: $('.has-breadcrumbs'),
model: new BreadcrumbsModel(),
events: {
'click .all-topics': function(event) {
event.preventDefault();
this.model.set('contents', []);
router.navigate('', {trigger: true});
router.nav.selectTopic($('.forum-nav-browse-menu-all'));
}
}
}).render();
// Add new breadcrumbs when the user selects topics
router.nav.on('topic:selected', function(topic) {
breadcrumbs.model.set('contents', topic);
});
}; };
}); });
}).call(this, define || RequireJS.define); }).call(this, define || RequireJS.define);
/**
* This Backbone view mimics the appearance of breadcrumbs, but does not provide true breadcrumb navigation.
* This implementation is a stopgap developed due to limitations in the Discussions UI.
* Don't use this breadcrumbs implementation as a model or reference.
* Instead, check out the UXPL's breadcrumbs, which have been vetted for UX and A11Y.
* http://ux.edx.org/components/breadcrumbs/
*/
(function(define) {
'use strict';
define([
'backbone',
'edx-ui-toolkit/js/utils/html-utils',
'text!discussion/templates/fake-breadcrumbs.underscore',
],
function(Backbone, HtmlUtils, breadcrumbsTemplate) {
var DiscussionFakeBreadcrumbs = Backbone.View.extend({
initialize: function() {
this.template = HtmlUtils.template(breadcrumbsTemplate);
this.listenTo(this.model, 'change', this.render);
this.render();
},
render: function() {
var json = this.model.attributes;
HtmlUtils.setHtml(this.$el, this.template(json));
return this;
}
});
return DiscussionFakeBreadcrumbs;
});
}).call(this, define || RequireJS.define);
<h6 class="hd-6 breadcrumbs">
<span class="nav-item">
<a class="all-topics" href="">All Topics</a>
</span>
<% contents.forEach(function(content) { %>
<span class="fa fa-angle-right"></span>
<span class="nav-item"><%- content %></span>
<% }); %>
</h6>
...@@ -57,7 +57,7 @@ DiscussionBoardFactory({ ...@@ -57,7 +57,7 @@ DiscussionBoardFactory({
<header class="page-header has-secondary"> <header class="page-header has-secondary">
<div class="page-header-main"> <div class="page-header-main">
<div class="sr-is-focusable" tabindex="-1"></div> <div class="sr-is-focusable" tabindex="-1"></div>
<h2 class="hd hd-2 page-title">${_("Discussion")}</h2> <div class="has-breadcrumbs"></div>
</div> </div>
<div class="page-header-secondary"> <div class="page-header-secondary">
% if has_permission(user, 'create_thread', course.id): % if has_permission(user, 'create_thread', course.id):
......
...@@ -29,6 +29,13 @@ ...@@ -29,6 +29,13 @@
position: relative; position: relative;
} }
// Temporary breadcrumbs
.has-breadcrumbs {
.breadcrumbs {
margin: 5px 0 0 0;
}
}
// ------------------------ // ------------------------
// navigation - browse menu // navigation - browse menu
// ------------------------ // ------------------------
...@@ -160,7 +167,7 @@ li[class*=forum-nav-thread-label-] { ...@@ -160,7 +167,7 @@ li[class*=forum-nav-thread-label-] {
// Inline Discussion Module Overrides // Inline Discussion Module Overrides
// ------- // -------
.discussion-module { .discussion-module {
.wrapper-post-header .post-title { .wrapper-post-header .post-title {
margin-bottom: 0 !important; // overrides "#seq_content h1" styling margin-bottom: 0 !important; // overrides "#seq_content h1" styling
} }
......
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