[#13,transforms][l]: re-enable column transforms (bulk editing).
* TODO: only operates on documents in current view atm -- to do this properly want a transform function on Backend.
This commit is contained in:
parent
b934307a2a
commit
e23354eb4e
@ -25,6 +25,7 @@ var costco = function() {
|
|||||||
preview.push({before: JSON.stringify(before), after: JSON.stringify(after)});
|
preview.push({before: JSON.stringify(before), after: JSON.stringify(after)});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: 2012-01-05 Move this out of this function and up into (view) functions that call this
|
||||||
util.render('editPreview', 'expression-preview-container', {rows: preview});
|
util.render('editPreview', 'expression-preview-container', {rows: preview});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,4 +167,4 @@ var costco = function() {
|
|||||||
ensureCommit: ensureCommit,
|
ensureCommit: ensureCommit,
|
||||||
uploadCSV: uploadCSV
|
uploadCSV: uploadCSV
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|||||||
234
src/view.js
234
src/view.js
@ -147,8 +147,8 @@ my.DataTable = Backbone.View.extend({
|
|||||||
var self = this;
|
var self = this;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var actions = {
|
var actions = {
|
||||||
bulkEdit: function() { self.showDialog('bulkEdit', {name: self.state.currentColumn}) },
|
bulkEdit: function() { self.showTransformColumnDialog('bulkEdit', {name: self.state.currentColumn}) },
|
||||||
transform: function() { showDialog('transform') },
|
transform: function() { self.showTransformDialog('transform') },
|
||||||
csv: function() { window.location.href = app.csvUrl },
|
csv: function() { window.location.href = app.csvUrl },
|
||||||
json: function() { window.location.href = "_rewrite/api/json" },
|
json: function() { window.location.href = "_rewrite/api/json" },
|
||||||
urlImport: function() { showDialog('urlImport') },
|
urlImport: function() { showDialog('urlImport') },
|
||||||
@ -180,6 +180,37 @@ my.DataTable = Backbone.View.extend({
|
|||||||
actions[$(e.target).attr('data-action')]();
|
actions[$(e.target).attr('data-action')]();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showTransformColumnDialog: function() {
|
||||||
|
var $el = $('.dialog-content');
|
||||||
|
util.show('dialog');
|
||||||
|
var view = new my.ColumnTransform({
|
||||||
|
model: this.model
|
||||||
|
});
|
||||||
|
view.state = this.state;
|
||||||
|
view.render();
|
||||||
|
$el.empty();
|
||||||
|
$el.append(view.el);
|
||||||
|
util.observeExit($el, function() {
|
||||||
|
util.hide('dialog');
|
||||||
|
})
|
||||||
|
$('.dialog').draggable({ handle: '.dialog-header', cursor: 'move' });
|
||||||
|
},
|
||||||
|
|
||||||
|
showTransformDialog: function() {
|
||||||
|
var $el = $('.dialog-content');
|
||||||
|
util.show('dialog');
|
||||||
|
var view = new my.DataTransform({
|
||||||
|
});
|
||||||
|
view.render();
|
||||||
|
$el.empty();
|
||||||
|
$el.append(view.el);
|
||||||
|
util.observeExit($el, function() {
|
||||||
|
util.hide('dialog');
|
||||||
|
})
|
||||||
|
$('.dialog').draggable({ handle: '.dialog-header', cursor: 'move' });
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
// Core Templating
|
// Core Templating
|
||||||
template: ' \
|
template: ' \
|
||||||
@ -308,6 +339,205 @@ my.DataTableRow = Backbone.View.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// View (Dialog) for doing data transformations (on columns of data).
|
||||||
|
my.ColumnTransform = Backbone.View.extend({
|
||||||
|
className: 'transform-column-view',
|
||||||
|
template: ' \
|
||||||
|
<div class="dialog-header"> \
|
||||||
|
Functional transform on column {{name}} \
|
||||||
|
</div> \
|
||||||
|
<div class="dialog-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" class="refine-tabs ui-tabs ui-widget ui-widget-content ui-corner-all"> \
|
||||||
|
<span>Preview</span> \
|
||||||
|
<div id="expression-preview-tabs-preview" class="ui-tabs-panel ui-widget-content ui-corner-bottom"> \
|
||||||
|
<div class="expression-preview-container" style="width: 652px; "> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</td> \
|
||||||
|
</tr> \
|
||||||
|
</tbody> \
|
||||||
|
</table> \
|
||||||
|
</div> \
|
||||||
|
</td> \
|
||||||
|
</tr> \
|
||||||
|
</tbody> \
|
||||||
|
</table> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
<div class="dialog-footer"> \
|
||||||
|
<button class="okButton button"> Update All </button> \
|
||||||
|
<button class="cancelButton button">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) {
|
||||||
|
util.notify("Error with function! " + editFunc.errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
util.hide('dialog');
|
||||||
|
util.notify("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) {
|
||||||
|
util.notify(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)
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
costco.previewTransform(docs, editFunc, self.state.currentColumn);
|
||||||
|
} else {
|
||||||
|
errors.text(editFunc.errorMessage);
|
||||||
|
}
|
||||||
|
}, 1, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// View (Dialog) for doing data transformations on whole dataset.
|
||||||
|
my.DataTransform = Backbone.View.extend({
|
||||||
|
className: 'transform-view',
|
||||||
|
template: ' \
|
||||||
|
<div class="dialog-header"> \
|
||||||
|
Recursive transform on all rows \
|
||||||
|
</div> \
|
||||||
|
<div class="dialog-body"> \
|
||||||
|
<div class="grid-layout layout-full"> \
|
||||||
|
<p class="info">Traverse and transform objects by visiting every node on a recursive walk using <a href="https://github.com/substack/js-traverse">js-traverse</a>.</p> \
|
||||||
|
<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" class="refine-tabs ui-tabs ui-widget ui-widget-content ui-corner-all"> \
|
||||||
|
<span>Preview</span> \
|
||||||
|
<div id="expression-preview-tabs-preview" class="ui-tabs-panel ui-widget-content ui-corner-bottom"> \
|
||||||
|
<div class="expression-preview-container" style="width: 652px; "> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
</td> \
|
||||||
|
</tr> \
|
||||||
|
</tbody> \
|
||||||
|
</table> \
|
||||||
|
</div> \
|
||||||
|
</td> \
|
||||||
|
</tr> \
|
||||||
|
</tbody> \
|
||||||
|
</table> \
|
||||||
|
</div> \
|
||||||
|
</div> \
|
||||||
|
<div class="dialog-footer"> \
|
||||||
|
<button class="okButton button"> Update All </button> \
|
||||||
|
<button class="cancelButton button">Cancel</button> \
|
||||||
|
</div> \
|
||||||
|
',
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
this.el = $(this.el);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
this.el.html(this.template);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
my.FlotGraph = Backbone.View.extend({
|
my.FlotGraph = Backbone.View.extend({
|
||||||
|
|
||||||
tagName: "div",
|
tagName: "div",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user