Commit 69ae314d by Anthony Mangano

enable users to select course when making support requests

ECOM-5936
parent b8befaf7
...@@ -11,8 +11,10 @@ from util import views ...@@ -11,8 +11,10 @@ from util import views
from zendesk import ZendeskError from zendesk import ZendeskError
import json import json
import mock import mock
from ddt import ddt, data, unpack
from student.tests.test_configuration_overrides import fake_get_value from student.tests.test_configuration_overrides import fake_get_value
from student.tests.factories import CourseEnrollmentFactory
def fake_support_backend_values(name, default=None): # pylint: disable=unused-argument def fake_support_backend_values(name, default=None): # pylint: disable=unused-argument
...@@ -26,8 +28,9 @@ def fake_support_backend_values(name, default=None): # pylint: disable=unused-a ...@@ -26,8 +28,9 @@ def fake_support_backend_values(name, default=None): # pylint: disable=unused-a
return config_dict[name] return config_dict[name]
@ddt
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": True}) @mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": True})
@override_settings(ZENDESK_URL="dummy", ZENDESK_USER="dummy", ZENDESK_API_KEY="dummy") @override_settings(ZENDESK_URL="dummy", ZENDESK_USER="dummy", ZENDESK_API_KEY="dummy", ZENDESK_CUSTOM_FIELDS={})
@mock.patch("util.views.dog_stats_api") @mock.patch("util.views.dog_stats_api")
@mock.patch("util.views._ZendeskApi", autospec=True) @mock.patch("util.views._ZendeskApi", autospec=True)
class SubmitFeedbackTest(TestCase): class SubmitFeedbackTest(TestCase):
...@@ -44,14 +47,12 @@ class SubmitFeedbackTest(TestCase): ...@@ -44,14 +47,12 @@ class SubmitFeedbackTest(TestCase):
username="test", username="test",
profile__name="Test User" profile__name="Test User"
) )
# This contains issue_type and course_id to ensure that tags are submitted correctly
self._anon_fields = { self._anon_fields = {
"email": "test@edx.org", "email": "test@edx.org",
"name": "Test User", "name": "Test User",
"subject": "a subject", "subject": "a subject",
"details": "some details", "details": "some details",
"issue_type": "test_issue", "issue_type": "test_issue"
"course_id": "test_course"
} }
# This does not contain issue_type nor course_id to ensure that they are optional # This does not contain issue_type nor course_id to ensure that they are optional
self._auth_fields = {"subject": "a subject", "details": "some details"} self._auth_fields = {"subject": "a subject", "details": "some details"}
...@@ -130,13 +131,9 @@ class SubmitFeedbackTest(TestCase): ...@@ -130,13 +131,9 @@ class SubmitFeedbackTest(TestCase):
resp = self._build_and_run_request(user, fields) resp = self._build_and_run_request(user, fields)
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
def _assert_datadog_called(self, datadog_mock, with_tags): def _assert_datadog_called(self, datadog_mock, tags):
expected_datadog_calls = [ """Assert that datadog was called with the correct tags."""
mock.call.increment( expected_datadog_calls = [mock.call.increment(views.DATADOG_FEEDBACK_METRIC, tags=tags)]
views.DATADOG_FEEDBACK_METRIC,
tags=(["course_id:test_course", "issue_type:test_issue"] if with_tags else [])
)
]
self.assertEqual(datadog_mock.mock_calls, expected_datadog_calls) self.assertEqual(datadog_mock.mock_calls, expected_datadog_calls)
def test_bad_request_anon_user_no_name(self, zendesk_mock_class, datadog_mock): def test_bad_request_anon_user_no_name(self, zendesk_mock_class, datadog_mock):
...@@ -184,7 +181,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -184,7 +181,7 @@ class SubmitFeedbackTest(TestCase):
"requester": {"name": "Test User", "email": "test@edx.org"}, "requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject", "subject": "a subject",
"comment": {"body": "some details"}, "comment": {"body": "some details"},
"tags": ["test_course", "test_issue", "LMS"] "tags": ["test_issue", "LMS"]
} }
} }
), ),
...@@ -206,7 +203,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -206,7 +203,7 @@ class SubmitFeedbackTest(TestCase):
) )
] ]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls) self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=True) self._assert_datadog_called(datadog_mock, ["issue_type:test_issue"])
@mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_get_value) @mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_get_value)
def test_valid_request_anon_user_configuration_override(self, zendesk_mock_class, datadog_mock): def test_valid_request_anon_user_configuration_override(self, zendesk_mock_class, datadog_mock):
...@@ -228,7 +225,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -228,7 +225,7 @@ class SubmitFeedbackTest(TestCase):
"requester": {"name": "Test User", "email": "test@edx.org"}, "requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject", "subject": "a subject",
"comment": {"body": "some details"}, "comment": {"body": "some details"},
"tags": ["test_course", "test_issue", "LMS", "whitelabel_fakeorg"] "tags": ["test_issue", "LMS", "whitelabel_fakeorg"]
} }
} }
), ),
...@@ -250,7 +247,69 @@ class SubmitFeedbackTest(TestCase): ...@@ -250,7 +247,69 @@ class SubmitFeedbackTest(TestCase):
) )
] ]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls) self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=True) self._assert_datadog_called(datadog_mock, ["issue_type:test_issue"])
@data("course-v1:testOrg+testCourseNumber+testCourseRun", "", None)
@override_settings(ZENDESK_CUSTOM_FIELDS={"course_id": 1234, "enrollment_mode": 5678})
def test_valid_request_anon_user_with_custom_fields(self, course_id, zendesk_mock, datadog_mock):
"""
Test a valid request from an anonymous user when configured to use Zendesk Custom Fields.
The response should have a 200 (success) status code, and a ticket with
the given information should have been submitted via the Zendesk API. When course_id is
present, it should be sent to Zendesk via a custom field. When course_id is blank or missing,
the request should still be processed successfully.
"""
zendesk_mock_instance = zendesk_mock.return_value
zendesk_mock_instance.create_ticket.return_value = 42
fields = self._anon_fields.copy()
expected_zendesk_tags = None
expected_datadog_tags = None
if course_id is not None:
fields["course_id"] = course_id
expected_zendesk_tags = [course_id, "test_issue", "LMS"]
expected_datadog_tags = ["course_id:{}".format(course_id), "issue_type:test_issue"]
else:
expected_zendesk_tags = ["test_issue", "LMS"]
expected_datadog_tags = ["issue_type:test_issue"]
expected_create_ticket_request = {
"ticket": {
"recipient": "registration@example.com",
"requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject",
"comment": {"body": "some details"},
"tags": expected_zendesk_tags
}
}
expected_update_ticket_request = {
"ticket": {
"comment": {
"public": False,
"body":
"Additional information:\n\n"
"Client IP: 1.2.3.4\n"
"Host: test_server\n"
"Page: test_referer\n"
"Browser: test_user_agent"
}
}
}
if fields.get("course_id"):
expected_custom_fields = [{"id": 1234, "value": fields["course_id"]}]
expected_create_ticket_request["ticket"]["custom_fields"] = expected_custom_fields
self._test_success(self._anon_user, fields)
expected_zendesk_calls = [
mock.call.create_ticket(expected_create_ticket_request),
mock.call.update_ticket(42, expected_update_ticket_request)
]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, expected_datadog_tags)
def test_bad_request_auth_user_no_subject(self, zendesk_mock_class, datadog_mock): def test_bad_request_auth_user_no_subject(self, zendesk_mock_class, datadog_mock):
"""Test a request from an authenticated user not specifying `subject`.""" """Test a request from an authenticated user not specifying `subject`."""
...@@ -303,7 +362,85 @@ class SubmitFeedbackTest(TestCase): ...@@ -303,7 +362,85 @@ class SubmitFeedbackTest(TestCase):
) )
] ]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls) self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=False) self._assert_datadog_called(datadog_mock, [])
@data(
("course-v1:testOrg+testCourseNumber+testCourseRun", True),
("course-v1:testOrg+testCourseNumber+testCourseRun", False),
("", None),
(None, None)
)
@unpack
@override_settings(ZENDESK_CUSTOM_FIELDS={"course_id": 1234, "enrollment_mode": 5678})
def test_valid_request_auth_user_with_custom_fields(self, course_id, enrollment_state, zendesk_mock, datadog_mock):
"""
Test a valid request from an authenticated user when configured to use Zendesk Custom Fields.
The response should have a 200 (success) status code, and a ticket with
the given information should have been submitted via the Zendesk API. When course_id is
present, it should be sent to Zendesk via a custom field, along with the enrollment mode
if the user has an active enrollment for that course. When course_id is blank or missing,
the request should still be processed successfully.
"""
zendesk_mock_instance = zendesk_mock.return_value
zendesk_mock_instance.create_ticket.return_value = 42
fields = self._auth_fields.copy()
expected_zendesk_tags = None
expected_datadog_tags = None
if course_id is not None:
fields["course_id"] = course_id
expected_zendesk_tags = [course_id, "LMS"]
expected_datadog_tags = ["course_id:{}".format(course_id)]
else:
expected_zendesk_tags = ["LMS"]
expected_datadog_tags = []
expected_create_ticket_request = {
"ticket": {
"recipient": "registration@example.com",
"requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject",
"comment": {"body": "some details"},
"tags": expected_zendesk_tags
}
}
expected_update_ticket_request = {
"ticket": {
"comment": {
"public": False,
"body":
"Additional information:\n\n"
"username: test\n"
"Client IP: 1.2.3.4\n"
"Host: test_server\n"
"Page: test_referer\n"
"Browser: test_user_agent",
}
}
}
if fields.get("course_id"):
expected_custom_fields = [{"id": 1234, "value": fields["course_id"]}]
if enrollment_state is not None:
enrollment = CourseEnrollmentFactory.create(
user=self._auth_user,
course_id=course_id,
is_active=enrollment_state
)
if enrollment.is_active:
expected_custom_fields.append({"id": 5678, "value": enrollment.mode})
expected_create_ticket_request["ticket"]["custom_fields"] = expected_custom_fields
self._test_success(self._auth_user, fields)
expected_zendesk_calls = [
mock.call.create_ticket(expected_create_ticket_request),
mock.call.update_ticket(42, expected_update_ticket_request)
]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, expected_datadog_tags)
def test_get_request(self, zendesk_mock_class, datadog_mock): def test_get_request(self, zendesk_mock_class, datadog_mock):
"""Test that a GET results in a 405 even with all required fields""" """Test that a GET results in a 405 even with all required fields"""
...@@ -329,7 +466,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -329,7 +466,7 @@ class SubmitFeedbackTest(TestCase):
resp = self._build_and_run_request(self._anon_user, self._anon_fields) resp = self._build_and_run_request(self._anon_user, self._anon_fields)
self.assertEqual(resp.status_code, 500) self.assertEqual(resp.status_code, 500)
self.assertFalse(resp.content) self.assertFalse(resp.content)
self._assert_datadog_called(datadog_mock, with_tags=True) self._assert_datadog_called(datadog_mock, ["issue_type:test_issue"])
def test_zendesk_error_on_update(self, zendesk_mock_class, datadog_mock): def test_zendesk_error_on_update(self, zendesk_mock_class, datadog_mock):
""" """
...@@ -344,7 +481,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -344,7 +481,7 @@ class SubmitFeedbackTest(TestCase):
zendesk_mock_instance.update_ticket.side_effect = err zendesk_mock_instance.update_ticket.side_effect = err
resp = self._build_and_run_request(self._anon_user, self._anon_fields) resp = self._build_and_run_request(self._anon_user, self._anon_fields)
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
self._assert_datadog_called(datadog_mock, with_tags=True) self._assert_datadog_called(datadog_mock, ["issue_type:test_issue"])
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False}) @mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
def test_not_enabled(self, zendesk_mock_class, datadog_mock): def test_not_enabled(self, zendesk_mock_class, datadog_mock):
......
...@@ -25,6 +25,7 @@ from edxmako.shortcuts import render_to_response, render_to_string ...@@ -25,6 +25,7 @@ from edxmako.shortcuts import render_to_response, render_to_string
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
import track.views import track.views
from student.roles import GlobalStaff from student.roles import GlobalStaff
from student.models import CourseEnrollment
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -222,6 +223,40 @@ class _ZendeskApi(object): ...@@ -222,6 +223,40 @@ class _ZendeskApi(object):
return None return None
def _get_zendesk_custom_field_context(request):
"""
Construct a dictionary of data that can be stored in Zendesk custom fields.
"""
context = {}
course_id = request.POST.get("course_id")
if not course_id:
return context
context["course_id"] = course_id
if not request.user.is_authenticated():
return context
enrollment = CourseEnrollment.get_enrollment(request.user, CourseKey.from_string(course_id))
if enrollment and enrollment.is_active:
context["enrollment_mode"] = enrollment.mode
return context
def _format_zendesk_custom_fields(context):
"""
Format the data in `context` for compatibility with the Zendesk API.
Ignore any keys that have not been configured in `ZENDESK_CUSTOM_FIELDS`.
"""
custom_fields = []
for key, val, in settings.ZENDESK_CUSTOM_FIELDS.items():
if key in context:
custom_fields.append({"id": val, "value": context[key]})
return custom_fields
def _record_feedback_in_zendesk( def _record_feedback_in_zendesk(
realname, realname,
email, email,
...@@ -231,7 +266,8 @@ def _record_feedback_in_zendesk( ...@@ -231,7 +266,8 @@ def _record_feedback_in_zendesk(
additional_info, additional_info,
group_name=None, group_name=None,
require_update=False, require_update=False,
support_email=None support_email=None,
custom_fields=None
): ):
""" """
Create a new user-requested Zendesk ticket. Create a new user-requested Zendesk ticket.
...@@ -246,6 +282,8 @@ def _record_feedback_in_zendesk( ...@@ -246,6 +282,8 @@ def _record_feedback_in_zendesk(
If `require_update` is provided, returns False when the update does not If `require_update` is provided, returns False when the update does not
succeed. This allows using the private comment to add necessary information succeed. This allows using the private comment to add necessary information
which the user will not see in followup emails from support. which the user will not see in followup emails from support.
If `custom_fields` is provided, submits data to those fields in Zendesk.
""" """
zendesk_api = _ZendeskApi() zendesk_api = _ZendeskApi()
...@@ -271,6 +309,10 @@ def _record_feedback_in_zendesk( ...@@ -271,6 +309,10 @@ def _record_feedback_in_zendesk(
"tags": zendesk_tags "tags": zendesk_tags
} }
} }
if custom_fields:
new_ticket["ticket"]["custom_fields"] = custom_fields
group = None group = None
if group_name is not None: if group_name is not None:
group = zendesk_api.get_group(group_name) group = zendesk_api.get_group(group_name)
...@@ -412,6 +454,11 @@ def submit_feedback(request): ...@@ -412,6 +454,11 @@ def submit_feedback(request):
if not settings.ZENDESK_URL or not settings.ZENDESK_USER or not settings.ZENDESK_API_KEY: if not settings.ZENDESK_URL or not settings.ZENDESK_USER or not settings.ZENDESK_API_KEY:
raise Exception("Zendesk enabled but not configured") raise Exception("Zendesk enabled but not configured")
custom_fields = None
if settings.ZENDESK_CUSTOM_FIELDS:
custom_field_context = _get_zendesk_custom_field_context(request)
custom_fields = _format_zendesk_custom_fields(custom_field_context)
success = _record_feedback_in_zendesk( success = _record_feedback_in_zendesk(
context["realname"], context["realname"],
context["email"], context["email"],
...@@ -419,7 +466,8 @@ def submit_feedback(request): ...@@ -419,7 +466,8 @@ def submit_feedback(request):
context["details"], context["details"],
context["tags"], context["tags"],
context["additional_info"], context["additional_info"],
support_email=context["support_email"] support_email=context["support_email"],
custom_fields=custom_fields
) )
_record_feedback_in_datadog(context["tags"]) _record_feedback_in_datadog(context["tags"])
......
...@@ -333,6 +333,8 @@ COMMENTS_SERVICE_URL = ENV_TOKENS.get("COMMENTS_SERVICE_URL", '') ...@@ -333,6 +333,8 @@ COMMENTS_SERVICE_URL = ENV_TOKENS.get("COMMENTS_SERVICE_URL", '')
COMMENTS_SERVICE_KEY = ENV_TOKENS.get("COMMENTS_SERVICE_KEY", '') COMMENTS_SERVICE_KEY = ENV_TOKENS.get("COMMENTS_SERVICE_KEY", '')
CERT_QUEUE = ENV_TOKENS.get("CERT_QUEUE", 'test-pull') CERT_QUEUE = ENV_TOKENS.get("CERT_QUEUE", 'test-pull')
ZENDESK_URL = ENV_TOKENS.get('ZENDESK_URL', ZENDESK_URL) ZENDESK_URL = ENV_TOKENS.get('ZENDESK_URL', ZENDESK_URL)
ZENDESK_CUSTOM_FIELDS = ENV_TOKENS.get('ZENDESK_CUSTOM_FIELDS', ZENDESK_CUSTOM_FIELDS)
FEEDBACK_SUBMISSION_EMAIL = ENV_TOKENS.get("FEEDBACK_SUBMISSION_EMAIL") FEEDBACK_SUBMISSION_EMAIL = ENV_TOKENS.get("FEEDBACK_SUBMISSION_EMAIL")
MKTG_URLS = ENV_TOKENS.get('MKTG_URLS', MKTG_URLS) MKTG_URLS = ENV_TOKENS.get('MKTG_URLS', MKTG_URLS)
......
...@@ -1003,6 +1003,7 @@ FEEDBACK_SUBMISSION_EMAIL = None ...@@ -1003,6 +1003,7 @@ FEEDBACK_SUBMISSION_EMAIL = None
ZENDESK_URL = None ZENDESK_URL = None
ZENDESK_USER = None ZENDESK_USER = None
ZENDESK_API_KEY = None ZENDESK_API_KEY = None
ZENDESK_CUSTOM_FIELDS = {}
##### EMBARGO ##### ##### EMBARGO #####
EMBARGO_SITE_REDIRECT_URL = None EMBARGO_SITE_REDIRECT_URL = None
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
@import 'shared/modal'; @import 'shared/modal';
@import 'shared/activation_messages'; @import 'shared/activation_messages';
@import 'shared/unsubscribe'; @import 'shared/unsubscribe';
@import 'shared/help-tab';
// shared - platform // shared - platform
@import 'multicourse/home'; @import 'multicourse/home';
......
...@@ -78,3 +78,9 @@ ...@@ -78,3 +78,9 @@
padding: 0 $baseline $baseline; padding: 0 $baseline $baseline;
} }
} }
.feedback-form-select {
background: $white;
margin-bottom: $baseline;
width: 100%;
}
.feedback-form-select {
background: $white;
margin-bottom: $baseline;
width: 100%;
}
...@@ -99,15 +99,21 @@ from xmodule.tabs import CourseTabList ...@@ -99,15 +99,21 @@ from xmodule.tabs import CourseTabList
<label data-field="email" for="feedback_form_email">${_('E-mail')}*</label> <label data-field="email" for="feedback_form_email">${_('E-mail')}*</label>
<input name="email" type="text" id="feedback_form_email" required> <input name="email" type="text" id="feedback_form_email" required>
% endif % endif
<div class="js-course-id-anchor">
% if course:
<input name="course_id" type="hidden" value="${unicode(course.id)}">
% endif
</div>
<label data-field="subject" for="feedback_form_subject">${_('Briefly describe your issue')}*</label> <label data-field="subject" for="feedback_form_subject">${_('Briefly describe your issue')}*</label>
<input name="subject" type="text" id="feedback_form_subject" required> <input name="subject" type="text" id="feedback_form_subject" required>
<label data-field="details" for="feedback_form_details">${_('Tell us the details')}*</label> <label data-field="details" for="feedback_form_details">${_('Tell us the details')}*</label>
<span class="tip" id="feedback_form_details_tip">${_('Describe what you were doing when you encountered the issue. Include any details that will help us to troubleshoot, including error messages that you saw.')}</span> <span class="tip" id="feedback_form_details_tip">${_('Describe what you were doing when you encountered the issue. Include any details that will help us to troubleshoot, including error messages that you saw.')}</span>
<textarea name="details" id="feedback_form_details" required aria-describedby="feedback_form_details_tip"></textarea> <textarea name="details" id="feedback_form_details" required aria-describedby="feedback_form_details_tip"></textarea>
<input name="issue_type" type="hidden"> <input name="issue_type" type="hidden">
% if course:
<input name="course_id" type="hidden" value="${unicode(course.id)}">
% endif
<div class="submit"> <div class="submit">
<input name="submit" type="submit" value="${_('Submit')}" id="feedback_submit"> <input name="submit" type="submit" value="${_('Submit')}" id="feedback_submit">
</div> </div>
...@@ -138,7 +144,12 @@ from xmodule.tabs import CourseTabList ...@@ -138,7 +144,12 @@ from xmodule.tabs import CourseTabList
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() { $(document).ready(function() {
var $helpModal = $("#help-modal"), var currentCourseId,
courseOptions = [],
userAuthenticated = false,
courseOptionsLoadInProgress = false,
finishedLoadingCourseOptions = false,
$helpModal = $("#help-modal"),
$closeButton = $("#help-modal .close-modal"), $closeButton = $("#help-modal .close-modal"),
$leanOverlay = $("#lean_overlay"), $leanOverlay = $("#lean_overlay"),
$feedbackForm = $("#feedback_form"), $feedbackForm = $("#feedback_form"),
...@@ -149,11 +160,101 @@ $(document).ready(function() { ...@@ -149,11 +160,101 @@ $(document).ready(function() {
$('area,input,select,textarea,button').removeAttr('tabindex'); $('area,input,select,textarea,button').removeAttr('tabindex');
$(".help-tab a").focus(); $(".help-tab a").focus();
$leanOverlay.removeAttr('tabindex'); $leanOverlay.removeAttr('tabindex');
},
showFeedback = function(event, issue_type, title, subject_label, details_label) {
event.preventDefault();
DialogTabControls.initializeTabKeyValues("#feedback_form_wrapper", $closeButton);
$("#feedback_form input[name='issue_type']").val(issue_type);
$("#feedback_form_wrapper header").html("<h2>" + title + "</h2><hr>");
$("#feedback_form_wrapper label[data-field='subject']").html(subject_label);
$("#feedback_form_wrapper label[data-field='details']").html(details_label);
if (userAuthenticated && finishedLoadingCourseOptions && courseOptions.length > 1) {
$('.js-course-id-anchor').html([
'<label for="feedback_form_course">' + '${_("Course") | n, js_escaped_string}' + '</label>',
'<select name="course_id" id="feedback_form_course" class="feedback-form-select">',
courseOptions.join(''),
'</select>'
].join(''));
}
$("#help_wrapper").css("display", "none");
$("#feedback_form_wrapper").css("display", "block");
$closeButton.focus();
},
loadCourseOptions = function() {
courseOptionsLoadInProgress = true;
$.ajax({
url: '/api/enrollment/v1/enrollment',
success: function(data) {
var i,
courseDetails,
courseName,
courseId,
option,
defaultOptionText = '${_("- Select -") | n, js_escaped_string}',
markedSelectedOption = false;
// Make sure courseOptions is empty before we begin pushing options into it.
courseOptions = [];
for (i = 0; i < data.length; i++) {
courseDetails = data[i].course_details;
if (!courseDetails) {
continue;
}
courseName = courseDetails.course_name;
courseId = courseDetails.course_id;
if (!(courseName && courseId)) {
continue;
}
// Build an option for this course and select it if it's the course we're currently viewing.
if (!markedSelectedOption && courseId === currentCourseId) {
option = buildCourseOption(courseName, courseId, true);
markedSelectedOption = true;
} else {
option = buildCourseOption(courseName, courseId, false);
}
courseOptions.push(option);
}
// Build the default option and select it if we haven't already selected another option.
option = buildCourseOption(defaultOptionText, '', !markedSelectedOption);
// Add the default option to the head of the courseOptions Array.
courseOptions.unshift(option);
finishedLoadingCourseOptions = true;
},
complete: function() {
courseOptionsLoadInProgress = false;
}
});
},
buildCourseOption = function(courseName, courseId, selected) {
var option = '<option value="' + _.escape(courseId) + '"';
if (selected) {
option += ' selected';
}
option += '>' + _.escape(courseName) + '</option>';
return option;
}; };
% if user.is_authenticated():
userAuthenticated = true;
% endif
% if course:
currentCourseId = "${unicode(course.id) | n, js_escaped_string}";
% endif
DialogTabControls.setKeydownListener($helpModal, $closeButton); DialogTabControls.setKeydownListener($helpModal, $closeButton);
$(".help-tab").click(function() { $(".help-tab").click(function() {
if (userAuthenticated && !finishedLoadingCourseOptions && !courseOptionsLoadInProgress) {
loadCourseOptions();
}
$helpModal.css("position", "absolute"); $helpModal.css("position", "absolute");
DialogTabControls.initializeTabKeyValues("#help_wrapper", $closeButton); DialogTabControls.initializeTabKeyValues("#help_wrapper", $closeButton);
$(".field-error").removeClass("field-error"); $(".field-error").removeClass("field-error");
...@@ -171,18 +272,6 @@ $(document).ready(function() { ...@@ -171,18 +272,6 @@ $(document).ready(function() {
$closeButton.focus(); $closeButton.focus();
}); });
showFeedback = function(event, issue_type, title, subject_label, details_label) {
$("#help_wrapper").css("display", "none");
DialogTabControls.initializeTabKeyValues("#feedback_form_wrapper", $closeButton);
$("#feedback_form input[name='issue_type']").val(issue_type);
$("#feedback_form_wrapper").css("display", "block");
$("#feedback_form_wrapper header").html("<h2>" + title + "</h2><hr>");
$("#feedback_form_wrapper label[data-field='subject']").html(subject_label);
$("#feedback_form_wrapper label[data-field='details']").html(details_label);
$closeButton.focus();
event.preventDefault();
};
$("#feedback_link_problem").click(function(event) { $("#feedback_link_problem").click(function(event) {
$("#feedback_form_details_tip").css({"display": "block", "padding-bottom": "5px"}); $("#feedback_form_details_tip").css({"display": "block", "padding-bottom": "5px"});
showFeedback( showFeedback(
......
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