Changeset 531 for Dev/trunk/src/server


Ignore:
Timestamp:
03/27/14 14:44:36 (11 years ago)
Author:
hendrikvanantwerpen
Message:
  • Return to using truly ISO formatted dates, including milliseconds.
  • Also set constraint on surveyrun dates when value is initially set.
  • Separate runs & results from surveys and questions.
  • Moved date & email format to schema itself.
Location:
Dev/trunk/src/server
Files:
1 added
7 edited

Legend:

Unmodified
Added
Removed
  • Dev/trunk/src/server/api/responses.js

    r527 r531  
    1313
    1414    var getResponsesBySurveyRunId = exports.getResponsesBySurveyRunId = function(surveyRunId) {
    15         var url = '_design/responses/_view/by_surveyrun?key='+JSON.stringify(surveyRunId);
    16         return couch.get(url)
     15        return couch.get('_design/responses/_view/by_surveyrun',
     16                         {query:{key:surveyRunId,reduce:false,include_docs:true}})
    1717        .handle({
    1818            '-1': _.identity,
    19             200: util.handleRowValues,
     19            200: util.handleRowDocs,
    2020            default: util.handleUnknownResponse
    2121        });
  • Dev/trunk/src/server/api/surveyRuns.js

    r527 r531  
    1515    app.get('/',
    1616        util.ensureMIME(util.JSON_MIME),
    17         util.makeDocsGet('SurveyRun'));
     17        function(req,res) {
     18            var qs = {reduce:false,include_docs:true};
     19            var now = new Date().toISOString();
     20            var hr;
     21            if ( 'current' in req.query ) {
     22                // we make the assumption that there will be fewer
     23                // runs with no or a future enddate than with a
     24                // startdate in the past, i.e. we assume fewer future
     25                // surveys are planned than past surveys are run.
     26                hr = couch.get('_design/surveyRuns/_view/by_end_date',{
     27                    query: {startkey:now,reduce:false,include_docs:true}
     28                }).handle({
     29                    '-1': _.identity,
     30                    200: function(result) {
     31                        return _.filter(
     32                            util.handleRowDocs(result),
     33                            function(doc){
     34                                return !doc.startDate ||
     35                                       doc.startDate <= now;
     36                            });
     37                    },
     38                    default: util.handleUnknownResponse
     39                });
     40            } else if ( 'future' in req.query ) {
     41                hr = couch.get('_design/surveyRuns/_view/by_start_date',{
     42                    query: {startkey:now,reduce:false,include_docs:true}
     43                }).handle({
     44                    '-1': _.identity,
     45                    200: util.handleRowDocs,
     46                    default: util.handleUnknownResponse
     47                });
     48            } else if ( 'past' in req.query ) {
     49                hr = couch.get('_design/surveyRuns/_view/by_end_date',{
     50                    query: {endkey:now,reduce:false,include_docs:true}
     51                }).handle({
     52                    '-1': _.identity,
     53                    200: util.handleRowDocs,
     54                    default: util.handleUnknownResponse
     55                });
     56            } else {
     57                hr = util.getDocumentsOfType('SurveyRun');
     58            }
     59            hr.handle({'-1': util.handleException})
     60            .handle(res.send.bind(res));
     61        });
    1862    app.post('/',
    1963        util.ensureMIME(util.JSON_MIME),
  • Dev/trunk/src/server/api/util.js

    r527 r531  
    8181
    8282    var getDocumentsOfType = exports.getDocumentsOfType = function(type) {
    83         var url = '_design/default/_view/by_type?key='+JSON.stringify(type);
    84         return couch.get(url)
     83        return couch.get('_design/default/_view/by_type',
     84                         {query:{reduce:false,include_docs:true,key:type}})
    8585        .handle({
    8686            '-1': _.identity,
    87             200: handleRowValues,
     87            200: handleRowDocs,
    8888            404: function() { return {error: "Cannot find collection of type "+type}; },
    8989            default: handleUnknownResponse
  • Dev/trunk/src/server/config/couchdb-design-docs.js

    r525 r531  
    3030        _id: "schemaInfo",
    3131        version: "4",
    32         viewsVersion: "1"
     32        viewsVersion: "2"
    3333    },
    3434
     
    4949            by_type: {
    5050                map: function(doc){
    51                     emit(doc.type, doc);
    52                 }
     51                    emit(doc.type, 1);
     52                },
     53                reduce: function(keys,values){ return sum(values); }
    5354            },
    5455            typeless: {
     
    104105                    emit(doc.topic||"(default)",1);
    105106                },
    106                 reduce: function(key, values, rereduce) { return sum(values); }
     107                reduce: function(key, values ) { return sum(values); }
    107108            },
    108109            all_variables: {
     
    137138                map: function(doc){
    138139                    if ( doc.type !== 'Question' ) { return; }
    139                     emit(doc.code,doc);
    140                 }
     140                    emit(doc.code,1);
     141                },
     142                reduce: function(key, values) { return sum(values); }
    141143            },
    142144            published_by_code: {
    143145                map: function(doc){
    144                     if ( doc.type !== 'Question' || !doc.publicationDate ) { return; }
    145                     emit(doc.code,doc);
    146                 }
     146                    if ( doc.type !== 'Question' ||
     147                         !doc.publicationDate ) { return; }
     148                    emit(doc.code,1);
     149                },
     150                reduce: function(key, values) { return sum(values); }
    147151            },
    148152            lib: {
     
    159163            drafts: {
    160164                map: function(doc){
    161                     if ( doc.type !== 'Survey' || doc.publicationDate ) { return; }
     165                    if ( doc.type !== 'Survey' ||
     166                         doc.publicationDate ) { return; }
    162167                    emit(doc._id,doc);
    163168                }
     
    165170            published: {
    166171                map: function(doc){
    167                     if ( doc.type !== 'Survey' || !doc.publicationDate ) { return; }
     172                    if ( doc.type !== 'Survey' ||
     173                         !doc.publicationDate ) { return; }
    168174                    emit(doc._id,doc);
    169175                }
     
    176182        language: "javascript",
    177183        views: {
    178             by_dates: {
     184            by_start_date: {
    179185                map: function(doc){
    180186                    if ( doc.type !== 'SurveyRun' ) { return; }
    181                     var startDate = doc.startDate || "";
    182                     var endDate = doc.endDate || {};
    183                     emit([startDate,endDate,doc.liveName||null],doc);
    184                 }
     187                    emit(doc.startDate||null,1);
     188                },
     189                reduce: function(keys,values){ return sum(values); }
     190            },
     191            by_end_date: {
     192                map: function(doc){
     193                    if ( doc.type !== 'SurveyRun' ) { return; }
     194                    emit(doc.endDate||{},1);
     195                },
     196                reduce: function(keys,values){ return sum(values); }
    185197            }
    186198        }
     
    194206                map: function(doc){
    195207                    if ( doc.type !== 'Response' ) { return; }
    196                     emit(doc.surveyRunId, doc);
    197                 }
     208                    emit(doc.surveyRunId, 1);
     209                },
     210                reduce: function(keys,values){ return sum(values); }
    198211            }
    199212        }
  • Dev/trunk/src/server/config/couchdb-schema.json

    r525 r531  
    1010  "definitions": {
    1111    "nonEmptyString": { "type": "string", "minLength": 1 },
    12     "codeString": { "type": "string", "pattern": "^[A-Za-z0-9]+$" },
    13     "subcodeString": { "type": "string", "pattern": "^[A-Za-z0-9]*$" },
     12    "code": { "type": "string", "pattern": "^[A-Za-z0-9]+$" },
     13    "subcode": { "type": "string", "pattern": "^[A-Za-z0-9]*$" },
     14    "datetime": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$"},
     15    "html5Email": {"type": "string", "pattern": "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"},
    1416    "schemaInfo": {
    1517      "type": "object",
     
    4042          "_rev": { "$ref": "#/definitions/nonEmptyString" },
    4143          "categories": { "type": "array", "items": { "$ref": "#/definitions/nonEmptyString" } },
    42           "code": { "$ref": "#/definitions/codeString" },
     44          "code": { "$ref": "#/definitions/code" },
    4345          "content": { "type": "array", "items": { "$ref": "#/definitions/content/any" } },
    4446          "description": { "$ref": "#/definitions/nonEmptyString" },
    45           "publicationDate": { "type": "string", "format": "datetime" },
     47          "publicationDate": { "$ref": "#/definitions/datetime" },
    4648          "title": { "$ref": "#/definitions/nonEmptyString" },
    4749          "topic": { "$ref": "#/definitions/nonEmptyString" }
     
    5759          "_rev": { "$ref": "#/definitions/nonEmptyString" },
    5860          "description": { "$ref": "#/definitions/nonEmptyString" },
    59           "publicationDate": { "type": "string", "format": "datetime" },
     61          "publicationDate": { "$ref": "#/definitions/datetime" },
    6062          "questions": { "type": "array", "items": { "$ref": "#/definitions/docs/Question" } },
    6163          "title": { "$ref": "#/definitions/nonEmptyString" }
     
    7173          "_rev": { "$ref": "#/definitions/nonEmptyString" },
    7274          "description": { "$ref": "#/definitions/nonEmptyString" },
    73           "endDate": { "type": "string", "format": "datetime" },
    74           "liveName": { "$ref": "#/definitions/nonEmptyString" },
     75          "endDate": { "$ref": "#/definitions/datetime" },
    7576          "mode": { "type": "string", "enum": [ "open", "closed" ] },
    7677          "respondentCanDeleteOwnResponse": { "type": "boolean" },
    7778          "secret": { "$ref": "#/definitions/nonEmptyString" },
    78           "startDate": { "type": "string", "format": "datetime" },
     79          "startDate": { "$ref": "#/definitions/datetime" },
    7980          "survey": { "$ref": "#/definitions/docs/Survey" },
    8081          "title": { "$ref": "#/definitions/nonEmptyString" }
     
    9697              "additionalProperties": false
    9798          },
    98           "email": { "type": "string", "format": "email" },
    99           "publicationDate": { "type": "string", "format": "datetime" },
     99          "publicationDate": { "$ref": "#/definitions/datetime" },
    100100          "secret": { "$ref": "#/definitions/nonEmptyString" },
    101101          "surveyRunId": { "$ref": "#/definitions/nonEmptyString" }
     
    149149        "properties": {
    150150          "type": { "type": "string", "pattern": "^StringInput$" },
    151           "subcode": { "$ref": "#/definitions/subcodeString" },
     151          "subcode": { "$ref": "#/definitions/subcode" },
    152152          "text": { "$ref": "#/definitions/nonEmptyString" }
    153153        },
     
    160160          "type": { "type": "string", "pattern": "^TextInput$" },
    161161          "maxLength": { "type": "integer" },
    162           "subcode": { "$ref": "#/definitions/subcodeString" },
     162          "subcode": { "$ref": "#/definitions/subcode" },
    163163          "text": { "$ref": "#/definitions/nonEmptyString" }
    164164        },
     
    173173          "max": { "type": "integer" },
    174174          "places": { "type": "integer" },
    175           "subcode": { "$ref": "#/definitions/subcodeString" },
     175          "subcode": { "$ref": "#/definitions/subcode" },
    176176          "text": { "$ref": "#/definitions/nonEmptyString" }
    177177        },
     
    193193              "minLabel": { "$ref": "#/definitions/nonEmptyString" },
    194194              "maxLabel": { "$ref": "#/definitions/nonEmptyString" },
    195               "subcode": { "$ref": "#/definitions/subcodeString" },
     195              "subcode": { "$ref": "#/definitions/subcode" },
    196196              "text": { "$ref": "#/definitions/nonEmptyString" }
    197197            },
     
    219219              "type": "object",
    220220              "properties": {
    221                   "subcode": { "$ref": "#/definitions/subcodeString" }
     221                  "subcode": { "$ref": "#/definitions/subcode" }
    222222              },
    223223              "required": ["subcode"],
    224224              "additionalProperties": false
    225225          },
    226           "subcode": { "$ref": "#/definitions/subcodeString" }
     226          "subcode": { "$ref": "#/definitions/subcode" }
    227227        },
    228228        "required":["type","items","subcode"],
     
    236236              "type": "object",
    237237              "properties": {
    238                 "subcode": { "$ref": "#/definitions/subcodeString" },
     238                "subcode": { "$ref": "#/definitions/subcode" },
    239239                "text": { "$ref": "#/definitions/nonEmptyString" }
    240240              },
     
    245245              "type": "object",
    246246              "properties": {
    247                 "subcode": { "$ref": "#/definitions/subcodeString" }
     247                "subcode": { "$ref": "#/definitions/subcode" }
    248248              },
    249249              "required": ["subcode"],
  • Dev/trunk/src/server/util/http-result.js

    r527 r531  
    6363                if ( status in fOrObj ) {
    6464                    return fOrObj[status](result);
     65                } else if ( status >= 200 && status < 300 &&
     66                            'success' in fOrObj ) {
     67                    return fOrObj.success(status,result);
     68                } else if ( !(status >= 200 && status < 300) &&
     69                            'failure' in fOrObj ) {
     70                    return fOrObj.failure(status,result);
    6571                } else if ( 'default' in fOrObj ) {
    6672                    return fOrObj['default'](status,result);
  • Dev/trunk/src/server/util/validator.js

    r493 r531  
    11var tv4 = require('tv4');
    2 
    3 // from: http://www.w3.org/TR/html5/forms.html#valid-e-mail-address
    4 var html5EmailRe = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
    5 var datetimeRe = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z/;
    6 
    7 tv4.addFormat({
    8     email: function(data){
    9         if ( typeof data === "string" && html5EmailRe.test(data) ) {
    10             return null;
    11         } else {
    12             return "Probably an invalid email address.";
    13         }
    14     },
    15     datetime: function(data){
    16         if ( typeof data === "string" && datetimeRe.test(data) ) {
    17             return null;
    18         } else {
    19             return "Invalid timestamp.";
    20         }
    21     }
    22 });
    232
    243module.exports = function() {
Note: See TracChangeset for help on using the changeset viewer.