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
3662fbc1
Commit
3662fbc1
authored
Aug 31, 2015
by
cahrens
Committed by
Eric Fischer
Sep 10, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Edit Membership functionality and tests
TNL-1913
parent
0c3be8e1
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
473 additions
and
30 deletions
+473
-30
common/test/acceptance/pages/lms/teams.py
+58
-3
common/test/acceptance/tests/lms/test_teams.py
+90
-5
lms/djangoapps/teams/static/teams/js/spec/views/edit_team_members_spec.js
+138
-0
lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js
+9
-1
lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js
+1
-0
lms/djangoapps/teams/static/teams/js/views/edit_team_members.js
+103
-0
lms/djangoapps/teams/static/teams/js/views/instructor_tools.js
+4
-2
lms/djangoapps/teams/static/teams/js/views/team_card.js
+3
-3
lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
+6
-3
lms/djangoapps/teams/static/teams/js/views/team_utils.js
+2
-2
lms/djangoapps/teams/static/teams/js/views/teams_tab.js
+48
-11
lms/djangoapps/teams/static/teams/templates/date.underscore
+0
-0
lms/djangoapps/teams/static/teams/templates/edit-team-member.underscore
+10
-0
lms/static/js/spec/main.js
+1
-0
No files found.
common/test/acceptance/pages/lms/teams.py
View file @
3662fbc1
...
@@ -317,9 +317,7 @@ class TeamManagementPage(CoursePage, FieldsMixin, BreadcrumbsMixin):
...
@@ -317,9 +317,7 @@ class TeamManagementPage(CoursePage, FieldsMixin, BreadcrumbsMixin):
def
is_browser_on_page
(
self
):
def
is_browser_on_page
(
self
):
"""Check if we're on the create team page for a particular topic."""
"""Check if we're on the create team page for a particular topic."""
has_correct_url
=
self
.
url
.
endswith
(
self
.
url_path
)
return
self
.
q
(
css
=
'.team-edit-fields'
)
.
present
teams_create_view_present
=
self
.
q
(
css
=
'.team-edit-fields'
)
.
present
return
has_correct_url
and
teams_create_view_present
@property
@property
def
header_page_name
(
self
):
def
header_page_name
(
self
):
...
@@ -351,6 +349,63 @@ class TeamManagementPage(CoursePage, FieldsMixin, BreadcrumbsMixin):
...
@@ -351,6 +349,63 @@ class TeamManagementPage(CoursePage, FieldsMixin, BreadcrumbsMixin):
"""Returns the 'delete team' button."""
"""Returns the 'delete team' button."""
return
self
.
q
(
css
=
'.action-delete'
)
.
first
return
self
.
q
(
css
=
'.action-delete'
)
.
first
def
click_membership_button
(
self
):
"""Clicks the 'edit membership' button"""
self
.
q
(
css
=
'.action-edit-members'
)
.
first
.
click
()
self
.
wait_for_ajax
()
@property
def
membership_button_present
(
self
):
"""Checks if the edit membership button is present"""
return
self
.
q
(
css
=
'.action-edit-members'
)
.
present
class
EditMembershipPage
(
CoursePage
):
"""
Staff or discussion-privileged user page to remove troublesome or inactive
students from a team
"""
def
__init__
(
self
,
browser
,
course_id
,
team
):
"""
Set up `self.url_path` on instantiation, since it dynamically
reflects the current team.
"""
super
(
EditMembershipPage
,
self
)
.
__init__
(
browser
,
course_id
)
self
.
team
=
team
self
.
url_path
=
"teams/#teams/{topic_id}/{team_id}/edit-team/manage-members"
.
format
(
topic_id
=
self
.
team
[
'topic_id'
],
team_id
=
self
.
team
[
'id'
]
)
def
is_browser_on_page
(
self
):
"""Check if we're on the team membership page for a particular team."""
self
.
wait_for_ajax
()
if
self
.
q
(
css
=
'.edit-members'
)
.
present
:
return
True
empty_query
=
self
.
q
(
css
=
'.teams-main>.page-content>p'
)
.
first
return
(
len
(
empty_query
.
results
)
>
0
and
empty_query
[
0
]
.
text
==
"This team does not have any members."
)
@property
def
team_members
(
self
):
"""Returns the number of team members shown on the page."""
return
len
(
self
.
q
(
css
=
'.team-member'
))
def
click_first_remove
(
self
):
"""Clicks the remove link on the first member listed."""
self
.
q
(
css
=
'.action-remove-member'
)
.
first
.
click
()
def
confirm_delete_membership_dialog
(
self
):
"""Click 'delete' on the warning dialog."""
confirm_prompt
(
self
,
require_notification
=
False
)
self
.
wait_for_ajax
()
def
cancel_delete_membership_dialog
(
self
):
"""Click 'delete' on the warning dialog."""
confirm_prompt
(
self
,
cancel
=
True
)
class
TeamPage
(
CoursePage
,
PaginatedUIMixin
,
BreadcrumbsMixin
):
class
TeamPage
(
CoursePage
,
PaginatedUIMixin
,
BreadcrumbsMixin
):
"""
"""
...
...
common/test/acceptance/tests/lms/test_teams.py
View file @
3662fbc1
...
@@ -28,6 +28,7 @@ from ...pages.lms.teams import (
...
@@ -28,6 +28,7 @@ from ...pages.lms.teams import (
BrowseTopicsPage
,
BrowseTopicsPage
,
BrowseTeamsPage
,
BrowseTeamsPage
,
TeamManagementPage
,
TeamManagementPage
,
EditMembershipPage
,
TeamPage
TeamPage
)
)
from
...pages.common.utils
import
confirm_prompt
from
...pages.common.utils
import
confirm_prompt
...
@@ -207,7 +208,7 @@ class TeamsTabTest(TeamsTabBase):
...
@@ -207,7 +208,7 @@ class TeamsTabTest(TeamsTabBase):
@ddt.data
(
@ddt.data
(
'topics/{topic_id}'
,
'topics/{topic_id}'
,
'topics/{topic_id}/search'
,
'topics/{topic_id}/search'
,
't
opic
s/{topic_id}/{team_id}/edit-team'
,
't
eam
s/{topic_id}/{team_id}/edit-team'
,
'teams/{topic_id}/{team_id}'
'teams/{topic_id}/{team_id}'
)
)
def
test_unauthorized_error_message
(
self
,
route
):
def
test_unauthorized_error_message
(
self
,
route
):
...
@@ -217,10 +218,10 @@ class TeamsTabTest(TeamsTabBase):
...
@@ -217,10 +218,10 @@ class TeamsTabTest(TeamsTabBase):
"""
"""
topics
=
self
.
create_topics
(
1
)
topics
=
self
.
create_topics
(
1
)
topic
=
topics
[
0
]
topic
=
topics
[
0
]
self
.
set_team_configuration
(
{
self
.
set_team_configuration
(
u'max_team_size'
:
10
,
{
u'max_team_size'
:
10
,
u'topics'
:
topics
}
,
u'topics'
:
topics
global_staff
=
True
}
)
)
team
=
self
.
create_teams
(
topic
,
1
)[
0
]
team
=
self
.
create_teams
(
topic
,
1
)[
0
]
self
.
teams_page
.
visit
()
self
.
teams_page
.
visit
()
self
.
browser
.
delete_cookie
(
'sessionid'
)
self
.
browser
.
delete_cookie
(
'sessionid'
)
...
@@ -1424,6 +1425,90 @@ class EditTeamTest(TeamFormActions):
...
@@ -1424,6 +1425,90 @@ class EditTeamTest(TeamFormActions):
self
.
verify_and_navigate_to_edit_team_page
()
self
.
verify_and_navigate_to_edit_team_page
()
@ddt.ddt
class
EditMembershipTest
(
TeamFormActions
):
"""
Tests for administrating from the team membership page
"""
def
setUp
(
self
):
super
(
EditMembershipTest
,
self
)
.
setUp
()
self
.
set_team_configuration
(
{
'course_id'
:
self
.
course_id
,
'max_team_size'
:
10
,
'topics'
:
[
self
.
topic
]},
global_staff
=
True
)
self
.
team_management_page
=
TeamManagementPage
(
self
.
browser
,
self
.
course_id
,
self
.
topic
)
self
.
team
=
self
.
create_teams
(
self
.
topic
,
num_teams
=
1
)[
0
]
#make sure a user exists on this team so we can edit the membership
self
.
create_membership
(
self
.
user_info
[
'username'
],
self
.
team
[
'id'
])
self
.
edit_membership_page
=
EditMembershipPage
(
self
.
browser
,
self
.
course_id
,
self
.
team
)
self
.
team_page
=
TeamPage
(
self
.
browser
,
self
.
course_id
,
team
=
self
.
team
)
def
edit_membership_helper
(
self
,
role
,
cancel
=
False
):
""" Helper for common functionality in edit membership tests """
if
role
is
not
None
:
AutoAuthPage
(
self
.
browser
,
course_id
=
self
.
course_id
,
staff
=
False
,
roles
=
role
)
.
visit
()
self
.
team_page
.
visit
()
self
.
team_page
.
click_edit_team_button
()
self
.
team_management_page
.
wait_for_page
()
self
.
assertTrue
(
self
.
team_management_page
.
membership_button_present
)
self
.
team_management_page
.
click_membership_button
()
self
.
edit_membership_page
.
wait_for_page
()
self
.
edit_membership_page
.
click_first_remove
()
if
cancel
:
self
.
edit_membership_page
.
cancel_delete_membership_dialog
()
self
.
assertEqual
(
self
.
edit_membership_page
.
team_members
,
1
)
else
:
self
.
edit_membership_page
.
confirm_delete_membership_dialog
()
self
.
assertEqual
(
self
.
edit_membership_page
.
team_members
,
0
)
self
.
assertTrue
(
self
.
edit_membership_page
.
is_browser_on_page
)
@ddt.data
(
'Moderator'
,
'Community TA'
,
'Administrator'
,
None
)
def
test_remove_membership
(
self
,
role
):
"""
Scenario: The user should be able to remove a membership
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 Membership button
And When I click the edit membership button
Then I should see the edit membership page
And When I click the remove button and confirm the dialog
Then my membership should be removed, and I should remain on the page
"""
self
.
edit_membership_helper
(
role
,
cancel
=
False
)
@ddt.data
(
'Moderator'
,
'Community TA'
,
'Administrator'
,
None
)
def
test_cancel_remove_membership
(
self
,
role
):
"""
Scenario: The user should be able to remove a membership
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 Membership button
And When I click the edit membership button
Then I should see the edit membership page
And When I click the remove button and cancel the dialog
Then my membership should not be removed, and I should remain on the page
"""
self
.
edit_membership_helper
(
role
,
cancel
=
True
)
@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_members_spec.js
0 → 100644
View file @
3662fbc1
define
([
'jquery'
,
'underscore'
,
'backbone'
,
'common/js/spec_helpers/ajax_helpers'
,
'teams/js/views/edit_team_members'
,
'teams/js/models/team'
,
'teams/js/views/team_utils'
,
'teams/js/spec_helpers/team_spec_helpers'
],
function
(
$
,
_
,
Backbone
,
AjaxHelpers
,
TeamEditMembershipView
,
TeamModel
,
TeamUtils
,
TeamSpecHelpers
)
{
'use strict'
;
describe
(
'CreateEditTeam'
,
function
()
{
var
editTeamID
=
'av'
,
DEFAULT_MEMBERSHIP
=
[
{
'user'
:
{
'username'
:
'frodo'
,
'profile_image'
:
{
'has_image'
:
true
,
'image_url_medium'
:
'/frodo-image-url'
},
},
last_activity_at
:
"2015-08-21T18:53:01.145Z"
,
date_joined
:
"2014-01-01T18:53:01.145Z"
}
],
deleteTeamMemember
=
function
(
view
,
confirm
)
{
view
.
$
(
'.action-remove-member'
).
click
();
// Confirm delete dialog
if
(
confirm
)
{
$
(
'.action-primary'
).
click
();
}
else
{
$
(
'.action-secondary'
).
click
();
}
},
verifyTeamMembersView
=
function
(
view
)
{
expect
(
view
.
$
(
'.team-member'
).
length
).
toEqual
(
1
);
expect
(
view
.
$
(
'.member-profile'
).
attr
(
'href'
)).
toEqual
(
'/u/frodo'
);
expect
(
view
.
$
(
'img.image-url'
).
attr
(
'src'
)).
toEqual
(
'/frodo-image-url'
);
expect
(
view
.
$
(
'.member-info-container .primary'
).
text
()).
toBe
(
'frodo'
);
expect
(
view
.
$el
.
find
(
'#last-active abbr'
).
attr
(
'title'
)).
toEqual
(
"2015-08-21T18:53:01.145Z"
);
expect
(
view
.
$el
.
find
(
'#date-joined abbr'
).
attr
(
'title'
)).
toEqual
(
"2014-01-01T18:53:01.145Z"
);
},
verifyNoMembersView
=
function
(
view
){
expect
(
view
.
$el
.
text
().
trim
()).
toBe
(
'This team does not have any members.'
);
},
createTeamModelData
=
function
(
membership
)
{
return
{
id
:
editTeamID
,
name
:
'Avengers'
,
description
:
'Team of dumbs'
,
language
:
'en'
,
country
:
'US'
,
membership
:
membership
,
url
:
'/api/team/v0/teams/'
+
editTeamID
};
},
createEditTeamMembersView
=
function
(
membership
)
{
var
teamModel
=
new
TeamModel
(
createTeamModelData
(
membership
),
{
parse
:
true
}
);
return
new
TeamEditMembershipView
({
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
el
:
$
(
'.teams-content'
),
model
:
teamModel
,
context
:
TeamSpecHelpers
.
testContext
}).
render
();
};
beforeEach
(
function
()
{
setFixtures
(
'<div id="page-prompt"></div><div class="teams-content"></div>'
);
spyOn
(
Backbone
.
history
,
'navigate'
);
spyOn
(
TeamUtils
,
'showMessage'
);
});
it
(
'can render a message when there are no members'
,
function
()
{
var
view
=
createEditTeamMembersView
([]);
verifyNoMembersView
(
view
);
});
it
(
'can delete a team member and update the view'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
view
=
createEditTeamMembersView
(
DEFAULT_MEMBERSHIP
);
spyOn
(
view
.
teamEvents
,
'trigger'
);
verifyTeamMembersView
(
view
);
deleteTeamMemember
(
view
,
true
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'DELETE'
,
'/api/team/v0/team_membership/av,frodo'
,
null
);
AjaxHelpers
.
respondWithNoContent
(
requests
);
expect
(
view
.
teamEvents
.
trigger
).
toHaveBeenCalledWith
(
'teams:update'
,
{
action
:
'leave'
,
team
:
view
.
model
}
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
view
.
model
.
get
(
'url'
));
AjaxHelpers
.
respondWithJson
(
requests
,
createTeamModelData
([]));
verifyNoMembersView
(
view
);
});
it
(
'can show an error message if removing the user fails'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
view
=
createEditTeamMembersView
(
DEFAULT_MEMBERSHIP
);
spyOn
(
view
.
teamEvents
,
'trigger'
);
verifyTeamMembersView
(
view
);
deleteTeamMemember
(
view
,
true
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'DELETE'
,
'/api/team/v0/team_membership/av,frodo'
,
null
);
AjaxHelpers
.
respondWithError
(
requests
);
expect
(
TeamUtils
.
showMessage
).
toHaveBeenCalledWith
(
'An error occurred while removing the member from the team. Try again.'
,
undefined
);
expect
(
view
.
teamEvents
.
trigger
).
not
.
toHaveBeenCalled
();
verifyTeamMembersView
(
view
);
});
it
(
'can cancel team membership deletion'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
view
=
createEditTeamMembersView
(
DEFAULT_MEMBERSHIP
);
spyOn
(
view
.
teamEvents
,
'trigger'
);
verifyTeamMembersView
(
view
);
deleteTeamMemember
(
view
,
false
);
expect
(
requests
.
length
).
toBe
(
0
);
expect
(
view
.
teamEvents
.
trigger
).
not
.
toHaveBeenCalled
();
verifyTeamMembersView
(
view
);
});
});
});
lms/djangoapps/teams/static/teams/js/spec/views/instructor_tools_spec.js
View file @
3662fbc1
...
@@ -15,7 +15,7 @@ define([
...
@@ -15,7 +15,7 @@ define([
createInstructorTools
=
function
()
{
createInstructorTools
=
function
()
{
return
new
InstructorToolsView
({
return
new
InstructorToolsView
({
team
:
new
Team
(
TeamSpecHelpers
.
createMockTeamData
(
1
,
1
)[
0
]),
team
:
new
Team
(
TeamSpecHelpers
.
createMockTeamData
(
1
,
1
)[
0
]),
teamEvents
:
TeamSpecHelpers
.
teamEvents
,
teamEvents
:
TeamSpecHelpers
.
teamEvents
});
});
},
},
deleteTeam
=
function
(
view
,
confirm
)
{
deleteTeam
=
function
(
view
,
confirm
)
{
...
@@ -80,5 +80,13 @@ define([
...
@@ -80,5 +80,13 @@ define([
AjaxHelpers
.
respondWithError
(
requests
,
404
);
AjaxHelpers
.
respondWithError
(
requests
,
404
);
expectSuccessMessage
(
view
.
team
);
expectSuccessMessage
(
view
.
team
);
});
});
it
(
'can trigger the edit membership view'
,
function
()
{
view
.
$
(
'.action-edit-members'
).
click
();
expect
(
Backbone
.
history
.
navigate
).
toHaveBeenCalledWith
(
'teams/'
+
view
.
team
.
get
(
'topic_id'
)
+
"/"
+
view
.
team
.
id
+
"/edit-team/manage-members"
,
{
trigger
:
true
}
);
});
});
});
});
});
lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js
View file @
3662fbc1
...
@@ -37,6 +37,7 @@ define([
...
@@ -37,6 +37,7 @@ define([
country
:
testCountries
[
i
%
4
][
0
],
country
:
testCountries
[
i
%
4
][
0
],
membership
:
[],
membership
:
[],
last_activity_at
:
''
,
last_activity_at
:
''
,
topic_id
:
'topic_id'
+
i
,
url
:
'api/team/v0/teams/'
+
id
url
:
'api/team/v0/teams/'
+
id
};
};
});
});
...
...
lms/djangoapps/teams/static/teams/js/views/edit_team_members.js
0 → 100644
View file @
3662fbc1
;(
function
(
define
)
{
'use strict'
;
define
([
'backbone'
,
'jquery'
,
'underscore'
,
'gettext'
,
'teams/js/models/team'
,
'teams/js/views/team_utils'
,
'common/js/components/utils/view_utils'
,
'text!teams/templates/edit-team-member.underscore'
,
'text!teams/templates/date.underscore'
],
function
(
Backbone
,
$
,
_
,
gettext
,
TeamModel
,
TeamUtils
,
ViewUtils
,
editTeamMemberTemplate
,
dateTemplate
)
{
return
Backbone
.
View
.
extend
({
dateTemplate
:
_
.
template
(
dateTemplate
),
teamMemberTemplate
:
_
.
template
(
editTeamMemberTemplate
),
errorMessage
:
gettext
(
"An error occurred while removing the member from the team. Try again."
),
events
:
{
'click .action-remove-member'
:
'removeMember'
},
initialize
:
function
(
options
)
{
this
.
teamMembershipDetailUrl
=
options
.
context
.
teamMembershipDetailUrl
;
// The URL ends with team_id,request_username. We want to replace
// the last occurrence of team_id with the actual team_id, and remove request_username
// as the actual user to be removed from the team will be added on before calling DELETE.
this
.
teamMembershipDetailUrl
=
this
.
teamMembershipDetailUrl
.
substring
(
0
,
this
.
teamMembershipDetailUrl
.
lastIndexOf
(
'team_id'
)
)
+
this
.
model
.
get
(
'id'
)
+
","
;
this
.
teamEvents
=
options
.
teamEvents
;
},
render
:
function
()
{
if
(
this
.
model
.
get
(
'membership'
).
length
===
0
)
{
this
.
$el
.
html
(
'<p>'
+
gettext
(
'This team does not have any members.'
)
+
'</p>'
);
}
else
{
this
.
$el
.
html
(
'<ul class="edit-members"></ul>'
);
this
.
renderTeamMembers
();
}
return
this
;
},
renderTeamMembers
:
function
()
{
var
self
=
this
,
dateJoined
,
lastActivity
;
_
.
each
(
this
.
model
.
get
(
'membership'
),
function
(
membership
)
{
dateJoined
=
interpolate
(
// Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see: https://github.com/rmm5t/jquery-timeago)
gettext
(
"Joined %(date)s"
),
{
date
:
self
.
dateTemplate
({
date
:
membership
.
date_joined
})},
true
);
lastActivity
=
interpolate
(
// Translators: 'date' is a placeholder for a fuzzy, relative timestamp (see: https://github.com/rmm5t/jquery-timeago)
gettext
(
"Last Activity %(date)s"
),
{
date
:
self
.
dateTemplate
({
date
:
membership
.
last_activity_at
})},
true
);
// It is assumed that the team member array is automatically in the order of date joined.
self
.
$
(
'.edit-members'
).
append
(
self
.
teamMemberTemplate
({
imageUrl
:
membership
.
user
.
profile_image
.
image_url_medium
,
username
:
membership
.
user
.
username
,
memberProfileUrl
:
'/u/'
+
membership
.
user
.
username
,
dateJoined
:
dateJoined
,
lastActive
:
lastActivity
}));
});
this
.
$
(
'abbr'
).
timeago
();
},
removeMember
:
function
(
event
)
{
var
self
=
this
,
username
=
$
(
event
.
currentTarget
).
data
(
'username'
);
event
.
preventDefault
();
ViewUtils
.
confirmThenRunOperation
(
gettext
(
'Remove this team member?'
),
gettext
(
'This learner will be removed from the team, allowing another learner to take the available spot.'
),
gettext
(
'Remove'
),
function
()
{
$
.
ajax
({
type
:
'DELETE'
,
url
:
self
.
teamMembershipDetailUrl
+
username
}).
done
(
function
()
{
self
.
teamEvents
.
trigger
(
'teams:update'
,
{
action
:
'leave'
,
team
:
self
.
model
});
self
.
model
.
fetch
().
done
(
function
()
{
self
.
render
();
});
}).
fail
(
function
(
data
)
{
TeamUtils
.
parseAndShowMessage
(
data
,
self
.
errorMessage
);
});
}
);
}
});
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
lms/djangoapps/teams/static/teams/js/views/instructor_tools.js
View file @
3662fbc1
...
@@ -38,8 +38,10 @@
...
@@ -38,8 +38,10 @@
editMembership
:
function
(
event
)
{
editMembership
:
function
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
alert
(
"You clicked the button!"
);
Backbone
.
history
.
navigate
(
//placeholder; will route to remove team member page
'teams/'
+
this
.
team
.
get
(
'topic_id'
)
+
'/'
+
this
.
team
.
id
+
'/edit-team/manage-members'
,
{
trigger
:
true
}
);
},
},
handleDelete
:
function
()
{
handleDelete
:
function
()
{
...
...
lms/djangoapps/teams/static/teams/js/views/team_card.js
View file @
3662fbc1
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
'teams/js/views/team_utils'
,
'teams/js/views/team_utils'
,
'text!teams/templates/team-membership-details.underscore'
,
'text!teams/templates/team-membership-details.underscore'
,
'text!teams/templates/team-country-language.underscore'
,
'text!teams/templates/team-country-language.underscore'
,
'text!teams/templates/
team-activity
.underscore'
'text!teams/templates/
date
.underscore'
],
function
(
],
function
(
Backbone
,
Backbone
,
_
,
_
,
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
TeamUtils
,
TeamUtils
,
teamMembershipDetailsTemplate
,
teamMembershipDetailsTemplate
,
teamCountryLanguageTemplate
,
teamCountryLanguageTemplate
,
teamActivity
Template
date
Template
)
{
)
{
var
TeamMembershipView
,
TeamCountryLanguageView
,
TeamActivityView
,
TeamCardView
;
var
TeamMembershipView
,
TeamCountryLanguageView
,
TeamActivityView
,
TeamCardView
;
...
@@ -68,7 +68,7 @@
...
@@ -68,7 +68,7 @@
TeamActivityView
=
Backbone
.
View
.
extend
({
TeamActivityView
=
Backbone
.
View
.
extend
({
tagName
:
'div'
,
tagName
:
'div'
,
className
:
'team-activity'
,
className
:
'team-activity'
,
template
:
_
.
template
(
teamActivity
Template
),
template
:
_
.
template
(
date
Template
),
initialize
:
function
(
options
)
{
initialize
:
function
(
options
)
{
this
.
date
=
options
.
date
;
this
.
date
=
options
.
date
;
...
...
lms/djangoapps/teams/static/teams/js/views/team_profile_header_actions.js
View file @
3662fbc1
...
@@ -2,11 +2,12 @@
...
@@ -2,11 +2,12 @@
'use strict'
;
'use strict'
;
define
([
'backbone'
,
define
([
'backbone'
,
'jquery'
,
'underscore'
,
'underscore'
,
'gettext'
,
'gettext'
,
'teams/js/views/team_utils'
,
'teams/js/views/team_utils'
,
'text!teams/templates/team-profile-header-actions.underscore'
],
'text!teams/templates/team-profile-header-actions.underscore'
],
function
(
Backbone
,
_
,
gettext
,
TeamUtils
,
teamProfileHeaderActionsTemplate
)
{
function
(
Backbone
,
$
,
_
,
gettext
,
TeamUtils
,
teamProfileHeaderActionsTemplate
)
{
return
Backbone
.
View
.
extend
({
return
Backbone
.
View
.
extend
({
errorMessage
:
gettext
(
"An error occurred. Try again."
),
errorMessage
:
gettext
(
"An error occurred. Try again."
),
...
@@ -56,8 +57,10 @@
...
@@ -56,8 +57,10 @@
return
view
;
return
view
;
},
},
joinTeam
:
function
()
{
joinTeam
:
function
(
event
)
{
var
view
=
this
;
var
view
=
this
;
event
.
preventDefault
();
$
.
ajax
({
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
url
:
view
.
context
.
teamMembershipsUrl
,
url
:
view
.
context
.
teamMembershipsUrl
,
...
@@ -117,7 +120,7 @@
...
@@ -117,7 +120,7 @@
editTeam
:
function
(
event
)
{
editTeam
:
function
(
event
)
{
event
.
preventDefault
();
event
.
preventDefault
();
Backbone
.
history
.
navigate
(
Backbone
.
history
.
navigate
(
't
opic
s/'
+
this
.
topic
.
id
+
'/'
+
this
.
model
.
get
(
'id'
)
+
'/edit-team'
,
't
eam
s/'
+
this
.
topic
.
id
+
'/'
+
this
.
model
.
get
(
'id'
)
+
'/edit-team'
,
{
trigger
:
true
}
{
trigger
:
true
}
);
);
}
}
...
...
lms/djangoapps/teams/static/teams/js/views/team_utils.js
View file @
3662fbc1
/* Team utility methods*/
/* Team utility methods*/
;(
function
(
define
)
{
;(
function
(
define
)
{
'use strict'
;
'use strict'
;
define
([
define
([
"jquery"
,
"underscore"
],
function
()
{
],
function
(
$
,
_
)
{
return
{
return
{
/**
/**
...
...
lms/djangoapps/teams/static/teams/js/views/teams_tab.js
View file @
3662fbc1
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
'use strict'
;
'use strict'
;
define
([
'backbone'
,
define
([
'backbone'
,
'jquery'
,
'underscore'
,
'underscore'
,
'gettext'
,
'gettext'
,
'common/js/components/views/search_field'
,
'common/js/components/views/search_field'
,
...
@@ -19,14 +20,15 @@
...
@@ -19,14 +20,15 @@
'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/edit_team_members'
,
'teams/js/views/team_profile_header_actions'
,
'teams/js/views/team_profile_header_actions'
,
'teams/js/views/instructor_tools'
,
'teams/js/views/team_utils'
,
'teams/js/views/team_utils'
,
'teams/js/views/instructor_tools'
,
'text!teams/templates/teams_tab.underscore'
],
'text!teams/templates/teams_tab.underscore'
],
function
(
Backbone
,
_
,
gettext
,
SearchFieldView
,
HeaderView
,
HeaderModel
,
function
(
Backbone
,
$
,
_
,
gettext
,
SearchFieldView
,
HeaderView
,
HeaderModel
,
TopicModel
,
TopicCollection
,
TeamModel
,
TeamCollection
,
TeamMembershipCollection
,
TeamAnalytics
,
TopicModel
,
TopicCollection
,
TeamModel
,
TeamCollection
,
TeamMembershipCollection
,
TeamAnalytics
,
TeamsTabbedView
,
TopicsView
,
TeamProfileView
,
MyTeamsView
,
TopicTeamsView
,
TeamEditView
,
TeamsTabbedView
,
TopicsView
,
TeamProfileView
,
MyTeamsView
,
TopicTeamsView
,
TeamEditView
,
TeamProfileHeaderActionsView
,
TeamUtils
,
InstructorToolsView
,
teamsTemplate
)
{
Team
MembersEditView
,
Team
ProfileHeaderActionsView
,
TeamUtils
,
InstructorToolsView
,
teamsTemplate
)
{
var
TeamsHeaderModel
=
HeaderModel
.
extend
({
var
TeamsHeaderModel
=
HeaderModel
.
extend
({
initialize
:
function
()
{
initialize
:
function
()
{
_
.
extend
(
this
.
defaults
,
{
nav_aria_label
:
gettext
(
'teams'
)});
_
.
extend
(
this
.
defaults
,
{
nav_aria_label
:
gettext
(
'teams'
)});
...
@@ -73,7 +75,6 @@
...
@@ -73,7 +75,6 @@
[
'topics/:topic_id(/)'
,
_
.
bind
(
this
.
browseTopic
,
this
)],
[
'topics/:topic_id(/)'
,
_
.
bind
(
this
.
browseTopic
,
this
)],
[
'topics/:topic_id/search(/)'
,
_
.
bind
(
this
.
searchTeams
,
this
)],
[
'topics/:topic_id/search(/)'
,
_
.
bind
(
this
.
searchTeams
,
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
)]
...
@@ -81,6 +82,17 @@
...
@@ -81,6 +82,17 @@
router
.
route
.
apply
(
router
,
route
);
router
.
route
.
apply
(
router
,
route
);
});
});
if
(
this
.
canEditTeam
())
{
_
.
each
([
[
'teams/:topic_id/:team_id/edit-team(/)'
,
_
.
bind
(
this
.
editTeam
,
this
)],
[
'teams/:topic_id/:team_id/edit-team/manage-members(/)'
,
_
.
bind
(
this
.
editTeamMembers
,
this
)
]
],
function
(
route
)
{
router
.
route
.
apply
(
router
,
route
);
});
}
// Create an event queue to track team changes
// Create an event queue to track team changes
this
.
teamEvents
=
_
.
clone
(
Backbone
.
Events
);
this
.
teamEvents
=
_
.
clone
(
Backbone
.
Events
);
...
@@ -245,8 +257,7 @@
...
@@ -245,8 +257,7 @@
editTeam
:
function
(
topicID
,
teamID
)
{
editTeam
:
function
(
topicID
,
teamID
)
{
var
self
=
this
,
var
self
=
this
,
editViewWithHeader
;
editViewWithHeader
;
this
.
getTopic
(
topicID
).
done
(
function
(
topic
)
{
$
.
when
(
this
.
getTopic
(
topicID
),
this
.
getTeam
(
teamID
,
false
)).
done
(
function
(
topic
,
team
)
{
self
.
getTeam
(
teamID
,
false
).
done
(
function
(
team
)
{
var
view
=
new
TeamEditView
({
var
view
=
new
TeamEditView
({
action
:
'edit'
,
action
:
'edit'
,
teamEvents
:
self
.
teamEvents
,
teamEvents
:
self
.
teamEvents
,
...
@@ -268,8 +279,31 @@
...
@@ -268,8 +279,31 @@
});
});
self
.
mainView
=
editViewWithHeader
;
self
.
mainView
=
editViewWithHeader
;
self
.
render
();
self
.
render
();
TeamAnalytics
.
emitPageViewed
(
'edit-team'
,
topicID
,
teamID
);
});
});
},
/**
*
* The backbone router entry for editing team members, using topic and team IDs.
*/
editTeamMembers
:
function
(
topicID
,
teamID
)
{
var
self
=
this
;
$
.
when
(
this
.
getTopic
(
topicID
),
this
.
getTeam
(
teamID
,
true
)).
done
(
function
(
topic
,
team
)
{
var
view
=
new
TeamMembersEditView
({
teamEvents
:
self
.
teamEvents
,
context
:
self
.
context
,
model
:
team
});
self
.
mainView
=
self
.
createViewWithHeader
({
mainView
:
view
,
title
:
gettext
(
"Membership"
),
description
:
gettext
(
"You can remove members from this team, especially if they have not participated in the team's activity."
),
topic
:
topic
,
team
:
team
}
);
self
.
render
();
TeamAnalytics
.
emitPageViewed
(
'edit-team'
,
topicID
,
teamID
);
});
});
},
},
...
@@ -372,8 +406,8 @@
...
@@ -372,8 +406,8 @@
getBrowseTeamView
:
function
(
topicID
,
teamID
)
{
getBrowseTeamView
:
function
(
topicID
,
teamID
)
{
var
self
=
this
,
var
self
=
this
,
deferred
=
$
.
Deferred
();
deferred
=
$
.
Deferred
();
self
.
getTopic
(
topicID
).
done
(
function
(
topic
)
{
self
.
getTeam
(
teamID
,
true
).
done
(
function
(
team
)
{
$
.
when
(
this
.
getTopic
(
topicID
),
this
.
getTeam
(
teamID
,
true
)).
done
(
function
(
topic
,
team
)
{
var
view
=
new
TeamProfileView
({
var
view
=
new
TeamProfileView
({
teamEvents
:
self
.
teamEvents
,
teamEvents
:
self
.
teamEvents
,
router
:
self
.
router
,
router
:
self
.
router
,
...
@@ -387,7 +421,7 @@
...
@@ -387,7 +421,7 @@
context
:
self
.
context
,
context
:
self
.
context
,
model
:
team
,
model
:
team
,
topic
:
topic
,
topic
:
topic
,
showEditButton
:
self
.
context
.
userInfo
.
privileged
||
self
.
context
.
userInfo
.
staff
showEditButton
:
self
.
canEditTeam
()
});
});
deferred
.
resolve
(
deferred
.
resolve
(
self
.
createViewWithHeader
(
self
.
createViewWithHeader
(
...
@@ -400,10 +434,13 @@
...
@@ -400,10 +434,13 @@
)
)
);
);
});
});
});
return
deferred
.
promise
();
return
deferred
.
promise
();
},
},
canEditTeam
:
function
()
{
return
this
.
context
.
userInfo
.
privileged
||
this
.
context
.
userInfo
.
staff
;
},
createBreadcrumbs
:
function
(
topic
,
team
)
{
createBreadcrumbs
:
function
(
topic
,
team
)
{
var
breadcrumbs
=
[{
var
breadcrumbs
=
[{
title
:
gettext
(
'All Topics'
),
title
:
gettext
(
'All Topics'
),
...
...
lms/djangoapps/teams/static/teams/templates/
team-activity
.underscore
→
lms/djangoapps/teams/static/teams/templates/
date
.underscore
View file @
3662fbc1
File moved
lms/djangoapps/teams/static/teams/templates/edit-team-member.underscore
0 → 100644
View file @
3662fbc1
<li class="team-member">
<a class="member-profile" href="<%= memberProfileUrl %>">
<p class="tooltip-custom"><%= username %></p>
<img class="image-url" src="<%= imageUrl %>" alt="profile page" />
</a>
<span class="date-joined"><%= dateJoined %></span>
<span>|</span>
<span class="last-active"><%= lastActive %></span>
<a class="action-remove-member" data-username="<%= username %>" href=""><%- gettext("Remove") %></a>
</li>
lms/static/js/spec/main.js
View file @
3662fbc1
...
@@ -702,6 +702,7 @@
...
@@ -702,6 +702,7 @@
'lms/include/teams/js/spec/collections/topic_collection_spec.js'
,
'lms/include/teams/js/spec/collections/topic_collection_spec.js'
,
'lms/include/teams/js/spec/teams_tab_factory_spec.js'
,
'lms/include/teams/js/spec/teams_tab_factory_spec.js'
,
'lms/include/teams/js/spec/views/edit_team_spec.js'
,
'lms/include/teams/js/spec/views/edit_team_spec.js'
,
'lms/include/teams/js/spec/views/edit_team_members_spec.js'
,
'lms/include/teams/js/spec/views/instructor_tools_spec.js'
,
'lms/include/teams/js/spec/views/instructor_tools_spec.js'
,
'lms/include/teams/js/spec/views/my_teams_spec.js'
,
'lms/include/teams/js/spec/views/my_teams_spec.js'
,
'lms/include/teams/js/spec/views/team_card_spec.js'
,
'lms/include/teams/js/spec/views/team_card_spec.js'
,
...
...
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