Entrance Exam authoring and messaging updates
Multi-commit history: - hide drag functionality for entrance exam section. - hide entrance exam subsection elements e.g. delete, drag, name etc. - show unit/verticals expanded in case of entrance exam - modify code in order to allow user to update entrance exam score from UI. - write down unit tests. - write down Jasmine tests. - add bok-choy test - updated bok-choy test - internationalize string - repositioned sequential block creatori - SOL-221 (entrance exam message) - SOL-199 LMS Part (show entrance exam content) and hide the course navigation bar. - redirect the view in case of entrance exam. - update code structure as per suggestions - write down unit tests - fix pep8 - instead of hiding the exam requirement message, now also showing the exam the completion message (success state). - write down unit test to show exam completion message. - Update code as per review suggestions - update doc string - addressed review suggestions - change sequential message text - css adjustments - added new css class for entrance exam score in studio - added Jasmine test for remaning coverage - sequential message should appear under the context of entrance exam subsection. - updated text in CMS and LMS as per suggestions. - added unit text to insure sequential message should not be present in other chapters rather then entrance exam. - skip setter if empty prerequisite course list - exclude logic from xblock_info.js that is specifically related to entrance exam. - added js tests and updated code as per suggestions - added tests - addressed several PR issues - Several small fixes (style, refactoring) - Fixed score update issue - added some more unit tests. - code suggested changes. - addressed PR feedback
This commit is contained in:
@@ -133,9 +133,19 @@ function(Backbone, _, str, ModuleUtils) {
|
||||
*/
|
||||
'has_content_group_components': null,
|
||||
/**
|
||||
* Indicate the type of xblock
|
||||
* actions defines the state of delete, drag and child add functionality for a xblock.
|
||||
* currently, each xblock has default value of 'True' for keys: deletable, draggable and childAddable.
|
||||
*/
|
||||
'override_type': null
|
||||
'actions': null,
|
||||
/**
|
||||
* Header visible to UI.
|
||||
*/
|
||||
'is_header_visible': null,
|
||||
/**
|
||||
* Optional explanatory message about the xblock.
|
||||
*/
|
||||
'explanatory_message': null
|
||||
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
@@ -172,13 +182,33 @@ function(Backbone, _, str, ModuleUtils) {
|
||||
return !this.get('published') || this.get('has_changes');
|
||||
},
|
||||
|
||||
canBeDeleted: function(){
|
||||
//get the type of xblock
|
||||
if(this.get('override_type') != null) {
|
||||
var type = this.get('override_type');
|
||||
isDeletable: function() {
|
||||
return this.isActionRequired('deletable');
|
||||
},
|
||||
|
||||
//hide/remove the delete trash icon if type is entrance exam.
|
||||
if (_.has(type, 'is_entrance_exam') && type['is_entrance_exam']) {
|
||||
isDraggable: function() {
|
||||
return this.isActionRequired('draggable');
|
||||
},
|
||||
|
||||
isChildAddable: function(){
|
||||
return this.isActionRequired('childAddable');
|
||||
},
|
||||
|
||||
isHeaderVisible: function(){
|
||||
if(this.get('is_header_visible') !== null) {
|
||||
return this.get('is_header_visible');
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return true if action is required e.g. delete, drag, add new child etc or if given key is not present.
|
||||
* @return {boolean}
|
||||
*/
|
||||
isActionRequired: function(actionName) {
|
||||
var actions = this.get('actions');
|
||||
if(actions !== null) {
|
||||
if (_.has(actions, actionName) && !actions[actionName]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -188,8 +218,8 @@ function(Backbone, _, str, ModuleUtils) {
|
||||
/**
|
||||
* Return a list of convenience methods to check affiliation to the category.
|
||||
* @return {Array}
|
||||
*/
|
||||
getCategoryHelpers: function () {
|
||||
*/
|
||||
getCategoryHelpers: function () {
|
||||
var categories = ['course', 'chapter', 'sequential', 'vertical'],
|
||||
helpers = {};
|
||||
|
||||
@@ -200,15 +230,15 @@ function(Backbone, _, str, ModuleUtils) {
|
||||
}, this);
|
||||
|
||||
return helpers;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if we can edit current XBlock or not on Course Outline page.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isEditableOnCourseOutline: function() {
|
||||
return this.isSequential() || this.isChapter() || this.isVertical();
|
||||
}
|
||||
/**
|
||||
* Check if we can edit current XBlock or not on Course Outline page.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isEditableOnCourseOutline: function() {
|
||||
return this.isSequential() || this.isChapter() || this.isVertical();
|
||||
}
|
||||
});
|
||||
return XBlockInfo;
|
||||
});
|
||||
|
||||
@@ -7,16 +7,47 @@ define(['backbone', 'js/models/xblock_info'],
|
||||
expect(new XBlockInfo({'category': 'sequential'}).isEditableOnCourseOutline()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'vertical'}).isEditableOnCourseOutline()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('cannot delete an entrance exam', function(){
|
||||
expect(new XBlockInfo({'category': 'chapter', 'override_type': {'is_entrance_exam':true}})
|
||||
.canBeDeleted()).toBe(false);
|
||||
describe('XblockInfo actions state and header visibility ', function() {
|
||||
|
||||
it('works correct to hide icons e.g. trash icon, drag when actions are not required', function(){
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'deletable':false}})
|
||||
.isDeletable()).toBe(false);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'draggable':false}})
|
||||
.isDraggable()).toBe(false);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'childAddable':false}})
|
||||
.isChildAddable()).toBe(false);
|
||||
});
|
||||
|
||||
it('can delete module rather then entrance exam', function(){
|
||||
expect(new XBlockInfo({'category': 'chapter', 'override_type': {'is_entrance_exam':false}}).canBeDeleted()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'override_type': {}}).canBeDeleted()).toBe(true);
|
||||
it('works correct to show icons e.g. trash icon, drag when actions are required', function(){
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'deletable':true}})
|
||||
.isDeletable()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'draggable':true}})
|
||||
.isDraggable()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {'childAddable':true}})
|
||||
.isChildAddable()).toBe(true);
|
||||
});
|
||||
|
||||
it('displays icons e.g. trash icon, drag when actions are undefined', function(){
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {}})
|
||||
.isDeletable()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {}})
|
||||
.isDraggable()).toBe(true);
|
||||
expect(new XBlockInfo({'category': 'chapter', 'actions': {}})
|
||||
.isChildAddable()).toBe(true);
|
||||
});
|
||||
|
||||
it('works correct to hide header content', function(){
|
||||
expect(new XBlockInfo({'category': 'sequential', 'is_header_visible': false})
|
||||
.isHeaderVisible()).toBe(false);
|
||||
});
|
||||
|
||||
it('works correct to show header content when is_header_visible is not defined', function() {
|
||||
expect(new XBlockInfo({'category': 'sequential', 'actions': {'deletable': true}})
|
||||
.isHeaderVisible()).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ define(["jquery", "sinon", "js/common_helpers/ajax_helpers", "js/views/utils/vie
|
||||
getItemsOfType, getItemHeaders, verifyItemsExpanded, expandItemsAndVerifyState,
|
||||
collapseItemsAndVerifyState, createMockCourseJSON, createMockSectionJSON, createMockSubsectionJSON,
|
||||
verifyTypePublishable, mockCourseJSON, mockEmptyCourseJSON, mockSingleSectionCourseJSON,
|
||||
createMockVerticalJSON, createMockIndexJSON,
|
||||
createMockVerticalJSON, createMockIndexJSON, mockCourseEntranceExamJSON
|
||||
mockOutlinePage = readFixtures('mock/mock-course-outline-page.underscore'),
|
||||
mockRerunNotification = readFixtures('mock/mock-course-rerun-notification.underscore');
|
||||
|
||||
@@ -228,6 +228,14 @@ define(["jquery", "sinon", "js/common_helpers/ajax_helpers", "js/views/utils/vie
|
||||
mockSingleSectionCourseJSON = createMockCourseJSON({}, [
|
||||
createMockSectionJSON()
|
||||
]);
|
||||
mockCourseEntranceExamJSON = createMockCourseJSON({}, [
|
||||
createMockSectionJSON({}, [
|
||||
createMockSubsectionJSON({'is_header_visible': false}, [
|
||||
createMockVerticalJSON()
|
||||
])
|
||||
])
|
||||
]);
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
@@ -259,6 +267,11 @@ define(["jquery", "sinon", "js/common_helpers/ajax_helpers", "js/views/utils/vie
|
||||
verifyItemsExpanded('subsection', false);
|
||||
expect(getItemsOfType('unit')).not.toExist();
|
||||
});
|
||||
|
||||
it('unit initially exist for entrance exam', function() {
|
||||
createCourseOutlinePage(this, mockCourseEntranceExamJSON);
|
||||
expect(getItemsOfType('unit')).toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Rerun notification", function () {
|
||||
|
||||
@@ -44,6 +44,17 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
this.renderTemplate();
|
||||
this.addButtonActions(this.$el);
|
||||
this.addNameEditor();
|
||||
|
||||
// For cases in which we need to suppress the header controls during rendering, we'll
|
||||
// need to add the current model's id/locator to the set of expanded locators
|
||||
if (this.model.get('is_header_visible') !== null && !this.model.get('is_header_visible')) {
|
||||
var locator = this.model.get('id');
|
||||
if(!_.isUndefined(this.expandedLocators) && !this.expandedLocators.contains(locator)) {
|
||||
this.expandedLocators.add(locator);
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldRenderChildren() && this.shouldExpandChildren()) {
|
||||
this.renderChildren();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user