mirror of https://github.com/BTCPrivate/copay.git
added files
This commit is contained in:
parent
6797c3db19
commit
3fc401ea79
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* Small module for exporting data to CSV.
|
||||
*/
|
||||
var _ = require('lodash');
|
||||
var preconditions = require('preconditions').singleton();
|
||||
var moment = require('../../lib/moment/moment');
|
||||
|
||||
var logger = require('../util/log.js');
|
||||
var config = require('../../config');
|
||||
|
||||
|
||||
var COL_DELIMITER = ',';
|
||||
var ROW_DELIMITER = '\r\n';
|
||||
|
||||
function getValue(obj, property) {
|
||||
if (_.isFunction(property)) {
|
||||
try {
|
||||
return property(obj);
|
||||
} catch (err) {
|
||||
if (_.isString(err)) return err;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
if (!_.isObject(obj)) return undefined;
|
||||
return obj.hasOwnProperty(property) ? obj[property] : undefined;
|
||||
};
|
||||
|
||||
function formatValue(value, type, format) {
|
||||
if (_.isUndefined(value) || _.isNull(value)) return '';
|
||||
|
||||
var r;
|
||||
switch (type) {
|
||||
default:
|
||||
case 'string':
|
||||
r = value.toString();
|
||||
r.replace('"', '\\"');
|
||||
break;
|
||||
case 'date':
|
||||
r = moment(value).format(format);
|
||||
break;
|
||||
case 'number':
|
||||
r = value.toString();
|
||||
break;
|
||||
}
|
||||
|
||||
// escape when commas in values
|
||||
if (r.indexOf(',') !== -1) {
|
||||
r = '"' + r + '"';
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
function getHeader(descriptor) {
|
||||
return _.map(descriptor.columns, function (col) {
|
||||
return col.label || (_.isString(col.property) ? col.property : '') || '';
|
||||
});
|
||||
};
|
||||
|
||||
function processDataRow(data, descriptor) {
|
||||
return _.map(descriptor.columns, function (col) {
|
||||
var value = getValue(data, col.property);
|
||||
var formatted = formatValue(value, col.type, col.format);
|
||||
return formatted;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Convert json object to csv based on a descriptor
|
||||
*
|
||||
* @param {array} data - the array of json objects to convert to csv
|
||||
* @param {object} descriptor - an object that parameterizes the conversion
|
||||
* @param {function} cb - called with the resulting csv
|
||||
*/
|
||||
module.exports.toCsv = function(data, descriptor, cb) {
|
||||
preconditions.shouldBeArray(data);
|
||||
preconditions.shouldBeObject(descriptor);
|
||||
preconditions.shouldBeArray(descriptor.columns);
|
||||
preconditions.shouldBeFunction(cb);
|
||||
|
||||
var colDelimiter = descriptor.colDelimiter || COL_DELIMITER;
|
||||
var rowDelimiter = descriptor.rowDelimiter || ROW_DELIMITER;
|
||||
|
||||
var rows = _.map(data, function (dataRow) {
|
||||
return processDataRow(dataRow, descriptor);
|
||||
});
|
||||
|
||||
var header = getHeader(descriptor);
|
||||
rows.unshift(header);
|
||||
|
||||
var csv = _.reduce(rows, function (memo, row) {
|
||||
return memo + row.join(colDelimiter) + rowDelimiter;
|
||||
}, '');
|
||||
|
||||
return cb(null, csv);
|
||||
};
|
|
@ -0,0 +1,166 @@
|
|||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var chai = chai || require('chai');
|
||||
var sinon = sinon || require('sinon');
|
||||
var should = chai.should();
|
||||
|
||||
var csv = require('../js/util/csv')
|
||||
var moment = require('../lib/moment/moment');
|
||||
|
||||
describe('csv utils', function() {
|
||||
it('should convert simple json', function(done) {
|
||||
var data = [
|
||||
{ name: 'Lennon John', age: 40, lastLogin: moment(1417608870000), },
|
||||
{ name: 'Cobain, Kurt', age: 27, lastLogin: moment('2014-11-01'), },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ label: 'Name', property: 'name', type: 'string' },
|
||||
{ label: 'Age', property: 'age', type: 'number' },
|
||||
{ property: 'lastLogin', type: 'date' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('Name,Age,lastLogin\r\nLennon John,40,2014-12-03T09:14:30-03:00\r\n"Cobain, Kurt",27,2014-11-01T00:00:00-03:00\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should handle empty data', function(done) {
|
||||
var data = [];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ label: 'Name', property: 'name', type: 'string' },
|
||||
{ label: 'Age', property: 'age', type: 'number' },
|
||||
{ property: 'lastLogin', type: 'date' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('Name,Age,lastLogin\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should handle null row in data', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', age: 40 },
|
||||
null,
|
||||
{ name: 'Kurt', age: 27 },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ label: 'Name', property: 'name', type: 'string' },
|
||||
{ label: 'Age', property: 'age', type: 'number' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('Name,Age\r\nJohn,40\r\n,\r\nKurt,27\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should format dates', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', age: 40, lastLogin: moment(1417608870000), },
|
||||
{ name: 'Kurt', age: 27, lastLogin: moment('2014-11-01'), },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ property: 'name', type: 'string' },
|
||||
{ property: 'age', type: 'number' },
|
||||
{ property: 'lastLogin', type: 'date', format: 'YYYY MM DD' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('name,age,lastLogin\r\nJohn,40,2014 12 03\r\nKurt,27,2014 11 01\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should compute values from function properties', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', payments: 400, withdrawals: 300, },
|
||||
{ name: 'Kurt', payments: 270.5, withdrawals: 200, },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ property: 'name', type: 'string' },
|
||||
{ label: 'Balance', property: function (obj) { return obj.payments - obj.withdrawals; }, type: 'number' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('name,Balance\r\nJohn,100\r\nKurt,70.5\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should not fail on error from calculated values', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', error: 0 },
|
||||
{ name: 'Kurt', error: 1 },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [{
|
||||
property: 'name',
|
||||
type: 'string'
|
||||
}, {
|
||||
label: 'Error',
|
||||
property: function(obj) {
|
||||
if (obj.error) {
|
||||
throw 'dummy error';
|
||||
} else {
|
||||
return 'ok';
|
||||
}
|
||||
}
|
||||
}, ],
|
||||
};
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('name,Error\r\nJohn,ok\r\nKurt,dummy error\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should use blank label if label not specified for computed property', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', payments: 400, withdrawals: 300, },
|
||||
{ name: 'Kurt', payments: 270.5, withdrawals: 200, },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ property: 'name', type: 'string' },
|
||||
{ property: function (obj) { return obj.payments - obj.withdrawals; }, type: 'number' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('name,\r\nJohn,100\r\nKurt,70.5\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should handle non existent properties', function(done) {
|
||||
var data = [
|
||||
{ name: 'John', age: 40 },
|
||||
{ name: 'Kurt', age: 27 },
|
||||
];
|
||||
|
||||
var descriptor = {
|
||||
columns: [
|
||||
{ property: 'name', type: 'string' },
|
||||
{ property: 'age', type: 'number' },
|
||||
{ property: 'lastLogin', type: 'date', format: 'YYYY MM DD' },
|
||||
],
|
||||
};
|
||||
|
||||
csv.toCsv(data, descriptor, function (err, res) {
|
||||
res.should.equal('name,age,lastLogin\r\nJohn,40,\r\nKurt,27,\r\n');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue