Last active
July 10, 2019 14:59
-
-
Save dancgray/bf9e026d8b79cd19151aed1976b6b851 to your computer and use it in GitHub Desktop.
Overly complex version of scaffoldListView.js with courseassets cleaned up on item removal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
define([ | |
'core/origin', | |
'core/helpers', | |
'core/models/courseAssetModel', | |
'core/collections/contentCollection', | |
'backbone-forms', | |
'backbone-forms-lists' | |
], function(Origin, Helpers, CourseAssetModel, ContentCollection, BackboneForms) { | |
var ScaffoldListView = Backbone.Form.editors.List.extend({ | |
defaultValue: [], | |
render: function() { | |
var instance = Backbone.Form.editors.__List.prototype.render.apply(this, arguments); | |
// set-up drag 'n drop | |
this.$list.sortable({ | |
placeholder: 'sortable-placeholder', | |
containment: '.app-inner', | |
update: this.updateItemPositions.bind(this), | |
start: function(event, ui) { | |
Origin.scaffold.getCurrentModel().set('_isDragging', true); | |
ui.placeholder.height(ui.item.height()); | |
}, | |
stop: function(event, ui) { | |
_.defer(function() { | |
Origin.scaffold.getCurrentModel().set('_isDragging', false); | |
}); | |
} | |
}); | |
return instance; | |
}, | |
updateItemPositions: function(e, ui) { | |
var $items = $('.list-item', this.$el); | |
var newIndex = $items.index(ui.item); | |
for(var i = 0, count = this.items.length; i < count; i++) { | |
var item = this.items[i]; | |
if(!item.$el.is(ui.item)) continue; | |
this.items.splice(i, 1); | |
this.items.splice(newIndex, 0, item); | |
this.trigger('change', this); | |
return; // found our match, end here | |
} | |
}, | |
// HACK needed to fix reset functionality (see https://github.com/powmedia/backbone-forms/issues/517) | |
setValue: function(value) { | |
this.value = value; | |
// remove previous items, and add new ones | |
this.items.forEach(function(item) { item.remove(); }); | |
this.items = []; | |
this.value.forEach(this.addItem.bind(this)); | |
}, | |
/** | |
* Accomodate sweetalert in item removal | |
*/ | |
removeItem: function(item) { | |
var remove = function(isConfirmed) { | |
if(isConfirmed === false) return; | |
var index = this.items.indexOf(item); | |
// pass item data to asset checker, use editor value so we can delete assets added before model is saved | |
var itemFormData = this.items[index] ? this.items[index] : {}; | |
if (itemFormData.editor && itemFormData.editor.value) { | |
itemAssetCheck(itemFormData.editor.value, 'delete'); | |
} | |
this.items[index].remove(); | |
this.items.splice(index, 1); | |
if(item.addEventTriggered) { | |
this.trigger('remove', this, item.editor); | |
this.trigger('change', this); | |
} | |
if(!this.items.length && !this.Editor.isAsync) { | |
this.addItem(); | |
} | |
}.bind(this); | |
// no confirmation needed, just remove | |
if(! this.schema.confirmDelete) return remove(); | |
// confirm delete action | |
window.confirm({ | |
title: this.schema.confirmDelete, | |
type: 'warning', | |
callback: remove | |
}); | |
} | |
}); | |
var ScaffoldListItemView = Backbone.Form.editors.List.Item.extend({ | |
events: function() { | |
return _.extend({}, Backbone.Form.editors.__List.__Item.prototype.events, { | |
'click [data-action="clone"]': 'cloneItem' | |
}); | |
}, | |
cloneItem: function(event) { | |
itemAssetCheck(this.editor.value, 'create'); | |
this.list.addItem(this.editor.value, true); | |
} | |
}); | |
Origin.on('origin:dataReady', function() { | |
// NOTE override default list view (keep the old one in case...) | |
Backbone.Form.editors.__List = Backbone.Form.editors.List; | |
Backbone.Form.editors.__List.__Item = Backbone.Form.editors.List.Item; | |
Backbone.Form.editors.List = ScaffoldListView; | |
Backbone.Form.editors.List.Item = ScaffoldListItemView; | |
// overrides | |
Backbone.Form.editors.List.prototype.constructor.template = Handlebars.templates.list; | |
Backbone.Form.editors.List.Item.prototype.constructor.template = Handlebars.templates.listItem; | |
Backbone.Form.editors.List.Modal.prototype.itemToString = modalItemToString; | |
Backbone.Form.editors.List.Modal.prototype.__openEditor = Backbone.Form.editors.List.Modal.prototype.openEditor; | |
Backbone.Form.editors.List.Modal.prototype.openEditor = openEditor; | |
}); | |
/** | |
* Helper functions | |
*/ | |
/** | |
* Builds a string from nested values | |
* OVERRIDES Backbone.Form.editors.List.Modal.prototype.itemToString | |
*/ | |
function modalItemToString(value) { | |
if(!value) { | |
return ''; | |
} | |
return Object.keys(this.nestedSchema).reduce(function(parts, key) { | |
var val = getModalItemValueString(value[key]); | |
var title = this.nestedSchema[key].title || Backbone.Form.Field.prototype.createTitle.call({ key: key }); | |
return parts + '<p class="list-item-modal-item">' + wrapSchemaTitle(title) + val + '</p>'; | |
}.bind(this), ''); | |
} | |
/** | |
* FIX to avoid opening the modal after stopping dragging a list item | |
* OVERRIDES Backbone.Form.editors.List.Modal.prototype.openEditor | |
*/ | |
function openEditor() { | |
if(Origin.scaffold.getCurrentModel().get('_isDragging')) { | |
return; | |
} | |
Backbone.Form.editors.List.Modal.prototype.__openEditor.apply(this, arguments); | |
} | |
/** | |
* Returns an apt string value from Modal.Item value | |
*/ | |
function getModalItemValueString(value) { | |
if (typeof value !== 'object') { | |
return value; | |
} | |
if(Array.isArray(value)) { | |
return Origin.l10n.t('app.items', { smart_count: Object.keys(value).length }); | |
} | |
// print nested name/value pairs | |
var pairs = ''; | |
for (var name in value) { | |
if(value.hasOwnProperty(name)) pairs += '<br />' + wrapSchemaTitle(name) + value[name]; | |
} | |
return '<p class="list-item-modal-object">' + pairs + '</p>'; | |
} | |
function wrapSchemaTitle(value) { | |
return '<span class="list-item-description">' + value + ':</span>'; | |
} | |
function getAssetId(filterText, cb) { | |
var pattern = '.*' + filterText.toLowerCase() + '.*'; | |
$.ajax({ | |
url: 'api/asset/query', | |
type:'GET', | |
data: {search: { filename: filterText }}, | |
success: function (data) { | |
if (data.length == 0) return cb(Origin.l10n.t('app.errorsaveasset')); | |
return cb(null, data[0]._id); | |
}, | |
error: function() { | |
cb(Origin.l10n.t('app.errorsaveasset')); | |
} | |
}); | |
} | |
function openNotifyAlert(type, text) { | |
Origin.Notify.alert({ | |
type: type, | |
text: text | |
}); | |
} | |
/** | |
* checks all attributes in a list item for assets and creates or deletes associated course asset record | |
*/ | |
function itemAssetCheck(assetItem, action) { | |
if (typeof assetItem !== 'object' || !action) { | |
return 'error'; | |
} | |
var flatItem = Helpers.flattenNestedProperties(assetItem); | |
var itemValues = _.values(flatItem); | |
var parentAttributes = Origin.scaffold.getCurrentModel().attributes; | |
_.each(itemValues, function(item) { | |
if (item.length !== 0 && item.indexOf('course/assets') === 0) { | |
var itemFileName = item.substring(item.lastIndexOf('/')+1); | |
if (typeof itemFileName !== 'string') openNotifyAlert('error', Origin.l10n.t('app.errorsaveasset')); | |
if (action === 'create') { | |
getAssetId(itemFileName, function(error, assetId) { | |
if (error || !assetId) { | |
return openNotifyAlert('error', Origin.l10n.t('app.errorsaveasset')); | |
} | |
(new CourseAssetModel()).save({ | |
_courseId : Origin.editor.data.course.get('_id'), | |
_contentType : parentAttributes._type, | |
_contentTypeId : parentAttributes._id, | |
_fieldName : itemFileName, | |
_assetId : assetId, | |
_contentTypeParentId: parentAttributes._parentId | |
}, { | |
error: function(error) { | |
openNotifyAlert('error', Origin.l10n.t('app.errorsaveasset')); | |
} | |
}); | |
}); | |
} else if (action === 'delete') { | |
var itemAssetCollection = new ContentCollection(null, { _type: 'courseasset' }).fetch({ | |
data: { | |
_contentTypeId: parentAttributes._id, | |
_contentType: parentAttributes._type, | |
_fieldName: itemFileName | |
}, | |
success: function(collection) { | |
if (!collection.length) return; | |
var listModels = collection.models ? collection.models.slice() : collection.slice(); | |
var listModel = listModels[0]; | |
if (!listModel) return; | |
listModel.destroy({ | |
error: function() { | |
console.error('Failed to destroy courseasset record', listModel.get('_id')); | |
return; | |
} | |
}); | |
}, | |
error: function(model, response) { | |
return openNotifyAlert('error', Origin.l10n.t('app.errordelete')); | |
} | |
}); | |
} | |
} | |
}); | |
} | |
return ScaffoldListView; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment