Commit e5a5704b by John Eskew

Merge pull request #12495 from edx/jeskew/release_to_master_merge

Merge release to master for 2016-05-17 release
parents 5db315be f2ffbab0
...@@ -510,9 +510,8 @@ def course_about(request, course_id): ...@@ -510,9 +510,8 @@ def course_about(request, course_id):
ecommerce_bulk_checkout_link = '' ecommerce_bulk_checkout_link = ''
professional_mode = None professional_mode = None
ecomm_service = EcommerceService() ecomm_service = EcommerceService()
if ecomm_service.is_enabled(request.user) and ( is_professional_mode = CourseMode.PROFESSIONAL in modes or CourseMode.NO_ID_PROFESSIONAL_MODE in modes
CourseMode.PROFESSIONAL in modes or CourseMode.NO_ID_PROFESSIONAL_MODE in modes if ecomm_service.is_enabled(request.user) and (is_professional_mode):
):
professional_mode = modes.get(CourseMode.PROFESSIONAL, '') or \ professional_mode = modes.get(CourseMode.PROFESSIONAL, '') or \
modes.get(CourseMode.NO_ID_PROFESSIONAL_MODE, '') modes.get(CourseMode.NO_ID_PROFESSIONAL_MODE, '')
ecommerce_checkout_link = ecomm_service.checkout_page_url(professional_mode.sku) ecommerce_checkout_link = ecomm_service.checkout_page_url(professional_mode.sku)
......
...@@ -2525,6 +2525,9 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment ...@@ -2525,6 +2525,9 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
Test that some minimum of information is formatted Test that some minimum of information is formatted
correctly in the response to get_students_features. correctly in the response to get_students_features.
""" """
for student in self.students:
student.profile.city = "Mos Eisley {}".format(student.id)
student.profile.save()
url = reverse('get_students_features', kwargs={'course_id': self.course.id.to_deprecated_string()}) url = reverse('get_students_features', kwargs={'course_id': self.course.id.to_deprecated_string()})
response = self.client.get(url, {}) response = self.client.get(url, {})
res_json = json.loads(response.content) res_json = json.loads(response.content)
...@@ -2536,6 +2539,8 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment ...@@ -2536,6 +2539,8 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
][0] ][0]
self.assertEqual(student_json['username'], student.username) self.assertEqual(student_json['username'], student.username)
self.assertEqual(student_json['email'], student.email) self.assertEqual(student_json['email'], student.email)
self.assertEqual(student_json['city'], student.profile.city)
self.assertEqual(student_json['country'], "")
@ddt.data(True, False) @ddt.data(True, False)
def test_get_students_features_cohorted(self, is_cohorted): def test_get_students_features_cohorted(self, is_cohorted):
......
...@@ -1245,7 +1245,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red ...@@ -1245,7 +1245,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
query_features = [ query_features = [
'id', 'username', 'name', 'email', 'language', 'location', 'id', 'username', 'name', 'email', 'language', 'location',
'year_of_birth', 'gender', 'level_of_education', 'mailing_address', 'year_of_birth', 'gender', 'level_of_education', 'mailing_address',
'goals', 'city', 'country' 'goals',
] ]
# Provide human-friendly and translatable names for these features. These names # Provide human-friendly and translatable names for these features. These names
...@@ -1263,8 +1263,6 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red ...@@ -1263,8 +1263,6 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
'level_of_education': _('Level of Education'), 'level_of_education': _('Level of Education'),
'mailing_address': _('Mailing Address'), 'mailing_address': _('Mailing Address'),
'goals': _('Goals'), 'goals': _('Goals'),
'city': _('City'),
'country': _('Country'),
} }
if is_course_cohorted(course.id): if is_course_cohorted(course.id):
...@@ -1276,6 +1274,12 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red ...@@ -1276,6 +1274,12 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
query_features.append('team') query_features.append('team')
query_features_names['team'] = _('Team') query_features_names['team'] = _('Team')
# For compatibility reasons, city and country should always appear last.
query_features.append('city')
query_features_names['city'] = _('City')
query_features.append('country')
query_features_names['country'] = _('Country')
if not csv: if not csv:
student_data = instructor_analytics.basic.enrolled_students_features(course_key, query_features) student_data = instructor_analytics.basic.enrolled_students_features(course_key, query_features)
response_payload = { response_payload = {
......
...@@ -158,7 +158,7 @@ var edx = edx || {}; ...@@ -158,7 +158,7 @@ var edx = edx || {};
* @return {object} JQuery Promise. * @return {object} JQuery Promise.
*/ */
getCourseData: function (courseId) { getCourseData: function (courseId) {
var courseDetailUrl = '/api/course_structure/v0/courses/{courseId}/'; var courseDetailUrl = '/api/courses/v1/courses/{courseId}/';
return $.ajax({ return $.ajax({
url: edx.StringUtils.interpolate(courseDetailUrl, {courseId: courseId}), url: edx.StringUtils.interpolate(courseDetailUrl, {courseId: courseId}),
type: 'GET', type: 'GET',
...@@ -247,7 +247,13 @@ var edx = edx || {}; ...@@ -247,7 +247,13 @@ var edx = edx || {};
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
var line = order.lines[i], var line = order.lines[i],
attributeValues = _.find(line.product.attribute_values, function (attribute) { attributeValues = _.find(line.product.attribute_values, function (attribute) {
return attribute.name === 'course_key' // If the attribute has a 'code' property, compare its value, otherwise compare 'name'
var value_to_match = 'course_key';
if (attribute.code) {
return attribute.code === value_to_match;
} else {
return attribute.name === value_to_match;
}
}); });
// This method assumes that all items in the order are related to a single course. // This method assumes that all items in the order are related to a single course.
......
...@@ -36,7 +36,7 @@ define([ ...@@ -36,7 +36,7 @@ define([
mockRequests(requests, 'GET', orderUrlFormat, data); mockRequests(requests, 'GET', orderUrlFormat, data);
mockRequests( mockRequests(
requests, 'GET', '/api/course_structure/v0/courses/course-v1:edx+dummy+2015_T3/', courseResponseData requests, 'GET', '/api/courses/v1/courses/course-v1:edx+dummy+2015_T3/', courseResponseData
); );
mockRequests(requests, 'GET', '/api/credit/v1/providers/edx/', providerResponseData); mockRequests(requests, 'GET', '/api/credit/v1/providers/edx/', providerResponseData);
...@@ -81,6 +81,7 @@ define([ ...@@ -81,6 +81,7 @@ define([
}, },
{ {
"name": "course_key", "name": "course_key",
"code": "course_key",
"value": "course-v1:edx+dummy+2015_T3" "value": "course-v1:edx+dummy+2015_T3"
}, },
{ {
...@@ -135,7 +136,7 @@ define([ ...@@ -135,7 +136,7 @@ define([
"org": "edx", "org": "edx",
"run": "2015_T2", "run": "2015_T2",
"course": "CS420", "course": "CS420",
"uri": "http://test.com/api/course_structure/v0/courses/course-v1:edx+dummy+2015_T3/", "uri": "http://test.com/api/courses/v1/courses/course-v1:edx+dummy+2015_T3/",
"image_url": "/test.jpg", "image_url": "/test.jpg",
"start": "2030-01-01T00:00:00Z", "start": "2030-01-01T00:00:00Z",
"end": null "end": null
......
...@@ -13,3 +13,5 @@ ...@@ -13,3 +13,5 @@
@import 'shared-v2/navigation'; @import 'shared-v2/navigation';
@import 'shared-v2/header'; @import 'shared-v2/header';
@import 'shared-v2/footer'; @import 'shared-v2/footer';
@import 'shared-v2/modal';
@import 'shared-v2/help-tab';
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
@include left(0); @include left(0);
display: inline-block; display: inline-block;
position: absolute; position: absolute;
top: -1000px; top: -999999px;
overflow: hidden; overflow: hidden;
} }
......
.help-tab {
@include transform(rotate(-90deg));
@include transform-origin(0 0);
z-index: z-index(front);
top: 250px;
left: 0;
position: fixed;
a:link,
a:visited {
cursor: pointer;
border: 1px solid palette(grayscale, light);
border-top-style: none;
border-radius: 0 0 ($baseline/2) + px ($baseline/2) + px;
background: transparentize(palette(grayscale, white-t), 0.25);
color: transparentize(palette(grayscale-cool, x-dark), 0.25);
font-weight: bold;
text-decoration: none;
padding: 6px 22px 11px;
display: inline-block;
&:hover,
&:focus {
color: palette(grayscale, white-t);
background: palette(primary, base);
}
}
}
.help-buttons {
padding: ($baseline/2) + px ($baseline*2.5) + px;
a:link, a:visited {
padding: ($baseline*0.75) + px 0;
text-align: center;
cursor: pointer;
background: palette(grayscale, white-t);
text-decoration: none;
display: block;
border: 1px solid palette(grayscale, light);
&#feedback_link_problem {
border-bottom-style: none;
border-radius: ($baseline/2) + px ($baseline/2) + px 0 0;
}
&#feedback_link_question {
border-top-style: none;
border-radius: 0 0 ($baseline/2) + px ($baseline/2) + px;
}
&:hover, &:focus {
color: palette(grayscale, white-t);
background: palette(primary, base);
}
}
}
#feedback_form {
input,
textarea {
font: {
size: font-size(base);
family: $font-family-sans-serif;
}
line-height: 1.4;
}
textarea[name="details"] {
height: 150px;
}
}
#feedback_success_wrapper {
p {
padding: 0 $baseline + px $baseline + px $baseline + px;
}
}
#lean_overlay {
@include background-image(radial-gradient(circle at 50% 30%, $shadow-d1, $shadow-d2));
background: transparent;
display: none;
height:100%;
left: 0;
position: fixed;
top: 0;
width:100%;
z-index: 100;
}
.modal {
@include span(5);
z-index: z-index(mid-front);
display: none;
position: absolute;
left: 50%;
padding: 8px;
border-radius: 3px;
box-shadow: 0 0px 5px 0 $shadow-d1;
background: $gray-d2;
color: $base-font-color;
.inner-wrapper {
z-index: z-index(mid-front);
background: $modal-bg-color;
border-radius: 0;
border: 1px solid rgba(0, 0, 0, 0.9);
box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.7);
overflow: hidden;
padding-left: ($baseline/2) + px;
padding-right: ($baseline/2) + px;
padding-bottom: ($baseline/2) + px;
position: relative;
p {
font-size: font-size(small);
line-height: 1.4;
}
a {
&:hover,
&:focus {
text-decoration: underline;
}
}
.sr {
@extend .sr-only;
}
header {
z-index: z-index(mid-front);
margin-bottom: ($baseline*1.5) + px;
overflow: hidden;
padding: 28px $baseline + px 0;
position: relative;
&::before {
@include background-image(radial-gradient(50% 50%, circle closest-side, rgba(255,255,255, 0.8) 0%, rgba(255,255,255, 0) 100%));
content: "";
display: block;
height: 400px;
left: 0;
margin: 0 auto;
position: absolute;
top: -140px;
width: 100%;
z-index: 1;
}
hr {
@include background-image(linear-gradient(180deg, rgba(255,255,255, 0) 0%,
rgba(255,255,255, 0.8) 50%,
rgba(255,255,255, 0)));
height: 1px;
width: 100%;
border: none;
margin: 0;
position: relative;
z-index: 2;
&::after {
@include background-image(linear-gradient(180deg, rgba(200,200,200, 0) 0%,
rgba(200,200,200, 1) 50%,
rgba(200,200,200, 0)));
height: 1px;
width: 100%;
bottom: 0;
content: '';
display: block;
position: absolute;
top: -1px;
}
}
h2 {
@extend .hd-4;
position: relative;
text-align: center;
text-shadow: 0 1px rgba(255,255,255, 0.4);
z-index: 2;
text-transform: uppercase;
font-family: $font-family-serif;
.edx {
text-transform: none;
}
}
}
.modal-form-error {
background: tint($red,90%);
border: 1px solid rgb(143, 14, 14);
color: rgb(143, 14, 14);
display: none;
margin-bottom: $baseline + px;
padding: 12px;
}
.notice {
background: $yellow;
border: 1px solid darken($yellow, 60%);
color: darken($yellow, 60%);
display: none;
margin-bottom: $baseline + px;
padding: 12px;
}
.activation-message, .message {
padding: 0 ($baseline*2) + px ($baseline/2) + px;
p {
margin-bottom: ($baseline/2) + px;
}
}
form {
margin-bottom: 12px;
padding: 0 ($baseline*2) + px $baseline + px;
position: relative;
z-index: 2;
.input-group {
@include clearfix();
border-bottom: 1px solid rgb(210,210,210);
box-shadow: 0 1px 0 0 rgba(255,255,255, 0.6);
margin-bottom: ($baseline*1.5) + px;
padding-bottom: ($baseline/2) + px;
}
label {
color: $text-color;
font: {
family: $font-family-serif;
style: italic;
}
line-height: 1.6;
&.field-error {
display: block;
color: #8F0E0E;
+ input, + textarea {
border: 1px solid #CA1111;
color: #8F0E0E;
}
}
}
input[type="checkbox"] {
margin-right: ($baseline/4) + px;
}
textarea {
background: rgb(255,255,255);
display: block;
height: 45px;
margin-bottom: $baseline + px;
width: 100%;
}
input[type="email"],
input[type="text"],
input[type="password"] {
background: rgb(255,255,255);
display: block;
height: 45px;
margin-bottom: $baseline + px;
width: 100%;
}
.submit {
padding-top: ($baseline/2) + px;
input[type="submit"] {
@extend .btn-brand;
display: block;
height: auto;
margin: 0 auto;
width: 100%;
white-space: normal;
}
}
}
.close-modal {
@include transition(all 0.15s ease-out 0s);
border-radius: 2px;
cursor: pointer;
display: inline-block;
padding: 10px;
position: absolute;
right: 2px;
top: 0px;
z-index: z-index(front);
color: $lighter-base-font-color;
font: {
size: font-size(large);
family: $font-family-sans-serif;
}
line-height: 1;
text-align: center;
border: none;
background: transparent;
text-shadow: none;
letter-spacing: 0;
text-transform: none;
&:hover,
&:focus {
color: $base-font-color;
text-decoration: none;
opacity: 0.8;
}
&:focus {
border: none !important;
}
}
}
#help_wrapper,
#feedback_form_wrapper,
.discussion-alert-wrapper {
padding: 0 ($baseline*1.5) + px ($baseline*1.5) + px ($baseline*1.5) + px;
header {
margin-bottom: $baseline + px;
padding-right: 0;
padding-left: 0;
}
.note {
font: {
size: font-size(x-small);
family: $font-family-sans-serif;
}
line-height: 1.475;
margin-top: ($baseline/2) + px;
color: $lighter-base-font-color;
}
}
.tip {
font-size: font-size(x-small);
display: block;
color: $dark-gray;
}
}
.leanModal_box {
@extend .modal;
}
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