Changeset 463 for Dev


Ignore:
Timestamp:
06/23/13 13:59:15 (12 years ago)
Author:
hendrikvanantwerpen
Message:

Working towards Heroku deployment, restructuring for that and to allow coffee builds.

Location:
Dev/trunk
Files:
6 added
3 deleted
8 edited
3 moved

Legend:

Unmodified
Added
Removed
  • Dev/trunk/Gruntfile.js

    r462 r463  
    66 * can be distributed.
    77 */
    8 var fs = require('fs');
    9 var path = require('path');
    108
    119module.exports = function(grunt) {
    1210
    13     var buildDir = '../build/';
    14     var binDir = buildDir+'bin/';
    15     var distDir = '../dist/';
     11    var buildDir = 'build/';
     12    var srcDir   = 'src/';
    1613
    1714    grunt.initConfig({
    1815        clean: {
    1916            build: {
    20                 options: {
    21                     force: true
    22                 },
    23                 src: [buildDir],
     17                src: [buildDir]
     18            }
     19        },
     20        coffee: {
     21            options: {
     22                bare: true
     23            },
     24            compile: {
     25                files: [{
     26                    expand: true,
     27                    cwd: srcDir,
     28                    src: ['client/qed-client/**/*.coffee', 'server/**/*.coffee'],
     29                    dest: buildDir,
     30                    ext: '.js'
     31                }]
    2432            }
    2533        },
    2634        copy: {
    27             build: {
    28                 files: [
    29                     {src: ['client/*.html'], dest: buildDir},
    30                     {src: ['server/**', '!**/node_modules/**'], dest: buildDir},
    31                     {src: ['qed-server.key', 'qed-server.pem'], dest: buildDir},
    32                 ]
    33             },
    34             dist: {
    35                 files: [
    36                     {src: ['client/bin/'], dest: binDir},
    37                     {src: ['server/**', '!**/node_modules/**'], dest: buildDir},
    38                     {src: ['qed-server.key', 'qed-server.pem'], dest: buildDir},
    39                 ]
    40             }
    41         },
    42         'curl-dir': {
    43             dist: {
    44                 src: [
    45                     'http://apache.xl-mirror.nl/couchdb/binary/win/1.3.0/setup-couchdb-1.3.0_R15B03-1.exe',
    46                     'http://nodejs.org/dist/v0.10.10/node-v0.10.10-x86.msi'
    47                 ],
    48                 dest: binDir
     35            compile: {
     36                files: [{
     37                    src: [srcDir+'**', '!**/*.coffee' ],
     38                    dest: buildDir
     39                }]
    4940            }
    5041        },
    5142        dojo: {
    5243            options: {
    53                 dojo: 'client/dojo/dojo.js',
     44                dojo: srcDir+'client/dojo/dojo.js'
    5445            },
    5546            build: {
    5647                options: {
    57                     profile: 'client/client.profile.js'
     48                    profile: srcDir+'client/client.profile.js',
     49                    releaseDir: buildDir
    5850                }
    5951            }
     
    6153        htmlhint: {
    6254            options: {
    63                 htmlhintrc: ".htmlhintrc"
     55                htmlhintrc: srcDir+".htmlhintrc"
    6456            },
    6557            compile: {
    66                 files: {
    67                     src: ['client/*.html', 'client/qed-client/**.html']
    68                 }
     58                files: [{
     59                    expand: true,
     60                    cwd: srcDir,
     61                    src: ['client/*.html', 'client/qed-client/**/*.html']
     62                }]
    6963            }
    7064        },
    7165        jshint: {
    7266            options: {
    73                 jshintrc: ".jshintrc"
     67                jshintrc: srcDir+".jshintrc"
    7468            },
    7569            compile: {
    76                 files: {
    77                     src: ['client/qed-client/**/*.js', 'server/**.js', '!**/node_modules/**']
    78                 }
     70                files: [{
     71                    expand: true,
     72                    cwd: srcDir,
     73                    src: ['client/qed-client/**/*.js', 'server/**.js']
     74                }]
    7975            }
    8076        },
     
    8581            },
    8682            compile: {
    87                 files: {
    88                     'client/qed-client/css/qed.css': 'client/qed-client/css/qed.less'
    89                 }
    90             }
    91         },
    92         zip: {
    93             dist: {
    94                 cwd: buildDir,
    95                 src: [buildDir+'**'],
    96                 dest: distDir+'qed-'+(new Date().toISOString())+'-x86.zip'
     83                files: [{
     84                    expand: true,
     85                    cwd: srcDir,
     86                    src: ['client/qed-client/css/qed.less'],
     87                    dest: buildDir,
     88                    ext: '.css'
     89                }]
    9790            }
    9891        }
     
    10093
    10194    grunt.loadNpmTasks('grunt-contrib-clean');
     95    grunt.loadNpmTasks('grunt-contrib-coffee');
    10296    grunt.loadNpmTasks('grunt-contrib-copy');
    10397    grunt.loadNpmTasks('grunt-contrib-jshint');
     
    108102    grunt.loadNpmTasks('grunt-zip');
    109103
    110     grunt.registerTask('compile', ['less:compile', 'jshint:compile', 'htmlhint:compile']);
    111     grunt.registerTask('build', ['clean:build', 'compile', 'dojo:build', 'copy:build']);
    112     grunt.registerTask('dist', ['build', 'copy:dist', 'curl-dir:dist', 'zip:dist']);
     104    grunt.registerTask('compile', ['less:compile', 'jshint:compile', 'htmlhint:compile', 'coffee:compile', 'copy:compile']);
     105    grunt.registerTask('build', ['clean:build', 'compile', 'dojo:build']);
     106    grunt.registerTask('deploy', []);
    113107    grunt.registerTask('default', ['compile']);
    114108
  • Dev/trunk/README.txt

    r424 r463  
    88- Install CouchDB
    99- Install Node.js
    10 - Install apache with rewrite,proxy and proxy_http modules enables
    11 - Run in console (cmd.exe):
    12   C:\>cd <qed-root>/server/couchdb-admin/
    13   C:\..\couchdb-admin\>run.bat config/config.js
    14 - Open http://localhost/.../qed/admin.html
     10-
    1511
    1612
  • Dev/trunk/docs/TODO.md

    r457 r463  
    1 Todo
     1TODO
    22====
    33
    4  * Check that question codes are unique.
     4 * Have a generic page-wide note (rounded corner, close button thingy)
     5   for notification (maybe completely replace the toaster?)
     6 * Response:
     7   - should we show response answers after submission?
     8   - idem after the run ended?
     9 * Questions
     10   - Question is always shown as 'no topic' when no category is added to it.
     11   - Fragile: widget creation relies on the names in Factory, but
     12     these must match the types returned by the actual widgets. Fix
     13     this.
     14 * Codes
     15   - Details need to be figured out. Now we have a code in one place,
     16     we add indices to disambiguate. Should we allow code editing all
     17     the way to the lowest detail? And should it be the complete code or
     18     just additions?
     19   - Check that question codes are unique in the database.
     20   - It might be good to show the codes in GUI, so they know at least
     21     which element will be called what
     22 * Validation
     23   - restore our json schema, there's probably several problems, it
     24     was disabled because the questions didn't pass anymore.
     25   - use it server side (and maybe client side as well?)
    526 * Validate documents on the server before saving them.
    627 * Implement authentication and later authorization.
    7  * Question is always shown as 'no topic' when no category is added to it.
    8  * Check that answers are saved correctly.
    9    Answers to multi-item questions (like scales) are stored in an object
    10    now with index as keys. This is not symmetrical with the fact that the
    11    configuration is an array.
     28   - Can we hook in request API so stores work correctly?
    1229 * Export answers for a survey run
    13  * Revive json schema checks for our data.
    14    Questions don't pass the schema at the moment.
    15  * Fragile: widget creation relies on the names in Factory, but these
    16    must match the types returned by the actual widgets. Fix this.
    17  * Write a spec for the codes.
    18  * Don't allow Save in Question unless all question items are done editing.
    19  * Use node as a server, adopt the layout described in
    20    http://dojotoolkit.org/documentation/tutorials/1.8/node/
    21    This will require quite a lot of moving and creating a rest interface
    22    -> can be just a proxy to CouchDB in he beginning.
     30   - Allow to include partial results, or just include submission date.
     31   - Include an URL to the dataset/run so it can easily be traced back.
     32   - Flatten object structure
     33 * Check if it works on tablets. We could consider special tablet UI
     34   later.
     35 * Sessions
     36   - modes: fixed, bulk, registration
     37   - off-line session:
     38     * provide a portal page where people can select available survey,
     39       maybe later see progress.
     40     * Allow for a registration round at the beginning (email, nick).
     41     * Show name clearly in portal, to prevent mistakes with the
     42       tablets.
     43     * Allow sessions based on subnet or a session code (A23X5Y).
     44     * Easy grouping of participants or selecting a subset for a
     45       survey.
     46     * On the server (localhost) show the ip(s) that people should
     47       connect to.
    2348
    2449Checklist
  • Dev/trunk/src/client/client.profile.js

    r453 r463  
    22    return {
    33        basePath: '.',
    4         releaseDir: '../../build',
    54        releaseName: 'client',
    65        action: 'release',
  • Dev/trunk/src/client/qed-client/index.js

    r443 r463  
    11define([
    2     'dojo/_base/array',
    3     'dojo/parser',
    4     './app/Content',
    5     './app/Page',
    6     './app/Router',
    7     './ui/MainMenu',
    8     './routes',
    9     './store',
    10     'dojo/domReady!',
    11     './stddeps'
    12 ],function(array,parser,Content,Page,Router,MainMenu,routes,store) {
     2    "./app/Content",
     3    "./app/Page",
     4    "./app/Router",
     5    "./routes",
     6    "./store",
     7    "./store/request",
     8    "./ui/MainMenu",
     9    "dojo/_base/array",
     10    "dojo/parser",
     11    "dojo/request/registry",
     12    "./stddeps",
     13    "dojo/domReady!"
     14], function(Content, Page, Router, routes, store, request, MainMenu, array, parser, registry) {
     15
     16    registry.register(/.*/,request);
     17   
    1318    parser.parse();
    14 
    1519    store.info()
    1620    .then(function(){
  • Dev/trunk/src/client/qed-client/pages/surveyRun.js

    r457 r463  
    7272            var surveyRun = this.surveyRunWidget.get('value');
    7373            if ( surveyRun.mode === "open" ) {
    74                 this.runURLNode.innerHTML = this._link(this._getGeneralURL(store.getIdentity(this.surveyRun)));
     74                this.runURLNode.innerHTML =
     75                    this._link(this._getGeneralURL(store.getIdentity(this.surveyRun)));
    7576            } else {
    76                 this.runURLNode.innerHTML = "No general URL. Add individual respondents below.";
     77                this.runURLNode.innerHTML =
     78                    "No general URL. Add individual respondents below.";
    7779            }
    7880        },
     
    102104                });
    103105            }
    104             event.stop(evt);
     106            if ( evt ) { event.stop(evt); }
    105107            return false;
    106108        },
    107109        _onDiscard: function(evt) {
    108110            Router.go('/surveys');
     111            if ( evt ) { event.stop(evt); }
     112            return false;
     113        },
     114        _onExport: function(evt) {
     115            if ( evt ) { event.stop(evt); }
     116            return false;
    109117        }
    110118    });
  • Dev/trunk/src/client/qed-client/pages/templates/response.html

    r461 r463  
    11<div class="blue">
    22
    3     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
     3    <div data-dojo-type="dijit/layout/ContentPane"
     4         data-dojo-props="region:'top'">
    45        <h2>
    56            <span class="rftIcon rftIconSurvey"></span>
     
    910    </div>
    1011   
    11     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" data-dojo-attach-point="content">
    12         <div name="answers" data-dojo-type="../model/widgets/SurveyRenderWidget" data-dojo-attach-point="surveyWidget"></div>
     12    <div data-dojo-type="dijit/layout/ContentPane"
     13         data-dojo-props="region:'center'" data-dojo-attach-point="content">
     14        <div name="answers"
     15             data-dojo-type="../model/widgets/SurveyRenderWidget"
     16             data-dojo-attach-point="surveyWidget"></div>
    1317    </div>
    1418   
    1519
    16     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom'">
     20    <div data-dojo-type="dijit/layout/ContentPane"
     21         data-dojo-props="region:'bottom'">
    1722        <button data-dojo-type="dijit/form/Button"
    1823                type="submit"
  • Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html

    r457 r463  
    11<div class="blue">
    22
    3     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
     3    <div data-dojo-type="dijit/layout/ContentPane"
     4         data-dojo-props="region:'top'">
    45        <h2>
    56            <span class="rftIcon rftIconSurvey"></span>
    6             <span class="headerText" data-dojo-attach-point="titleNode">SurveyRun Editor</span>
     7            <span class="headerText"
     8                  data-dojo-attach-point="titleNode">SurveyRun Editor</span>
    79        </h2>
    810    </div>
    911   
    10     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
     12    <div data-dojo-type="dijit/layout/ContentPane"
     13         data-dojo-props="region:'center'">
    1114        <fieldset class="qedFieldset">
    1215            <legend>Survey</legend>
    13             <div data-dojo-type="../model/widgets/SurveySummary" data-dojo-attach-point="surveySummaryWidget"></div>
     16            <div data-dojo-type="../model/widgets/SurveySummary"
     17                 data-dojo-attach-point="surveySummaryWidget"></div>
    1418        </fieldset>
    1519        <fieldset class="qedFieldset">
    1620            <legend>Run Details</legend>
    17             <div data-dojo-type="../model/widgets/SurveyRunWidget" data-dojo-attach-point="surveyRunWidget"></div>
     21            <div data-dojo-type="../model/widgets/SurveyRunWidget"
     22                 data-dojo-attach-point="surveyRunWidget"></div>
    1823        </fieldset>
    1924        <fieldset class="qedFieldset">
    2025            <legend>Response Details</legend>
    21             <div><div class="qedLabel">General URL</div><div class="qedField" data-dojo-attach-point="runURLNode" style="overflow: ellipsis"></div></div>
    22             <div><div class="qedLabel">Responses <span data-dojo-attach-point="responsesCountNode"></span></div><div class="qedField qedFill" data-dojo-attach-point="responsesNode"></div></div>
     26            <div>
     27                <div class="qedLabel">General URL</div>
     28                <div class="qedField"
     29                     data-dojo-attach-point="runURLNode"
     30                     style="overflow: ellipsis"></div>
     31            </div>
     32            <div>
     33                <div class="qedLabel">Response count</div>
     34                <div data-dojo-attach-point="responsesCountNode"></div>
     35            </div>
     36            <div>
     37                <div class="qedLabel">In progress count</div>
     38                <div data-dojo-attach-point="inprogressCountNode"></div>
     39            </div>
     40            <div>
     41                <div class="qedLabel">Responses (including partial)</div>
     42                <div class="qedField qedFill"
     43                     data-dojo-attach-point="responsesNode"></div>
     44            </div>
     45            <div>
     46                <div class="qedLabel">Export results</div>
     47                <button data-dojo-type="dijit/form/Button"
     48                        class="qedField blue"
     49                        data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
     50                        data-dojo-attach-event="onClick:_onExport">To CSV</button>
     51            </div>
    2352        </fieldset>
    2453    </div>
    2554   
    26     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'bottom'" style="height: 40px;">
     55    <div data-dojo-type="dijit/layout/ContentPane"
     56         data-dojo-props="region: 'bottom'" style="height: 40px;">
    2757        <button data-dojo-type="dijit/form/Button"
    2858                class="blue"
  • Dev/trunk/src/client/qed-client/store/CouchStore.js

    r461 r463  
    55    "dojo/_base/json",
    66    "dojo/_base/lang",
    7     "dojo/request",
     7    "dojo/request/registry",
    88    "dojo/store/util/QueryResults"
    99], function(Deferred, array, declare, json, lang, request, QueryResults) {
  • Dev/trunk/src/package.json

    r458 r463  
    11{
    2   "name": "qed-full",
     2  "name": "qed-server",
    33  "version": "0.0.1",
    4   "description": "QED Full",
    5   "devDependencies": {
    6     "grunt": "~0.4.0",
    7     "grunt-contrib-copy": "~0.4.1",
    8     "grunt-contrib-jshint": "~0.2.0",
    9     "grunt-contrib-less": "~0.5.0",
    10     "grunt-dojo": "~0.2.3",
    11     "grunt-exec": "~0.4.1",
    12     "grunt-htmlhint": "~0.4.0",
    13     "grunt-contrib-clean": "~0.4.1",
    14     "grunt-zip": "~0.9.0",
    15     "grunt-curl": "~1.1.0"
     4  "description": "QED Server",
     5  "dependencies": {
     6    "simple-http-proxy": "~0.5.2",
     7    "express": "~3.2.3",
     8    "underscore": "~1.4.4",
     9    "passport": "~0.1.17",
     10    "passport-local": "~0.1.6"
    1611  },
    17   "dependencies": {
    18     "underscore": "~1.4.4",
    19     "q": "~0.9.4",
    20     "q-io": "~1.7.0"
     12  "engines": {
     13    "node": "0.10.x",
     14    "npm": "1.2.x"
    2115  }
    2216}
  • Dev/trunk/src/server/app.js

    r462 r463  
    11var express = require("express");
     2var passport = require("passport"),
     3    passportLocal = require("passport-local");
    24var fs = require("fs");
    3 var https = require("https");
    4 var os = require("os");
    55var path = require("path");
    66var proxy = require("simple-http-proxy");
    77var _ = require("underscore");
    88
    9 function clientPath(relativePath) {
    10     return path.resolve('../client/'+relativePath);
     9function assertSetting(name, settings, validate) {
     10    if ( typeof settings[name] === 'undefined' ) {
     11        throw new Error("Required setting '"+name+"' undefined.");
     12    }
     13    if ( _.isFunction(validate) && !validate(settings[name]) ) {
     14        throw new Error("Setting '"+name+"' with value '"+settings[name]+"' is invalid.");
     15    }
    1116}
    1217
    13 var httpsOptions = {
    14     key: fs.readFileSync(path.resolve('../qed-server.key')),
    15     cert: fs.readFileSync(path.resolve('../qed-server.pem'))
     18exports.App = function(settings) {
     19
     20    assertSetting("couchDbURL", settings, _.isString);
     21   
     22    function clientPath(relativePath) {
     23        return path.resolve(__dirname+'/../client/'+relativePath);
     24    }
     25
     26    passport.use(new passportLocal.Strategy(function(username, password, done){
     27        if ( username === "igor" && password === "mayer" ) {
     28            done(null,{ username: "igor" });
     29        } else {
     30            done(null,false,{ message: 'Invalid credentials.' });
     31        }
     32    }));
     33
     34    var app = express();
     35    app.use(express.logger());
     36    app.use(express.compress());
     37    app.use(express.favicon());
     38
     39    app.use(express.cookieParser());
     40    app.use(express.bodyParser());
     41    app.use(express.session({ secret: "quasi experimental design" }));
     42
     43    // initialize passport
     44    app.use(passport.initialize());
     45    app.use(passport.session());
     46
     47    // static resources
     48    app.get('/', function(request, response){
     49        response.sendfile(clientPath('index.html'));
     50    });
     51    app.get('/*.html', function(request, response) {
     52        response.sendfile(clientPath(request.path));
     53    });
     54    _.each(['/dojo', '/dijit', '/dojox', '/qed', '/qed-client'], function(dir){
     55        app.use(dir, express.static(clientPath(dir)));
     56    });
     57
     58    // url to login (might work on others as well?)
     59    // you should then have a session to work with
     60    app.post('/api/login', passport.authenticate('local'));
     61
     62    // forward to couch
     63    app.use('/data/couch', passport.authenticate('local'), proxy(settings.couchDbURL));
     64
     65    return app;
     66
    1667};
    17 
    18 var app = express();
    19 app.use(express.logger());
    20 app.use(express.compress());
    21 app.use(express.favicon());
    22 app.get('/', function(request, response){
    23     response.sendfile(clientPath('index.html'));
    24 });
    25 app.get('/*.html', function(request, response) {
    26     response.sendfile(clientPath(request.path));
    27 });
    28 _.each(['/dojo', '/dijit', '/dojox', '/qed', '/qed-client'], function(dir){
    29     app.use(dir, express.static(clientPath(dir)));
    30 });
    31 app.use('/data/couch', proxy('http://localhost:5984/qed'));
    32 
    33 var server = https.createServer(httpsOptions, app);
    34 server.listen(8443);
    35 
    36 console.log(
    37     "Listening on " +
    38     _.chain(os.networkInterfaces())
    39      .map(function(value,key){ return value; })
    40      .flatten()
    41      .filter(function(intf){ return intf.family === "IPv4" && !intf.internal; })
    42      .reduce(function(urls, intf){ return urls+', http://'+intf.address+':8443/'; }, "http://127.0.0.1:8443/")
    43      .value() + ".");
Note: See TracChangeset for help on using the changeset viewer.