Merge pull request #9376 from edx/muzaffar/tnl1914-team-edit-page
Edit team page for Instructors only.
This commit is contained in:
@@ -205,7 +205,7 @@ class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
|
||||
self.wait_for_ajax()
|
||||
|
||||
|
||||
class CreateTeamPage(CoursePage, FieldsMixin):
|
||||
class CreateOrEditTeamPage(CoursePage, FieldsMixin):
|
||||
"""
|
||||
Create team page.
|
||||
"""
|
||||
@@ -216,7 +216,7 @@ class CreateTeamPage(CoursePage, FieldsMixin):
|
||||
representation of a topic following the same convention as a
|
||||
course module's topic.
|
||||
"""
|
||||
super(CreateTeamPage, self).__init__(browser, course_id)
|
||||
super(CreateOrEditTeamPage, self).__init__(browser, course_id)
|
||||
self.topic = topic
|
||||
self.url_path = "teams/#topics/{topic_id}/create-team".format(topic_id=self.topic['id'])
|
||||
|
||||
@@ -410,3 +410,12 @@ class TeamPage(CoursePage, PaginatedUIMixin):
|
||||
"""Navigate to the 'All Topics' page."""
|
||||
self.q(css='.breadcrumbs a').results[0].click()
|
||||
self.wait_for_ajax()
|
||||
|
||||
@property
|
||||
def edit_team_button_present(self):
|
||||
""" Returns True if Edit Team button is present else False """
|
||||
return self.q(css='.form-actions .action-edit-team').present
|
||||
|
||||
def click_edit_team_button(self):
|
||||
""" Click on Edit Team button"""
|
||||
self.q(css='.form-actions .action-edit-team').first.click()
|
||||
|
||||
@@ -20,7 +20,7 @@ from ...pages.lms.auto_auth import AutoAuthPage
|
||||
from ...pages.lms.course_info import CourseInfoPage
|
||||
from ...pages.lms.learner_profile import LearnerProfilePage
|
||||
from ...pages.lms.tab_nav import TabNavPage
|
||||
from ...pages.lms.teams import TeamsPage, MyTeamsPage, BrowseTopicsPage, BrowseTeamsPage, CreateTeamPage, TeamPage
|
||||
from ...pages.lms.teams import TeamsPage, MyTeamsPage, BrowseTopicsPage, BrowseTeamsPage, CreateOrEditTeamPage, TeamPage
|
||||
|
||||
|
||||
TOPICS_PER_PAGE = 12
|
||||
@@ -335,7 +335,7 @@ class BrowseTopicsTest(TeamsTabBase):
|
||||
browse_teams_page = BrowseTeamsPage(self.browser, self.course_id, topic)
|
||||
self.assertTrue(browse_teams_page.is_browser_on_page())
|
||||
browse_teams_page.click_create_team_link()
|
||||
create_team_page = CreateTeamPage(self.browser, self.course_id, topic)
|
||||
create_team_page = CreateOrEditTeamPage(self.browser, self.course_id, topic)
|
||||
create_team_page.value_for_text_field(field_id='name', value='Team Name', press_enter=False)
|
||||
create_team_page.value_for_textarea_field(
|
||||
field_id='description',
|
||||
@@ -629,47 +629,109 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
|
||||
|
||||
|
||||
@attr('shard_5')
|
||||
class CreateTeamTest(TeamsTabBase):
|
||||
class TeamFormActions(TeamsTabBase):
|
||||
"""
|
||||
Base class for create & edit team.
|
||||
"""
|
||||
TEAM_DESCRIPTION = 'The Avengers are a fictional team of superheroes.'
|
||||
|
||||
topic = {'name': 'Example Topic', 'id': 'example_topic', 'description': 'Description'}
|
||||
TEAMS_NAME = 'Avengers'
|
||||
|
||||
def verify_page_header(self, title, description, breadcrumbs):
|
||||
"""
|
||||
Verify that the page header correctly reflects the
|
||||
create team header, description and breadcrumb.
|
||||
"""
|
||||
self.assertEqual(self.create_or_edit_team_page.header_page_name, title)
|
||||
self.assertEqual(self.create_or_edit_team_page.header_page_description, description)
|
||||
self.assertEqual(self.create_or_edit_team_page.header_page_breadcrumbs, breadcrumbs)
|
||||
|
||||
def verify_and_navigate_to_create_team_page(self):
|
||||
"""Navigates to the create team page and verifies."""
|
||||
self.browse_teams_page.click_create_team_link()
|
||||
self.verify_page_header(
|
||||
title='Create a New Team',
|
||||
description='Create a new team if you can\'t find existing teams to '
|
||||
'join, or if you would like to learn with friends you know.',
|
||||
breadcrumbs=self.topic['name']
|
||||
)
|
||||
|
||||
def verify_and_navigate_to_edit_team_page(self):
|
||||
"""Navigates to the edit team page and verifies."""
|
||||
# pylint: disable=no-member
|
||||
self.assertEqual(self.team_page.team_name, self.team['name'])
|
||||
self.assertTrue(self.team_page.edit_team_button_present)
|
||||
|
||||
self.team_page.click_edit_team_button()
|
||||
|
||||
self.create_or_edit_team_page.wait_for_page()
|
||||
|
||||
# Edit page header.
|
||||
self.verify_page_header(
|
||||
title='Edit Team',
|
||||
description='If you make significant changes, make sure you notify '
|
||||
'members of the team before making these changes.',
|
||||
breadcrumbs='All Topics {topic_name} {team_name}'.format(
|
||||
topic_name=self.topic['name'],
|
||||
team_name=self.team['name']
|
||||
)
|
||||
)
|
||||
|
||||
def verify_team_info(self, name, description, location, language):
|
||||
"""Verify the team information on team page."""
|
||||
# pylint: disable=no-member
|
||||
self.assertEqual(self.team_page.team_name, name)
|
||||
self.assertEqual(self.team_page.team_description, description)
|
||||
self.assertEqual(self.team_page.team_location, location)
|
||||
self.assertEqual(self.team_page.team_language, language)
|
||||
|
||||
def fill_create_or_edit_form(self):
|
||||
"""Fill the create/edit team form fields with appropriate values."""
|
||||
self.create_or_edit_team_page.value_for_text_field(field_id='name', value=self.TEAMS_NAME, press_enter=False)
|
||||
self.create_or_edit_team_page.value_for_textarea_field(
|
||||
field_id='description',
|
||||
value=self.TEAM_DESCRIPTION
|
||||
)
|
||||
self.create_or_edit_team_page.value_for_dropdown_field(field_id='language', value='English')
|
||||
self.create_or_edit_team_page.value_for_dropdown_field(field_id='country', value='Pakistan')
|
||||
|
||||
def verify_all_fields_exist(self):
|
||||
"""
|
||||
Verify the fields for create/edit page.
|
||||
"""
|
||||
self.assertEqual(
|
||||
self.create_or_edit_team_page.message_for_field('name'),
|
||||
'A name that identifies your team (maximum 255 characters).'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_or_edit_team_page.message_for_textarea_field('description'),
|
||||
'A short description of the team to help other learners understand '
|
||||
'the goals or direction of the team (maximum 300 characters).'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_or_edit_team_page.message_for_field('country'),
|
||||
'The country that team members primarily identify with.'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_or_edit_team_page.message_for_field('language'),
|
||||
'The language that team members primarily use to communicate with each other.'
|
||||
)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CreateTeamTest(TeamFormActions):
|
||||
"""
|
||||
Tests for creating a new Team within a Topic on the Teams page.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(CreateTeamTest, self).setUp()
|
||||
self.topic = {'name': 'Example Topic', 'id': 'example_topic', 'description': 'Description'}
|
||||
self.set_team_configuration({'course_id': self.course_id, 'max_team_size': 10, 'topics': [self.topic]})
|
||||
|
||||
self.create_or_edit_team_page = CreateOrEditTeamPage(self.browser, self.course_id, self.topic)
|
||||
self.browse_teams_page = BrowseTeamsPage(self.browser, self.course_id, self.topic)
|
||||
self.browse_teams_page.visit()
|
||||
self.create_team_page = CreateTeamPage(self.browser, self.course_id, self.topic)
|
||||
self.team_name = 'Avengers'
|
||||
|
||||
def verify_page_header(self):
|
||||
"""
|
||||
Verify that the page header correctly reflects the
|
||||
create team header, description and breadcrumb.
|
||||
"""
|
||||
self.assertEqual(self.create_team_page.header_page_name, 'Create a New Team')
|
||||
self.assertEqual(
|
||||
self.create_team_page.header_page_description,
|
||||
'Create a new team if you can\'t find existing teams to join, '
|
||||
'or if you would like to learn with friends you know.'
|
||||
)
|
||||
self.assertEqual(self.create_team_page.header_page_breadcrumbs, self.topic['name'])
|
||||
|
||||
def verify_and_navigate_to_create_team_page(self):
|
||||
"""Navigates to the create team page and verifies."""
|
||||
self.browse_teams_page.click_create_team_link()
|
||||
self.verify_page_header()
|
||||
|
||||
def fill_create_form(self):
|
||||
"""Fill the create team form fields with appropriate values."""
|
||||
self.create_team_page.value_for_text_field(field_id='name', value=self.team_name, press_enter=False)
|
||||
self.create_team_page.value_for_textarea_field(
|
||||
field_id='description',
|
||||
value='The Avengers are a fictional team of superheroes.'
|
||||
)
|
||||
self.create_team_page.value_for_dropdown_field(field_id='language', value='English')
|
||||
self.create_team_page.value_for_dropdown_field(field_id='country', value='Pakistan')
|
||||
|
||||
def test_user_can_see_create_team_page(self):
|
||||
"""
|
||||
@@ -683,23 +745,7 @@ class CreateTeamTest(TeamsTabBase):
|
||||
And I should also see the help messages for fields.
|
||||
"""
|
||||
self.verify_and_navigate_to_create_team_page()
|
||||
self.assertEqual(
|
||||
self.create_team_page.message_for_field('name'),
|
||||
'A name that identifies your team (maximum 255 characters).'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_team_page.message_for_textarea_field('description'),
|
||||
'A short description of the team to help other learners understand '
|
||||
'the goals or direction of the team (maximum 300 characters).'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_team_page.message_for_field('country'),
|
||||
'The country that team members primarily identify with.'
|
||||
)
|
||||
self.assertEqual(
|
||||
self.create_team_page.message_for_field('language'),
|
||||
'The language that team members primarily use to communicate with each other.'
|
||||
)
|
||||
self.verify_all_fields_exist()
|
||||
|
||||
def test_user_can_see_error_message_for_missing_data(self):
|
||||
"""
|
||||
@@ -711,14 +757,14 @@ class CreateTeamTest(TeamsTabBase):
|
||||
Then I should see the error message and highlighted fields.
|
||||
"""
|
||||
self.verify_and_navigate_to_create_team_page()
|
||||
self.create_team_page.submit_form()
|
||||
self.create_or_edit_team_page.submit_form()
|
||||
|
||||
self.assertEqual(
|
||||
self.create_team_page.validation_message_text,
|
||||
self.create_or_edit_team_page.validation_message_text,
|
||||
'Check the highlighted fields below and try again.'
|
||||
)
|
||||
self.assertTrue(self.create_team_page.error_for_field(field_id='name'))
|
||||
self.assertTrue(self.create_team_page.error_for_field(field_id='description'))
|
||||
self.assertTrue(self.create_or_edit_team_page.error_for_field(field_id='name'))
|
||||
self.assertTrue(self.create_or_edit_team_page.error_for_field(field_id='description'))
|
||||
|
||||
def test_user_can_see_error_message_for_incorrect_data(self):
|
||||
"""
|
||||
@@ -733,7 +779,7 @@ class CreateTeamTest(TeamsTabBase):
|
||||
self.verify_and_navigate_to_create_team_page()
|
||||
|
||||
# Fill the name field with >255 characters to see validation message.
|
||||
self.create_team_page.value_for_text_field(
|
||||
self.create_or_edit_team_page.value_for_text_field(
|
||||
field_id='name',
|
||||
value='EdX is a massive open online course (MOOC) provider and online learning platform. '
|
||||
'It hosts online university-level courses in a wide range of disciplines to a worldwide '
|
||||
@@ -745,13 +791,13 @@ class CreateTeamTest(TeamsTabBase):
|
||||
'edX has more than 4 million users taking more than 500 courses online.',
|
||||
press_enter=False
|
||||
)
|
||||
self.create_team_page.submit_form()
|
||||
self.create_or_edit_team_page.submit_form()
|
||||
|
||||
self.assertEqual(
|
||||
self.create_team_page.validation_message_text,
|
||||
self.create_or_edit_team_page.validation_message_text,
|
||||
'Check the highlighted fields below and try again.'
|
||||
)
|
||||
self.assertTrue(self.create_team_page.error_for_field(field_id='name'))
|
||||
self.assertTrue(self.create_or_edit_team_page.error_for_field(field_id='name'))
|
||||
|
||||
def test_user_can_create_new_team_successfully(self):
|
||||
"""
|
||||
@@ -767,16 +813,19 @@ class CreateTeamTest(TeamsTabBase):
|
||||
And the number of teams should be updated on the topic card
|
||||
And if I switch to "My Team", the newly created team is displayed
|
||||
"""
|
||||
AutoAuthPage(self.browser, course_id=self.course_id).visit()
|
||||
self.browse_teams_page.visit()
|
||||
|
||||
self.verify_and_navigate_to_create_team_page()
|
||||
|
||||
self.fill_create_form()
|
||||
self.create_team_page.submit_form()
|
||||
self.fill_create_or_edit_form()
|
||||
self.create_or_edit_team_page.submit_form()
|
||||
|
||||
# Verify that the page is shown for the new team
|
||||
team_page = TeamPage(self.browser, self.course_id)
|
||||
team_page.wait_for_page()
|
||||
self.assertEqual(team_page.team_name, self.team_name)
|
||||
self.assertEqual(team_page.team_description, 'The Avengers are a fictional team of superheroes.')
|
||||
self.assertEqual(team_page.team_name, self.TEAMS_NAME)
|
||||
self.assertEqual(team_page.team_description, self.TEAM_DESCRIPTION)
|
||||
self.assertEqual(team_page.team_user_membership_text, 'You are a member of this team.')
|
||||
|
||||
# Verify the new team was added to the topic list
|
||||
@@ -802,7 +851,7 @@ class CreateTeamTest(TeamsTabBase):
|
||||
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 0 out of 0 total')
|
||||
|
||||
self.verify_and_navigate_to_create_team_page()
|
||||
self.create_team_page.cancel_team()
|
||||
self.create_or_edit_team_page.cancel_team()
|
||||
|
||||
self.assertTrue(self.browse_teams_page.is_browser_on_page())
|
||||
self.assertEqual(self.browse_teams_page.get_pagination_header_text(), 'Showing 0 out of 0 total')
|
||||
@@ -813,6 +862,157 @@ class CreateTeamTest(TeamsTabBase):
|
||||
self.verify_my_team_count(0)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class EditTeamTest(TeamFormActions):
|
||||
"""
|
||||
Tests for editing the team.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(EditTeamTest, self).setUp()
|
||||
|
||||
self.set_team_configuration(
|
||||
{'course_id': self.course_id, 'max_team_size': 10, 'topics': [self.topic]},
|
||||
global_staff=True
|
||||
)
|
||||
self.create_or_edit_team_page = CreateOrEditTeamPage(self.browser, self.course_id, self.topic)
|
||||
|
||||
self.team = self.create_teams(self.topic, num_teams=1)[0]
|
||||
self.team_page = TeamPage(self.browser, self.course_id, team=self.team)
|
||||
self.team_page.visit()
|
||||
|
||||
def test_staff_can_navigate_to_edit_team_page(self):
|
||||
"""
|
||||
Scenario: The user should be able to see and navigate to the edit team page.
|
||||
Given I am staff user for a course with a team
|
||||
When I visit the Team profile page
|
||||
Then I should see the Edit Team button
|
||||
And When I click edit team button
|
||||
Then I should see the edit team page
|
||||
And I should see the edit team header
|
||||
And I should also see the help messages for fields
|
||||
"""
|
||||
self.verify_and_navigate_to_edit_team_page()
|
||||
self.verify_all_fields_exist()
|
||||
|
||||
def test_staff_can_edit_team_successfully(self):
|
||||
"""
|
||||
Scenario: The staff should be able to edit team successfully.
|
||||
Given I am staff user for a course with a team
|
||||
When I visit the Team profile page
|
||||
Then I should see the Edit Team button
|
||||
And When I click edit team button
|
||||
Then I should see the edit team page
|
||||
When I edit all the fields with appropriate data
|
||||
And I click Update button
|
||||
Then I should see the page for my team with updated data
|
||||
"""
|
||||
self.verify_team_info(
|
||||
name=self.team['name'],
|
||||
description=self.team['description'],
|
||||
location='Afghanistan',
|
||||
language='Afar'
|
||||
)
|
||||
self.verify_and_navigate_to_edit_team_page()
|
||||
|
||||
self.fill_create_or_edit_form()
|
||||
self.create_or_edit_team_page.submit_form()
|
||||
|
||||
self.team_page.wait_for_page()
|
||||
|
||||
self.verify_team_info(
|
||||
name=self.TEAMS_NAME,
|
||||
description=self.TEAM_DESCRIPTION,
|
||||
location='Pakistan',
|
||||
language='English'
|
||||
)
|
||||
|
||||
def test_staff_can_cancel_the_team_edit(self):
|
||||
"""
|
||||
Scenario: The user should be able to cancel the editing of team.
|
||||
Given I am staff user for a course with a team
|
||||
When I visit the Team profile page
|
||||
Then I should see the Edit Team button
|
||||
And When I click edit team button
|
||||
Then I should see the edit team page
|
||||
Then I should see the Edit Team header
|
||||
When I click Cancel button
|
||||
Then I should see team page page without changes.
|
||||
"""
|
||||
self.verify_team_info(
|
||||
name=self.team['name'],
|
||||
description=self.team['description'],
|
||||
location='Afghanistan',
|
||||
language='Afar'
|
||||
)
|
||||
|
||||
self.verify_and_navigate_to_edit_team_page()
|
||||
|
||||
self.fill_create_or_edit_form()
|
||||
self.create_or_edit_team_page.cancel_team()
|
||||
|
||||
self.team_page.wait_for_page()
|
||||
|
||||
self.verify_team_info(
|
||||
name=self.team['name'],
|
||||
description=self.team['description'],
|
||||
location='Afghanistan',
|
||||
language='Afar'
|
||||
)
|
||||
|
||||
def test_student_cannot_see_edit_button(self):
|
||||
"""
|
||||
Scenario: The student should not see the edit team button.
|
||||
Given I am student for a course with a team
|
||||
When I visit the Team profile page
|
||||
Then I should not see the Edit Team button
|
||||
"""
|
||||
AutoAuthPage(self.browser, course_id=self.course_id).visit()
|
||||
self.team_page.visit()
|
||||
self.assertFalse(self.team_page.edit_team_button_present)
|
||||
|
||||
@ddt.data('Moderator', 'Community TA', 'Administrator')
|
||||
def test_discussion_privileged_user_can_edit_team(self, role):
|
||||
"""
|
||||
Scenario: The user with specified role should see the edit team button.
|
||||
Given I am user with privileged role for a course with a team
|
||||
When I visit the Team profile page
|
||||
Then I should see the Edit Team button
|
||||
"""
|
||||
kwargs = {
|
||||
'course_id': self.course_id,
|
||||
'staff': False
|
||||
}
|
||||
if role is not None:
|
||||
kwargs['roles'] = role
|
||||
|
||||
AutoAuthPage(self.browser, **kwargs).visit()
|
||||
|
||||
self.team_page.visit()
|
||||
self.teams_page.wait_for_page()
|
||||
self.assertTrue(self.team_page.edit_team_button_present)
|
||||
|
||||
self.verify_team_info(
|
||||
name=self.team['name'],
|
||||
description=self.team['description'],
|
||||
location='Afghanistan',
|
||||
language='Afar'
|
||||
)
|
||||
self.verify_and_navigate_to_edit_team_page()
|
||||
|
||||
self.fill_create_or_edit_form()
|
||||
self.create_or_edit_team_page.submit_form()
|
||||
|
||||
self.team_page.wait_for_page()
|
||||
|
||||
self.verify_team_info(
|
||||
name=self.TEAMS_NAME,
|
||||
description=self.TEAM_DESCRIPTION,
|
||||
location='Pakistan',
|
||||
language='English'
|
||||
)
|
||||
|
||||
|
||||
@attr('shard_5')
|
||||
@ddt.ddt
|
||||
class TeamPageTest(TeamsTabBase):
|
||||
|
||||
@@ -4,13 +4,14 @@ define([
|
||||
'backbone',
|
||||
'common/js/spec_helpers/ajax_helpers',
|
||||
'teams/js/views/edit_team',
|
||||
'teams/js/models/team',
|
||||
'teams/js/spec_helpers/team_spec_helpers'
|
||||
], function ($, _, Backbone, AjaxHelpers, TeamEditView, TeamSpecHelpers) {
|
||||
], function ($, _, Backbone, AjaxHelpers, TeamEditView, TeamModel, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe('EditTeam', function () {
|
||||
describe('CreateEditTeam', function() {
|
||||
var teamsUrl = '/api/team/v0/teams/',
|
||||
teamsData = {
|
||||
createTeamData = {
|
||||
id: null,
|
||||
name: "TeamName",
|
||||
is_active: null,
|
||||
@@ -18,11 +19,17 @@ define([
|
||||
topic_id: "awesomeness",
|
||||
date_created: "",
|
||||
description: "TeamDescription",
|
||||
country: "c",
|
||||
language: "a",
|
||||
country: "US",
|
||||
language: "en",
|
||||
membership: [],
|
||||
last_activity_at: ''
|
||||
},
|
||||
editTeamData = {
|
||||
name: "UpdatedAvengers",
|
||||
description: "We do not discuss about avengers.",
|
||||
country: "US",
|
||||
language: "en"
|
||||
},
|
||||
verifyValidation = function (requests, teamEditView, fieldsData) {
|
||||
_.each(fieldsData, function (fieldData) {
|
||||
teamEditView.$(fieldData[0]).val(fieldData[1]);
|
||||
@@ -32,33 +39,57 @@ define([
|
||||
|
||||
var message = teamEditView.$('.wrapper-msg');
|
||||
expect(message.hasClass('is-hidden')).toBeFalsy();
|
||||
expect(message.find('.title').text().trim()).toBe("Your team could not be created!");
|
||||
var actionMessage = (teamAction === 'create' ? 'Your team could not be created.' : 'Your team could not be updated.');
|
||||
expect(message.find('.title').text().trim()).toBe(actionMessage);
|
||||
expect(message.find('.copy').text().trim()).toBe(
|
||||
"Check the highlighted fields below and try again."
|
||||
);
|
||||
|
||||
_.each(fieldsData, function (fieldData) {
|
||||
if(fieldData[2] === 'error') {
|
||||
if (fieldData[2] === 'error') {
|
||||
expect(teamEditView.$(fieldData[0].split(" ")[0] + '.error').length).toBe(1);
|
||||
} else if(fieldData[2] === 'success') {
|
||||
} else if (fieldData[2] === 'success') {
|
||||
expect(teamEditView.$(fieldData[0].split(" ")[0] + '.error').length).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
expect(requests.length).toBe(0);
|
||||
};
|
||||
},
|
||||
editTeamID = 'av',
|
||||
teamAction;
|
||||
|
||||
var createEditTeamView = function () {
|
||||
var teamModel = {};
|
||||
if (teamAction === 'edit') {
|
||||
teamModel = new TeamModel(
|
||||
{
|
||||
id: editTeamID,
|
||||
name: 'Avengers',
|
||||
description: 'Team of dumbs',
|
||||
language: 'en',
|
||||
country: 'US',
|
||||
membership: [],
|
||||
url: '/api/team/v0/teams/' + editTeamID
|
||||
},
|
||||
{
|
||||
parse: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
var createTeamEditView = function() {
|
||||
return new TeamEditView({
|
||||
teamEvents: TeamSpecHelpers.teamEvents,
|
||||
el: $('.teams-content'),
|
||||
action: teamAction,
|
||||
model: teamModel,
|
||||
teamParams: {
|
||||
teamsUrl: teamsUrl,
|
||||
courseID: "a/b/c",
|
||||
topicID: 'awesomeness',
|
||||
topicName: 'Awesomeness',
|
||||
languages: [['a', 'aaa'], ['b', 'bbb']],
|
||||
countries: [['c', 'ccc'], ['d', 'ddd']]
|
||||
languages: [['aa', 'Afar'], ['fr', 'French'], ['en', 'English']],
|
||||
countries: [['af', 'Afghanistan'], ['CA', 'Canada'], ['US', 'United States']],
|
||||
teamsDetailUrl: teamModel.url
|
||||
}
|
||||
}).render();
|
||||
};
|
||||
@@ -68,15 +99,15 @@ define([
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
});
|
||||
|
||||
it('can render itself correctly', function () {
|
||||
var assertFormRendersCorrectly = function() {
|
||||
var fieldClasses = [
|
||||
'.u-field-name',
|
||||
'.u-field-description',
|
||||
'.u-field-optional_description',
|
||||
'.u-field-language',
|
||||
'.u-field-country'
|
||||
],
|
||||
teamEditView = createTeamEditView();
|
||||
'.u-field-name',
|
||||
'.u-field-description',
|
||||
'.u-field-optional_description',
|
||||
'.u-field-language',
|
||||
'.u-field-country'
|
||||
],
|
||||
teamEditView = createEditTeamView();
|
||||
|
||||
_.each(fieldClasses, function (fieldClass) {
|
||||
expect(teamEditView.$el.find(fieldClass).length).toBe(1);
|
||||
@@ -84,32 +115,46 @@ define([
|
||||
|
||||
expect(teamEditView.$('.create-team.form-actions .action-primary').length).toBe(1);
|
||||
expect(teamEditView.$('.create-team.form-actions .action-cancel').length).toBe(1);
|
||||
});
|
||||
|
||||
it('can create a team', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamEditView = createTeamEditView();
|
||||
if (teamAction === 'edit') {
|
||||
expect(teamEditView.$el.find('.u-field-name input').val()).toBe('Avengers');
|
||||
expect(teamEditView.$el.find('.u-field-description textarea').val()).toBe('Team of dumbs');
|
||||
expect(teamEditView.$el.find('.u-field-language select option:selected').text()).toBe('English');
|
||||
expect(teamEditView.$el.find('.u-field-country select option:selected').text()).toBe('United States');
|
||||
}
|
||||
};
|
||||
|
||||
var requestMethod = function() {
|
||||
return teamAction === 'create' ? 'POST' : 'PATCH';
|
||||
};
|
||||
|
||||
var assertTeamCreateUpdateInfo = function(that, teamsData, teamsUrl, expectedUrl) {
|
||||
var requests = AjaxHelpers.requests(that),
|
||||
teamEditView = createEditTeamView();
|
||||
|
||||
teamEditView.$('.u-field-name input').val(teamsData.name);
|
||||
teamEditView.$('.u-field-textarea textarea').val(teamsData.description);
|
||||
teamEditView.$('.u-field-language select').val('a').attr("selected", "selected");
|
||||
teamEditView.$('.u-field-country select').val('c').attr("selected", "selected");
|
||||
teamEditView.$('.u-field-language select').val(teamsData.language).attr("selected", "selected");
|
||||
teamEditView.$('.u-field-country select').val(teamsData.country).attr("selected", "selected");
|
||||
|
||||
teamEditView.$('.create-team.form-actions .action-primary').click();
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', teamsUrl, teamsData);
|
||||
AjaxHelpers.respondWithJson(requests, _.extend(_.extend({}, teamsData), { id: '123'}));
|
||||
|
||||
AjaxHelpers.expectJsonRequest(requests, requestMethod(), teamsUrl, teamsData);
|
||||
AjaxHelpers.respondWithJson(requests, _.extend(_.extend({}, teamsData), teamAction === 'create' ? {id: '123'} : {}));
|
||||
|
||||
expect(teamEditView.$('.create-team.wrapper-msg .copy').text().trim().length).toBe(0);
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain('teams/awesomeness/123');
|
||||
});
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain(expectedUrl);
|
||||
};
|
||||
|
||||
var assertValidationMessagesWhenFieldsEmpty = function(that) {
|
||||
var requests = AjaxHelpers.requests(that),
|
||||
teamEditView = createEditTeamView();
|
||||
|
||||
it('shows validation error message when field is empty', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamEditView = createTeamEditView();
|
||||
verifyValidation(requests, teamEditView, [
|
||||
['.u-field-name input', 'Name', 'success'],
|
||||
['.u-field-textarea textarea', '', 'error']
|
||||
]);
|
||||
|
||||
teamEditView.render();
|
||||
verifyValidation(requests, teamEditView, [
|
||||
['.u-field-name input', '', 'error'],
|
||||
@@ -120,13 +165,13 @@ define([
|
||||
['.u-field-name input', '', 'error'],
|
||||
['.u-field-textarea textarea', '', 'error']
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
it('shows validation error message when field value length exceeded the limit', function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamEditView = createTeamEditView(),
|
||||
teamName = new Array(500 + 1).join( '$'),
|
||||
teamDescription = new Array(500 + 1).join( '$' );
|
||||
var assertValidationMessagesWhenInvalidData = function(that) {
|
||||
var requests = AjaxHelpers.requests(that),
|
||||
teamEditView = createEditTeamView(),
|
||||
teamName = new Array(500 + 1).join('$'),
|
||||
teamDescription = new Array(500 + 1).join('$');
|
||||
|
||||
verifyValidation(requests, teamEditView, [
|
||||
['.u-field-name input', teamName, 'error'],
|
||||
@@ -142,48 +187,114 @@ define([
|
||||
['.u-field-name input', teamName, 'error'],
|
||||
['.u-field-textarea textarea', teamDescription, 'error']
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
it("shows an error message for HTTP 500", function () {
|
||||
var teamEditView = createTeamEditView(),
|
||||
requests = AjaxHelpers.requests(this);
|
||||
var assertShowMessageOnError = function(that, teamsData, teamsUrl, errorCode) {
|
||||
var teamEditView = createEditTeamView(),
|
||||
requests = AjaxHelpers.requests(that);
|
||||
|
||||
teamEditView.$('.u-field-name input').val(teamsData.name);
|
||||
teamEditView.$('.u-field-textarea textarea').val(teamsData.description);
|
||||
|
||||
teamEditView.$('.create-team.form-actions .action-primary').click();
|
||||
teamsData.country = '';
|
||||
teamsData.language = '';
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', teamsUrl, teamsData);
|
||||
AjaxHelpers.respondWithError(requests);
|
||||
|
||||
expect(teamEditView.$('.wrapper-msg .copy').text().trim()).toBe("An error occurred. Please try again.");
|
||||
});
|
||||
if (teamAction === 'create') {
|
||||
teamsData.country = '';
|
||||
teamsData.language = '';
|
||||
}
|
||||
AjaxHelpers.expectJsonRequest(requests, requestMethod(), teamsUrl, teamsData);
|
||||
|
||||
it("shows correct error message when server returns an error", function () {
|
||||
var requests = AjaxHelpers.requests(this),
|
||||
teamEditView = createTeamEditView();
|
||||
if (errorCode < 500) {
|
||||
AjaxHelpers.respondWithError(
|
||||
requests,
|
||||
errorCode,
|
||||
{'user_message': 'User message', 'developer_message': 'Developer message'}
|
||||
);
|
||||
expect(teamEditView.$('.wrapper-msg .copy').text().trim()).toBe("User message");
|
||||
} else {
|
||||
AjaxHelpers.respondWithError(requests);
|
||||
expect(teamEditView.$('.wrapper-msg .copy').text().trim()).toBe("An error occurred. Please try again.");
|
||||
}
|
||||
};
|
||||
|
||||
teamEditView.$('.u-field-name input').val(teamsData.name);
|
||||
teamEditView.$('.u-field-textarea textarea').val(teamsData.description);
|
||||
|
||||
teamEditView.$('.create-team.form-actions .action-primary').click();
|
||||
teamsData.country = '';
|
||||
teamsData.language = '';
|
||||
AjaxHelpers.expectJsonRequest(requests, 'POST', teamsUrl, teamsData);
|
||||
AjaxHelpers.respondWithError(
|
||||
requests,
|
||||
400,
|
||||
{'user_message': 'User message', 'developer_message': 'Developer message'}
|
||||
);
|
||||
|
||||
expect(teamEditView.$('.wrapper-msg .copy').text().trim()).toBe("User message");
|
||||
});
|
||||
|
||||
it("changes route on cancel click", function () {
|
||||
var teamEditView = createTeamEditView();
|
||||
var assertRedirectsToCorrectUrlOnCancel = function(expectedUrl) {
|
||||
var teamEditView = createEditTeamView();
|
||||
teamEditView.$('.create-team.form-actions .action-cancel').click();
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain('topics/awesomeness');
|
||||
expect(Backbone.history.navigate.calls[0].args).toContain(expectedUrl);
|
||||
};
|
||||
|
||||
describe('NewTeam', function () {
|
||||
|
||||
beforeEach(function() {
|
||||
teamAction = 'create';
|
||||
});
|
||||
|
||||
it('can render itself correctly', function () {
|
||||
assertFormRendersCorrectly();
|
||||
});
|
||||
|
||||
it('can create a team', function () {
|
||||
assertTeamCreateUpdateInfo(this, createTeamData, teamsUrl, 'teams/awesomeness/123');
|
||||
});
|
||||
|
||||
it('shows validation error message when field is empty', function () {
|
||||
assertValidationMessagesWhenFieldsEmpty(this);
|
||||
});
|
||||
|
||||
it('shows validation error message when field value length exceeded the limit', function () {
|
||||
assertValidationMessagesWhenInvalidData(this);
|
||||
});
|
||||
|
||||
it("shows an error message for HTTP 500", function () {
|
||||
assertShowMessageOnError(this, createTeamData, teamsUrl, 500);
|
||||
});
|
||||
|
||||
it("shows correct error message when server returns an error", function () {
|
||||
assertShowMessageOnError(this, createTeamData, teamsUrl, 400);
|
||||
});
|
||||
|
||||
it("changes route on cancel click", function () {
|
||||
assertRedirectsToCorrectUrlOnCancel('topics/awesomeness');
|
||||
});
|
||||
});
|
||||
|
||||
describe('EditTeam', function () {
|
||||
|
||||
beforeEach(function() {
|
||||
teamAction = 'edit';
|
||||
});
|
||||
|
||||
it('can render itself correctly', function () {
|
||||
assertFormRendersCorrectly();
|
||||
});
|
||||
|
||||
it('can edit a team', function () {
|
||||
var copyTeamsData = _.clone(editTeamData);
|
||||
copyTeamsData.country = 'CA';
|
||||
copyTeamsData.language = 'fr';
|
||||
|
||||
assertTeamCreateUpdateInfo(this, copyTeamsData, teamsUrl + editTeamID + '?expand=user', 'teams/awesomeness/' + editTeamID);
|
||||
});
|
||||
|
||||
it('shows validation error message when field is empty', function () {
|
||||
assertValidationMessagesWhenFieldsEmpty(this);
|
||||
});
|
||||
|
||||
it('shows validation error message when field value length exceeded the limit', function () {
|
||||
assertValidationMessagesWhenInvalidData(this);
|
||||
});
|
||||
|
||||
it("shows an error message for HTTP 500", function () {
|
||||
assertShowMessageOnError(this, editTeamData, teamsUrl + editTeamID + '?expand=user', 500);
|
||||
});
|
||||
|
||||
it("shows correct error message when server returns an error", function () {
|
||||
assertShowMessageOnError(this, editTeamData, teamsUrl + editTeamID + '?expand=user', 400);
|
||||
});
|
||||
|
||||
it("changes route on cancel click", function () {
|
||||
assertRedirectsToCorrectUrlOnCancel('teams/awesomeness/' + editTeamID);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
define([
|
||||
'backbone', 'underscore', 'common/js/spec_helpers/ajax_helpers', 'teams/js/models/team',
|
||||
'teams/js/views/team_join', 'teams/js/spec_helpers/team_spec_helpers'
|
||||
], function (Backbone, _, AjaxHelpers, TeamModel, TeamJoinView, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
describe('TeamJoinView', function () {
|
||||
var createTeamsUrl,
|
||||
createTeamModelData,
|
||||
createMembershipData,
|
||||
createJoinView,
|
||||
verifyErrorMessage,
|
||||
ACCOUNTS_API_URL = '/api/user/v1/accounts/',
|
||||
TEAMS_URL = '/api/team/v0/teams/',
|
||||
TEAMS_MEMBERSHIP_URL = '/api/team/v0/team_membership/';
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures(
|
||||
'<div class="teams-content"><div class="msg-content"><div class="copy"></div></div><div class="header-action-view"></div></div>'
|
||||
);
|
||||
});
|
||||
|
||||
verifyErrorMessage = function (requests, errorMessage, expectedMessage, joinTeam) {
|
||||
var view = createJoinView(1, 'ma', createTeamModelData('teamA', 'teamAlpha', []));
|
||||
if (joinTeam) {
|
||||
// if we want the error to return when user try to join team, respond with no membership
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 0});
|
||||
view.$('.action.action-primary').click();
|
||||
}
|
||||
AjaxHelpers.respondWithTextError(requests, 400, errorMessage);
|
||||
expect($('.msg-content .copy').text().trim()).toBe(expectedMessage);
|
||||
};
|
||||
|
||||
createTeamsUrl = function (teamId) {
|
||||
return TEAMS_URL + teamId + '?expand=user';
|
||||
};
|
||||
|
||||
createTeamModelData = function (teamId, teamName, membership) {
|
||||
return {
|
||||
id: teamId,
|
||||
name: teamName,
|
||||
membership: membership
|
||||
};
|
||||
};
|
||||
|
||||
createMembershipData = function (username) {
|
||||
return [
|
||||
{
|
||||
"user": {
|
||||
"username": username,
|
||||
"url": ACCOUNTS_API_URL + username
|
||||
}
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
createJoinView = function(maxTeamSize, currentUsername, teamModelData, teamId) {
|
||||
teamId = teamId || 'teamA';
|
||||
|
||||
var model = new TeamModel(teamModelData, { parse: true });
|
||||
model.url = createTeamsUrl(teamId);
|
||||
|
||||
var teamJoinView = new TeamJoinView(
|
||||
{
|
||||
courseID: TeamSpecHelpers.testCourseID,
|
||||
teamEvents: TeamSpecHelpers.teamEvents,
|
||||
model: model,
|
||||
teamsUrl: createTeamsUrl(teamId),
|
||||
maxTeamSize: maxTeamSize,
|
||||
currentUsername: currentUsername,
|
||||
teamMembershipsUrl: TEAMS_MEMBERSHIP_URL
|
||||
}
|
||||
);
|
||||
return teamJoinView.render();
|
||||
};
|
||||
|
||||
it('can render itself', function () {
|
||||
var teamModelData = createTeamModelData('teamA', 'teamAlpha', createMembershipData('ma'));
|
||||
var view = createJoinView(1, 'ma', teamModelData);
|
||||
|
||||
expect(view.$('.join-team').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('can join team successfully', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var currentUsername = 'ma1';
|
||||
var teamId = 'teamA';
|
||||
var teamName = 'teamAlpha';
|
||||
var teamModelData = createTeamModelData(teamId, teamName, []);
|
||||
var view = createJoinView(1, currentUsername, teamModelData);
|
||||
|
||||
// a get request will be sent to get user membership info
|
||||
// because current user is not member of current team
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
TEAMS_MEMBERSHIP_URL + '?' + $.param({
|
||||
'username': currentUsername, 'course_id': TeamSpecHelpers.testCourseID
|
||||
})
|
||||
);
|
||||
|
||||
// current user is not a member of any team so we should see the Join Team button
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 0});
|
||||
expect(view.$('.action.action-primary').length).toEqual(1);
|
||||
|
||||
// a post request will be sent to add current user to current team
|
||||
view.$('.action.action-primary').click();
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
TEAMS_MEMBERSHIP_URL,
|
||||
$.param({'username': currentUsername, 'team_id': teamId})
|
||||
);
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
// on success, team model will be fetched and
|
||||
// join team view and team profile will be re-rendered
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
createTeamsUrl(teamId)
|
||||
);
|
||||
AjaxHelpers.respondWithJson(
|
||||
requests, createTeamModelData(teamId, teamName, createMembershipData(currentUsername))
|
||||
);
|
||||
|
||||
// current user is now member of the current team then there should be no button and no message
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('shows already member message', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var currentUsername = 'ma1';
|
||||
var view = createJoinView(1, currentUsername, createTeamModelData('teamA', 'teamAlpha', []));
|
||||
|
||||
// a get request will be sent to get user membership info
|
||||
// because current user is not member of current team
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
TEAMS_MEMBERSHIP_URL + '?' + $.param({
|
||||
'username': currentUsername, 'course_id': TeamSpecHelpers.testCourseID
|
||||
})
|
||||
);
|
||||
|
||||
// current user is a member of another team so we should see the correct message
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 1});
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').text().trim()).toBe(view.alreadyMemberMessage);
|
||||
});
|
||||
|
||||
it('shows team full message', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var view = createJoinView(
|
||||
1,
|
||||
'ma1',
|
||||
createTeamModelData('teamA', 'teamAlpha', createMembershipData('ma'))
|
||||
);
|
||||
|
||||
// team has no space and current user is a not member of
|
||||
// current team so we should see the correct message
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').text().trim()).toBe(view.teamFullMessage);
|
||||
|
||||
// there should be no request made
|
||||
expect(requests.length).toBe(0);
|
||||
});
|
||||
|
||||
it('shows correct error message if user fails to join team', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
// verify user_message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'user_message': "Can't be made member"}),
|
||||
"Can't be made member",
|
||||
true
|
||||
);
|
||||
|
||||
// verify generic error message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
'',
|
||||
'An error occurred. Try again.',
|
||||
true
|
||||
);
|
||||
|
||||
// verify error message when json parsing succeeded but error message format is incorrect
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'blah': "Can't be made member"}),
|
||||
'An error occurred. Try again.',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('shows correct error message if initializing the view fails', function () {
|
||||
// Rendering the view sometimes require fetching user's memberships. This may fail.
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
// verify user_message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'user_message': "Can't return user memberships"}),
|
||||
"Can't return user memberships",
|
||||
false
|
||||
);
|
||||
|
||||
// verify generic error message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
'',
|
||||
'An error occurred. Try again.',
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,254 @@
|
||||
define([
|
||||
'backbone', 'underscore', 'common/js/spec_helpers/ajax_helpers', 'teams/js/models/team',
|
||||
'teams/js/views/team_profile_header_actions', 'teams/js/spec_helpers/team_spec_helpers'
|
||||
], function (Backbone, _, AjaxHelpers, TeamModel, TeamProfileHeaderActionsView, TeamSpecHelpers) {
|
||||
'use strict';
|
||||
|
||||
describe('TeamProfileHeaderActionsView', function () {
|
||||
var createTeamsUrl,
|
||||
createTeamModelData,
|
||||
createMembershipData,
|
||||
createHeaderActionsView,
|
||||
verifyErrorMessage,
|
||||
ACCOUNTS_API_URL = '/api/user/v1/accounts/',
|
||||
TEAMS_URL = '/api/team/v0/teams/',
|
||||
TEAMS_MEMBERSHIP_URL = '/api/team/v0/team_membership/';
|
||||
|
||||
createTeamsUrl = function (teamId) {
|
||||
return TEAMS_URL + teamId + '?expand=user';
|
||||
};
|
||||
|
||||
createTeamModelData = function (teamId, teamName, membership) {
|
||||
return {
|
||||
id: teamId,
|
||||
name: teamName,
|
||||
membership: membership,
|
||||
url: createTeamsUrl(teamId)
|
||||
};
|
||||
};
|
||||
|
||||
createHeaderActionsView = function(maxTeamSize, currentUsername, teamModelData, showEditButton) {
|
||||
var teamId = 'teamA';
|
||||
|
||||
var model = new TeamModel(teamModelData, { parse: true });
|
||||
|
||||
return new TeamProfileHeaderActionsView(
|
||||
{
|
||||
courseID: TeamSpecHelpers.testCourseID,
|
||||
teamEvents: TeamSpecHelpers.teamEvents,
|
||||
model: model,
|
||||
teamsUrl: createTeamsUrl(teamId),
|
||||
maxTeamSize: maxTeamSize,
|
||||
currentUsername: currentUsername,
|
||||
teamMembershipsUrl: TEAMS_MEMBERSHIP_URL,
|
||||
topicID: '',
|
||||
showEditButton: showEditButton
|
||||
}
|
||||
).render();
|
||||
};
|
||||
|
||||
createMembershipData = function (username) {
|
||||
return [
|
||||
{
|
||||
"user": {
|
||||
"username": username,
|
||||
"url": ACCOUNTS_API_URL + username
|
||||
}
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
describe('JoinButton', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
setFixtures(
|
||||
'<div class="teams-content"><div class="msg-content"><div class="copy"></div></div><div class="header-action-view"></div></div>'
|
||||
);
|
||||
});
|
||||
|
||||
verifyErrorMessage = function (requests, errorMessage, expectedMessage, joinTeam) {
|
||||
var view = createHeaderActionsView(1, 'ma', createTeamModelData('teamA', 'teamAlpha', []));
|
||||
if (joinTeam) {
|
||||
// if we want the error to return when user try to join team, respond with no membership
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 0});
|
||||
view.$('.action.action-primary').click();
|
||||
}
|
||||
AjaxHelpers.respondWithTextError(requests, 400, errorMessage);
|
||||
expect($('.msg-content .copy').text().trim()).toBe(expectedMessage);
|
||||
};
|
||||
|
||||
it('can render itself', function () {
|
||||
var teamModelData = createTeamModelData('teamA', 'teamAlpha', createMembershipData('ma'));
|
||||
var view = createHeaderActionsView(1, 'ma', teamModelData);
|
||||
|
||||
expect(view.$('.join-team').length).toEqual(1);
|
||||
});
|
||||
|
||||
it('can join team successfully', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var currentUsername = 'ma1';
|
||||
var teamId = 'teamA';
|
||||
var teamName = 'teamAlpha';
|
||||
var teamModelData = createTeamModelData(teamId, teamName, []);
|
||||
var view = createHeaderActionsView(1, currentUsername, teamModelData);
|
||||
|
||||
// a get request will be sent to get user membership info
|
||||
// because current user is not member of current team
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
TEAMS_MEMBERSHIP_URL + '?' + $.param({
|
||||
'username': currentUsername, 'course_id': TeamSpecHelpers.testCourseID
|
||||
})
|
||||
);
|
||||
|
||||
// current user is not a member of any team so we should see the Join Team button
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 0});
|
||||
expect(view.$('.action.action-primary').length).toEqual(1);
|
||||
|
||||
// a post request will be sent to add current user to current team
|
||||
view.$('.action.action-primary').click();
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'POST',
|
||||
TEAMS_MEMBERSHIP_URL,
|
||||
$.param({'username': currentUsername, 'team_id': teamId})
|
||||
);
|
||||
AjaxHelpers.respondWithJson(requests, {});
|
||||
|
||||
// on success, team model will be fetched and
|
||||
// join team view and team profile will be re-rendered
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
createTeamsUrl(teamId)
|
||||
);
|
||||
AjaxHelpers.respondWithJson(
|
||||
requests, createTeamModelData(teamId, teamName, createMembershipData(currentUsername))
|
||||
);
|
||||
|
||||
// current user is now member of the current team then there should be no button and no message
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').length).toEqual(0);
|
||||
});
|
||||
|
||||
it('shows already member message', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var currentUsername = 'ma1';
|
||||
var view = createHeaderActionsView(1, currentUsername, createTeamModelData('teamA', 'teamAlpha', []));
|
||||
|
||||
// a get request will be sent to get user membership info
|
||||
// because current user is not member of current team
|
||||
AjaxHelpers.expectRequest(
|
||||
requests,
|
||||
'GET',
|
||||
TEAMS_MEMBERSHIP_URL + '?' + $.param({
|
||||
'username': currentUsername, 'course_id': TeamSpecHelpers.testCourseID
|
||||
})
|
||||
);
|
||||
|
||||
// current user is a member of another team so we should see the correct message
|
||||
AjaxHelpers.respondWithJson(requests, {"count": 1});
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').text().trim()).toBe(view.alreadyMemberMessage);
|
||||
});
|
||||
|
||||
it('shows team full message', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
var view = createHeaderActionsView(
|
||||
1,
|
||||
'ma1',
|
||||
createTeamModelData('teamA', 'teamAlpha', createMembershipData('ma'))
|
||||
);
|
||||
|
||||
// team has no space and current user is a not member of
|
||||
// current team so we should see the correct message
|
||||
expect(view.$('.action.action-primary').length).toEqual(0);
|
||||
expect(view.$('.join-team-message').text().trim()).toBe(view.teamFullMessage);
|
||||
|
||||
// there should be no request made
|
||||
expect(requests.length).toBe(0);
|
||||
});
|
||||
|
||||
it('shows correct error message if user fails to join team', function () {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
// verify user_message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'user_message': "Can't be made member"}),
|
||||
"Can't be made member",
|
||||
true
|
||||
);
|
||||
|
||||
// verify generic error message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
'',
|
||||
'An error occurred. Try again.',
|
||||
true
|
||||
);
|
||||
|
||||
// verify error message when json parsing succeeded but error message format is incorrect
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'blah': "Can't be made member"}),
|
||||
'An error occurred. Try again.',
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('shows correct error message if initializing the view fails', function () {
|
||||
// Rendering the view sometimes require fetching user's memberships. This may fail.
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
|
||||
// verify user_message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
JSON.stringify({'user_message': "Can't return user memberships"}),
|
||||
"Can't return user memberships",
|
||||
false
|
||||
);
|
||||
|
||||
// verify generic error message
|
||||
verifyErrorMessage(
|
||||
requests,
|
||||
'',
|
||||
'An error occurred. Try again.',
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('EditButton', function() {
|
||||
var teamModelData,
|
||||
view,
|
||||
createAndAssertView;
|
||||
|
||||
createAndAssertView = function(showEditButton) {
|
||||
teamModelData = createTeamModelData('aveA', 'avengers', createMembershipData('ma'));
|
||||
view = createHeaderActionsView(1, 'ma', teamModelData, showEditButton);
|
||||
expect(view.$('.action-edit-team').length).toEqual(showEditButton ? 1 : 0);
|
||||
};
|
||||
|
||||
it('renders when option showEditButton is true', function () {
|
||||
createAndAssertView(true);
|
||||
});
|
||||
|
||||
it('does not render when option showEditButton is false', function () {
|
||||
createAndAssertView(false);
|
||||
});
|
||||
|
||||
it("can navigate to correct url", function () {
|
||||
spyOn(Backbone.history, 'navigate');
|
||||
createAndAssertView(true);
|
||||
var editButton = view.$('.action-edit-team');
|
||||
|
||||
expect(editButton.length).toEqual(1);
|
||||
$(editButton).click();
|
||||
|
||||
expect(Backbone.history.navigate.calls[0].args[0]).toContain('/edit-team');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -14,9 +14,9 @@
|
||||
maxTeamDescriptionLength: 300,
|
||||
|
||||
events: {
|
||||
'click .action-primary': 'createTeam',
|
||||
'submit form': 'createTeam',
|
||||
'click .action-cancel': 'goBackToTopic'
|
||||
'click .action-primary': 'createOrUpdateTeam',
|
||||
'submit form': 'createOrUpdateTeam',
|
||||
'click .action-cancel': 'cancelAndGoBack'
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
@@ -27,12 +27,20 @@
|
||||
this.teamsUrl = options.teamParams.teamsUrl;
|
||||
this.languages = options.teamParams.languages;
|
||||
this.countries = options.teamParams.countries;
|
||||
this.primaryButtonTitle = options.primaryButtonTitle || 'Submit';
|
||||
this.teamsDetailUrl = options.teamParams.teamsDetailUrl;
|
||||
this.action = options.action;
|
||||
|
||||
_.bindAll(this, 'goBackToTopic', 'createTeam');
|
||||
_.bindAll(this, 'cancelAndGoBack', 'createOrUpdateTeam');
|
||||
|
||||
this.teamModel = new TeamModel({});
|
||||
this.teamModel.url = this.teamsUrl;
|
||||
if (this.action === 'create') {
|
||||
this.teamModel = new TeamModel({});
|
||||
this.teamModel.url = this.teamsUrl;
|
||||
this.primaryButtonTitle = 'Create';
|
||||
} else if(this.action === 'edit' ) {
|
||||
this.teamModel = options.model;
|
||||
this.teamModel.url = this.teamsDetailUrl.replace('team_id', options.model.get('id')) + '?expand=user';
|
||||
this.primaryButtonTitle = 'Update';
|
||||
}
|
||||
|
||||
this.teamNameField = new FieldViews.TextFieldView({
|
||||
model: this.teamModel,
|
||||
@@ -74,7 +82,11 @@
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(_.template(editTeamTemplate)({primaryButtonTitle: this.primaryButtonTitle}));
|
||||
this.$el.html(_.template(editTeamTemplate) ({
|
||||
primaryButtonTitle: this.primaryButtonTitle,
|
||||
action: this.action,
|
||||
totalMembers: _.isUndefined(this.teamModel) ? 0 : this.teamModel.get('membership').length
|
||||
}));
|
||||
this.set(this.teamNameField, '.team-required-fields');
|
||||
this.set(this.teamDescriptionField, '.team-required-fields');
|
||||
this.set(this.teamLanguageField, '.team-optional-fields');
|
||||
@@ -91,20 +103,28 @@
|
||||
}
|
||||
},
|
||||
|
||||
createTeam: function (event) {
|
||||
createOrUpdateTeam: function (event) {
|
||||
event.preventDefault();
|
||||
var view = this,
|
||||
teamLanguage = this.teamLanguageField.fieldValue(),
|
||||
teamCountry = this.teamCountryField.fieldValue();
|
||||
teamCountry = this.teamCountryField.fieldValue(),
|
||||
data = {
|
||||
name: this.teamNameField.fieldValue(),
|
||||
description: this.teamDescriptionField.fieldValue(),
|
||||
language: _.isNull(teamLanguage) ? '' : teamLanguage,
|
||||
country: _.isNull(teamCountry) ? '' : teamCountry
|
||||
},
|
||||
saveOptions = {
|
||||
wait: true
|
||||
};
|
||||
|
||||
var data = {
|
||||
course_id: this.courseID,
|
||||
topic_id: this.topicID,
|
||||
name: this.teamNameField.fieldValue(),
|
||||
description: this.teamDescriptionField.fieldValue(),
|
||||
language: _.isNull(teamLanguage) ? '' : teamLanguage,
|
||||
country: _.isNull(teamCountry) ? '' : teamCountry
|
||||
};
|
||||
if (this.action === 'create') {
|
||||
data.course_id = this.courseID;
|
||||
data.topic_id = this.topicID;
|
||||
} else if (this.action === 'edit' ) {
|
||||
saveOptions.patch = true;
|
||||
saveOptions.contentType = 'application/merge-patch+json';
|
||||
}
|
||||
|
||||
var validationResult = this.validateTeamData(data);
|
||||
if (validationResult.status === false) {
|
||||
@@ -112,10 +132,10 @@
|
||||
return;
|
||||
}
|
||||
|
||||
this.teamModel.save(data, { wait: true })
|
||||
this.teamModel.save(data, saveOptions)
|
||||
.done(function(result) {
|
||||
view.teamEvents.trigger('teams:update', {
|
||||
action: 'create',
|
||||
action: view.action,
|
||||
team: result
|
||||
});
|
||||
Backbone.history.navigate(
|
||||
@@ -186,8 +206,15 @@
|
||||
}
|
||||
},
|
||||
|
||||
goBackToTopic: function () {
|
||||
Backbone.history.navigate('topics/' + this.topicID, {trigger: true});
|
||||
cancelAndGoBack: function (event) {
|
||||
event.preventDefault();
|
||||
var url;
|
||||
if (this.action === 'create') {
|
||||
url = 'topics/' + this.topicID;
|
||||
} else if (this.action === 'edit' ) {
|
||||
url = 'teams/' + this.topicID + '/' + this.teamModel.get('id');
|
||||
}
|
||||
Backbone.history.navigate(url, {trigger: true});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
'underscore',
|
||||
'gettext',
|
||||
'teams/js/views/team_utils',
|
||||
'text!teams/templates/team-join.underscore'],
|
||||
function (Backbone, _, gettext, TeamUtils, teamJoinTemplate) {
|
||||
'text!teams/templates/team-profile-header-actions.underscore'],
|
||||
function (Backbone, _, gettext, TeamUtils, teamProfileHeaderActionsTemplate) {
|
||||
return Backbone.View.extend({
|
||||
|
||||
errorMessage: gettext("An error occurred. Try again."),
|
||||
@@ -14,31 +14,34 @@
|
||||
teamFullMessage: gettext("This team is full."),
|
||||
|
||||
events: {
|
||||
"click .action-primary": "joinTeam"
|
||||
"click .action-primary": "joinTeam",
|
||||
"click .action-edit-team": "editTeam"
|
||||
},
|
||||
|
||||
initialize: function(options) {
|
||||
this.teamEvents = options.teamEvents;
|
||||
this.template = _.template(teamJoinTemplate);
|
||||
this.template = _.template(teamProfileHeaderActionsTemplate);
|
||||
this.courseID = options.courseID;
|
||||
this.maxTeamSize = options.maxTeamSize;
|
||||
this.currentUsername = options.currentUsername;
|
||||
this.teamMembershipsUrl = options.teamMembershipsUrl;
|
||||
_.bindAll(this, 'render', 'joinTeam', 'getUserTeamInfo');
|
||||
this.showEditButton = options.showEditButton;
|
||||
this.topicID = options.topicID;
|
||||
_.bindAll(this, 'render', 'joinTeam','editTeam', 'getUserTeamInfo');
|
||||
this.listenTo(this.model, "change", this.render);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var view = this,
|
||||
message,
|
||||
showButton,
|
||||
showJoinButton,
|
||||
teamHasSpace;
|
||||
this.getUserTeamInfo(this.currentUsername, view.maxTeamSize).done(function (info) {
|
||||
teamHasSpace = info.teamHasSpace;
|
||||
|
||||
// if user is the member of current team then we wouldn't show anything
|
||||
if (!info.memberOfCurrentTeam) {
|
||||
showButton = !info.alreadyMember && teamHasSpace;
|
||||
showJoinButton = !info.alreadyMember && teamHasSpace;
|
||||
|
||||
if (info.alreadyMember) {
|
||||
message = info.memberOfCurrentTeam ? '' : view.alreadyMemberMessage;
|
||||
@@ -47,7 +50,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
view.$el.html(view.template({showButton: showButton, message: message}));
|
||||
view.$el.html(view.template({
|
||||
showJoinButton: showJoinButton,
|
||||
message: message,
|
||||
showEditButton: view.showEditButton
|
||||
}));
|
||||
});
|
||||
return view;
|
||||
},
|
||||
@@ -108,6 +115,10 @@
|
||||
}
|
||||
|
||||
return deferred.promise();
|
||||
},
|
||||
editTeam: function (event) {
|
||||
event.preventDefault();
|
||||
Backbone.history.navigate('topics/' + this.topicID + '/' + this.model.get('id') +'/edit-team', {trigger: true});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -17,12 +17,12 @@
|
||||
'teams/js/views/my_teams',
|
||||
'teams/js/views/topic_teams',
|
||||
'teams/js/views/edit_team',
|
||||
'teams/js/views/team_join',
|
||||
'teams/js/views/team_profile_header_actions',
|
||||
'text!teams/templates/teams_tab.underscore'],
|
||||
function (Backbone, _, gettext, HeaderView, HeaderModel, TabbedView,
|
||||
TopicModel, TopicCollection, TeamModel, TeamCollection, TeamMembershipCollection,
|
||||
TopicsView, TeamProfileView, MyTeamsView, TopicTeamsView, TeamEditView,
|
||||
TeamJoinView, teamsTemplate) {
|
||||
TeamProfileHeaderActionsView, teamsTemplate) {
|
||||
var TeamsHeaderModel = HeaderModel.extend({
|
||||
initialize: function (attributes) {
|
||||
_.extend(this.defaults, {nav_aria_label: gettext('teams')});
|
||||
@@ -52,6 +52,7 @@
|
||||
this.topics = options.topics;
|
||||
this.topicUrl = options.topicUrl;
|
||||
this.teamsUrl = options.teamsUrl;
|
||||
this.teamsDetailUrl = options.teamsDetailUrl;
|
||||
this.teamMembershipsUrl = options.teamMembershipsUrl;
|
||||
this.teamMembershipDetailUrl = options.teamMembershipDetailUrl;
|
||||
this.maxTeamSize = options.maxTeamSize;
|
||||
@@ -74,6 +75,7 @@
|
||||
}, this)],
|
||||
['topics/:topic_id(/)', _.bind(this.browseTopic, this)],
|
||||
['topics/:topic_id/create-team(/)', _.bind(this.newTeam, this)],
|
||||
['topics/:topic_id/:team_id/edit-team(/)', _.bind(this.editTeam, this)],
|
||||
['teams/:topic_id/:team_id(/)', _.bind(this.browseTeam, this)],
|
||||
[new RegExp('^(browse)\/?$'), _.bind(this.goToTab, this)],
|
||||
[new RegExp('^(my-teams)\/?$'), _.bind(this.goToTab, this)]
|
||||
@@ -208,16 +210,53 @@
|
||||
})
|
||||
}),
|
||||
main: new TeamEditView({
|
||||
action: 'create',
|
||||
teamEvents: self.teamEvents,
|
||||
tagName: 'create-new-team',
|
||||
teamParams: teamsView.main.teamParams,
|
||||
primaryButtonTitle: 'Create'
|
||||
teamParams: teamsView.main.teamParams
|
||||
})
|
||||
});
|
||||
self.render();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the edit team form.
|
||||
*/
|
||||
editTeam: function (topicID, teamID) {
|
||||
var self = this,
|
||||
editViewWithHeader;
|
||||
this.getTopic(topicID).done(function (topic) {
|
||||
self.getTeam(teamID, false).done(function(team) {
|
||||
var view = new TeamEditView({
|
||||
action: 'edit',
|
||||
teamEvents: self.teamEvents,
|
||||
teamParams: {
|
||||
courseID: self.courseID,
|
||||
topicID: topic.get('id'),
|
||||
teamsUrl: self.teamsUrl,
|
||||
topicName: topic.get('name'),
|
||||
languages: self.languages,
|
||||
countries: self.countries,
|
||||
teamsDetailUrl: self.teamsDetailUrl
|
||||
},
|
||||
model: team
|
||||
});
|
||||
editViewWithHeader = self.createViewWithHeader({
|
||||
mainView: view,
|
||||
subject: {
|
||||
name: gettext("Edit Team"),
|
||||
description: gettext("If you make significant changes, make sure you notify members of the team before making these changes.")
|
||||
},
|
||||
parentTeam: team,
|
||||
parentTopic: topic
|
||||
}
|
||||
);
|
||||
self.mainView = editViewWithHeader;
|
||||
self.render();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a promise for the TeamsView for the given topic ID.
|
||||
*/
|
||||
@@ -227,7 +266,7 @@
|
||||
var self = this,
|
||||
router = this.router,
|
||||
deferred = $.Deferred();
|
||||
if (this.teamsCollection && this.teamsCollection.topic_id === topicID) {
|
||||
if (this.teamsCollection && this.teamsCollection.topic_id === topicID && this.teamsView) {
|
||||
deferred.resolve(this.teamsView);
|
||||
} else {
|
||||
this.getTopic(topicID)
|
||||
@@ -254,7 +293,8 @@
|
||||
teamsUrl: self.teamsUrl,
|
||||
topicName: topic.get('name'),
|
||||
languages: self.languages,
|
||||
countries: self.countries
|
||||
countries: self.countries,
|
||||
teamsDetailUrl: self.teamsDetailUrl
|
||||
}
|
||||
});
|
||||
deferred.resolve(
|
||||
@@ -311,14 +351,17 @@
|
||||
teamMembershipDetailUrl: self.teamMembershipDetailUrl,
|
||||
setFocusToHeaderFunc: self.setFocusToHeader
|
||||
});
|
||||
var teamJoinView = new TeamJoinView({
|
||||
|
||||
var TeamProfileActionsView = new TeamProfileHeaderActionsView({
|
||||
teamEvents: self.teamEvents,
|
||||
courseID: courseID,
|
||||
model: team,
|
||||
courseID: courseID,
|
||||
model: team,
|
||||
teamsUrl: self.teamsUrl,
|
||||
maxTeamSize: self.maxTeamSize,
|
||||
currentUsername: self.userInfo.username,
|
||||
teamMembershipsUrl: self.teamMembershipsUrl
|
||||
teamMembershipsUrl: self.teamMembershipsUrl,
|
||||
topicID: topicID,
|
||||
showEditButton: self.userInfo.privileged || self.userInfo.staff
|
||||
});
|
||||
deferred.resolve(
|
||||
self.createViewWithHeader(
|
||||
@@ -326,7 +369,7 @@
|
||||
mainView: view,
|
||||
subject: team,
|
||||
parentTopic: topic,
|
||||
headerActionsView: teamJoinView
|
||||
headerActionsView: TeamProfileActionsView
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -337,7 +380,8 @@
|
||||
|
||||
createViewWithHeader: function (options) {
|
||||
var router = this.router,
|
||||
breadcrumbs, headerView;
|
||||
breadcrumbs, headerView,
|
||||
viewDescription, viewTitle;
|
||||
breadcrumbs = [{
|
||||
title: gettext('All Topics'),
|
||||
url: '#browse'
|
||||
@@ -348,10 +392,25 @@
|
||||
url: '#topics/' + options.parentTopic.id
|
||||
});
|
||||
}
|
||||
if (options.parentTeam) {
|
||||
breadcrumbs.push({
|
||||
title: options.parentTeam.get('name'),
|
||||
url: '#teams/' + options.parentTopic.id + '/' + options.parentTeam.id
|
||||
});
|
||||
}
|
||||
if (options.subject instanceof Backbone.Model) {
|
||||
viewDescription = options.subject.get('description');
|
||||
viewTitle = options.subject.get('name');
|
||||
|
||||
} else if (options.subject) {
|
||||
viewDescription = options.subject.description;
|
||||
viewTitle = options.subject.name;
|
||||
}
|
||||
|
||||
headerView = new HeaderView({
|
||||
model: new TeamsHeaderModel({
|
||||
description: options.subject.get('description'),
|
||||
title: options.subject.get('name'),
|
||||
description: viewDescription,
|
||||
title: viewTitle,
|
||||
breadcrumbs: breadcrumbs
|
||||
}),
|
||||
headerActionsView: options.headerActionsView,
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
<form>
|
||||
<div class="create-team wrapper-msg is-incontext urgency-low warning is-hidden" tabindex="-1">
|
||||
<div class="create-team wrapper-msg is-incontext urgency-low error is-hidden" tabindex="-1">
|
||||
<div class="msg">
|
||||
<div class="msg-content">
|
||||
<h3 class="title"><%- gettext("Your team could not be created!") %></h3>
|
||||
<h3 class="title">
|
||||
<% if (action === 'create') { %>
|
||||
<%- gettext("Your team could not be created.") %>
|
||||
<% } else if (action === 'edit') { %>
|
||||
<%- gettext("Your team could not be updated.") %>
|
||||
<% } %>
|
||||
</h3>
|
||||
<span class="screen-reader-message sr"></span>
|
||||
<div class="copy">
|
||||
<p></p>
|
||||
@@ -11,15 +17,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-instructions create-team-instructions">
|
||||
<p class="copy">
|
||||
<%- gettext("Enter information to describe your team. You cannot change these details after you create the team.") %></p>
|
||||
</div>
|
||||
<% if (action === 'create') { %>
|
||||
<div class="form-instructions create-team-instructions">
|
||||
<p class="copy">
|
||||
<%- gettext("Enter information to describe your team. You cannot change these details after you create the team.") %></p>
|
||||
</div>
|
||||
<% } %>
|
||||
|
||||
<div class="team-edit-fields">
|
||||
<div class="team-required-fields">
|
||||
</div>
|
||||
|
||||
<div class="team-optional-fields">
|
||||
<fieldset>
|
||||
<div class="u-field u-field-optional_description">
|
||||
@@ -38,7 +45,7 @@
|
||||
<button class="action action-primary">
|
||||
<%=
|
||||
interpolate_text(
|
||||
_.escape(gettext("{primaryButtonTitle} {span_start}a new team{span_end}")),
|
||||
_.escape(gettext("{primaryButtonTitle} {span_start}a team{span_end}")),
|
||||
{
|
||||
'primaryButtonTitle': primaryButtonTitle, 'span_start': '<span class="sr">', 'span_end': '</span>'
|
||||
}
|
||||
@@ -48,9 +55,10 @@
|
||||
<button class="action action-cancel">
|
||||
<%=
|
||||
interpolate_text(
|
||||
_.escape(gettext("Cancel {span_start}a new team{span_end}")),
|
||||
_.escape(gettext("Cancel {span_start} {action} team {span_end}")),
|
||||
{
|
||||
'span_start': '<span class="sr">', 'span_end': '</span>'
|
||||
'span_start': '<span class="sr">', 'span_end': '</span>',
|
||||
'action': action === 'create' ? 'creating' : 'updating'
|
||||
}
|
||||
)
|
||||
%>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<div class="join-team form-actions">
|
||||
<% if (showButton) {%>
|
||||
<% if (showJoinButton) {%>
|
||||
<button class="action action-primary">
|
||||
<%- gettext("Join Team") %>
|
||||
</button>
|
||||
<% } else if (message) { %>
|
||||
<p class="join-team-message"><%- message %></p>
|
||||
<% } %>
|
||||
|
||||
<% if (showEditButton) { %>
|
||||
<button class="btn btn-secondary action-edit-team"><%- gettext("Edit Team") %></button>
|
||||
<% } %>
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<% if (isMember) { %>
|
||||
<div class="leave-team">
|
||||
<button class="btn btn-link btn-base btn-secondary leave-team-link"><%- gettext("Leave Team") %></button>
|
||||
<button class="btn btn-link leave-team-link"><%- gettext("Leave Team") %></button>
|
||||
</div>
|
||||
|
||||
<div class="divider-lv1"></div>
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
topicUrl: '${ topic_url }',
|
||||
topicsUrl: '${ topics_url }',
|
||||
teamsUrl: '${ teams_url }',
|
||||
teamsDetailUrl: '${ teams_detail_url }',
|
||||
teamMembershipsUrl: '${ team_memberships_url }',
|
||||
teamMembershipDetailUrl: '${ team_membership_detail_url }',
|
||||
maxTeamSize: ${ course.teams_max_size },
|
||||
|
||||
@@ -117,6 +117,7 @@ class TeamsDashboardView(View):
|
||||
),
|
||||
"topics_url": reverse('topics_list', request=request),
|
||||
"teams_url": reverse('teams_list', request=request),
|
||||
"teams_detail_url": reverse('teams_detail', args=['team_id']),
|
||||
"team_memberships_url": reverse('team_membership_list', request=request),
|
||||
"team_membership_detail_url": reverse('team_membership_detail', args=['team_id', user.username]),
|
||||
"languages": settings.ALL_LANGUAGES,
|
||||
|
||||
@@ -802,7 +802,7 @@
|
||||
'lms/include/teams/js/spec/views/topic_card_spec.js',
|
||||
'lms/include/teams/js/spec/views/topic_teams_spec.js',
|
||||
'lms/include/teams/js/spec/views/topics_spec.js',
|
||||
'lms/include/teams/js/spec/views/team_join_spec.js'
|
||||
'lms/include/teams/js/spec/views/team_profile_header_actions_spec.js'
|
||||
]);
|
||||
|
||||
}).call(this, requirejs, define);
|
||||
|
||||
@@ -404,7 +404,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
.btn-secondary {
|
||||
@extend %btn-pl-secondary-base;
|
||||
|
||||
background-image: none;
|
||||
@@ -416,3 +416,24 @@
|
||||
color: $link-color;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
@extend %shame-link-text;
|
||||
|
||||
// reset of inherited buttons
|
||||
border-radius: 0;
|
||||
border-color: $transparent;
|
||||
padding: 1px;
|
||||
background: $transparent;
|
||||
background-image: none;
|
||||
|
||||
@extend %t-action3;
|
||||
@extend %t-strong;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-image: none !important;
|
||||
background-color: $transparent !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user