Commit ab8fc07b by Peter Fogg

Merge pull request #10645 from CourseTalk/coursetalk_widget

Integration CourseTalk widgets with OpenEdx.
parents 91fd6dbe 41424383
......@@ -788,6 +788,7 @@ INSTALLED_APPS = (
'external_auth',
'student', # misleading name due to sharing with lms
'openedx.core.djangoapps.course_groups', # not used in cms (yet), but tests run
'openedx.core.djangoapps.coursetalk', # not used in cms (yet), but tests run
'xblock_config',
# Tracking
......
......@@ -269,7 +269,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
self.assertEqual(resp.status_code, 200)
def test_num_queries_instructor_paced(self):
self.fetch_course_info_with_queries(self.instructor_paced_course, 19, 4)
self.fetch_course_info_with_queries(self.instructor_paced_course, 20, 4)
def test_num_queries_self_paced(self):
self.fetch_course_info_with_queries(self.self_paced_course, 19, 4)
self.fetch_course_info_with_queries(self.self_paced_course, 20, 4)
......@@ -65,6 +65,8 @@ from courseware.user_state_client import DjangoXBlockUserStateClient
from edxmako.shortcuts import render_to_response, render_to_string, marketing_link
from instructor.enrollment import uses_shib
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.coursetalk.helpers import inject_coursetalk_keys_into_context
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
from openedx.core.djangoapps.credit.api import (
get_credit_requirement_status,
is_user_eligible_for_credit,
......@@ -97,8 +99,6 @@ from .entrance_exams import (
from .module_render import toc_for_course, get_module_for_descriptor, get_module, get_module_by_usage_id
from lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.user_api.preferences.api import get_user_preference
log = logging.getLogger("edx.courseware")
......@@ -727,6 +727,9 @@ def course_info(request, course_id):
# course is not yet visible to students.
context['disable_student_access'] = True
if CourseEnrollment.is_enrolled(request.user, course.id):
inject_coursetalk_keys_into_context(context, course_key)
return render_to_response('courseware/info.html', context)
......@@ -935,7 +938,7 @@ def course_about(request, course_id):
# Overview
overview = CourseOverview.get_from_id(course.id)
return render_to_response('courseware/course_about.html', {
context = {
'course': course,
'staff_access': staff_access,
'studio_url': studio_url,
......@@ -961,7 +964,10 @@ def course_about(request, course_id):
'cart_link': reverse('shoppingcart.views.show_cart'),
'pre_requisite_courses': pre_requisite_courses,
'course_image_urls': overview.image_urls,
})
}
inject_coursetalk_keys_into_context(context, course_key)
return render_to_response('courseware/course_about.html', context)
@transaction.non_atomic_requests
......
......@@ -1976,6 +1976,9 @@ INSTALLED_APPS = (
# Static i18n support
'statici18n',
# Review widgets
'openedx.core.djangoapps.coursetalk',
)
# Migrations which are not in the standard module "migrations"
......
......@@ -424,6 +424,11 @@
}
}
>.coursetalk-read-reviews {
margin-top: -200px;
margin-bottom: 220px;
}
header {
margin-bottom: 30px;
padding-bottom: 16px;
......
......@@ -17,7 +17,10 @@ from openedx.core.lib.courses import course_image_url
</%block>
<%block name="js_extra">
## CourseTalk widget js script
% if show_coursetalk_widget:
<script src="//d3q6qq2zt8nhwv.cloudfront.net/s/js/widgets/coursetalk-read-reviews.js"></script>
% endif
<script type="text/javascript">
(function() {
$(".register").click(function(event) {
......@@ -283,6 +286,12 @@ from openedx.core.lib.courses import course_image_url
</ol>
</section>
## CourseTalk widget
% if show_coursetalk_widget:
<div class="coursetalk-read-reviews">
<div id="ct-custom-read-review-widget" data-provider="${platform_key}" data-course="${course_review_key}"></div>
</div>
% endif
## For now, ocw links are the only thing that goes in additional resources
% if get_course_about_section(request, course, "ocw_links"):
......@@ -298,6 +307,7 @@ from openedx.core.lib.courses import course_image_url
</section>
</section>
%endif
</section>
</section>
......
......@@ -45,6 +45,10 @@ from openedx.core.djangolib.markup import Text, HTML
</%static:require_module>
<%block name="js_extra">
## CourseTalk widget js script
% if show_coursetalk_widget:
<script src="//d3q6qq2zt8nhwv.cloudfront.net/s/js/widgets/coursetalk-write-reviews.js"></script>
% endif
<script type="text/javascript" src="${static.url('js/jquery.treeview.js')}"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
......@@ -79,6 +83,13 @@ from openedx.core.djangolib.markup import Text, HTML
<h1>${_("Course Updates and News")}</h1>
${HTML(get_course_info_section(request, masquerade_user, course, 'updates'))}
## CourseTalk widget
% if show_coursetalk_widget:
<div class="coursetalk-write-reviews">
<div id="ct-custom-read-review-widget" data-provider="${platform_key}" data-course="${course_review_key}"></div>
</div>
% endif
</section>
<section aria-label="${_('Handout Navigation')}" class="handouts">
% if SelfPacedConfiguration.current().enable_course_home_improvements:
......
"""Manage coursetalk configuration. """
from django.contrib import admin
from config_models.admin import ConfigurationModelAdmin
from openedx.core.djangoapps.coursetalk.models import CourseTalkWidgetConfiguration
admin.site.register(CourseTalkWidgetConfiguration, ConfigurationModelAdmin)
"""
CourseTalk widget helpers
"""
from __future__ import unicode_literals
from openedx.core.djangoapps.coursetalk import models
def get_coursetalk_course_key(course_key):
"""
Return course key for coursetalk widget
CourseTalk unique key for a course contains only organization and course code.
:param course_key: SlashSeparatedCourseKey instance
:type course_key: SlashSeparatedCourseKey
:return: CourseTalk course key
:rtype: str
"""
return '{0.org}_{0.course}'.format(course_key)
def inject_coursetalk_keys_into_context(context, course_key):
"""
Set params to view context based on course_key and CourseTalkWidgetConfiguration
:param context: view context
:type context: dict
:param course_key: SlashSeparatedCourseKey instance
:type course_key: SlashSeparatedCourseKey
"""
show_coursetalk_widget = models.CourseTalkWidgetConfiguration.is_enabled()
if show_coursetalk_widget:
context['show_coursetalk_widget'] = True
context['platform_key'] = models.CourseTalkWidgetConfiguration.get_platform_key()
context['course_review_key'] = get_coursetalk_course_key(course_key)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='CourseTalkWidgetConfiguration',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('change_date', models.DateTimeField(auto_now_add=True, verbose_name='Change date')),
('enabled', models.BooleanField(default=False, verbose_name='Enabled')),
('platform_key', models.CharField(help_text="This key needs to associate CourseTalk reviews with your platform. Better to use domain name Ex: for 'http://edx.org' platform_key will be 'edx'", max_length=50)),
('changed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, editable=False, to=settings.AUTH_USER_MODEL, null=True, verbose_name='Changed by')),
],
options={
'ordering': ('-change_date',),
'abstract': False,
},
),
]
"""
Models for CourseTalk configurations
"""
from __future__ import unicode_literals
from django.db import models
from django.utils.translation import ugettext_lazy as _
from config_models.models import ConfigurationModel
class CourseTalkWidgetConfiguration(ConfigurationModel):
"""
This model represents Enable Configuration for CourseTalk widget.
If the setting enabled, widget will will be available on course
info page and on course about page.
"""
platform_key = models.fields.CharField(
max_length=50,
help_text=_(
"The platform key associates CourseTalk widgets with your platform. "
"Generally, it is the domain name for your platform. For example, "
"if your platform is http://edx.org, the platform key is \"edx\"."
)
)
@classmethod
def get_platform_key(cls):
"""
Return platform_key for current active configuration.
If current configuration is not enabled - return empty string
:return: Platform key
:rtype: unicode
"""
return cls.current().platform_key if cls.is_enabled() else ''
def __unicode__(self):
return 'CourseTalkWidgetConfiguration - {0}'.format(self.enabled)
""" CourseTalk widget helpers tests """
from __future__ import unicode_literals
from unittest import skipUnless
from django import test
from django.conf import settings
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from openedx.core.djangoapps.coursetalk import helpers
from openedx.core.djangoapps.coursetalk import models
@skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Tests only valid in LMS')
class CourseTalkKeyTests(test.TestCase):
"""
CourseTalkKeyTests:
tests for function get_coursetalk_course_key
tests for function inject_coursetalk_keys_into_context
"""
PLATFORM_KEY = 'some_platform'
def setUp(self):
super(CourseTalkKeyTests, self).setUp()
self.course_key = SlashSeparatedCourseKey('org', 'course', 'run')
self.context = {}
def db_set_up(self, enabled):
"""
Setup database for this test:
Create CourseTalkWidgetConfiguration
"""
config = models.CourseTalkWidgetConfiguration.current()
config.enabled = enabled
config.platform_key = self.PLATFORM_KEY
config.save()
def test_simple_key(self):
coursetalk_course_key = helpers.get_coursetalk_course_key(self.course_key)
self.assertEqual(coursetalk_course_key, 'org_course')
def test_inject_coursetalk_keys_when_widget_not_enabled(self):
self.db_set_up(False)
helpers.inject_coursetalk_keys_into_context(self.context, self.course_key)
self.assertNotIn('show_coursetalk_widget', self.context)
self.assertNotIn('platform_key', self.context)
self.assertNotIn('course_review_key', self.context)
def test_inject_coursetalk_keys_when_widget_enabled(self):
self.db_set_up(True)
helpers.inject_coursetalk_keys_into_context(self.context, self.course_key)
self.assertIn('show_coursetalk_widget', self.context)
self.assertIn('platform_key', self.context)
self.assertIn('course_review_key', self.context)
self.assertEqual(self.context.get('show_coursetalk_widget'), True)
self.assertEqual(self.context.get('platform_key'), self.PLATFORM_KEY)
self.assertEqual(self.context.get('course_review_key'), 'org_course')
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