Permalink
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
Cannot retrieve contributors at this time.
Cannot retrieve contributors at this time
| 'use strict'; | |
| var _ = require('underscore'); | |
| var lodash = require('lodash'); | |
| var GoodTables = require('goodtables'); | |
| var Promise = require('bluebird'); | |
| var csv = require('papaparse'); | |
| var jts = require('json-table-schema'); | |
| var inflector = require('inflected'); | |
| var path = require('path'); | |
| var url = require('url'); | |
| var validator = require('validator'); | |
| module.exports.isUrl = function(url) { | |
| return validator.isURL(url); | |
| }; | |
| module.exports.undecorateProxyUrl = function(urlToUndecorate) { | |
| var result = url.parse(urlToUndecorate, true); | |
| if (result && result.pathname) { | |
| if ((result.pathname == 'proxy') && result.query && result.query.url) { | |
| return result.query.url; | |
| } | |
| } | |
| return urlToUndecorate; | |
| }; | |
| module.exports.decorateProxyUrl = function(urlToDecorate) { | |
| return 'proxy?url=' + encodeURIComponent( | |
| module.exports.undecorateProxyUrl(urlToDecorate)); | |
| }; | |
| module.exports.convertToSlug = function(string) { | |
| var ret = inflector.parameterize( | |
| inflector.transliterate('' + (string || ''))); | |
| if (ret === '') { | |
| return 'slug'; | |
| } | |
| return ret; | |
| }; | |
| module.exports.getCsvSchema = function(urlOrFile) { | |
| return new Promise(function(resolve, reject) { | |
| var config = { | |
| download: true, | |
| preview: 1000, | |
| skipEmptyLines: true, | |
| encoding: urlOrFile.encoding, | |
| complete: function(results) { | |
| if (results.errors.length) { | |
| reject(results.errors); | |
| } | |
| var headers = _.first(results.data); | |
| var rows = _.rest(results.data); | |
| var schema = jts.infer(headers, rows); | |
| var delimiter = results.meta.delimiter; | |
| var linebreak = results.meta.linebreak; | |
| var raw = csv.unparse(results.data, { | |
| quotes: true, | |
| delimiter: ',', | |
| newline: '\r\n' | |
| }); | |
| resolve({ | |
| raw: raw, | |
| headers: headers, | |
| rows: rows, | |
| schema: schema, | |
| dialect: { | |
| delimiter: delimiter, | |
| linebreak: linebreak | |
| } | |
| }); | |
| } | |
| }; | |
| csv.parse(urlOrFile, config); | |
| }); | |
| }; | |
| module.exports.validateData = function(data, dataUrl, schema, | |
| userEndpointURL) { | |
| var goodTables = new GoodTables({ | |
| method: 'post', | |
| // jscs:disable | |
| report_type: 'grouped' | |
| // jscs:enable | |
| }, userEndpointURL); | |
| return goodTables.run( | |
| data, !!schema ? JSON.stringify(schema) : undefined, dataUrl) | |
| .then(function(results) { | |
| if (!results) { | |
| return false; | |
| } | |
| var grouped = results.getGroupedByRows(); | |
| var headers = results.getHeaders(); | |
| var encoding = results.getEncoding(); | |
| return { | |
| headers: headers, | |
| encoding: encoding, | |
| errors: _.map(grouped, function(item) { | |
| return _.extend(_.values(item)[0], { | |
| headers: headers | |
| }); | |
| }) | |
| }; | |
| }); | |
| }; | |
| module.exports.availableCurrencies = []; | |
| module.exports.getDefaultCurrency = function() { | |
| var currencies = module.exports.availableCurrencies; | |
| var defaultCurrencies = _.intersection( | |
| ['USD', 'EUR', _.first(currencies).code], | |
| _.pluck(currencies, 'code')); | |
| var defaultCurrencyCode = _.first(defaultCurrencies); | |
| return _.find(currencies, function(item) { | |
| return item.code == defaultCurrencyCode; | |
| }); | |
| }; | |
| module.exports.availableConcepts = (function() { | |
| var allTypes = _.pluck(module.exports.availableDataTypes, 'id'); | |
| var idTypes = ['integer', 'number', 'string']; | |
| return [ | |
| { | |
| name: '', | |
| id: '', | |
| group: null, | |
| required: false | |
| }, | |
| { | |
| osType: 'value', | |
| id: 'measures.amount', | |
| group: 'measure', | |
| required: true, | |
| options: [ | |
| { | |
| name: 'currency', | |
| title: 'Currency', | |
| defaultValue: null, | |
| values: [] | |
| }, | |
| { | |
| name: 'factor', | |
| title: 'Factor', | |
| defaultValue: '', | |
| type: 'number' | |
| }, | |
| { | |
| name: 'direction', | |
| title: 'Direction', | |
| defaultValue: '', | |
| values: [ | |
| {name: '', value: ''}, | |
| {name: 'Expenditure', value: 'expenditure'}, | |
| {name: 'Revenue', value: 'revenue'} | |
| ] | |
| }, | |
| { | |
| name: 'phase', | |
| title: 'Phase', | |
| defaultValue: '', | |
| values: [ | |
| {name: '', value: ''}, | |
| {name: 'Proposed', value: 'proposed'}, | |
| {name: 'Approved', value: 'approved'}, | |
| {name: 'Adjusted', value: 'adjusted'}, | |
| {name: 'Executed', value: 'executed'} | |
| ] | |
| } | |
| ] | |
| }, | |
| ]; | |
| })(); | |
| //module.exports.availablePossibilities = (function() { | |
| // var updateByConcepts = function(resources) { | |
| // if (!this || !_.isArray(this.concepts)) { | |
| // return; | |
| // } | |
| // | |
| // var conceptsToCheck = _.chain(this.concepts) | |
| // .map(function(concept) { | |
| // return [concept, false]; | |
| // }) | |
| // .object() | |
| // .value(); | |
| // | |
| // var self = this; | |
| // _.each(resources, function(resource) { | |
| // _.each(resource.fields, function(field) { | |
| // if (_.contains(self.concepts, field.concept)) { | |
| // conceptsToCheck[field.concept] = true; | |
| // } | |
| // }); | |
| // }); | |
| // | |
| // this.isAvailable = !_.contains(conceptsToCheck, false); | |
| // }; | |
| // | |
| // return [ | |
| // { | |
| // id: 'transaction-table', | |
| // name: 'Transaction Table', | |
| // isAvailable: false, | |
| // concepts: ['measures.amount'], | |
| // graph: 'pie', | |
| // icon: 'os-icon os-icon-piechart', | |
| // update: updateByConcepts | |
| // }, | |
| // { | |
| // id: 'time-series', | |
| // name: 'Time series', | |
| // isAvailable: false, | |
| // graph: 'lines', | |
| // icon: 'os-icon os-icon-linechart', | |
| // concepts: ['measures.amount', 'dimensions.datetime'], | |
| // update: updateByConcepts | |
| // }, | |
| // { | |
| // id: 'treemap', | |
| // name: 'Treemap', | |
| // isAvailable: false, | |
| // graph: 'treemap', | |
| // icon: 'os-icon os-icon-treemap', | |
| // concepts: ['measures.amount', 'dimensions.classification'], | |
| // update: updateByConcepts | |
| // }, | |
| // { | |
| // id: 'classification', | |
| // name: 'Classification explorer', | |
| // isAvailable: false, | |
| // graph: 'treemap', | |
| // icon: 'os-icon os-icon-table', | |
| // concepts: ['measures.amount', 'dimensions.classification'], | |
| // update: updateByConcepts | |
| // }, | |
| // { | |
| // id: 'mutlidimension', | |
| // name: 'Multiple dimension agg', | |
| // isAvailable: false, | |
| // graph: 'treemap', | |
| // icon: 'os-icon os-icon-layers', | |
| // concepts: ['measures.amount'], | |
| // update: function(resources) { | |
| // updateByConcepts.call(this, resources); | |
| // if (this.isAvailable) { | |
| // var countOfDimensions = 0; | |
| // _.each(resources, function(resource) { | |
| // _.each(resource.fields, function(field) { | |
| // var concept = _.findWhere(module.exports.availableConcepts, { | |
| // id: field.concept | |
| // }); | |
| // if (concept && (concept.group == 'dimension')) { | |
| // countOfDimensions += 1; | |
| // } | |
| // }); | |
| // }); | |
| // // There should be at least one measure and more than one dimension | |
| // if (countOfDimensions < 2) { | |
| // this.isAvailable = false; | |
| // } | |
| // } | |
| // } | |
| // } | |
| // ]; | |
| //})(); | |
| module.exports.setAvailableCurrencies = function(currencies) { | |
| var temp = module.exports.availableCurrencies; | |
| temp.splice(0, temp.length); | |
| if (_.isArray(currencies)) { | |
| [].push.apply(temp, currencies); | |
| } | |
| }; | |
| module.exports.setAvailableCurrencies(require('../data/iso4217.json')); | |
| module.exports.createNameFromPath = function(fileName) { | |
| var result = path.basename(fileName, path.extname(fileName)); | |
| return module.exports.convertToSlug(result || fileName); | |
| }; | |
| module.exports.createNameFromUrl = function(urlOfResource) { | |
| var result = url.parse(module.exports.undecorateProxyUrl(urlOfResource)); | |
| if (result && result.pathname) { | |
| return module.exports.createNameFromPath(result.pathname); | |
| } | |
| return urlOfResource; | |
| }; | |
| module.exports.createUniqueName = function(desiredName, availableNames) { | |
| if (!_.contains(availableNames, desiredName)) { | |
| return desiredName; | |
| } | |
| desiredName += '-'; | |
| var mapped = _.map(availableNames, function(item) { | |
| if (item.indexOf(desiredName) == 0) { | |
| var rest = item.substr(desiredName.length); | |
| if (rest.match(/^[0-9]$/g)) { | |
| return parseInt(rest); | |
| } | |
| } | |
| return 0; | |
| }); | |
| mapped.push(0); | |
| return desiredName + (_.max(mapped) + 1); | |
| }; | |
| module.exports.addItemWithUniqueName = function(collection, item) { | |
| item.name = module.exports.createUniqueName(item.name, | |
| _.pluck(collection, 'name')); | |
| collection.push(item); | |
| }; | |
| module.exports.removeEmptyAttributes = function(object) { | |
| return _.pick(object, function(value) { | |
| return !!value; | |
| }); | |
| }; | |
| //module.exports.getDataForPreview = function() { return [{name:'Hello',value:'world',dateTime:'today'}]; }; | |
| //module.exports.getDataForPreview = function(resources, maxCount) { | |
| // if (!_.isArray(resources) || (resources.length < 1)) { | |
| // return []; | |
| // } | |
| // | |
| // var amountFieldIndex = null; | |
| // var dateTimeFieldIndex = null; | |
| // var dimensionFieldIndex = null; | |
| // | |
| // var resource = _.first(resources); | |
| // _.each(resource.fields, function(field, index) { | |
| // switch (field.concept) { | |
| // case 'measures.amount': amountFieldIndex = index; break; | |
| // case 'dimensions.datetime': dateTimeFieldIndex = index; break; | |
| // case 'dimensions.entity': dimensionFieldIndex = index; break; | |
| // case 'dimensions.classification': dimensionFieldIndex = index; break; | |
| // case 'dimensions.activity': dimensionFieldIndex = index; break; | |
| // case 'dimensions.location': dimensionFieldIndex = index; break; | |
| // } | |
| // }); | |
| // | |
| // if (amountFieldIndex === null) { | |
| // return []; | |
| // } | |
| // | |
| // if (dimensionFieldIndex === null) { | |
| // dimensionFieldIndex = dateTimeFieldIndex; | |
| // } | |
| // if (dimensionFieldIndex === null) { | |
| // dimensionFieldIndex = amountFieldIndex; | |
| // } | |
| // | |
| // var rows = resource.data.rows; | |
| // maxCount = parseFloat(maxCount); | |
| // if (isFinite(maxCount)) { | |
| // rows = rows.slice(0, maxCount); | |
| // } | |
| // | |
| // return _.map(rows, function(row) { | |
| // var result = {}; | |
| // result.value = row[amountFieldIndex]; | |
| // if (dateTimeFieldIndex !== null) { | |
| // result.dateTime = row[dateTimeFieldIndex]; | |
| // } | |
| // if (dimensionFieldIndex !== null) { | |
| // result.name = row[dimensionFieldIndex]; | |
| // } | |
| // | |
| // return result; | |
| // }); | |
| //}; | |
| module.exports.blobToFileDescriptor = function(blob, maxAllowedSize) { | |
| if ((typeof Blob == 'undefined') || !_.isFunction(Blob) || | |
| !(blob instanceof Blob)) { | |
| return Promise.resolve(blob); | |
| } | |
| if (!!maxAllowedSize && (maxAllowedSize > 0) && | |
| (blob.size > maxAllowedSize)) { | |
| return Promise.resolve(blob); | |
| } | |
| return new Promise(function(resolve, reject) { | |
| var reader = new FileReader(); | |
| reader.addEventListener('loadend', function() { | |
| resolve({ | |
| name: blob.name, | |
| type: blob.type, | |
| size: reader.result.length, | |
| data: reader.result | |
| }); | |
| }); | |
| reader.addEventListener('error', function() { | |
| reject(reader.error); | |
| }); | |
| reader.readAsArrayBuffer(blob); | |
| }); | |
| }; | |
| module.exports.fileDescriptorToBlob = function(descriptor) { | |
| var result = descriptor; | |
| if (_.isObject(descriptor) && _.isFunction(Blob)) { | |
| if (descriptor instanceof Blob) { | |
| result = descriptor; | |
| } else { | |
| result = new Blob([descriptor.data], { | |
| type: descriptor.type | |
| }); | |
| result.name = descriptor.name; | |
| result.encoding = descriptor.encoding; | |
| } | |
| } | |
| return Promise.resolve(result); | |
| }; |