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
0b78ffdf
Commit
0b78ffdf
authored
Sep 08, 2015
by
Diana Huang
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9632 from edx/diana/teams-changed-event
Add events for tracking when teams are edited.
parents
c45b8a17
8c1bf2cd
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
139 additions
and
18 deletions
+139
-18
common/djangoapps/util/model_utils.py
+33
-16
common/test/acceptance/tests/lms/test_teams.py
+50
-1
lms/djangoapps/teams/models.py
+6
-0
lms/djangoapps/teams/tests/test_views.py
+28
-1
lms/djangoapps/teams/views.py
+22
-0
No files found.
common/djangoapps/util/model_utils.py
View file @
0b78ffdf
...
...
@@ -99,18 +99,19 @@ def emit_field_changed_events(instance, user, db_table, excluded_fields=None, hi
del
instance
.
_changed_fields
def
emit_setting_changed_event
(
user
,
db_table
,
setting_name
,
old_value
,
new_value
):
"""Emits an event for a change in a setting.
def
truncate_fields
(
old_value
,
new_value
):
"""
Truncates old_value and new_value for analytics event emission if necessary.
Args:
user (User): the user that this setting is associated with.
db_table (str): the name of the table that we're modifying.
setting_name (str): the name of the setting being changed.
old_value (object): the value before the change.
new_value (object): the new value being saved.
old_value(obj): the value before the change
new_value(obj): the new value being saved
Returns:
None
a dictionary with the following fields:
'old': the truncated old value
'new': the truncated new value
'truncated': the list of fields that have been truncated
"""
# Compute the maximum value length so that two copies can fit into the maximum event size
# in addition to all the other fields recorded.
...
...
@@ -123,16 +124,32 @@ def emit_setting_changed_event(user, db_table, setting_name, old_value, new_valu
truncated_values
.
append
(
"old"
)
if
new_was_truncated
:
truncated_values
.
append
(
"new"
)
return
{
'old'
:
serialized_old_value
,
'new'
:
serialized_new_value
,
'truncated'
:
truncated_values
}
def
emit_setting_changed_event
(
user
,
db_table
,
setting_name
,
old_value
,
new_value
):
"""Emits an event for a change in a setting.
Args:
user (User): the user that this setting is associated with.
db_table (str): the name of the table that we're modifying.
setting_name (str): the name of the setting being changed.
old_value (object): the value before the change.
new_value (object): the new value being saved.
Returns:
None
"""
truncated_fields
=
truncate_fields
(
old_value
,
new_value
)
truncated_fields
[
'setting'
]
=
setting_name
truncated_fields
[
'user_id'
]
=
user
.
id
truncated_fields
[
'table'
]
=
db_table
tracker
.
emit
(
USER_SETTINGS_CHANGED_EVENT_NAME
,
{
"setting"
:
setting_name
,
"old"
:
serialized_old_value
,
"new"
:
serialized_new_value
,
"truncated"
:
truncated_values
,
"user_id"
:
user
.
id
,
"table"
:
db_table
,
}
truncated_fields
)
...
...
common/test/acceptance/tests/lms/test_teams.py
View file @
0b78ffdf
...
...
@@ -1028,6 +1028,7 @@ class EditTeamTest(TeamFormActions):
Then I should see the Edit Team button
And When I click edit team button
Then I should see the edit team page
And an analytics event should be fired
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
...
...
@@ -1041,7 +1042,55 @@ class EditTeamTest(TeamFormActions):
self
.
verify_and_navigate_to_edit_team_page
()
self
.
fill_create_or_edit_form
()
self
.
create_or_edit_team_page
.
submit_form
()
expected_events
=
[
{
'event_type'
:
'edx.team.changed'
,
'event'
:
{
'course_id'
:
self
.
course_id
,
'team_id'
:
self
.
team
[
'id'
],
'field'
:
'country'
,
'old'
:
'AF'
,
'new'
:
'PK'
,
'truncated'
:
[],
}
},
{
'event_type'
:
'edx.team.changed'
,
'event'
:
{
'course_id'
:
self
.
course_id
,
'team_id'
:
self
.
team
[
'id'
],
'field'
:
'name'
,
'old'
:
self
.
team
[
'name'
],
'new'
:
self
.
TEAMS_NAME
,
'truncated'
:
[],
}
},
{
'event_type'
:
'edx.team.changed'
,
'event'
:
{
'course_id'
:
self
.
course_id
,
'team_id'
:
self
.
team
[
'id'
],
'field'
:
'language'
,
'old'
:
'aa'
,
'new'
:
'en'
,
'truncated'
:
[],
}
},
{
'event_type'
:
'edx.team.changed'
,
'event'
:
{
'course_id'
:
self
.
course_id
,
'team_id'
:
self
.
team
[
'id'
],
'field'
:
'description'
,
'old'
:
self
.
team
[
'description'
],
'new'
:
self
.
TEAM_DESCRIPTION
,
'truncated'
:
[],
}
},
]
with
self
.
assert_events_match_during
(
event_filter
=
self
.
only_team_events
,
expected_events
=
expected_events
):
self
.
create_or_edit_team_page
.
submit_form
()
self
.
team_page
.
wait_for_page
()
...
...
lms/djangoapps/teams/models.py
View file @
0b78ffdf
...
...
@@ -4,6 +4,7 @@ from datetime import datetime
from
uuid
import
uuid4
import
pytz
from
datetime
import
datetime
from
model_utils
import
FieldTracker
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.contrib.auth.models
import
User
...
...
@@ -89,6 +90,11 @@ class CourseTeam(models.Model):
users
=
models
.
ManyToManyField
(
User
,
db_index
=
True
,
related_name
=
'teams'
,
through
=
'CourseTeamMembership'
)
team_size
=
models
.
IntegerField
(
default
=
0
,
db_index
=
True
)
# indexed for ordering
field_tracker
=
FieldTracker
()
# Don't emit changed events when these fields change.
FIELD_BLACKLIST
=
[
'last_activity_at'
,
'team_size'
]
@classmethod
def
create
(
cls
,
name
,
course_id
,
description
,
topic_id
=
None
,
country
=
None
,
language
=
None
):
"""Create a complete CourseTeam object.
...
...
lms/djangoapps/teams/tests/test_views.py
View file @
0b78ffdf
...
...
@@ -755,9 +755,12 @@ class TestDetailTeamAPI(TeamAPITestCase):
@ddt.ddt
class
TestUpdateTeamAPI
(
TeamAPITestCase
):
class
TestUpdateTeamAPI
(
EventTestMixin
,
TeamAPITestCase
):
"""Test cases for the team update endpoint."""
def
setUp
(
self
):
# pylint: disable=arguments-differ
super
(
TestUpdateTeamAPI
,
self
)
.
setUp
(
'teams.views.tracker'
)
@ddt.data
(
(
None
,
401
),
(
'student_inactive'
,
401
),
...
...
@@ -769,9 +772,19 @@ class TestUpdateTeamAPI(TeamAPITestCase):
)
@ddt.unpack
def
test_access
(
self
,
user
,
status
):
prev_name
=
self
.
solar_team
.
name
team
=
self
.
patch_team_detail
(
self
.
solar_team
.
team_id
,
status
,
{
'name'
:
'foo'
},
user
=
user
)
if
status
==
200
:
self
.
assertEquals
(
team
[
'name'
],
'foo'
)
self
.
assert_event_emitted
(
'edx.team.changed'
,
team_id
=
self
.
solar_team
.
team_id
,
course_id
=
unicode
(
self
.
solar_team
.
course_id
),
truncated
=
[],
field
=
'name'
,
old
=
prev_name
,
new
=
'foo'
)
@ddt.data
(
(
None
,
401
),
...
...
@@ -799,8 +812,22 @@ class TestUpdateTeamAPI(TeamAPITestCase):
@ddt.data
((
'country'
,
'US'
),
(
'language'
,
'en'
),
(
'foo'
,
'bar'
))
@ddt.unpack
def
test_good_requests
(
self
,
key
,
value
):
if
hasattr
(
self
.
solar_team
,
key
):
prev_value
=
getattr
(
self
.
solar_team
,
key
)
self
.
patch_team_detail
(
self
.
solar_team
.
team_id
,
200
,
{
key
:
value
},
user
=
'staff'
)
if
hasattr
(
self
.
solar_team
,
key
):
self
.
assert_event_emitted
(
'edx.team.changed'
,
team_id
=
self
.
solar_team
.
team_id
,
course_id
=
unicode
(
self
.
solar_team
.
course_id
),
truncated
=
[],
field
=
key
,
old
=
prev_value
,
new
=
value
)
def
test_does_not_exist
(
self
):
self
.
patch_team_detail
(
'no_such_team'
,
404
,
user
=
'staff'
)
...
...
lms/djangoapps/teams/views.py
View file @
0b78ffdf
...
...
@@ -16,6 +16,8 @@ from rest_framework.authentication import (
from
rest_framework
import
status
from
rest_framework
import
permissions
from
django.db.models
import
Count
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.contrib.auth.models
import
User
from
django_countries
import
countries
from
django.utils.translation
import
ugettext
as
_
...
...
@@ -40,6 +42,7 @@ from student.models import CourseEnrollment, CourseAccessRole
from
student.roles
import
CourseStaffRole
from
django_comment_client.utils
import
has_discussion_privileges
from
teams
import
is_feature_enabled
from
util.model_utils
import
truncate_fields
from
.models
import
CourseTeam
,
CourseTeamMembership
from
.serializers
import
(
CourseTeamSerializer
,
...
...
@@ -59,6 +62,25 @@ TOPICS_PER_PAGE = 12
MAXIMUM_SEARCH_SIZE
=
100000
@receiver
(
post_save
,
sender
=
CourseTeam
)
def
team_post_save_callback
(
sender
,
instance
,
**
kwargs
):
# pylint: disable=unused-argument
""" Emits signal after the team is saved. """
changed_fields
=
instance
.
field_tracker
.
changed
()
# Don't emit events when we are first creating the team.
if
not
kwargs
[
'created'
]:
for
field
in
changed_fields
:
if
field
not
in
instance
.
FIELD_BLACKLIST
:
truncated_fields
=
truncate_fields
(
unicode
(
changed_fields
[
field
]),
unicode
(
getattr
(
instance
,
field
)))
truncated_fields
[
'team_id'
]
=
instance
.
team_id
truncated_fields
[
'course_id'
]
=
unicode
(
instance
.
course_id
)
truncated_fields
[
'field'
]
=
field
tracker
.
emit
(
'edx.team.changed'
,
truncated_fields
)
class
TeamsDashboardView
(
View
):
"""
View methods related to the teams dashboard.
...
...
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