[#128,backend/gdoc][s]: refactor gdocs to standard backend setup.
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
this.recline = this.recline || {};
|
this.recline = this.recline || {};
|
||||||
this.recline.Backend = this.recline.Backend || {};
|
this.recline.Backend = this.recline.Backend || {};
|
||||||
|
this.recline.Backend.GDocs = this.recline.Backend.GDocs || {};
|
||||||
|
|
||||||
(function($, my) {
|
(function($, my) {
|
||||||
|
|
||||||
// ## Google spreadsheet backend
|
// ## Google spreadsheet backend
|
||||||
//
|
//
|
||||||
// Connect to Google Docs spreadsheet.
|
// Connect to Google Docs spreadsheet.
|
||||||
@@ -16,50 +18,25 @@ this.recline.Backend = this.recline.Backend || {};
|
|||||||
// 'gdocs'
|
// 'gdocs'
|
||||||
// );
|
// );
|
||||||
// </pre>
|
// </pre>
|
||||||
my.GDoc = my.Base.extend({
|
my.Backbone = function() {
|
||||||
__type__: 'gdoc',
|
this.__type__ = 'gdocs';
|
||||||
readonly: true,
|
this.readonly = true;
|
||||||
getUrl: function(dataset) {
|
|
||||||
var url = dataset.get('url');
|
this.sync = function(method, model, options) {
|
||||||
if (url.indexOf('feeds/list') != -1) {
|
|
||||||
return url;
|
|
||||||
} else {
|
|
||||||
// https://docs.google.com/spreadsheet/ccc?key=XXXX#gid=0
|
|
||||||
var regex = /.*spreadsheet\/ccc?.*key=([^#?&+]+).*/;
|
|
||||||
var matches = url.match(regex);
|
|
||||||
if (matches) {
|
|
||||||
var key = matches[1];
|
|
||||||
var worksheet = 1;
|
|
||||||
var out = 'https://spreadsheets.google.com/feeds/list/' + key + '/' + worksheet + '/public/values?alt=json';
|
|
||||||
return out;
|
|
||||||
} else {
|
|
||||||
alert('Failed to extract gdocs key from ' + url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sync: function(method, model, options) {
|
|
||||||
var self = this;
|
var self = this;
|
||||||
if (method === "read") {
|
if (method === "read") {
|
||||||
var dfd = $.Deferred();
|
var dfd = $.Deferred();
|
||||||
var dataset = model;
|
loadData(model.get('url')).done(function(result) {
|
||||||
|
model.fields.reset(result.fields);
|
||||||
var url = this.getUrl(model);
|
|
||||||
|
|
||||||
$.getJSON(url, function(d) {
|
|
||||||
result = self.gdocsToJavascript(d);
|
|
||||||
model.fields.reset(_.map(result.field, function(fieldId) {
|
|
||||||
return {id: fieldId};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
// cache data onto dataset (we have loaded whole gdoc it seems!)
|
// cache data onto dataset (we have loaded whole gdoc it seems!)
|
||||||
model._dataCache = result.data;
|
model._dataCache = result.data;
|
||||||
dfd.resolve(model);
|
dfd.resolve(model);
|
||||||
});
|
});
|
||||||
return dfd.promise();
|
return dfd.promise();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
query: function(dataset, queryObj) {
|
this.query = function(dataset, queryObj) {
|
||||||
var dfd = $.Deferred();
|
var dfd = $.Deferred();
|
||||||
var fields = _.pluck(dataset.fields.toJSON(), 'id');
|
var fields = _.pluck(dataset.fields.toJSON(), 'id');
|
||||||
|
|
||||||
@@ -72,70 +49,115 @@ this.recline.Backend = this.recline.Backend || {};
|
|||||||
});
|
});
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
dfd.resolve(this._docsToQueryResult(objs));
|
var out = {
|
||||||
|
total: objs.length,
|
||||||
|
hits: _.map(objs, function(row) {
|
||||||
|
return { _source: row }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
dfd.resolve(out);
|
||||||
return dfd;
|
return dfd;
|
||||||
},
|
};
|
||||||
gdocsToJavascript: function(gdocsSpreadsheet) {
|
};
|
||||||
/*
|
|
||||||
:options: (optional) optional argument dictionary:
|
|
||||||
columnsToUse: list of columns to use (specified by field names)
|
|
||||||
colTypes: dictionary (with column names as keys) specifying types (e.g. range, percent for use in conversion).
|
|
||||||
:return: tabular data object (hash with keys: field and data).
|
|
||||||
|
|
||||||
Issues: seems google docs return columns in rows in random order and not even sure whether consistent across rows.
|
// ## loadData
|
||||||
*/
|
//
|
||||||
var options = {};
|
// loadData from a google docs URL
|
||||||
if (arguments.length > 1) {
|
//
|
||||||
options = arguments[1];
|
// @return object with two attributes
|
||||||
}
|
//
|
||||||
var results = {
|
// * fields: array of objects
|
||||||
'field': [],
|
// * data: array of arrays
|
||||||
'data': []
|
var loadData = function(url) {
|
||||||
};
|
var dfd = $.Deferred();
|
||||||
// default is no special info on type of columns
|
var url = my.getSpreadsheetAPIUrl(url);
|
||||||
var colTypes = {};
|
var out = {
|
||||||
if (options.colTypes) {
|
fields: [],
|
||||||
colTypes = options.colTypes;
|
data: []
|
||||||
}
|
|
||||||
// either extract column headings from spreadsheet directly, or used supplied ones
|
|
||||||
if (options.columnsToUse) {
|
|
||||||
// columns set to subset supplied
|
|
||||||
results.field = options.columnsToUse;
|
|
||||||
} else {
|
|
||||||
// set columns to use to be all available
|
|
||||||
if (gdocsSpreadsheet.feed.entry.length > 0) {
|
|
||||||
for (var k in gdocsSpreadsheet.feed.entry[0]) {
|
|
||||||
if (k.substr(0, 3) == 'gsx') {
|
|
||||||
var col = k.substr(4);
|
|
||||||
results.field.push(col);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts non numberical values that should be numerical (22.3%[string] -> 0.223[float])
|
|
||||||
var rep = /^([\d\.\-]+)\%$/;
|
|
||||||
$.each(gdocsSpreadsheet.feed.entry, function (i, entry) {
|
|
||||||
var row = [];
|
|
||||||
for (var k in results.field) {
|
|
||||||
var col = results.field[k];
|
|
||||||
var _keyname = 'gsx$' + col;
|
|
||||||
var value = entry[_keyname]['$t'];
|
|
||||||
// if labelled as % and value contains %, convert
|
|
||||||
if (colTypes[col] == 'percent') {
|
|
||||||
if (rep.test(value)) {
|
|
||||||
var value2 = rep.exec(value);
|
|
||||||
var value3 = parseFloat(value2);
|
|
||||||
value = value3 / 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row.push(value);
|
|
||||||
}
|
|
||||||
results.data.push(row);
|
|
||||||
});
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
});
|
$.getJSON(url, function(d) {
|
||||||
|
result = my.parseData(d);
|
||||||
|
result.fields = _.map(result.fields, function(fieldId) {
|
||||||
|
return {id: fieldId};
|
||||||
|
});
|
||||||
|
dfd.resolve(result);
|
||||||
|
});
|
||||||
|
return dfd.promise();
|
||||||
|
};
|
||||||
|
|
||||||
}(jQuery, this.recline.Backend));
|
// ## parseData
|
||||||
|
//
|
||||||
|
// Parse data from Google Docs API into a reasonable form
|
||||||
|
//
|
||||||
|
// :options: (optional) optional argument dictionary:
|
||||||
|
// columnsToUse: list of columns to use (specified by field names)
|
||||||
|
// colTypes: dictionary (with column names as keys) specifying types (e.g. range, percent for use in conversion).
|
||||||
|
// :return: tabular data object (hash with keys: field and data).
|
||||||
|
//
|
||||||
|
// Issues: seems google docs return columns in rows in random order and not even sure whether consistent across rows.
|
||||||
|
my.parseData = function(gdocsSpreadsheet) {
|
||||||
|
var options = {};
|
||||||
|
if (arguments.length > 1) {
|
||||||
|
options = arguments[1];
|
||||||
|
}
|
||||||
|
var results = {
|
||||||
|
'fields': [],
|
||||||
|
'data': []
|
||||||
|
};
|
||||||
|
// default is no special info on type of columns
|
||||||
|
var colTypes = {};
|
||||||
|
if (options.colTypes) {
|
||||||
|
colTypes = options.colTypes;
|
||||||
|
}
|
||||||
|
if (gdocsSpreadsheet.feed.entry.length > 0) {
|
||||||
|
for (var k in gdocsSpreadsheet.feed.entry[0]) {
|
||||||
|
if (k.substr(0, 3) == 'gsx') {
|
||||||
|
var col = k.substr(4);
|
||||||
|
results.fields.push(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts non numberical values that should be numerical (22.3%[string] -> 0.223[float])
|
||||||
|
var rep = /^([\d\.\-]+)\%$/;
|
||||||
|
$.each(gdocsSpreadsheet.feed.entry, function (i, entry) {
|
||||||
|
var row = [];
|
||||||
|
for (var k in results.fields) {
|
||||||
|
var col = results.fields[k];
|
||||||
|
var _keyname = 'gsx$' + col;
|
||||||
|
var value = entry[_keyname]['$t'];
|
||||||
|
// if labelled as % and value contains %, convert
|
||||||
|
if (colTypes[col] == 'percent') {
|
||||||
|
if (rep.test(value)) {
|
||||||
|
var value2 = rep.exec(value);
|
||||||
|
var value3 = parseFloat(value2);
|
||||||
|
value = value3 / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row.push(value);
|
||||||
|
}
|
||||||
|
results.data.push(row);
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convenience function to get GDocs JSON API Url from standard URL
|
||||||
|
my.getSpreadsheetAPIUrl = function(url) {
|
||||||
|
if (url.indexOf('feeds/list') != -1) {
|
||||||
|
return url;
|
||||||
|
} else {
|
||||||
|
// https://docs.google.com/spreadsheet/ccc?key=XXXX#gid=0
|
||||||
|
var regex = /.*spreadsheet\/ccc?.*key=([^#?&+]+).*/;
|
||||||
|
var matches = url.match(regex);
|
||||||
|
if (matches) {
|
||||||
|
var key = matches[1];
|
||||||
|
var worksheet = 1;
|
||||||
|
var out = 'https://spreadsheets.google.com/feeds/list/' + key + '/' + worksheet + '/public/values?alt=json';
|
||||||
|
return out;
|
||||||
|
} else {
|
||||||
|
alert('Failed to extract gdocs key from ' + url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}(jQuery, this.recline.Backend.GDocs));
|
||||||
|
|
||||||
|
|||||||
@@ -273,8 +273,8 @@ var sample_gdocs_spreadsheet_data = {
|
|||||||
"encoding": "UTF-8"
|
"encoding": "UTF-8"
|
||||||
}
|
}
|
||||||
|
|
||||||
test("GDoc Backend", function() {
|
test("GDocs Backend", function() {
|
||||||
var backend = new recline.Backend.GDoc();
|
var backend = new recline.Backend.GDocs.Backbone();
|
||||||
var dataset = new recline.Model.Dataset({
|
var dataset = new recline.Model.Dataset({
|
||||||
url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json'
|
url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json'
|
||||||
},
|
},
|
||||||
@@ -301,13 +301,10 @@ test("GDoc Backend", function() {
|
|||||||
$.getJSON.restore();
|
$.getJSON.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("GDoc Backend.getUrl", function() {
|
test("GDocs Backend.getUrl", function() {
|
||||||
var key = 'Abc_dajkdkjdafkj';
|
var key = 'Abc_dajkdkjdafkj';
|
||||||
var dataset = new recline.Model.Dataset({
|
var url = 'https://docs.google.com/spreadsheet/ccc?key=' + key + '#gid=0'
|
||||||
url: 'https://docs.google.com/spreadsheet/ccc?key=' + key + '#gid=0'
|
var out = recline.Backend.GDocs.getSpreadsheetAPIUrl(url);
|
||||||
});
|
|
||||||
var backend = new recline.Backend.GDoc();
|
|
||||||
var out = backend.getUrl(dataset);
|
|
||||||
var exp = 'https://spreadsheets.google.com/feeds/list/' + key + '/1/public/values?alt=json'
|
var exp = 'https://spreadsheets.google.com/feeds/list/' + key + '/1/public/values?alt=json'
|
||||||
equal(exp, out);
|
equal(exp, out);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user