diff --git a/src/costco.js b/src/costco.js
index 7c5b089c..edce7590 100755
--- a/src/costco.js
+++ b/src/costco.js
@@ -25,6 +25,7 @@ var costco = function() {
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});
}
@@ -166,4 +167,4 @@ var costco = function() {
ensureCommit: ensureCommit,
uploadCSV: uploadCSV
};
-}();
\ No newline at end of file
+}();
diff --git a/src/view.js b/src/view.js
index 3beb60f2..e416d697 100644
--- a/src/view.js
+++ b/src/view.js
@@ -147,8 +147,8 @@ my.DataTable = Backbone.View.extend({
var self = this;
e.preventDefault();
var actions = {
- bulkEdit: function() { self.showDialog('bulkEdit', {name: self.state.currentColumn}) },
- transform: function() { showDialog('transform') },
+ bulkEdit: function() { self.showTransformColumnDialog('bulkEdit', {name: self.state.currentColumn}) },
+ transform: function() { self.showTransformDialog('transform') },
csv: function() { window.location.href = app.csvUrl },
json: function() { window.location.href = "_rewrite/api/json" },
urlImport: function() { showDialog('urlImport') },
@@ -180,6 +180,37 @@ my.DataTable = Backbone.View.extend({
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
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: ' \
+
\
+ \
+
\
+
\
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ | \
+ Expression \
+ | \
+ \
+ \
+ | \
+ \
+ \
+ \
+ | \
+ \
+ No syntax error. \
+ | \
+ \
+ \
+ | \
+ \
+ | \
+ \
+ \
+ \
+ \
+ | \
+
\
+ \
+
\
+
\
+
\
+ \
+ ',
+
+ 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: ' \
+ \
+ \
+
\
+
Traverse and transform objects by visiting every node on a recursive walk using js-traverse.
\
+
\
+ \
+ \
+ \
+ \
+ \
+ \
+ \
+ | \
+ Expression \
+ | \
+ \
+ \
+ | \
+ \
+ \
+ \
+ | \
+ \
+ No syntax error. \
+ | \
+ \
+ \
+ | \
+ \
+ | \
+ \
+ \
+ \
+ \
+ | \
+
\
+ \
+
\
+
\
+
\
+ \
+ ',
+
+ initialize: function() {
+ this.el = $(this.el);
+ },
+
+ render: function() {
+ this.el.html(this.template);
+ }
+});
+
+
my.FlotGraph = Backbone.View.extend({
tagName: "div",