fix: eslint autofixable issues (#32181)
* fix: eslint operator-linebreak issue * fix: eslint quotes issue * fix: react jsx indent and props issues * fix: eslint trailing spaces issues * fix: eslint line around directives issue * fix: eslint semi rule * fix: eslint newline per chain rule * fix: eslint space infix ops rule * fix: eslint space-in-parens issue * fix: eslint space before function paren issue * fix: eslint space before blocks issue * fix: eslint arrow body style issue * fix: eslint dot-location issue * fix: eslint quotes issue * fix: eslint quote props issue * fix: eslint operator assignment issue * fix: eslint new line after import issue * fix: indent issues * fix: operator assignment issue * fix: all autofixable eslint issues * fix: all react related fixable issues * fix: autofixable eslint issues * chore: remove all template literals * fix: remaining autofixable issues * fix: failing js test
This commit is contained in:
committed by
GitHub
parent
f2daf37d4a
commit
d7053a6783
@@ -49,7 +49,6 @@
|
||||
"import/no-dynamic-require": "off",
|
||||
"import/no-unresolved": "off",
|
||||
"max-len": "off",
|
||||
"newline-per-chained-call": "off",
|
||||
"no-console": "off",
|
||||
"no-lonely-if": "off",
|
||||
"no-param-reassign": "off",
|
||||
@@ -73,7 +72,6 @@
|
||||
"radix": "off",
|
||||
"react/jsx-indent-props": ["error", 4],
|
||||
"react/prop-types": "off",
|
||||
"semi": "off",
|
||||
"vars-on-top": "off"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
jasmine.getFixtures().fixturesPath = '/base/templates';
|
||||
|
||||
import 'common/js/spec_helpers/jasmine-extensions';
|
||||
import 'common/js/spec_helpers/jasmine-stealth';
|
||||
import 'common/js/spec_helpers/jasmine-waituntil';
|
||||
@@ -12,11 +10,6 @@ import _ from 'underscore';
|
||||
import str from 'underscore.string';
|
||||
import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils';
|
||||
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
|
||||
window._ = _;
|
||||
window._.str = str;
|
||||
window.edx = window.edx || {};
|
||||
window.edx.HtmlUtils = HtmlUtils;
|
||||
window.edx.StringUtils = StringUtils;
|
||||
|
||||
// These are the tests that will be run
|
||||
import './xblock/cms.runtime.v1_spec.js';
|
||||
@@ -31,4 +24,12 @@ import '../../../js/spec/views/pages/course_outline_spec.js';
|
||||
import '../../../js/spec/views/xblock_editor_spec.js';
|
||||
import '../../../js/spec/views/xblock_string_field_editor_spec.js';
|
||||
|
||||
jasmine.getFixtures().fixturesPath = '/base/templates';
|
||||
|
||||
window._ = _;
|
||||
window._.str = str;
|
||||
window.edx = window.edx || {};
|
||||
window.edx.HtmlUtils = HtmlUtils;
|
||||
window.edx.StringUtils = StringUtils;
|
||||
|
||||
window.__karma__.start(); // eslint-disable-line no-underscore-dangle
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// http://tobyho.com/2012/01/30/write-a-jasmine-matcher/
|
||||
|
||||
define(['jquery'], function($) { // eslint-disable-line no-unused-vars
|
||||
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
return function() {
|
||||
jasmine.addMatchers({
|
||||
|
||||
@@ -64,16 +64,16 @@ function(_, $, Course, CertificatePreview, TemplateHelpers, ViewHelpers, AjaxHel
|
||||
|
||||
it('course mode selection updating the link successfully', function() {
|
||||
selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test1');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href')).
|
||||
toEqual('/users/1/courses/orgX/009/2016?preview=test1');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href'))
|
||||
.toEqual('/users/1/courses/orgX/009/2016?preview=test1');
|
||||
|
||||
selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test2');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href')).
|
||||
toEqual('/users/1/courses/orgX/009/2016?preview=test2');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href'))
|
||||
.toEqual('/users/1/courses/orgX/009/2016?preview=test2');
|
||||
|
||||
selectDropDownByText(this.view.$(SELECTORS.course_modes), 'test3');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href')).
|
||||
toEqual('/users/1/courses/orgX/009/2016?preview=test3');
|
||||
expect(this.view.$(SELECTORS.preview_certificate).attr('href'))
|
||||
.toEqual('/users/1/courses/orgX/009/2016?preview=test3');
|
||||
});
|
||||
|
||||
it('toggle certificate activation event works fine', function() {
|
||||
|
||||
@@ -21,6 +21,6 @@ export default function ContainerFactory(componentTemplates, XBlockInfoJson, act
|
||||
var view = new ContainerPage(_.extend(main_options, options));
|
||||
view.render();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {ContainerFactory}
|
||||
export {ContainerFactory};
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import * as ContextCourse from 'js/models/course';
|
||||
|
||||
export {ContextCourse}
|
||||
export {ContextCourse};
|
||||
|
||||
@@ -21,6 +21,6 @@ export default function EditTabsFactory(courseLocation, explicitUrl) {
|
||||
mast: $('.wrapper-mast')
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {EditTabsFactory}
|
||||
export {EditTabsFactory};
|
||||
|
||||
@@ -24,6 +24,6 @@ export default function LibraryFactory(componentTemplates, XBlockInfoJson, optio
|
||||
var view = new PagedContainerPage(_.extend(main_options, options));
|
||||
view.render();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {LibraryFactory}
|
||||
export {LibraryFactory};
|
||||
|
||||
@@ -16,9 +16,9 @@ define([
|
||||
|
||||
// Toggle collapsibles when trigger is clicked
|
||||
$('.collapsible .collapsible-trigger').click(function() {
|
||||
const contentId = this.id.replace('-trigger', '-content')
|
||||
$(`#${contentId}`).toggleClass('collapsed')
|
||||
})
|
||||
const contentId = this.id.replace('-trigger', '-content');
|
||||
$(`#${contentId}`).toggleClass('collapsed');
|
||||
});
|
||||
|
||||
model = new CourseDetailsModel();
|
||||
model.urlRoot = detailsUrl;
|
||||
|
||||
@@ -19,6 +19,6 @@ export default function TextbooksFactory(textbooksJson) {
|
||||
return gettext('You have unsaved changes. Do you really want to leave this page?');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {TextbooksFactory}
|
||||
export {TextbooksFactory};
|
||||
|
||||
@@ -16,6 +16,6 @@ export default function XBlockValidationFactory(validationMessages, hasEditingUr
|
||||
if (!model.get('empty')) {
|
||||
new XBlockValidationView({el: validationEle, model: model, root: isRoot}).render();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export {XBlockValidationFactory}
|
||||
export {XBlockValidationFactory};
|
||||
|
||||
@@ -10,7 +10,7 @@ define(['backbone', 'js/models/location', 'js/collections/course_grader', 'edx-u
|
||||
grace_period: null, // either null or { hours: n, minutes: m, ...}
|
||||
minimum_grade_credit: null, // either null or percentage
|
||||
assignment_count_info: [], // Object with keys mapping assignment type names to a list of
|
||||
//assignment display names
|
||||
// assignment display names
|
||||
},
|
||||
parse: function(attributes) {
|
||||
if (attributes.graders) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import 'jquery.smoothScroll';
|
||||
|
||||
'use strict';
|
||||
|
||||
var toggleSock = function (e) {
|
||||
var toggleSock = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $btnShowSockLabel = $(this).find('.copy-show');
|
||||
@@ -33,9 +33,9 @@ var toggleSock = function (e) {
|
||||
});
|
||||
};
|
||||
|
||||
domReady(function () {
|
||||
domReady(function() {
|
||||
// toggling footer additional support
|
||||
$('.cta-show-sock').bind('click', toggleSock);
|
||||
});
|
||||
|
||||
export {toggleSock}
|
||||
export {toggleSock};
|
||||
|
||||
@@ -147,7 +147,7 @@ define(['js/views/license', 'js/models/license', 'common/js/spec_helpers/templat
|
||||
this.view = new LicenseView({model: this.model, showPreview: true});
|
||||
this.view.render();
|
||||
expect(this.view.$('.license-preview').length).toEqual(1);
|
||||
// Expect default text to be "All Rights Reserved"
|
||||
// Expect default text to be "All Rights Reserved"
|
||||
expect(this.view.$('.license-preview')).toContainText('All Rights Reserved');
|
||||
this.view.$('li[data-license=creative-commons] button').click();
|
||||
expect(this.view.$('.license-preview').length).toEqual(1);
|
||||
|
||||
@@ -64,7 +64,7 @@ describe('ModuleEdit', function() {
|
||||
});
|
||||
});
|
||||
describe('render', function() {
|
||||
beforeEach(function () {
|
||||
beforeEach(function() {
|
||||
edit_helpers.installEditTemplates(true);
|
||||
spyOn(this.moduleEdit, 'loadDisplay');
|
||||
spyOn(this.moduleEdit, 'delegateEvents');
|
||||
|
||||
@@ -343,15 +343,15 @@ describe('Container Subviews', function() {
|
||||
it('renders the last published date and user when there are no changes', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({published_on: 'Jul 01, 2014 at 12:45 UTC', published_by: 'amako'});
|
||||
expect(containerPage.$(lastDraftCss).text()).
|
||||
toContain('Last published Jul 01, 2014 at 12:45 UTC by amako');
|
||||
expect(containerPage.$(lastDraftCss).text())
|
||||
.toContain('Last published Jul 01, 2014 at 12:45 UTC by amako');
|
||||
});
|
||||
|
||||
it('renders the last saved date and user when there are changes', function() {
|
||||
renderContainerPage(this, mockContainerXBlockHtml);
|
||||
fetch({has_changes: true, edited_on: 'Jul 02, 2014 at 14:20 UTC', edited_by: 'joe'});
|
||||
expect(containerPage.$(lastDraftCss).text()).
|
||||
toContain('Draft saved on Jul 02, 2014 at 14:20 UTC by joe');
|
||||
expect(containerPage.$(lastDraftCss).text())
|
||||
.toContain('Draft saved on Jul 02, 2014 at 14:20 UTC by joe');
|
||||
});
|
||||
|
||||
describe('Release Date', function() {
|
||||
@@ -596,8 +596,8 @@ describe('Container Subviews', function() {
|
||||
fetch({
|
||||
published: true, published_on: 'Jul 01, 2014 at 12:45 UTC', published_by: 'amako'
|
||||
});
|
||||
expect(containerPage.$(lastPublishCss).text()).
|
||||
toContain('Last published Jul 01, 2014 at 12:45 UTC by amako');
|
||||
expect(containerPage.$(lastPublishCss).text())
|
||||
.toContain('Last published Jul 01, 2014 at 12:45 UTC by amako');
|
||||
});
|
||||
|
||||
it('renders correctly when the block is published without publish info', function() {
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('CourseOutlinePage', function() {
|
||||
selectVisibilitySettings, selectDiscussionSettings, selectAdvancedSettings, createMockCourseJSON, createMockSectionJSON,
|
||||
createMockSubsectionJSON, verifyTypePublishable, mockCourseJSON, mockEmptyCourseJSON, setSelfPaced, setSelfPacedCustomPLS,
|
||||
mockSingleSectionCourseJSON, createMockVerticalJSON, createMockIndexJSON, mockCourseEntranceExamJSON,
|
||||
selectOnboardingExam, createMockCourseJSONWithReviewRules,mockCourseJSONWithReviewRules,
|
||||
selectOnboardingExam, createMockCourseJSONWithReviewRules, mockCourseJSONWithReviewRules,
|
||||
mockOutlinePage = readFixtures('templates/mock/mock-course-outline-page.underscore'),
|
||||
mockRerunNotification = readFixtures('templates/mock/mock-course-rerun-notification.underscore');
|
||||
|
||||
@@ -210,7 +210,7 @@ describe('CourseOutlinePage', function() {
|
||||
setSelfPacedCustomPLS = function() {
|
||||
setSelfPaced();
|
||||
course.set('is_custom_relative_dates_active', true);
|
||||
}
|
||||
};
|
||||
|
||||
createCourseOutlinePage = function(test, courseJSON, createOnly) {
|
||||
requests = AjaxHelpers.requests(test);
|
||||
@@ -1458,7 +1458,7 @@ describe('CourseOutlinePage', function() {
|
||||
$('.wrapper-modal-window .action-save').click();
|
||||
});
|
||||
|
||||
it('can select the onboarding exam when a course supports onboarding', function () {
|
||||
it('can select the onboarding exam when a course supports onboarding', function() {
|
||||
var mockCourseWithSpecialExamJSON = createMockCourseJSON({}, [
|
||||
createMockSectionJSON({
|
||||
has_changes: true,
|
||||
@@ -2191,7 +2191,7 @@ describe('CourseOutlinePage', function() {
|
||||
expect($modalWindow.find('.outline-subsection')).not.toExist();
|
||||
});
|
||||
|
||||
describe('Self Paced with Custom Personalized Learner Schedules (PLS)', function () {
|
||||
describe('Self Paced with Custom Personalized Learner Schedules (PLS)', function() {
|
||||
beforeEach(function() {
|
||||
var mockCourseJSON = createMockCourseJSON({}, [
|
||||
createMockSectionJSON({}, [
|
||||
@@ -2210,7 +2210,7 @@ describe('CourseOutlinePage', function() {
|
||||
|
||||
selectRelativeWeeksSubsection = function(weeks) {
|
||||
$('#due_in').val(weeks).trigger('keyup');
|
||||
}
|
||||
};
|
||||
|
||||
mockCustomPacingServerValuesJson = createMockSectionJSON({
|
||||
release_date: 'Jan 01, 2970 at 05:00 UTC'
|
||||
@@ -2235,7 +2235,7 @@ describe('CourseOutlinePage', function() {
|
||||
])
|
||||
]);
|
||||
|
||||
it('can show correct editors for self_paced course with custom pacing', function (){
|
||||
it('can show correct editors for self_paced course with custom pacing', function() {
|
||||
outlinePage.$('.outline-subsection .configure-button').click();
|
||||
expect($('.edit-settings-release').length).toBe(0);
|
||||
// Due date input exists for custom pacing self paced courses
|
||||
@@ -2295,7 +2295,7 @@ describe('CourseOutlinePage', function() {
|
||||
expectShowCorrectness('never');
|
||||
});
|
||||
|
||||
it ('does not show relative date input when assignment is not graded', function() {
|
||||
it('does not show relative date input when assignment is not graded', function() {
|
||||
outlinePage.$('.outline-subsection .configure-button').click();
|
||||
$('#grading_type').val('Lab').trigger('change');
|
||||
$('#due_in').val('').trigger('change');
|
||||
@@ -2304,7 +2304,7 @@ describe('CourseOutlinePage', function() {
|
||||
$('#grading_type').val('notgraded').trigger('change');
|
||||
$('#due_in').val('').trigger('change');
|
||||
expect($('#relative_date_input').css('display')).toBe('none');
|
||||
})
|
||||
});
|
||||
|
||||
it('shows validation error on relative date', function() {
|
||||
outlinePage.$('.outline-subsection .configure-button').click();
|
||||
@@ -2371,7 +2371,7 @@ describe('CourseOutlinePage', function() {
|
||||
'Contains staff only content'
|
||||
);
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
// Note: most tests for units can be found in Bok Choy
|
||||
@@ -2470,13 +2470,12 @@ describe('CourseOutlinePage', function() {
|
||||
expect(messages).toContainText('Contains staff only content');
|
||||
});
|
||||
|
||||
describe('discussion settings', function () {
|
||||
describe('discussion settings', function() {
|
||||
it('hides discussion settings if unit level discussions are disabled', function() {
|
||||
getUnitStatus({}, {unit_level_discussions: false});
|
||||
outlinePage.$('.outline-unit .configure-button').click();
|
||||
expect($('.modal-section .edit-discussion')).not.toExist();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
verifyTypePublishable('unit', function(options) {
|
||||
|
||||
@@ -110,8 +110,8 @@ define(['jquery', 'js/models/xblock_validation', 'js/views/xblock_validation', '
|
||||
it('renders action info', function() {
|
||||
expect(view.$('a.edit-button .action-button-text').text()).toContain('Summary Action');
|
||||
|
||||
expect(view.$('a.notification-action-button .action-button-text').text()).
|
||||
toContain('First Message Action');
|
||||
expect(view.$('a.notification-action-button .action-button-text').text())
|
||||
.toContain('First Message Action');
|
||||
expect(view.$('a.notification-action-button').data('notification-action')).toBe('fix-up');
|
||||
});
|
||||
|
||||
|
||||
@@ -138,4 +138,4 @@ export {
|
||||
installEditTemplates,
|
||||
showEditModal,
|
||||
verifyXBlockRequest,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,66 +1,67 @@
|
||||
define([
|
||||
"jquery",
|
||||
"underscore",
|
||||
"backbone",
|
||||
"js/views/utils/xblock_utils",
|
||||
"js/utils/templates",
|
||||
"js/views/modals/course_outline_modals",
|
||||
"edx-ui-toolkit/js/utils/html-utils",
|
||||
], function ($, _, Backbone, XBlockViewUtils, TemplateUtils, CourseOutlineModalsFactory, HtmlUtils) {
|
||||
"use strict";
|
||||
var CourseVideoSharingEnableView = Backbone.View.extend({
|
||||
events: {
|
||||
"change #video-sharing-configuration-options": "handleVideoSharingConfigurationChange",
|
||||
},
|
||||
'jquery',
|
||||
'underscore',
|
||||
'backbone',
|
||||
'js/views/utils/xblock_utils',
|
||||
'js/utils/templates',
|
||||
'js/views/modals/course_outline_modals',
|
||||
'edx-ui-toolkit/js/utils/html-utils',
|
||||
], function($, _, Backbone, XBlockViewUtils, TemplateUtils, CourseOutlineModalsFactory, HtmlUtils) {
|
||||
'use strict';
|
||||
|
||||
initialize: function () {
|
||||
this.template = TemplateUtils.loadTemplate("course-video-sharing-enable");
|
||||
},
|
||||
|
||||
getRequestData: function (value) {
|
||||
return {
|
||||
metadata: {
|
||||
'video_sharing_options': value,
|
||||
var CourseVideoSharingEnableView = Backbone.View.extend({
|
||||
events: {
|
||||
'change #video-sharing-configuration-options': 'handleVideoSharingConfigurationChange',
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
handleVideoSharingConfigurationChange: function (event) {
|
||||
if (event.type === "change") {
|
||||
event.preventDefault();
|
||||
this.updateVideoSharingConfiguration(event.target.value);
|
||||
this.trackVideoSharingConfigurationChange(event.target.value);
|
||||
}
|
||||
},
|
||||
initialize: function() {
|
||||
this.template = TemplateUtils.loadTemplate('course-video-sharing-enable');
|
||||
},
|
||||
|
||||
updateVideoSharingConfiguration: function (value) {
|
||||
XBlockViewUtils.updateXBlockFields(this.model, this.getRequestData(value), {
|
||||
success: this.refresh.bind(this)
|
||||
});
|
||||
},
|
||||
getRequestData: function(value) {
|
||||
return {
|
||||
metadata: {
|
||||
video_sharing_options: value,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
trackVideoSharingConfigurationChange: function (value) {
|
||||
window.analytics.track(
|
||||
'edx.social.video_sharing_options.changed',
|
||||
{
|
||||
course_id: this.model.id,
|
||||
video_sharing_options: value
|
||||
}
|
||||
);
|
||||
},
|
||||
handleVideoSharingConfigurationChange: function(event) {
|
||||
if (event.type === 'change') {
|
||||
event.preventDefault();
|
||||
this.updateVideoSharingConfiguration(event.target.value);
|
||||
this.trackVideoSharingConfigurationChange(event.target.value);
|
||||
}
|
||||
},
|
||||
|
||||
refresh: function () {
|
||||
this.model.fetch({
|
||||
success: this.render.bind(this),
|
||||
});
|
||||
},
|
||||
updateVideoSharingConfiguration: function(value) {
|
||||
XBlockViewUtils.updateXBlockFields(this.model, this.getRequestData(value), {
|
||||
success: this.refresh.bind(this)
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var html = this.template(this.model.attributes);
|
||||
HtmlUtils.setHtml(this.$el, HtmlUtils.HTML(html));
|
||||
return this;
|
||||
},
|
||||
});
|
||||
trackVideoSharingConfigurationChange: function(value) {
|
||||
window.analytics.track(
|
||||
'edx.social.video_sharing_options.changed',
|
||||
{
|
||||
course_id: this.model.id,
|
||||
video_sharing_options: value
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
return CourseVideoSharingEnableView;
|
||||
refresh: function() {
|
||||
this.model.fetch({
|
||||
success: this.render.bind(this),
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var html = this.template(this.model.attributes);
|
||||
HtmlUtils.setHtml(this.$el, HtmlUtils.HTML(html));
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
return CourseVideoSharingEnableView;
|
||||
});
|
||||
|
||||
@@ -313,7 +313,7 @@ define(
|
||||
updateUrlFieldVisibility: function() {
|
||||
const urlContainer = this.$el.find('.public-access-block-url-container');
|
||||
|
||||
if(this.getValueFromEditor()) {
|
||||
if (this.getValueFromEditor()) {
|
||||
urlContainer.removeClass('is-hidden');
|
||||
} else {
|
||||
urlContainer.addClass('is-hidden');
|
||||
|
||||
@@ -408,11 +408,11 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
if (!this.getValue() || !course.get('start')) { return; }
|
||||
var startDate = new Date(course.get('start'));
|
||||
// The value returned by toUTCString() is a string in the form Www, dd Mmm yyyy hh:mm:ss GMT
|
||||
var startDateList = startDate.toUTCString().split(' ')
|
||||
var startDateList = startDate.toUTCString().split(' ');
|
||||
// This text will look like Mmm dd, yyyy (i.e. Jul 26, 2021)
|
||||
this.$('#relative_weeks_due_start_date').text(startDateList[2] + ' ' + startDateList[1] + ', ' + startDateList[3]);
|
||||
var projectedDate = new Date(startDate)
|
||||
projectedDate.setDate(projectedDate.getDate() + this.getValue()*7);
|
||||
var projectedDate = new Date(startDate);
|
||||
projectedDate.setDate(projectedDate.getDate() + this.getValue() * 7);
|
||||
var projectedDateList = projectedDate.toUTCString().split(' ');
|
||||
this.$('#relative_weeks_due_projected_due_in').text(projectedDateList[2] + ' ' + projectedDateList[1] + ', ' + projectedDateList[3]);
|
||||
this.$('#relative_weeks_due_projected').show();
|
||||
@@ -433,9 +433,9 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
afterRender: function() {
|
||||
AbstractEditor.prototype.afterRender.call(this);
|
||||
if (this.model.get('graded')) {
|
||||
this.$('#relative_date_input').show()
|
||||
this.$('#relative_date_input').show();
|
||||
} else {
|
||||
this.$('#relative_date_input').hide()
|
||||
this.$('#relative_date_input').hide();
|
||||
}
|
||||
this.$('.field-due-in input').val(this.model.get('relative_weeks_due'));
|
||||
this.$('#relative_weeks_due_projected').hide();
|
||||
@@ -444,12 +444,12 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
|
||||
getRequestData: function() {
|
||||
// Grab all the sections, map them to their block_ids, then return as an Array
|
||||
var sectionIds = $('.outline-section').map(function(){ return this.id; }).get()
|
||||
var sectionIds = $('.outline-section').map(function() { return this.id; }).get();
|
||||
// Grab all the subsections, map them to their block_ids, then return as an Array
|
||||
var subsectionIds = $('.outline-subsection').map(function(){ return this.id; }).get()
|
||||
var subsectionIds = $('.outline-subsection').map(function() { return this.id; }).get();
|
||||
var relative_weeks_due = null;
|
||||
if (this.getValue() > 0 && $('#grading_type').val() !== 'notgraded') {
|
||||
relative_weeks_due = this.getValue()
|
||||
relative_weeks_due = this.getValue();
|
||||
}
|
||||
window.analytics.track('edx.bi.studio.relative_date.saved', {
|
||||
block_id: this.model.get('id'),
|
||||
@@ -944,16 +944,16 @@ define(['jquery', 'backbone', 'underscore', 'gettext', 'js/views/baseview',
|
||||
|
||||
showTipText: function() {
|
||||
if (this.model.get('published')) {
|
||||
$('.un-published-tip').hide()
|
||||
$('.un-published-tip').hide();
|
||||
} else {
|
||||
$('.un-published-tip').show()
|
||||
$('.un-published-tip').show();
|
||||
}
|
||||
let enabledForGraded = course.get('discussions_settings').enable_graded_units
|
||||
let enabledForGraded = course.get('discussions_settings').enable_graded_units;
|
||||
if (this.model.get('graded') && !enabledForGraded) {
|
||||
$('#discussion_enabled').prop('disabled', true);
|
||||
$('.graded-tip').show()
|
||||
$('.graded-tip').show();
|
||||
} else {
|
||||
$('.graded-tip').hide()
|
||||
$('.graded-tip').hide();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ function($, _, ViewUtils, ContainerView, ModuleUtils, gettext, NotificationView,
|
||||
if (originalDone) {
|
||||
originalDone();
|
||||
}
|
||||
}
|
||||
};
|
||||
self.handleXBlockFragment(fragment, options);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -265,15 +265,15 @@ function($, _, Backbone, gettext, BasePage, ViewUtils, ContainerView, XBlockView
|
||||
editXBlock: function(event, options) {
|
||||
event.preventDefault();
|
||||
|
||||
if(!options || options.view !== 'visibility_view' ){
|
||||
const primaryHeader = $(event.target).closest('.xblock-header-primary')
|
||||
if (!options || options.view !== 'visibility_view') {
|
||||
const primaryHeader = $(event.target).closest('.xblock-header-primary');
|
||||
|
||||
var useNewTextEditor = primaryHeader.attr('use-new-editor-text'),
|
||||
useNewVideoEditor = primaryHeader.attr('use-new-editor-video'),
|
||||
useNewProblemEditor = primaryHeader.attr('use-new-editor-problem'),
|
||||
blockType = primaryHeader.attr('data-block-type');
|
||||
|
||||
if( (useNewTextEditor === 'True' && blockType === 'html')
|
||||
if((useNewTextEditor === 'True' && blockType === 'html')
|
||||
|| (useNewVideoEditor === 'True' && blockType === 'video')
|
||||
|| (useNewProblemEditor === 'True' && blockType === 'problem')
|
||||
) {
|
||||
@@ -476,13 +476,13 @@ function($, _, Backbone, gettext, BasePage, ViewUtils, ContainerView, XBlockView
|
||||
useNewProblemEditor = this.$('.xblock-header-primary').attr('use-new-editor-problem');
|
||||
|
||||
// find the block type in the locator if availible
|
||||
if(data.hasOwnProperty('locator')){
|
||||
if(data.hasOwnProperty('locator')) {
|
||||
var matchBlockTypeFromLocator = /\@(.*?)\+/;
|
||||
var blockType = data.locator.match(matchBlockTypeFromLocator);
|
||||
}
|
||||
if((useNewTextEditor === 'True' && blockType.includes('html'))
|
||||
|| (useNewVideoEditor === 'True' && blockType.includes('video'))
|
||||
||(useNewProblemEditor === 'True' && blockType.includes('problem'))
|
||||
|| (useNewProblemEditor === 'True' && blockType.includes('problem'))
|
||||
){
|
||||
var destinationUrl = this.$('.xblock-header-primary').attr('authoring_MFE_base_url') + '/' + blockType[1] + '/' + encodeURI(data.locator);
|
||||
window.location.href = destinationUrl;
|
||||
|
||||
@@ -125,7 +125,7 @@ function($, _, gettext, BasePage, XBlockViewUtils, CourseOutlineView, ViewUtils,
|
||||
* at 100 millisecond intervals until element is found or
|
||||
* Polling is reached
|
||||
*/
|
||||
scrollToElement: function () {
|
||||
scrollToElement: function() {
|
||||
this.findElementPollingTimeout -= this.pollingDelay;
|
||||
|
||||
const elementID = window.location.hash.replace('#', '');
|
||||
|
||||
@@ -75,7 +75,7 @@ function(ValidatingView, _, $, ui, GraderView, StringUtils, HtmlUtils) {
|
||||
this);
|
||||
gradeCollection.each(function(gradeModel) {
|
||||
var graderType = gradeModel.get('type');
|
||||
var graderTypeAssignmentList = self.courseAssignmentLists[graderType]
|
||||
var graderTypeAssignmentList = self.courseAssignmentLists[graderType];
|
||||
if (graderTypeAssignmentList === undefined) {
|
||||
graderTypeAssignmentList = [];
|
||||
}
|
||||
|
||||
@@ -388,7 +388,7 @@ function(ValidatingView, CodeMirror, _, $, ui, DateUtils, FileUploadModel,
|
||||
Hides and clears the certificate available date field if a display behavior that doesn't use it is
|
||||
chosen. Because we are clearing it, toggling back to "end_with_date" will require re-entering the date
|
||||
*/
|
||||
if (!this.useV2CertDisplaySettings){
|
||||
if (!this.useV2CertDisplaySettings) {
|
||||
return;
|
||||
}
|
||||
let showDatepicker = this.model.get('certificates_display_behavior') == 'end_with_date';
|
||||
@@ -402,7 +402,7 @@ function(ValidatingView, CodeMirror, _, $, ui, DateUtils, FileUploadModel,
|
||||
datepicker.prop('disabled', true);
|
||||
datepicker.val(null);
|
||||
this.clearValidationErrors();
|
||||
this.setAndValidate('certificate_available_date', null)
|
||||
this.setAndValidate('certificate_available_date', null);
|
||||
certificateAvailableDateField.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
||||
|
||||
var options = {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
||||
|
||||
var options = {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
||||
|
||||
var options = {
|
||||
|
||||
@@ -34,7 +34,7 @@ const BlockType = PropTypes.shape({
|
||||
});
|
||||
|
||||
export const BlockList = ({
|
||||
blocks, selectedBlock, onSelectBlock, onChangeRoot
|
||||
blocks, selectedBlock, onSelectBlock, onChangeRoot,
|
||||
}) => (
|
||||
<ul className="block-list">
|
||||
{blocks.map(block => (
|
||||
@@ -48,11 +48,12 @@ export const BlockList = ({
|
||||
label={block.display_name}
|
||||
/>
|
||||
{block.children
|
||||
&& <Button
|
||||
onClick={() => onChangeRoot(block.id)}
|
||||
label={RightIcon}
|
||||
/>
|
||||
}
|
||||
&& (
|
||||
<Button
|
||||
onClick={() => onChangeRoot(block.id)}
|
||||
label={RightIcon}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@@ -71,7 +72,7 @@ BlockList.defaultProps = {
|
||||
};
|
||||
|
||||
export const BlockBrowser = ({
|
||||
blocks, selectedBlock, onSelectBlock, onChangeRoot, className
|
||||
blocks, selectedBlock, onSelectBlock, onChangeRoot, className,
|
||||
}) => !!blocks && (
|
||||
<div className={classNames('block-browser', className)}>
|
||||
<div className="header">
|
||||
|
||||
@@ -29,4 +29,4 @@ export const getCourseBlocks = courseId => fetch(`${COURSE_BLOCKS_API}?${buildQu
|
||||
credentials: 'same-origin',
|
||||
method: 'get',
|
||||
headers: HEADERS,
|
||||
},);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ function NextArrow(props) {
|
||||
} = props;
|
||||
const showArrow = slideCount - currentSlide > displayedSlides;
|
||||
const opts = {
|
||||
className: classNames('js-carousel-nav', 'carousel-arrow', 'next', 'btn btn-secondary', {'active': showArrow}),
|
||||
className: classNames('js-carousel-nav', 'carousel-arrow', 'next', 'btn btn-secondary', {active: showArrow}),
|
||||
onClick
|
||||
};
|
||||
|
||||
@@ -22,8 +22,8 @@ function NextArrow(props) {
|
||||
return (
|
||||
<button {...opts}>
|
||||
<span>Next </span>
|
||||
<span className="icon fa fa-chevron-right" aria-hidden="true"></span>
|
||||
<span className="sr">{ 'Scroll carousel forwards' }</span>
|
||||
<span className="icon fa fa-chevron-right" aria-hidden="true" />
|
||||
<span className="sr">Scroll carousel forwards</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -32,7 +32,7 @@ function PrevArrow(props) {
|
||||
const {currentSlide, onClick} = props;
|
||||
const showArrow = currentSlide > 0;
|
||||
const opts = {
|
||||
className: classNames('js-carousel-nav', 'carousel-arrow', 'prev', 'btn btn-secondary', {'active': showArrow}),
|
||||
className: classNames('js-carousel-nav', 'carousel-arrow', 'prev', 'btn btn-secondary', {active: showArrow}),
|
||||
onClick
|
||||
};
|
||||
|
||||
@@ -41,10 +41,10 @@ function PrevArrow(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<button {...opts} >
|
||||
<span className="icon fa fa-chevron-left" aria-hidden="true"></span>
|
||||
<button {...opts}>
|
||||
<span className="icon fa fa-chevron-left" aria-hidden="true" />
|
||||
<span> Prev</span>
|
||||
<span className="sr">{ 'Scroll carousel backwards' }</span>
|
||||
<span className="sr">Scroll carousel backwards</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ export default class ExperimentalCarousel extends React.Component {
|
||||
},
|
||||
tabIndex: tabIndex,
|
||||
className: 'carousel-item'
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div {...carouselLinkProps}>
|
||||
@@ -113,7 +113,7 @@ export default class ExperimentalCarousel extends React.Component {
|
||||
};
|
||||
|
||||
return (
|
||||
<Slider {...carouselSettings} >
|
||||
<Slider {...carouselSettings}>
|
||||
{this.getCarouselContent()}
|
||||
</Slider>
|
||||
);
|
||||
@@ -122,4 +122,4 @@ export default class ExperimentalCarousel extends React.Component {
|
||||
|
||||
ExperimentalCarousel.propTypes = {
|
||||
slides: PropTypes.array.isRequired
|
||||
};
|
||||
};
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
Content.prototype.incrementVote = function(increment) {
|
||||
var newVotes;
|
||||
newVotes = _.clone(this.get('votes'));
|
||||
newVotes.up_count = newVotes.up_count + increment;
|
||||
newVotes.up_count += increment;
|
||||
return this.set('votes', newVotes);
|
||||
};
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
if (_.isUndefined(userId)) {
|
||||
userId = this.user ? this.user.id : void 0;
|
||||
}
|
||||
if(_.isUndefined(this.roleIds)) {
|
||||
this.roleIds = {}
|
||||
if (_.isUndefined(this.roleIds)) {
|
||||
this.roleIds = {};
|
||||
}
|
||||
staff = _.union(this.roleIds.Moderator, this.roleIds.Administrator);
|
||||
return _.include(staff, parseInt(userId));
|
||||
@@ -77,7 +77,9 @@
|
||||
DiscussionUtil.generateDiscussionLink = function(cls, txt, handler) {
|
||||
return $('<a>')
|
||||
.addClass('discussion-link').attr('href', '#')
|
||||
.addClass(cls).text(txt).click(function() { return handler(this); });
|
||||
.addClass(cls)
|
||||
.text(txt)
|
||||
.click(function() { return handler(this); });
|
||||
};
|
||||
|
||||
DiscussionUtil.urlFor = function(name, param, param1, param2) {
|
||||
@@ -484,7 +486,6 @@
|
||||
element,
|
||||
this.postMathJaxProcessor(this.markdownWithHighlight(element.text()))
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
DiscussionUtil.typesetMathJax = function(element) {
|
||||
|
||||
@@ -9,4 +9,4 @@ jasmine.getFixtures().fixturesPath = '/base/';
|
||||
// Stub out modal dialog alerts, which will prevent
|
||||
// us from accessing the test results in the DOM
|
||||
window.confirm = function() { return true; };
|
||||
window.alert = function() { return; };
|
||||
window.alert = function() { };
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
initialized we can't override the ExceptionFormatter as Jasmine then uses the stored reference to the function */
|
||||
(function() {
|
||||
/* globals jasmineRequire */
|
||||
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
var OldExceptionFormatter = jasmineRequire.ExceptionFormatter(),
|
||||
oldExceptionFormatter = new OldExceptionFormatter(),
|
||||
|
||||
@@ -40,9 +40,11 @@
|
||||
|
||||
var path = require('path');
|
||||
var _ = require('underscore');
|
||||
|
||||
var appRoot = path.join(__dirname, '../../../../');
|
||||
var webdriver = require('selenium-webdriver');
|
||||
var firefox = require('selenium-webdriver/firefox');
|
||||
|
||||
var webpackConfig = require(path.join(appRoot, 'webpack.dev.config.js'));
|
||||
|
||||
// The following crazy bit is to work around the webpack.optimize.CommonsChunkPlugin
|
||||
|
||||
@@ -57,11 +57,11 @@
|
||||
_ref >= 0 ? _i <= _ref : _i >= _ref;
|
||||
i = _ref >= 0 ? ++_i : --_i
|
||||
) {
|
||||
threadData.body = threadData.body + imageTag;
|
||||
threadData.body += imageTag;
|
||||
if (i === 0) {
|
||||
expectedHtml = expectedHtml + imageTag;
|
||||
expectedHtml += imageTag;
|
||||
} else {
|
||||
expectedHtml = expectedHtml + '<em>image omitted</em>';
|
||||
expectedHtml += '<em>image omitted</em>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +80,6 @@
|
||||
callbackFunc(draggableObj);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
return;
|
||||
} else {
|
||||
if (draggableObj.originalConfigObj.label.length > 0) {
|
||||
draggableObj.iconEl = $(HtmlUtils.joinHtml(
|
||||
@@ -101,8 +99,6 @@
|
||||
setTimeout(function() {
|
||||
callbackFunc(draggableObj);
|
||||
}, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
describe('interpolate_ntext', function() {
|
||||
it('replaces placeholder values', function() {
|
||||
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 1, {count: 1})).
|
||||
toBe('contains 1 student');
|
||||
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 5, {count: 2})).
|
||||
toBe('contains 2 students');
|
||||
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 1, {count: 1}))
|
||||
.toBe('contains 1 student');
|
||||
expect(interpolate_ntext('contains {count} student', 'contains {count} students', 5, {count: 2}))
|
||||
.toBe('contains 2 students');
|
||||
});
|
||||
});
|
||||
|
||||
describe('interpolate_text', function() {
|
||||
it('replaces placeholder values', function() {
|
||||
expect(interpolate_text('contains {adjective} students', {adjective: 'awesome'})).
|
||||
toBe('contains awesome students');
|
||||
expect(interpolate_text('contains {adjective} students', {adjective: 'awesome'}))
|
||||
.toBe('contains awesome students');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import CookieBanner from '@edx/frontend-component-cookie-policy-banner';
|
||||
|
||||
export function CookiePolicyBanner() { return <CookieBanner />; };
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export function CookiePolicyBanner() { return <CookieBanner />; }
|
||||
|
||||
@@ -151,7 +151,7 @@ var accessible_modal = function(trigger, closeButtonId, modalId, mainPageId) {
|
||||
// see http://accessibility.oit.ncsu.edu/blog/2013/09/13/the-incredible-accessible-modal-dialog/
|
||||
// for more information on managing modals
|
||||
//
|
||||
var initialFocus
|
||||
var initialFocus;
|
||||
$(trigger).click(function() {
|
||||
$focusedElementBeforeModal = $(trigger);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
||||
|
||||
var options = {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
|
||||
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
|
||||
|
||||
var options = {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
module.exports = {
|
||||
'globals': {
|
||||
'gettext': (t) => { return t; },
|
||||
globals: {
|
||||
gettext: (t) => t,
|
||||
},
|
||||
'modulePaths': [
|
||||
modulePaths: [
|
||||
'common/static/common/js/components',
|
||||
],
|
||||
'setupFilesAfterEnv': ['<rootDir>/setupTests.js'],
|
||||
'testMatch': [
|
||||
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
|
||||
testMatch: [
|
||||
'/**/*.test.jsx',
|
||||
'common/static/common/js/components/**/?(*.)+(spec|test).js?(x)',
|
||||
],
|
||||
'testEnvironment': 'jsdom',
|
||||
'transform': {
|
||||
testEnvironment: 'jsdom',
|
||||
transform: {
|
||||
'^.+\\.jsx$': 'babel-jest',
|
||||
'^.+\\.js$': 'babel-jest',
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ export default class Main extends React.Component {
|
||||
this.props.problemResponsesEndpoint,
|
||||
this.props.taskStatusEndpoint,
|
||||
this.props.reportDownloadEndpoint,
|
||||
this.props.selectedBlock
|
||||
this.props.selectedBlock,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ describe('ProblemBrowser Main component', () => {
|
||||
fetchCourseBlocks={jest.fn()}
|
||||
problemResponsesEndpoint={problemResponsesEndpoint}
|
||||
onSelectBlock={jest.fn()}
|
||||
selectedBlock={'some-selected-block'}
|
||||
selectedBlock="some-selected-block"
|
||||
taskStatusEndpoint={taskStatusEndpoint}
|
||||
/>
|
||||
</Provider>,
|
||||
@@ -64,7 +64,7 @@ describe('ProblemBrowser Main component', () => {
|
||||
fetchCourseBlocks={fetchCourseBlocksMock}
|
||||
problemResponsesEndpoint={problemResponsesEndpoint}
|
||||
onSelectBlock={jest.fn()}
|
||||
selectedBlock={'some-selected-block'}
|
||||
selectedBlock="some-selected-block"
|
||||
taskStatusEndpoint={taskStatusEndpoint}
|
||||
/>
|
||||
</Provider>,
|
||||
@@ -83,7 +83,7 @@ describe('ProblemBrowser Main component', () => {
|
||||
fetchCourseBlocks={jest.fn()}
|
||||
problemResponsesEndpoint={problemResponsesEndpoint}
|
||||
onSelectBlock={jest.fn()}
|
||||
selectedBlock={'some-selected-block'}
|
||||
selectedBlock="some-selected-block"
|
||||
taskStatusEndpoint={taskStatusEndpoint}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
(courseId, excludeBlockTypes) => dispatch(fetchCourseBlocks(courseId, excludeBlockTypes)),
|
||||
createProblemResponsesReportTask:
|
||||
(problemResponsesEndpoint, taskStatusEndpoint, reportDownloadEndpoint, problemLocation) => dispatch(
|
||||
createProblemResponsesReportTask(problemResponsesEndpoint, taskStatusEndpoint, reportDownloadEndpoint, problemLocation,),
|
||||
createProblemResponsesReportTask(problemResponsesEndpoint, taskStatusEndpoint, reportDownloadEndpoint, problemLocation),
|
||||
),
|
||||
});
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as PropTypes from 'prop-types';
|
||||
import * as React from 'react';
|
||||
|
||||
const ReportStatus = ({
|
||||
error, succeeded, inProgress, reportPath
|
||||
error, succeeded, inProgress, reportPath,
|
||||
}) => {
|
||||
const progressMessage = (
|
||||
<div className="msg progress">
|
||||
|
||||
@@ -23,8 +23,8 @@ describe('ReportStatus component', () => {
|
||||
<ReportStatus
|
||||
error={null}
|
||||
inProgress={false}
|
||||
reportName={'some-report-name'}
|
||||
reportPath={'/some/report/path.csv'}
|
||||
reportName="some-report-name"
|
||||
reportPath="/some/report/path.csv"
|
||||
succeeded
|
||||
/>,
|
||||
);
|
||||
@@ -35,7 +35,7 @@ describe('ReportStatus component', () => {
|
||||
test('render error status', () => {
|
||||
const component = renderer.create(
|
||||
<ReportStatus
|
||||
error={'some error status'}
|
||||
error="some error status"
|
||||
inProgress={false}
|
||||
reportName={null}
|
||||
reportPath={null}
|
||||
|
||||
@@ -15,14 +15,14 @@ function initiateProblemResponsesRequest(endpoint, blockId) {
|
||||
method: 'post',
|
||||
headers: HEADERS,
|
||||
body: formData,
|
||||
},);
|
||||
});
|
||||
}
|
||||
|
||||
const fetchTaskStatus = (endpoint, taskId) => fetch(`${endpoint}/?task_id=${taskId}`, {
|
||||
credentials: 'same-origin',
|
||||
method: 'get',
|
||||
headers: HEADERS,
|
||||
},);
|
||||
});
|
||||
|
||||
const fetchDownloadsList = (endpoint, reportName) => {
|
||||
const formData = new FormData();
|
||||
@@ -33,7 +33,7 @@ const fetchDownloadsList = (endpoint, reportName) => {
|
||||
method: 'POST',
|
||||
headers: HEADERS,
|
||||
body: formData,
|
||||
},);
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
|
||||
@@ -13,9 +13,9 @@ const mapStateToProps = state => ({
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
createEntitlement: ({
|
||||
username, courseUuid, mode, comments
|
||||
username, courseUuid, mode, comments,
|
||||
}) => dispatch(createEntitlement({
|
||||
username, courseUuid, mode, comments
|
||||
username, courseUuid, mode, comments,
|
||||
})),
|
||||
reissueEntitlement: ({ entitlement, comments }) => dispatch(reissueEntitlement({ entitlement, comments })),
|
||||
closeForm: () => dispatch(closeForm()),
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
Button, InputSelect, InputText, TextArea
|
||||
Button, InputSelect, InputText, TextArea,
|
||||
} from '@edx/paragon';
|
||||
import { formTypes } from '../../data/constants/formTypes';
|
||||
|
||||
@@ -57,21 +57,21 @@ class EntitlementForm extends React.Component {
|
||||
|
||||
submitForm() {
|
||||
const {
|
||||
courseUuid, username, mode, comments
|
||||
courseUuid, username, mode, comments,
|
||||
} = this.state;
|
||||
const { formType, entitlement } = this.props;
|
||||
if (formType === formTypes.REISSUE) { // if there is an active entitlement we are updating an entitlement
|
||||
this.props.reissueEntitlement({ entitlement, comments });
|
||||
} else { // if there is no active entitlement we are creating a new entitlement
|
||||
this.props.createEntitlement({
|
||||
courseUuid, username, mode, comments
|
||||
courseUuid, username, mode, comments,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
courseUuid, username, mode, comments
|
||||
courseUuid, username, mode, comments,
|
||||
} = this.state;
|
||||
const isReissue = this.props.formType === formTypes.REISSUE;
|
||||
const title = isReissue ? 'Re-issue Entitlement' : 'Create Entitlement';
|
||||
|
||||
@@ -47,7 +47,7 @@ const entitlementColumns = [
|
||||
|
||||
const parseEntitlementData = (entitlements, ecommerceUrl, openReissueForm) => entitlements.map((entitlement) => {
|
||||
const {
|
||||
expiredAt, created, modified, orderNumber, enrollmentCourseRun
|
||||
expiredAt, created, modified, orderNumber, enrollmentCourseRun,
|
||||
} = entitlement;
|
||||
return Object.assign({}, entitlement, {
|
||||
expiredAt: expiredAt ? moment(expiredAt).format('lll') : '',
|
||||
|
||||
@@ -67,7 +67,7 @@ const createEntitlementSuccess = entitlement => ({
|
||||
const createEntitlementFailure = error => dispatch => dispatch(displayError('Error Creating Entitlement', error));
|
||||
|
||||
const createEntitlement = ({
|
||||
username, courseUuid, mode, comments
|
||||
username, courseUuid, mode, comments,
|
||||
}) => (dispatch) => {
|
||||
postEntitlement({
|
||||
username,
|
||||
|
||||
@@ -12,10 +12,10 @@ const HEADERS = {
|
||||
const getEntitlements = username => fetch(`${entitlementApi}?user=${username}`, {
|
||||
credentials: 'same-origin',
|
||||
method: 'get',
|
||||
},);
|
||||
});
|
||||
|
||||
const postEntitlement = ({
|
||||
username, courseUuid, mode, action, comments = null
|
||||
username, courseUuid, mode, action, comments = null,
|
||||
}) => fetch(`${entitlementApi}`, {
|
||||
credentials: 'same-origin',
|
||||
method: 'post',
|
||||
@@ -30,10 +30,10 @@ const postEntitlement = ({
|
||||
comments,
|
||||
}],
|
||||
}),
|
||||
},);
|
||||
});
|
||||
|
||||
const patchEntitlement = ({
|
||||
uuid, action, unenrolledRun = null, comments = null
|
||||
uuid, action, unenrolledRun = null, comments = null,
|
||||
}) => fetch(`${entitlementApi}${uuid}`, {
|
||||
credentials: 'same-origin',
|
||||
method: 'patch',
|
||||
@@ -46,7 +46,7 @@ const patchEntitlement = ({
|
||||
comments,
|
||||
}],
|
||||
}),
|
||||
},);
|
||||
});
|
||||
|
||||
export {
|
||||
getEntitlements,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { formActions, entitlementActions } from '../constants/actionTypes';
|
||||
import { formTypes } from '../constants/formTypes';
|
||||
|
||||
const clearFormState = {
|
||||
formType: '',
|
||||
isOpen: false,
|
||||
@@ -10,11 +11,11 @@ const form = (state = {}, action) => {
|
||||
switch (action.type) {
|
||||
case formActions.OPEN_REISSUE_FORM:
|
||||
return {
|
||||
...state, formType: formTypes.REISSUE, isOpen: true, activeEntitlement: action.entitlement
|
||||
...state, formType: formTypes.REISSUE, isOpen: true, activeEntitlement: action.entitlement,
|
||||
};
|
||||
case formActions.OPEN_CREATION_FORM:
|
||||
return {
|
||||
...state, formType: formTypes.CREATE, isOpen: true, activeEntitlement: null
|
||||
...state, formType: formTypes.CREATE, isOpen: true, activeEntitlement: null,
|
||||
};
|
||||
case formActions.CLOSE_FORM:
|
||||
case entitlementActions.reissue.SUCCESS:
|
||||
|
||||
@@ -141,8 +141,7 @@ class FileUpload extends React.Component {
|
||||
fileName={this.state.fileInProgress}
|
||||
request={this.state.currentRequest}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
<div className="uploaded-files">
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Cookies from 'js-cookie';
|
||||
import {
|
||||
Button, InputText, TextArea, StatusAlert
|
||||
Button, InputText, TextArea, StatusAlert,
|
||||
} from '@edx/paragon';
|
||||
|
||||
export const LinkProgramEnrollmentsSupportPage = props => (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Button, InputText, StatusAlert, InputSelect
|
||||
Button, InputText, StatusAlert, InputSelect,
|
||||
} from '@edx/paragon';
|
||||
|
||||
/*
|
||||
@@ -112,7 +112,7 @@ const renderEnrollmentsSection = enrollments => (
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
@@ -152,7 +152,7 @@ export const ProgramEnrollmentsInspectorPage = props => (
|
||||
dialog={props.error}
|
||||
/>
|
||||
)}
|
||||
<div id="input_alert" className={'alert alert-danger'} hidden>
|
||||
<div id="input_alert" className="alert alert-danger" hidden>
|
||||
Search either by edx username or email, or Institution user key, but not both
|
||||
</div>
|
||||
<div key="edX_accounts">
|
||||
@@ -228,7 +228,7 @@ ProgramEnrollmentsInspectorPage.propTypes = {
|
||||
is_active: PropTypes.bool,
|
||||
mode: PropTypes.string,
|
||||
}),
|
||||
})
|
||||
}),
|
||||
),
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -150,7 +150,7 @@ class RenderForm extends React.Component {
|
||||
{
|
||||
id: this.props.context.customFields.referrer,
|
||||
value: document.referrer ? document.referrer : 'Direct Contact Us Page Request',
|
||||
}
|
||||
},
|
||||
],
|
||||
tags: this.props.context.tags,
|
||||
};
|
||||
@@ -175,6 +175,7 @@ class RenderForm extends React.Component {
|
||||
this.scrollToTop();
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
validateFormData(formData) {
|
||||
const { course, subject, message } = formData;
|
||||
|
||||
@@ -273,21 +274,25 @@ class RenderForm extends React.Component {
|
||||
let userElement,
|
||||
suggestionsListComponent = null;
|
||||
if (this.userInformation) {
|
||||
userElement = (<LoggedInUser
|
||||
userInformation={this.userInformation}
|
||||
onChangeCallback={this.formOnChangeCallback}
|
||||
handleClick={this.handleClick}
|
||||
showWarning={this.showWarningMessage()}
|
||||
showDiscussionButton={this.showDiscussionButton()}
|
||||
reDirectUser={this.reDirectUser}
|
||||
errorList={this.getFormErrorsFromState()}
|
||||
/>);
|
||||
userElement = (
|
||||
<LoggedInUser
|
||||
userInformation={this.userInformation}
|
||||
onChangeCallback={this.formOnChangeCallback}
|
||||
handleClick={this.handleClick}
|
||||
showWarning={this.showWarningMessage()}
|
||||
showDiscussionButton={this.showDiscussionButton()}
|
||||
reDirectUser={this.reDirectUser}
|
||||
errorList={this.getFormErrorsFromState()}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
userElement = (<LoggedOutUser
|
||||
platformName={this.props.context.platformName}
|
||||
loginQuery={this.props.context.loginQuery}
|
||||
supportEmail={this.props.context.supportEmail}
|
||||
/>);
|
||||
userElement = (
|
||||
<LoggedOutUser
|
||||
platformName={this.props.context.platformName}
|
||||
loginQuery={this.props.context.loginQuery}
|
||||
supportEmail={this.props.context.supportEmail}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (suggestions !== null && suggestions.length) {
|
||||
suggestionsListComponent = (
|
||||
|
||||
@@ -7,7 +7,7 @@ import PropTypes from 'prop-types';
|
||||
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
|
||||
|
||||
function Success({
|
||||
platformName, homepageUrl, dashboardUrl, isLoggedIn
|
||||
platformName, homepageUrl, dashboardUrl, isLoggedIn,
|
||||
}) {
|
||||
let btnText,
|
||||
btnUrl;
|
||||
|
||||
@@ -11,7 +11,7 @@ export function markBlocksCompletedOnViewIfNeeded(runtime, containerElement) {
|
||||
const tracker = new ViewedEventTracker();
|
||||
|
||||
blockElements.forEach((blockElement) => {
|
||||
const markCompletedOnViewAfterDelay = parseInt(blockElement.dataset.markCompletedOnViewAfterDelay, 10,);
|
||||
const markCompletedOnViewAfterDelay = parseInt(blockElement.dataset.markCompletedOnViewAfterDelay, 10);
|
||||
if (markCompletedOnViewAfterDelay >= 0) {
|
||||
tracker.addElement(blockElement, markCompletedOnViewAfterDelay);
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
|
||||
this.before = this.before.replace(regex,
|
||||
function(match) {
|
||||
chunkObj.startTag = chunkObj.startTag + match;
|
||||
chunkObj.startTag += match;
|
||||
return '';
|
||||
});
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
|
||||
this.selection = this.selection.replace(regex,
|
||||
function(match) {
|
||||
chunkObj.startTag = chunkObj.startTag + match;
|
||||
chunkObj.startTag += match;
|
||||
return '';
|
||||
});
|
||||
}
|
||||
@@ -194,14 +194,14 @@
|
||||
|
||||
this.selection = this.selection.replace(/(^\n*)/, '');
|
||||
|
||||
this.startTag = this.startTag + re.$1;
|
||||
this.startTag += re.$1;
|
||||
|
||||
this.selection = this.selection.replace(/(\n*$)/, '');
|
||||
this.endTag = this.endTag + re.$1;
|
||||
this.endTag += re.$1;
|
||||
this.startTag = this.startTag.replace(/(^\n*)/, '');
|
||||
this.before = this.before + re.$1;
|
||||
this.before += re.$1;
|
||||
this.endTag = this.endTag.replace(/(\n*$)/, '');
|
||||
this.after = this.after + re.$1;
|
||||
this.after += re.$1;
|
||||
|
||||
if (this.before) {
|
||||
regexText = replacementText = '';
|
||||
@@ -236,7 +236,7 @@
|
||||
|
||||
function findAnEmptyToolbar(toolbarClassName) {
|
||||
var toolbars = doc.getElementsByClassName(toolbarClassName);
|
||||
for (var i=0; i < toolbars.length; ++i) {
|
||||
for (var i = 0; i < toolbars.length; ++i) {
|
||||
var aToolbar = toolbars[i];
|
||||
if (aToolbar.children.length == 0) {
|
||||
var anEmptyToolbar = aToolbar;
|
||||
@@ -524,7 +524,6 @@
|
||||
var keyCodeChar = String.fromCharCode(keyCode);
|
||||
|
||||
switch (keyCodeChar) {
|
||||
|
||||
case 'y':
|
||||
undoObj.redo();
|
||||
handled = true;
|
||||
@@ -548,7 +547,6 @@
|
||||
if (window.event) {
|
||||
window.event.returnValue = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -737,7 +735,7 @@
|
||||
|
||||
// Sets the TextareaState properties given a chunk of markdown.
|
||||
this.setChunks = function(chunk) {
|
||||
chunk.before = chunk.before + chunk.startTag;
|
||||
chunk.before += chunk.startTag;
|
||||
chunk.after = chunk.endTag + chunk.after;
|
||||
|
||||
this.start = chunk.before.length;
|
||||
@@ -1572,11 +1570,9 @@
|
||||
|
||||
// Add the true markup.
|
||||
var markup = nStars <= 1 ? '*' : '**'; // shouldn't the test be = ?
|
||||
chunk.before = chunk.before + markup;
|
||||
chunk.before += markup;
|
||||
chunk.after = markup + chunk.after;
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
|
||||
commandProto.stripLinkDefs = function(text, defsToAdd) {
|
||||
@@ -1663,7 +1659,9 @@
|
||||
});
|
||||
if (title) {
|
||||
title = title.trim ? title.trim() : title.replace(/^\s*/, '').replace(/\s*$/, '');
|
||||
title = $.trim(title).replace(/"/g, 'quot;').replace(/\(/g, '(').replace(/\)/g, ')').replace(/</g, '<').replace(/>/g, '>');
|
||||
title = $.trim(title).replace(/"/g, 'quot;').replace(/\(/g, '(').replace(/\)/g, ')')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
return title ? link + ' "' + title + '"' : link;
|
||||
});
|
||||
|
||||
@@ -19,11 +19,11 @@ export class StatusAlertRenderer {
|
||||
*/
|
||||
ReactDOM.render(
|
||||
<StatusAlert
|
||||
alertType='warning'
|
||||
dismissible={true}
|
||||
open={true}
|
||||
alertType="warning"
|
||||
dismissible
|
||||
open
|
||||
dialog={message}
|
||||
dismissable={true}
|
||||
dismissable
|
||||
onClose={() => this.shiftFocus(afterselector)}
|
||||
/>,
|
||||
document.querySelector(selector)
|
||||
|
||||
@@ -49,9 +49,9 @@ $(function() {
|
||||
});
|
||||
|
||||
if (cancel_submit) {
|
||||
$('.status.message.submission-error').
|
||||
removeClass('is-hidden').
|
||||
focus();
|
||||
$('.status.message.submission-error')
|
||||
.removeClass('is-hidden')
|
||||
.focus();
|
||||
$('html, body').animate({scrollTop: 0}, 'fast');
|
||||
return false;
|
||||
}
|
||||
@@ -72,10 +72,10 @@ $(function() {
|
||||
toggleSubmitButton(true);
|
||||
json = $.parseJSON(jqXHR.responseText);
|
||||
$('.status.message.submission-error').addClass('is-shown').focus();
|
||||
$('.status.message.submission-error .message-copy').
|
||||
text(gettext('There has been an error processing your survey.')).
|
||||
stop().
|
||||
css('display', 'block');
|
||||
$('.status.message.submission-error .message-copy')
|
||||
.text(gettext('There has been an error processing your survey.'))
|
||||
.stop()
|
||||
.css('display', 'block');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -83,14 +83,14 @@ function toggleSubmitButton(enable) {
|
||||
var $submitButton = $('form .form-actions #submit');
|
||||
|
||||
if (enable) {
|
||||
$submitButton.
|
||||
removeClass('is-disabled').
|
||||
attr('aria-disabled', false).
|
||||
removeProp('disabled');
|
||||
$submitButton
|
||||
.removeClass('is-disabled')
|
||||
.attr('aria-disabled', false)
|
||||
.removeProp('disabled');
|
||||
} else {
|
||||
$submitButton.
|
||||
addClass('is-disabled').
|
||||
attr('aria-disabled', true).
|
||||
prop('disabled', true);
|
||||
$submitButton
|
||||
.addClass('is-disabled')
|
||||
.attr('aria-disabled', true)
|
||||
.prop('disabled', true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ var edx = edx || {};
|
||||
display: 'block',
|
||||
'z-index': 0
|
||||
});
|
||||
$('#activate-account-modal').focus()
|
||||
$('#activate-account-modal').focus();
|
||||
}
|
||||
|
||||
$('.action-email-settings').each(function(index) {
|
||||
|
||||
@@ -4,13 +4,12 @@ import Cookies from 'js-cookie';
|
||||
import {DemographicsCollectionModal} from './DemographicsCollectionModal';
|
||||
|
||||
export class DemographicsCollectionBanner extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
modalOpen: false,
|
||||
hideBanner: false
|
||||
}
|
||||
};
|
||||
|
||||
this.dismissBanner = this.dismissBanner.bind(this);
|
||||
}
|
||||
@@ -65,30 +64,31 @@ export class DemographicsCollectionBanner extends React.Component {
|
||||
{gettext('Want to make edX better for everyone?')}
|
||||
</div>
|
||||
<button className="demographics-banner-btn d-flex align-items-center bg-white font-weight-bold border-0 py-2 px-3 mx-2 mb-3 m-lg-0 shadow justify-content-center">
|
||||
<span className="fa fa-thumbs-up px-2" aria-hidden="true"></span>
|
||||
<span className="fa fa-thumbs-up px-2" aria-hidden="true" />
|
||||
{gettext('Get started')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="demographics-dismiss-container md-flex justify-content-right align-self-start align-self-lg-center ml-lg-auto">
|
||||
<button type="button" className="demographics-dismiss-btn btn btn-default px-0" id="demographics-dismiss" aria-label="close">
|
||||
<i className="fa fa-times-circle text-white px-2" aria-hidden="true" onClick={this.dismissBanner}></i>
|
||||
<i className="fa fa-times-circle text-white px-2" aria-hidden="true" onClick={this.dismissBanner} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div>
|
||||
{this.state.modalOpen
|
||||
&& <DemographicsCollectionModal
|
||||
{...this.props}
|
||||
user={this.props.user}
|
||||
open={this.state.modalOpen}
|
||||
closeModal={() => this.setState({modalOpen: false})}
|
||||
dismissBanner={this.dismissBanner}
|
||||
/>
|
||||
}
|
||||
&& (
|
||||
<DemographicsCollectionModal
|
||||
{...this.props}
|
||||
user={this.props.user}
|
||||
open={this.state.modalOpen}
|
||||
closeModal={() => this.setState({modalOpen: false})}
|
||||
dismissBanner={this.dismissBanner}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* global gettext */
|
||||
import React from 'react';
|
||||
import get from 'lodash/get';
|
||||
import Wizard from './Wizard';
|
||||
import Cookies from 'js-cookie';
|
||||
import {SelectWithInput} from './SelectWithInput'
|
||||
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
|
||||
import FocusLock from 'react-focus-lock';
|
||||
import Wizard from './Wizard';
|
||||
import {SelectWithInput} from './SelectWithInput';
|
||||
import {MultiselectDropdown} from './MultiselectDropdown';
|
||||
import AxiosJwtTokenService from '../jwt_auth/AxiosJwtTokenService';
|
||||
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
|
||||
import AxiosCsrfTokenService from '../jwt_auth/AxiosCsrfTokenService';
|
||||
import FocusLock from 'react-focus-lock';
|
||||
|
||||
const FIELD_NAMES = {
|
||||
CURRENT_WORK: 'current_work_sector',
|
||||
@@ -66,7 +66,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
accessToken,
|
||||
refreshUrl,
|
||||
);
|
||||
this.csrfTokenService = new AxiosCsrfTokenService(this.props.csrfTokenPath)
|
||||
this.csrfTokenService = new AxiosCsrfTokenService(this.props.csrfTokenPath);
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
@@ -108,7 +108,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
};
|
||||
try {
|
||||
await this.jwtTokenService.getJwtToken();
|
||||
await fetch(url, options)
|
||||
await fetch(url, options);
|
||||
} catch (error) {
|
||||
this.setState({loading: false, fieldError: true, errorMessage: error});
|
||||
}
|
||||
@@ -129,13 +129,13 @@ class DemographicsCollectionModal extends React.Component {
|
||||
this.setState(({selected}) => {
|
||||
// decline was previously selected
|
||||
if (selected[FIELD_NAMES.ETHNICITY].find(i => i === 'declined')) {
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: values.filter(value => value !== 'declined')}}
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: values.filter(value => value !== 'declined')}};
|
||||
// decline was just selected
|
||||
} else if (decline) {
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: [decline]}}
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: [decline]}};
|
||||
// anything else was selected
|
||||
} else {
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: values}}
|
||||
return {selected: {...selected, [FIELD_NAMES.ETHNICITY]: values}};
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -174,7 +174,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
// We gather the possible answers to any demographics questions from the OPTIONS of the api
|
||||
async getDemographicsQuestionOptions() {
|
||||
try {
|
||||
const optionsResponse = await fetch(`${this.props.demographicsBaseUrl}/demographics/api/v1/demographics/`, {method: 'OPTIONS'})
|
||||
const optionsResponse = await fetch(`${this.props.demographicsBaseUrl}/demographics/api/v1/demographics/`, {method: 'OPTIONS'});
|
||||
const demographicsOptions = await optionsResponse.json();
|
||||
return demographicsOptions;
|
||||
} catch (error) {
|
||||
@@ -240,7 +240,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
|
||||
render() {
|
||||
if (this.state.loading) {
|
||||
return <div className="demographics-collection-modal d-flex justify-content-center align-items-start" />
|
||||
return <div className="demographics-collection-modal d-flex justify-content-center align-items-start" />;
|
||||
}
|
||||
return (
|
||||
<FocusLock>
|
||||
@@ -261,8 +261,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
currentPage: currentPage,
|
||||
totalPages: totalPages
|
||||
}
|
||||
)
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
<h2 className="mb-1 mt-4 font-weight-bold text-secondary">
|
||||
{gettext('Help make edX better for everyone!')}
|
||||
@@ -282,204 +281,209 @@ class DemographicsCollectionModal extends React.Component {
|
||||
)}
|
||||
</Wizard.Header>
|
||||
<Wizard.Page>
|
||||
{({wizardConsumer}) => <div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Gender Identity */}
|
||||
<SelectWithInput
|
||||
selectName={FIELD_NAMES.GENDER}
|
||||
selectId={FIELD_NAMES.GENDER}
|
||||
selectValue={wizardConsumer[FIELD_NAMES.GENDER]}
|
||||
selectOnChange={this.handleSelectChange}
|
||||
labelText={gettext('What is your gender identity?')}
|
||||
options={[
|
||||
<option value="default" key="default">{gettext('Select gender')}</option>,
|
||||
this.loadOptions(FIELD_NAMES.GENDER)
|
||||
]}
|
||||
showInput={wizardConsumer[FIELD_NAMES.GENDER] == 'self-describe'}
|
||||
inputName={FIELD_NAMES.GENDER_DESCRIPTION}
|
||||
inputId={FIELD_NAMES.GENDER_DESCRIPTION}
|
||||
inputType="text"
|
||||
inputValue={wizardConsumer[FIELD_NAMES.GENDER_DESCRIPTION]}
|
||||
inputOnChange={this.handleInputChange}
|
||||
inputOnBlur={this.handleSelectChange}
|
||||
disabled={this.state.fieldError}
|
||||
/>
|
||||
{/* Ethnicity */}
|
||||
<MultiselectDropdown
|
||||
label={gettext('Which of the following describes you best?')}
|
||||
emptyLabel={gettext('Check all that apply')}
|
||||
options={get(this.state.options, FIELD_NAMES.ETHNICITY_OPTIONS, {choices: []}).choices}
|
||||
selected={wizardConsumer[FIELD_NAMES.ETHNICITY]}
|
||||
onChange={this.handleMultiselectChange}
|
||||
disabled={this.state.fieldError}
|
||||
onBlur={() => {
|
||||
{({wizardConsumer}) => (
|
||||
<div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Gender Identity */}
|
||||
<SelectWithInput
|
||||
selectName={FIELD_NAMES.GENDER}
|
||||
selectId={FIELD_NAMES.GENDER}
|
||||
selectValue={wizardConsumer[FIELD_NAMES.GENDER]}
|
||||
selectOnChange={this.handleSelectChange}
|
||||
labelText={gettext('What is your gender identity?')}
|
||||
options={[
|
||||
<option value="default" key="default">{gettext('Select gender')}</option>,
|
||||
this.loadOptions(FIELD_NAMES.GENDER)
|
||||
]}
|
||||
showInput={wizardConsumer[FIELD_NAMES.GENDER] == 'self-describe'}
|
||||
inputName={FIELD_NAMES.GENDER_DESCRIPTION}
|
||||
inputId={FIELD_NAMES.GENDER_DESCRIPTION}
|
||||
inputType="text"
|
||||
inputValue={wizardConsumer[FIELD_NAMES.GENDER_DESCRIPTION]}
|
||||
inputOnChange={this.handleInputChange}
|
||||
inputOnBlur={this.handleSelectChange}
|
||||
disabled={this.state.fieldError}
|
||||
/>
|
||||
{/* Ethnicity */}
|
||||
<MultiselectDropdown
|
||||
label={gettext('Which of the following describes you best?')}
|
||||
emptyLabel={gettext('Check all that apply')}
|
||||
options={get(this.state.options, FIELD_NAMES.ETHNICITY_OPTIONS, {choices: []}).choices}
|
||||
selected={wizardConsumer[FIELD_NAMES.ETHNICITY]}
|
||||
onChange={this.handleMultiselectChange}
|
||||
disabled={this.state.fieldError}
|
||||
onBlur={() => {
|
||||
// we create a fake "event", and then use it to call our normal selection handler function that
|
||||
// is used by the other dropdowns.
|
||||
const e = {
|
||||
target: {
|
||||
name: FIELD_NAMES.ETHNICITY,
|
||||
value: wizardConsumer[FIELD_NAMES.ETHNICITY].map(ethnicity => ({ethnicity, value: ethnicity})),
|
||||
const e = {
|
||||
target: {
|
||||
name: FIELD_NAMES.ETHNICITY,
|
||||
value: wizardConsumer[FIELD_NAMES.ETHNICITY].map(ethnicity => ({ethnicity, value: ethnicity})),
|
||||
}
|
||||
};
|
||||
this.handleSelectChange(e);
|
||||
}}
|
||||
/>
|
||||
{/* Family Income */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.INCOME}>
|
||||
{gettext('What was the total combined income, during the last 12 months, of all members of your family? ')}
|
||||
</label>
|
||||
<select
|
||||
onChange={this.handleSelectChange}
|
||||
className="form-control"
|
||||
name={FIELD_NAMES.INCOME}
|
||||
id={FIELD_NAMES.INCOME}
|
||||
value={wizardConsumer[FIELD_NAMES.INCOME]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select income')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.INCOME)
|
||||
}
|
||||
}
|
||||
this.handleSelectChange(e);
|
||||
}}
|
||||
/>
|
||||
{/* Family Income */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.INCOME}>
|
||||
{gettext('What was the total combined income, during the last 12 months, of all members of your family? ')}
|
||||
</label>
|
||||
<select
|
||||
onChange={this.handleSelectChange}
|
||||
className="form-control"
|
||||
name={FIELD_NAMES.INCOME} id={FIELD_NAMES.INCOME}
|
||||
value={wizardConsumer[FIELD_NAMES.INCOME]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select income')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.INCOME)
|
||||
}
|
||||
</select>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</Wizard.Page>
|
||||
<Wizard.Page>
|
||||
{({wizardConsumer}) => <div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Military History */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.MILITARY}>
|
||||
{gettext('Have you ever served on active duty in the U.S. Armed Forces, Reserves, or National Guard?')}
|
||||
</label>
|
||||
<select
|
||||
autoFocus
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.MILITARY}
|
||||
id={FIELD_NAMES.MILITARY}
|
||||
value={wizardConsumer[FIELD_NAMES.MILITARY]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select military status')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.MILITARY)
|
||||
}
|
||||
</select>
|
||||
{({wizardConsumer}) => (
|
||||
<div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Military History */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.MILITARY}>
|
||||
{gettext('Have you ever served on active duty in the U.S. Armed Forces, Reserves, or National Guard?')}
|
||||
</label>
|
||||
<select
|
||||
autoFocus
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.MILITARY}
|
||||
id={FIELD_NAMES.MILITARY}
|
||||
value={wizardConsumer[FIELD_NAMES.MILITARY]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select military status')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.MILITARY)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</Wizard.Page>
|
||||
<Wizard.Page>
|
||||
{({wizardConsumer}) => <div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Learner Education Level */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.EDUCATION_LEVEL}>
|
||||
{gettext('What is the highest level of education that you have achieved so far?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
autoFocus
|
||||
onChange={this.handleSelectChange}
|
||||
key="self-education"
|
||||
name={FIELD_NAMES.EDUCATION_LEVEL}
|
||||
id={FIELD_NAMES.EDUCATION_LEVEL}
|
||||
value={wizardConsumer[FIELD_NAMES.EDUCATION_LEVEL]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select level of education')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.EDUCATION_LEVEL)
|
||||
}
|
||||
</select>
|
||||
{({wizardConsumer}) => (
|
||||
<div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Learner Education Level */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.EDUCATION_LEVEL}>
|
||||
{gettext('What is the highest level of education that you have achieved so far?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
autoFocus
|
||||
onChange={this.handleSelectChange}
|
||||
key="self-education"
|
||||
name={FIELD_NAMES.EDUCATION_LEVEL}
|
||||
id={FIELD_NAMES.EDUCATION_LEVEL}
|
||||
value={wizardConsumer[FIELD_NAMES.EDUCATION_LEVEL]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select level of education')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.EDUCATION_LEVEL)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
{/* Parent/Guardian Education Level */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.PARENT_EDUCATION}>
|
||||
{gettext('What is the highest level of education that any of your parents or guardians have achieved?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.PARENT_EDUCATION}
|
||||
id={FIELD_NAMES.PARENT_EDUCATION}
|
||||
value={wizardConsumer[FIELD_NAMES.PARENT_EDUCATION]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select guardian education')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.PARENT_EDUCATION)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{/* Parent/Guardian Education Level */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.PARENT_EDUCATION}>
|
||||
{gettext('What is the highest level of education that any of your parents or guardians have achieved?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.PARENT_EDUCATION}
|
||||
id={FIELD_NAMES.PARENT_EDUCATION}
|
||||
value={wizardConsumer[FIELD_NAMES.PARENT_EDUCATION]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select guardian education')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.PARENT_EDUCATION)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</Wizard.Page>
|
||||
<Wizard.Page>
|
||||
{({wizardConsumer}) => <div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Employment Status */}
|
||||
<SelectWithInput
|
||||
selectName={FIELD_NAMES.WORK_STATUS}
|
||||
selectId={FIELD_NAMES.WORK_STATUS}
|
||||
selectValue={wizardConsumer[FIELD_NAMES.WORK_STATUS]}
|
||||
selectOnChange={this.handleSelectChange}
|
||||
labelText={'What is your current employment status?'}
|
||||
options={[
|
||||
<option value="default" key="default">{gettext('Select employment status')}</option>,
|
||||
this.loadOptions(FIELD_NAMES.WORK_STATUS)
|
||||
]}
|
||||
showInput={wizardConsumer[FIELD_NAMES.WORK_STATUS] == 'other'}
|
||||
inputName={FIELD_NAMES.WORK_STATUS_DESCRIPTION}
|
||||
inputId={FIELD_NAMES.WORK_STATUS_DESCRIPTION}
|
||||
inputType="text"
|
||||
inputValue={wizardConsumer[FIELD_NAMES.WORK_STATUS_DESCRIPTION]}
|
||||
inputOnChange={this.handleInputChange}
|
||||
inputOnBlur={this.handleSelectChange}
|
||||
disabled={this.state.fieldError}
|
||||
/>
|
||||
{/* Current Work Industry */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.CURRENT_WORK}>
|
||||
{gettext('What industry do you currently work in?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.CURRENT_WORK}
|
||||
id={FIELD_NAMES.CURRENT_WORK}
|
||||
value={wizardConsumer[FIELD_NAMES.CURRENT_WORK]}
|
||||
{({wizardConsumer}) => (
|
||||
<div className="demographics-form-container" data-hj-suppress>
|
||||
{/* Employment Status */}
|
||||
<SelectWithInput
|
||||
selectName={FIELD_NAMES.WORK_STATUS}
|
||||
selectId={FIELD_NAMES.WORK_STATUS}
|
||||
selectValue={wizardConsumer[FIELD_NAMES.WORK_STATUS]}
|
||||
selectOnChange={this.handleSelectChange}
|
||||
labelText="What is your current employment status?"
|
||||
options={[
|
||||
<option value="default" key="default">{gettext('Select employment status')}</option>,
|
||||
this.loadOptions(FIELD_NAMES.WORK_STATUS)
|
||||
]}
|
||||
showInput={wizardConsumer[FIELD_NAMES.WORK_STATUS] == 'other'}
|
||||
inputName={FIELD_NAMES.WORK_STATUS_DESCRIPTION}
|
||||
inputId={FIELD_NAMES.WORK_STATUS_DESCRIPTION}
|
||||
inputType="text"
|
||||
inputValue={wizardConsumer[FIELD_NAMES.WORK_STATUS_DESCRIPTION]}
|
||||
inputOnChange={this.handleInputChange}
|
||||
inputOnBlur={this.handleSelectChange}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select current industry')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.CURRENT_WORK)
|
||||
}
|
||||
</select>
|
||||
/>
|
||||
{/* Current Work Industry */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.CURRENT_WORK}>
|
||||
{gettext('What industry do you currently work in?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.CURRENT_WORK}
|
||||
id={FIELD_NAMES.CURRENT_WORK}
|
||||
value={wizardConsumer[FIELD_NAMES.CURRENT_WORK]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select current industry')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.CURRENT_WORK)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
{/* Future Work Industry */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.FUTURE_WORK}>
|
||||
{gettext('What industry do you want to work in?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.FUTURE_WORK}
|
||||
id={FIELD_NAMES.FUTURE_WORK}
|
||||
value={wizardConsumer[FIELD_NAMES.FUTURE_WORK]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select prospective industry')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.FUTURE_WORK)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{/* Future Work Industry */}
|
||||
<div className="d-flex flex-column pb-3">
|
||||
<label htmlFor={FIELD_NAMES.FUTURE_WORK}>
|
||||
{gettext('What industry do you want to work in?')}
|
||||
</label>
|
||||
<select
|
||||
className="form-control"
|
||||
onChange={this.handleSelectChange}
|
||||
name={FIELD_NAMES.FUTURE_WORK}
|
||||
id={FIELD_NAMES.FUTURE_WORK}
|
||||
value={wizardConsumer[FIELD_NAMES.FUTURE_WORK]}
|
||||
disabled={this.state.fieldError}
|
||||
>
|
||||
<option value="default">{gettext('Select prospective industry')}</option>
|
||||
{
|
||||
this.loadOptions(FIELD_NAMES.FUTURE_WORK)
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</Wizard.Page>
|
||||
<Wizard.Closer>
|
||||
<div className="demographics-modal-closer m-sm-0">
|
||||
<i className="fa fa-check" aria-hidden="true"></i>
|
||||
<i className="fa fa-check" aria-hidden="true" />
|
||||
<h3>
|
||||
{gettext('Thank you! You’re helping make edX better for everyone.')}
|
||||
</h3>
|
||||
@@ -493,7 +497,7 @@ class DemographicsCollectionModal extends React.Component {
|
||||
</Wizard>
|
||||
</div>
|
||||
</FocusLock>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ class MultiselectDropdown extends React.Component {
|
||||
this.buttonRef = null;
|
||||
this.setButtonRef = (element) => {
|
||||
this.buttonRef = element;
|
||||
}
|
||||
};
|
||||
|
||||
this.focusButton = this.focusButton.bind(this);
|
||||
this.handleKeydown = this.handleKeydown.bind(this);
|
||||
@@ -27,7 +27,6 @@ class MultiselectDropdown extends React.Component {
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
||||
document.removeEventListener('keydown', this.handleKeydown, false);
|
||||
}
|
||||
|
||||
@@ -87,7 +86,7 @@ class MultiselectDropdown extends React.Component {
|
||||
.map(selected => this.findOption(selected).display_name)
|
||||
.join(', ');
|
||||
if (selectedList.length > 60) {
|
||||
return selectedList.substring(0, 55) + '...'
|
||||
return selectedList.substring(0, 55) + '...';
|
||||
}
|
||||
return selectedList;
|
||||
}
|
||||
@@ -95,7 +94,7 @@ class MultiselectDropdown extends React.Component {
|
||||
renderUnselect() {
|
||||
return this.props.selected.length > 0 && (
|
||||
<button id="unselect-button" disabled={this.props.disabled} aria-label="Clear all selected" onClick={this.handleRemoveAllClick}>{gettext('Clear all')}</button>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
renderMenu() {
|
||||
@@ -112,15 +111,15 @@ class MultiselectDropdown extends React.Component {
|
||||
<span className="pl-2">{option.display_name}</span>
|
||||
</label>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<fieldset id="multiselect-dropdown-fieldset" disabled={this.props.disabled}>
|
||||
<legend className="sr-only">{this.props.label}</legend>
|
||||
{options}
|
||||
</fieldset>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -136,7 +135,7 @@ class MultiselectDropdown extends React.Component {
|
||||
// and close the dropdown.
|
||||
if (!e.currentTarget.contains(e.relatedTarget)) {
|
||||
this.props.onBlur(e);
|
||||
this.setState({open: false})
|
||||
this.setState({open: false});
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -151,7 +150,7 @@ class MultiselectDropdown extends React.Component {
|
||||
{this.renderMenu()}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,19 +32,20 @@ export const SelectWithInput = (props) => {
|
||||
{options}
|
||||
</select>
|
||||
{showInput
|
||||
&& <input
|
||||
className="form-control"
|
||||
aria-label={`${selectName} description field`}
|
||||
type={inputType}
|
||||
name={inputName}
|
||||
id={inputId}
|
||||
onChange={inputOnChange}
|
||||
onBlur={inputOnBlur}
|
||||
value={inputValue}
|
||||
disabled={disabled}
|
||||
maxLength={255}
|
||||
/>
|
||||
}
|
||||
&& (
|
||||
<input
|
||||
className="form-control"
|
||||
aria-label={`${selectName} description field`}
|
||||
type={inputType}
|
||||
name={inputName}
|
||||
id={inputId}
|
||||
onChange={inputOnChange}
|
||||
onBlur={inputOnBlur}
|
||||
value={inputValue}
|
||||
disabled={disabled}
|
||||
maxLength={255}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ export default class Wizard extends React.Component {
|
||||
totalPages: 0,
|
||||
pages: [],
|
||||
wizardContext: {},
|
||||
}
|
||||
};
|
||||
|
||||
this.wizardComplete = this.wizardComplete.bind(this);
|
||||
}
|
||||
@@ -32,18 +32,18 @@ export default class Wizard extends React.Component {
|
||||
|
||||
handleNext() {
|
||||
if (this.state.currentPage < this.props.children.length) {
|
||||
this.setState(prevState => ({currentPage: prevState.currentPage + 1}))
|
||||
this.setState(prevState => ({currentPage: prevState.currentPage + 1}));
|
||||
}
|
||||
}
|
||||
|
||||
findSubComponentByType(type) {
|
||||
return React.Children.toArray(this.props.children).filter(child => child.type.name === type)
|
||||
return React.Children.toArray(this.props.children).filter(child => child.type.name === type);
|
||||
}
|
||||
|
||||
// this needs to handle the case of no provided header
|
||||
renderHeader() {
|
||||
const header = this.findSubComponentByType(Wizard.Header.name)[0];
|
||||
return header.props.children({currentPage: this.state.currentPage, totalPages: this.state.totalPages})
|
||||
return header.props.children({currentPage: this.state.currentPage, totalPages: this.state.totalPages});
|
||||
}
|
||||
|
||||
renderPage() {
|
||||
@@ -74,7 +74,7 @@ export default class Wizard extends React.Component {
|
||||
<button className="wizard-button colored" arial-label={gettext('close questionnaire')} onClick={this.props.onWizardComplete}>{gettext('Close')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
_.each(modifiedUsers.changed, function(changedInfo) {
|
||||
oldCohort = changedInfo.previous_cohort;
|
||||
if (oldCohort in movedByCohort) {
|
||||
movedByCohort[oldCohort] = movedByCohort[oldCohort] + 1;
|
||||
movedByCohort[oldCohort] += 1;
|
||||
} else {
|
||||
movedByCohort[oldCohort] = 1;
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ function createMobileMenu() {
|
||||
* Dynamically create a mobile menu from all specified mobile links
|
||||
* on the page.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
$('.mobile-nav-item').each(function() {
|
||||
var mobileNavItem = $(this).clone().addClass('mobile-nav-link');
|
||||
|
||||
@@ -91,9 +91,9 @@ var onCertificatesReady = null;
|
||||
var response = JSON.parse(jqXHR.responseText);
|
||||
$certificate_regeneration_status.text(gettext(response.message)).addClass('message');
|
||||
} catch (error) {
|
||||
$certificate_regeneration_status.
|
||||
text(gettext('Error while regenerating certificates. Please try again.')).
|
||||
addClass('message');
|
||||
$certificate_regeneration_status
|
||||
.text(gettext('Error while regenerating certificates. Please try again.'))
|
||||
.addClass('message');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
(function($) { // eslint-disable-line wrap-iife
|
||||
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
$.fn.extend({
|
||||
/*
|
||||
|
||||
@@ -81,13 +81,15 @@ class CircleChart extends React.Component {
|
||||
lastY = nextY;
|
||||
|
||||
// eslint-disable-next-line react/jsx-indent
|
||||
return <path
|
||||
d={d}
|
||||
className={`slice-${sliceIndex}`}
|
||||
key={index}
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
/>;
|
||||
return (
|
||||
<path
|
||||
d={d}
|
||||
className={`slice-${sliceIndex}`}
|
||||
key={index}
|
||||
stroke={strokeColor}
|
||||
strokeWidth={strokeWidth}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,6 @@ class CircleChartLegend extends React.Component {
|
||||
|
||||
CircleChartLegend.propTypes = {
|
||||
data: PropTypes.array.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
export default CircleChartLegend;
|
||||
|
||||
@@ -72,7 +72,7 @@ class Discussions extends React.Component {
|
||||
</div>
|
||||
<div className="post-counts">
|
||||
<div className="votes-wrapper">
|
||||
<span className="fa fa-plus-square-o count-icon" aria-hidden="true"></span>
|
||||
<span className="fa fa-plus-square-o count-icon" aria-hidden="true" />
|
||||
<span className="user-count">{thread_votes}</span>
|
||||
<p className="label">Votes on your posts, comments, and replies</p>
|
||||
</div>
|
||||
@@ -85,6 +85,6 @@ class Discussions extends React.Component {
|
||||
Discussions.propTypes = {
|
||||
content_authored: PropTypes.number.isRequired,
|
||||
thread_votes: PropTypes.number.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
export default Discussions;
|
||||
|
||||
@@ -22,7 +22,7 @@ class DueDates extends React.Component {
|
||||
|
||||
getLabel(type) {
|
||||
const {assignmentCounts} = this.props;
|
||||
if (assignmentCounts[type] < 2 ) {
|
||||
if (assignmentCounts[type] < 2) {
|
||||
return type;
|
||||
} else {
|
||||
this.renderLabels[type] += 1;
|
||||
@@ -35,14 +35,12 @@ class DueDates extends React.Component {
|
||||
this.renderLabels = this.initLabelTracker(assignmentCounts);
|
||||
|
||||
return dates.sort((a, b) => new Date(a.due) > new Date(b.due))
|
||||
.map(({format, due}, index) => {
|
||||
return (
|
||||
<li className="date-item" key={index}>
|
||||
<div className="label">{this.getLabel(format)}</div>
|
||||
<div className="data">{this.getDate(due)}</div>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
.map(({format, due}, index) => (
|
||||
<li className="date-item" key={index}>
|
||||
<div className="label">{this.getLabel(format)}</div>
|
||||
<div className="data">{this.getDate(due)}</div>
|
||||
</li>
|
||||
));
|
||||
}
|
||||
|
||||
initLabelTracker(list) {
|
||||
@@ -51,7 +49,7 @@ class DueDates extends React.Component {
|
||||
return labels.reduce((accumulator, key) => {
|
||||
accumulator[key] = 0;
|
||||
return accumulator;
|
||||
}, {})
|
||||
}, {});
|
||||
}
|
||||
|
||||
renderList() {
|
||||
@@ -73,6 +71,6 @@ class DueDates extends React.Component {
|
||||
|
||||
DueDates.propTypes = {
|
||||
dates: PropTypes.array.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
export default DueDates;
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const exGrades = [
|
||||
{
|
||||
'assignment_type':'Exam',
|
||||
'total_possible':6.0,
|
||||
'total_earned':3.0
|
||||
assignment_type: 'Exam',
|
||||
total_possible: 6.0,
|
||||
total_earned: 3.0
|
||||
},
|
||||
{
|
||||
'assignment_type':'Homework',
|
||||
'total_possible':5.0,
|
||||
assignment_type: 'Homework',
|
||||
total_possible: 5.0,
|
||||
},
|
||||
{
|
||||
'assignment_type':'Homework',
|
||||
'total_possible':11.0,
|
||||
'total_earned':0.0
|
||||
assignment_type: 'Homework',
|
||||
total_possible: 11.0,
|
||||
total_earned: 0.0
|
||||
}
|
||||
];
|
||||
|
||||
@@ -26,7 +27,7 @@ class GradeTable extends React.Component {
|
||||
getTableGroup(type, groupIndex) {
|
||||
const {grades} = this.props;
|
||||
const groupData = grades.filter(value => {
|
||||
if (value['assignment_type'] === type) {
|
||||
if (value.assignment_type === type) {
|
||||
return value;
|
||||
}
|
||||
});
|
||||
@@ -68,15 +69,15 @@ class GradeTable extends React.Component {
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GradeTable.propTypes = {
|
||||
assignmentTypes: PropTypes.array.isRequired,
|
||||
grades: PropTypes.array.isRequired,
|
||||
passingGrade: PropTypes.number.isRequired,
|
||||
percentGrade: PropTypes.number.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
export default GradeTable;
|
||||
|
||||
@@ -15,7 +15,7 @@ function arrayToObject(array) {
|
||||
const key = Object.keys(obj)[0];
|
||||
accumulator[key] = obj[key];
|
||||
return accumulator;
|
||||
}, {})
|
||||
}, {});
|
||||
}
|
||||
|
||||
function countByType(type, assignments) {
|
||||
@@ -24,7 +24,7 @@ function countByType(type, assignments) {
|
||||
if (format === type) {
|
||||
count += 1;
|
||||
}
|
||||
})
|
||||
});
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -34,18 +34,16 @@ function getActiveUserString(count) {
|
||||
}
|
||||
|
||||
function getAssignmentCounts(types, assignments) {
|
||||
const countsArray = types.map((type) => {
|
||||
return {
|
||||
[type]: countByType(type, assignments)
|
||||
}
|
||||
});
|
||||
const countsArray = types.map((type) => ({
|
||||
[type]: countByType(type, assignments)
|
||||
}));
|
||||
|
||||
return arrayToObject(countsArray);
|
||||
}
|
||||
|
||||
function getStreakIcons(count) {
|
||||
return Array.apply(null, {length: count}).map((e, i) => (
|
||||
<span className="fa fa-trophy" aria-hidden="true" key={i}></span>
|
||||
<span className="fa fa-trophy" aria-hidden="true" key={i} />
|
||||
));
|
||||
}
|
||||
|
||||
@@ -56,7 +54,7 @@ function getStreakEncouragement(count) {
|
||||
}
|
||||
|
||||
function getStreakString(count) {
|
||||
const unit = (count ===1) ? 'week' : 'weeks';
|
||||
const unit = (count === 1) ? 'week' : 'weeks';
|
||||
return (count > 0) ? `Active ${count} ${unit} in a row` : false;
|
||||
}
|
||||
|
||||
@@ -64,16 +62,14 @@ export function LearnerAnalyticsDashboard(props) {
|
||||
const {
|
||||
grading_policy, grades, schedule, schedule_raw, week_streak, weekly_active_users, discussion_info, profile_images, passing_grade, percent_grade
|
||||
} = props;
|
||||
const gradeBreakdown = grading_policy.GRADER.map(({type, weight}, index) => {
|
||||
return {
|
||||
value: weight,
|
||||
label: type,
|
||||
sliceIndex: index + 1
|
||||
}
|
||||
});
|
||||
const gradeBreakdown = grading_policy.GRADER.map(({type, weight}, index) => ({
|
||||
value: weight,
|
||||
label: type,
|
||||
sliceIndex: index + 1
|
||||
}));
|
||||
|
||||
// Get a list of assignment types minus duplicates
|
||||
const assignments = gradeBreakdown.map(value => value['label']);
|
||||
const assignments = gradeBreakdown.map(value => value.label);
|
||||
const assignmentTypes = [...new Set(assignments)];
|
||||
const assignmentCounts = getAssignmentCounts(assignmentTypes, schedule);
|
||||
|
||||
@@ -86,23 +82,23 @@ export function LearnerAnalyticsDashboard(props) {
|
||||
<div className="analytics-group">
|
||||
<h2 className="group-heading">Grading</h2>
|
||||
{gradeBreakdown
|
||||
&& <h3 className="section-heading">Weight</h3>
|
||||
}
|
||||
&& <h3 className="section-heading">Weight</h3>}
|
||||
{gradeBreakdown
|
||||
&& <div className="grading-weight-wrapper">
|
||||
<div className="chart-wrapper">
|
||||
<CircleChart
|
||||
slices={gradeBreakdown}
|
||||
centerHole={true}
|
||||
sliceBorder={{
|
||||
strokeColor: '#f5f5f5',
|
||||
strokeWidth: 2
|
||||
}}
|
||||
/>
|
||||
&& (
|
||||
<div className="grading-weight-wrapper">
|
||||
<div className="chart-wrapper">
|
||||
<CircleChart
|
||||
slices={gradeBreakdown}
|
||||
centerHole
|
||||
sliceBorder={{
|
||||
strokeColor: '#f5f5f5',
|
||||
strokeWidth: 2
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<CircleChartLegend data={gradeBreakdown} />
|
||||
</div>
|
||||
<CircleChartLegend data={gradeBreakdown} />
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
|
||||
<h3 className="section-heading">Graded Assignments</h3>
|
||||
{/* TODO: LEARNER-3854: If implementing Learner Analytics, rename to graded-assignments-wrapper. */}
|
||||
@@ -125,8 +121,7 @@ export function LearnerAnalyticsDashboard(props) {
|
||||
<div className="week-streak-wrapper">
|
||||
<h3 className="section-heading">Week streak</h3>
|
||||
{week_streak > 0
|
||||
&& <div className="streak-icon-wrapper" aria-hidden="true">{getStreakIcons(week_streak)}</div>
|
||||
}
|
||||
&& <div className="streak-icon-wrapper" aria-hidden="true">{getStreakIcons(week_streak)}</div>}
|
||||
<p>{getStreakString(week_streak)}</p>
|
||||
<p className="streak-encouragement">{getStreakEncouragement(week_streak)}</p>
|
||||
<ul className="streak-criteria">
|
||||
@@ -136,8 +131,8 @@ export function LearnerAnalyticsDashboard(props) {
|
||||
</ul>
|
||||
</div>
|
||||
<div className="active-users-wrapper">
|
||||
<span className="fa fa-user count-icon" aria-hidden="true"></span>
|
||||
<span className="user-count">{weekly_active_users.toLocaleString('en', {useGrouping:true})}</span>
|
||||
<span className="fa fa-user count-icon" aria-hidden="true" />
|
||||
<span className="user-count">{weekly_active_users.toLocaleString('en', {useGrouping: true})}</span>
|
||||
<p className="label">{getActiveUserString(weekly_active_users)}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -117,7 +117,7 @@ class EnterpriseLearnerPortalModal extends React.Component {
|
||||
gettext('You have access to the {enterpriseName} dashboard'),
|
||||
{
|
||||
enterpriseName: this.props.enterpriseCustomerName,
|
||||
}
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
<p>
|
||||
@@ -125,7 +125,7 @@ class EnterpriseLearnerPortalModal extends React.Component {
|
||||
gettext('To access the courses available to you through {enterpriseName}, visit the {enterpriseName} dashboard.'),
|
||||
{
|
||||
enterpriseName: this.props.enterpriseCustomerName,
|
||||
}
|
||||
},
|
||||
)}
|
||||
</p>
|
||||
<div className="mt-4 d-flex align-content-center justify-content-end">
|
||||
|
||||
@@ -217,7 +217,7 @@ describe('Course Enroll View', () => {
|
||||
view.enrollSuccess();
|
||||
|
||||
expect(CourseEnrollView.redirect).toHaveBeenCalledWith(
|
||||
view.trackSelectionUrl + courseCardModel.get('course_run_key')
|
||||
view.trackSelectionUrl + courseCardModel.get('course_run_key'),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ describe('Course Entitlement View', () => {
|
||||
|
||||
it('Courses with an an enroll by date should indicate so on the selection option.', () => {
|
||||
const enrollEndSetOptionIndex = entitlementAvailableSessions.findIndex(
|
||||
session => session.enrollment_end !== null
|
||||
session => session.enrollment_end !== null,
|
||||
);
|
||||
const enrollEndSetOption = selectOptions[enrollEndSetOptionIndex];
|
||||
expect(enrollEndSetOption && enrollEndSetOption.text.includes('Open until')).toBe(true);
|
||||
@@ -123,7 +123,7 @@ describe('Course Entitlement View', () => {
|
||||
|
||||
it('Currently selected session should be specified in the dropdown options.', () => {
|
||||
const selectedSessionIndex = entitlementAvailableSessions.findIndex(
|
||||
session => initialSessionId === session.session_id
|
||||
session => initialSessionId === session.session_id,
|
||||
);
|
||||
expect(selectOptions[selectedSessionIndex].text.includes('Currently Selected')).toBe(true);
|
||||
});
|
||||
|
||||
@@ -61,18 +61,18 @@ describe('Program Progress View', () => {
|
||||
|
||||
expect(view.$('.js-subscription-info')[0]).toBeInDOM();
|
||||
expect(
|
||||
view.$('.js-subscription-info .divider-heading').text().trim()
|
||||
view.$('.js-subscription-info .divider-heading').text().trim(),
|
||||
).toEqual(heading);
|
||||
expect(
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(1)')
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(1)'),
|
||||
).toContainHtml(body);
|
||||
expect(
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(2)')
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(2)'),
|
||||
).toContainText(
|
||||
/Need help\? Check out the.*Learner Help Center.*to troubleshoot issues or contact support/
|
||||
/Need help\? Check out the.*Learner Help Center.*to troubleshoot issues or contact support/,
|
||||
);
|
||||
expect(
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(2) .subscription-link').attr('href')
|
||||
view.$('.js-subscription-info .subscription-section p:nth-child(2) .subscription-link').attr('href'),
|
||||
).toEqual('/learner');
|
||||
};
|
||||
|
||||
@@ -235,18 +235,18 @@ describe('Program Progress View', () => {
|
||||
testSubscriptionState(
|
||||
'pre',
|
||||
'Inactive subscription',
|
||||
'If you had a subscription previously, your payment history is still available'
|
||||
'If you had a subscription previously, your payment history is still available',
|
||||
);
|
||||
});
|
||||
|
||||
it('should render active trial subscription info if subscription is active with trial', () => {
|
||||
subscriptionData.trial_end = moment().add(3, 'days').utc().format(
|
||||
'YYYY-MM-DDTHH:mm:ss[Z]'
|
||||
'YYYY-MM-DDTHH:mm:ss[Z]',
|
||||
);
|
||||
testSubscriptionState(
|
||||
'active',
|
||||
'Trial subscription',
|
||||
'View your receipts or modify your subscription'
|
||||
'View your receipts or modify your subscription',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -254,7 +254,7 @@ describe('Program Progress View', () => {
|
||||
testSubscriptionState(
|
||||
'active',
|
||||
'Active subscription',
|
||||
'View your receipts or modify your subscription'
|
||||
'View your receipts or modify your subscription',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -262,7 +262,7 @@ describe('Program Progress View', () => {
|
||||
testSubscriptionState(
|
||||
'inactive',
|
||||
'Inactive subscription',
|
||||
'Restart your subscription for $100/month. Your payment history is still available'
|
||||
'Restart your subscription for $100/month. Your payment history is still available',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -524,7 +524,7 @@ describe('Program Details View', () => {
|
||||
};
|
||||
if (trial) {
|
||||
subscriptionData.trial_end = moment().add(3, 'days').utc().format(
|
||||
'YYYY-MM-DDTHH:mm:ss[Z]'
|
||||
'YYYY-MM-DDTHH:mm:ss[Z]',
|
||||
);
|
||||
}
|
||||
view = initView({
|
||||
@@ -580,9 +580,9 @@ describe('Program Details View', () => {
|
||||
expect(view.$('.program-heading-title').text()).toEqual('Your Program Journey');
|
||||
expect(view.$('.program-heading-message').text().trim()
|
||||
.replace(/\s+/g, ' ')).toEqual(
|
||||
'Track and plan your progress through the 3 courses in this program. '
|
||||
'Track and plan your progress through the 3 courses in this program. '
|
||||
+ 'To complete the program, you must earn a verified certificate for each course.',
|
||||
);
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the program heading congratulations message if all courses completed', () => {
|
||||
@@ -598,8 +598,8 @@ describe('Program Details View', () => {
|
||||
expect(view.$('.program-heading-title').text()).toEqual('Congratulations!');
|
||||
expect(view.$('.program-heading-message').text().trim()
|
||||
.replace(/\s+/g, ' ')).toEqual(
|
||||
'You have successfully completed all the requirements for the Test Course Title Test.',
|
||||
);
|
||||
'You have successfully completed all the requirements for the Test Course Title Test.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the course list headings', () => {
|
||||
@@ -695,7 +695,7 @@ describe('Program Details View', () => {
|
||||
testSubscriptionState(
|
||||
'pre',
|
||||
'Start 7-day free trial',
|
||||
'$100/month subscription after trial ends. Cancel anytime.'
|
||||
'$100/month subscription after trial ends. Cancel anytime.',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -704,7 +704,7 @@ describe('Program Details View', () => {
|
||||
'active',
|
||||
'Manage my subscription',
|
||||
'Active trial ends',
|
||||
true
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -712,7 +712,7 @@ describe('Program Details View', () => {
|
||||
testSubscriptionState(
|
||||
'active',
|
||||
'Manage my subscription',
|
||||
'Your next billing date is'
|
||||
'Your next billing date is',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -720,7 +720,7 @@ describe('Program Details View', () => {
|
||||
testSubscriptionState(
|
||||
'inactive',
|
||||
'Restart my subscription',
|
||||
'Unlock verified access to all courses for $100/month. Cancel anytime.'
|
||||
'Unlock verified access to all courses for $100/month. Cancel anytime.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,7 +45,7 @@ class CollectionListView extends Backbone.View {
|
||||
StringUtils.interpolate(this.titleContext.title),
|
||||
HtmlUtils.HTML('</'),
|
||||
this.titleContext.el,
|
||||
HtmlUtils.HTML('>')
|
||||
HtmlUtils.HTML('>'),
|
||||
);
|
||||
return titleHtml;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class ProgramDetailsView extends Backbone.View {
|
||||
this.programModel = new Backbone.Model(this.options.programData);
|
||||
this.courseData = new Backbone.Model(this.options.courseData);
|
||||
this.certificateCollection = new Backbone.Collection(
|
||||
this.options.certificateData
|
||||
this.options.certificateData,
|
||||
);
|
||||
this.subscriptionModel = new SubscriptionModel({
|
||||
context: this.options,
|
||||
@@ -92,7 +92,7 @@ class ProgramDetailsView extends Backbone.View {
|
||||
const totalCount = completedCount + inProgressCount + remainingCount;
|
||||
const buyButtonUrl = ProgramDetailsView.getUrl(
|
||||
this.options.urls.buy_button_url,
|
||||
this.options.programData
|
||||
this.options.programData,
|
||||
);
|
||||
|
||||
let data = {
|
||||
|
||||
@@ -2,7 +2,7 @@ import Backbone from 'backbone';
|
||||
|
||||
import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils';
|
||||
|
||||
import progressViewTpl from '../../../templates/learner_dashboard//progress_circle_view.underscore';
|
||||
import progressViewTpl from '../../../templates/learner_dashboard/progress_circle_view.underscore';
|
||||
import progressSegmentTpl from '../../../templates/learner_dashboard/progress_circle_segment.underscore';
|
||||
|
||||
class ProgressCircleView extends Backbone.View {
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import Backbone from 'backbone';
|
||||
|
||||
class UnenrollView extends Backbone.View {
|
||||
|
||||
constructor(options) {
|
||||
const defaults = {
|
||||
el: '.unenroll-modal',
|
||||
|
||||
@@ -101,7 +101,6 @@ function(Backbone, $, AjaxHelpers, TemplateHelpers, CohortsView, CohortCollectio
|
||||
if (options && options.selectCohort) {
|
||||
cohortsView.$('.cohort-select').val(options.selectCohort.toString()).change();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
respondToRefresh = function(catCount, dogCount) {
|
||||
@@ -262,8 +261,8 @@ function(Backbone, $, AjaxHelpers, TemplateHelpers, CohortsView, CohortCollectio
|
||||
// But upload form should not be visible until toggle is clicked.
|
||||
expect(cohortsView.$(fileUploadFormCss).length).toBe(0);
|
||||
uploadCsvToggle = cohortsView.$('.toggle-cohort-management-secondary');
|
||||
expect(uploadCsvToggle.text()).
|
||||
toContain('Assign learners to cohorts by uploading a CSV file');
|
||||
expect(uploadCsvToggle.text())
|
||||
.toContain('Assign learners to cohorts by uploading a CSV file');
|
||||
uploadCsvToggle.click();
|
||||
// After toggle is clicked, it should be hidden.
|
||||
expect(uploadCsvToggle).toHaveClass('hidden');
|
||||
|
||||
@@ -133,17 +133,17 @@ function(Backbone, $, AjaxHelpers, TemplateHelpers, DiscussionsView, CourseDiscu
|
||||
expect($inlineDiscussionsForm.length).toBe(1);
|
||||
expect($courseWideDiscussionsForm.length).toBe(1);
|
||||
|
||||
expect($courseWideDiscussionsForm.text()).
|
||||
toContain('Course-Wide Discussion Topics');
|
||||
expect($courseWideDiscussionsForm.text()).
|
||||
toContain('Select the course-wide discussion topics that you want to divide.');
|
||||
expect($courseWideDiscussionsForm.text())
|
||||
.toContain('Course-Wide Discussion Topics');
|
||||
expect($courseWideDiscussionsForm.text())
|
||||
.toContain('Select the course-wide discussion topics that you want to divide.');
|
||||
|
||||
// Should see the inline discussions form and its content
|
||||
expect($inlineDiscussionsForm.length).toBe(1);
|
||||
expect($inlineDiscussionsForm.text()).
|
||||
toContain('Content-Specific Discussion Topics');
|
||||
expect($inlineDiscussionsForm.text()).
|
||||
toContain('Specify whether content-specific discussion topics are divided.');
|
||||
expect($inlineDiscussionsForm.text())
|
||||
.toContain('Content-Specific Discussion Topics');
|
||||
expect($inlineDiscussionsForm.text())
|
||||
.toContain('Specify whether content-specific discussion topics are divided.');
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
|
||||
@@ -182,10 +182,10 @@ function($, AjaxHelpers, CertificateInvalidationModel, CertificateInvalidationVi
|
||||
view.collection.add(model);
|
||||
expect(view.$el.find('table tbody tr').length).toBe(3);
|
||||
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html()).
|
||||
toMatch(notes);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html()).
|
||||
toMatch(user);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html())
|
||||
.toMatch(notes);
|
||||
expect(view.$el.find('table tbody tr td:contains("' + user + '")').parent().html())
|
||||
.toMatch(user);
|
||||
|
||||
// Remove a model from collection
|
||||
var collection_model = view.collection.get({id: 2});
|
||||
|
||||
@@ -17,7 +17,6 @@ function($, id, AjaxHelper) {
|
||||
dataDownload = window.InstructorDashboard.sections;
|
||||
dataDownload.DataDownloadV2($('#data_download_2'));
|
||||
window.InstructorDashboard.util.PendingInstructorTasks = function() {
|
||||
return;
|
||||
};
|
||||
requests = AjaxHelper.requests(this);
|
||||
$selected = $('<option data-endpoint="api/url/fake"></option>');
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
define(['jquery', 'js/instructor_dashboard/student_admin', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'],
|
||||
function($, StudentAdmin, AjaxHelpers) {
|
||||
// 'js/instructor_dashboard/student_admin'
|
||||
|
||||
'use strict';
|
||||
|
||||
'use strict';
|
||||
|
||||
describe('edx.instructor_dashboard.student_admin.StudentAdmin', function() {
|
||||
var studentadmin, dashboardApiUrl, uniqStudentIdentifier, alertMsg;
|
||||
|
||||
@@ -53,7 +53,6 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViewsSpecHelpers, He
|
||||
Helpers.expectLoadingErrorIsVisible(accountSettingsView, true);
|
||||
});
|
||||
|
||||
|
||||
it('shows loading error when UserPreferencesModel fails to load', function() {
|
||||
requests = AjaxHelpers.requests(this);
|
||||
|
||||
@@ -108,7 +107,7 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViewsSpecHelpers, He
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.TIME_ZONE_RESPONSE);
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
|
||||
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
|
||||
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
|
||||
|
||||
var sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
|
||||
|
||||
@@ -272,7 +271,7 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViewsSpecHelpers, He
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.createAccountSettingsData());
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.TIME_ZONE_RESPONSE);
|
||||
AjaxHelpers.respondWithJson(requests, Helpers.createUserPreferencesData());
|
||||
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
|
||||
AjaxHelpers.respondWithJson(requests, {}); // Page viewed analytics event
|
||||
|
||||
sectionsData = accountSettingsView.options.tabSections.aboutTabSections;
|
||||
|
||||
@@ -322,7 +321,7 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, FieldViewsSpecHelpers, He
|
||||
title: view.options.title,
|
||||
valueAttribute: view.options.valueAttribute,
|
||||
helpMessage: '',
|
||||
validValue: Helpers.FIELD_OPTIONS[1][0], // dummy option for dropdown field
|
||||
validValue: Helpers.FIELD_OPTIONS[1][0], // dummy option for dropdown field
|
||||
invalidValue1: Helpers.FIELD_OPTIONS[2][0], // dummy option for dropdown field
|
||||
invalidValue2: Helpers.FIELD_OPTIONS[3][0], // dummy option for dropdown field
|
||||
validationError: 'Nope, this will not do!',
|
||||
|
||||
@@ -45,8 +45,8 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, UserAccountModel, FieldVi
|
||||
AjaxHelpers.respondWithJson(requests, {success: 'true'});
|
||||
FieldViewsSpecHelpers.expectMessageContains(
|
||||
view,
|
||||
"We've sent a message to legolas@woodland.middlearth. " +
|
||||
'Click the link in the message to reset your password.'
|
||||
"We've sent a message to legolas@woodland.middlearth. "
|
||||
+ 'Click the link in the message to reset your password.'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ function(Backbone, $, _, AjaxHelpers, TemplateHelpers, Helpers, FieldViews, User
|
||||
{
|
||||
title: 'Basic Account Information',
|
||||
messageType: 'info',
|
||||
message: 'Your profile settings are managed by Test Enterprise. ' +
|
||||
'Contact your administrator or <a href="https://support.edx.org/">edX Support</a> for help.',
|
||||
message: 'Your profile settings are managed by Test Enterprise. '
|
||||
+ 'Contact your administrator or <a href="https://support.edx.org/">edX Support</a> for help.',
|
||||
fields: [
|
||||
{
|
||||
view: new FieldViews.ReadonlyFieldView({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user