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
48f72612
Commit
48f72612
authored
Sep 10, 2015
by
Peter Fogg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prevent over-expansion of team memberships.
TNL-3202
parent
17e64535
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
87 additions
and
16 deletions
+87
-16
lms/djangoapps/teams/serializers.py
+2
-1
lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js
+5
-2
lms/djangoapps/teams/static/teams/js/views/team_card.js
+17
-3
lms/djangoapps/teams/tests/test_serializers.py
+54
-9
openedx/core/lib/api/fields.py
+9
-1
No files found.
lms/djangoapps/teams/serializers.py
View file @
48f72612
...
...
@@ -112,7 +112,8 @@ class MembershipSerializer(serializers.ModelSerializer):
view_name
=
'teams_detail'
,
read_only
=
True
,
),
expanded_serializer
=
CourseTeamSerializer
(
read_only
=
True
)
expanded_serializer
=
CourseTeamSerializer
(
read_only
=
True
),
exclude_expand_fields
=
{
'user'
},
)
class
Meta
(
object
):
...
...
lms/djangoapps/teams/static/teams/js/spec_helpers/team_spec_helpers.js
View file @
48f72612
...
...
@@ -68,8 +68,11 @@ define([
return
_
.
map
(
_
.
range
(
startIndex
,
stopIndex
+
1
),
function
(
i
)
{
return
{
user
:
{
'username'
:
testUser
,
'url'
:
'https://openedx.example.com/api/user/v1/accounts/'
+
testUser
username
:
testUser
,
url
:
'https://openedx.example.com/api/user/v1/accounts/'
+
testUser
,
profile_image
:
{
image_url_small
:
'test_profile_image'
}
},
team
:
teams
[
i
-
1
]
};
...
...
lms/djangoapps/teams/static/teams/js/views/team_card.js
View file @
48f72612
...
...
@@ -32,11 +32,13 @@
initialize
:
function
(
options
)
{
this
.
maxTeamSize
=
options
.
maxTeamSize
;
this
.
memberships
=
options
.
memberships
;
},
render
:
function
()
{
var
allMemberships
=
_
(
this
.
model
.
get
(
'membership'
))
.
sortBy
(
function
(
member
)
{
return
new
Date
(
member
.
last_activity_at
);}).
reverse
(),
var
allMemberships
=
_
(
this
.
memberships
).
sortBy
(
function
(
member
)
{
return
new
Date
(
member
.
last_activity_at
);
}).
reverse
(),
displayableMemberships
=
allMemberships
.
slice
(
0
,
5
),
maxMemberCount
=
this
.
maxTeamSize
;
this
.
$el
.
html
(
this
.
template
({
...
...
@@ -97,7 +99,7 @@
CardView
.
prototype
.
initialize
.
apply
(
this
,
arguments
);
// TODO: show last activity detail view
this
.
detailViews
=
[
new
TeamMembershipView
({
m
odel
:
this
.
teamModel
(),
maxTeamSize
:
this
.
maxTeamSize
}),
new
TeamMembershipView
({
m
emberships
:
this
.
getMemberships
(),
maxTeamSize
:
this
.
maxTeamSize
}),
new
TeamCountryLanguageView
({
model
:
this
.
teamModel
(),
countries
:
this
.
countries
,
...
...
@@ -105,6 +107,9 @@
}),
new
TeamActivityView
({
date
:
this
.
teamModel
().
get
(
'last_activity_at'
)})
];
this
.
model
.
on
(
'change:membership'
,
function
()
{
this
.
detailViews
[
0
].
memberships
=
this
.
getMemberships
();
},
this
);
},
teamModel
:
function
()
{
...
...
@@ -112,6 +117,15 @@
return
this
.
model
;
},
getMemberships
:
function
()
{
if
(
this
.
model
.
has
(
'team'
))
{
return
[
this
.
model
.
attributes
];
}
else
{
return
this
.
model
.
get
(
'membership'
);
}
},
configuration
:
'list_card'
,
cardClass
:
'team-card'
,
title
:
function
()
{
return
this
.
teamModel
().
get
(
'name'
);
},
...
...
lms/djangoapps/teams/tests/test_serializers.py
View file @
48f72612
...
...
@@ -3,18 +3,24 @@
Tests for custom Teams Serializers.
"""
from
django.core.paginator
import
Paginator
from
django.test.client
import
RequestFactory
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
student.tests.factories
import
CourseEnrollmentFactory
,
UserFactory
from
xmodule.modulestore.tests.django_utils
import
SharedModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
lms.djangoapps.teams.tests.factories
import
CourseTeamFactory
from
lms.djangoapps.teams.tests.factories
import
CourseTeamFactory
,
CourseTeamMembershipFactory
from
lms.djangoapps.teams.serializers
import
(
BaseTopicSerializer
,
PaginatedTopicSerializer
,
BulkTeamCountPaginatedTopicSerializer
,
TopicSerializer
,
add_team_count
BaseTopicSerializer
,
PaginatedTopicSerializer
,
BulkTeamCountPaginatedTopicSerializer
,
TopicSerializer
,
MembershipSerializer
,
add_team_count
)
class
TopicTestCase
(
ModuleStoreTestCase
):
class
SerializerTestCase
(
Shared
ModuleStoreTestCase
):
"""
Base test class to set up a course with topics
"""
...
...
@@ -22,7 +28,7 @@ class TopicTestCase(ModuleStoreTestCase):
"""
Set up a course with a teams configuration.
"""
super
(
Topic
TestCase
,
self
)
.
setUp
()
super
(
Serializer
TestCase
,
self
)
.
setUp
()
self
.
course
=
CourseFactory
.
create
(
teams_configuration
=
{
"max_team_size"
:
10
,
...
...
@@ -31,7 +37,46 @@ class TopicTestCase(ModuleStoreTestCase):
)
class
BaseTopicSerializerTestCase
(
TopicTestCase
):
class
MembershipSerializerTestCase
(
SerializerTestCase
):
"""
Tests for the membership serializer.
"""
def
setUp
(
self
):
super
(
MembershipSerializerTestCase
,
self
)
.
setUp
()
self
.
team
=
CourseTeamFactory
.
create
(
course_id
=
self
.
course
.
id
,
topic_id
=
self
.
course
.
teams_topics
[
0
][
'id'
]
)
self
.
user
=
UserFactory
.
create
()
CourseEnrollmentFactory
.
create
(
user
=
self
.
user
,
course_id
=
self
.
course
.
id
)
self
.
team_membership
=
CourseTeamMembershipFactory
.
create
(
team
=
self
.
team
,
user
=
self
.
user
)
def
test_membership_serializer_expand_user_and_team
(
self
):
"""Verify that the serializer only expands the user and team one level."""
data
=
MembershipSerializer
(
self
.
team_membership
,
context
=
{
'expand'
:
[
u'team'
,
u'user'
],
'request'
:
RequestFactory
()
.
get
(
'/api/team/v0/team_membership'
)
})
.
data
username
=
self
.
user
.
username
self
.
assertEqual
(
data
[
'user'
],
{
'url'
:
'http://testserver/api/user/v1/accounts/'
+
username
,
'username'
:
username
,
'profile_image'
:
{
'image_url_full'
:
'http://testserver/static/default_500.png'
,
'image_url_large'
:
'http://testserver/static/default_120.png'
,
'image_url_medium'
:
'http://testserver/static/default_50.png'
,
'image_url_small'
:
'http://testserver/static/default_30.png'
,
'has_image'
:
False
}
})
self
.
assertEqual
(
data
[
'team'
][
'membership'
][
0
][
'user'
],
{
'url'
:
'http://testserver/api/user/v1/accounts/'
+
username
,
'username'
:
username
})
class
BaseTopicSerializerTestCase
(
SerializerTestCase
):
"""
Tests for the `BaseTopicSerializer`, which should not serialize team count
data.
...
...
@@ -46,7 +91,7 @@ class BaseTopicSerializerTestCase(TopicTestCase):
)
class
TopicSerializerTestCase
(
Topic
TestCase
):
class
TopicSerializerTestCase
(
Serializer
TestCase
):
"""
Tests for the `TopicSerializer`, which should serialize team count data for
a single topic.
...
...
@@ -95,7 +140,7 @@ class TopicSerializerTestCase(TopicTestCase):
)
class
BasePaginatedTopicSerializerTestCase
(
Topic
TestCase
):
class
BasePaginatedTopicSerializerTestCase
(
Serializer
TestCase
):
"""
Base class for testing the two paginated topic serializers.
"""
...
...
openedx/core/lib/api/fields.py
View file @
48f72612
...
...
@@ -5,18 +5,26 @@ from rest_framework.serializers import CharField, Field
class
ExpandableField
(
Field
):
"""Field that can dynamically use a more detailed serializer based on a user-provided "expand" parameter."""
"""Field that can dynamically use a more detailed serializer based on a user-provided "expand" parameter.
Kwargs:
collapsed_serializer (Serializer): the serializer to use for a non-expanded representation.
expanded_serializer (Serializer): the serializer to use for an expanded representation.
exclude_expand_fields (set(str)): a set of fields which will not be expanded by sub-serializers.
"""
def
__init__
(
self
,
**
kwargs
):
"""Sets up the ExpandableField with the collapsed and expanded versions of the serializer."""
assert
'collapsed_serializer'
in
kwargs
and
'expanded_serializer'
in
kwargs
self
.
collapsed
=
kwargs
.
pop
(
'collapsed_serializer'
)
self
.
expanded
=
kwargs
.
pop
(
'expanded_serializer'
)
self
.
exclude_expand_fields
=
kwargs
.
pop
(
'exclude_expand_fields'
,
set
())
super
(
ExpandableField
,
self
)
.
__init__
(
**
kwargs
)
def
field_to_native
(
self
,
obj
,
field_name
):
"""Converts obj to a native representation, using the expanded serializer if the context requires it."""
if
'expand'
in
self
.
context
and
field_name
in
self
.
context
[
'expand'
]:
self
.
expanded
.
initialize
(
self
,
field_name
)
self
.
expanded
.
context
[
'expand'
]
=
list
(
set
(
self
.
expanded
.
context
[
'expand'
])
-
self
.
exclude_expand_fields
)
return
self
.
expanded
.
field_to_native
(
obj
,
field_name
)
else
:
self
.
collapsed
.
initialize
(
self
,
field_name
)
...
...
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