176 lines
5.7 KiB
JavaScript
176 lines
5.7 KiB
JavaScript
/*jshint multistr:true */
|
||
|
||
this.recline = this.recline || {};
|
||
this.recline.View = this.recline.View || {};
|
||
|
||
// Views module following classic module pattern
|
||
(function($, my) {
|
||
|
||
// ## ColumnTransform
|
||
//
|
||
// View (Dialog) for doing data transformations (on columns of data).
|
||
my.ColumnTransform = Backbone.View.extend({
|
||
className: 'transform-column-view modal fade in',
|
||
template: ' \
|
||
<div class="modal-header"> \
|
||
<a class="close" data-dismiss="modal">×</a> \
|
||
<h3>Functional transform on column {{name}}</h3> \
|
||
</div> \
|
||
<div class="modal-body"> \
|
||
<div class="grid-layout layout-tight layout-full"> \
|
||
<table> \
|
||
<tbody> \
|
||
<tr> \
|
||
<td colspan="4"> \
|
||
<div class="grid-layout layout-tight layout-full"> \
|
||
<table rows="4" cols="4"> \
|
||
<tbody> \
|
||
<tr style="vertical-align: bottom;"> \
|
||
<td colspan="4"> \
|
||
Expression \
|
||
</td> \
|
||
</tr> \
|
||
<tr> \
|
||
<td colspan="3"> \
|
||
<div class="input-container"> \
|
||
<textarea class="expression-preview-code"></textarea> \
|
||
</div> \
|
||
</td> \
|
||
<td class="expression-preview-parsing-status" width="150" style="vertical-align: top;"> \
|
||
No syntax error. \
|
||
</td> \
|
||
</tr> \
|
||
<tr> \
|
||
<td colspan="4"> \
|
||
<div id="expression-preview-tabs"> \
|
||
<span>Preview</span> \
|
||
<div id="expression-preview-tabs-preview"> \
|
||
<div class="expression-preview-container"> \
|
||
</div> \
|
||
</div> \
|
||
</div> \
|
||
</td> \
|
||
</tr> \
|
||
</tbody> \
|
||
</table> \
|
||
</div> \
|
||
</td> \
|
||
</tr> \
|
||
</tbody> \
|
||
</table> \
|
||
</div> \
|
||
</div> \
|
||
<div class="modal-footer"> \
|
||
<button class="okButton btn primary"> Update All </button> \
|
||
<button class="cancelButton btn danger">Cancel</button> \
|
||
</div> \
|
||
',
|
||
|
||
events: {
|
||
'click .okButton': 'onSubmit',
|
||
'keydown .expression-preview-code': 'onEditorKeydown'
|
||
},
|
||
|
||
initialize: function() {
|
||
this.el = $(this.el);
|
||
},
|
||
|
||
render: function() {
|
||
var htmls = $.mustache(this.template,
|
||
{name: this.state.currentColumn}
|
||
);
|
||
this.el.html(htmls);
|
||
// Put in the basic (identity) transform script
|
||
// TODO: put this into the template?
|
||
var editor = this.el.find('.expression-preview-code');
|
||
editor.val("function(doc) {\n doc['"+ this.state.currentColumn+"'] = doc['"+ this.state.currentColumn+"'];\n return doc;\n}");
|
||
editor.focus().get(0).setSelectionRange(18, 18);
|
||
editor.keydown();
|
||
},
|
||
|
||
onSubmit: function(e) {
|
||
var self = this;
|
||
var funcText = this.el.find('.expression-preview-code').val();
|
||
var editFunc = costco.evalFunction(funcText);
|
||
if (editFunc.errorMessage) {
|
||
this.trigger('recline:flash', {message: "Error with function! " + editFunc.errorMessage});
|
||
return;
|
||
}
|
||
this.el.modal('hide');
|
||
this.trigger('recline:flash', {message: "Updating all visible docs. This could take a while...", persist: true, loader: true});
|
||
var docs = self.model.currentDocuments.map(function(doc) {
|
||
return doc.toJSON();
|
||
});
|
||
// TODO: notify about failed docs?
|
||
var toUpdate = costco.mapDocs(docs, editFunc).edited;
|
||
var totalToUpdate = toUpdate.length;
|
||
function onCompletedUpdate() {
|
||
totalToUpdate += -1;
|
||
if (totalToUpdate === 0) {
|
||
self.trigger('recline:flash', {message: toUpdate.length + " documents updated successfully"});
|
||
alert('WARNING: We have only updated the docs in this view. (Updating of all docs not yet implemented!)');
|
||
self.remove();
|
||
}
|
||
}
|
||
// TODO: Very inefficient as we search through all docs every time!
|
||
_.each(toUpdate, function(editedDoc) {
|
||
var realDoc = self.model.currentDocuments.get(editedDoc.id);
|
||
realDoc.set(editedDoc);
|
||
realDoc.save().then(onCompletedUpdate).fail(onCompletedUpdate);
|
||
});
|
||
this.el.remove();
|
||
},
|
||
|
||
editPreviewTemplate: ' \
|
||
<div class="expression-preview-table-wrapper"> \
|
||
<table class="table table-condensed"> \
|
||
<thead> \
|
||
<tr> \
|
||
<th class="expression-preview-heading"> \
|
||
before \
|
||
</th> \
|
||
<th class="expression-preview-heading"> \
|
||
after \
|
||
</th> \
|
||
</tr> \
|
||
</thead> \
|
||
<tbody> \
|
||
{{#rows}} \
|
||
<tr> \
|
||
<td class="expression-preview-value"> \
|
||
{{before}} \
|
||
</td> \
|
||
<td class="expression-preview-value"> \
|
||
{{after}} \
|
||
</td> \
|
||
</tr> \
|
||
{{/rows}} \
|
||
</tbody> \
|
||
</table> \
|
||
</div> \
|
||
',
|
||
|
||
onEditorKeydown: function(e) {
|
||
var self = this;
|
||
// if you don't setTimeout it won't grab the latest character if you call e.target.value
|
||
window.setTimeout( function() {
|
||
var errors = self.el.find('.expression-preview-parsing-status');
|
||
var editFunc = costco.evalFunction(e.target.value);
|
||
if (!editFunc.errorMessage) {
|
||
errors.text('No syntax error.');
|
||
var docs = self.model.currentDocuments.map(function(doc) {
|
||
return doc.toJSON();
|
||
});
|
||
var previewData = costco.previewTransform(docs, editFunc, self.state.currentColumn);
|
||
var $el = self.el.find('.expression-preview-container');
|
||
var templated = $.mustache(self.editPreviewTemplate, {rows: previewData.slice(0,4)});
|
||
$el.html(templated);
|
||
} else {
|
||
errors.text(editFunc.errorMessage);
|
||
}
|
||
}, 1, true);
|
||
}
|
||
});
|
||
|
||
})(jQuery, recline.View);
|