Commit a60d456f by Brian Jacobel

Add breadcrumbs to discussion forums header

parent 6c540351
......@@ -392,10 +392,10 @@
};
DiscussionThreadListView.prototype.threadSelected = function(e) {
var thread_id;
thread_id = $(e.target).closest('.forum-nav-thread').attr('data-id');
this.setActiveThread(thread_id);
this.trigger('thread:selected', thread_id);
var threadId;
threadId = $(e.target).closest('.forum-nav-thread').attr('data-id');
this.setActiveThread(threadId);
this.trigger('thread:selected', threadId);
return false;
};
......@@ -479,6 +479,22 @@
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) {
var items, query,
self = this;
......@@ -568,25 +584,28 @@
};
DiscussionThreadListView.prototype.selectTopic = function($target) {
var allItems, discussionIds, item;
var allItems, discussionIds, $item;
this.hideBrowseMenu();
this.clearSearch();
item = $target.closest('.forum-nav-browse-menu-item');
this.setCurrentTopicDisplay(this.getPathText(item));
if (item.hasClass('forum-nav-browse-menu-all')) {
$item = $target.closest('.forum-nav-browse-menu-item');
this.setCurrentTopicDisplay(this.getPathText($item));
this.trigger('topic:selected', this.getBreadcrumbText($item));
if ($item.hasClass('forum-nav-browse-menu-all')) {
this.discussionIds = '';
this.$('.forum-nav-filter-cohort').show();
return this.retrieveAllThreads();
} else if (item.hasClass('forum-nav-browse-menu-following')) {
} else if ($item.hasClass('forum-nav-browse-menu-following')) {
this.retrieveFollowed();
return this.$('.forum-nav-filter-cohort').hide();
} 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) {
return $(elem).data('discussion-id');
}).get();
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):
@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):
"""
Tests for the discussion page displaying a single thread
......
......@@ -6,9 +6,10 @@
'jquery',
'backbone',
'discussion/js/discussion_router',
'discussion/js/views/discussion_fake_breadcrumbs',
'common/js/discussion/views/new_post_view'
],
function($, Backbone, DiscussionRouter, NewPostView) {
function($, Backbone, DiscussionRouter, DiscussionFakeBreadcrumbs, NewPostView) {
return function(options) {
var userInfo = options.user_info,
sortPreference = options.sort_preference,
......@@ -19,7 +20,10 @@
discussion,
courseSettings,
newPostView,
router;
router,
breadcrumbs,
BreadcrumbsModel;
// TODO: Perhaps eliminate usage of global variables when possible
window.DiscussionUtil.loadRoles(options.roles);
window.$$course_id = options.courseId;
......@@ -27,6 +31,7 @@
window.DiscussionUtil.setUser(user);
window.user = user;
window.Content.loadContentInfos(contentInfo);
discussion = new window.Discussion(threads, {pages: threadPages, sort: sortPreference});
courseSettings = new window.DiscussionCourseSettings(options.course_settings);
......@@ -47,6 +52,30 @@
newPostView: newPostView
});
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);
/**
* 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({
<header class="page-header has-secondary">
<div class="page-header-main">
<div class="sr-is-focusable" tabindex="-1"></div>
<h2 class="hd hd-2 page-title">${_("Discussion")}</h2>
<div class="has-breadcrumbs"></div>
</div>
<div class="page-header-secondary">
% if has_permission(user, 'create_thread', course.id):
......
......@@ -29,6 +29,13 @@
position: relative;
}
// Temporary breadcrumbs
.has-breadcrumbs {
.breadcrumbs {
margin: 5px 0 0 0;
}
}
// ------------------------
// navigation - browse menu
// ------------------------
......@@ -160,7 +167,7 @@ li[class*=forum-nav-thread-label-] {
// Inline Discussion Module Overrides
// -------
.discussion-module {
.wrapper-post-header .post-title {
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