- Timestamp:
- 06/23/13 13:59:15 (12 years ago)
- Location:
- Dev/trunk
- Files:
-
- 6 added
- 3 deleted
- 8 edited
- 3 moved
Legend:
- Unmodified
- Added
- Removed
-
Dev/trunk/Gruntfile.js
r462 r463 6 6 * can be distributed. 7 7 */ 8 var fs = require('fs');9 var path = require('path');10 8 11 9 module.exports = function(grunt) { 12 10 13 var buildDir = '../build/'; 14 var binDir = buildDir+'bin/'; 15 var distDir = '../dist/'; 11 var buildDir = 'build/'; 12 var srcDir = 'src/'; 16 13 17 14 grunt.initConfig({ 18 15 clean: { 19 16 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 }] 24 32 } 25 33 }, 26 34 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 }] 49 40 } 50 41 }, 51 42 dojo: { 52 43 options: { 53 dojo: 'client/dojo/dojo.js',44 dojo: srcDir+'client/dojo/dojo.js' 54 45 }, 55 46 build: { 56 47 options: { 57 profile: 'client/client.profile.js' 48 profile: srcDir+'client/client.profile.js', 49 releaseDir: buildDir 58 50 } 59 51 } … … 61 53 htmlhint: { 62 54 options: { 63 htmlhintrc: ".htmlhintrc"55 htmlhintrc: srcDir+".htmlhintrc" 64 56 }, 65 57 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 }] 69 63 } 70 64 }, 71 65 jshint: { 72 66 options: { 73 jshintrc: ".jshintrc"67 jshintrc: srcDir+".jshintrc" 74 68 }, 75 69 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 }] 79 75 } 80 76 }, … … 85 81 }, 86 82 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 }] 97 90 } 98 91 } … … 100 93 101 94 grunt.loadNpmTasks('grunt-contrib-clean'); 95 grunt.loadNpmTasks('grunt-contrib-coffee'); 102 96 grunt.loadNpmTasks('grunt-contrib-copy'); 103 97 grunt.loadNpmTasks('grunt-contrib-jshint'); … … 108 102 grunt.loadNpmTasks('grunt-zip'); 109 103 110 grunt.registerTask('compile', ['less:compile', 'jshint:compile', 'htmlhint:compile' ]);111 grunt.registerTask('build', ['clean:build', 'compile', 'dojo:build' , 'copy:build']);112 grunt.registerTask('d ist', ['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', []); 113 107 grunt.registerTask('default', ['compile']); 114 108 -
Dev/trunk/README.txt
r424 r463 8 8 - Install CouchDB 9 9 - 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 - 15 11 16 12 -
Dev/trunk/docs/TODO.md
r457 r463 1 T odo1 TODO 2 2 ==== 3 3 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?) 5 26 * Validate documents on the server before saving them. 6 27 * 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? 12 29 * 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. 23 48 24 49 Checklist -
Dev/trunk/src/client/client.profile.js
r453 r463 2 2 return { 3 3 basePath: '.', 4 releaseDir: '../../build',5 4 releaseName: 'client', 6 5 action: 'release', -
Dev/trunk/src/client/qed-client/index.js
r443 r463 1 1 define([ 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 13 18 parser.parse(); 14 15 19 store.info() 16 20 .then(function(){ -
Dev/trunk/src/client/qed-client/pages/surveyRun.js
r457 r463 72 72 var surveyRun = this.surveyRunWidget.get('value'); 73 73 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))); 75 76 } else { 76 this.runURLNode.innerHTML = "No general URL. Add individual respondents below."; 77 this.runURLNode.innerHTML = 78 "No general URL. Add individual respondents below."; 77 79 } 78 80 }, … … 102 104 }); 103 105 } 104 event.stop(evt);106 if ( evt ) { event.stop(evt); } 105 107 return false; 106 108 }, 107 109 _onDiscard: function(evt) { 108 110 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; 109 117 } 110 118 }); -
Dev/trunk/src/client/qed-client/pages/templates/response.html
r461 r463 1 1 <div class="blue"> 2 2 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'"> 4 5 <h2> 5 6 <span class="rftIcon rftIconSurvey"></span> … … 9 10 </div> 10 11 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> 13 17 </div> 14 18 15 19 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'"> 17 22 <button data-dojo-type="dijit/form/Button" 18 23 type="submit" -
Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html
r457 r463 1 1 <div class="blue"> 2 2 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'"> 4 5 <h2> 5 6 <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> 7 9 </h2> 8 10 </div> 9 11 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'"> 11 14 <fieldset class="qedFieldset"> 12 15 <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> 14 18 </fieldset> 15 19 <fieldset class="qedFieldset"> 16 20 <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> 18 23 </fieldset> 19 24 <fieldset class="qedFieldset"> 20 25 <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> 23 52 </fieldset> 24 53 </div> 25 54 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;"> 27 57 <button data-dojo-type="dijit/form/Button" 28 58 class="blue" -
Dev/trunk/src/client/qed-client/store/CouchStore.js
r461 r463 5 5 "dojo/_base/json", 6 6 "dojo/_base/lang", 7 "dojo/request ",7 "dojo/request/registry", 8 8 "dojo/store/util/QueryResults" 9 9 ], function(Deferred, array, declare, json, lang, request, QueryResults) { -
Dev/trunk/src/package.json
r458 r463 1 1 { 2 "name": "qed- full",2 "name": "qed-server", 3 3 "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" 16 11 }, 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" 21 15 } 22 16 } -
Dev/trunk/src/server/app.js
r462 r463 1 1 var express = require("express"); 2 var passport = require("passport"), 3 passportLocal = require("passport-local"); 2 4 var fs = require("fs"); 3 var https = require("https");4 var os = require("os");5 5 var path = require("path"); 6 6 var proxy = require("simple-http-proxy"); 7 7 var _ = require("underscore"); 8 8 9 function clientPath(relativePath) { 10 return path.resolve('../client/'+relativePath); 9 function 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 } 11 16 } 12 17 13 var httpsOptions = { 14 key: fs.readFileSync(path.resolve('../qed-server.key')), 15 cert: fs.readFileSync(path.resolve('../qed-server.pem')) 18 exports.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 16 67 }; 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.