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
e5c8acb6
Unverified
Commit
e5c8acb6
authored
Oct 20, 2017
by
Tyler Hallada
Committed by
Gabe Mulley
Nov 01, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow communication experiences to be customized per-learner
parent
908d5f91
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
54 additions
and
2 deletions
+54
-2
openedx/core/djangoapps/schedules/admin.py
+5
-0
openedx/core/djangoapps/schedules/migrations/0006_scheduleexperience.py
+22
-0
openedx/core/djangoapps/schedules/models.py
+18
-0
openedx/core/djangoapps/schedules/resolvers.py
+9
-2
No files found.
openedx/core/djangoapps/schedules/admin.py
View file @
e5c8acb6
...
@@ -4,12 +4,17 @@ from django.utils.translation import ugettext_lazy as _
...
@@ -4,12 +4,17 @@ from django.utils.translation import ugettext_lazy as _
from
.
import
models
from
.
import
models
class
ScheduleExperienceAdminInline
(
admin
.
StackedInline
):
model
=
models
.
ScheduleExperience
@admin.register
(
models
.
Schedule
)
@admin.register
(
models
.
Schedule
)
class
ScheduleAdmin
(
admin
.
ModelAdmin
):
class
ScheduleAdmin
(
admin
.
ModelAdmin
):
list_display
=
(
'username'
,
'course_id'
,
'active'
,
'start'
,
'upgrade_deadline'
)
list_display
=
(
'username'
,
'course_id'
,
'active'
,
'start'
,
'upgrade_deadline'
)
raw_id_fields
=
(
'enrollment'
,)
raw_id_fields
=
(
'enrollment'
,)
readonly_fields
=
(
'modified'
,)
readonly_fields
=
(
'modified'
,)
search_fields
=
(
'enrollment__user__username'
,
'enrollment__course_id'
,)
search_fields
=
(
'enrollment__user__username'
,
'enrollment__course_id'
,)
inlines
=
(
ScheduleExperienceAdminInline
,)
def
username
(
self
,
obj
):
def
username
(
self
,
obj
):
return
obj
.
enrollment
.
user
.
username
return
obj
.
enrollment
.
user
.
username
...
...
openedx/core/djangoapps/schedules/migrations/0006_scheduleexperience.py
0 → 100644
View file @
e5c8acb6
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'schedules'
,
'0005_auto_20171010_1722'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'ScheduleExperience'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
verbose_name
=
'ID'
,
serialize
=
False
,
auto_created
=
True
,
primary_key
=
True
)),
(
'experience_type'
,
models
.
IntegerField
(
default
=
0
,
choices
=
[(
0
,
b
'Recurring Nudge and Upgrade Reminder'
),
(
1
,
b
'Course Updates'
)])),
(
'schedule'
,
models
.
OneToOneField
(
related_name
=
'experience'
,
to
=
'schedules.Schedule'
)),
],
),
]
openedx/core/djangoapps/schedules/models.py
View file @
e5c8acb6
...
@@ -6,6 +6,13 @@ from model_utils.models import TimeStampedModel
...
@@ -6,6 +6,13 @@ from model_utils.models import TimeStampedModel
from
config_models.models
import
ConfigurationModel
from
config_models.models
import
ConfigurationModel
EXPERIENCE_TYPES
=
(
(
0
,
'Recurring Nudge and Upgrade Reminder'
),
(
1
,
'Course Updates'
),
)
DEFAULT_EXPERIENCE_TYPE
=
EXPERIENCE_TYPES
[
0
][
0
]
class
Schedule
(
TimeStampedModel
):
class
Schedule
(
TimeStampedModel
):
enrollment
=
models
.
OneToOneField
(
'student.CourseEnrollment'
,
null
=
False
)
enrollment
=
models
.
OneToOneField
(
'student.CourseEnrollment'
,
null
=
False
)
active
=
models
.
BooleanField
(
active
=
models
.
BooleanField
(
...
@@ -23,6 +30,12 @@ class Schedule(TimeStampedModel):
...
@@ -23,6 +30,12 @@ class Schedule(TimeStampedModel):
help_text
=
_
(
'Deadline by which the learner must upgrade to a verified seat'
)
help_text
=
_
(
'Deadline by which the learner must upgrade to a verified seat'
)
)
)
def
get_experience_type
(
self
):
if
(
hasattr
(
self
,
'experience'
)):
return
self
.
experience
.
experience_type
else
:
return
DEFAULT_EXPERIENCE_TYPE
class
Meta
(
object
):
class
Meta
(
object
):
verbose_name
=
_
(
'Schedule'
)
verbose_name
=
_
(
'Schedule'
)
verbose_name_plural
=
_
(
'Schedules'
)
verbose_name_plural
=
_
(
'Schedules'
)
...
@@ -39,3 +52,8 @@ class ScheduleConfig(ConfigurationModel):
...
@@ -39,3 +52,8 @@ class ScheduleConfig(ConfigurationModel):
deliver_upgrade_reminder
=
models
.
BooleanField
(
default
=
False
)
deliver_upgrade_reminder
=
models
.
BooleanField
(
default
=
False
)
enqueue_course_update
=
models
.
BooleanField
(
default
=
False
)
enqueue_course_update
=
models
.
BooleanField
(
default
=
False
)
deliver_course_update
=
models
.
BooleanField
(
default
=
False
)
deliver_course_update
=
models
.
BooleanField
(
default
=
False
)
class
ScheduleExperience
(
models
.
Model
):
schedule
=
models
.
OneToOneField
(
Schedule
,
related_name
=
'experience'
)
experience_type
=
models
.
IntegerField
(
choices
=
EXPERIENCE_TYPES
,
default
=
DEFAULT_EXPERIENCE_TYPE
)
openedx/core/djangoapps/schedules/resolvers.py
View file @
e5c8acb6
...
@@ -18,7 +18,7 @@ from courseware.date_summary import verified_upgrade_deadline_link, verified_upg
...
@@ -18,7 +18,7 @@ from courseware.date_summary import verified_upgrade_deadline_link, verified_upg
from
openedx.core.djangoapps.monitoring_utils
import
function_trace
,
set_custom_metric
from
openedx.core.djangoapps.monitoring_utils
import
function_trace
,
set_custom_metric
from
openedx.core.djangoapps.schedules.config
import
COURSE_UPDATE_WAFFLE_FLAG
from
openedx.core.djangoapps.schedules.config
import
COURSE_UPDATE_WAFFLE_FLAG
from
openedx.core.djangoapps.schedules.exceptions
import
CourseUpdateDoesNotExist
from
openedx.core.djangoapps.schedules.exceptions
import
CourseUpdateDoesNotExist
from
openedx.core.djangoapps.schedules.models
import
Schedule
from
openedx.core.djangoapps.schedules.models
import
DEFAULT_EXPERIENCE_TYPE
,
EXPERIENCE_TYPES
,
Schedule
from
openedx.core.djangoapps.schedules.utils
import
PrefixedDebugLoggerMixin
from
openedx.core.djangoapps.schedules.utils
import
PrefixedDebugLoggerMixin
from
openedx.core.djangoapps.schedules.template_context
import
(
from
openedx.core.djangoapps.schedules.template_context
import
(
absolute_url
,
absolute_url
,
...
@@ -64,6 +64,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
...
@@ -64,6 +64,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
relative to. For example, if this resolver finds schedules that started 7 days ago
relative to. For example, if this resolver finds schedules that started 7 days ago
this variable should be set to "start".
this variable should be set to "start".
num_bins -- the int number of bins to split the users into
num_bins -- the int number of bins to split the users into
experience_type -- the string name for the experience type that users will be filtered to
"""
"""
async_send_task
=
attr
.
ib
()
async_send_task
=
attr
.
ib
()
site
=
attr
.
ib
()
site
=
attr
.
ib
()
...
@@ -74,6 +75,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
...
@@ -74,6 +75,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
schedule_date_field
=
None
schedule_date_field
=
None
num_bins
=
DEFAULT_NUM_BINS
num_bins
=
DEFAULT_NUM_BINS
experience_type
=
DEFAULT_EXPERIENCE_TYPE
def
__attrs_post_init__
(
self
):
def
__attrs_post_init__
(
self
):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
...
@@ -123,10 +125,14 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
...
@@ -123,10 +125,14 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
'enrollment__user__profile'
,
'enrollment__user__profile'
,
'enrollment__course'
,
'enrollment__course'
,
)
.
prefetch_related
(
)
.
prefetch_related
(
'enrollment__course__modes'
'enrollment__course__modes'
,
'experience'
,
)
.
filter
(
)
.
filter
(
Q
(
enrollment__course__end__isnull
=
True
)
|
Q
(
Q
(
enrollment__course__end__isnull
=
True
)
|
Q
(
enrollment__course__end__gte
=
self
.
current_datetime
),
enrollment__course__end__gte
=
self
.
current_datetime
),
Q
(
experience__isnull
=
True
)
|
Q
(
experience__experience_type
=
self
.
experience_type
)
if
self
.
experience_type
==
DEFAULT_EXPERIENCE_TYPE
else
Q
(
experience__isnull
=
False
)
&
Q
(
experience__experience_type
=
self
.
experience_type
),
enrollment__user__in
=
users
,
enrollment__user__in
=
users
,
enrollment__is_active
=
True
,
enrollment__is_active
=
True
,
**
schedule_day_equals_target_day_filter
**
schedule_day_equals_target_day_filter
...
@@ -333,6 +339,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
...
@@ -333,6 +339,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
log_prefix
=
'Course Update'
log_prefix
=
'Course Update'
schedule_date_field
=
'start'
schedule_date_field
=
'start'
num_bins
=
COURSE_UPDATE_NUM_BINS
num_bins
=
COURSE_UPDATE_NUM_BINS
experience_type
=
EXPERIENCE_TYPES
[
1
][
0
]
def
schedules_for_bin
(
self
):
def
schedules_for_bin
(
self
):
week_num
=
abs
(
self
.
day_offset
)
/
7
week_num
=
abs
(
self
.
day_offset
)
/
7
...
...
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