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
f788caa6
Commit
f788caa6
authored
Aug 19, 2015
by
muzaffaryousaf
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Edit team page for Instructor only.
TNL-1914
parent
406c9bc5
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 @
f788caa6
...
@@ -205,7 +205,7 @@ class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
...
@@ -205,7 +205,7 @@ class BrowseTeamsPage(CoursePage, PaginatedUIMixin):
self
.
wait_for_ajax
()
self
.
wait_for_ajax
()
class
CreateTeamPage
(
CoursePage
,
FieldsMixin
):
class
Create
OrEdit
TeamPage
(
CoursePage
,
FieldsMixin
):
"""
"""
Create team page.
Create team page.
"""
"""
...
@@ -216,7 +216,7 @@ class CreateTeamPage(CoursePage, FieldsMixin):
...
@@ -216,7 +216,7 @@ class CreateTeamPage(CoursePage, FieldsMixin):
representation of a topic following the same convention as a
representation of a topic following the same convention as a
course module's topic.
course module's topic.
"""
"""
super
(
CreateTeamPage
,
self
)
.
__init__
(
browser
,
course_id
)
super
(
Create
OrEdit
TeamPage
,
self
)
.
__init__
(
browser
,
course_id
)
self
.
topic
=
topic
self
.
topic
=
topic
self
.
url_path
=
"teams/#topics/{topic_id}/create-team"
.
format
(
topic_id
=
self
.
topic
[
'id'
])
self
.
url_path
=
"teams/#topics/{topic_id}/create-team"
.
format
(
topic_id
=
self
.
topic
[
'id'
])
...
@@ -410,3 +410,12 @@ class TeamPage(CoursePage, PaginatedUIMixin):
...
@@ -410,3 +410,12 @@ class TeamPage(CoursePage, PaginatedUIMixin):
"""Navigate to the 'All Topics' page."""
"""Navigate to the 'All Topics' page."""
self
.
q
(
css
=
'.breadcrumbs a'
)
.
results
[
0
]
.
click
()
self
.
q
(
css
=
'.breadcrumbs a'
)
.
results
[
0
]
.
click
()
self
.
wait_for_ajax
()
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 @
f788caa6
...
@@ -20,7 +20,7 @@ from ...pages.lms.auto_auth import AutoAuthPage
...
@@ -20,7 +20,7 @@ from ...pages.lms.auto_auth import AutoAuthPage
from
...pages.lms.course_info
import
CourseInfoPage
from
...pages.lms.course_info
import
CourseInfoPage
from
...pages.lms.learner_profile
import
LearnerProfilePage
from
...pages.lms.learner_profile
import
LearnerProfilePage
from
...pages.lms.tab_nav
import
TabNavPage
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
TOPICS_PER_PAGE
=
12
...
@@ -335,7 +335,7 @@ class BrowseTopicsTest(TeamsTabBase):
...
@@ -335,7 +335,7 @@ class BrowseTopicsTest(TeamsTabBase):
browse_teams_page
=
BrowseTeamsPage
(
self
.
browser
,
self
.
course_id
,
topic
)
browse_teams_page
=
BrowseTeamsPage
(
self
.
browser
,
self
.
course_id
,
topic
)
self
.
assertTrue
(
browse_teams_page
.
is_browser_on_page
())
self
.
assertTrue
(
browse_teams_page
.
is_browser_on_page
())
browse_teams_page
.
click_create_team_link
()
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_text_field
(
field_id
=
'name'
,
value
=
'Team Name'
,
press_enter
=
False
)
create_team_page
.
value_for_textarea_field
(
create_team_page
.
value_for_textarea_field
(
field_id
=
'description'
,
field_id
=
'description'
,
...
@@ -629,78 +629,124 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
...
@@ -629,78 +629,124 @@ class BrowseTeamsWithinTopicTest(TeamsTabBase):
@attr
(
'shard_5'
)
@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
):
topic
=
{
'name'
:
'Example Topic'
,
'id'
:
'example_topic'
,
'description'
:
'Description'
}
super
(
CreateTeamTest
,
self
)
.
setUp
()
TEAMS_NAME
=
'Avengers'
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'
def
verify_page_header
(
self
):
def
verify_page_header
(
self
,
title
,
description
,
breadcrumbs
):
"""
"""
Verify that the page header correctly reflects the
Verify that the page header correctly reflects the
create team header, description and breadcrumb.
create team header, description and breadcrumb.
"""
"""
self
.
assertEqual
(
self
.
create_team_page
.
header_page_name
,
'Create a New Team'
)
self
.
assertEqual
(
self
.
create_or_edit_team_page
.
header_page_name
,
title
)
self
.
assertEqual
(
self
.
assertEqual
(
self
.
create_or_edit_team_page
.
header_page_description
,
description
)
self
.
create_team_page
.
header_page_description
,
self
.
assertEqual
(
self
.
create_or_edit_team_page
.
header_page_breadcrumbs
,
breadcrumbs
)
'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
):
def
verify_and_navigate_to_create_team_page
(
self
):
"""Navigates to the create team page and verifies."""
"""Navigates to the create team page and verifies."""
self
.
browse_teams_page
.
click_create_team_link
()
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
):
# Edit page header.
"""Fill the create team form fields with appropriate values."""
self
.
verify_page_header
(
self
.
create_team_page
.
value_for_text_field
(
field_id
=
'name'
,
value
=
self
.
team_name
,
press_enter
=
False
)
title
=
'Edit Team'
,
self
.
create_team_page
.
value_for_textarea_field
(
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'
,
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_
or_edit_
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
=
'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.
Verify the fields for create/edit 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
.
assertEqual
(
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).'
'A name that identifies your team (maximum 255 characters).'
)
)
self
.
assertEqual
(
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 '
'A short description of the team to help other learners understand '
'the goals or direction of the team (maximum 300 characters).'
'the goals or direction of the team (maximum 300 characters).'
)
)
self
.
assertEqual
(
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.'
'The country that team members primarily identify with.'
)
)
self
.
assertEqual
(
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.'
'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
):
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.
Scenario: The user should be able to see error message in case of missing required field.
...
@@ -711,14 +757,14 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -711,14 +757,14 @@ class CreateTeamTest(TeamsTabBase):
Then I should see the error message and highlighted fields.
Then I should see the error message and highlighted fields.
"""
"""
self
.
verify_and_navigate_to_create_team_page
()
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
.
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.'
'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'
))
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
=
'description'
))
def
test_user_can_see_error_message_for_incorrect_data
(
self
):
def
test_user_can_see_error_message_for_incorrect_data
(
self
):
"""
"""
...
@@ -733,7 +779,7 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -733,7 +779,7 @@ class CreateTeamTest(TeamsTabBase):
self
.
verify_and_navigate_to_create_team_page
()
self
.
verify_and_navigate_to_create_team_page
()
# Fill the name field with >255 characters to see validation message.
# 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'
,
field_id
=
'name'
,
value
=
'EdX is a massive open online course (MOOC) provider and online learning platform. '
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 '
'It hosts online university-level courses in a wide range of disciplines to a worldwide '
...
@@ -745,13 +791,13 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -745,13 +791,13 @@ class CreateTeamTest(TeamsTabBase):
'edX has more than 4 million users taking more than 500 courses online.'
,
'edX has more than 4 million users taking more than 500 courses online.'
,
press_enter
=
False
press_enter
=
False
)
)
self
.
create_team_page
.
submit_form
()
self
.
create_
or_edit_
team_page
.
submit_form
()
self
.
assertEqual
(
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.'
'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
):
def
test_user_can_create_new_team_successfully
(
self
):
"""
"""
...
@@ -767,16 +813,19 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -767,16 +813,19 @@ class CreateTeamTest(TeamsTabBase):
And the number of teams should be updated on the topic card
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
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
.
verify_and_navigate_to_create_team_page
()
self
.
fill_create_form
()
self
.
fill_create_
or_edit_
form
()
self
.
create_team_page
.
submit_form
()
self
.
create_
or_edit_
team_page
.
submit_form
()
# Verify that the page is shown for the new team
# Verify that the page is shown for the new team
team_page
=
TeamPage
(
self
.
browser
,
self
.
course_id
)
team_page
=
TeamPage
(
self
.
browser
,
self
.
course_id
)
team_page
.
wait_for_page
()
team_page
.
wait_for_page
()
self
.
assertEqual
(
team_page
.
team_name
,
self
.
team_name
)
self
.
assertEqual
(
team_page
.
team_name
,
self
.
TEAMS_NAME
)
self
.
assertEqual
(
team_page
.
team_description
,
'The Avengers are a fictional team of superheroes.'
)
self
.
assertEqual
(
team_page
.
team_description
,
self
.
TEAM_DESCRIPTION
)
self
.
assertEqual
(
team_page
.
team_user_membership_text
,
'You are a member of this team.'
)
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
# Verify the new team was added to the topic list
...
@@ -802,7 +851,7 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -802,7 +851,7 @@ class CreateTeamTest(TeamsTabBase):
self
.
assertEqual
(
self
.
browse_teams_page
.
get_pagination_header_text
(),
'Showing 0 out of 0 total'
)
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
.
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
.
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'
)
self
.
assertEqual
(
self
.
browse_teams_page
.
get_pagination_header_text
(),
'Showing 0 out of 0 total'
)
...
@@ -813,6 +862,157 @@ class CreateTeamTest(TeamsTabBase):
...
@@ -813,6 +862,157 @@ class CreateTeamTest(TeamsTabBase):
self
.
verify_my_team_count
(
0
)
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'
)
@attr
(
'shard_5'
)
@ddt.ddt
@ddt.ddt
class
TeamPageTest
(
TeamsTabBase
):
class
TeamPageTest
(
TeamsTabBase
):
...
...
lms/djangoapps/teams/static/teams/js/spec/views/edit_team_spec.js
View file @
f788caa6
...
@@ -4,13 +4,14 @@ define([
...
@@ -4,13 +4,14 @@ define([
'backbone'
,
'backbone'
,
'common/js/spec_helpers/ajax_helpers'
,
'common/js/spec_helpers/ajax_helpers'
,
'teams/js/views/edit_team'
,
'teams/js/views/edit_team'
,
'teams/js/models/team'
,
'teams/js/spec_helpers/team_spec_helpers'
'teams/js/spec_helpers/team_spec_helpers'
],
function
(
$
,
_
,
Backbone
,
AjaxHelpers
,
TeamEditView
,
TeamSpecHelpers
)
{
],
function
(
$
,
_
,
Backbone
,
AjaxHelpers
,
TeamEditView
,
Team
Model
,
Team
SpecHelpers
)
{
'use strict'
;
'use strict'
;
describe
(
'
EditTeam'
,
function
()
{
describe
(
'
CreateEditTeam'
,
function
()
{
var
teamsUrl
=
'/api/team/v0/teams/'
,
var
teamsUrl
=
'/api/team/v0/teams/'
,
teams
Data
=
{
createTeam
Data
=
{
id
:
null
,
id
:
null
,
name
:
"TeamName"
,
name
:
"TeamName"
,
is_active
:
null
,
is_active
:
null
,
...
@@ -18,11 +19,17 @@ define([
...
@@ -18,11 +19,17 @@ define([
topic_id
:
"awesomeness"
,
topic_id
:
"awesomeness"
,
date_created
:
""
,
date_created
:
""
,
description
:
"TeamDescription"
,
description
:
"TeamDescription"
,
country
:
"
c
"
,
country
:
"
US
"
,
language
:
"
a
"
,
language
:
"
en
"
,
membership
:
[],
membership
:
[],
last_activity_at
:
''
last_activity_at
:
''
},
},
editTeamData
=
{
name
:
"UpdatedAvengers"
,
description
:
"We do not discuss about avengers."
,
country
:
"US"
,
language
:
"en"
},
verifyValidation
=
function
(
requests
,
teamEditView
,
fieldsData
)
{
verifyValidation
=
function
(
requests
,
teamEditView
,
fieldsData
)
{
_
.
each
(
fieldsData
,
function
(
fieldData
)
{
_
.
each
(
fieldsData
,
function
(
fieldData
)
{
teamEditView
.
$
(
fieldData
[
0
]).
val
(
fieldData
[
1
]);
teamEditView
.
$
(
fieldData
[
0
]).
val
(
fieldData
[
1
]);
...
@@ -32,33 +39,57 @@ define([
...
@@ -32,33 +39,57 @@ define([
var
message
=
teamEditView
.
$
(
'.wrapper-msg'
);
var
message
=
teamEditView
.
$
(
'.wrapper-msg'
);
expect
(
message
.
hasClass
(
'is-hidden'
)).
toBeFalsy
();
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
(
expect
(
message
.
find
(
'.copy'
).
text
().
trim
()).
toBe
(
"Check the highlighted fields below and try again."
"Check the highlighted fields below and try again."
);
);
_
.
each
(
fieldsData
,
function
(
fieldData
)
{
_
.
each
(
fieldsData
,
function
(
fieldData
)
{
if
(
fieldData
[
2
]
===
'error'
)
{
if
(
fieldData
[
2
]
===
'error'
)
{
expect
(
teamEditView
.
$
(
fieldData
[
0
].
split
(
" "
)[
0
]
+
'.error'
).
length
).
toBe
(
1
);
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
(
teamEditView
.
$
(
fieldData
[
0
].
split
(
" "
)[
0
]
+
'.error'
).
length
).
toBe
(
0
);
}
}
});
});
expect
(
requests
.
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
({
return
new
TeamEditView
({
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
el
:
$
(
'.teams-content'
),
el
:
$
(
'.teams-content'
),
action
:
teamAction
,
model
:
teamModel
,
teamParams
:
{
teamParams
:
{
teamsUrl
:
teamsUrl
,
teamsUrl
:
teamsUrl
,
courseID
:
"a/b/c"
,
courseID
:
"a/b/c"
,
topicID
:
'awesomeness'
,
topicID
:
'awesomeness'
,
topicName
:
'Awesomeness'
,
topicName
:
'Awesomeness'
,
languages
:
[[
'a'
,
'aaa'
],
[
'b'
,
'bbb'
]],
languages
:
[[
'aa'
,
'Afar'
],
[
'fr'
,
'French'
],
[
'en'
,
'English'
]],
countries
:
[[
'c'
,
'ccc'
],
[
'd'
,
'ddd'
]]
countries
:
[[
'af'
,
'Afghanistan'
],
[
'CA'
,
'Canada'
],
[
'US'
,
'United States'
]],
teamsDetailUrl
:
teamModel
.
url
}
}
}).
render
();
}).
render
();
};
};
...
@@ -68,15 +99,15 @@ define([
...
@@ -68,15 +99,15 @@ define([
spyOn
(
Backbone
.
history
,
'navigate'
);
spyOn
(
Backbone
.
history
,
'navigate'
);
});
});
it
(
'can render itself correctly'
,
function
()
{
var
assertFormRendersCorrectly
=
function
()
{
var
fieldClasses
=
[
var
fieldClasses
=
[
'.u-field-name'
,
'.u-field-name'
,
'.u-field-description'
,
'.u-field-description'
,
'.u-field-optional_description'
,
'.u-field-optional_description'
,
'.u-field-language'
,
'.u-field-language'
,
'.u-field-country'
'.u-field-country'
],
],
teamEditView
=
create
TeamEdit
View
();
teamEditView
=
create
EditTeam
View
();
_
.
each
(
fieldClasses
,
function
(
fieldClass
)
{
_
.
each
(
fieldClasses
,
function
(
fieldClass
)
{
expect
(
teamEditView
.
$el
.
find
(
fieldClass
).
length
).
toBe
(
1
);
expect
(
teamEditView
.
$el
.
find
(
fieldClass
).
length
).
toBe
(
1
);
...
@@ -84,32 +115,46 @@ define([
...
@@ -84,32 +115,46 @@ define([
expect
(
teamEditView
.
$
(
'.create-team.form-actions .action-primary'
).
length
).
toBe
(
1
);
expect
(
teamEditView
.
$
(
'.create-team.form-actions .action-primary'
).
length
).
toBe
(
1
);
expect
(
teamEditView
.
$
(
'.create-team.form-actions .action-cancel'
).
length
).
toBe
(
1
);
expect
(
teamEditView
.
$
(
'.create-team.form-actions .action-cancel'
).
length
).
toBe
(
1
);
});
it
(
'can create a team'
,
function
()
{
if
(
teamAction
===
'edit'
)
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
expect
(
teamEditView
.
$el
.
find
(
'.u-field-name input'
).
val
()).
toBe
(
'Avengers'
);
teamEditView
=
createTeamEditView
();
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-name input'
).
val
(
teamsData
.
name
);
teamEditView
.
$
(
'.u-field-textarea textarea'
).
val
(
teamsData
.
description
);
teamEditView
.
$
(
'.u-field-textarea textarea'
).
val
(
teamsData
.
description
);
teamEditView
.
$
(
'.u-field-language select'
).
val
(
'a'
).
attr
(
"selected"
,
"selected"
);
teamEditView
.
$
(
'.u-field-language select'
).
val
(
teamsData
.
language
).
attr
(
"selected"
,
"selected"
);
teamEditView
.
$
(
'.u-field-country select'
).
val
(
'c'
).
attr
(
"selected"
,
"selected"
);
teamEditView
.
$
(
'.u-field-country select'
).
val
(
teamsData
.
country
).
attr
(
"selected"
,
"selected"
);
teamEditView
.
$
(
'.create-team.form-actions .action-primary'
).
click
();
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
(
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
,
[
verifyValidation
(
requests
,
teamEditView
,
[
[
'.u-field-name input'
,
'Name'
,
'success'
],
[
'.u-field-name input'
,
'Name'
,
'success'
],
[
'.u-field-textarea textarea'
,
''
,
'error'
]
[
'.u-field-textarea textarea'
,
''
,
'error'
]
]);
]);
teamEditView
.
render
();
teamEditView
.
render
();
verifyValidation
(
requests
,
teamEditView
,
[
verifyValidation
(
requests
,
teamEditView
,
[
[
'.u-field-name input'
,
''
,
'error'
],
[
'.u-field-name input'
,
''
,
'error'
],
...
@@ -120,13 +165,13 @@ define([
...
@@ -120,13 +165,13 @@ define([
[
'.u-field-name input'
,
''
,
'error'
],
[
'.u-field-name input'
,
''
,
'error'
],
[
'.u-field-textarea textarea'
,
''
,
'error'
]
[
'.u-field-textarea textarea'
,
''
,
'error'
]
]);
]);
}
)
;
};
it
(
'shows validation error message when field value length exceeded the limit'
,
function
(
)
{
var
assertValidationMessagesWhenInvalidData
=
function
(
that
)
{
var
requests
=
AjaxHelpers
.
requests
(
th
is
),
var
requests
=
AjaxHelpers
.
requests
(
th
at
),
teamEditView
=
create
TeamEdit
View
(),
teamEditView
=
create
EditTeam
View
(),
teamName
=
new
Array
(
500
+
1
).
join
(
'$'
),
teamName
=
new
Array
(
500
+
1
).
join
(
'$'
),
teamDescription
=
new
Array
(
500
+
1
).
join
(
'$'
);
teamDescription
=
new
Array
(
500
+
1
).
join
(
'$'
);
verifyValidation
(
requests
,
teamEditView
,
[
verifyValidation
(
requests
,
teamEditView
,
[
[
'.u-field-name input'
,
teamName
,
'error'
],
[
'.u-field-name input'
,
teamName
,
'error'
],
...
@@ -142,48 +187,114 @@ define([
...
@@ -142,48 +187,114 @@ define([
[
'.u-field-name input'
,
teamName
,
'error'
],
[
'.u-field-name input'
,
teamName
,
'error'
],
[
'.u-field-textarea textarea'
,
teamDescription
,
'error'
]
[
'.u-field-textarea textarea'
,
teamDescription
,
'error'
]
]);
]);
}
)
;
};
it
(
"shows an error message for HTTP 500"
,
function
(
)
{
var
assertShowMessageOnError
=
function
(
that
,
teamsData
,
teamsUrl
,
errorCode
)
{
var
teamEditView
=
create
TeamEdit
View
(),
var
teamEditView
=
create
EditTeam
View
(),
requests
=
AjaxHelpers
.
requests
(
th
is
);
requests
=
AjaxHelpers
.
requests
(
th
at
);
teamEditView
.
$
(
'.u-field-name input'
).
val
(
teamsData
.
name
);
teamEditView
.
$
(
'.u-field-name input'
).
val
(
teamsData
.
name
);
teamEditView
.
$
(
'.u-field-textarea textarea'
).
val
(
teamsData
.
description
);
teamEditView
.
$
(
'.u-field-textarea textarea'
).
val
(
teamsData
.
description
);
teamEditView
.
$
(
'.create-team.form-actions .action-primary'
).
click
();
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
()
{
if
(
errorCode
<
500
)
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
AjaxHelpers
.
respondWithError
(
teamEditView
=
createTeamEditView
();
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
);
var
assertRedirectsToCorrectUrlOnCancel
=
function
(
expectedUrl
)
{
teamEditView
.
$
(
'.u-field-textarea textarea'
).
val
(
teamsData
.
description
);
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
();
describe
(
'NewTeam'
,
function
()
{
teamsData
.
country
=
''
;
teamsData
.
language
=
''
;
beforeEach
(
function
()
{
AjaxHelpers
.
expectJsonRequest
(
requests
,
'POST'
,
teamsUrl
,
teamsData
);
teamAction
=
'create'
;
AjaxHelpers
.
respondWithError
(
});
requests
,
400
,
it
(
'can render itself correctly'
,
function
()
{
{
'user_message'
:
'User message'
,
'developer_message'
:
'Developer message'
}
assertFormRendersCorrectly
();
);
});
expect
(
teamEditView
.
$
(
'.wrapper-msg .copy'
).
text
().
trim
()).
toBe
(
"User message"
);
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
()
{
describe
(
'EditTeam'
,
function
()
{
var
teamEditView
=
createTeamEditView
();
teamEditView
.
$
(
'.create-team.form-actions .action-cancel'
).
click
();
beforeEach
(
function
()
{
expect
(
Backbone
.
history
.
navigate
.
calls
[
0
].
args
).
toContain
(
'topics/awesomeness'
);
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 @
f788caa6
define
([
define
([
'backbone'
,
'underscore'
,
'common/js/spec_helpers/ajax_helpers'
,
'teams/js/models/team'
,
'backbone'
,
'underscore'
,
'common/js/spec_helpers/ajax_helpers'
,
'teams/js/models/team'
,
'teams/js/views/team_
join
'
,
'teams/js/spec_helpers/team_spec_helpers'
'teams/js/views/team_
profile_header_actions
'
,
'teams/js/spec_helpers/team_spec_helpers'
],
function
(
Backbone
,
_
,
AjaxHelpers
,
TeamModel
,
Team
Join
View
,
TeamSpecHelpers
)
{
],
function
(
Backbone
,
_
,
AjaxHelpers
,
TeamModel
,
Team
ProfileHeaderActions
View
,
TeamSpecHelpers
)
{
'use strict'
;
'use strict'
;
describe
(
'TeamJoinView'
,
function
()
{
describe
(
'TeamProfileHeaderActionsView'
,
function
()
{
var
createTeamsUrl
,
var
createTeamsUrl
,
createTeamModelData
,
createTeamModelData
,
createMembershipData
,
createMembershipData
,
create
Join
View
,
create
HeaderActions
View
,
verifyErrorMessage
,
verifyErrorMessage
,
ACCOUNTS_API_URL
=
'/api/user/v1/accounts/'
,
ACCOUNTS_API_URL
=
'/api/user/v1/accounts/'
,
TEAMS_URL
=
'/api/team/v0/teams/'
,
TEAMS_URL
=
'/api/team/v0/teams/'
,
TEAMS_MEMBERSHIP_URL
=
'/api/team/v0/team_membership/'
;
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
)
{
createTeamsUrl
=
function
(
teamId
)
{
return
TEAMS_URL
+
teamId
+
'?expand=user'
;
return
TEAMS_URL
+
teamId
+
'?expand=user'
;
};
};
...
@@ -38,28 +22,17 @@ define([
...
@@ -38,28 +22,17 @@ define([
return
{
return
{
id
:
teamId
,
id
:
teamId
,
name
:
teamName
,
name
:
teamName
,
membership
:
membership
membership
:
membership
,
url
:
createTeamsUrl
(
teamId
)
};
};
};
};
createMembershipData
=
function
(
username
)
{
createHeaderActionsView
=
function
(
maxTeamSize
,
currentUsername
,
teamModelData
,
showEditButton
)
{
return
[
var
teamId
=
'teamA'
;
{
"user"
:
{
"username"
:
username
,
"url"
:
ACCOUNTS_API_URL
+
username
}
}
];
};
createJoinView
=
function
(
maxTeamSize
,
currentUsername
,
teamModelData
,
teamId
)
{
teamId
=
teamId
||
'teamA'
;
var
model
=
new
TeamModel
(
teamModelData
,
{
parse
:
true
});
var
model
=
new
TeamModel
(
teamModelData
,
{
parse
:
true
});
model
.
url
=
createTeamsUrl
(
teamId
);
var
teamJoinView
=
new
TeamJoin
View
(
return
new
TeamProfileHeaderActions
View
(
{
{
courseID
:
TeamSpecHelpers
.
testCourseID
,
courseID
:
TeamSpecHelpers
.
testCourseID
,
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
...
@@ -67,152 +40,215 @@ define([
...
@@ -67,152 +40,215 @@ define([
teamsUrl
:
createTeamsUrl
(
teamId
),
teamsUrl
:
createTeamsUrl
(
teamId
),
maxTeamSize
:
maxTeamSize
,
maxTeamSize
:
maxTeamSize
,
currentUsername
:
currentUsername
,
currentUsername
:
currentUsername
,
teamMembershipsUrl
:
TEAMS_MEMBERSHIP_URL
teamMembershipsUrl
:
TEAMS_MEMBERSHIP_URL
,
topicID
:
''
,
showEditButton
:
showEditButton
}
}
);
).
render
();
return
teamJoinView
.
render
();
};
};
it
(
'can render itself'
,
function
()
{
createMembershipData
=
function
(
username
)
{
var
teamModelData
=
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
createMembershipData
(
'ma'
));
return
[
var
view
=
createJoinView
(
1
,
'ma'
,
teamModelData
);
{
"user"
:
{
"username"
:
username
,
"url"
:
ACCOUNTS_API_URL
+
username
}
}
];
};
expect
(
view
.
$
(
'.join-team'
).
length
).
toEqual
(
1
);
describe
(
'JoinButton'
,
function
()
{
});
it
(
'can join team successfully'
,
function
()
{
beforeEach
(
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
setFixtures
(
var
currentUsername
=
'ma1'
;
'<div class="teams-content"><div class="msg-content"><div class="copy"></div></div><div class="header-action-view"></div></div>'
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
()
{
verifyErrorMessage
=
function
(
requests
,
errorMessage
,
expectedMessage
,
joinTeam
)
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
view
=
createHeaderActionsView
(
1
,
'ma'
,
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
[]));
var
currentUsername
=
'ma1'
;
if
(
joinTeam
)
{
var
view
=
createJoinView
(
1
,
currentUsername
,
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
[]));
// if we want the error to return when user try to join team, respond with no membership
AjaxHelpers
.
respondWithJson
(
requests
,
{
"count"
:
0
});
// a get request will be sent to get user membership info
view
.
$
(
'.action.action-primary'
).
click
();
// because current user is not member of current team
}
AjaxHelpers
.
expectRequest
(
AjaxHelpers
.
respondWithTextError
(
requests
,
400
,
errorMessage
);
requests
,
expect
(
$
(
'.msg-content .copy'
).
text
().
trim
()).
toBe
(
expectedMessage
);
'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
()
{
it
(
'can render itself'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
teamModelData
=
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
createMembershipData
(
'ma'
));
var
view
=
createJoinView
(
var
view
=
createHeaderActionsView
(
1
,
'ma'
,
teamModelData
);
1
,
'ma1'
,
expect
(
view
.
$
(
'.join-team'
).
length
).
toEqual
(
1
);
createTeamModelData
(
'teamA'
,
'teamAlpha'
,
createMembershipData
(
'ma'
))
});
);
it
(
'can join team successfully'
,
function
()
{
// team has no space and current user is a not member of
var
requests
=
AjaxHelpers
.
requests
(
this
);
// current team so we should see the correct message
var
currentUsername
=
'ma1'
;
expect
(
view
.
$
(
'.action.action-primary'
).
length
).
toEqual
(
0
);
var
teamId
=
'teamA'
;
expect
(
view
.
$
(
'.join-team-message'
).
text
().
trim
()).
toBe
(
view
.
teamFullMessage
);
var
teamName
=
'teamAlpha'
;
var
teamModelData
=
createTeamModelData
(
teamId
,
teamName
,
[]);
// there should be no request made
var
view
=
createHeaderActionsView
(
1
,
currentUsername
,
teamModelData
);
expect
(
requests
.
length
).
toBe
(
0
);
});
// 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
()
{
// a post request will be sent to add current user to current team
var
requests
=
AjaxHelpers
.
requests
(
this
);
view
.
$
(
'.action.action-primary'
).
click
();
AjaxHelpers
.
expectRequest
(
// verify user_message
requests
,
verifyErrorMessage
(
'POST'
,
requests
,
TEAMS_MEMBERSHIP_URL
,
JSON
.
stringify
({
'user_message'
:
"Can't be made member"
}),
$
.
param
({
'username'
:
currentUsername
,
'team_id'
:
teamId
})
"Can't be made member"
,
);
true
AjaxHelpers
.
respondWithJson
(
requests
,
{});
);
// on success, team model will be fetched and
// verify generic error message
// join team view and team profile will be re-rendered
verifyErrorMessage
(
AjaxHelpers
.
expectRequest
(
requests
,
requests
,
''
,
'GET'
,
'An error occurred. Try again.'
,
createTeamsUrl
(
teamId
)
true
);
);
AjaxHelpers
.
respondWithJson
(
requests
,
createTeamModelData
(
teamId
,
teamName
,
createMembershipData
(
currentUsername
))
// verify error message when json parsing succeeded but error message format is incorrect
);
verifyErrorMessage
(
requests
,
// current user is now member of the current team then there should be no button and no message
JSON
.
stringify
({
'blah'
:
"Can't be made member"
}),
expect
(
view
.
$
(
'.action.action-primary'
).
length
).
toEqual
(
0
);
'An error occurred. Try again.'
,
expect
(
view
.
$
(
'.join-team-message'
).
length
).
toEqual
(
0
);
true
});
);
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
()
{
describe
(
'EditButton'
,
function
()
{
// Rendering the view sometimes require fetching user's memberships. This may fail.
var
teamModelData
,
var
requests
=
AjaxHelpers
.
requests
(
this
);
view
,
createAndAssertView
;
// verify user_message
verifyErrorMessage
(
createAndAssertView
=
function
(
showEditButton
)
{
requests
,
teamModelData
=
createTeamModelData
(
'aveA'
,
'avengers'
,
createMembershipData
(
'ma'
));
JSON
.
stringify
({
'user_message'
:
"Can't return user memberships"
}),
view
=
createHeaderActionsView
(
1
,
'ma'
,
teamModelData
,
showEditButton
);
"Can't return user memberships"
,
expect
(
view
.
$
(
'.action-edit-team'
).
length
).
toEqual
(
showEditButton
?
1
:
0
);
false
};
);
it
(
'renders when option showEditButton is true'
,
function
()
{
// verify generic error message
createAndAssertView
(
true
);
verifyErrorMessage
(
});
requests
,
''
,
it
(
'does not render when option showEditButton is false'
,
function
()
{
'An error occurred. Try again.'
,
createAndAssertView
(
false
);
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 @
f788caa6
...
@@ -14,9 +14,9 @@
...
@@ -14,9 +14,9 @@
maxTeamDescriptionLength
:
300
,
maxTeamDescriptionLength
:
300
,
events
:
{
events
:
{
'click .action-primary'
:
'createTeam'
,
'click .action-primary'
:
'create
OrUpdate
Team'
,
'submit form'
:
'createTeam'
,
'submit form'
:
'create
OrUpdate
Team'
,
'click .action-cancel'
:
'
goBackToTopic
'
'click .action-cancel'
:
'
cancelAndGoBack
'
},
},
initialize
:
function
(
options
)
{
initialize
:
function
(
options
)
{
...
@@ -27,12 +27,20 @@
...
@@ -27,12 +27,20 @@
this
.
teamsUrl
=
options
.
teamParams
.
teamsUrl
;
this
.
teamsUrl
=
options
.
teamParams
.
teamsUrl
;
this
.
languages
=
options
.
teamParams
.
languages
;
this
.
languages
=
options
.
teamParams
.
languages
;
this
.
countries
=
options
.
teamParams
.
countries
;
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
({
this
.
teamNameField
=
new
FieldViews
.
TextFieldView
({
model
:
this
.
teamModel
,
model
:
this
.
teamModel
,
...
@@ -74,7 +82,11 @@
...
@@ -74,7 +82,11 @@
},
},
render
:
function
()
{
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
.
teamNameField
,
'.team-required-fields'
);
this
.
set
(
this
.
teamDescriptionField
,
'.team-required-fields'
);
this
.
set
(
this
.
teamDescriptionField
,
'.team-required-fields'
);
this
.
set
(
this
.
teamLanguageField
,
'.team-optional-fields'
);
this
.
set
(
this
.
teamLanguageField
,
'.team-optional-fields'
);
...
@@ -91,20 +103,28 @@
...
@@ -91,20 +103,28 @@
}
}
},
},
createTeam
:
function
(
event
)
{
create
OrUpdate
Team
:
function
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
var
view
=
this
,
var
view
=
this
,
teamLanguage
=
this
.
teamLanguageField
.
fieldValue
(),
teamLanguage
=
this
.
teamLanguageField
.
fieldValue
(),
teamCountry
=
this
.
teamCountryField
.
fieldValue
();
teamCountry
=
this
.
teamCountryField
.
fieldValue
(),
data
=
{
var
data
=
{
name
:
this
.
teamNameField
.
fieldValue
(),
course_id
:
this
.
courseID
,
description
:
this
.
teamDescriptionField
.
fieldValue
(),
topic_id
:
this
.
topicID
,
language
:
_
.
isNull
(
teamLanguage
)
?
''
:
teamLanguage
,
name
:
this
.
teamNameField
.
fieldValue
(),
country
:
_
.
isNull
(
teamCountry
)
?
''
:
teamCountry
description
:
this
.
teamDescriptionField
.
fieldValue
(),
},
language
:
_
.
isNull
(
teamLanguage
)
?
''
:
teamLanguage
,
saveOptions
=
{
country
:
_
.
isNull
(
teamCountry
)
?
''
:
teamCountry
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
);
var
validationResult
=
this
.
validateTeamData
(
data
);
if
(
validationResult
.
status
===
false
)
{
if
(
validationResult
.
status
===
false
)
{
...
@@ -112,10 +132,10 @@
...
@@ -112,10 +132,10 @@
return
;
return
;
}
}
this
.
teamModel
.
save
(
data
,
{
wait
:
true
}
)
this
.
teamModel
.
save
(
data
,
saveOptions
)
.
done
(
function
(
result
)
{
.
done
(
function
(
result
)
{
view
.
teamEvents
.
trigger
(
'teams:update'
,
{
view
.
teamEvents
.
trigger
(
'teams:update'
,
{
action
:
'create'
,
action
:
view
.
action
,
team
:
result
team
:
result
});
});
Backbone
.
history
.
navigate
(
Backbone
.
history
.
navigate
(
...
@@ -186,8 +206,15 @@
...
@@ -186,8 +206,15 @@
}
}
},
},
goBackToTopic
:
function
()
{
cancelAndGoBack
:
function
(
event
)
{
Backbone
.
history
.
navigate
(
'topics/'
+
this
.
topicID
,
{
trigger
:
true
});
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 @
f788caa6
...
@@ -5,8 +5,8 @@
...
@@ -5,8 +5,8 @@
'underscore'
,
'underscore'
,
'gettext'
,
'gettext'
,
'teams/js/views/team_utils'
,
'teams/js/views/team_utils'
,
'text!teams/templates/team-
join
.underscore'
],
'text!teams/templates/team-
profile-header-actions
.underscore'
],
function
(
Backbone
,
_
,
gettext
,
TeamUtils
,
team
Join
Template
)
{
function
(
Backbone
,
_
,
gettext
,
TeamUtils
,
team
ProfileHeaderActions
Template
)
{
return
Backbone
.
View
.
extend
({
return
Backbone
.
View
.
extend
({
errorMessage
:
gettext
(
"An error occurred. Try again."
),
errorMessage
:
gettext
(
"An error occurred. Try again."
),
...
@@ -14,31 +14,34 @@
...
@@ -14,31 +14,34 @@
teamFullMessage
:
gettext
(
"This team is full."
),
teamFullMessage
:
gettext
(
"This team is full."
),
events
:
{
events
:
{
"click .action-primary"
:
"joinTeam"
"click .action-primary"
:
"joinTeam"
,
"click .action-edit-team"
:
"editTeam"
},
},
initialize
:
function
(
options
)
{
initialize
:
function
(
options
)
{
this
.
teamEvents
=
options
.
teamEvents
;
this
.
teamEvents
=
options
.
teamEvents
;
this
.
template
=
_
.
template
(
team
Join
Template
);
this
.
template
=
_
.
template
(
team
ProfileHeaderActions
Template
);
this
.
courseID
=
options
.
courseID
;
this
.
courseID
=
options
.
courseID
;
this
.
maxTeamSize
=
options
.
maxTeamSize
;
this
.
maxTeamSize
=
options
.
maxTeamSize
;
this
.
currentUsername
=
options
.
currentUsername
;
this
.
currentUsername
=
options
.
currentUsername
;
this
.
teamMembershipsUrl
=
options
.
teamMembershipsUrl
;
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
);
this
.
listenTo
(
this
.
model
,
"change"
,
this
.
render
);
},
},
render
:
function
()
{
render
:
function
()
{
var
view
=
this
,
var
view
=
this
,
message
,
message
,
showButton
,
show
Join
Button
,
teamHasSpace
;
teamHasSpace
;
this
.
getUserTeamInfo
(
this
.
currentUsername
,
view
.
maxTeamSize
).
done
(
function
(
info
)
{
this
.
getUserTeamInfo
(
this
.
currentUsername
,
view
.
maxTeamSize
).
done
(
function
(
info
)
{
teamHasSpace
=
info
.
teamHasSpace
;
teamHasSpace
=
info
.
teamHasSpace
;
// if user is the member of current team then we wouldn't show anything
// if user is the member of current team then we wouldn't show anything
if
(
!
info
.
memberOfCurrentTeam
)
{
if
(
!
info
.
memberOfCurrentTeam
)
{
showButton
=
!
info
.
alreadyMember
&&
teamHasSpace
;
show
Join
Button
=
!
info
.
alreadyMember
&&
teamHasSpace
;
if
(
info
.
alreadyMember
)
{
if
(
info
.
alreadyMember
)
{
message
=
info
.
memberOfCurrentTeam
?
''
:
view
.
alreadyMemberMessage
;
message
=
info
.
memberOfCurrentTeam
?
''
:
view
.
alreadyMemberMessage
;
...
@@ -47,7 +50,11 @@
...
@@ -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
;
return
view
;
},
},
...
@@ -108,6 +115,10 @@
...
@@ -108,6 +115,10 @@
}
}
return
deferred
.
promise
();
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 @
f788caa6
...
@@ -17,12 +17,12 @@
...
@@ -17,12 +17,12 @@
'teams/js/views/my_teams'
,
'teams/js/views/my_teams'
,
'teams/js/views/topic_teams'
,
'teams/js/views/topic_teams'
,
'teams/js/views/edit_team'
,
'teams/js/views/edit_team'
,
'teams/js/views/team_
join
'
,
'teams/js/views/team_
profile_header_actions
'
,
'text!teams/templates/teams_tab.underscore'
],
'text!teams/templates/teams_tab.underscore'
],
function
(
Backbone
,
_
,
gettext
,
HeaderView
,
HeaderModel
,
TabbedView
,
function
(
Backbone
,
_
,
gettext
,
HeaderView
,
HeaderModel
,
TabbedView
,
TopicModel
,
TopicCollection
,
TeamModel
,
TeamCollection
,
TeamMembershipCollection
,
TopicModel
,
TopicCollection
,
TeamModel
,
TeamCollection
,
TeamMembershipCollection
,
TopicsView
,
TeamProfileView
,
MyTeamsView
,
TopicTeamsView
,
TeamEditView
,
TopicsView
,
TeamProfileView
,
MyTeamsView
,
TopicTeamsView
,
TeamEditView
,
Team
Join
View
,
teamsTemplate
)
{
Team
ProfileHeaderActions
View
,
teamsTemplate
)
{
var
TeamsHeaderModel
=
HeaderModel
.
extend
({
var
TeamsHeaderModel
=
HeaderModel
.
extend
({
initialize
:
function
(
attributes
)
{
initialize
:
function
(
attributes
)
{
_
.
extend
(
this
.
defaults
,
{
nav_aria_label
:
gettext
(
'teams'
)});
_
.
extend
(
this
.
defaults
,
{
nav_aria_label
:
gettext
(
'teams'
)});
...
@@ -52,6 +52,7 @@
...
@@ -52,6 +52,7 @@
this
.
topics
=
options
.
topics
;
this
.
topics
=
options
.
topics
;
this
.
topicUrl
=
options
.
topicUrl
;
this
.
topicUrl
=
options
.
topicUrl
;
this
.
teamsUrl
=
options
.
teamsUrl
;
this
.
teamsUrl
=
options
.
teamsUrl
;
this
.
teamsDetailUrl
=
options
.
teamsDetailUrl
;
this
.
teamMembershipsUrl
=
options
.
teamMembershipsUrl
;
this
.
teamMembershipsUrl
=
options
.
teamMembershipsUrl
;
this
.
teamMembershipDetailUrl
=
options
.
teamMembershipDetailUrl
;
this
.
teamMembershipDetailUrl
=
options
.
teamMembershipDetailUrl
;
this
.
maxTeamSize
=
options
.
maxTeamSize
;
this
.
maxTeamSize
=
options
.
maxTeamSize
;
...
@@ -74,6 +75,7 @@
...
@@ -74,6 +75,7 @@
},
this
)],
},
this
)],
[
'topics/:topic_id(/)'
,
_
.
bind
(
this
.
browseTopic
,
this
)],
[
'topics/:topic_id(/)'
,
_
.
bind
(
this
.
browseTopic
,
this
)],
[
'topics/:topic_id/create-team(/)'
,
_
.
bind
(
this
.
newTeam
,
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
)],
[
'teams/:topic_id/:team_id(/)'
,
_
.
bind
(
this
.
browseTeam
,
this
)],
[
new
RegExp
(
'^(browse)
\
/?$'
),
_
.
bind
(
this
.
goToTab
,
this
)],
[
new
RegExp
(
'^(browse)
\
/?$'
),
_
.
bind
(
this
.
goToTab
,
this
)],
[
new
RegExp
(
'^(my-teams)
\
/?$'
),
_
.
bind
(
this
.
goToTab
,
this
)]
[
new
RegExp
(
'^(my-teams)
\
/?$'
),
_
.
bind
(
this
.
goToTab
,
this
)]
...
@@ -208,10 +210,9 @@
...
@@ -208,10 +210,9 @@
})
})
}),
}),
main
:
new
TeamEditView
({
main
:
new
TeamEditView
({
action
:
'create'
,
teamEvents
:
self
.
teamEvents
,
teamEvents
:
self
.
teamEvents
,
tagName
:
'create-new-team'
,
teamParams
:
teamsView
.
main
.
teamParams
teamParams
:
teamsView
.
main
.
teamParams
,
primaryButtonTitle
:
'Create'
})
})
});
});
self
.
render
();
self
.
render
();
...
@@ -219,6 +220,44 @@
...
@@ -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.
* Return a promise for the TeamsView for the given topic ID.
*/
*/
getTeamsView
:
function
(
topicID
)
{
getTeamsView
:
function
(
topicID
)
{
...
@@ -227,7 +266,7 @@
...
@@ -227,7 +266,7 @@
var
self
=
this
,
var
self
=
this
,
router
=
this
.
router
,
router
=
this
.
router
,
deferred
=
$
.
Deferred
();
deferred
=
$
.
Deferred
();
if
(
this
.
teamsCollection
&&
this
.
teamsCollection
.
topic_id
===
topicID
)
{
if
(
this
.
teamsCollection
&&
this
.
teamsCollection
.
topic_id
===
topicID
&&
this
.
teamsView
)
{
deferred
.
resolve
(
this
.
teamsView
);
deferred
.
resolve
(
this
.
teamsView
);
}
else
{
}
else
{
this
.
getTopic
(
topicID
)
this
.
getTopic
(
topicID
)
...
@@ -254,7 +293,8 @@
...
@@ -254,7 +293,8 @@
teamsUrl
:
self
.
teamsUrl
,
teamsUrl
:
self
.
teamsUrl
,
topicName
:
topic
.
get
(
'name'
),
topicName
:
topic
.
get
(
'name'
),
languages
:
self
.
languages
,
languages
:
self
.
languages
,
countries
:
self
.
countries
countries
:
self
.
countries
,
teamsDetailUrl
:
self
.
teamsDetailUrl
}
}
});
});
deferred
.
resolve
(
deferred
.
resolve
(
...
@@ -311,14 +351,17 @@
...
@@ -311,14 +351,17 @@
teamMembershipDetailUrl
:
self
.
teamMembershipDetailUrl
,
teamMembershipDetailUrl
:
self
.
teamMembershipDetailUrl
,
setFocusToHeaderFunc
:
self
.
setFocusToHeader
setFocusToHeaderFunc
:
self
.
setFocusToHeader
});
});
var
teamJoinView
=
new
TeamJoinView
({
var
TeamProfileActionsView
=
new
TeamProfileHeaderActionsView
({
teamEvents
:
self
.
teamEvents
,
teamEvents
:
self
.
teamEvents
,
courseID
:
courseID
,
courseID
:
courseID
,
model
:
team
,
model
:
team
,
teamsUrl
:
self
.
teamsUrl
,
teamsUrl
:
self
.
teamsUrl
,
maxTeamSize
:
self
.
maxTeamSize
,
maxTeamSize
:
self
.
maxTeamSize
,
currentUsername
:
self
.
userInfo
.
username
,
currentUsername
:
self
.
userInfo
.
username
,
teamMembershipsUrl
:
self
.
teamMembershipsUrl
teamMembershipsUrl
:
self
.
teamMembershipsUrl
,
topicID
:
topicID
,
showEditButton
:
self
.
userInfo
.
privileged
||
self
.
userInfo
.
staff
});
});
deferred
.
resolve
(
deferred
.
resolve
(
self
.
createViewWithHeader
(
self
.
createViewWithHeader
(
...
@@ -326,7 +369,7 @@
...
@@ -326,7 +369,7 @@
mainView
:
view
,
mainView
:
view
,
subject
:
team
,
subject
:
team
,
parentTopic
:
topic
,
parentTopic
:
topic
,
headerActionsView
:
teamJoin
View
headerActionsView
:
TeamProfileActions
View
}
}
)
)
);
);
...
@@ -337,7 +380,8 @@
...
@@ -337,7 +380,8 @@
createViewWithHeader
:
function
(
options
)
{
createViewWithHeader
:
function
(
options
)
{
var
router
=
this
.
router
,
var
router
=
this
.
router
,
breadcrumbs
,
headerView
;
breadcrumbs
,
headerView
,
viewDescription
,
viewTitle
;
breadcrumbs
=
[{
breadcrumbs
=
[{
title
:
gettext
(
'All Topics'
),
title
:
gettext
(
'All Topics'
),
url
:
'#browse'
url
:
'#browse'
...
@@ -348,10 +392,25 @@
...
@@ -348,10 +392,25 @@
url
:
'#topics/'
+
options
.
parentTopic
.
id
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
({
headerView
=
new
HeaderView
({
model
:
new
TeamsHeaderModel
({
model
:
new
TeamsHeaderModel
({
description
:
options
.
subject
.
get
(
'description'
)
,
description
:
viewDescription
,
title
:
options
.
subject
.
get
(
'name'
)
,
title
:
viewTitle
,
breadcrumbs
:
breadcrumbs
breadcrumbs
:
breadcrumbs
}),
}),
headerActionsView
:
options
.
headerActionsView
,
headerActionsView
:
options
.
headerActionsView
,
...
...
lms/djangoapps/teams/static/teams/templates/edit-team.underscore
View file @
f788caa6
<form>
<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">
<div class="msg-content">
<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>
<span class="screen-reader-message sr"></span>
<div class="copy">
<div class="copy">
<p></p>
<p></p>
...
@@ -11,15 +17,16 @@
...
@@ -11,15 +17,16 @@
</div>
</div>
</div>
</div>
<div class="form-instructions create-team-instructions">
<% if (action === 'create') { %>
<p class="copy">
<div class="form-instructions create-team-instructions">
<%- gettext("Enter information to describe your team. You cannot change these details after you create the team.") %></p>
<p class="copy">
</div>
<%- 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-edit-fields">
<div class="team-required-fields">
<div class="team-required-fields">
</div>
</div>
<div class="team-optional-fields">
<div class="team-optional-fields">
<fieldset>
<fieldset>
<div class="u-field u-field-optional_description">
<div class="u-field u-field-optional_description">
...
@@ -38,7 +45,7 @@
...
@@ -38,7 +45,7 @@
<button class="action action-primary">
<button class="action action-primary">
<%=
<%=
interpolate_text(
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>'
'primaryButtonTitle': primaryButtonTitle, 'span_start': '<span class="sr">', 'span_end': '</span>'
}
}
...
@@ -48,9 +55,10 @@
...
@@ -48,9 +55,10 @@
<button class="action action-cancel">
<button class="action action-cancel">
<%=
<%=
interpolate_text(
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 @
f788caa6
<div class="join-team form-actions">
<div class="join-team form-actions">
<% if (showButton) {%>
<% if (show
Join
Button) {%>
<button class="action action-primary">
<button class="action action-primary">
<%- gettext("Join Team") %>
<%- gettext("Join Team") %>
</button>
</button>
<% } else if (message) { %>
<% } else if (message) { %>
<p class="join-team-message"><%- message %></p>
<p class="join-team-message"><%- message %></p>
<% } %>
<% } %>
<% if (showEditButton) { %>
<button class="btn btn-secondary action-edit-team"><%- gettext("Edit Team") %></button>
<% } %>
</div>
</div>
lms/djangoapps/teams/static/teams/templates/team-profile.underscore
View file @
f788caa6
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<% if (isMember) { %>
<% if (isMember) { %>
<div class="leave-team">
<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>
<div class="divider-lv1"></div>
<div class="divider-lv1"></div>
...
...
lms/djangoapps/teams/templates/teams/teams.html
View file @
f788caa6
...
@@ -39,6 +39,7 @@
...
@@ -39,6 +39,7 @@
topicUrl: '${ topic_url }',
topicUrl: '${ topic_url }',
topicsUrl: '${ topics_url }',
topicsUrl: '${ topics_url }',
teamsUrl: '${ teams_url }',
teamsUrl: '${ teams_url }',
teamsDetailUrl: '${ teams_detail_url }',
teamMembershipsUrl: '${ team_memberships_url }',
teamMembershipsUrl: '${ team_memberships_url }',
teamMembershipDetailUrl: '${ team_membership_detail_url }',
teamMembershipDetailUrl: '${ team_membership_detail_url }',
maxTeamSize: ${ course.teams_max_size },
maxTeamSize: ${ course.teams_max_size },
...
...
lms/djangoapps/teams/views.py
View file @
f788caa6
...
@@ -117,6 +117,7 @@ class TeamsDashboardView(View):
...
@@ -117,6 +117,7 @@ class TeamsDashboardView(View):
),
),
"topics_url"
:
reverse
(
'topics_list'
,
request
=
request
),
"topics_url"
:
reverse
(
'topics_list'
,
request
=
request
),
"teams_url"
:
reverse
(
'teams_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_memberships_url"
:
reverse
(
'team_membership_list'
,
request
=
request
),
"team_membership_detail_url"
:
reverse
(
'team_membership_detail'
,
args
=
[
'team_id'
,
user
.
username
]),
"team_membership_detail_url"
:
reverse
(
'team_membership_detail'
,
args
=
[
'team_id'
,
user
.
username
]),
"languages"
:
settings
.
ALL_LANGUAGES
,
"languages"
:
settings
.
ALL_LANGUAGES
,
...
...
lms/static/js/spec/main.js
View file @
f788caa6
...
@@ -802,7 +802,7 @@
...
@@ -802,7 +802,7 @@
'lms/include/teams/js/spec/views/topic_card_spec.js'
,
'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/topic_teams_spec.js'
,
'lms/include/teams/js/spec/views/topics_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
);
}).
call
(
this
,
requirejs
,
define
);
lms/static/sass/elements/_controls.scss
View file @
f788caa6
...
@@ -404,7 +404,7 @@
...
@@ -404,7 +404,7 @@
}
}
}
}
.btn-
link
{
.btn-
secondary
{
@extend
%btn-pl-secondary-base
;
@extend
%btn-pl-secondary-base
;
background-image
:
none
;
background-image
:
none
;
...
@@ -416,3 +416,24 @@
...
@@ -416,3 +416,24 @@
color
:
$link-color
;
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