restrict move action
This commit is contained in:
@@ -205,13 +205,17 @@ define(['jquery', 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
|
||||
return category + '_display_name_' + xblockIndex;
|
||||
})
|
||||
);
|
||||
if (category !== 'component') {
|
||||
if (category === 'component') {
|
||||
if (hasCurrentLocation) {
|
||||
expect(displayedInfo.currentLocationText).toEqual('(Currently selected)');
|
||||
}
|
||||
} else {
|
||||
if (hasCurrentLocation) {
|
||||
expect(displayedInfo.currentLocationText).toEqual('(Current location)');
|
||||
}
|
||||
expect(displayedInfo.forwardButtonSRTexts).toEqual(
|
||||
_.map(_.range(expectedXBlocksCount), function() {
|
||||
return 'Click for children';
|
||||
return 'View child items';
|
||||
})
|
||||
);
|
||||
expect(displayedInfo.forwardButtonCount).toEqual(expectedXBlocksCount);
|
||||
@@ -519,15 +523,8 @@ define(['jquery', 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
|
||||
});
|
||||
});
|
||||
|
||||
describe('Move an xblock', function() {
|
||||
it('can not move in a disabled state', function() {
|
||||
verifyMoveEnabled(false);
|
||||
modal.$el.find('.modal-actions .action-move').click();
|
||||
expect(modal.movedAlertView).toBeNull();
|
||||
expect(getSentRequests().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('move button is disabled when navigating to same parent', function() {
|
||||
describe('Move button', function() {
|
||||
it('is disabled when navigating to same parent', function() {
|
||||
// select a target parent as the same as source parent and click
|
||||
renderViews(courseOutline);
|
||||
_.each(_.range(3), function() {
|
||||
@@ -536,7 +533,7 @@ define(['jquery', 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
|
||||
verifyMoveEnabled('component', true);
|
||||
});
|
||||
|
||||
it('move button is enabled when navigating to different parent', function() {
|
||||
it('is enabled when navigating to different parent', function() {
|
||||
// select a target parent as the different as source parent and click
|
||||
renderViews(courseOutline);
|
||||
_.each(_.range(3), function() {
|
||||
@@ -553,6 +550,111 @@ define(['jquery', 'underscore', 'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpe
|
||||
verifyXBlockInfo(courseOutlineOptions, 'section', 1, 'forward', false);
|
||||
});
|
||||
|
||||
it('is disbabled when navigating to same source xblock', function() {
|
||||
var outline,
|
||||
libraryContentXBlockInfo = {
|
||||
category: 'library_content',
|
||||
display_name: 'Library Content',
|
||||
has_children: true,
|
||||
id: 'LIBRARY_CONTENT_ID'
|
||||
},
|
||||
outlineOptions = {library_content: 1, component: 1};
|
||||
|
||||
// make above xblock source xblock.
|
||||
modal.sourceXBlockInfo = libraryContentXBlockInfo;
|
||||
outline = createXBlockInfo('component', outlineOptions, libraryContentXBlockInfo);
|
||||
renderViews(outline);
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
|
||||
// select a target parent
|
||||
clickForwardButton(0);
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('is disabled when navigating inside source content experiment', function() {
|
||||
var outline,
|
||||
splitTestXBlockInfo = {
|
||||
category: 'split_test',
|
||||
display_name: 'Content Experiment',
|
||||
has_children: true,
|
||||
id: 'SPLIT_TEST_ID'
|
||||
},
|
||||
outlineOptions = {split_test: 1, unit: 2, component: 1};
|
||||
|
||||
// make above xblock source xblock.
|
||||
modal.sourceXBlockInfo = splitTestXBlockInfo;
|
||||
outline = createXBlockInfo('unit', outlineOptions, splitTestXBlockInfo);
|
||||
renderViews(outline);
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
|
||||
// navigate to groups level
|
||||
clickForwardButton(0);
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
|
||||
// navigate to component level inside a group
|
||||
clickForwardButton(0);
|
||||
|
||||
// move should be disabled because we are navigating inside source xblock
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('is disabled when navigating to any content experiment groups', function() {
|
||||
var outline,
|
||||
splitTestXBlockInfo = {
|
||||
category: 'split_test',
|
||||
display_name: 'Content Experiment',
|
||||
has_children: true,
|
||||
id: 'SPLIT_TEST_ID'
|
||||
},
|
||||
outlineOptions = {split_test: 1, unit: 2, component: 1};
|
||||
|
||||
// group level should be disabled but component level inside groups should be movable
|
||||
outline = createXBlockInfo('unit', outlineOptions, splitTestXBlockInfo);
|
||||
renderViews(outline);
|
||||
|
||||
// move is disabled on groups level
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
|
||||
// navigate to component level inside a group
|
||||
clickForwardButton(1);
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('is enabled when navigating to any parentable component', function() {
|
||||
var parentableXBlockInfo = {
|
||||
category: 'vertical',
|
||||
display_name: 'Parentable Component',
|
||||
has_children: true,
|
||||
id: 'PARENTABLE_ID'
|
||||
};
|
||||
renderViews(parentableXBlockInfo);
|
||||
|
||||
// move is enabled on parentable xblocks.
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('is disabled when navigating to any non-parentable component', function() {
|
||||
var nonParentableXBlockInfo = {
|
||||
category: 'html',
|
||||
display_name: 'Non Parentable Component',
|
||||
has_children: false,
|
||||
id: 'NON_PARENTABLE_ID'
|
||||
};
|
||||
renderViews(nonParentableXBlockInfo);
|
||||
|
||||
// move is disabled on non-parent xblocks.
|
||||
expect(modal.$el.find('.modal-actions .action-move').hasClass('is-disabled')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Move an xblock', function() {
|
||||
it('can not move in a disabled state', function() {
|
||||
verifyMoveEnabled(false);
|
||||
modal.$el.find('.modal-actions .action-move').click();
|
||||
expect(modal.movedAlertView).toBeNull();
|
||||
expect(getSentRequests().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('move an xblock when move button is clicked', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
moveXBlockWithSuccess(requests);
|
||||
|
||||
@@ -122,6 +122,7 @@ function($, Backbone, _, gettext, BaseView, XBlockViewUtils, MoveXBlockUtils, Ht
|
||||
this.moveXBlockListView = new MoveXBlockListView(
|
||||
{
|
||||
model: new XBlockInfoModel(courseOutlineInfo, {parse: true}),
|
||||
sourceXBlockInfo: this.sourceXBlockInfo,
|
||||
ancestorInfo: ancestorInfo
|
||||
}
|
||||
);
|
||||
@@ -136,12 +137,30 @@ function($, Backbone, _, gettext, BaseView, XBlockViewUtils, MoveXBlockUtils, Ht
|
||||
}
|
||||
},
|
||||
|
||||
isValidCategory: function(sourceParentType, targetParentType, targetHasChildren) {
|
||||
var basicBlockTypes = ['course', 'chapter', 'sequential', 'vertical'];
|
||||
// Treat source parent component as vertical to support move child components under content experiment
|
||||
// and other similar xblocks.
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
sourceParentType = sourceParentType === 'split_test' ? 'vertical' : sourceParentType;
|
||||
// Treat target parent component as a vertical to support move to parentable target parent components.
|
||||
// Also, moving a component directly to content experiment is not allowed, we need to visit to group level.
|
||||
if (targetHasChildren && !_.contains(basicBlockTypes, targetParentType) &&
|
||||
targetParentType !== 'split_test') {
|
||||
targetParentType = 'vertical'; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
return targetParentType === sourceParentType;
|
||||
},
|
||||
|
||||
enableMoveOperation: function(targetParentXBlockInfo) {
|
||||
var isValidMove = false,
|
||||
sourceParentType = this.sourceParentXBlockInfo.get('category'),
|
||||
targetParentType = targetParentXBlockInfo.get('category');
|
||||
targetParentType = targetParentXBlockInfo.get('category'),
|
||||
targetHasChildren = targetParentXBlockInfo.get('has_children');
|
||||
|
||||
if (targetParentType === sourceParentType && this.sourceParentXBlockInfo.id !== targetParentXBlockInfo.id) {
|
||||
if (this.isValidCategory(sourceParentType, targetParentType, targetHasChildren) &&
|
||||
this.sourceParentXBlockInfo.id !== targetParentXBlockInfo.id && // same parent case
|
||||
this.sourceXBlockInfo.id !== targetParentXBlockInfo.id) { // same source item case
|
||||
isValidMove = true;
|
||||
this.targetParentXBlockInfo = targetParentXBlockInfo;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ function($, Backbone, _, gettext, HtmlUtils, StringUtils, XBlockUtils, MoveXBloc
|
||||
section: gettext('Sections'),
|
||||
subsection: gettext('Subsections'),
|
||||
unit: gettext('Units'),
|
||||
component: gettext('Components')
|
||||
component: gettext('Components'),
|
||||
group: gettext('Groups')
|
||||
},
|
||||
|
||||
events: {
|
||||
@@ -43,6 +44,7 @@ function($, Backbone, _, gettext, HtmlUtils, StringUtils, XBlockUtils, MoveXBloc
|
||||
initialize: function(options) {
|
||||
this.visitedAncestors = [];
|
||||
this.template = HtmlUtils.template(MoveXBlockListViewTemplate);
|
||||
this.sourceXBlockInfo = options.sourceXBlockInfo;
|
||||
this.ancestorInfo = options.ancestorInfo;
|
||||
this.listenTo(Backbone, 'move:breadcrumbButtonPressed', this.handleBreadcrumbButtonPress);
|
||||
this.renderXBlockInfo();
|
||||
@@ -53,6 +55,7 @@ function($, Backbone, _, gettext, HtmlUtils, StringUtils, XBlockUtils, MoveXBloc
|
||||
this.$el,
|
||||
this.template(
|
||||
{
|
||||
sourceXBlockId: this.sourceXBlockInfo.id,
|
||||
xblocks: this.childrenInfo.children,
|
||||
noChildText: this.getNoChildText(),
|
||||
categoryText: this.getCategoryText(),
|
||||
@@ -123,10 +126,14 @@ function($, Backbone, _, gettext, HtmlUtils, StringUtils, XBlockUtils, MoveXBloc
|
||||
* Set parent and child XBlock categories.
|
||||
*/
|
||||
setDisplayedXBlocksCategories: function() {
|
||||
this.parentInfo.category = XBlockUtils.getXBlockType(
|
||||
this.parentInfo.parent.get('category'),
|
||||
this.visitedAncestors[this.visitedAncestors.length - 2]
|
||||
);
|
||||
var childCategory = 'component';
|
||||
this.parentInfo.category = XBlockUtils.getXBlockType(this.parentInfo.parent.get('category'));
|
||||
if (!_.contains(_.keys(this.categoryRelationMap), this.parentInfo.category)) {
|
||||
if (this.parentInfo.category === 'split_test') {
|
||||
childCategory = 'group'; // This is just to show groups text on group listing.
|
||||
}
|
||||
this.categoryRelationMap[this.parentInfo.category] = childCategory;
|
||||
}
|
||||
this.childrenInfo.category = this.categoryRelationMap[this.parentInfo.category];
|
||||
},
|
||||
|
||||
@@ -136,25 +143,19 @@ function($, Backbone, _, gettext, HtmlUtils, StringUtils, XBlockUtils, MoveXBloc
|
||||
* @returns {any} Integer or undefined
|
||||
*/
|
||||
getCurrentLocationIndex: function() {
|
||||
var category, ancestorXBlock, currentLocationIndex;
|
||||
|
||||
if (this.childrenInfo.category === 'component' || this.childrenInfo.children.length === 0) {
|
||||
return currentLocationIndex;
|
||||
}
|
||||
|
||||
category = this.childrenInfo.children[0].get('category');
|
||||
ancestorXBlock = _.find(
|
||||
this.ancestorInfo.ancestors, function(ancestor) { return ancestor.category === category; }
|
||||
);
|
||||
|
||||
if (ancestorXBlock) {
|
||||
_.each(this.childrenInfo.children, function(xblock, index) {
|
||||
if (ancestorXBlock.display_name === xblock.get('display_name') &&
|
||||
ancestorXBlock.id === xblock.get('id')) {
|
||||
currentLocationIndex = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
var self = this,
|
||||
currentLocationIndex;
|
||||
_.each(self.childrenInfo.children, function(xblock, index) {
|
||||
if (xblock.get('id') === self.sourceXBlockInfo.id) {
|
||||
currentLocationIndex = index;
|
||||
} else {
|
||||
_.each(self.ancestorInfo.ancestors, function(ancestor) {
|
||||
if (ancestor.display_name === xblock.get('display_name') && ancestor.id === xblock.get('id')) {
|
||||
currentLocationIndex = index;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return currentLocationIndex;
|
||||
},
|
||||
|
||||
@@ -395,20 +395,21 @@
|
||||
}
|
||||
|
||||
.component {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
color: $black;
|
||||
padding: ($baseline/4) ($baseline/2);
|
||||
}
|
||||
|
||||
.xblock-displayname {
|
||||
@include float(left);
|
||||
}
|
||||
|
||||
.button-forward, .component {
|
||||
border: none;
|
||||
padding: ($baseline/2);
|
||||
}
|
||||
|
||||
.button-forward {
|
||||
.xblock-displayname {
|
||||
@include float(left);
|
||||
}
|
||||
|
||||
padding: ($baseline/2);
|
||||
.forward-sr-icon {
|
||||
@include float(right);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user