Changeset 475


Ignore:
Timestamp:
07/28/13 17:46:12 (12 years ago)
Author:
hendrikvanantwerpen
Message:
  • Added CouchDB script to make interacting with couch easier.
  • Use this script in the database configuration.
  • Get CSV export to work.
Location:
Dev/trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • Dev/trunk/package.json

    r469 r475  
    66    "grunt": "~0.4.0",
    77    "grunt-contrib-copy": "~0.4.1",
    8     "grunt-contrib-jshint": "~0.2.0",
    9     "grunt-contrib-less": "~0.5.0",
     8    "grunt-contrib-jshint": "~0.6.0",
     9    "grunt-contrib-less": "~0.6.4",
    1010    "grunt-dojo": "~0.2.3",
    1111    "grunt-exec": "~0.4.1",
    1212    "grunt-htmlhint": "~0.4.0",
    13     "grunt-contrib-clean": "~0.4.1",
     13    "grunt-contrib-clean": "~0.5.0",
    1414    "grunt-contrib-coffee": "~0.7.0",
    1515    "underscore": "~1.4.4",
    16     "grunt-coffeelint": "0.0.6",
     16    "grunt-coffeelint": "~0.0.6",
    1717    "grunt-banner": "~0.1.4",
    1818    "grunt-amd-check": "~0.5.2"
  • Dev/trunk/src/.jshintrc

    r469 r475  
    66    "immed": true,
    77    "indent": 4,
    8     "latedef": true,
     8    "latedef": "nofunc",
    99    "newcap": true,
    1010    "noarg": true,
     
    1616
    1717    "loopfunc": true,
     18    "laxcomma": true,
    1819
    1920    "devel": true,
  • Dev/trunk/src/.jshintrc-generated

    r469 r475  
    2121    "browser": true,
    2222    "couch": true,
     23    "boss": true,
    2324
    2425    "globals": {
  • Dev/trunk/src/package.json

    r468 r475  
    99    "passport-local": "~0.1.6",
    1010    "q": "~0.9.6",
    11     "request": "~2.21.0"
     11    "request": "~2.21.0",
     12    "ya-csv": "~0.9.2"
    1213  },
    1314  "engines": {
  • Dev/trunk/src/server/app.js

    r470 r475  
    1 var express = require("express");
    2 var passport = require("passport"),
    3     passportLocal = require("passport-local");
    4 var fs = require("fs");
    5 var path = require("path");
    6 var proxy = require("./util/simple-http-proxy");
    7 var _ = require("underscore");
     1var express = require("express")
     2  , passport = require("passport")
     3  , passportLocal = require("passport-local")
     4  , fs = require("fs")
     5  , path = require("path")
     6  , proxy = require("./util/simple-http-proxy")
     7  , CSV = require("ya-csv")
     8  , CouchDB = require('./util/couch').CouchDB
     9  , _ = require("underscore")
     10  ;
    811
    912function assertSetting(name, settings, validate) {
     
    1922
    2023    assertSetting("couchDbURL", settings, _.isString);
     24    var couch = new CouchDB(settings.couchDbURL);
    2125   
    2226    function clientPath(relativePath) {
     
    105109        function(req, res) {
    106110            var id = req.params.id;
    107             // query CouchDB and build the CSV file
    108             res.set({
    109                 'Content-Type': 'text/csv',
    110                 'Content-Disposition': 'attachment; filename=surveyRun-'+id+'-responses.csv'
     111            var url = '_design/responses/_view/by_surveyrun?key='+JSON.stringify(id);
     112            couch.get(url).then(function(result){
     113                var responses = _.map(result.rows, function(item) { return item.value; });
     114                var flatResponses = responsesToVariables(responses);
     115                res.set({
     116                    'Content-Type': 'text/csv',
     117                    'Content-Disposition': 'attachment; filename=surveyRun-'+id+'-responses.csv'
     118                });
     119                res.status(200);
     120                writeObjectsToCSVStream(flatResponses, res);
     121                res.end();
     122            }, function(error){
     123                res.send(404, {error: "Cannot find responses for survey run "+id});
    111124            });
    112             res.send(200, "Response for surveyRun "+id);
    113125        });
    114126   
     
    116128
    117129};
     130
     131function responsesToVariables(responses) {
     132    return _.map(responses, responseToVariables);
     133}
     134
     135function responseToVariables(response) {
     136    var result = flattenObject(response.answers);
     137    result.respondent = response.id;
     138    return result;
     139}
     140
     141function flattenObject(value) {
     142    var result = {};
     143    (function agg(val,key,res){
     144        if ( _.isObject(val) ) {
     145            _.forEach(val, function(v,k){
     146                agg(v,(key ? key+'.' : '')+k,res);
     147            });
     148        } else if ( _.isArray(val) ) {
     149            _.forEach(val, function(v,i){
     150                agg(v,(key ? key+'.' : '')+i,res);
     151            });
     152        } else {
     153            res[key] = val;
     154        }
     155    })(value,null,result);
     156    return result;
     157}
     158
     159function writeObjectsToCSVStream(objects, stream) {
     160    var keys = _.chain(objects)
     161                .map(_.keys)
     162                .flatten()
     163                .uniq()
     164                .value();
     165    var idxs = {};
     166    _.forEach(keys, function(key,idx){
     167        idxs[key] = idx;
     168    });
     169    var writer = new CSV.CsvWriter(stream);
     170    writer.writeRecord(keys);
     171    _.forEach(objects, function(obj){
     172        var row = [];
     173        _.forEach(obj, function(val,key){
     174            row[idxs[key]] = val;
     175        });
     176        writer.writeRecord(row);
     177    });
     178}
  • Dev/trunk/src/server/config/config-couchdb.js

    r470 r475  
    1 var q = require('q'),
    2     request = require('../util/q-request'),
    3     _ = require('underscore'),
    4     util = require('util');
     1var Q = require('q')
     2  , request = require('../util/q-request')
     3  , _ = require('underscore')
     4  , CouchDB = require('../util/couch').CouchDB
     5  , util = require('util');
    56
    67var designDocs = require('./couchdb-design-docs');
    78
    89module.exports = function(couchDbURL) {
    9 
    10     function stringifyFunctions(value) {
    11         if ( value === null ) {
    12             return null;
    13         } else if ( _.isArray(value) ) {
    14             return value;
    15         } else if ( _.isFunction(value) ) {
    16             return value.toString();
    17         } else if ( _.isObject(value) ) {
    18             value = _.clone(value);
    19             _.each(value, function(propValue, propName){
    20                 value[propName] = stringifyFunctions(propValue);
    21             });
    22             return value;
    23         } else {
    24             return value;
    25         }
    26     }
    27 
    28     function dbRequest(method,path,content) {
    29         var url = couchDbURL+path;
    30         var options = {
    31             method: method,
    32             headers: {
    33                 'content-type': 'application/json; charset=utf-8',
    34                 'accept': 'application/json'
    35             },
    36             body: JSON.stringify(content)
    37         };
    38         //console.log('req',url,options);
    39         return request(url,options).then(function(res){
    40             return JSON.parse(res);
    41         }, function(err){
    42             return JSON.parse(err);
    43         });
    44     }
     10    var server = new CouchDB(couchDbURL);
    4511
    4612    console.log("Configuring CouchDB for QED");
    4713    console.log("Checking CouchDB version");
    48     return dbRequest('GET','')
    49     .then(function(res){
    50         if (res.version !== "1.2.0" ) {
    51             console.log("Found "+res.version+", only tested with CouchDB 1.2.0");
     14    return server.get('')
     15    .then(function(info){
     16        if (info.version !== "1.2.0" ) {
     17            console.log("Found "+info.version+", only tested with CouchDB 1.2.0");
    5218        } else {
    5319            console.log("CouchDB 1.2.0 found");
     
    5521    }).then(function(res){
    5622        console.log("Checking database 'qed'");
    57         return dbRequest('GET','qed')
    58         .then(function(res){
     23        return server.get('qed')
     24        .then(function(db){
    5925            console.log("Database 'qed' found.");
    6026        },function(err){
    6127            console.log("Creating database 'qed'");
    62             return dbRequest('PUT','qed');
     28            return server.put('qed');
    6329        });
    6430    }).then(function(){
    6531        console.log("Putting documents in database.");
    66         designDocs = stringifyFunctions(designDocs);
    67         return q.all(_.map(designDocs, function(doc,docUrl){
     32        return _.reduce(designDocs, function(memo, doc, docUrl) {
    6833            var configAction = doc.__configAction || "replace";
    6934            delete doc.__configAction;
     
    7136            case "ignore":
    7237                console.log(docUrl+" ignored.");
    73                 break;
     38                return memo;
    7439            case "update":
    7540                console.log(docUrl+" updating.");
    76                 return dbRequest('GET',docUrl)
    77                 .then(function(oldDoc){
    78                     _.extend(oldDoc,doc);
    79                     return dbRequest('PUT',docUrl,oldDoc);
    80                 },function(){
    81                     return dbRequest('PUT',docUrl,doc);
     41                return memo.then(function(){
     42                    server.get(docUrl)
     43                    .then(function(oldDoc){
     44                        _.extend(oldDoc,doc);
     45                        return server.put(docUrl,oldDoc);
     46                    },function(){
     47                        return server.put(docUrl,doc);
     48                    });
    8249                });
    8350            case "replace":
    8451                console.log(docUrl+" replacing.");
    85                 return dbRequest('GET',docUrl)
    86                 .then(function(oldDoc){
    87                     _.extend(doc,_.pick(oldDoc,'_id','_rev'));
    88                     return dbRequest('PUT',docUrl,doc);
    89                 },function(){
    90                     return dbRequest('PUT',docUrl,doc);
     52                return memo.then(function(){
     53                    server.get(docUrl)
     54                    .then(function(oldDoc){
     55                        _.extend(doc,_.pick(oldDoc,'_id','_rev'));
     56                        return server.put(docUrl,doc);
     57                    },function(){
     58                        return server.put(docUrl,doc);
     59                    });
    9160                });
    9261            default:
    9362                console.warn("Unknown action",configAction);
    94                 break;
     63                return memo;
    9564            }
    96         }));
     65        }, Q.resolve());
    9766    }).then(function(results){
    98         console.log("Done!");
     67        console.log("Done!", results);
    9968    },function(err){
    10069        console.error("ERROR",err,err.stack);
  • Dev/trunk/src/server/heroku.js

    r468 r475  
    1515        console.log('Listening on port',port);
    1616    });
     17}, function(error){
     18    console.error(error);
    1719});
  • Dev/trunk/src/server/util

    • Property svn:ignore set to

      ### begin grunt-svn-ignore managed ignores
      ### edits will be overwritten when grunt svn-ignore is run
      couch.js
      ### end grunt-svn-ignore managed ignores
Note: See TracChangeset for help on using the changeset viewer.