diff --git a/common/test/acceptance/pages/lms/teams.py b/common/test/acceptance/pages/lms/teams.py index 486dce4e38..f031f7ee1b 100644 --- a/common/test/acceptance/pages/lms/teams.py +++ b/common/test/acceptance/pages/lms/teams.py @@ -18,4 +18,4 @@ class TeamsPage(CoursePage): def get_body_text(self): """ Returns the current dummy text. This will be changed once there is more content on the page. """ - return self.q(css='.teams-text').text[0] + return self.q(css='.page-content-main').text[0] diff --git a/lms/djangoapps/teams/static/teams/js/spec/teams_factory_spec.js b/lms/djangoapps/teams/static/teams/js/spec/teams_factory_spec.js index 6a4c3b9115..e7b5874aff 100644 --- a/lms/djangoapps/teams/static/teams/js/spec/teams_factory_spec.js +++ b/lms/djangoapps/teams/static/teams/js/spec/teams_factory_spec.js @@ -1,5 +1,5 @@ -define(["jquery", "teams/js/teams_tab_factory"], - function($, TeamsTabFactory) { +define(["jquery", "backbone", "teams/js/teams_tab_factory"], + function($, Backbone, TeamsTabFactory) { 'use strict'; describe("teams django app", function() { @@ -10,6 +10,10 @@ define(["jquery", "teams/js/teams_tab_factory"], teamsTab = new TeamsTabFactory(); }); + afterEach(function() { + Backbone.history.stop(); + }); + it("can load templates", function() { expect($("body").text()).toContain("This is the new Teams tab"); }); diff --git a/lms/djangoapps/teams/static/teams/js/views/teams_tab.js b/lms/djangoapps/teams/static/teams/js/views/teams_tab.js index 27c884d1e8..a8f9ea982c 100644 --- a/lms/djangoapps/teams/static/teams/js/views/teams_tab.js +++ b/lms/djangoapps/teams/static/teams/js/views/teams_tab.js @@ -6,8 +6,8 @@ 'gettext', 'js/components/header/views/header', 'js/components/header/models/header', - 'text!teams/templates/teams-tab.underscore'], - function (Backbone, _, gettext, HeaderView, HeaderModel, teamsTabTemplate) { + 'js/components/tabbed/views/tabbed_view'], + function (Backbone, _, gettext, HeaderView, HeaderModel, TabbedView) { var TeamTabView = Backbone.View.extend({ initialize: function() { this.headerModel = new HeaderModel({ @@ -17,12 +17,35 @@ this.headerView = new HeaderView({ model: this.headerModel }); + // TODO replace this with actual views! + var TempTabView = Backbone.View.extend({ + initialize: function (options) { + this.text = options.text; + }, + + render: function () { + this.$el.text(this.text) + } + }); + this.tabbedView = new TabbedView({ + tabs: [{ + title: gettext('My Teams'), + url: 'teams', + view: new TempTabView({text: 'This is the new Teams tab.'}) + }, { + title: gettext('Browse'), + url: 'browse', + view: new TempTabView({text: 'Browse team topics here.'}) + }] + }); + Backbone.history.start(); }, render: function() { - this.$el.html(_.template(teamsTabTemplate, {})); - this.$el.prepend(this.headerView.$el); + this.$el.append(this.headerView.$el); this.headerView.render(); + this.$el.append(this.tabbedView.$el); + this.tabbedView.render(); } }); diff --git a/lms/djangoapps/teams/static/teams/templates/teams-tab.underscore b/lms/djangoapps/teams/static/teams/templates/teams-tab.underscore deleted file mode 100644 index e9411c5ab0..0000000000 --- a/lms/djangoapps/teams/static/teams/templates/teams-tab.underscore +++ /dev/null @@ -1 +0,0 @@ -
This is the new Teams tab.
diff --git a/lms/static/js/components/tabbed/views/tabbed_view.js b/lms/static/js/components/tabbed/views/tabbed_view.js new file mode 100644 index 0000000000..a3c4dfd8c5 --- /dev/null +++ b/lms/static/js/components/tabbed/views/tabbed_view.js @@ -0,0 +1,59 @@ +;(function (define) { + 'use strict'; + define(['backbone', + 'underscore', + 'jquery', + 'text!templates/components/tabbed/tabbed_view.underscore', + 'text!templates/components/tabbed/tab.underscore'], + function (Backbone, _, $, tabbedViewTemplate, tabTemplate) { + var TabbedView = Backbone.View.extend({ + events: { + 'click .nav-item': 'switchTab' + }, + + template: _.template(tabbedViewTemplate), + + /** + * View for a tabbed interface. Expects a list of tabs + * in its options object, each of which should contain the + * following properties: + * view (Backbone.View): the view to render for this tab. + * title (string): The title to display for this tab. + * url (string): The URL fragment which will navigate to this tab. + */ + initialize: function (options) { + this.router = new Backbone.Router(); + this.$el.html(this.template({})); + var self = this; + this.tabs = options.tabs; + _.each(this.tabs, function(tabInfo, index) { + var tabEl = $(_.template(tabTemplate, { + index: index, + title: tabInfo.title + })); + self.$('.page-content-nav').append(tabEl); + + self.router.route(tabInfo.url, function () { + self.setActiveTab(index); + }); + }); + this.setActiveTab(0); + }, + + setActiveTab: function (index) { + this.$('a.is-active').removeClass('is-active').attr('aria-selected', 'false'); + this.$('a[data-index='+index+']').addClass('is-active').attr('aria-selected', 'true'); + var view = this.tabs[index].view; + view.render(); + this.$('.page-content-main').html(view.$el.html()); + this.$('.sr-is-focusable').focus(); + }, + + switchTab: function (event) { + event.preventDefault(); + this.setActiveTab($(event.currentTarget).data('index')); + } + }); + return TabbedView; + }); +}).call(this, define || RequireJS.define); diff --git a/lms/static/js/spec/components/tabbed/tabbed_view_spec.js b/lms/static/js/spec/components/tabbed/tabbed_view_spec.js new file mode 100644 index 0000000000..69a18e045e --- /dev/null +++ b/lms/static/js/spec/components/tabbed/tabbed_view_spec.js @@ -0,0 +1,78 @@ +(function (define) { + 'use strict'; + + define(['jquery', + 'underscore', + 'backbone', + 'js/components/tabbed/views/tabbed_view' + ], + function($, _, Backbone, TabbedView) { + var view, + TestSubview = Backbone.View.extend({ + initialize: function (options) { + this.text = options.text; + }, + + render: function () { + this.$el.text(this.text); + } + }); + + describe('TabbedView component', function () { + beforeEach(function () { + spyOn(Backbone.history, 'navigate').andCallThrough(); + Backbone.history.start(); + view = new TabbedView({ + tabs: [{ + url: 'test 1', + title: 'Test 1', + view: new TestSubview({text: 'this is test text'}) + }, { + url: 'test 2', + title: 'Test 2', + view: new TestSubview({text: 'other text'}) + }] + }); + }); + + afterEach(function () { + Backbone.history.stop(); + }); + + it('can render itself', function () { + expect(view.$el.html()).toContain('