Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
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
course-discovery
Commits
2f956826
Commit
2f956826
authored
Feb 20, 2017
by
Waheed Ahmed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Course run mark as reviewed.
ECOM-6248
parent
0098e790
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
431 additions
and
60 deletions
+431
-60
course_discovery/apps/publisher/api/tests/test_serializers.py
+4
-3
course_discovery/apps/publisher/api/tests/test_views.py
+35
-2
course_discovery/apps/publisher/emails.py
+81
-2
course_discovery/apps/publisher/models.py
+26
-10
course_discovery/apps/publisher/tests/test_emails.py
+100
-5
course_discovery/apps/publisher/tests/test_model.py
+10
-0
course_discovery/apps/publisher/tests/test_views.py
+62
-19
course_discovery/apps/publisher/views.py
+12
-11
course_discovery/conf/locale/en/LC_MESSAGES/django.mo
+0
-0
course_discovery/conf/locale/en/LC_MESSAGES/django.po
+25
-2
course_discovery/conf/locale/en/LC_MESSAGES/djangojs.mo
+0
-0
course_discovery/conf/locale/en/LC_MESSAGES/djangojs.po
+2
-2
course_discovery/conf/locale/eo/LC_MESSAGES/django.mo
+0
-0
course_discovery/conf/locale/eo/LC_MESSAGES/django.po
+32
-2
course_discovery/conf/locale/eo/LC_MESSAGES/djangojs.mo
+0
-0
course_discovery/conf/locale/eo/LC_MESSAGES/djangojs.po
+2
-2
course_discovery/templates/publisher/email/course_run/mark_as_reviewed.html
+25
-0
course_discovery/templates/publisher/email/course_run/mark_as_reviewed.txt
+15
-0
No files found.
course_discovery/apps/publisher/api/tests/test_serializers.py
View file @
2f956826
...
...
@@ -155,13 +155,14 @@ class CourseStateSerializerTests(TestCase):
self
.
user
=
UserFactory
()
self
.
request
.
user
=
self
.
user
CourseUserRoleFactory
(
course
=
self
.
course_state
.
course
,
role
=
PublisherUserRole
.
CourseTeam
,
user
=
self
.
user
)
def
test_update
(
self
):
"""
Verify that we can update course workflow state with serializer.
"""
CourseUserRoleFactory
(
course
=
self
.
course_state
.
course
,
role
=
PublisherUserRole
.
CourseTeam
,
user
=
self
.
user
)
course
=
self
.
course_state
.
course
course
.
image
=
make_image_file
(
'test_banner.jpg'
)
course
.
save
()
...
...
course_discovery/apps/publisher/api/tests/test_views.py
View file @
2f956826
...
...
@@ -481,6 +481,9 @@ class ChangeCourseStateViewTests(TestCase):
"""
Verify that user cannot change course workflow state directly from `Draft` to `Approved`.
"""
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
CourseTeam
,
user
=
self
.
user
)
response
=
self
.
client
.
patch
(
self
.
change_state_url
,
data
=
json
.
dumps
({
'name'
:
CourseStateChoices
.
Approved
}),
...
...
@@ -576,11 +579,12 @@ class ChangeCourseRunStateViewTests(TestCase):
self
.
assertEqual
(
response
.
data
,
expected
)
def
test_
mark_as_reviewed
(
self
):
def
test_
send_for_review
(
self
):
"""
Verify that user can
mark course-run as reviewed
.
Verify that user can
change course-run workflow state and owner role will be changed to `CourseTeam`
.
"""
self
.
run_state
.
name
=
CourseRunStateChoices
.
Draft
self
.
run_state
.
owner_role
=
PublisherUserRole
.
MarketingReviewer
self
.
run_state
.
save
()
self
.
_assign_role
(
self
.
course_run
.
course
,
PublisherUserRole
.
MarketingReviewer
,
self
.
user
)
...
...
@@ -599,6 +603,7 @@ class ChangeCourseRunStateViewTests(TestCase):
course_run_state
=
CourseRunState
.
objects
.
get
(
course_run
=
self
.
course_run
)
self
.
assertEqual
(
course_run_state
.
name
,
CourseRunStateChoices
.
Review
)
self
.
assertEqual
(
course_run_state
.
owner_role
,
PublisherUserRole
.
CourseTeam
)
self
.
assertEqual
(
len
(
mail
.
outbox
),
1
)
...
...
@@ -607,3 +612,31 @@ class ChangeCourseRunStateViewTests(TestCase):
factories
.
CourseUserRoleFactory
(
course
=
course
,
role
=
role
,
user
=
user
)
def
test_mark_as_reviewed
(
self
):
"""
Verify that user can change course-run workflow state and owner role will be changed to `Publisher`.
"""
self
.
run_state
.
name
=
CourseRunStateChoices
.
Review
self
.
run_state
.
owner_role
=
PublisherUserRole
.
CourseTeam
self
.
run_state
.
save
()
self
.
_assign_role
(
self
.
course_run
.
course
,
PublisherUserRole
.
CourseTeam
,
self
.
user
)
self
.
_assign_role
(
self
.
course_run
.
course
,
PublisherUserRole
.
MarketingReviewer
,
UserFactory
())
self
.
_assign_role
(
self
.
course_run
.
course
,
PublisherUserRole
.
Publisher
,
UserFactory
())
response
=
self
.
client
.
patch
(
self
.
change_state_url
,
data
=
json
.
dumps
({
'name'
:
CourseStateChoices
.
Approved
}),
content_type
=
JSON_CONTENT_TYPE
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
run_state
=
CourseRunState
.
objects
.
get
(
course_run
=
self
.
course_run
)
self
.
assertEqual
(
self
.
run_state
.
name
,
CourseRunStateChoices
.
Approved
)
self
.
assertEqual
(
self
.
run_state
.
owner_role
,
PublisherUserRole
.
Publisher
)
self
.
assertEqual
(
len
(
mail
.
outbox
),
2
)
course_discovery/apps/publisher/emails.py
View file @
2f956826
...
...
@@ -185,7 +185,7 @@ def send_email_for_mark_as_reviewed(course, user):
logger
.
exception
(
'Failed to send email notifications mark as reviewed of course
%
s'
,
course
.
id
)
def
send_course_workflow_email
(
course
,
user
,
subject
,
txt_template
,
html_template
,
page_path
):
def
send_course_workflow_email
(
course
,
user
,
subject
,
txt_template
,
html_template
,
page_path
,
course_name
=
None
):
""" Send email for course workflow state change.
Arguments:
...
...
@@ -194,6 +194,8 @@ def send_course_workflow_email(course, user, subject, txt_template, html_templat
subject (String): Email subject
txt_template: (String): Email text template path
html_template: (String): Email html template path
page_path: (URL): Detail page url
course_name: (String): Custom course name, by default None
"""
recipient_user
=
course
.
marketing_reviewer
user_role
=
course
.
course_user_roles
.
get
(
user
=
user
)
...
...
@@ -207,7 +209,7 @@ def send_course_workflow_email(course, user, subject, txt_template, html_templat
context
=
{
'recipient_name'
:
recipient_user
.
full_name
or
recipient_user
.
username
if
recipient_user
else
''
,
'sender_name'
:
user
.
full_name
or
user
.
username
,
'course_name'
:
course
.
title
,
'course_name'
:
course
_name
if
course_name
else
course
.
title
,
'contact_us_email'
:
partner_coordinator
.
email
if
partner_coordinator
else
''
,
'page_url'
:
'https://{host}{path}'
.
format
(
host
=
Site
.
objects
.
get_current
()
.
domain
.
strip
(
'/'
),
path
=
page_path
...
...
@@ -241,3 +243,80 @@ def send_email_for_send_for_review_course_run(course_run, user):
send_course_workflow_email
(
course_run
.
course
,
user
,
subject
,
txt_template
,
html_template
,
page_path
)
except
Exception
:
# pylint: disable=broad-except
logger
.
exception
(
'Failed to send email notifications send for review of course-run
%
s'
,
course_run
.
id
)
def
send_email_for_mark_as_reviewed_course_run
(
course_run
,
user
):
""" Send email when course-run is marked as reviewed.
Arguments:
course-run (Object): CourseRun object
user (Object): User object
"""
txt_template
=
'publisher/email/course_run/mark_as_reviewed.txt'
html_template
=
'publisher/email/course_run/mark_as_reviewed.html'
run_name
=
'{pacing_type}: {start_date}'
.
format
(
pacing_type
=
course_run
.
get_pacing_type_display
(),
start_date
=
course_run
.
start
.
strftime
(
"
%
B
%
d,
%
Y"
)
)
subject
=
_
(
'Changes to {run_name} has been marked as reviewed'
)
.
format
(
run_name
=
run_name
)
# pylint: disable=no-member
try
:
page_path
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
course_run
.
id
})
send_course_workflow_email
(
course_run
.
course
,
user
,
subject
,
txt_template
,
html_template
,
page_path
,
course_name
=
run_name
)
except
Exception
:
# pylint: disable=broad-except
logger
.
exception
(
'Failed to send email notifications for mark as reviewed of course-run
%
s'
,
course_run
.
id
)
def
send_email_to_publisher
(
course_run
,
user
):
""" Send email to publisher when course-run is marked as reviewed.
Arguments:
course_run (Object): CourseRun object
user (Object): User object
"""
txt_template
=
'publisher/email/course_run/mark_as_reviewed.txt'
html_template
=
'publisher/email/course_run/mark_as_reviewed.html'
run_name
=
'{pacing_type}: {start_date}'
.
format
(
pacing_type
=
course_run
.
get_pacing_type_display
(),
start_date
=
course_run
.
start
.
strftime
(
"
%
B
%
d,
%
Y"
)
)
subject
=
_
(
'Changes to {run_name} has been marked as reviewed'
)
.
format
(
run_name
=
run_name
)
# pylint: disable=no-member
recipient_user
=
course_run
.
course
.
publisher
try
:
if
is_email_notification_enabled
(
recipient_user
):
partner_coordinator
=
course_run
.
course
.
partner_coordinator
to_addresses
=
[
recipient_user
.
email
]
from_address
=
settings
.
PUBLISHER_FROM_EMAIL
page_path
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
course_run
.
id
})
context
=
{
'recipient_name'
:
recipient_user
.
full_name
or
recipient_user
.
username
if
recipient_user
else
''
,
'sender_name'
:
user
.
full_name
or
user
.
username
,
'course_name'
:
run_name
,
'contact_us_email'
:
partner_coordinator
.
email
if
partner_coordinator
else
''
,
'page_url'
:
'https://{host}{path}'
.
format
(
host
=
Site
.
objects
.
get_current
()
.
domain
.
strip
(
'/'
),
path
=
page_path
)
}
template
=
get_template
(
txt_template
)
plain_content
=
template
.
render
(
context
)
template
=
get_template
(
html_template
)
html_content
=
template
.
render
(
context
)
email_msg
=
EmailMultiAlternatives
(
subject
,
plain_content
,
from_address
,
to_addresses
)
email_msg
.
attach_alternative
(
html_content
,
'text/html'
)
email_msg
.
send
()
except
Exception
:
# pylint: disable=broad-except
logger
.
exception
(
'Failed to send email notifications for mark as reviewed of course-run
%
s'
,
course_run
.
id
)
course_discovery/apps/publisher/models.py
View file @
2f956826
...
...
@@ -22,11 +22,8 @@ from course_discovery.apps.course_metadata.choices import CourseRunPacing
from
course_discovery.apps.course_metadata.models
import
LevelType
,
Organization
,
Person
,
Subject
from
course_discovery.apps.course_metadata.utils
import
UploadToFieldNamePath
from
course_discovery.apps.ietf_language_tags.models
import
LanguageTag
from
course_discovery.apps.publisher
import
emails
from
course_discovery.apps.publisher.choices
import
CourseRunStateChoices
,
CourseStateChoices
,
PublisherUserRole
from
course_discovery.apps.publisher.emails
import
(
send_email_for_change_state
,
send_email_for_mark_as_reviewed
,
send_email_for_send_for_review
,
send_email_for_send_for_review_course_run
)
from
course_discovery.apps.publisher.utils
import
is_email_notification_enabled
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -161,9 +158,9 @@ class Course(TimeStampedModel, ChangedByMixin):
"""
users_list_roles
=
[
obj
.
user
for
obj
in
self
.
course_user_roles
.
all
()]
emails
=
[
user
.
email
for
user
in
users_list_roles
if
is_email_notification_enabled
(
user
)]
user_
emails
=
[
user
.
email
for
user
in
users_list_roles
if
is_email_notification_enabled
(
user
)]
return
emails
return
user_
emails
@property
def
keywords_data
(
self
):
...
...
@@ -218,6 +215,13 @@ class Course(TimeStampedModel, ChangedByMixin):
return
None
@property
def
publisher
(
self
):
try
:
return
self
.
course_user_roles
.
get
(
role
=
PublisherUserRole
.
Publisher
)
.
user
except
CourseUserRole
.
DoesNotExist
:
return
None
class
CourseRun
(
TimeStampedModel
,
ChangedByMixin
):
""" Publisher CourseRun model. It contains fields related to the course run intake form."""
...
...
@@ -318,7 +322,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
self
.
state
.
save
()
if
waffle
.
switch_is_active
(
'enable_publisher_email_notifications'
):
send_email_for_change_state
(
self
)
emails
.
send_email_for_change_state
(
self
)
@property
def
current_state
(
self
):
...
...
@@ -603,13 +607,16 @@ class CourseState(TimeStampedModel, ChangedByMixin):
self
.
review
()
if
waffle
.
switch_is_active
(
'enable_publisher_email_notifications'
):
send_email_for_send_for_review
(
self
.
course
,
user
)
emails
.
send_email_for_send_for_review
(
self
.
course
,
user
)
elif
state
==
CourseStateChoices
.
Approved
:
user_role
=
self
.
course
.
course_user_roles
.
get
(
user
=
user
)
self
.
approved_by_role
=
user_role
.
role
self
.
owner_role_modified
=
timezone
.
now
()
self
.
approved
()
if
waffle
.
switch_is_active
(
'enable_publisher_email_notifications'
):
send_email_for_mark_as_reviewed
(
self
.
course
,
user
)
emails
.
send_email_for_mark_as_reviewed
(
self
.
course
,
user
)
self
.
save
()
...
...
@@ -683,10 +690,19 @@ class CourseRunState(TimeStampedModel, ChangedByMixin):
self
.
review
()
if
waffle
.
switch_is_active
(
'enable_publisher_email_notifications'
):
send_email_for_send_for_review_course_run
(
self
.
course_run
,
user
)
emails
.
send_email_for_send_for_review_course_run
(
self
.
course_run
,
user
)
elif
state
==
CourseRunStateChoices
.
Approved
:
user_role
=
self
.
course_run
.
course
.
course_user_roles
.
get
(
user
=
user
)
self
.
approved_by_role
=
user_role
.
role
self
.
owner_role
=
PublisherUserRole
.
Publisher
self
.
owner_role_modified
=
timezone
.
now
()
self
.
approved
()
if
waffle
.
switch_is_active
(
'enable_publisher_email_notifications'
):
emails
.
send_email_for_mark_as_reviewed_course_run
(
self
.
course_run
,
user
)
emails
.
send_email_to_publisher
(
self
.
course_run
,
user
)
elif
state
==
CourseRunStateChoices
.
Published
:
self
.
published
()
...
...
course_discovery/apps/publisher/tests/test_emails.py
View file @
2f956826
...
...
@@ -62,13 +62,13 @@ class StateChangeEmailTests(TestCase):
toggle_switch
(
'enable_publisher_email_notifications'
,
True
)
@mock.patch
(
'course_discovery.apps.publisher.
mode
ls.send_email_for_change_state'
)
@mock.patch
(
'course_discovery.apps.publisher.
emai
ls.send_email_for_change_state'
)
def
test_email_with_enable_waffle_switch
(
self
,
send_email_for_change_state
):
""" Verify that send_email_for_state called with enable waffle switch.. """
self
.
course_run
.
change_state
(
target
=
State
.
DRAFT
)
send_email_for_change_state
.
assert_called_once_with
(
self
.
course_run
)
@mock.patch
(
'course_discovery.apps.publisher.
mode
ls.send_email_for_change_state'
)
@mock.patch
(
'course_discovery.apps.publisher.
emai
ls.send_email_for_change_state'
)
def
test_email_with_waffle_switch_disabled
(
self
,
send_email_for_change_state
):
""" Verify that send_email_for_state not called with disable waffle switch.. """
toggle_switch
(
'enable_publisher_email_notifications'
,
False
)
...
...
@@ -309,11 +309,11 @@ class CourseMarkAsReviewedEmailTests(TestCase):
)
class
CourseRun
MarkAsReviewed
EmailTests
(
TestCase
):
""" Tests for the email functionality for
mark as reviewed
. """
class
CourseRun
SendForReview
EmailTests
(
TestCase
):
""" Tests for the email functionality for
send for review
. """
def
setUp
(
self
):
super
(
CourseRun
MarkAsReviewed
EmailTests
,
self
)
.
setUp
()
super
(
CourseRun
SendForReview
EmailTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
()
self
.
user_2
=
UserFactory
()
self
.
user_3
=
UserFactory
()
...
...
@@ -376,3 +376,98 @@ class CourseRunMarkAsReviewedEmailTests(TestCase):
page_url
=
'https://{host}{path}'
.
format
(
host
=
Site
.
objects
.
get_current
()
.
domain
.
strip
(
'/'
),
path
=
page_path
)
self
.
assertIn
(
page_url
,
body
)
self
.
assertIn
(
'are ready for your review.'
,
body
)
class
CourseRunMarkAsReviewedEmailTests
(
TestCase
):
""" Tests email functionality of mark as reviewed. """
def
setUp
(
self
):
super
(
CourseRunMarkAsReviewedEmailTests
,
self
)
.
setUp
()
self
.
user
=
UserFactory
()
self
.
user_2
=
UserFactory
()
self
.
user_3
=
UserFactory
()
self
.
seat
=
factories
.
SeatFactory
()
self
.
course_run
=
self
.
seat
.
course_run
self
.
course
=
self
.
course_run
.
course
# add user in course-user-role table
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
CourseTeam
,
user
=
self
.
user_2
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
Publisher
,
user
=
self
.
user_3
)
self
.
course_run_state
=
factories
.
CourseRunStateFactory
(
course_run
=
self
.
course_run
)
toggle_switch
(
'enable_publisher_email_notifications'
,
True
)
def
test_email_sent_by_marketing_reviewer
(
self
):
""" Verify that email works successfully."""
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
MarketingReviewer
,
user
=
self
.
user
)
emails
.
send_email_for_mark_as_reviewed_course_run
(
self
.
course_run_state
.
course_run
,
self
.
user
)
self
.
assert_email_sent
(
self
.
user_2
)
def
test_email_sent_by_course_team
(
self
):
""" Verify that email works successfully."""
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
role
=
PublisherUserRole
.
MarketingReviewer
,
user
=
self
.
user
)
emails
.
send_email_for_mark_as_reviewed_course_run
(
self
.
course_run_state
.
course_run
,
self
.
user_2
)
self
.
assert_email_sent
(
self
.
user
)
def
test_email_mark_as_reviewed_with_error
(
self
):
""" Verify that email failure log error message."""
with
LogCapture
(
emails
.
logger
.
name
)
as
l
:
emails
.
send_email_for_mark_as_reviewed_course_run
(
self
.
course_run
,
self
.
user
)
l
.
check
(
(
emails
.
logger
.
name
,
'ERROR'
,
'Failed to send email notifications for mark as reviewed of course-run {}'
.
format
(
self
.
course_run
.
id
)
)
)
def
test_email_sent_to_publisher
(
self
):
""" Verify that email works successfully."""
emails
.
send_email_to_publisher
(
self
.
course_run_state
.
course_run
,
self
.
user
)
self
.
assert_email_sent
(
self
.
user_3
)
def
test_email_to_publisher_with_error
(
self
):
""" Verify that email failure log error message."""
with
mock
.
patch
(
'django.core.mail.message.EmailMessage.send'
,
side_effect
=
TypeError
):
with
LogCapture
(
emails
.
logger
.
name
)
as
l
:
emails
.
send_email_to_publisher
(
self
.
course_run
,
self
.
user_3
)
l
.
check
(
(
emails
.
logger
.
name
,
'ERROR'
,
'Failed to send email notifications for mark as reviewed of course-run {}'
.
format
(
self
.
course_run
.
id
)
)
)
def
assert_email_sent
(
self
,
to_email
):
""" Verify the email data for tests cases."""
run_name
=
'{pacing_type}: {start_date}'
.
format
(
pacing_type
=
self
.
course_run
.
get_pacing_type_display
(),
start_date
=
self
.
course_run
.
start
.
strftime
(
"
%
B
%
d,
%
Y"
)
)
subject
=
'Changes to {run_name} has been marked as reviewed'
.
format
(
run_name
=
run_name
)
self
.
assertEqual
(
len
(
mail
.
outbox
),
1
)
self
.
assertEqual
(
to_email
.
email
,
mail
.
outbox
[
0
]
.
to
[
0
])
self
.
assertEqual
(
str
(
mail
.
outbox
[
0
]
.
subject
),
subject
)
body
=
mail
.
outbox
[
0
]
.
body
.
strip
()
page_path
=
reverse
(
'publisher:publisher_course_run_detail'
,
kwargs
=
{
'pk'
:
self
.
course_run
.
id
})
page_url
=
'https://{host}{path}'
.
format
(
host
=
Site
.
objects
.
get_current
()
.
domain
.
strip
(
'/'
),
path
=
page_path
)
self
.
assertIn
(
page_url
,
body
)
self
.
assertIn
(
'has been marked as reviewed.'
,
body
)
course_discovery/apps/publisher/tests/test_model.py
View file @
2f956826
...
...
@@ -314,6 +314,16 @@ class CourseTests(TestCase):
self
.
assertEqual
(
self
.
user1
,
self
.
course2
.
marketing_reviewer
)
def
test_publisher
(
self
):
""" Verify that the publisher property returns user if exist. """
self
.
assertIsNone
(
self
.
course2
.
publisher
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course2
,
user
=
self
.
user1
,
role
=
PublisherUserRole
.
Publisher
)
self
.
assertEqual
(
self
.
user1
,
self
.
course2
.
publisher
)
class
SeatTests
(
TestCase
):
""" Tests for the publisher `Seat` model. """
...
...
course_discovery/apps/publisher/tests/test_views.py
View file @
2f956826
...
...
@@ -1031,9 +1031,6 @@ class CourseRunDetailTests(TestCase):
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
CourseTeam
)
self
.
course_state
.
owner_role
=
PublisherUserRole
.
MarketingReviewer
self
.
course_state
.
name
=
CourseStateChoices
.
Approved
self
.
course_state
.
save
()
new_user
=
UserFactory
()
factories
.
CourseUserRoleFactory
(
...
...
@@ -1063,8 +1060,6 @@ class CourseRunDetailTests(TestCase):
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
MarketingReviewer
)
self
.
course_state
.
owner_role
=
PublisherUserRole
.
MarketingReviewer
self
.
course_state
.
save
()
new_user
=
UserFactory
()
factories
.
CourseUserRoleFactory
(
...
...
@@ -1119,6 +1114,58 @@ class CourseRunDetailTests(TestCase):
response
=
self
.
client
.
get
(
self
.
page_url
)
self
.
assertContains
(
response
,
'<div class="parent-course-approval">'
)
def
test_course_run_mark_as_reviewed
(
self
):
"""
Verify that user can see mark as reviewed button on course detail page.
"""
toggle_switch
(
'publisher_approval_widget_feature'
,
True
)
self
.
course_run_state
.
name
=
CourseRunStateChoices
.
Review
self
.
course_run_state
.
save
()
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
CourseTeam
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
UserFactory
(),
role
=
PublisherUserRole
.
MarketingReviewer
)
response
=
self
.
client
.
get
(
self
.
page_url
)
# Verify that content is sent for review and user can see `Mark as Reviewed` button.
self
.
assertContains
(
response
,
'Send for Review'
)
self
.
assertContains
(
response
,
'<span class="icon fa fa-check" aria-hidden="true">'
,
count
=
1
)
self
.
assertContains
(
response
,
'Mark as Reviewed'
)
self
.
assertContains
(
response
,
self
.
get_expected_data
(
CourseRunStateChoices
.
Approved
))
def
test_course_with_reviewed
(
self
):
"""
Verify that user can see approval widget on course detail page with `Reviewed`.
"""
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
MarketingReviewer
)
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
UserFactory
(),
role
=
PublisherUserRole
.
CourseTeam
)
# To create history objects for both `Review` and `Approved` states
self
.
course_run_state
.
name
=
CourseStateChoices
.
Review
self
.
course_run_state
.
save
()
self
.
course_run_state
.
name
=
CourseStateChoices
.
Approved
self
.
course_run_state
.
owner_role
=
PublisherUserRole
.
Publisher
self
.
course_run_state
.
approved_by_role
=
PublisherUserRole
.
CourseTeam
self
.
course_run_state
.
save
()
self
.
user
.
groups
.
add
(
self
.
organization_extension
.
group
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
organization_extension
.
group
,
self
.
organization_extension
)
response
=
self
.
client
.
get
(
self
.
page_url
)
# Verify that content is marked as reviewed and user can see Reviewed status.
self
.
assertNotContains
(
response
,
'Mark as Reviewed'
)
self
.
assertContains
(
response
,
'Reviewed'
,
count
=
1
)
self
.
assertContains
(
response
,
'<span class="icon fa fa-check" aria-hidden="true">'
,
count
=
2
)
self
.
assertContains
(
response
,
'Send for Review'
,
count
=
1
)
# pylint: disable=attribute-defined-outside-init
@ddt.ddt
...
...
@@ -1686,16 +1733,13 @@ class CourseDetailViewTests(TestCase):
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
MarketingReviewer
)
self
.
course_state
.
owner_role
=
PublisherUserRole
.
MarketingReviewer
self
.
course_state
.
name
=
CourseStateChoices
.
Review
self
.
course_state
.
save
()
new_user
=
UserFactory
()
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
new_user
,
role
=
PublisherUserRole
.
CourseTeam
course
=
self
.
course
,
user
=
UserFactory
()
,
role
=
PublisherUserRole
.
CourseTeam
)
self
.
course
.
course_state
.
name
=
CourseStateChoices
.
Review
self
.
course
.
course_state
.
save
()
self
.
user
.
groups
.
add
(
self
.
organization_extension
.
group
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
organization_extension
.
group
,
self
.
organization_extension
)
response
=
self
.
client
.
get
(
self
.
detail_page_url
)
...
...
@@ -1723,25 +1767,24 @@ class CourseDetailViewTests(TestCase):
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
self
.
user
,
role
=
PublisherUserRole
.
MarketingReviewer
)
self
.
course_state
.
owner_role
=
PublisherUserRole
.
MarketingReviewer
self
.
course_state
.
save
()
new_user
=
UserFactory
()
factories
.
CourseUserRoleFactory
(
course
=
self
.
course
,
user
=
new_user
,
role
=
PublisherUserRole
.
CourseTeam
course
=
self
.
course
,
user
=
UserFactory
()
,
role
=
PublisherUserRole
.
CourseTeam
)
# To create history objects for both `Review` and `Approved` states
self
.
course
.
course_state
.
name
=
CourseStateChoices
.
Review
self
.
course
.
course_state
.
save
()
self
.
course
.
course_state
.
name
=
CourseStateChoices
.
Approved
self
.
course
.
course_state
.
save
()
self
.
course_state
.
name
=
CourseStateChoices
.
Review
self
.
course_state
.
save
()
self
.
course_state
.
name
=
CourseStateChoices
.
Approved
self
.
course_state
.
owner_role
=
PublisherUserRole
.
Publisher
self
.
course_state
.
approved_by_role
=
PublisherUserRole
.
CourseTeam
self
.
course_state
.
save
()
self
.
user
.
groups
.
add
(
self
.
organization_extension
.
group
)
assign_perm
(
OrganizationExtension
.
VIEW_COURSE
,
self
.
organization_extension
.
group
,
self
.
organization_extension
)
response
=
self
.
client
.
get
(
self
.
detail_page_url
)
# Verify that content is
sent for review and user can see Reviewed button
.
# Verify that content is
marked as reviewed and user can see Reviewed status
.
self
.
assertNotContains
(
response
,
'Mark as Reviewed'
)
self
.
assertContains
(
response
,
'Reviewed'
,
count
=
1
)
self
.
assertContains
(
response
,
'<span class="icon fa fa-check" aria-hidden="true">'
,
count
=
2
)
...
...
course_discovery/apps/publisher/views.py
View file @
2f956826
...
...
@@ -749,18 +749,19 @@ def get_course_role_widgets_data(user, course, state_object, change_state_url):
role_widget
[
'button_disabled'
]
=
True
if
course_role
.
role
in
[
PublisherUserRole
.
CourseTeam
,
PublisherUserRole
.
MarketingReviewer
]:
if
state_object
.
owner_role
!=
course_role
.
role
:
if
state_object
.
name
!=
CourseStateChoices
.
Draft
:
history_records
=
state_object
.
history
.
filter
(
name
=
CourseStateChoices
.
Review
)
.
order_by
(
'-modified'
)
role_widget
[
'sent_for_review'
]
=
history_records
.
first
()
and
history_records
.
first
()
.
modified
if
state_object
.
name
==
CourseStateChoices
.
Approved
:
history_records
=
state_object
.
history
.
filter
(
if
state_object
.
name
==
CourseStateChoices
.
Approved
and
course_role
.
role
==
state_object
.
approved_by_role
:
history_record
=
state_object
.
history
.
filter
(
name
=
CourseStateChoices
.
Approved
)
.
order_by
(
'-modified'
)
role_widget
[
'reviewed'
]
=
history_records
.
first
()
.
modified
)
.
order_by
(
'-modified'
)
.
first
()
if
history_record
:
role_widget
[
'reviewed'
]
=
history_record
.
modified
elif
state_object
.
name
!=
CourseStateChoices
.
Draft
and
course_role
.
role
!=
state_object
.
owner_role
:
history_record
=
state_object
.
history
.
filter
(
name
=
CourseStateChoices
.
Review
)
.
order_by
(
'-modified'
)
.
first
()
if
history_record
:
role_widget
[
'sent_for_review'
]
=
history_record
.
modified
role_widgets
.
append
(
role_widget
)
...
...
course_discovery/conf/locale/en/LC_MESSAGES/django.mo
View file @
2f956826
No preview for this file type
course_discovery/conf/locale/en/LC_MESSAGES/django.po
View file @
2f956826
...
...
@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-2
0 17:52
+0500\n"
"POT-Creation-Date: 2017-02-2
1 13:08
+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: apps/api/filters.py
#, python-brace-format
...
...
@@ -495,6 +495,11 @@ msgstr ""
msgid "Changes to {title} has been approved"
msgstr ""
#: apps/publisher/emails.py
#, python-brace-format
msgid "Changes to {run_name} has been marked as reviewed"
msgstr ""
#: apps/publisher/forms.py
msgid "Remove Image"
msgstr ""
...
...
@@ -2308,6 +2313,8 @@ msgstr ""
#: templates/publisher/email/course/mark_as_reviewed.txt
#: templates/publisher/email/course/send_for_review.html
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#, python-format
...
...
@@ -2328,6 +2335,8 @@ msgstr ""
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_created.html
#: templates/publisher/email/course_created.txt
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.html
...
...
@@ -2339,6 +2348,7 @@ msgstr ""
#: templates/publisher/email/course/mark_as_reviewed.html
#: templates/publisher/email/course/send_for_review.html
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
...
...
@@ -2354,6 +2364,7 @@ msgstr ""
#: templates/publisher/email/course/mark_as_reviewed.txt
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
...
...
@@ -2411,6 +2422,18 @@ msgid ""
" in Publisher on %(date)s at %(time)s."
msgstr ""
#: templates/publisher/email/course_run/mark_as_reviewed.html
#, python-format
msgid ""
"Changes to %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s has been marked as reviewed."
msgstr ""
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#, python-format
msgid "Changes to %(course_name)s has been marked as reviewed. %(page_url)s"
msgstr ""
#: templates/publisher/email/course_run/send_for_review.html
#, python-format
msgid ""
...
...
course_discovery/conf/locale/en/LC_MESSAGES/djangojs.mo
View file @
2f956826
No preview for this file type
course_discovery/conf/locale/en/LC_MESSAGES/djangojs.po
View file @
2f956826
...
...
@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-2
0 17:52
+0500\n"
"POT-Creation-Date: 2017-02-2
1 13:08
+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
#: static/js/catalogs-change-form.js
msgid "Preview"
...
...
course_discovery/conf/locale/eo/LC_MESSAGES/django.mo
View file @
2f956826
No preview for this file type
course_discovery/conf/locale/eo/LC_MESSAGES/django.po
View file @
2f956826
...
...
@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-2
0 17:52
+0500\n"
"POT-Creation-Date: 2017-02-2
1 13:08
+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: apps/api/filters.py
...
...
@@ -614,6 +614,13 @@ msgid "Changes to {title} has been approved"
msgstr ""
"Çhängés tö {title} häs ßéén äpprövéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тє#"
#: apps/publisher/emails.py
#, python-brace-format
msgid "Changes to {run_name} has been marked as reviewed"
msgstr ""
"Çhängés tö {run_name} häs ßéén märkéd äs révïéwéd Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт "
"αмєт, ¢σηѕє¢тєтυя #"
#: apps/publisher/forms.py
msgid "Remove Image"
msgstr "Rémövé Ìmägé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
...
...
@@ -2711,6 +2718,8 @@ msgstr "Vïéw çömmént: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#: templates/publisher/email/course/mark_as_reviewed.txt
#: templates/publisher/email/course/send_for_review.html
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#, python-format
...
...
@@ -2733,6 +2742,8 @@ msgstr ""
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_created.html
#: templates/publisher/email/course_created.txt
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.html
...
...
@@ -2744,6 +2755,7 @@ msgstr "Thänks, Ⱡ'σяєм ιρѕυм #"
#: templates/publisher/email/course/mark_as_reviewed.html
#: templates/publisher/email/course/send_for_review.html
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
...
...
@@ -2763,6 +2775,7 @@ msgstr ""
#: templates/publisher/email/course/mark_as_reviewed.txt
#: templates/publisher/email/course/send_for_review.txt
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
...
...
@@ -2844,6 +2857,23 @@ msgstr ""
" ïn Püßlïshér ön %(date)s ät %(time)s. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#: templates/publisher/email/course_run/mark_as_reviewed.html
#, python-format
msgid ""
"Changes to %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s has been marked as reviewed."
msgstr ""
"Çhängés tö %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s häs ßéén märkéd äs révïéwéd. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#"
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#, python-format
msgid "Changes to %(course_name)s has been marked as reviewed. %(page_url)s"
msgstr ""
"Çhängés tö %(course_name)s häs ßéén märkéd äs révïéwéd. %(page_url)s Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: templates/publisher/email/course_run/send_for_review.html
#, python-format
msgid ""
...
...
course_discovery/conf/locale/eo/LC_MESSAGES/djangojs.mo
View file @
2f956826
No preview for this file type
course_discovery/conf/locale/eo/LC_MESSAGES/djangojs.po
View file @
2f956826
...
...
@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-2
0 17:52
+0500\n"
"POT-Creation-Date: 2017-02-2
1 13:08
+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/js/catalogs-change-form.js
...
...
course_discovery/templates/publisher/email/course_run/mark_as_reviewed.html
0 → 100644
View file @
2f956826
{% extends "publisher/email/email_base.html" %}
{% load i18n %}
{% block body %}
<!-- Message Body -->
<p>
{% blocktrans trimmed %}
Dear {{ recipient_name }},
{% endblocktrans %}
<p>
{% blocktrans with link_start='
<a
href=
"' link_middle='"
>
' link_end='
</a>
' trimmed %}
Changes to {{ link_start }}{{ page_url }}{{ link_middle }} {{ course_name }} {{ link_end }} has been marked as reviewed.
{% endblocktrans %}
</p>
{% comment %}Translators: It's closing of mail.{% endcomment %}
{% trans "Thanks," %}
<br>
{{ sender_name }}
{% blocktrans trimmed %}
<p>
Note: This email address is unable to receive replies. For questions or comments, contact {{ contact_us_email }}.
</p>
{% endblocktrans %}
<!-- End Message Body -->
{% endblock body %}
course_discovery/templates/publisher/email/course_run/mark_as_reviewed.txt
0 → 100644
View file @
2f956826
{% load i18n %}
{% blocktrans trimmed %}
Dear {{ recipient_name }},
{% endblocktrans %}
{% blocktrans trimmed %}
Changes to {{ course_name }} has been marked as reviewed. {{ page_url }}
{% endblocktrans %}
{% trans "Thanks," %}
{{ sender_name }}
{% blocktrans trimmed %}
Note: This email address is unable to receive replies. For questions or comments, contact {{ contact_us_email }}.
{% endblocktrans %}
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