This commit implements STUD-1490, allowing creation of components on the container page. It also enables the delete and duplicate buttons now that new content can be created that would benefit. Note that it also creates shared functionality for adding components, and refactors the unit page to use it too.
122 lines
5.2 KiB
JavaScript
122 lines
5.2 KiB
JavaScript
define(["jquery", "underscore", "js/views/xblock", "js/utils/module", "gettext", "js/views/feedback_notification"],
|
|
function ($, _, XBlockView, ModuleUtils, gettext, NotificationView) {
|
|
var reorderableClass = '.reorderable-container',
|
|
studioXBlockWrapperClass = '.studio-xblock-wrapper';
|
|
|
|
var ContainerView = XBlockView.extend({
|
|
|
|
xblockReady: function () {
|
|
XBlockView.prototype.xblockReady.call(this);
|
|
var reorderableContainer = this.$(reorderableClass),
|
|
alreadySortable = this.$('.ui-sortable'),
|
|
newParent,
|
|
oldParent,
|
|
self = this;
|
|
|
|
alreadySortable.sortable("destroy");
|
|
|
|
reorderableContainer.sortable({
|
|
handle: '.drag-handle',
|
|
|
|
stop: function (event, ui) {
|
|
var saving, hideSaving, removeFromParent;
|
|
|
|
if (_.isUndefined(oldParent)) {
|
|
// If no actual change occurred,
|
|
// oldParent will never have been set.
|
|
return;
|
|
}
|
|
|
|
saving = new NotificationView.Mini({
|
|
title: gettext('Saving…')
|
|
});
|
|
saving.show();
|
|
|
|
hideSaving = function () {
|
|
saving.hide();
|
|
};
|
|
|
|
// If moving from one container to another,
|
|
// add to new container before deleting from old to
|
|
// avoid creating an orphan if the addition fails.
|
|
if (newParent) {
|
|
removeFromParent = oldParent;
|
|
self.reorder(newParent, function () {
|
|
self.reorder(removeFromParent, hideSaving);
|
|
});
|
|
} else {
|
|
// No new parent, only reordering within same container.
|
|
self.reorder(oldParent, hideSaving);
|
|
}
|
|
|
|
oldParent = undefined;
|
|
newParent = undefined;
|
|
},
|
|
update: function (event, ui) {
|
|
// When dragging from one ol to another, this method
|
|
// will be called twice (once for each list). ui.sender will
|
|
// be null if the change is related to the list the element
|
|
// was originally in (the case of a move within the same container
|
|
// or the deletion from a container when moving to a new container).
|
|
var parent = $(event.target).closest(studioXBlockWrapperClass);
|
|
if (ui.sender) {
|
|
// Move to a new container (the addition part).
|
|
newParent = parent;
|
|
} else {
|
|
// Reorder inside a container, or deletion when moving to new container.
|
|
oldParent = parent;
|
|
}
|
|
},
|
|
helper: "original",
|
|
opacity: '0.5',
|
|
placeholder: 'component-placeholder',
|
|
forcePlaceholderSize: true,
|
|
axis: 'y',
|
|
items: '> .is-draggable',
|
|
connectWith: reorderableClass,
|
|
tolerance: "pointer"
|
|
|
|
});
|
|
},
|
|
|
|
reorder: function (targetParent, successCallback) {
|
|
var children, childLocators;
|
|
|
|
// Find descendants with class "studio-xblock-wrapper" whose parent === targetParent.
|
|
// This is necessary to filter our grandchildren, great-grandchildren, etc.
|
|
children = targetParent.find(studioXBlockWrapperClass).filter(function () {
|
|
var parent = $(this).parent().closest(studioXBlockWrapperClass);
|
|
return parent.data('locator') === targetParent.data('locator');
|
|
});
|
|
|
|
childLocators = _.map(
|
|
children,
|
|
function (child) {
|
|
return $(child).data('locator');
|
|
}
|
|
);
|
|
$.ajax({
|
|
url: ModuleUtils.getUpdateUrl(targetParent.data('locator')),
|
|
type: 'PUT',
|
|
dataType: 'json',
|
|
contentType: 'application/json',
|
|
data: JSON.stringify({
|
|
children: childLocators
|
|
}),
|
|
success: function () {
|
|
// change data-parent on the element moved.
|
|
if (successCallback) {
|
|
successCallback();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
refresh: function() {
|
|
this.$(reorderableClass).sortable('refresh');
|
|
}
|
|
});
|
|
|
|
return ContainerView;
|
|
}); // end define();
|