Topic teams actions (#24336)

* modern eslint allowances

* update topic teams to request team membership per local teamset

* update tests for topic_teams change

* cleanup

Co-authored-by: Ben Warzeski <benwarzeski@edX-C02CD0HCLVDM.cable.rcn.com>
This commit is contained in:
Ben Warzeski
2020-06-26 14:46:51 -04:00
committed by GitHub
parent c962423bbc
commit 64e8332d38
5 changed files with 187 additions and 129 deletions

View File

@@ -0,0 +1,7 @@
{
"rules": {
"comma-dangle": "off",
"object-curly-spacing": "off",
"no-underscore-dangle": "off"
}
}

View File

@@ -38,14 +38,14 @@ define([
)); ));
}; };
var createTeamsTabView = function(test, options) { var createTeamsTabView = function(options) {
var teamsTabView = new TeamsTabView( var teamsTabView = new TeamsTabView(
{ {
el: $('.teams-content'), el: $('.teams-content'),
context: TeamSpecHelpers.createMockContext(options) context: TeamSpecHelpers.createMockContext(options)
} }
); );
requests = AjaxHelpers.requests(test); requests = AjaxHelpers.requests();
PageHelpers.preventBackboneChangingUrl(); PageHelpers.preventBackboneChangingUrl();
teamsTabView.start(); teamsTabView.start();
return teamsTabView; return teamsTabView;
@@ -65,7 +65,7 @@ define([
describe('Navigation', function() { describe('Navigation', function() {
it('does not render breadcrumbs for the top level tabs', function() { it('does not render breadcrumbs for the top level tabs', function() {
var teamsTabView = createTeamsTabView(this); var teamsTabView = createTeamsTabView();
teamsTabView.router.navigate('#my-teams', {trigger: true}); teamsTabView.router.navigate('#my-teams', {trigger: true});
expect(teamsTabView.$('.breadcrumbs').length).toBe(0); expect(teamsTabView.$('.breadcrumbs').length).toBe(0);
teamsTabView.router.navigate('#browse', {trigger: true}); teamsTabView.router.navigate('#browse', {trigger: true});
@@ -73,20 +73,20 @@ define([
}); });
it('does not interfere with anchor links to #main', function() { it('does not interfere with anchor links to #main', function() {
var teamsTabView = createTeamsTabView(this); var teamsTabView = createTeamsTabView();
teamsTabView.router.navigate('#main', {trigger: true}); teamsTabView.router.navigate('#main', {trigger: true});
expect(teamsTabView.$('.wrapper-msg')).toHaveClass('is-hidden'); expect(teamsTabView.$('.wrapper-msg')).toHaveClass('is-hidden');
}); });
it('displays and focuses an error message when trying to navigate to a nonexistent page', function() { it('displays and focuses an error message when trying to navigate to a nonexistent page', function() {
var teamsTabView = createTeamsTabView(this); var teamsTabView = createTeamsTabView();
teamsTabView.router.navigate('no_such_page', {trigger: true}); teamsTabView.router.navigate('no_such_page', {trigger: true});
expectError(teamsTabView, 'The page "no_such_page" could not be found.'); expectError(teamsTabView, 'The page "no_such_page" could not be found.');
expectFocus(teamsTabView.$('.warning')); expectFocus(teamsTabView.$('.warning'));
}); });
it('displays and focuses an error message when trying to navigate to a nonexistent topic', function() { it('displays and focuses an error message when trying to navigate to a nonexistent topic', function() {
var teamsTabView = createTeamsTabView(this); var teamsTabView = createTeamsTabView();
teamsTabView.router.navigate('topics/no_such_topic', {trigger: true}); teamsTabView.router.navigate('topics/no_such_topic', {trigger: true});
AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/topics/no_such_topic,course/1', null); AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/topics/no_such_topic,course/1', null);
AjaxHelpers.respondWithError(requests, 404); AjaxHelpers.respondWithError(requests, 404);
@@ -95,7 +95,7 @@ define([
}); });
it('displays and focuses an error message when trying to navigate to a nonexistent team', function() { it('displays and focuses an error message when trying to navigate to a nonexistent team', function() {
var teamsTabView = createTeamsTabView(this); var teamsTabView = createTeamsTabView();
teamsTabView.router.navigate('teams/' + TeamSpecHelpers.testTopicID + '/no_such_team', {trigger: true}); teamsTabView.router.navigate('teams/' + TeamSpecHelpers.testTopicID + '/no_such_team', {trigger: true});
AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/teams/no_such_team?expand=user', null); AjaxHelpers.expectRequest(requests, 'GET', '/api/team/v0/teams/no_such_team?expand=user', null);
AjaxHelpers.respondWithError(requests, 404); AjaxHelpers.respondWithError(requests, 404);
@@ -104,7 +104,7 @@ define([
}); });
it('displays and focuses an error message when it receives a 401 AJAX response', function() { it('displays and focuses an error message when it receives a 401 AJAX response', function() {
var teamsTabView = createTeamsTabView(this).render(); var teamsTabView = createTeamsTabView().render();
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true}); teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
AjaxHelpers.respondWithError(requests, 401); AjaxHelpers.respondWithError(requests, 401);
expectError(teamsTabView, 'Your request could not be completed. Reload the page and try again.'); expectError(teamsTabView, 'Your request could not be completed. Reload the page and try again.');
@@ -112,7 +112,7 @@ define([
}); });
it('displays and focuses an error message when it receives a 500 AJAX response', function() { it('displays and focuses an error message when it receives a 500 AJAX response', function() {
var teamsTabView = createTeamsTabView(this).render(); var teamsTabView = createTeamsTabView().render();
teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true}); teamsTabView.router.navigate('topics/' + TeamSpecHelpers.testTopicID, {trigger: true});
AjaxHelpers.respondWithError(requests, 500); AjaxHelpers.respondWithError(requests, 500);
expectError( expectError(
@@ -124,7 +124,7 @@ define([
}); });
it('does not navigate to the topics page when syncing its collection if not on search page', function() { it('does not navigate to the topics page when syncing its collection if not on search page', function() {
var teamsTabView = createTeamsTabView(this), var teamsTabView = createTeamsTabView(),
collection = TeamSpecHelpers.createMockTeams(); collection = TeamSpecHelpers.createMockTeams();
teamsTabView.createTeamsListView({ teamsTabView.createTeamsListView({
collection: collection, collection: collection,
@@ -179,7 +179,7 @@ define([
} }
] ]
}, function(url, expectedEvent) { }, function(url, expectedEvent) {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({staff: true}) userInfo: TeamSpecHelpers.createMockUserInfo({staff: true})
}); });
teamsTabView.teamsCollection = TeamSpecHelpers.createMockTeams(); teamsTabView.teamsCollection = TeamSpecHelpers.createMockTeams();
@@ -193,7 +193,7 @@ define([
describe('Discussion privileges', function() { describe('Discussion privileges', function() {
it('allows privileged access to any team', function() { it('allows privileged access to any team', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}) userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true})
}); });
// Note: using `undefined` here to ensure that we // Note: using `undefined` here to ensure that we
@@ -203,7 +203,7 @@ define([
}); });
it('allows access to a team which an unprivileged user is a member of', function() { it('allows access to a team which an unprivileged user is a member of', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({ userInfo: TeamSpecHelpers.createMockUserInfo({
username: TeamSpecHelpers.testUser, username: TeamSpecHelpers.testUser,
privileged: false privileged: false
@@ -221,7 +221,7 @@ define([
}); });
it('does not allow access if the user is neither privileged nor a team member', function() { it('does not allow access if the user is neither privileged nor a team member', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false, staff: true}) userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false, staff: true})
}); });
expect(teamsTabView.readOnlyDiscussion({ expect(teamsTabView.readOnlyDiscussion({
@@ -233,7 +233,7 @@ define([
describe('Manage Tab', function() { describe('Manage Tab', function() {
var manageTabSelector = '.page-content-nav>.nav-item[data-url=manage]'; var manageTabSelector = '.page-content-nav>.nav-item[data-url=manage]';
it('is not visible to unprivileged users', function() { it('is not visible to unprivileged users', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false}), userInfo: TeamSpecHelpers.createMockUserInfo({privileged: false}),
hasManagedTopic: true hasManagedTopic: true
}); });
@@ -241,7 +241,7 @@ define([
}); });
it('is not visible when there are no managed topics', function() { it('is not visible when there are no managed topics', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}), userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}),
hasManagedTopic: false hasManagedTopic: false
}); });
@@ -249,7 +249,7 @@ define([
}); });
it('is visible to privileged users when there is a managed topic', function() { it('is visible to privileged users when there is a managed topic', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}), userInfo: TeamSpecHelpers.createMockUserInfo({privileged: true}),
hasManagedTopic: true hasManagedTopic: true
}); });
@@ -260,7 +260,7 @@ define([
describe('Browse Tab', function() { describe('Browse Tab', function() {
var browseTabSelector = '.page-content-nav>.nav-item[data-url=browse]'; var browseTabSelector = '.page-content-nav>.nav-item[data-url=browse]';
it('is not visible if there are no open and no public teamsets', function() { it('is not visible if there are no open and no public teamsets', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
hasOpenTopic: false, hasOpenTopic: false,
hasPublicManagedTopic: false hasPublicManagedTopic: false
}); });
@@ -268,7 +268,7 @@ define([
}); });
it('is visible if there are open teamsets', function() { it('is visible if there are open teamsets', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
hasOpenTopic: true, hasOpenTopic: true,
hasPublicManagedTopic: false hasPublicManagedTopic: false
}); });
@@ -276,7 +276,7 @@ define([
}); });
it('is visible if there are public teamsets', function() { it('is visible if there are public teamsets', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
hasOpenTopic: false, hasOpenTopic: false,
hasPublicManagedTopic: true hasPublicManagedTopic: true
}); });
@@ -284,7 +284,7 @@ define([
}); });
it('is visible if there are both public and open teamsets', function() { it('is visible if there are both public and open teamsets', function() {
var teamsTabView = createTeamsTabView(this, { var teamsTabView = createTeamsTabView({
hasOpenTopic: true, hasOpenTopic: true,
hasPublicManagedTopic: true hasPublicManagedTopic: true
}); });
@@ -293,39 +293,46 @@ define([
}); });
describe('Search', function() { describe('Search', function() {
var performSearch = function(reqs, teamsTabView) { var teamsTabView;
var performSearch = function() {
teamsTabView.$('.search-field').val('foo'); teamsTabView.$('.search-field').val('foo');
teamsTabView.$('.action-search').click(); teamsTabView.$('.action-search').click();
verifyTeamsRequest({ verifyTeamsRequest({
order_by: '', order_by: '',
text_search: 'foo' text_search: 'foo'
}); });
AjaxHelpers.respondWithJson(reqs, TeamSpecHelpers.createMockTeamsResponse({results: []})); AjaxHelpers.respondWithJson(
requests,
TeamSpecHelpers.createMockTeamsResponse({ results: [] }
));
AjaxHelpers.respondWithJson(requests, { count: 0 });
// Expect exactly one search request to be fired // Expect exactly one search request to be fired, and one request to see if the user is
AjaxHelpers.expectNoRequests(reqs); // in a team in the current teamset
AjaxHelpers.expectNoRequests(requests);
}; };
it('can search teams', function() { beforeEach(function() {
var teamsTabView = createTeamsTabView(this); teamsTabView = createTeamsTabView();
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID); teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
verifyTeamsRequest({ verifyTeamsRequest({
order_by: 'last_activity_at', order_by: 'last_activity_at',
text_search: '' text_search: ''
}); });
AjaxHelpers.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
performSearch(requests, teamsTabView); AjaxHelpers.respondWithJson(requests, { count: 0 });
});
it('can search teams', function() {
performSearch();
expect(teamsTabView.$('.page-title').text()).toBe('Team Search'); expect(teamsTabView.$('.page-title').text()).toBe('Team Search');
expect(teamsTabView.$('.page-description').text()).toBe('Showing results for "foo"'); expect(teamsTabView.$('.page-description').text()).toBe('Showing results for "foo"');
}); });
it('can clear a search', function() { it('can clear a search', function() {
var teamsTabView = createTeamsTabView(this);
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
AjaxHelpers.respondWithJson(requests, {});
// Perform a search // Perform a search
performSearch(requests, teamsTabView); performSearch();
// Clear the search and submit it again // Clear the search and submit it again
teamsTabView.$('.search-field').val(''); teamsTabView.$('.search-field').val('');
@@ -335,17 +342,14 @@ define([
order_by: 'last_activity_at' order_by: 'last_activity_at'
}); });
AjaxHelpers.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.respondWithJson(requests, { count: 0 });
expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1'); expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1');
expect(teamsTabView.$('.page-description').text()).toBe('Test description 1'); expect(teamsTabView.$('.page-description').text()).toBe('Test description 1');
}); });
it('can navigate back to all teams from a search', function() { it('can navigate back to all teams from a search', function() {
var teamsTabView = createTeamsTabView(this);
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
AjaxHelpers.respondWithJson(requests, {});
// Perform a search // Perform a search
performSearch(requests, teamsTabView); performSearch();
// Verify the breadcrumbs have a link back to the teams list, and click on it // Verify the breadcrumbs have a link back to the teams list, and click on it
expect(teamsTabView.$('.breadcrumbs a').length).toBe(2); expect(teamsTabView.$('.breadcrumbs a').length).toBe(2);
@@ -355,15 +359,12 @@ define([
text_search: '' text_search: ''
}); });
AjaxHelpers.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
AjaxHelpers.respondWithJson(requests, { count: 0 });
expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1'); expect(teamsTabView.$('.page-title').text()).toBe('Test Topic 1');
expect(teamsTabView.$('.page-description').text()).toBe('Test description 1'); expect(teamsTabView.$('.page-description').text()).toBe('Test description 1');
}); });
it('does not switch to showing results when the search returns an error', function() { it('does not switch to showing results when the search returns an error', function() {
var teamsTabView = createTeamsTabView(this);
teamsTabView.browseTopic(TeamSpecHelpers.testTopicID);
AjaxHelpers.respondWithJson(requests, {});
// Perform a search but respond with a 500 // Perform a search but respond with a 500
teamsTabView.$('.search-field').val('foo'); teamsTabView.$('.search-field').val('foo');
teamsTabView.$('.action-search').click(); teamsTabView.$('.action-search').click();

View File

@@ -2,33 +2,69 @@ define([
'backbone', 'backbone',
'underscore', 'underscore',
'teams/js/views/topic_teams', 'teams/js/views/topic_teams',
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers',
'teams/js/spec_helpers/team_spec_helpers', 'teams/js/spec_helpers/team_spec_helpers',
'common/js/spec_helpers/page_helpers' 'common/js/spec_helpers/page_helpers'
], function(Backbone, _, TopicTeamsView, TeamSpecHelpers, PageHelpers) { ], function(Backbone, _, TopicTeamsView, AjaxHelpers, TeamSpecHelpers, PageHelpers) {
'use strict'; 'use strict';
describe('Topic Teams View', function() { describe('Topic Teams View', function() {
var createTopicTeamsView = function(options, isInstructorManagedTopic) { var requests, teamsView;
options = options || {}; // eslint-disable-line no-param-reassign
return new TopicTeamsView({ var verifyTeamsetTeamsRequest = function(hasTeams) {
AjaxHelpers.expectRequestURL(
requests,
TeamSpecHelpers.testContext.teamMembershipsUrl,
{
username: TeamSpecHelpers.testUser,
course_id: TeamSpecHelpers.testCourseID,
teamset_id: TeamSpecHelpers.testTopicID,
}
);
AjaxHelpers.respondWithJson(
requests,
{ count: hasTeams ? 1 : 0 }
);
AjaxHelpers.expectNoRequests(requests);
};
var createTopicTeamsView = function(_options) {
var options = _options || {};
var onTeamInTeamset = options.onTeamInTeamset || false,
isInstructorManagedTopic = options.isInstructorManagedTopic || false;
var result, topicTeamsView;
requests = AjaxHelpers.requests(this);
topicTeamsView = new TopicTeamsView({
el: '.teams-container', el: '.teams-container',
model: isInstructorManagedTopic ? model: isInstructorManagedTopic ?
TeamSpecHelpers.createMockInstructorManagedTopic() : TeamSpecHelpers.createMockTopic(), TeamSpecHelpers.createMockInstructorManagedTopic() : TeamSpecHelpers.createMockTopic(),
collection: options.teams || TeamSpecHelpers.createMockTeams({results: []}), collection: options.teams || TeamSpecHelpers.createMockTeams({results: []}),
myTopicTeamsCollection: (
options.myTopicTeamsCollection || TeamSpecHelpers.createMockTeams({results: []})
),
context: _.extend({}, TeamSpecHelpers.testContext, options) context: _.extend({}, TeamSpecHelpers.testContext, options)
}).render(); });
result = topicTeamsView.render();
if (
topicTeamsView.context.userInfo.staff ||
topicTeamsView.context.userInfo.privileged ||
isInstructorManagedTopic
) {
AjaxHelpers.expectNoRequests(requests);
} else {
verifyTeamsetTeamsRequest(onTeamInTeamset);
}
return result;
}; };
var verifyActions = function(teamsView, options) { var verifyActions = function(showActions) {
var expectedTitle = 'Are you having trouble finding a team to join?', var expectedTitle = 'Are you having trouble finding a team to join?',
expectedMessage = 'Browse teams in other topics or search teams in this topic. ' + expectedMessage = 'Browse teams in other topics or search teams in this topic. ' +
'If you still can\'t find a team to join, create a new team in this topic.', 'If you still can\'t find a team to join, create a new team in this topic.',
title = teamsView.$('.title').text().trim(), title = teamsView.$('.title').text().trim(),
message = teamsView.$('.copy').text().trim(); message = teamsView.$('.copy').text().trim(),
options = options || {showActions: true}; // eslint-disable-line no-param-reassign _showActions = showActions === undefined ? true : showActions;
if (options.showActions) {
if (_showActions) {
expect(title).toBe(expectedTitle); expect(title).toBe(expectedTitle);
expect(message).toBe(expectedMessage); expect(message).toBe(expectedMessage);
} else { } else {
@@ -49,32 +85,35 @@ define([
results: testTeamData results: testTeamData
}) })
}; };
var teamsView = createTopicTeamsView(options); var footerEl;
var footerEl = teamsView.$('.teams-paging-footer');
teamsView = createTopicTeamsView(options);
footerEl = teamsView.$('.teams-paging-footer');
expect(teamsView.$('.teams-paging-header').text()).toMatch('Showing 1-5 out of 6 total'); expect(teamsView.$('.teams-paging-header').text()).toMatch('Showing 1-5 out of 6 total');
expect(footerEl.text()).toMatch('1\\s+out of\\s+\/\\s+2'); // eslint-disable-line no-useless-escape expect(footerEl.text()).toMatch('1\\s+out of\\s+\/\\s+2'); // eslint-disable-line no-useless-escape
expect(footerEl).not.toHaveClass('hidden'); expect(footerEl).not.toHaveClass('hidden');
TeamSpecHelpers.verifyCards(teamsView, testTeamData); TeamSpecHelpers.verifyCards(teamsView, testTeamData);
verifyActions(teamsView); verifyActions();
}); });
it('can browse all teams', function() { it('can browse all teams', function() {
var teamsView = createTopicTeamsView(); teamsView = createTopicTeamsView();
spyOn(Backbone.history, 'navigate'); spyOn(Backbone.history, 'navigate');
teamsView.$('.browse-teams').click(); teamsView.$('.browse-teams').click();
expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe('browse'); expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe('browse');
}); });
it('gives the search field focus when clicking on the search teams link', function() { it('gives the search field focus when clicking on the search teams link', function() {
var teamsView = createTopicTeamsView(); teamsView = createTopicTeamsView();
spyOn($.fn, 'focus').and.callThrough(); spyOn($.fn, 'focus').and.callThrough();
teamsView.$('.search-teams').click(); teamsView.$('.search-teams').click();
expect(teamsView.$('.search-field').first().focus).toHaveBeenCalled(); expect(teamsView.$('.search-field').first().focus).toHaveBeenCalled();
}); });
it('can show the create team modal', function() { it('can show the create team modal', function() {
var teamsView = createTopicTeamsView(); teamsView = createTopicTeamsView();
spyOn(Backbone.history, 'navigate'); spyOn(Backbone.history, 'navigate');
teamsView.$('a.create-team').click(); teamsView.$('a.create-team').click();
expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe( expect(Backbone.history.navigate.calls.mostRecent().args[0]).toBe(
@@ -83,14 +122,13 @@ define([
}); });
it('does not show actions for a user already in a team in the teamset', function() { it('does not show actions for a user already in a team in the teamset', function() {
var options = {myTopicTeamsCollection: TeamSpecHelpers.createMockTeams()}; teamsView = createTopicTeamsView({ onTeamInTeamset: true });
var teamsView = createTopicTeamsView(options); verifyActions(false);
verifyActions(teamsView, {showActions: false});
}); });
it('does not show actions for a student in an instructor managed topic', function() { it('does not show actions for a student in an instructor managed topic', function() {
var teamsView = createTopicTeamsView({}, true); teamsView = createTopicTeamsView({ isInstructorManagedTopic: true });
verifyActions(teamsView, {showActions: false}); verifyActions(false);
}); });
it('shows actions for a privileged user already in a team', function() { it('shows actions for a privileged user already in a team', function() {
@@ -99,10 +137,10 @@ define([
privileged: true, privileged: true,
staff: false staff: false
}, },
myTopicTeamsCollection: TeamSpecHelpers.createMockTeams() onTeamInTeamset: true,
}; };
var teamsView = createTopicTeamsView(options); teamsView = createTopicTeamsView(options);
verifyActions(teamsView, {showActions: true}); verifyActions();
}); });
it('shows actions for a staff user already in a team', function() { it('shows actions for a staff user already in a team', function() {
@@ -111,10 +149,10 @@ define([
privileged: false, privileged: false,
staff: true staff: true
}, },
myTopicTeamsCollection: TeamSpecHelpers.createMockTeams() onTeamInTeamset: true,
}; };
var teamsView = createTopicTeamsView(options); teamsView = createTopicTeamsView(options);
verifyActions(teamsView, {showActions: true}); verifyActions();
}); });
/* /*
@@ -123,7 +161,7 @@ define([
var requests = AjaxHelpers.requests(this), var requests = AjaxHelpers.requests(this),
teamMemberships = TeamSpecHelpers.createMockTeamMemberships([]), teamMemberships = TeamSpecHelpers.createMockTeamMemberships([]),
teamsView = createTopicTeamsView({ teamMemberships: teamMemberships }); teamsView = createTopicTeamsView({ teamMemberships: teamMemberships });
verifyActions(teamsView, {showActions: true}); verifyActions({showActions: true});
teamMemberships.teamEvents.trigger('teams:update', { action: 'create' }); teamMemberships.teamEvents.trigger('teams:update', { action: 'create' });
teamsView.render(); teamsView.render();
AjaxHelpers.expectRequestURL( AjaxHelpers.expectRequestURL(
@@ -138,7 +176,7 @@ define([
} }
); );
AjaxHelpers.respondWithJson(requests, {}); AjaxHelpers.respondWithJson(requests, {});
verifyActions(teamsView, {showActions: false}); verifyActions({showActions: false});
}); });
*/ */
}); });

View File

@@ -380,24 +380,11 @@
createTeamsListView: function(options) { createTeamsListView: function(options) {
var topic = options.topic, var topic = options.topic,
collection = options.collection, collection = options.collection,
myTopicTeamsCollection = new TeamCollection(
this.context.userInfo.teams,
{
teamEvents: this.teamEvents,
course_id: this.context.courseID,
username: this.context.userInfo.username,
topic_id: topic.get('id'),
perPage: 5,
parse: true,
url: this.context.myTeamsUrl
}
),
teamsView = new TopicTeamsView({ teamsView = new TopicTeamsView({
router: this.router, router: this.router,
context: this.context, context: this.context,
model: topic, model: topic,
collection: collection, collection: collection,
myTopicTeamsCollection: myTopicTeamsCollection,
showSortControls: options.showSortControls showSortControls: options.showSortControls
}), }),
searchFieldView = new SearchFieldView({ searchFieldView = new SearchFieldView({

View File

@@ -1,6 +1,7 @@
(function(define) { (function(define) {
'use strict'; 'use strict';
define([ define([
'jquery',
'underscore', 'underscore',
'backbone', 'backbone',
'gettext', 'gettext',
@@ -9,7 +10,34 @@
'common/js/components/views/paging_header', 'common/js/components/views/paging_header',
'text!teams/templates/team-actions.underscore', 'text!teams/templates/team-actions.underscore',
'teams/js/views/team_utils' 'teams/js/views/team_utils'
], function(_, Backbone, gettext, HtmlUtils, TeamsView, PagingHeader, teamActionsTemplate, TeamUtils) { ], function($, _, Backbone, gettext, HtmlUtils, TeamsView, PagingHeader, teamActionsTemplate, TeamUtils) {
// Translators: this string is shown at the bottom of the teams page
// to find a team to join or else to create a new one. There are three
// links that need to be included in the message:
// 1. Browse teams in other topics
// 2. search teams
// 3. create a new team
// Be careful to start each link with the appropriate start indicator
// (e.g. {browse_span_start} for #1) and finish it with {span_end}.
var actionMessage = interpolate_text( // eslint-disable-line no-undef
_.escape(gettext(
'{browse_span_start}Browse teams in other ' +
'topics{span_end} or {search_span_start}search teams{span_end} ' +
'in this topic. If you still can\'t find a team to join, ' +
'{create_span_start}create a new team in this topic{span_end}.'
)),
{
browse_span_start: '<a class="browse-teams" href="">',
search_span_start: '<a class="search-teams" href="">',
create_span_start: '<a class="create-team" href="">',
span_end: '</a>'
}
);
var canUserCreateTeamErrorMessage = gettext(
'An error occurred while looking up team membership. Try refreshing the page.'
);
var TopicTeamsView = TeamsView.extend({ var TopicTeamsView = TeamsView.extend({
events: { events: {
'click a.browse-teams': 'browseTeams', 'click a.browse-teams': 'browseTeams',
@@ -24,51 +52,48 @@
TeamsView.prototype.initialize.call(this, options); TeamsView.prototype.initialize.call(this, options);
}, },
canUserCreateTeam: function() { checkIfUserCanCreateTeam: function() {
// Note: non-staff and non-privileged users are automatically added to any team var deferred = $.Deferred();
// that they create. This means that if multiple team membership is if (this.context.userInfo.staff || this.context.userInfo.privileged) {
// disabled that they cannot create a new team when they already deferred.resolve(true);
// belong to one. } else if (TeamUtils.isInstructorManagedTopic(this.model.attributes.type)) {
return this.context.userInfo.staff deferred.resolve(false);
|| this.context.userInfo.privileged } else {
|| (!TeamUtils.isInstructorManagedTopic(this.model.attributes.type) $.ajax({
&& this.options.myTopicTeamsCollection.length === 0); type: 'GET',
url: this.context.teamMembershipsUrl,
data: {
username: this.context.userInfo.username,
course_id: this.context.courseID,
teamset_id: this.model.get('id')
}
}).done(function(data) {
deferred.resolve(data.count === 0);
}).fail(function(data) {
TeamUtils.parseAndShowMessage(data, canUserCreateTeamErrorMessage);
deferred.resolve(false);
});
}
return deferred.promise();
},
showActions: function() {
HtmlUtils.append(
this.$el,
HtmlUtils.template(teamActionsTemplate)({message: actionMessage})
);
}, },
render: function() { render: function() {
var self = this; this.collection.refresh().done(_.bind(function() {
this.collection.refresh().done(function() { TeamsView.prototype.render.call(this);
var message; this.checkIfUserCanCreateTeam().done(_.bind(function(canUserCreateTeam) {
TeamsView.prototype.render.call(self); if (canUserCreateTeam) {
if (self.canUserCreateTeam()) { this.showActions();
message = interpolate_text( // eslint-disable-line no-undef }
// Translators: this string is shown at the bottom of the teams page }, this));
// to find a team to join or else to create a new one. There are three }, this));
// links that need to be included in the message:
// 1. Browse teams in other topics
// 2. search teams
// 3. create a new team
// Be careful to start each link with the appropriate start indicator
// (e.g. {browse_span_start} for #1) and finish it with {span_end}.
_.escape(gettext(
'{browse_span_start}Browse teams in other ' +
'topics{span_end} or {search_span_start}search teams{span_end} ' +
'in this topic. If you still can\'t find a team to join, ' +
'{create_span_start}create a new team in this topic{span_end}.'
)),
{
browse_span_start: '<a class="browse-teams" href="">',
search_span_start: '<a class="search-teams" href="">',
create_span_start: '<a class="create-team" href="">',
span_end: '</a>'
}
);
HtmlUtils.append(
self.$el,
HtmlUtils.template(teamActionsTemplate)({message: message})
);
}
});
return this; return this;
}, },