Commit 2d85fe4a by Anthony Mangano Committed by GitHub

Merge pull request #14279 from…

Merge pull request #14279 from edx/ECOM-5936-send-course-id-and-enrollment-track-to-zendesk-custom-fields

Ecom 5936 enable users to select course when making support requests
parents 6572b1df 38d8017d
......@@ -11,8 +11,19 @@ from util import views
from zendesk import ZendeskError
import json
import mock
from ddt import ddt, data, unpack
from student.tests.test_configuration_overrides import fake_get_value
from student.tests.factories import CourseEnrollmentFactory
TEST_SUPPORT_EMAIL = "support@example.com"
TEST_ZENDESK_CUSTOM_FIELD_CONFIG = {"course_id": 1234, "enrollment_mode": 5678}
TEST_REQUEST_HEADERS = {
"HTTP_REFERER": "test_referer",
"HTTP_USER_AGENT": "test_user_agent",
"REMOTE_ADDR": "1.2.3.4",
"SERVER_NAME": "test_server",
}
def fake_support_backend_values(name, default=None): # pylint: disable=unused-argument
......@@ -21,13 +32,20 @@ def fake_support_backend_values(name, default=None): # pylint: disable=unused-a
"""
config_dict = {
"CONTACT_FORM_SUBMISSION_BACKEND": "email",
"email_from_address": "support_from@example.com",
"email_from_address": TEST_SUPPORT_EMAIL,
}
return config_dict[name]
@ddt
@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(
DEFAULT_FROM_EMAIL=TEST_SUPPORT_EMAIL,
ZENDESK_URL="dummy",
ZENDESK_USER="dummy",
ZENDESK_API_KEY="dummy",
ZENDESK_CUSTOM_FIELDS={}
)
@mock.patch("util.views.dog_stats_api")
@mock.patch("util.views._ZendeskApi", autospec=True)
class SubmitFeedbackTest(TestCase):
......@@ -44,14 +62,12 @@ class SubmitFeedbackTest(TestCase):
username="test",
profile__name="Test User"
)
# This contains issue_type and course_id to ensure that tags are submitted correctly
self._anon_fields = {
"email": "test@edx.org",
"name": "Test User",
"subject": "a subject",
"details": "some details",
"issue_type": "test_issue",
"course_id": "test_course"
"issue_type": "test_issue"
}
# This does not contain issue_type nor course_id to ensure that they are optional
self._auth_fields = {"subject": "a subject", "details": "some details"}
......@@ -66,10 +82,10 @@ class SubmitFeedbackTest(TestCase):
req = self._request_factory.post(
"/submit_feedback",
data=fields,
HTTP_REFERER="test_referer",
HTTP_USER_AGENT="test_user_agent",
REMOTE_ADDR="1.2.3.4",
SERVER_NAME="test_server",
HTTP_REFERER=TEST_REQUEST_HEADERS["HTTP_REFERER"],
HTTP_USER_AGENT=TEST_REQUEST_HEADERS["HTTP_USER_AGENT"],
REMOTE_ADDR=TEST_REQUEST_HEADERS["REMOTE_ADDR"],
SERVER_NAME=TEST_REQUEST_HEADERS["SERVER_NAME"],
)
req.user = user
return views.submit_feedback(req)
......@@ -130,13 +146,58 @@ class SubmitFeedbackTest(TestCase):
resp = self._build_and_run_request(user, fields)
self.assertEqual(resp.status_code, 200)
def _assert_datadog_called(self, datadog_mock, with_tags):
expected_datadog_calls = [
mock.call.increment(
views.DATADOG_FEEDBACK_METRIC,
tags=(["course_id:test_course", "issue_type:test_issue"] if with_tags else [])
)
def _build_zendesk_ticket(self, recipient, name, email, subject, details, tags, custom_fields=None):
"""
Build a Zendesk ticket that can be used in assertions to verify that the correct
data was submitted to create a Zendesk ticket.
"""
ticket = {
"ticket": {
"recipient": recipient,
"requester": {"name": name, "email": email},
"subject": subject,
"comment": {"body": details},
"tags": tags
}
}
if custom_fields is not None:
ticket["ticket"]["custom_fields"] = custom_fields
return ticket
def _build_zendesk_ticket_update(self, request_headers, username=None):
"""
Build a Zendesk ticket update that can be used in assertions to verify that the correct
data was submitted to update a Zendesk ticket.
"""
body = []
if username:
body.append("username: {}".format(username))
# FIXME the tests rely on the body string being built in this specific order, which doesn't seem
# reliable given that the view builds the string by iterating over a dictionary.
header_text_mapping = [
("Client IP", "REMOTE_ADDR"),
("Host", "SERVER_NAME"),
("Page", "HTTP_REFERER"),
("Browser", "HTTP_USER_AGENT")
]
for text, header in header_text_mapping:
body.append("{}: {}".format(text, request_headers[header]))
body = "Additional information:\n\n" + "\n".join(body)
return {"ticket": {"comment": {"public": False, "body": body}}}
def _assert_zendesk_called(self, zendesk_mock, ticket_id, ticket, ticket_update):
"""Assert that Zendesk was called with the correct ticket and ticket_update."""
expected_zendesk_calls = [mock.call.create_ticket(ticket), mock.call.update_ticket(ticket_id, ticket_update)]
self.assertEqual(zendesk_mock.mock_calls, expected_zendesk_calls)
def _assert_datadog_called(self, datadog_mock, tags):
"""Assert that datadog was called with the correct tags."""
expected_datadog_calls = [mock.call.increment(views.DATADOG_FEEDBACK_METRIC, tags=tags)]
self.assertEqual(datadog_mock.mock_calls, expected_datadog_calls)
def test_bad_request_anon_user_no_name(self, zendesk_mock_class, datadog_mock):
......@@ -174,39 +235,26 @@ class SubmitFeedbackTest(TestCase):
the given information should have been submitted via the Zendesk API.
"""
zendesk_mock_instance = zendesk_mock_class.return_value
zendesk_mock_instance.create_ticket.return_value = 42
self._test_success(self._anon_user, self._anon_fields)
expected_zendesk_calls = [
mock.call.create_ticket(
{
"ticket": {
"recipient": "registration@example.com",
"requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject",
"comment": {"body": "some details"},
"tags": ["test_course", "test_issue", "LMS"]
}
}
),
mock.call.update_ticket(
42,
{
"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"
}
}
}
)
]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=True)
user = self._anon_user
fields = self._anon_fields
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
ticket = self._build_zendesk_ticket(
recipient=TEST_SUPPORT_EMAIL,
name=fields["name"],
email=fields["email"],
subject=fields["subject"],
details=fields["details"],
tags=[fields["issue_type"], "LMS"]
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(fields["issue_type"])])
@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):
......@@ -218,39 +266,75 @@ class SubmitFeedbackTest(TestCase):
tag that will come from site configuration override.
"""
zendesk_mock_instance = zendesk_mock_class.return_value
zendesk_mock_instance.create_ticket.return_value = 42
self._test_success(self._anon_user, self._anon_fields)
expected_zendesk_calls = [
mock.call.create_ticket(
{
"ticket": {
"recipient": "no-reply@fakeuniversity.com",
"requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject",
"comment": {"body": "some details"},
"tags": ["test_course", "test_issue", "LMS", "whitelabel_fakeorg"]
}
}
),
mock.call.update_ticket(
42,
{
"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"
}
}
}
)
]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=True)
user = self._anon_user
fields = self._anon_fields
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
ticket = self._build_zendesk_ticket(
recipient=fake_get_value("email_from_address"),
name=fields["name"],
email=fields["email"],
subject=fields["subject"],
details=fields["details"],
tags=[fields["issue_type"], "LMS", "whitelabel_{}".format(fake_get_value("course_org_filter"))]
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(fields["issue_type"])])
@data("course-v1:testOrg+testCourseNumber+testCourseRun", "", None)
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
def test_valid_request_anon_user_with_custom_fields(self, course_id, zendesk_mock_class, 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_class.return_value
user = self._anon_user
fields = self._anon_fields.copy()
if course_id is not None:
fields["course_id"] = course_id
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
zendesk_tags = [fields["issue_type"], "LMS"]
datadog_tags = ["issue_type:{}".format(fields["issue_type"])]
zendesk_custom_fields = None
if course_id:
# FIXME the tests rely on the tags being in this specific order, which doesn't seem
# reliable given that the view builds the list by iterating over a dictionary.
zendesk_tags.insert(0, course_id)
datadog_tags.insert(0, "course_id:{}".format(course_id))
zendesk_custom_fields = [
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
]
ticket = self._build_zendesk_ticket(
recipient=TEST_SUPPORT_EMAIL,
name=fields["name"],
email=fields["email"],
subject=fields["subject"],
details=fields["details"],
tags=zendesk_tags,
custom_fields=zendesk_custom_fields
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, datadog_tags)
def test_bad_request_auth_user_no_subject(self, zendesk_mock_class, datadog_mock):
"""Test a request from an authenticated user not specifying `subject`."""
......@@ -270,40 +354,92 @@ class SubmitFeedbackTest(TestCase):
the given information should have been submitted via the Zendesk API.
"""
zendesk_mock_instance = zendesk_mock_class.return_value
zendesk_mock_instance.create_ticket.return_value = 42
self._test_success(self._auth_user, self._auth_fields)
expected_zendesk_calls = [
mock.call.create_ticket(
{
"ticket": {
"recipient": "registration@example.com",
"requester": {"name": "Test User", "email": "test@edx.org"},
"subject": "a subject",
"comment": {"body": "some details"},
"tags": ["LMS"]
}
}
),
mock.call.update_ticket(
42,
{
"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"
}
}
}
)
]
self.assertEqual(zendesk_mock_instance.mock_calls, expected_zendesk_calls)
self._assert_datadog_called(datadog_mock, with_tags=False)
user = self._auth_user
fields = self._auth_fields
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
ticket = self._build_zendesk_ticket(
recipient=TEST_SUPPORT_EMAIL,
name=user.profile.name,
email=user.email,
subject=fields["subject"],
details=fields["details"],
tags=["LMS"]
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
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=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
def test_valid_request_auth_user_with_custom_fields(self, course_id, enrolled, zendesk_mock_class, 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_class.return_value
user = self._auth_user
fields = self._auth_fields.copy()
if course_id is not None:
fields["course_id"] = course_id
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
zendesk_tags = ["LMS"]
datadog_tags = []
zendesk_custom_fields = None
if course_id:
# FIXME the tests rely on the tags being in this specific order, which doesn't seem
# reliable given that the view builds the list by iterating over a dictionary.
zendesk_tags.insert(0, course_id)
datadog_tags.insert(0, "course_id:{}".format(course_id))
zendesk_custom_fields = [
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
]
if enrolled is not None:
enrollment = CourseEnrollmentFactory.create(
user=user,
course_id=course_id,
is_active=enrolled
)
if enrollment.is_active:
zendesk_custom_fields.append(
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
)
ticket = self._build_zendesk_ticket(
recipient=TEST_SUPPORT_EMAIL,
name=user.profile.name,
email=user.email,
subject=fields["subject"],
details=fields["details"],
tags=zendesk_tags,
custom_fields=zendesk_custom_fields
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, datadog_tags)
def test_get_request(self, zendesk_mock_class, datadog_mock):
"""Test that a GET results in a 405 even with all required fields"""
......@@ -329,7 +465,7 @@ class SubmitFeedbackTest(TestCase):
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
self.assertEqual(resp.status_code, 500)
self.assertFalse(resp.content)
self._assert_datadog_called(datadog_mock, with_tags=True)
self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(self._anon_fields["issue_type"])])
def test_zendesk_error_on_update(self, zendesk_mock_class, datadog_mock):
"""
......@@ -344,7 +480,7 @@ class SubmitFeedbackTest(TestCase):
zendesk_mock_instance.update_ticket.side_effect = err
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
self.assertEqual(resp.status_code, 200)
self._assert_datadog_called(datadog_mock, with_tags=True)
self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(self._anon_fields["issue_type"])])
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
def test_not_enabled(self, zendesk_mock_class, datadog_mock):
......
......@@ -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
import track.views
from student.roles import GlobalStaff
from student.models import CourseEnrollment
log = logging.getLogger(__name__)
......@@ -222,6 +223,40 @@ class _ZendeskApi(object):
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(
realname,
email,
......@@ -231,7 +266,8 @@ def _record_feedback_in_zendesk(
additional_info,
group_name=None,
require_update=False,
support_email=None
support_email=None,
custom_fields=None
):
"""
Create a new user-requested Zendesk ticket.
......@@ -246,6 +282,8 @@ def _record_feedback_in_zendesk(
If `require_update` is provided, returns False when the update does not
succeed. This allows using the private comment to add necessary information
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()
......@@ -271,6 +309,10 @@ def _record_feedback_in_zendesk(
"tags": zendesk_tags
}
}
if custom_fields:
new_ticket["ticket"]["custom_fields"] = custom_fields
group = None
if group_name is not None:
group = zendesk_api.get_group(group_name)
......@@ -322,7 +364,7 @@ def get_feedback_form_context(request):
context["subject"] = request.POST["subject"]
context["details"] = request.POST["details"]
context["tags"] = dict(
[(tag, request.POST[tag]) for tag in ["issue_type", "course_id"] if tag in request.POST]
[(tag, request.POST[tag]) for tag in ["issue_type", "course_id"] if request.POST.get(tag)]
)
context["additional_info"] = {}
......@@ -412,6 +454,11 @@ def submit_feedback(request):
if not settings.ZENDESK_URL or not settings.ZENDESK_USER or not settings.ZENDESK_API_KEY:
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(
context["realname"],
context["email"],
......@@ -419,7 +466,8 @@ def submit_feedback(request):
context["details"],
context["tags"],
context["additional_info"],
support_email=context["support_email"]
support_email=context["support_email"],
custom_fields=custom_fields
)
_record_feedback_in_datadog(context["tags"])
......
......@@ -333,6 +333,8 @@ COMMENTS_SERVICE_URL = ENV_TOKENS.get("COMMENTS_SERVICE_URL", '')
COMMENTS_SERVICE_KEY = ENV_TOKENS.get("COMMENTS_SERVICE_KEY", '')
CERT_QUEUE = ENV_TOKENS.get("CERT_QUEUE", 'test-pull')
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")
MKTG_URLS = ENV_TOKENS.get('MKTG_URLS', MKTG_URLS)
......
......@@ -1003,6 +1003,7 @@ FEEDBACK_SUBMISSION_EMAIL = None
ZENDESK_URL = None
ZENDESK_USER = None
ZENDESK_API_KEY = None
ZENDESK_CUSTOM_FIELDS = {}
##### EMBARGO #####
EMBARGO_SITE_REDIRECT_URL = None
......
......@@ -35,6 +35,7 @@
@import 'shared/modal';
@import 'shared/activation_messages';
@import 'shared/unsubscribe';
@import 'shared/help-tab';
// shared - platform
@import 'multicourse/home';
......
......@@ -78,3 +78,9 @@
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
<label data-field="email" for="feedback_form_email">${_('E-mail')}*</label>
<input name="email" type="text" id="feedback_form_email" required>
% 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>
<input name="subject" type="text" id="feedback_form_subject" required>
<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>
<textarea name="details" id="feedback_form_details" required aria-describedby="feedback_form_details_tip"></textarea>
<input name="issue_type" type="hidden">
% if course:
<input name="course_id" type="hidden" value="${unicode(course.id)}">
% endif
<div class="submit">
<input name="submit" type="submit" value="${_('Submit')}" id="feedback_submit">
</div>
......@@ -138,7 +144,12 @@ from xmodule.tabs import CourseTabList
<script type="text/javascript">
$(document).ready(function() {
var $helpModal = $("#help-modal"),
var currentCourseId,
courseOptions = [],
userAuthenticated = false,
courseOptionsLoadInProgress = false,
finishedLoadingCourseOptions = false,
$helpModal = $("#help-modal"),
$closeButton = $("#help-modal .close-modal"),
$leanOverlay = $("#lean_overlay"),
$feedbackForm = $("#feedback_form"),
......@@ -149,11 +160,101 @@ $(document).ready(function() {
$('area,input,select,textarea,button').removeAttr('tabindex');
$(".help-tab a").focus();
$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);
$(".help-tab").click(function() {
if (userAuthenticated && !finishedLoadingCourseOptions && !courseOptionsLoadInProgress) {
loadCourseOptions();
}
$helpModal.css("position", "absolute");
DialogTabControls.initializeTabKeyValues("#help_wrapper", $closeButton);
$(".field-error").removeClass("field-error");
......@@ -171,18 +272,6 @@ $(document).ready(function() {
$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_form_details_tip").css({"display": "block", "padding-bottom": "5px"});
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