Commit 15bd7d7f by Waheed Ahmed

Email funtionality for `Send for Review`

ECOM-6047
parent 09a629fd
...@@ -384,12 +384,14 @@ class ChangeCourseStateViewTests(TestCase): ...@@ -384,12 +384,14 @@ class ChangeCourseStateViewTests(TestCase):
self.user = UserFactory() self.user = UserFactory()
self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME)) self.user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME))
course = self.course_state.course self.course = self.course_state.course
course.image = make_image_file('test_banner.jpg') self.course.image = make_image_file('test_banner.jpg')
course.save() self.course.save()
self.organization_extension = factories.OrganizationExtensionFactory() self.organization_extension = factories.OrganizationExtensionFactory()
course.organizations.add(self.organization_extension.organization) self.course.organizations.add(self.organization_extension.organization)
factories.UserAttributeFactory(user=self.user, enable_email_notification=True)
toggle_switch('enable_publisher_email_notifications', True)
self.change_state_url = reverse('publisher:api:change_course_state', kwargs={'pk': self.course_state.id}) self.change_state_url = reverse('publisher:api:change_course_state', kwargs={'pk': self.course_state.id})
...@@ -402,11 +404,12 @@ class ChangeCourseStateViewTests(TestCase): ...@@ -402,11 +404,12 @@ class ChangeCourseStateViewTests(TestCase):
""" """
self.assertNotEqual(self.course_state.name, CourseStateChoices.Review) self.assertNotEqual(self.course_state.name, CourseStateChoices.Review)
factories.CourseUserRoleFactory( factories.CourseUserRoleFactory(
course=self.course_state.course, role=PublisherUserRole.MarketingReviewer, user=self.user course=self.course, role=PublisherUserRole.MarketingReviewer, user=self.user
) )
course_team_user = UserFactory()
factories.CourseUserRoleFactory( factories.CourseUserRoleFactory(
course=self.course_state.course, role=PublisherUserRole.CourseTeam, user=UserFactory() course=self.course, role=PublisherUserRole.CourseTeam, user=course_team_user
) )
response = self.client.patch( response = self.client.patch(
...@@ -417,11 +420,13 @@ class ChangeCourseStateViewTests(TestCase): ...@@ -417,11 +420,13 @@ class ChangeCourseStateViewTests(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.course_state = CourseState.objects.get(course=self.course_state.course) self.course_state = CourseState.objects.get(course=self.course)
self.assertEqual(self.course_state.name, CourseStateChoices.Review) self.assertEqual(self.course_state.name, CourseStateChoices.Review)
self.assertEqual(self.course_state.owner_role, PublisherUserRole.CourseTeam) self.assertEqual(self.course_state.owner_role, PublisherUserRole.CourseTeam)
self._assert_email_sent(course_team_user)
def test_change_course_state_with_course_team(self): def test_change_course_state_with_course_team(self):
""" """
Verify that course team admin can change course workflow state Verify that course team admin can change course workflow state
...@@ -432,7 +437,12 @@ class ChangeCourseStateViewTests(TestCase): ...@@ -432,7 +437,12 @@ class ChangeCourseStateViewTests(TestCase):
self.assertNotEqual(self.course_state.name, CourseStateChoices.Review) self.assertNotEqual(self.course_state.name, CourseStateChoices.Review)
factories.CourseUserRoleFactory( factories.CourseUserRoleFactory(
course=self.course_state.course, role=PublisherUserRole.CourseTeam, user=self.user course=self.course, role=PublisherUserRole.CourseTeam, user=self.user
)
marketing_user = UserFactory()
factories.CourseUserRoleFactory(
course=self.course, role=PublisherUserRole.MarketingReviewer, user=marketing_user
) )
response = self.client.patch( response = self.client.patch(
...@@ -443,11 +453,24 @@ class ChangeCourseStateViewTests(TestCase): ...@@ -443,11 +453,24 @@ class ChangeCourseStateViewTests(TestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.course_state = CourseState.objects.get(course=self.course_state.course) self.course_state = CourseState.objects.get(course=self.course)
self.assertEqual(self.course_state.name, CourseStateChoices.Review) self.assertEqual(self.course_state.name, CourseStateChoices.Review)
self.assertEqual(self.course_state.owner_role, PublisherUserRole.MarketingReviewer) self.assertEqual(self.course_state.owner_role, PublisherUserRole.MarketingReviewer)
self._assert_email_sent(marketing_user)
def _assert_email_sent(self, user):
subject = 'Changes to {title} are ready for review'.format(title=self.course.title)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual([user.email], mail.outbox[0].to)
self.assertEqual(str(mail.outbox[0].subject), subject)
body = mail.outbox[0].body.strip()
object_path = reverse('publisher:publisher_course_detail', kwargs={'pk': self.course.id})
page_url = 'https://{host}{path}'.format(host=Site.objects.get_current().domain.strip('/'), path=object_path)
self.assertIn(page_url, body)
def test_change_course_state_with_error(self): def test_change_course_state_with_error(self):
""" """
Verify that user cannot change course workflow state directly from `Draft` to `Approved`. Verify that user cannot change course workflow state directly from `Draft` to `Approved`.
......
...@@ -146,3 +146,47 @@ def send_email_for_course_creation(course, course_run): ...@@ -146,3 +146,47 @@ def send_email_for_course_creation(course, course_run):
logger.exception( logger.exception(
'Failed to send email notifications for creation of course [%s]', course_run.course.id 'Failed to send email notifications for creation of course [%s]', course_run.course.id
) )
def send_email_for_send_for_review(course, user):
""" Send email when course is submitted for review.
Arguments:
course (Object): Course object
user (Object): User object
"""
try:
txt_template = 'publisher/email/send_for_review.txt'
html_template = 'publisher/email/send_for_review.html'
recipient_user = course.marketing_reviewer
user_role = course.course_user_roles.get(user=user)
if user_role.role == PublisherUserRole.MarketingReviewer:
recipient_user = course.course_team_admin
to_addresses = [recipient_user.email]
from_address = settings.PUBLISHER_FROM_EMAIL
page_path = reverse('publisher:publisher_course_detail', kwargs={'pk': course.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': course.title,
'course_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)
subject = _('Changes to {title} are ready for review').format(title=course.title) # pylint: disable=no-member
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 send for review of course %s', course.id)
...@@ -22,7 +22,7 @@ from course_discovery.apps.course_metadata.models import LevelType, Organization ...@@ -22,7 +22,7 @@ from course_discovery.apps.course_metadata.models import LevelType, Organization
from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath from course_discovery.apps.course_metadata.utils import UploadToFieldNamePath
from course_discovery.apps.ietf_language_tags.models import LanguageTag from course_discovery.apps.ietf_language_tags.models import LanguageTag
from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole
from course_discovery.apps.publisher.emails import send_email_for_change_state from course_discovery.apps.publisher.emails import send_email_for_change_state, send_email_for_send_for_review
from course_discovery.apps.publisher.utils import is_email_notification_enabled from course_discovery.apps.publisher.utils import is_email_notification_enabled
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -199,6 +199,13 @@ class Course(TimeStampedModel, ChangedByMixin): ...@@ -199,6 +199,13 @@ class Course(TimeStampedModel, ChangedByMixin):
organization = self.organizations.all().first() organization = self.organizations.all().first()
return organization.partner if organization else None return organization.partner if organization else None
@property
def marketing_reviewer(self):
try:
return self.course_user_roles.get(role=PublisherUserRole.MarketingReviewer).user
except CourseUserRole.DoesNotExist:
return None
class CourseRun(TimeStampedModel, ChangedByMixin): class CourseRun(TimeStampedModel, ChangedByMixin):
""" Publisher CourseRun model. It contains fields related to the course run intake form.""" """ Publisher CourseRun model. It contains fields related to the course run intake form."""
...@@ -535,6 +542,10 @@ class CourseState(TimeStampedModel, ChangedByMixin): ...@@ -535,6 +542,10 @@ class CourseState(TimeStampedModel, ChangedByMixin):
elif user_role.role == PublisherUserRole.CourseTeam: elif user_role.role == PublisherUserRole.CourseTeam:
self.owner_role = PublisherUserRole.MarketingReviewer self.owner_role = PublisherUserRole.MarketingReviewer
self.review() self.review()
if waffle.switch_is_active('enable_publisher_email_notifications'):
send_email_for_send_for_review(self.course, user)
elif state == CourseStateChoices.Approved: elif state == CourseStateChoices.Approved:
self.approved() self.approved()
......
...@@ -246,6 +246,16 @@ class CourseTests(TestCase): ...@@ -246,6 +246,16 @@ class CourseTests(TestCase):
""" Verify that the partner property returns organization partner if exist. """ """ Verify that the partner property returns organization partner if exist. """
self.assertEqual(self.course.partner, self.org_extension_1.organization.partner) self.assertEqual(self.course.partner, self.org_extension_1.organization.partner)
def test_marketing_reviewer(self):
""" Verify that the marketing_reviewer property returns user if exist. """
self.assertIsNone(self.course2.marketing_reviewer)
factories.CourseUserRoleFactory(
course=self.course2, user=self.user1, role=PublisherUserRole.MarketingReviewer
)
self.assertEqual(self.user1, self.course2.marketing_reviewer)
class SeatTests(TestCase): class SeatTests(TestCase):
""" Tests for the publisher `Seat` model. """ """ Tests for the publisher `Seat` model. """
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:02+0500\n" "POT-Creation-Date: 2017-02-13 14:47+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -493,6 +493,11 @@ msgstr "" ...@@ -493,6 +493,11 @@ msgstr ""
msgid "New Studio instance request for {title}" msgid "New Studio instance request for {title}"
msgstr "" msgstr ""
#: apps/publisher/emails.py
#, python-brace-format
msgid "Changes to {title} are ready for review"
msgstr ""
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "Remove Image" msgid "Remove Image"
msgstr "" msgstr ""
...@@ -1181,7 +1186,6 @@ msgid "Save Draft" ...@@ -1181,7 +1186,6 @@ msgid "Save Draft"
msgstr "" msgstr ""
#: templates/publisher/add_update_course_form.html #: templates/publisher/add_update_course_form.html
#: templates/publisher/course_detail.html
msgid "Course Form" msgid "Course Form"
msgstr "" msgstr ""
...@@ -1641,6 +1645,10 @@ msgstr "" ...@@ -1641,6 +1645,10 @@ msgstr ""
msgid "Courses" msgid "Courses"
msgstr "" msgstr ""
#: templates/publisher/course_detail.html
msgid "Course Detail"
msgstr ""
#: templates/publisher/course_detail.html templates/publisher/courses.html #: templates/publisher/course_detail.html templates/publisher/courses.html
#: templates/publisher/dashboard/_in_progress.html #: templates/publisher/dashboard/_in_progress.html
msgid "Institution" msgid "Institution"
...@@ -2333,6 +2341,8 @@ msgstr "" ...@@ -2333,6 +2341,8 @@ msgstr ""
#. Translators: It's closing of mail. #. Translators: It's closing of mail.
#: templates/publisher/email/course_created.html #: templates/publisher/email/course_created.html
#: templates/publisher/email/course_created.txt #: templates/publisher/email/course_created.txt
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/send_for_review.txt
#: templates/publisher/email/studio_instance_created.html #: templates/publisher/email/studio_instance_created.html
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
#: templates/publisher/email/studio_instance_needed.html #: templates/publisher/email/studio_instance_needed.html
...@@ -2353,6 +2363,45 @@ msgid "" ...@@ -2353,6 +2363,45 @@ msgid ""
" in Publisher on %(date)s at %(time)s." " in Publisher on %(date)s at %(time)s."
msgstr "" msgstr ""
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/send_for_review.txt
#, python-format
msgid "Dear %(recipient_name)s,"
msgstr ""
#: templates/publisher/email/send_for_review.html
#, python-format
msgid ""
"New changes to %(link_start)s%(course_page_url)s%(link_middle)s "
"%(course_name)s %(link_end)s are ready for your review. "
"%(link_start)s%(course_page_url)s%(link_middle)s View this course in "
"Publisher %(link_end)s to approve or decline the changes."
msgstr ""
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
msgid ""
"<p>Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s.</p>"
msgstr ""
#: templates/publisher/email/send_for_review.txt
#, python-format
msgid ""
"New changes to %(course_name)s are ready for your review. "
"%(course_page_url)s View this course in Publisher to approve or decline the "
"changes."
msgstr ""
#: templates/publisher/email/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
msgid ""
"Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s."
msgstr ""
#. Translators: course_team_name is course team member name. #. Translators: course_team_name is course team member name.
#: templates/publisher/email/studio_instance_created.html #: templates/publisher/email/studio_instance_created.html
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
...@@ -2416,13 +2465,6 @@ msgid "" ...@@ -2416,13 +2465,6 @@ msgid ""
"build your course. We recommend that you use the list early!" "build your course. We recommend that you use the list early!"
msgstr "" msgstr ""
#: templates/publisher/email/studio_instance_created.html
#, python-format
msgid ""
"<p>Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s.</p>"
msgstr ""
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
#, python-format #, python-format
msgid "" msgid ""
...@@ -2430,13 +2472,6 @@ msgid "" ...@@ -2430,13 +2472,6 @@ msgid ""
"%(course_run_page_url)s. You can now edit this course in Studio." "%(course_run_page_url)s. You can now edit this course in Studio."
msgstr "" msgstr ""
#: templates/publisher/email/studio_instance_created.txt
#, python-format
msgid ""
"Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s."
msgstr ""
#: templates/publisher/email/studio_instance_needed.html #: templates/publisher/email/studio_instance_needed.html
#: templates/publisher/email/studio_instance_needed.txt #: templates/publisher/email/studio_instance_needed.txt
msgid "Please create a Studio instance for the following course." msgid "Please create a Studio instance for the following course."
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:02+0500\n" "POT-Creation-Date: 2017-02-13 14:47+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:02+0500\n" "POT-Creation-Date: 2017-02-13 14:47+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -611,6 +611,13 @@ msgstr "" ...@@ -611,6 +611,13 @@ msgstr ""
"Néw Stüdïö ïnstänçé réqüést för {title} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " "Néw Stüdïö ïnstänçé réqüést för {title} Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєт#" "¢σηѕє¢тєт#"
#: apps/publisher/emails.py
#, python-brace-format
msgid "Changes to {title} are ready for review"
msgstr ""
"Çhängés tö {title} äré réädý för révïéw Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєт#"
#: apps/publisher/forms.py #: apps/publisher/forms.py
msgid "Remove Image" msgid "Remove Image"
msgstr "Rémövé Ìmägé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#" msgstr "Rémövé Ìmägé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
...@@ -1372,7 +1379,6 @@ msgid "Save Draft" ...@@ -1372,7 +1379,6 @@ msgid "Save Draft"
msgstr "Sävé Dräft Ⱡ'σяєм ιρѕυм ∂σłσ#" msgstr "Sävé Dräft Ⱡ'σяєм ιρѕυм ∂σłσ#"
#: templates/publisher/add_update_course_form.html #: templates/publisher/add_update_course_form.html
#: templates/publisher/course_detail.html
msgid "Course Form" msgid "Course Form"
msgstr "Çöürsé Förm Ⱡ'σяєм ιρѕυм ∂σłσя #" msgstr "Çöürsé Förm Ⱡ'σяєм ιρѕυм ∂σłσя #"
...@@ -1982,6 +1988,10 @@ msgstr "Däshßöärd Ⱡ'σяєм ιρѕυм ∂σł#" ...@@ -1982,6 +1988,10 @@ msgstr "Däshßöärd Ⱡ'σяєм ιρѕυм ∂σł#"
msgid "Courses" msgid "Courses"
msgstr "Çöürsés Ⱡ'σяєм ιρѕυм #" msgstr "Çöürsés Ⱡ'σяєм ιρѕυм #"
#: templates/publisher/course_detail.html
msgid "Course Detail"
msgstr "Çöürsé Détäïl Ⱡ'σяєм ιρѕυм ∂σłσя ѕι#"
#: templates/publisher/course_detail.html templates/publisher/courses.html #: templates/publisher/course_detail.html templates/publisher/courses.html
#: templates/publisher/dashboard/_in_progress.html #: templates/publisher/dashboard/_in_progress.html
msgid "Institution" msgid "Institution"
...@@ -2736,6 +2746,8 @@ msgstr "" ...@@ -2736,6 +2746,8 @@ msgstr ""
#. Translators: It's closing of mail. #. Translators: It's closing of mail.
#: templates/publisher/email/course_created.html #: templates/publisher/email/course_created.html
#: templates/publisher/email/course_created.txt #: templates/publisher/email/course_created.txt
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/send_for_review.txt
#: templates/publisher/email/studio_instance_created.html #: templates/publisher/email/studio_instance_created.html
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
#: templates/publisher/email/studio_instance_needed.html #: templates/publisher/email/studio_instance_needed.html
...@@ -2759,6 +2771,62 @@ msgstr "" ...@@ -2759,6 +2771,62 @@ msgstr ""
" ïn Püßlïshér ön %(date)s ät %(time)s. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, " " ïn Püßlïshér ön %(date)s ät %(time)s. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя α#" "¢σηѕє¢тєтυя α#"
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/send_for_review.txt
#, python-format
msgid "Dear %(recipient_name)s,"
msgstr "Déär %(recipient_name)s, Ⱡ'σяєм ιρѕυм ∂σł#"
#: templates/publisher/email/send_for_review.html
#, python-format
msgid ""
"New changes to %(link_start)s%(course_page_url)s%(link_middle)s "
"%(course_name)s %(link_end)s are ready for your review. "
"%(link_start)s%(course_page_url)s%(link_middle)s View this course in "
"Publisher %(link_end)s to approve or decline the changes."
msgstr ""
"Néw çhängés tö %(link_start)s%(course_page_url)s%(link_middle)s "
"%(course_name)s %(link_end)s äré réädý för ýöür révïéw. "
"%(link_start)s%(course_page_url)s%(link_middle)s Vïéw thïs çöürsé ïn "
"Püßlïshér %(link_end)s tö äpprövé ör déçlïné thé çhängés. Ⱡ'σяєм ιρѕυм ∂σłσя"
" ѕιт αмєт, ¢σηѕє¢тєтυя α∂ιριѕι¢ιηg єłιт, ѕє∂ ∂σ єιυѕмσ∂ тємρσя ιη¢ι∂ι∂υηт υт"
" łαвσяє єт ∂σłσяє мαgηα αłιqυα. υт єηιм α∂ мιηιм νєηιαм, qυιѕ ησѕтяυ∂ "
"єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ ¢σηѕєqυαт. ∂υιѕ "
"αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєłιт єѕѕє ¢ιłłυм ∂σłσяє єυ "
"ƒυgιαт ηυłłα ραяιαтυя. єχ¢єρтєυя ѕιηт σ¢¢αє¢αт ¢υρι∂αтαт ηση ρяσι∂єηт, ѕυηт "
"ιη ¢υłρα qυι σƒƒι¢ια ∂єѕєяυηт мσłłιт αηιм ι∂ єѕт łαв#"
#: templates/publisher/email/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
msgid ""
"<p>Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s.</p>"
msgstr ""
"<p>Nöté: Thïs émäïl äddréss ïs ünäßlé tö réçéïvé réplïés. För qüéstïöns ör "
"çömménts, çöntäçt %(contact_us_email)s.</p> Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: templates/publisher/email/send_for_review.txt
#, python-format
msgid ""
"New changes to %(course_name)s are ready for your review. "
"%(course_page_url)s View this course in Publisher to approve or decline the "
"changes."
msgstr ""
"Néw çhängés tö %(course_name)s äré réädý för ýöür révïéw. "
"%(course_page_url)s Vïéw thïs çöürsé ïn Püßlïshér tö äpprövé ör déçlïné thé "
"çhängés. Ⱡ'σяєм ιρѕυм ∂σł#"
#: templates/publisher/email/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
msgid ""
"Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s."
msgstr ""
"Nöté: Thïs émäïl äddréss ïs ünäßlé tö réçéïvé réplïés. För qüéstïöns ör "
"çömménts, çöntäçt %(contact_us_email)s. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#. Translators: course_team_name is course team member name. #. Translators: course_team_name is course team member name.
#: templates/publisher/email/studio_instance_created.html #: templates/publisher/email/studio_instance_created.html
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
...@@ -2850,15 +2918,6 @@ msgstr "" ...@@ -2850,15 +2918,6 @@ msgstr ""
"ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ " "ησѕтяυ∂ єχєя¢ιтαтιση υłłαм¢σ łαвσяιѕ ηιѕι υт αłιqυιρ єχ єα ¢σммσ∂σ "
"¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєł#" "¢σηѕєqυαт. ∂υιѕ αυтє ιяυяє ∂σłσя ιη яєρяєнєη∂єяιт ιη νσłυρтαтє νєł#"
#: templates/publisher/email/studio_instance_created.html
#, python-format
msgid ""
"<p>Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s.</p>"
msgstr ""
"<p>Nöté: Thïs émäïl äddréss ïs ünäßlé tö réçéïvé réplïés. För qüéstïöns ör "
"çömménts, çöntäçt %(contact_us_email)s.</p> Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт#"
#: templates/publisher/email/studio_instance_created.txt #: templates/publisher/email/studio_instance_created.txt
#, python-format #, python-format
msgid "" msgid ""
...@@ -2869,15 +2928,6 @@ msgstr "" ...@@ -2869,15 +2928,6 @@ msgstr ""
"%(course_run_page_url)s. Ýöü çän nöw édït thïs çöürsé ïn Stüdïö. Ⱡ'σяєм " "%(course_run_page_url)s. Ýöü çän nöw édït thïs çöürsé ïn Stüdïö. Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#" "ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢т#"
#: templates/publisher/email/studio_instance_created.txt
#, python-format
msgid ""
"Note: This email address is unable to receive replies. For questions or "
"comments, contact %(contact_us_email)s."
msgstr ""
"Nöté: Thïs émäïl äddréss ïs ünäßlé tö réçéïvé réplïés. För qüéstïöns ör "
"çömménts, çöntäçt %(contact_us_email)s. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#: templates/publisher/email/studio_instance_needed.html #: templates/publisher/email/studio_instance_needed.html
#: templates/publisher/email/studio_instance_needed.txt #: templates/publisher/email/studio_instance_needed.txt
msgid "Please create a Studio instance for the following course." msgid "Please create a Studio instance for the following course."
......
...@@ -7,7 +7,7 @@ msgid "" ...@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-13 14:02+0500\n" "POT-Creation-Date: 2017-02-13 14:47+0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% load staticfiles %} {% load staticfiles %}
{% block title %} {% block title %}
{% trans "Course Form" %} {% trans "Course Detail" %}
{% endblock title %} {% endblock title %}
{% block page_content %} {% block page_content %}
......
...@@ -29,7 +29,11 @@ ...@@ -29,7 +29,11 @@
<span>{{ role_widget.ownership.days }} {% trans "day in ownership" %}</span> <span>{{ role_widget.ownership.days }} {% trans "day in ownership" %}</span>
{% endif %} {% endif %}
<div class="field-readonly user-full-name"> <div class="field-readonly user-full-name">
{{ role_widget.course_role.user.full_name }} {% if role_widget.course_role.user.full_name %}
{{ role_widget.course_role.user.full_name }}
{% else %}
{{ role_widget.course_role.user.username }}
{% endif %}
</div> </div>
</div> </div>
</div> </div>
......
...@@ -15,7 +15,11 @@ ...@@ -15,7 +15,11 @@
<div class="role-assignment-container"> <div class="role-assignment-container">
<div id="userRoleContainer-{{ role_widget.user_course_role.role }}"> <div id="userRoleContainer-{{ role_widget.user_course_role.role }}">
<span id="userFullName-{{ role_widget.user_course_role.role }}" class="field-readonly user-full-name"> <span id="userFullName-{{ role_widget.user_course_role.role }}" class="field-readonly user-full-name">
{{ role_widget.user_course_role.user.full_name }} {% if role_widget.user_course_role.user.full_name %}
{{ role_widget.user_course_role.user.full_name }}
{% else %}
{{ role_widget.user_course_role.user.username }}
{% endif %}
</span> </span>
<a class="change-role-assignment" data-role="{{ role_widget.user_course_role.role }}" href="#"> <a class="change-role-assignment" data-role="{{ role_widget.user_course_role.role }}" href="#">
{% trans "change owner" %} {% trans "change owner" %}
......
{% 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 %}
New changes to {{ link_start }}{{ course_page_url }}{{ link_middle }} {{ course_name }} {{ link_end }} are ready for your review. {{ link_start }}{{ course_page_url }}{{ link_middle }} View this course in Publisher {{ link_end }} to approve or decline the changes.
{% 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 %}
{% load i18n %}
{% blocktrans trimmed %}
Dear {{ recipient_name }},
{% endblocktrans %}
{% blocktrans trimmed %}
New changes to {{ course_name }} are ready for your review. {{ course_page_url }} View this course in Publisher to approve or decline the changes.
{% 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 %}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment