Merge pull request #17582 from edx/MLoTurco/learner-3925-feature-view-and-template
Add EntitlementSupportView, Template, and base react element
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
const EntitlementSupportPage = () => (
|
||||
<div>
|
||||
Base Entitlement Support Page
|
||||
</div>
|
||||
);
|
||||
|
||||
export default EntitlementSupportPage;
|
||||
@@ -437,82 +437,3 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
)
|
||||
verified_mode.expiration_datetime = datetime(year=1970, month=1, day=9, tzinfo=UTC)
|
||||
verified_mode.save()
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class SupportViewCourseEntitlementsTests(SupportViewTestCase):
|
||||
""" Tests for the course entitlement support view."""
|
||||
|
||||
def setUp(self):
|
||||
super(SupportViewCourseEntitlementsTests, self).setUp()
|
||||
self.user = UserFactory(is_staff=True)
|
||||
SupportStaffRole().add_users(self.user)
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
|
||||
self.student = UserFactory.create(username='student', email='test@example.com', password='test')
|
||||
self.course_uuid = uuid4()
|
||||
|
||||
self.url = reverse('support:course_entitlement')
|
||||
|
||||
@ddt.data('username', 'email')
|
||||
def test_get_entitlements(self, search_string_type):
|
||||
CourseEntitlementFactory.create(mode=CourseMode.VERIFIED, user=self.student, course_uuid=self.course_uuid)
|
||||
url = self.url + getattr(self.student, search_string_type)
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = json.loads(response.content)
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertDictContainsSubset({
|
||||
'user': self.student.username,
|
||||
'course_uuid': unicode(self.course_uuid),
|
||||
'enrollment_course_run': None,
|
||||
'mode': CourseMode.VERIFIED,
|
||||
'support_details': []
|
||||
}, data[0])
|
||||
|
||||
def test_reinstate_entitlement(self):
|
||||
selected_run = CourseEnrollmentFactory(mode=CourseMode.VERIFIED, user=self.student)
|
||||
expired_entitlement = CourseEntitlementFactory.create(
|
||||
mode=CourseMode.VERIFIED, user=self.student, enrollment_course_run=selected_run, expired_at=datetime.now()
|
||||
)
|
||||
url = self.url + self.student.username
|
||||
response = self.client.put(url, data=json.dumps(
|
||||
{
|
||||
'entitlement_uuid': unicode(expired_entitlement.uuid),
|
||||
'reason': CourseEntitlementSupportDetail.LEAVE_SESSION
|
||||
}),
|
||||
content_type='application/json'
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data = json.loads(response.content)
|
||||
self.assertEqual(len(data['support_details']), 1)
|
||||
self.assertDictContainsSubset({
|
||||
'support_user': self.user.username,
|
||||
'reason': CourseEntitlementSupportDetail.LEAVE_SESSION,
|
||||
'comments': None,
|
||||
'unenrolled_run': unicode(selected_run.course_id)
|
||||
}, data['support_details'][0])
|
||||
|
||||
def test_create_entitlement(self):
|
||||
CourseEntitlementFactory.create(
|
||||
mode=CourseMode.VERIFIED, user=self.student, course_uuid=self.course_uuid, expired_at=datetime.now()
|
||||
)
|
||||
url = self.url + self.student.username
|
||||
response = self.client.post(
|
||||
url,
|
||||
data=json.dumps({
|
||||
'course_uuid': unicode(self.course_uuid),
|
||||
'reason': CourseEntitlementSupportDetail.LEARNER_REQUEST_NEW,
|
||||
'mode': CourseMode.VERIFIED
|
||||
}),
|
||||
content_type='application/json',
|
||||
)
|
||||
self.assertEqual(response.status_code, 201)
|
||||
data = json.loads(response.content)
|
||||
self.assertEqual(len(data['support_details']), 1)
|
||||
self.assertDictContainsSubset({
|
||||
'support_user': self.user.username,
|
||||
'reason': CourseEntitlementSupportDetail.LEARNER_REQUEST_NEW,
|
||||
'comments': None,
|
||||
'unenrolled_run': None
|
||||
}, data['support_details'][0])
|
||||
|
||||
@@ -11,21 +11,13 @@ from support.views.index import index
|
||||
from support.views.manage_user import ManageUserDetailView, ManageUserSupportView
|
||||
from support.views.refund import RefundSupportView
|
||||
|
||||
COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view({
|
||||
'get': 'list',
|
||||
'post': 'create',
|
||||
'put': 'update'
|
||||
})
|
||||
COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view()
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', index, name="index"),
|
||||
url(r'^certificates/?$', CertificatesSupportView.as_view(), name="certificates"),
|
||||
url(r'^refund/?$', RefundSupportView.as_view(), name="refund"),
|
||||
url(
|
||||
r'^course_entitlement/(?P<username_or_email>[\w.@+-]+)?$',
|
||||
COURSE_ENTITLEMENTS_VIEW,
|
||||
name="course_entitlement"
|
||||
),
|
||||
url(r'^course_entitlement/?$', COURSE_ENTITLEMENTS_VIEW, name="course_entitlement"),
|
||||
url(r'^enrollment/?$', EnrollmentSupportView.as_view(), name="enrollment"),
|
||||
url(r'^contact_us/?$', ContactUsView.as_view(), name="contact_us"),
|
||||
url(
|
||||
|
||||
@@ -6,20 +6,43 @@ from django.db import DatabaseError, transaction
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponseBadRequest
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.generic import View
|
||||
from edx_rest_framework_extensions.authentication import JwtAuthentication
|
||||
from rest_framework import permissions, status, viewsets
|
||||
from rest_framework.response import Response
|
||||
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from entitlements.api.v1.permissions import IsAdminOrAuthenticatedReadOnly
|
||||
from entitlements.api.v1.serializers import SupportCourseEntitlementSerializer
|
||||
from entitlements.models import CourseEntitlement, CourseEntitlementSupportDetail
|
||||
from lms.djangoapps.commerce.utils import EcommerceService
|
||||
from lms.djangoapps.support.decorators import require_support_permission
|
||||
from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticationCrossDomainCsrf
|
||||
|
||||
REQUIRED_CREATION_FIELDS = ['course_uuid', 'reason', 'mode']
|
||||
|
||||
|
||||
class EntitlementSupportView(viewsets.ModelViewSet):
|
||||
class EntitlementSupportView(View):
|
||||
"""
|
||||
View for viewing and changing learner enrollments, used by the
|
||||
support team.
|
||||
"""
|
||||
@method_decorator(require_support_permission)
|
||||
def get(self, request):
|
||||
"""Render the enrollment support tool view."""
|
||||
support_actions = CourseEntitlementSupportDetail.get_support_actions_list()
|
||||
|
||||
ecommerce_url = EcommerceService().get_order_dashboard_url()
|
||||
context = {
|
||||
'username': request.GET.get('user', ''),
|
||||
'uses_bootstrap': True,
|
||||
'ecommerce_url': ecommerce_url,
|
||||
'support_actions': support_actions
|
||||
}
|
||||
return render_to_response('support/entitlement.html', context)
|
||||
|
||||
|
||||
class EntitlementSupportListView(viewsets.ModelViewSet):
|
||||
"""
|
||||
Allows viewing and changing learner course entitlements, used the support team.
|
||||
"""
|
||||
|
||||
34
lms/templates/support/entitlement.html
Normal file
34
lms/templates/support/entitlement.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<%page expression_filter="h"/>
|
||||
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
from openedx.core.djangolib.js_utils import js_escaped_string
|
||||
%>
|
||||
|
||||
## Override the default styles_version to use Bootstrap
|
||||
<%! main_css = "css/bootstrap/lms-main.css" %>
|
||||
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
|
||||
<%inherit file="../main.html" />
|
||||
|
||||
<%block name="js_extra">
|
||||
</%block>
|
||||
|
||||
<%block name="pagetitle">
|
||||
${_("Entitlements")}
|
||||
</%block>
|
||||
|
||||
<%block name="content">
|
||||
<section class="container outside-app">
|
||||
${static.renderReact(
|
||||
component="EntitlementSupportPage",
|
||||
id="entitlement-support-page",
|
||||
props={
|
||||
'ecommerceUrl': ecommerce_url,
|
||||
'supportReasons': support_actions
|
||||
}
|
||||
)
|
||||
}
|
||||
</section>
|
||||
</%block>
|
||||
13
package-lock.json
generated
13
package-lock.json
generated
@@ -7981,11 +7981,10 @@
|
||||
"integrity": "sha1-eHTi04kR0nGeoncx0yRF2l7EOUw="
|
||||
},
|
||||
"react": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-15.6.2.tgz",
|
||||
"integrity": "sha1-26BDSrQ5z+gvEI8PURZjkIF5qnI=",
|
||||
"version": "16.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.1.0.tgz",
|
||||
"integrity": "sha512-hvKYlKqde2JNnNiEzORvSA0J1L7uSZ43l+J89ZNoP4EXxQrVNH0CFj8vorfPou3w+1ou1BNMBir2VVsuXtETRA==",
|
||||
"requires": {
|
||||
"create-react-class": "15.6.3",
|
||||
"fbjs": "0.8.16",
|
||||
"loose-envify": "1.3.1",
|
||||
"object-assign": "4.1.1",
|
||||
@@ -8003,9 +8002,9 @@
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "15.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.2.tgz",
|
||||
"integrity": "sha1-Qc+t9pO3V/rycIRDodH9WgK+9zA=",
|
||||
"version": "16.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.1.0.tgz",
|
||||
"integrity": "sha512-i9in5qW3H2PDinUPD9bnQK7tLAD8LhjYQ+fXi3nJOvVnxOO3ErHq6RNEnKY7pbjTPt155e74q7al8eBUuyLtew==",
|
||||
"requires": {
|
||||
"fbjs": "0.8.16",
|
||||
"loose-envify": "1.3.1",
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
"popper.js": "1.12.9",
|
||||
"prop-types": "15.6.0",
|
||||
"raw-loader": "0.5.1",
|
||||
"react": "15.6.2",
|
||||
"react-dom": "15.6.2",
|
||||
"react": "16.1.0",
|
||||
"react-dom": "16.1.0",
|
||||
"react-slick": "0.16.0",
|
||||
"requirejs": "2.3.5",
|
||||
"rtlcss": "2.2.1",
|
||||
|
||||
@@ -29,6 +29,7 @@ module.exports = {
|
||||
LearnerAnalyticsDashboard: './lms/static/js/learner_analytics_dashboard/LearnerAnalyticsDashboard.jsx',
|
||||
UpsellExperimentModal: './lms/static/common/js/components/UpsellExperimentModal.jsx',
|
||||
PortfolioExperimentUpsellModal: './lms/static/common/js/components/PortfolioExperimentUpsellModal.jsx',
|
||||
EntitlementSupportPage: './lms/djangoapps/support/static/support/jsx/entitlements/index.jsx',
|
||||
|
||||
// Learner Dashboard
|
||||
EntitlementFactory: './lms/static/js/learner_dashboard/course_entitlement_factory.js',
|
||||
|
||||
Reference in New Issue
Block a user