Commit ed75b9b5 by Waheed Ahmed

Added publish button.

ECOM-6078
parent 5b2c8f3e
......@@ -672,3 +672,37 @@ class ChangeCourseRunStateViewTests(TestCase):
self.assertEqual(len(mail.outbox), 1)
self.assertEqual([course.publisher.email, course.project_coordinator.email], mail.outbox[0].bcc)
def test_course_published(self):
"""
Verify that publisher user can publish course run.
"""
course = self.course_run.course
self.run_state.name = CourseRunStateChoices.Approved
self.run_state.preview_accepted = True
self.run_state.save()
self._assign_role(course, PublisherUserRole.Publisher, self.user)
self._assign_role(course, PublisherUserRole.CourseTeam, UserFactory())
response = self.client.patch(
self.change_state_url,
data=json.dumps({'name': CourseRunStateChoices.Published}),
content_type=JSON_CONTENT_TYPE
)
self.assertEqual(response.status_code, 200)
self.run_state = CourseRunState.objects.get(course_run=self.course_run)
self.assertTrue(self.run_state.is_published)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual([course.course_team_admin.email], mail.outbox[0].to)
course_name = '{title}: {pacing_type} - {start_date}'.format(
title=course.title,
pacing_type=self.course_run.get_pacing_type_display(),
start_date=self.course_run.start.strftime("%B %d, %Y")
)
expected_subject = 'Course {course_name} is now live'.format(course_name=course_name)
self.assertEqual(str(mail.outbox[0].subject), expected_subject)
......@@ -372,3 +372,53 @@ def send_email_preview_page_is_available(course_run):
except Exception: # pylint: disable=broad-except
logger.exception('Failed to send email notifications for preview available of course-run %s', course_run.id)
def send_course_run_published_email(course_run):
""" Send course run published email.
Arguments:
course_run (Object): CourseRun object
"""
txt_template = 'publisher/email/course_run/published.txt'
html_template = 'publisher/email/course_run/published.html'
course_name = '{title}: {pacing_type} - {start_date}'.format(
title=course_run.course.title,
pacing_type=course_run.get_pacing_type_display(),
start_date=course_run.start.strftime("%B %d, %Y")
)
subject = _('Course {course_name} is now live').format(course_name=course_name) # pylint: disable=no-member
course_team_user = course_run.course.course_team_admin
try:
if is_email_notification_enabled(course_team_user):
to_addresses = [course_team_user.email]
from_address = settings.PUBLISHER_FROM_EMAIL
project_coordinator = course_run.course.project_coordinator
page_path = reverse('publisher:publisher_course_run_detail', kwargs={'pk': course_run.id})
context = {
'course_name': course_name,
'recipient_name': course_team_user.get_full_name() or course_team_user.username,
'contact_us_email': project_coordinator.email if project_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=to_addresses
)
email_msg.attach_alternative(html_content, 'text/html')
email_msg.send()
except Exception: # pylint: disable=broad-except
error_message = 'Failed to send email notifications for course published of course-run [{run_id}]'.format(
run_id=course_run.id
)
logger.exception(error_message)
raise Exception(error_message)
......@@ -578,8 +578,7 @@ class CourseRunState(TimeStampedModel, ChangedByMixin):
@transition(field=name, source=CourseRunStateChoices.Approved, target=CourseRunStateChoices.Published)
def published(self):
# TODO: send email etc.
pass
emails.send_course_run_published_email(self.course_run)
def change_state(self, state, user):
if state == CourseRunStateChoices.Draft:
......@@ -627,6 +626,14 @@ class CourseRunState(TimeStampedModel, ChangedByMixin):
def is_approved(self):
return self.name == CourseRunStateChoices.Approved
@property
def is_ready_to_publish(self):
return self.is_approved and self.is_preview_accepted
@property
def is_published(self):
return self.name == CourseRunStateChoices.Published
class PublisherUser(User):
""" Publisher User Proxy Model. """
......
......@@ -455,3 +455,58 @@ class CourseRunPreviewEmailTests(TestCase):
)
)
)
class CourseRunPublishedEmailTests(TestCase):
"""
Tests email functionality for course run published.
"""
def setUp(self):
super(CourseRunPublishedEmailTests, self).setUp()
self.user = UserFactory()
self.run_state = factories.CourseRunStateFactory()
self.course_run = self.run_state.course_run
self.course = self.course_run.course
# add users in CourseUserRole table
factories.CourseUserRoleFactory(
course=self.course, role=PublisherUserRole.CourseTeam, user=self.user
)
factories.CourseUserRoleFactory(
course=self.course, role=PublisherUserRole.Publisher, user=UserFactory()
)
toggle_switch('enable_publisher_email_notifications', True)
def test_course_published_email(self):
"""
Verify that course published email functionality works fine.
"""
emails.send_course_run_published_email(self.course_run)
course_name = '{title}: {pacing_type} - {start_date}'.format(
title=self.course.title,
pacing_type=self.course_run.get_pacing_type_display(),
start_date=self.course_run.start.strftime("%B %d, %Y")
)
subject = 'Course {course_name} is now live'.format(course_name=course_name)
self.assertEqual(len(mail.outbox), 1)
self.assertEqual([self.course.course_team_admin.email], mail.outbox[0].to)
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('is now live.', body)
def test_course_published_email_with_error(self):
""" Verify that email failure log error message."""
message = 'Failed to send email notifications for course published of course-run [{}]'.format(
self.course_run.id
)
with mock.patch('django.core.mail.message.EmailMessage.send', side_effect=TypeError):
with self.assertRaises(Exception) as ex:
emails.send_course_run_published_email(self.course_run)
self.assertEqual(str(ex.exception), message)
......@@ -546,6 +546,8 @@ class CourseRunStateTests(TestCase):
self.course.course_state.name = CourseStateChoices.Approved
self.course.save()
self.course_run.staff.add(PersonFactory())
self.course_run_state.preview_accepted = False
self.course_run_state.save()
self.assertTrue(self.course_run_state.can_send_for_review())
def test_str(self):
......@@ -644,3 +646,22 @@ class CourseRunStateTests(TestCase):
self.course_run_state.name = CourseRunStateChoices.Approved
self.course_run_state.save()
self.assertTrue(self.course_run_state.is_approved)
def test_is_ready_to_publish(self):
"""
Verify that method return is_ready_to_publish status.
"""
self.assertFalse(self.course_run_state.is_ready_to_publish)
self.course_run_state.name = CourseRunStateChoices.Approved
self.course_run_state.preview_accepted = True
self.course_run_state.save()
self.assertTrue(self.course_run_state.is_ready_to_publish)
def test_is_published(self):
"""
Verify that method return is_published status.
"""
self.assertFalse(self.course_run_state.is_published)
self.course_run_state.name = CourseRunStateChoices.Published
self.course_run_state.save()
self.assertTrue(self.course_run_state.is_published)
......@@ -1071,6 +1071,48 @@ class CourseRunDetailTests(TestCase):
)
self.assertContains(response, '<input id="id-review-url" type="text">')
def test_course_publish_button(self):
"""Verify that publisher user can see Publish button."""
user_role = factories.CourseUserRoleFactory(
course=self.course, user=self.user, role=PublisherUserRole.Publisher
)
self.course_run_state.owner_role = PublisherUserRole.Publisher
self.course_run_state.name = CourseRunStateChoices.Approved
self.course_run_state.preview_accepted = True
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)
self.assertContains(response, '<button class="btn-brand btn-base btn-publish"')
user_role.role = PublisherUserRole.CourseTeam
user_role.save()
response = self.client.get(self.page_url)
# Verify that course team user cannot se publish button.
self.assertNotContains(response, '<button class="btn-brand btn-base btn-publish"')
def test_course_published(self):
"""Verify that user can see Published status if course is published."""
self.course_run_state.name = CourseRunStateChoices.Published
self.course_run_state.preview_accepted = True
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)
history_object = self.course_run_state.history.filter(
name=CourseRunStateChoices.Published
).order_by('-modified').first()
expected = 'Course run announced on {publish_date} - view it on edx.org at:'.format(
publish_date=history_object.modified.strftime('%m/%d/%y')
)
self.assertContains(response, expected)
self.assertNotContains(response, '<button class="btn-brand btn-base btn-publish"')
# pylint: disable=attribute-defined-outside-init
@ddt.ddt
......
......@@ -139,6 +139,12 @@ class CourseRunDetailView(mixins.LoginRequiredMixin, mixins.PublisherPermissionM
history_object = course_run_state.history.filter(preview_accepted=True).order_by('-modified').first()
if history_object:
context['preview_accepted_date'] = history_object.modified
if course_run_state.is_published:
history_object = course_run_state.history.filter(
name=CourseRunStateChoices.Published
).order_by('-modified').first()
if history_object:
context['publish_date'] = history_object.modified
context['breadcrumbs'] = make_bread_crumbs(
[
......@@ -157,6 +163,7 @@ class CourseRunDetailView(mixins.LoginRequiredMixin, mixins.PublisherPermissionM
context['publisher_hide_features_for_pilot'] = waffle.switch_is_active('publisher_hide_features_for_pilot')
context['publisher_comment_widget_feature'] = waffle.switch_is_active('publisher_comment_widget_feature')
context['publisher_approval_widget_feature'] = waffle.switch_is_active('publisher_approval_widget_feature')
context['publish_state_name'] = CourseRunStateChoices.Published
return context
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-01 16:02+0500\n"
"POT-Creation-Date: 2017-03-02 12:51+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
......@@ -511,6 +511,11 @@ msgstr ""
msgid "Preview for {run_name} is available"
msgstr ""
#: apps/publisher/emails.py
#, python-brace-format
msgid "Course {course_name} is now live"
msgstr ""
#: apps/publisher/forms.py
msgid "Remove Image"
msgstr ""
......@@ -2022,6 +2027,12 @@ msgid "Course Run Detail"
msgstr ""
#: templates/publisher/course_run_detail.html
#, python-format
msgid ""
"Course run announced on %(course_publish_date)s - view it on edx.org at:"
msgstr ""
#: templates/publisher/course_run_detail.html
msgid "All"
msgstr ""
......@@ -2345,6 +2356,10 @@ msgid "Accept"
msgstr ""
#: templates/publisher/course_run_detail/_widgets.html
msgid "Publish"
msgstr ""
#: templates/publisher/course_run_detail/_widgets.html
msgid "Submitted for review"
msgstr ""
......@@ -2482,6 +2497,8 @@ msgstr ""
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/decline_preview.html
#: templates/publisher/email/decline_preview.txt
msgid "The edX team"
......@@ -2515,6 +2532,8 @@ msgstr ""
#: 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/published.html
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#, python-format
......@@ -2541,6 +2560,8 @@ msgstr ""
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/published.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
......@@ -2555,6 +2576,7 @@ msgstr ""
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/preview_accepted.html
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
......@@ -2573,6 +2595,7 @@ msgstr ""
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
......@@ -2674,6 +2697,18 @@ msgstr ""
msgid "Preview for %(course_name)s is available for review. %(page_url)s"
msgstr ""
#: templates/publisher/email/course_run/published.html
#, python-format
msgid ""
"Your course %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s is now live."
msgstr ""
#: templates/publisher/email/course_run/published.txt
#, python-format
msgid "Your course %(course_name)s is now live. %(page_url)s"
msgstr ""
#: templates/publisher/email/course_run/send_for_review.html
#, python-format
msgid ""
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-01 16:02+0500\n"
"POT-Creation-Date: 2017-03-02 12:51+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"
......@@ -33,6 +33,10 @@ msgid "Something went wrong!"
msgstr ""
#: static/js/publisher/publisher.js
msgid "Something went wrong! please try again later."
msgstr ""
#: static/js/publisher/publisher.js
msgid "File must be smaller than 1 megabyte in size."
msgstr ""
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-01 16:02+0500\n"
"POT-Creation-Date: 2017-03-02 12:51+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
......@@ -633,6 +633,11 @@ msgid "Preview for {run_name} is available"
msgstr ""
"Prévïéw för {run_name} ïs äväïläßlé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢#"
#: apps/publisher/emails.py
#, python-brace-format
msgid "Course {course_name} is now live"
msgstr "Çöürsé {course_name} ïs nöw lïvé Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢#"
#: apps/publisher/forms.py
msgid "Remove Image"
msgstr "Rémövé Ìmägé Ⱡ'σяєм ιρѕυм ∂σłσя ѕ#"
......@@ -2470,6 +2475,14 @@ msgid "Course Run Detail"
msgstr "Çöürsé Rün Détäïl Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмє#"
#: templates/publisher/course_run_detail.html
#, python-format
msgid ""
"Course run announced on %(course_publish_date)s - view it on edx.org at:"
msgstr ""
"Çöürsé rün ännöünçéd ön %(course_publish_date)s - vïéw ït ön édx.örg ät: "
"Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя α#"
#: templates/publisher/course_run_detail.html
msgid "All"
msgstr "Àll Ⱡ'σяєм#"
......@@ -2801,6 +2814,10 @@ msgid "Accept"
msgstr "Àççépt Ⱡ'σяєм ιρѕυ#"
#: templates/publisher/course_run_detail/_widgets.html
msgid "Publish"
msgstr "Püßlïsh Ⱡ'σяєм ιρѕυм #"
#: templates/publisher/course_run_detail/_widgets.html
msgid "Submitted for review"
msgstr "Süßmïttéd för révïéw Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
......@@ -2957,6 +2974,8 @@ msgstr "Vïéw Çöürsé Ⱡ'σяєм ιρѕυм ∂σłσя #"
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/decline_preview.html
#: templates/publisher/email/decline_preview.txt
msgid "The edX team"
......@@ -2992,6 +3011,8 @@ msgstr "Vïéw çömmént: Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт#"
#: 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/published.html
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/course_run/send_for_review.txt
#, python-format
......@@ -3020,6 +3041,8 @@ msgstr ""
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/published.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
......@@ -3034,6 +3057,7 @@ msgstr "Thänks, Ⱡ'σяєм ιρѕυм #"
#: templates/publisher/email/course_run/mark_as_reviewed.html
#: templates/publisher/email/course_run/preview_accepted.html
#: templates/publisher/email/course_run/preview_available.html
#: templates/publisher/email/course_run/published.html
#: templates/publisher/email/course_run/send_for_review.html
#: templates/publisher/email/studio_instance_created.html
#, python-format
......@@ -3056,6 +3080,7 @@ msgstr ""
#: templates/publisher/email/course_run/mark_as_reviewed.txt
#: templates/publisher/email/course_run/preview_accepted.txt
#: templates/publisher/email/course_run/preview_available.txt
#: templates/publisher/email/course_run/published.txt
#: templates/publisher/email/course_run/send_for_review.txt
#: templates/publisher/email/studio_instance_created.txt
#, python-format
......@@ -3196,6 +3221,22 @@ msgstr ""
"Prévïéw för %(course_name)s ïs äväïläßlé för révïéw. %(page_url)s Ⱡ'σяєм "
"ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: templates/publisher/email/course_run/published.html
#, python-format
msgid ""
"Your course %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s is now live."
msgstr ""
"Ýöür çöürsé %(link_start)s%(page_url)s%(link_middle)s %(course_name)s "
"%(link_end)s ïs nöw lïvé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, ¢σηѕє¢тєтυя #"
#: templates/publisher/email/course_run/published.txt
#, python-format
msgid "Your course %(course_name)s is now live. %(page_url)s"
msgstr ""
"Ýöür çöürsé %(course_name)s ïs nöw lïvé. %(page_url)s Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт"
" αмєт, ¢σηѕє¢тє#"
#: templates/publisher/email/course_run/send_for_review.html
#, python-format
msgid ""
......
......@@ -7,14 +7,14 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-01 16:02+0500\n"
"POT-Creation-Date: 2017-03-02 12:51+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
......@@ -34,6 +34,12 @@ msgid "Something went wrong!"
msgstr "Söméthïng wént wröng! Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, #"
#: static/js/publisher/publisher.js
msgid "Something went wrong! please try again later."
msgstr ""
"Söméthïng wént wröng! pléäsé trý ägäïn lätér. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
"¢σηѕє¢тєтυя #"
#: static/js/publisher/publisher.js
msgid "File must be smaller than 1 megabyte in size."
msgstr ""
"Fïlé müst ßé smällér thän 1 mégäßýté ïn sïzé. Ⱡ'σяєм ιρѕυм ∂σłσя ѕιт αмєт, "
......
......@@ -132,7 +132,7 @@ $(document).ready(function(){
});
$('.btn-change-state').click(function (e) {
$('.btn-change-state, .btn-publish').click(function (e) {
$.ajax({
type: "PATCH",
url: $(this).data('change-state-url'),
......@@ -142,7 +142,11 @@ $(document).ready(function(){
location.reload();
},
error: function (response) {
$('#stateChangeError').html(response.responseJSON.name);
if (response.responseJSON) {
$('#stateChangeError').html(response.responseJSON.name);
} else {
$('#stateChangeError').html(gettext('Something went wrong! please try again later.'));
}
$('#stateChangeAlert').show();
console.log(response);
}
......
......@@ -51,3 +51,12 @@
border-color: #169BD5;
border-radius: 5px;
}
.btn-publish {
@include padding(5px, 30px, 5px, 30px);
@include float(right);
background-color: #169BD5;
border-color: #169BD5;
border-radius: 5px;
margin-top: 10px;
}
......@@ -621,3 +621,10 @@
color: red;
}
}
.published-status {
@include text-align(center);
padding-top: 20px;
padding-bottom: 20px;
font-size: 14px;
}
{% load i18n %}
<div class="approval-widget">
<div class="margin-top20">
<h5 class="hd-5 emphasized approvals-heading">{% trans "APPROVALS" %}</h5>
</div>
<h5 class="hd-5 emphasized approvals-heading">{% trans "APPROVALS" %}</h5>
{% if is_course_run and not object.course.course_state.is_approved %}
<div class="parent-course-approval">
{% url 'publisher:publisher_course_detail' object.course.id as course_url %}
......
......@@ -11,6 +11,16 @@
{% block page_content %}
<div class="layout-1t2t layout-flush publisher-container course-detail">
<main class="layout-col layout-col-b layout-col-b-custom">
{% if object.course_run_state.is_published %}
<div class="depth depth-0 published-status">
<strong>
{% blocktrans with publish_date|date:'m/d/y' as course_publish_date trimmed %}
Course run announced on {{ course_publish_date }} - view it on edx.org at:
{% endblocktrans %}
</strong>
<a href="{{ object.preview_url }}" target="_blank">{{ object.preview_url }}</a>
</div>
{% endif %}
<nav class="administration-nav">
<div class="tab-container">
{% if can_view_all_tabs %}
......@@ -35,6 +45,14 @@
{% include 'alert_messages.html' %}
<div id="stateChangeAlert" class="alert-messages hidden">
<div class="alert alert-error" role="alert" tabindex="-1">
<div>
<p id="stateChangeError" class="alert-copy"></p>
</div>
</div>
</div>
<div class="tabs">
<div id="tab-1" class="tab-content active">
{% include 'publisher/course_run_detail/_all.html' %}
......
......@@ -28,6 +28,11 @@
{% trans "Approved" %}<br>
{{ preview_accepted_date|date:'m/d/y H:i a' }}
</span>
{% if object.course_run_state.is_ready_to_publish and object.course.publisher == request.user %}
<button class="btn-brand btn-base btn-publish" data-change-state-url="{% url 'publisher:api:change_course_run_state' object.course_run_state.id %}" data-state-name="{{ publish_state_name }}" type="button">
{% trans "Publish" %}
</button>
{% endif %}
{% elif object.course.publisher == request.user %}
<span class="preview-status">{% trans "Submitted for review" %}</span>
<button data-url="{% url 'publisher:api:update_course_run' object.id %}" class="btn btn-neutral btn-edit-preview-url">{% trans "Edit" %}</button>
......
{% 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 %}
Your course {{ link_start }}{{ page_url }}{{ link_middle }} {{ course_name }} {{ link_end }} is now live.
{% endblocktrans %}
</p>
{% comment %}Translators: It's closing of mail.{% endcomment %}
{% trans "Thanks," %}<br>
{% trans "The edX team" %}
{% 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 %}
Your course {{ course_name }} is now live. {{ page_url }}
{% endblocktrans %}
{% trans "Thanks," %}
{% trans "The edX team" %}
{% 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