Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
28fddda4
Commit
28fddda4
authored
Aug 28, 2015
by
Muzaffar yousaf
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9376 from edx/muzaffar/tnl1914-team-edit-page
Edit team page for Instructors only.
parents
f9756eb4
f788caa6
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
849 additions
and
361 deletions
+849
-361
common/test/acceptance/pages/lms/teams.py
+11
-2
common/test/acceptance/tests/lms/test_teams.py
+255
-55
lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js
+180
-69
lms/djangoapps/teams/static/teams/js/spec/views/team_profile_header_actions_spec.js
+209
-173
lms/djangoapps/teams/static/teams/js/views/edit_team.js
+52
-25
lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
+19
-8
lms/djangoapps/teams/static/teams/js/views/teams_tab.js
+74
-15
lms/djangoapps/teams/static/teams/templates/edit-team.underscore
+18
-10
lms/djangoapps/teams/static/teams/templates/team-profile-header-actions.underscore
+5
-1
lms/djangoapps/teams/static/teams/templates/team-profile.underscore
+1
-1
lms/djangoapps/teams/templates/teams/teams.html
+1
-0
lms/djangoapps/teams/views.py
+1
-0
lms/static/js/spec/main.js
+1
-1
lms/static/sass/elements/_controls.scss
+22
-1
No files found.
common/test/acceptance/pages/lms/teams.py
View file @
28fddda4
...
...
@@ -205,7 +205,7 @@ class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
self
.
wait_for_ajax
()
class
CreateTeamPage
(
CoursePage
,
FieldsMixin
):
class
Create
OrEdit
TeamPage
(
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
(
Create
OrEdit
TeamPage
,
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
()
common/test/acceptance/tests/lms/test_teams.py
View file @
28fddda4
...
...
@@ -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
,
Create
OrEdit
TeamPage
,
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
=
Create
OrEdit
TeamPage
(
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,78 +629,124 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
@attr
(
'shard_5'
)
class
CreateTeamTest
(
TeamsTabBase
):
class
TeamFormActions
(
TeamsTabBase
):
"""
Tests for creating a new Team within a Topic on the Teams page
.
Base class for create & edit team
.
"""
TEAM_DESCRIPTION
=
'The Avengers are a fictional team of superheroes.'
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
.
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'
topic
=
{
'name'
:
'Example Topic'
,
'id'
:
'example_topic'
,
'description'
:
'Description'
}
TEAMS_NAME
=
'Avengers'
def
verify_page_header
(
self
):
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_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'
])
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
()
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
()
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
(
# 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
=
'The Avengers are a fictional team of superheroes.'
value
=
self
.
TEAM_DESCRIPTION
)
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'
)
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
test_user_can_see_create_team_page
(
self
):
def
verify_all_fields_exist
(
self
):
"""
Scenario: The user should be able to see the create team page via teams list page.
Given I am enrolled in a course with a team configuration and a topic
When I visit the Teams page for that topic
Then I should see the Create Team page link on bottom
And When I click create team link
Then I should see the create team page.
And I should see the create team header
And I should also see the help messages for fields.
Verify the fields for create/edit page.
"""
self
.
verify_and_navigate_to_create_team_page
()
self
.
assertEqual
(
self
.
create_team_page
.
message_for_field
(
'name'
),
self
.
create_
or_edit_
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'
),
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_team_page
.
message_for_field
(
'country'
),
self
.
create_
or_edit_
team_page
.
message_for_field
(
'country'
),
'The country that team members primarily identify with.'
)
self
.
assertEqual
(
self
.
create_team_page
.
message_for_field
(
'language'
),
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
.
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
()
def
test_user_can_see_create_team_page
(
self
):
"""
Scenario: The user should be able to see the create team page via teams list page.
Given I am enrolled in a course with a team configuration and a topic
When I visit the Teams page for that topic
Then I should see the Create Team page link on bottom
And When I click create team link
Then I should see the create team page.
And I should see the create team header
And I should also see the help messages for fields.
"""
self
.
verify_and_navigate_to_create_team_page
()
self
.
verify_all_fields_exist
()
def
test_user_can_see_error_message_for_missing_data
(
self
):
"""
Scenario: The user should be able to see error message in case of missing required field.
...
...
@@ -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
):
...
...
lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js
View file @
28fddda4
...
...
@@ -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
,
Team
Model
,
Team
SpecHelpers
)
{
'use strict'
;
describe
(
'
EditTeam'
,
function
()
{
describe
(
'
CreateEditTeam'
,
function
()
{
var
teamsUrl
=
'/api/team/v0/teams/'
,
teams
Data
=
{
createTeam
Data
=
{
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
=
create
TeamEdit
View
();
'.u-field-name'
,
'.u-field-description'
,
'.u-field-optional_description'
,
'.u-field-language'
,
'.u-field-country'
],
teamEditView
=
create
EditTeam
View
();
_
.
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
(
th
is
),
teamEditView
=
create
TeamEdit
View
(),
teamName
=
new
Array
(
500
+
1
).
join
(
'$'
),
teamDescription
=
new
Array
(
500
+
1
).
join
(
'$'
);
var
assertValidationMessagesWhenInvalidData
=
function
(
that
)
{
var
requests
=
AjaxHelpers
.
requests
(
th
at
),
teamEditView
=
create
EditTeam
View
(),
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
=
create
TeamEdit
View
(),
requests
=
AjaxHelpers
.
requests
(
th
is
);
var
assertShowMessageOnError
=
function
(
that
,
teamsData
,
teamsUrl
,
errorCode
)
{
var
teamEditView
=
create
EditTeam
View
(),
requests
=
AjaxHelpers
.
requests
(
th
at
);
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
);
var
assertRedirectsToCorrectUrlOnCancel
=
function
(
expectedUrl
)
{
var
teamEditView
=
createEditTeamView
();
teamEditView
.
$
(
'.create-team.form-actions .action-cancel'
).
click
();
expect
(
Backbone
.
history
.
navigate
.
calls
[
0
].
args
).
toContain
(
expectedUrl
);
};
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"
);
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'
);
});
});
it
(
"changes route on cancel click"
,
function
()
{
var
teamEditView
=
createTeamEditView
();
teamEditView
.
$
(
'.create-team.form-actions .action-cancel'
).
click
();
expect
(
Backbone
.
history
.
navigate
.
calls
[
0
].
args
).
toContain
(
'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
);
});
});
});
});
lms/djangoapps/teams/static/teams/js/spec/views/team_
join
_spec.js
→
lms/djangoapps/teams/static/teams/js/spec/views/team_
profile_header_actions
_spec.js
View file @
28fddda4
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
,
Team
Join
View
,
TeamSpecHelpers
)
{
'teams/js/views/team_
profile_header_actions
'
,
'teams/js/spec_helpers/team_spec_helpers'
],
function
(
Backbone
,
_
,
AjaxHelpers
,
TeamModel
,
Team
ProfileHeaderActions
View
,
TeamSpecHelpers
)
{
'use strict'
;
describe
(
'TeamJoinView'
,
function
()
{
describe
(
'TeamProfileHeaderActionsView'
,
function
()
{
var
createTeamsUrl
,
createTeamModelData
,
createMembershipData
,
create
Join
View
,
create
HeaderActions
View
,
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'
;
};
...
...
@@ -38,28 +22,17 @@ define([
return
{
id
:
teamId
,
name
:
teamName
,
membership
:
membership
membership
:
membership
,
url
:
createTeamsUrl
(
teamId
)
};
};
createMembershipData
=
function
(
username
)
{
return
[
{
"user"
:
{
"username"
:
username
,
"url"
:
ACCOUNTS_API_URL
+
username
}
}
];
};
createJoinView
=
function
(
maxTeamSize
,
currentUsername
,
teamModelData
,
teamId
)
{
teamId
=
teamId
||
'teamA'
;
createHeaderActionsView
=
function
(
maxTeamSize
,
currentUsername
,
teamModelData
,
showEditButton
)
{
var
teamId
=
'teamA'
;
var
model
=
new
TeamModel
(
teamModelData
,
{
parse
:
true
});
model
.
url
=
createTeamsUrl
(
teamId
);
var
teamJoinView
=
new
TeamJoin
View
(
return
new
TeamProfileHeaderActions
View
(
{
courseID
:
TeamSpecHelpers
.
testCourseID
,
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
...
...
@@ -67,152 +40,215 @@ define([
teamsUrl
:
createTeamsUrl
(
teamId
),
maxTeamSize
:
maxTeamSize
,
currentUsername
:
currentUsername
,
teamMembershipsUrl
:
TEAMS_MEMBERSHIP_URL
teamMembershipsUrl
:
TEAMS_MEMBERSHIP_URL
,
topicID
:
''
,
showEditButton
:
showEditButton
}
);
return
teamJoinView
.
render
();
).
render
();
};
it
(
'can render itself'
,
function
()
{
var
teamModelData
=
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
createMembershipData
(
'ma'
));
var
view
=
createJoinView
(
1
,
'ma'
,
teamModelData
);
createMembershipData
=
function
(
username
)
{
return
[
{
"user"
:
{
"username"
:
username
,
"url"
:
ACCOUNTS_API_URL
+
username
}
}
];
};
expect
(
view
.
$
(
'.join-team'
).
length
).
toEqual
(
1
);
});
describe
(
'JoinButton'
,
function
()
{
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
);
});
beforeEach
(
function
()
{
setFixtures
(
'<div class="teams-content"><div class="msg-content"><div class="copy"></div></div><div class="header-action-view"></div></div>'
);
});
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
);
});
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
(
'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
(
'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
);
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
);
// 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
);
});
});
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'
);
});
});
});
});
lms/djangoapps/teams/static/teams/js/views/edit_team.js
View file @
28fddda4
...
...
@@ -14,9 +14,9 @@
maxTeamDescriptionLength
:
300
,
events
:
{
'click .action-primary'
:
'createTeam'
,
'submit form'
:
'createTeam'
,
'click .action-cancel'
:
'
goBackToTopic
'
'click .action-primary'
:
'create
OrUpdate
Team'
,
'submit form'
:
'create
OrUpdate
Team'
,
'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'
;
_
.
bindAll
(
this
,
'goBackToTopic'
,
'createTeam'
);
this
.
teamModel
=
new
TeamModel
({});
this
.
teamModel
.
url
=
this
.
teamsUrl
;
this
.
teamsDetailUrl
=
options
.
teamParams
.
teamsDetailUrl
;
this
.
action
=
options
.
action
;
_
.
bindAll
(
this
,
'cancelAndGoBack'
,
'createOrUpdateTeam'
);
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
)
{
create
OrUpdate
Team
:
function
(
event
)
{
event
.
preventDefault
();
var
view
=
this
,
teamLanguage
=
this
.
teamLanguageField
.
fieldValue
(),
teamCountry
=
this
.
teamCountryField
.
fieldValue
();
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
};
teamCountry
=
this
.
teamCountryField
.
fieldValue
(),
data
=
{
name
:
this
.
teamNameField
.
fieldValue
(),
description
:
this
.
teamDescriptionField
.
fieldValue
(),
language
:
_
.
isNull
(
teamLanguage
)
?
''
:
teamLanguage
,
country
:
_
.
isNull
(
teamCountry
)
?
''
:
teamCountry
},
saveOptions
=
{
wait
:
true
};
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
});
}
});
});
...
...
lms/djangoapps/teams/static/teams/js/views/team_
join
.js
→
lms/djangoapps/teams/static/teams/js/views/team_
profile_header_actions
.js
View file @
28fddda4
...
...
@@ -5,8 +5,8 @@
'underscore'
,
'gettext'
,
'teams/js/views/team_utils'
,
'text!teams/templates/team-
join
.underscore'
],
function
(
Backbone
,
_
,
gettext
,
TeamUtils
,
team
Join
Template
)
{
'text!teams/templates/team-
profile-header-actions
.underscore'
],
function
(
Backbone
,
_
,
gettext
,
TeamUtils
,
team
ProfileHeaderActions
Template
)
{
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
(
team
Join
Template
);
this
.
template
=
_
.
template
(
team
ProfileHeaderActions
Template
);
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
,
show
Join
Button
,
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
;
show
Join
Button
=
!
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
});
}
});
});
...
...
lms/djangoapps/teams/static/teams/js/views/teams_tab.js
View file @
28fddda4
...
...
@@ -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
,
Team
Join
View
,
teamsTemplate
)
{
Team
ProfileHeaderActions
View
,
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,10 +210,9 @@
})
}),
main
:
new
TeamEditView
({
action
:
'create'
,
teamEvents
:
self
.
teamEvents
,
tagName
:
'create-new-team'
,
teamParams
:
teamsView
.
main
.
teamParams
,
primaryButtonTitle
:
'Create'
teamParams
:
teamsView
.
main
.
teamParams
})
});
self
.
render
();
...
...
@@ -219,6 +220,44 @@
},
/**
* 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.
*/
getTeamsView
:
function
(
topicID
)
{
...
...
@@ -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
:
teamJoin
View
headerActionsView
:
TeamProfileActions
View
}
)
);
...
...
@@ -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
,
...
...
lms/djangoapps/teams/static/teams/templates/edit-team.underscore
View file @
28fddda4
<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'
}
)
%>
...
...
lms/djangoapps/teams/static/teams/templates/team-
join
.underscore
→
lms/djangoapps/teams/static/teams/templates/team-
profile-header-actions
.underscore
View file @
28fddda4
<div class="join-team form-actions">
<% if (showButton) {%>
<% if (show
Join
Button) {%>
<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>
lms/djangoapps/teams/static/teams/templates/team-profile.underscore
View file @
28fddda4
...
...
@@ -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>
...
...
lms/djangoapps/teams/templates/teams/teams.html
View file @
28fddda4
...
...
@@ -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 },
...
...
lms/djangoapps/teams/views.py
View file @
28fddda4
...
...
@@ -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
,
...
...
lms/static/js/spec/main.js
View file @
28fddda4
...
...
@@ -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
);
lms/static/sass/elements/_controls.scss
View file @
28fddda4
...
...
@@ -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
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment