Changeset 410


Ignore:
Timestamp:
09/07/12 16:59:14 (13 years ago)
Author:
hendrikvanantwerpen
Message:

Next steps to actually make taking surveys possible.

Split Controller in Router and Content. Updated the view.html to work
with the new app/Content mechanism. Include view page in build profile.

Rearranged Couch design documents per type. Changed config tool so the
docs.js can be more readable, functions don't have to be on one line
anymore but are serialized later. Because the .htaccess proxy is limited
to the rft database for security reasons, the config tool has to be run
on Node.js, to be able to access the Couch port (which is limited by
cross domain security in the browser).

Added elastic search to .htaccess proxy as well. Seperated CouchStore?
from rft/store, which contains application specific data.

Removed some old API files that were hanging around still.

Introduced preview mode for viewSurvey page. Changed survey page to
only show published questions to be included. The surveys page has
three categories: drafts, published and runs. Creating survey runs is
not yet implemented.

Location:
Dev/branches/rest-dojo-ui
Files:
5 added
4 deleted
28 edited
2 copied
2 moved

Legend:

Unmodified
Added
Removed
  • Dev/branches/rest-dojo-ui/build/debug.profile.js

    r408 r410  
    3737            'config/db' :{
    3838                include: [ 'config/db' ]
    39             }/*,
     39            },
    4040            'rft/view' :{
    4141                include: [ 'rft/view' ]
    42             }*/
     42            }
    4343        }
    4444    };
  • Dev/branches/rest-dojo-ui/build/release.profile.js

    r408 r410  
    5252            'config/db' :{
    5353                include: [ 'config/db' ]
    54             }/*,
     54            },
    5555            'rft/view' :{
    5656                include: [ 'rft/view' ]
    57             }*/
     57            }
    5858        }
    5959    };
  • Dev/branches/rest-dojo-ui/client/config/db.js

    r408 r410  
    1 require([
    2          'dojo/_base/json',
    3          'dojo/_base/lang',
    4          'dojo/_base/xhr',
    5          'dojo/parser',
    6          'dojo/query',
    7          'dijit/registry',
    8          'dojo/domReady!'
    9 ],function(json,lang,xhr,parser,query,registry){
    10     var logNode;
    11     var usernameInput, passwordInput, resetInput, configButton;
    12     var defaultUsername = "", defaultPassword = "";
    13     var dbUrl = "../data/";
     1define([
     2     'dojo/_base/json',
     3     'dojo/_base/lang',
     4     'dojo/Deferred',
     5     'dojo/request',
     6     'dojox/lang/functional',
     7     './docs'
     8],function(json,lang,Deferred,request,func,docs){
     9    var dbUrl = "http://localhost:5984/";
    1410
    15     parser.parse()
    16     .then(function(){
    17         query("#log").forEach(function(n){logNode = n;});
    18         usernameInput = registry.byId('username');
    19         passwordInput = registry.byId('password');
    20         resetInput = registry.byId('reset');
    21         configButton = registry.byId('configure');
    22 
    23         usernameInput.set('value',defaultUsername);
    24         passwordInput.set('value',defaultPassword);
    25         configButton.on('click',configure);
    26 
    27         log("Give CouchDB admin username & password and click 'Configure' to start.\nIf the database already exists, rft_admin password will suffice.",true);
    28     });
    29 
    30     function configure(){
    31         var docs;
    32 
    33         log("Configuring CouchDB for RFT:",true);
    34 
    35         var username = usernameInput.get('value');
    36         var password = passwordInput.get('value');
    37         var reset = resetInput.get('value');
    38 
    39         log("Downloading most recent configuration.");
    40         xhr('GET',{
    41             url: 'docs.json',
    42             handleAs: 'json',
    43             sync: true
    44         },true)
    45         .then(function(result){
    46             docs = result;
    47         });
    48 
    49         function req(method,url,body) {
    50             var args = {
    51                 url: dbUrl+url,
    52                 contentType: 'application/json',
    53                 handleAs: 'json',
    54                 sync: true
    55             };
    56             if ( !body || lang.isObject(body) ) {
    57                 body = json.toJson(body || {});
    58             }
    59             args.rawBody = body;
    60             if ( username ) {
    61                 args.user = username;
    62                 args.password = password;
    63             }
    64             return xhr(method,args,true);
     11    function serializeFunctions(value) {
     12        if ( value === null ) {
     13            return null;
     14        } else if ( lang.isArray(value) ) {
     15            return value;
     16        } else if ( lang.isFunction(value) ) {
     17            return value.toString();
     18        } else if ( lang.isObject(value) ) {
     19            return func.mapIn(value,serializeFunctions);
     20        } else {
     21            return value;
    6522        }
    66 
    67         log("Checking CouchDB version");
    68         req('GET','/')
    69         .then(function(res){
    70             if (res.version !== "1.2.0" ) {
    71                 log("Found "+res.version+", only tested with CouchDB 1.2.0")
    72             } else {
    73                 log("CouchDB 1.2.0 found")
    74             }
    75         });
    76 
    77         var exists = false;
    78         log("Checking database 'rft'");
    79         req('GET','/rft')
    80         .then(function(db){
    81             log("Database 'rft' found.")
    82             exists = true;
    83         });
    84         if ( exists && reset ) {
    85             req('DELETE','/rft');
    86             exists = false;
    87         }
    88         if ( !exists ) {
    89             log("Creating database 'rft'")
    90             req('PUT','/rft')
    91         };
    92 
    93         function processDoc(docUrl,doc){
    94             var configAction = doc.__configAction;
    95             delete doc.__configAction;
    96             switch (configAction) {
    97                 case "ignore":
    98                     log(docUrl+" ignored.");
    99                     return false;
    100                 case "update":
    101                     log(docUrl+" updating.");
    102                     return req('GET',docUrl)
    103                     .then(function(oldDoc){
    104                         lang.mixin(oldDoc,doc);
    105                         return req('PUT',docUrl,oldDoc);
    106                     },function(){
    107                         return req('PUT',docUrl,doc);
    108                     });
    109                 case "replace":
    110                 default:
    111                     log(docUrl+" replacing.");
    112                     return req('GET',docUrl)
    113                     .then(function(oldDoc){
    114                         doc['_rev'] = oldDoc['_rev'];
    115                         return req('PUT',docUrl,doc);
    116                     },function(){
    117                         return req('PUT',docUrl,doc);
    118                     });
    119             }
    120         }
    121 
    122         for (var docUrl in docs) {
    123             processDoc(docUrl,docs[docUrl]);
    124         }
    125 
    126         log("Done!");
    12723    }
    12824
    129     function log(text,overwrite) {
    130         if ( overwrite ) logNode.innerHTML = text
    131         else logNode.innerHTML = logNode.innerHTML + '\n' + text;
     25    function req(method,path,body) {
     26        var args = {
     27            contentType: 'application/json',
     28            handleAs: 'json',
     29            data: json.toJson(body || {})
     30        };
     31        return request[method](dbUrl+path,args);
    13232    }
    13333
     34    function asyncSeq(functions) {
     35        var d = new Deferred();
     36        (function stepper(fs,arg) {
     37            if ( fs.length > 0 ) {
     38                try {
     39                    var f = fs.shift();
     40                    var ret = f(arg);
     41                    if ( ret && ret.then ) {
     42                        ret.then(function(ret){
     43                            stepper(fs,ret);
     44                        });
     45                    } else {
     46                        stepper(fs,ret);
     47                    }
     48                } catch(err) {
     49                    d.reject(err);
     50                }
     51            } else {
     52                d.resolve();
     53            }
     54        })(functions);
     55        return d.promise;
     56    }
     57
     58    function asyncFor(list,callback,ctx) {
     59        var d = new Deferred();
     60        (function stepper(list,idx){
     61            if ( list.length > 0 ) {
     62                var el = list.shift();
     63                var ret = callback.call(ctx,el,idx);
     64                if ( ret && ret.then ) {
     65                    ret.then(function(){
     66                        stepper(list,idx+1);
     67                    });
     68                } else {
     69                    stepper(list,idx+1);
     70                }
     71            } else {
     72                d.resolve();
     73            }
     74        })(list,0);
     75        return d.promise;
     76    }
     77
     78    asyncSeq([
     79        function(){
     80            console.log("Configuring CouchDB for RFT:");
     81        },
     82        function(){
     83            console.log("Checking CouchDB version");
     84            return req('get','')
     85            .then(function(res){
     86                if (res.version !== "1.2.0" ) {
     87                    console.log("Found "+res.version+", only tested with CouchDB 1.2.0")
     88                } else {
     89                    console.log("CouchDB 1.2.0 found");
     90                }
     91            });
     92        },function(){
     93            console.log("Checking database 'rft'");
     94            return req('get','rft')
     95            .then(function(){
     96                console.log("Database 'rft' found.");
     97            },function(){
     98                console.log("Creating database 'rft'");
     99                return req('put','/rft');
     100            });
     101        },function(){
     102            return serializeFunctions(docs);
     103        },function(docs){
     104            console.log("Putting documents in database.");
     105            return asyncFor(func.keys(docs),function(docUrl){
     106                var doc = docs[docUrl];
     107                var configAction = doc.__configAction;
     108                delete doc.__configAction;
     109                switch (configAction) {
     110                    case "ignore":
     111                        console.log(docUrl+" ignored.");
     112                    case "update":
     113                        console.log(docUrl+" updating.");
     114                        return req('get',docUrl)
     115                        .then(function(oldDoc){
     116                            lang.mixin(oldDoc,doc);
     117                            return req('put',docUrl,oldDoc);
     118                        },function(){
     119                            return req('put',docUrl,doc);
     120                        });
     121                    case "replace":
     122                    default:
     123                        console.log(docUrl+" replacing.");
     124                        return req('get',docUrl)
     125                        .then(function(oldDoc){
     126                            doc['_rev'] = oldDoc['_rev'];
     127                            return req('put',docUrl,doc);
     128                        },function(){
     129                            return req('put',docUrl,doc);
     130                        });
     131                }
     132            });
     133        },function(){
     134            console.log("Done!");
     135        }
     136    ]);
     137
     138
    134139});
  • Dev/branches/rest-dojo-ui/client/config/docs.js

    r409 r410  
    1 {
    2     "_users/rft_admin": {
    3         "__configAction": "ignore",
    4         "_id": "org.couchdb.user:rft_admin",
    5         "name": "rft_admin",
    6         "password": "Welkom01",
    7         "roles": [ "rft_admin" ],
    8         "type": "user"
    9     },
    10     "rft/_security": {
    11         "__configAction": "ignore",
    12         "admins" : {
    13             "names" : [],
    14             "roles" : ["rft_admin"]
     1define([],function(){
     2    return {
     3        "_users/rft_admin": {
     4            __configAction: "ignore",
     5            _id: "org.couchdb.user:rft_admin",
     6            name: "rft_admin",
     7            password: "Welkom01",
     8            roles: [ "rft_admin" ],
     9            type: "user"
    1510        },
    16         "readers" : {
    17             "names" : [],
    18             "roles" : ["rft_user"]
    19         }
    20     },
    21     "rft/_design/default": {
    22         "__configAction": "replace",
    23         "_id": "_design/default",
    24         "language": "javascript",
    25         "validate_doc_update": "function(newDoc, oldDoc, userCtx, secObj) { if(oldDoc&&oldDoc.published){throw({forbidden:'Published documents cannot be modified.'});} if (!newDoc.type){throw({forbidden:'Documents must have a type field.'});} }",
    26         "views": {
    27             "by_type": {
    28                 "map": "function(doc){ emit(doc.type, doc); }"
     11        "rft/_security": {
     12            __configAction: "ignore",
     13            admins: {
     14                names: [],
     15                roles: ["rft_admin"]
    2916            },
    30             "unpublished": {
    31                 "map": "function(doc){ if ( doc.type === 'Survey' && !doc.published ) { emit(doc._id, doc); } }"
     17            readers: {
     18                names: [],
     19                roles: ["rft_user"]
     20            }
     21        },
     22        "rft/_design/default": {
     23            __configAction: "replace",
     24            _id: "_design/default",
     25            language: "javascript",
     26            validate_doc_update: function(newDoc, oldDoc, userCtx, secObj) {
     27                if ( oldDoc && oldDoc.publicationDate ) { throw({forbidden:'Published documents cannot be modified.'}); }
     28                if ( !newDoc._deleted && !newDoc.type ) { throw({forbidden:'Documents must have a type field.'}); }
    3229            },
    33             "questions": {
    34                 "map": "function(doc){ if ( doc.type === 'Question' ) { if ( doc.categories && doc.categories.length > 0 ) { for (var i = 0; i < doc.categories.length; i++) { emit([doc.categories[i],doc.topic || null],1); } } else { emit([null,null],1); } } }",
    35                 "reduce": "function(keys,values) { return sum(values); }"
     30            views: {
     31                by_type: {
     32                    map: function(doc){
     33                        emit(doc.type, doc);
     34                    }
     35                }
     36            }
     37        },
     38        "rft/_design/questions": {
     39            __configAction: "replace",
     40            _id: "_design/questions",
     41            language: "javascript",
     42            validate_doc_update: function(newDoc, oldDoc, userCtx, secObj) {
     43                if( newDoc._deleted || newDoc.type!=='Question' ){ return; }
     44                if( !newDoc.code ){ throw({forbidden:'Question must have a code field.'});}
    3645            },
    37             "topics": {
    38                 "map": "function(doc){ if ( doc.type === 'Question' ) { emit(doc.topic, 1); } }",
    39                 "reduce":   "function(keys, values) { return null; }"
     46            views: {
     47                all: {
     48                    map: function(doc){
     49                        if ( doc.type !== 'Question' ) { return; }
     50                        if ( doc.categories && doc.categories.length > 0 ) {
     51                            for ( var i = 0; i < doc.categories.length; i++ ) {
     52                                emit([doc.categories[i],doc.topic||null],1);
     53                            }
     54                        } else {
     55                            emit([null,null],1);
     56                        }
     57                    },
     58                    reduce: function(keys,values){ return sum(values); }
     59                },
     60                published: {
     61                    map: function(doc){
     62                        if ( doc.type!=='Question' || !doc.publicationDate ) { return; }
     63                        if ( doc.categories && doc.categories.length > 0 ) {
     64                            for ( var i = 0; i < doc.categories.length; i++ ) {
     65                                emit([doc.categories[i],doc.topic||null],1);
     66                            }
     67                        } else {
     68                            emit([null,null],1);
     69                        }
     70                    },
     71                    reduce: function(keys,values){ return sum(values); }
     72                },
     73                all_topics: {
     74                    map: function(doc){
     75                        if( doc.type !== 'Question' ){ return; }
     76                        emit(doc.topic);
     77                    }
     78                },
     79                published_topics: {
     80                    map: function(doc){
     81                        if ( doc.type !== 'Question' || !doc.publicationDate ) { return; }
     82                        emit(doc.topic);
     83                    }
     84                }
     85            }
     86        },
     87        "rft/_design/surveys": {
     88            __configAction: "replace",
     89            _id: "_design/surveys",
     90            language: "javascript",
     91            views: {
     92                drafts: {
     93                    map: function(doc){
     94                        if ( doc.type !== 'Survey' || doc.publicationDate ) { return; }
     95                        emit(doc._id,doc);
     96                    }
     97                },
     98                published: {
     99                    map: function(doc){
     100                        if ( doc.type !== 'Survey' || !doc.publicationDate ) { return; }
     101                        emit(doc._id,doc);
     102                    }
     103                }
    40104            }
    41105        }
    42     }
    43 }
     106    };
     107});
  • Dev/branches/rest-dojo-ui/client/data/.htaccess

    r352 r410  
    11RewriteEngine on
    2 RewriteRule (.*) http://localhost:5984/$1 [P,QSA]
     2RewriteRule couch/(.*) http://localhost:5984/rft/$1 [P,QSA]
     3RewriteRule elastic http://localhost:9200/rft/_search [P,QSA]
  • Dev/branches/rest-dojo-ui/client/index.html

    r407 r410  
    1515            </div>
    1616        </div>
    17         <div id="toaster" data-dojo-type="rft/ui/Notifications">
    18         </div>
     17        <div id="toaster" data-dojo-type="rft/ui/Notifications"></div>
    1918    </body>
    2019</html>
  • Dev/branches/rest-dojo-ui/client/rft/app/Router.js

    r407 r410  
    44    'dojo/io-query',
    55    'dojo/topic',
    6     './Page',
    7     'dijit/registry'
    8 ],function(declare,hash,ioQuery,topic,Page,registry){
     6    './Content',
     7    './Page'
     8],function(declare,hash,ioQuery,topic,Content,Page){
    99
    10 
    11     var Controller = declare(null,{
     10    var Router = declare(null,{
    1211        _started: false,
    1312        _routes: null,
    14         _container: null,
    1513        _previousHash: null,
    16         _previousContent: null,
    1714
    1815        _paramMatch: /:(\w[\w\d]*)/g,
    19         _paramReplace: "([^\\/]+)",
     16        _paramReplace: "([^\\/!]+)",
    2017
    2118        constructor: function() {
     
    2421        startup: function() {
    2522            if ( this._started ) { return; }
     23            if ( !Content._started ) {
     24                Content.startup();
     25            }
     26            this._started = true;
    2627
    2728            var self = this;
    28 
    29             this._container = registry.byId('content');
    30             if ( !this._container || !this._container.addChild ) {
    31                 throw new Error("Cannot find container widget with id 'content'.");
    32             }
    33             this._started = true;
    3429
    3530            if ( hash() === "" ) {
     
    4237        },
    4338        register: function(route) {
     39            if ( this._started ) {
     40                console.warn('Registering routes after startup() is called is discouraged.');
     41            }
    4442            var self = this;
    4543            var callback;
    4644            if ( route.callback ) {
    4745                callback = function(params){
    48                     self._setContent(route.callback(params));
     46                    Content.set(route.callback(params));
    4947                };
    5048            } else if ( route.redirect ) {
     
    5452            } else if ( route.constructor ) {
    5553                callback = function(params){
    56                     self._setContent( new route.constructor(params) );
     54                    Content.set( new route.constructor(params) );
    5755                };
    5856            }
     
    7573                        }
    7674            path = path.replace(this._paramMatch, this._paramReplace);
    77             route.regexp = new RegExp('^!'+path+'(!.*)?$');
     75            route.regexp = new RegExp('^!'+path+'(!(.*))?$');
    7876            return route;
    7977        },
     
    9492                    }
    9593
    96                     if ( result.length > numParams+1 ) {
    97                         params.options = ioQuery.queryToObject(result[numParams]);
     94                    if ( result.length > numParams+1 && result[numParams+2] ) {
     95                        params.options = ioQuery.queryToObject(result[numParams+2]);
    9896                    }
    9997
     
    126124            return hash;
    127125        },
    128         _setContent: function(widget) {
    129             if ( this._previousContent ) {
    130                 this._previousContent.destroyRecursive();
    131                 this._previousContent = null;
    132             }
    133             widget.region = 'center';
    134             this._container.addChild(widget);
    135             this._previousContent = widget;
    136         },
    137126        _defaultCallback: function() {
    138             this._setContent(new Page({
     127            Content.set(new Page({
    139128                templateString: "<div>Requested page not found. Go <a href=\"#!/\">home</a>.</div>"
    140129            }));
     
    142131    });
    143132
    144     return new Controller();
     133    return new Router();
    145134});
  • Dev/branches/rest-dojo-ui/client/rft/pages/index.js

    r407 r410  
    11define([
    22    'dojo/_base/declare',
    3     '../app/Controller',
     3    '../app/Router',
    44    '../app/Page',
    55    'dojo/text!./index.html'
    6 ],function(declare,Controller,Page,template){
     6],function(declare,Router,Page,template){
    77    return declare([Page],{
    88        templateString: template,
     
    1111            if ( this._started ) { return; }
    1212            this.inherited(arguments);
    13             this.btnContentCreate.on("click",function(){ Controller.go("/sessions"); });
    14             this.btnContentFacilitate.on("click",function(){ Controller.go("/run"); });
    15             this.btnSurveys.on("click",function(){ Controller.go("/surveys"); });
    16             this.btnQuestions.on("click",function(){ Controller.go("/questions"); });
    17             this.btnApplications.on("click",function(){ Controller.go("/applications"); });
    18             this.btnDashboards.on("click",function(){ Controller.go("/dashboards"); });
    19             this.btnResults.on("click",function(){ Controller.go("/results"); });
     13            this.btnContentCreate.on("click",function(){ Router.go("/sessions"); });
     14            this.btnContentFacilitate.on("click",function(){ Router.go("/run"); });
     15            this.btnSurveys.on("click",function(){ Router.go("/surveys"); });
     16            this.btnQuestions.on("click",function(){ Router.go("/questions"); });
     17            this.btnApplications.on("click",function(){ Router.go("/applications"); });
     18            this.btnDashboards.on("click",function(){ Router.go("/dashboards"); });
     19            this.btnResults.on("click",function(){ Router.go("/results"); });
    2020        }
    2121    });
  • Dev/branches/rest-dojo-ui/client/rft/pages/question.js

    r407 r410  
    55    'dojo/_base/lang',
    66    '../store',
    7     '../app/Controller',
     7    '../app/Content',
     8    '../app/Router',
    89    '../app/Page',
    910    '../ui/QuestionEditorPreview',
    1011    '../ui/QuestionEditorToolkit',
    1112    'dojo/text!./question.html'
    12 ],function(declare, Deferred, event, lang, store, Controller, Page, QuestionEditorPreview, QuestionEditorToolkit, template){
     13],function(declare, Deferred, event, lang, store, Content, Router, Page, QuestionEditorPreview, QuestionEditorToolkit, template){
    1314    return declare([Page], {
    1415        templateString: template,
     
    4344            store.put(this.question)
    4445            .then(function() {
    45                 Controller.go('/questions');
     46                Router.go('/questions');
     47            },function(err){
     48                Content.notify(err.reason,'error');
    4649            });
    4750            evt && event.stop( evt );
     
    4952        },
    5053        _onDiscard: function() {
    51             Controller.go('/questions');
     54            Router.go('/questions');
    5255            return true;
    5356        },
  • Dev/branches/rest-dojo-ui/client/rft/pages/questions.js

    r407 r410  
    44    'dojo/_base/event',
    55    'dojo/_base/lang',
    6     '../app/Controller',
    76    '../store',
     7    '../app/Content',
     8    '../app/Router',
    89    '../app/Page',
    910    '../ui/TabbedQuestionBrowser',
    1011    'dojo/text!./questions.html'
    11 ],function(declare,Deferred,event,lang,Controller,store,Page,TabbedQuestionBrowser,template) {
     12],function(declare,Deferred,event,lang,store,Content,Router,Page,TabbedQuestionBrowser,template) {
    1213    return declare([Page],{
    1314        templateString: template,
     
    1920                'class': 'blue',
    2021                itemActions: {
    21                     'Edit': {
     22                    Edit: {
    2223                        callback: lang.hitch(this,"onEditQuestion"),
    23                            icon: 'Edit',
    24                            description: 'Edit question'
     24                        icon: 'Edit',
     25                        description: 'Edit question'
     26                    },
     27                    Publish: {
     28                        callback: lang.hitch(this,"onPublishQuestion"),
     29                        icon: 'Publish',
     30                        description: 'Publish question'
    2531                    }
    2632                }
    2733            },this.questionBrowser);
    2834            this.questionBrowser.startup();
    29         },
    30         _refresh: function() {
    31             Deferred.when(store.query('_design/default/_view/by_type',{key: 'Question'}))
    32             .then(lang.hitch(this,function(items){
    33                 this._list.setItems(items);
    34             }));
    3535        },
    3636        onNewQuestion: function() {
     
    4141        },
    4242        onEditQuestion: function(question) {
    43             Controller.go("/question/"+question._id);
     43            Router.go("/question/"+question._id);
     44        },
     45        onPublishQuestion: function(question) {
     46            question.publicationDate = store.timestamp();
     47            store.put(question)
     48            .then(function(){
     49                Content.notify("Question puplished.");
     50            },function(err){
     51                Content.notify(err.reason,'error');
     52            });
    4453        }
    4554    });
  • Dev/branches/rest-dojo-ui/client/rft/pages/session.js

    r407 r410  
    22    'dojo/_base/array',
    33    'dojo/_base/declare',
     4    'dojo/_base/Deferred',
     5    'dojo/_base/event',
    46    'dojo/_base/lang',
    5     'dojo/_base/event',
    6     'dojo/_base/Deferred',
    7     '../app/Controller',
     7    '../search',
    88    '../store',
    9     '../elastic/ElasticSearchFilteringSelect',
    10     '../elastic/ElasticReadStore',
    119    '../app/Page',
     10    '../app/Router',
     11    '../ui/ThresholdFilteringSelect',
    1212    '../ui/lists/AccountListView',
    1313    'dojo/text!./session.html'
    14 ],function(array,declare,lang,event,Deferred,ElasticSearchFilteringSelect,ElasticReadStore,store,Page,Controller,AccountListView,template){
     14],function(array,declare,Deferred,event,lang,search,store,Page,Router,ThresholdFilteringSelect,AccountListView,template){
    1515    return declare([Page],{
    1616        templateString: template,
     
    4848            store.put(this.session)
    4949            .then(function(){
    50                 Controller.go('/sessions');
     50                Router.go('/sessions');
    5151            });
    5252            event.stop(evt);
     
    5656            this.propertiesForm.reset();
    5757            event.stop(evt);
    58             Controller.go('/sessions');
     58            Router.go('/sessions');
    5959            return false;
    6060        },
     
    7070        },
    7171        _setupAutoComplete: function() {
    72             var accountStore = new ElasticReadStore({
    73                 url: "http://localhost:9200/rft/_search",
    74                 requestMethod: "POST"
    75             });
    76             this._select = new ElasticSearchFilteringSelect({
    77                 store: accountStore,
     72            this._select = new ThresholdFilteringSelect({
     73                store: search,
    7874                autoComplete: false,
    7975                required: false,
  • Dev/branches/rest-dojo-ui/client/rft/pages/sessions.js

    r407 r410  
    44    'dojo/date/stamp',
    55    '../store',
    6     '../app/Controller',
     6    '../app/Router',
    77    '../app/Page',
    88    '../ui/ObjectBox',
    99    'dojo/text!./sessions.html'
    10 ],function(declare,lang,dateStamp,store,Controller,Page,ObjectBox,template){
     10],function(declare,lang,dateStamp,store,Router,Page,ObjectBox,template){
    1111    return declare([Page],{
    1212        templateString: template,
     
    1818            this.templateActions = {
    1919                "Edit": function(obj){
    20                     Controller.go('/session/'+store.getIdentity(obj));
     20                    Router.go('/session/'+store.getIdentity(obj));
    2121                },
    2222                "Delete": lang.hitch(this,function(obj){
     
    3030            this.sessionActions = {
    3131                "Facilitate": function(obj){
    32                     Controller.go('run',{uid:store.getIdentity(obj)});
     32                    Router.go('run',{uid:store.getIdentity(obj)});
    3333                },
    3434                "Delete": lang.hitch(this,function(obj){
     
    6262            })
    6363            .then(lang.hitch(this,function(obj){
    64                 Controller.go('/session/'+store.getIdentity(obj));
     64                Router.go('/session/'+store.getIdentity(obj));
    6565            }));
    6666        },
     
    7070            delete session[store.revProperty];
    7171            session.type = "SessionInstance";
    72             session.publishedDate = dateStamp.toISOString(new Date(),{zulu: true});
     72            session.publicationDate = store.timestamp();
    7373            session.creator = "Igor Mayer";
    7474            store.add(session)
  • Dev/branches/rest-dojo-ui/client/rft/pages/survey.js

    r407 r410  
    55    'dojo/_base/event',
    66    'dojo/_base/lang',
    7     '../app/Controller',
     7    '../app/Router',
    88    '../store',
    99    '../app/Page',
     
    1111    '../ui/TabbedQuestionBrowser',
    1212    'dojo/text!./survey.html'
    13 ],function(array,declare,Deferred,event,lang,Controller,store,Page,
     13],function(array,declare,Deferred,event,lang,Router,store,Page,
    1414         QuestionListView,TabbedQuestionBrowser,template){
    1515    return declare([Page],{
     
    2727                this._setupQuestionBrowser();
    2828                this._setupListView();
    29                 Deferred.when(store.get(this.surveyId))
    30                 .then(lang.hitch(this,function(obj){
    31                     this.survey = obj;
    32                     store.query(null,{keys:this.survey.questions,include_docs:true})
    33                     .forEach(lang.hitch(this.questionList,'appendItem'));
    34                     this.refresh();
    35                 }));
     29                this._setupSurvey();
    3630            } else {
    3731                throw "No valid uid or survey passed!";
     
    4236                region: 'center',
    4337                'class': 'blue',
     38                include: 'published',
    4439                selectedActions: {
    4540                    "Include": {
     
    5954            this.questionBrowser.startup();
    6055        },
    61         _includeQuestion: function(question) {
    62             this.questionList.insertItem(question);
    63         },
    6456        _setupListView: function() {
    6557            this.questionList = new QuestionListView({
     
    6759            },this.surveyListViewNode);
    6860            this.questionList.startup();
     61        },
     62        _setupSurvey: function() {
     63            Deferred.when(store.get(this.surveyId))
     64            .then(lang.hitch(this,function(survey){
     65                this.survey = survey;
     66                store.query(null,{keys:this.survey.questions || [], include_docs: true})
     67                .forEach(lang.hitch(this.questionList,'appendItem'));
     68                this.refresh();
     69            }));
     70        },
     71        _includeQuestion: function(question) {
     72            this.questionList.insertItem(question);
    6973        },
    7074        refresh: function() {
     
    9498            store.put(this.survey)
    9599            .then(function() {
    96                 Controller.go('/surveys');
     100                Router.go('/surveys');
    97101            });
    98102            event.stop(evt);
     
    100104        },
    101105        _onDiscard: function(evt) {
     106            Router.go('/surveys');
    102107        },
    103108        _onShowPreview: function() {
    104             Controller.go('/viewSurvey/'+store.getIdentity(this.survey));
     109            Router.go('/viewSurvey/'+store.getIdentity(this.survey),{
     110                preview: true
     111            });
    105112        }
    106113    });
  • Dev/branches/rest-dojo-ui/client/rft/pages/surveys.html

    r407 r410  
    11<div>
    2     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'">
    3         <button data-dojo-type="dijit/form/Button" class="blue" data-dojo-props="disabled: true, baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconEdit'" data-dojo-attach-point="btnEdit">Edit</button>
    4         <button data-dojo-type="dijit/form/Button" class="blue" data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconPlus'" data-dojo-attach-point="btnNew">New</button>
    5         <div data-dojo-type="dojox/grid/DataGrid" data-dojo-props="autoWidth:true,autoHeight:true,structure:[{name:'Title',field:'title'}]" data-dojo-attach-point="grid"></div>
     2
     3    <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
     4        <h2>
     5            <span class="rftIcon rftIconSurvey"></span>
     6            <span class="headerText">Surveys</span>
     7        </h2>
    68    </div>
     9
     10    <div data-dojo-attach-point="tabContainer" data-dojo-type="dijit/layout/TabContainer" class="blue" data-dojo-props="tabPosition:'left-h',region:'center'">
     11
     12        <div data-dojo-type="dijit/layout/BorderContainer" title="Drafts" data-dojo-attach-point="draftsTab">
     13            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'" data-dojo-attach-point="draftsContainer">
     14            </div>
     15            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'bottom'" style="height: 40px;">
     16                <button data-dojo-type="dijit/form/Button" class="blue" data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconNew'" data-dojo-attach-event="onClick:_onNewSurvey">New survey</button>
     17            </div>
     18        </div>
     19
     20        <div data-dojo-type="dijit/layout/BorderContainer" title="Published" data-dojo-attach-point="publishedTab">
     21            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'" data-dojo-attach-point="publishedContainer">
     22            </div>
     23            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'bottom'" style="height: 40px;">
     24            </div>
     25        </div>
     26
     27        <div data-dojo-type="dijit/layout/BorderContainer" title="Runs" data-dojo-attach-point="runsTab">
     28            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'center'" data-dojo-attach-point="runsContainer">
     29            </div>
     30            <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region: 'bottom'" style="height: 40px;">
     31            </div>
     32        </div>
     33    </div>
     34
    735</div>
  • Dev/branches/rest-dojo-ui/client/rft/pages/surveys.js

    r407 r410  
    11define([
     2    'dojo/_base/array',
    23    'dojo/_base/declare',
    34    'dojo/_base/lang',
    4     'dojo/_base/Deferred',
    5     'dojo/data/ObjectStore',
    6     '../auth',
     5    'dojo/when',
    76    '../store',
    8     '../app/Controller',
     7    '../app/Content',
    98    '../app/Page',
     9    '../app/Router',
     10    '../ui/LineWithActionsWidget',
    1011    'dojo/text!./surveys.html'
    11 ],function(declare,lang,Deferred,ObjectStore,auth,store,Controller,Page,template){
     12],function(array,declare,lang,when,store,Content,Page,Router,LineWithActionsWidget,template){
    1213    return declare([Page],{
    1314        templateString: template,
    14         selectedObject: null,
    1515        startup: function() {
    1616            if ( this._started ) { return; }
    1717            this.inherited(arguments);
    18             this.grid.setStore(
    19                 ObjectStore({objectStore: store}),
    20                 "_design/default/_view/by_type",{key:'Survey'});
    21            
    22             this.grid.on('rowclick',lang.hitch(this,function(evt){
    23                 this.selectedObject = evt.grid.getItem(evt.rowIndex);
    24                 this.btnEdit.set('disabled',!this.selectedObject);
     18            this.refresh();
     19        },
     20        _onNewSurvey: function(){
     21            when( store.add({type:'Survey'}) )
     22            .then(function(survey) {
     23                Router.go('/survey/'+store.getIdentity(survey));
     24            });
     25        },
     26        _onPublishSurvey:function(survey){
     27            var self = this;
     28            survey.publicationDate = store.timestamp();
     29            store.put(survey).then(function(){
     30                self.refreshDrafts();
     31                self.refreshPublished();
     32            },function(err){
     33                Content.notify(err.reason,'error');
     34            });
     35        },
     36        _onDeleteSurvey:function(survey){
     37            var self = this;
     38            store.remove(store.getIdentity(survey),store.getRevision(survey))
     39            .then(function(){
     40                self.refreshDrafts();
     41            },function(err){
     42                Content.notify(err.reason,'error');
     43            });
     44        },
     45        _onEditSurvey:function(survey){
     46            Router.go('/survey/'+store.getIdentity(survey));
     47        },
     48        _onPreviewSurvey:function(survey){
     49            Router.go('/viewSurvey/'+store.getIdentity(survey),{preview:true});
     50        },
     51        _onRunSurvey:function(survey){
     52
     53        },
     54        refresh: function() {
     55            this.refreshDrafts();
     56            this.refreshPublished();
     57            this.refreshRuns();
     58        },
     59        refreshDrafts: function() {
     60            this.draftsContainer.set('content','');
     61            when(store.query("_design/surveys/_view/drafts")
     62                    ,lang.hitch(this,function(surveys){
     63                this.draftsTab.set('title','Drafts ('+surveys.length+')');
     64                array.forEach(surveys,function(survey){
     65                    var w = new LineWithActionsWidget({
     66                        title: survey.title || '(unnamed)',
     67                        actions: [{
     68                            callback: lang.hitch(this,'_onPublishSurvey',survey),
     69                            properties: {
     70                                label: 'Publish',
     71                                tooltip: 'Publish survey',
     72                                icon: 'Publish'
     73                            }
     74                        },{
     75                            callback: lang.hitch(this,'_onPreviewSurvey',survey),
     76                            properties: {
     77                                label: 'Preview',
     78                                tooltip: 'Preview survey',
     79                                icon: 'Preview'
     80                            }
     81                        },{
     82                            callback: lang.hitch(this,'_onDeleteSurvey',survey),
     83                            properties: {
     84                                label: 'Delete',
     85                                tooltip: 'Delete survey',
     86                                icon: 'Delete'
     87                            }
     88                        },{
     89                            callback: lang.hitch(this,'_onEditSurvey',survey),
     90                            properties: {
     91                                label: 'Edit',
     92                                tooltip: 'Edit survey',
     93                                icon: 'Edit'
     94                            }
     95                        }]
     96                    });
     97                    this.draftsContainer.addChild(w);
     98                },this);
    2599            }));
    26 
    27             this.grid.on('rowdblclick',lang.hitch(this,function(evt){
    28                 var obj = evt.grid.getItem(evt.rowIndex);
    29                 Controller.go('/survey/'+store.getIdentity(obj));
     100        },
     101        refreshPublished: function() {
     102            this.publishedContainer.set('content','');
     103            when(store.query("_design/surveys/_view/published")
     104                    ,lang.hitch(this,function(surveys){
     105                this.publishedTab.set('title','Published ('+surveys.length+')');
     106                array.forEach(surveys,function(survey){
     107                    var w = new LineWithActionsWidget({
     108                        title: survey.title,
     109                        actions:[{
     110                            callback: lang.hitch(this,'_onPreviewSurvey',survey),
     111                            properties: {
     112                                label: 'Preview',
     113                                tooltip: 'Preview survey',
     114                                icon: 'Preview'
     115                            }
     116                        },{
     117                            callback: lang.hitch(this,'_onRunSurvey',survey),
     118                            properties: {
     119                                label: 'Run',
     120                                tooltip: 'Run survey',
     121                                icon: 'Run'
     122                            }
     123                        }]
     124                    });
     125                    this.publishedContainer.addChild(w);
     126                },this);
    30127            }));
    31            
    32             this.btnNew.on('click',lang.hitch(this,function(){
    33                 Deferred.when( store.add({type:'Survey',creator:auth.getUser()}) )
    34                 .then(function(obj) {
    35                     Controller.go('/survey/'+store.getIdentity(obj));
    36                 });
    37             }));
    38 
    39             this.btnEdit.on('click',lang.hitch(this,function(){
    40                 if ( this.selectedObject ) {
    41                     Controller.go('/survey/'+store.getIdentity(this.selectedObject));
    42                 }
    43                
     128        },
     129        refreshRuns: function() {
     130            this.runsContainer.set('content','');
     131            when(store.query("_design/default/_view/by_type",{key:'SurveyRun'})
     132                    ,lang.hitch(this,function(surveyRuns){
     133                this.runsTab.set('title','Runs ('+surveyRuns.length+')');
     134                array.forEach(surveyRuns,function(surveyRun){
     135                    var w = new LineWithActionsWidget({
     136                        title: survey.title,
     137                        actions:[{
     138                            callback: lang.hitch(this,'_onCloseRun',surveyRun),
     139                            properties: {
     140                                label: 'Close',
     141                                tooltip: 'Close survey',
     142                                icon: 'Close'
     143                            }
     144                        }]
     145                    });
     146                    this.runsContainer.addChild(w);
     147                },this);
    44148            }));
    45149        }
  • Dev/branches/rest-dojo-ui/client/rft/pages/viewSurvey.html

    r407 r410  
    1616    </div>
    1717   
    18     <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom'">
     18    <div data-dojo-attach-point="buttonsPane" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom'">
    1919        <button data-dojo-type="dijit/form/Button"
    2020                type="submit"
  • Dev/branches/rest-dojo-ui/client/rft/pages/viewSurvey.js

    r407 r410  
    1313        templateString: template,
    1414        survey: null,
     15        surveyId: "",
     16        options: null,
    1517        constructor: function(){
    1618            this._dataMap = {};
     19            this.options = this.options || {};
    1720        },
    1821        startup: function() {
    1922            if ( this._started ) { return; }
    2023            this.inherited(arguments);
     24
     25
    2126            if ( this.surveyId ) {
    2227                Deferred.when(store.get(this.surveyId))
    23                 .then(lang.hitch(this,function(obj){
     28                .then(lang.hitch(this,function(survey){
     29                    if ( !survey.published ) {
     30                        this.options.preview = true;
     31                    }
     32                    if ( this.options.preview ) {
     33                        this.buttonsPane.destroyRecursive();
     34                    }
     35                    this.titleNode.innerHTML = survey.title +
     36                            (this.options.preview?' [preview]':'');
    2437                    var f = new ContentWidgetFactory();
    25                     this.survey = obj;
     38                    this.survey = survey;
    2639                    store.query(null,{keys:this.survey.questions,include_docs:true})
    2740                    .forEach(function(question){
     
    3750                }));
    3851            } else {
    39                 throw "No valid uid or survey passed!";
     52                throw new Error("No valid uid or survey passed!");
    4053            }
    4154        },
    4255        _onSubmit: function(evt) {
     56            if ( this.options.preview ) { return; }
    4357            var value = this.questionsForm.get('value');
    4458            this.questionsPane.set('content','<pre>'+JSON.stringify(value)+'</pre>');
     
    4761        },
    4862        _onCancel: function(evt) {
     63            if ( this.options.preview ) { return; }
    4964            event.stop(evt);
    5065            return false;
  • Dev/branches/rest-dojo-ui/client/rft/run.js

    r407 r410  
    22    'dojo/_base/array',
    33    'dojo/parser',
    4     'rft/app/Controller',
     4    'rft/app/Router',
    55    'rft/routes',
    66    'rft/stddeps',
    77    'dojo/domReady!'
    8 ],function(array,parser,controller,routes) {
     8],function(array,parser,router,routes) {
    99    parser.parse();
    1010    array.forEach(routes,function(route){
    11         controller.register(route);
     11        router.register(route);
    1212    });
    13     controller.startup();
     13    router.startup();
    1414});
  • Dev/branches/rest-dojo-ui/client/rft/store.js

    r407 r410  
    11define([
    2     'dojo/_base/array',
    3     'dojo/_base/declare',
    4     'dojo/_base/Deferred',
    5     'dojo/_base/json',
    6     'dojo/_base/lang',
    7     'dojo/_base/xhr',
    8     'dojo/store/util/QueryResults'
    9 ],function(array,declare,Deferred,json,lang,xhr,QueryResults){
     2    'dojo/date/stamp',
     3    './store/CouchStore'
     4],function(stamp,CouchStore){
    105   
    11     var CouchStore = declare(null, {
    12         /** dojo Store implementation for CouchDB
    13          *
    14          * See for details on the REST API, the wiki
    15          * at http://wiki.apache.org/couchdb/HTTP_Document_API.
    16          */
    17         target: "",
    18         accepts: "application/json",
    19         idProperty: "_id",
    20         revProperty: "_rev",
    21         _responseIdProperty: "id",
    22         _responseRevProperty: "rev",
    23         constructor: function(options){
    24             declare.safeMixin(this, options);
    25         },
    26         getIdentity: function(object){
    27             return object[this.idProperty];
    28         },
    29         getRevision: function(object){
    30             return object[this.revProperty];
    31         },
    32         get: function(id){
    33             var dfd = new Deferred();
    34             xhr("GET", {
    35                 url: this.target + id,
    36                 handleAs: "json",
    37                 headers: {
    38                     Accept: this.accepts
    39                 }
    40             }).then(function(result){
    41                 if ( result.error ) {
    42                     dfd.reject(result.reason);
    43                 } else {
    44                     dfd.resolve(result);
    45                 }
    46             }, function(err){
    47                 dfd.reject(err);
    48             });
    49             return dfd.promise;
    50         },
    51         put: function(object, options){
    52              // summary:
    53              //     put an object in CouchDB
    54              // object: Object
    55              //     The object to put
    56              // options: Object
    57              //     Options object as
    58              //         id: String
    59              //
    60             options = options || {};
    61 
    62             var dfd = new Deferred();
    63             var id = options.id ? options.id : this.getIdentity(object);
    64             var hasId = typeof id != "undefined";
    65             xhr(hasId ? "PUT" : "POST", {
    66                 url: hasId ? this.target + id : this.target,
    67                 postData: json.toJson(object),
    68                 handleAs: "json",
    69                 headers:{
    70                     "Content-Type": "application/json",
    71                     Accept: this.accepts
    72                 }
    73             }).then(lang.hitch(this,function(result){
    74                 if ( result.error ) {
    75                     dfd.reject(result.reason);
    76                 } else {
    77                     object[this.idProperty] = result[this._responseIdProperty];
    78                     object[this.revProperty] = result[this._responseRevProperty];
    79                     dfd.resolve(object);
    80                 }
    81             }), function(err){
    82                 dfd.reject(err);
    83             });
    84             return dfd.promise;
    85         },
    86         add: function(object, options){
    87             return this.put(object,options);
    88         },
    89         remove: function(id,rev){
    90             var dfd = new Deferred();
    91             xhr("DELETE",{
    92                 url: this.target + id,
    93                 headers: {
    94                     'If-Match': rev
    95                 }
    96             }).then(function(result){
    97                 if ( result.error ) {
    98                     dfd.reject(result.reason);
    99                 } else {
    100                     dfd.resolve();
    101                 }
    102             },function(err){
    103                 dfd.reject(err);
    104             });
    105             return dfd.promise;
    106         },
    107         query: function(query, options){
    108             // summary:
    109             //    query a couchdb view
    110             // query: String
    111             //    name of a couchdb view you want to query, relative to the current database
    112             // options: Object
    113             //     options object as
    114             //        start: Number
    115             //            Start results at this item
    116             //        count: Number
    117             //            Number of items to return
    118             //        sort: [{attribute:'key',descending:true|false}]
    119             //            CouchDB only support sorting by key, so only 'key'
    120             //            is allowed as attribute value. Multiple sort items
    121             //            are ignored.
    122             //        key: String|Array|Object
    123             //            Return only values with this key.
    124             //            Excludes start/endkey usage.
    125             //        startkey: String|Array|Object
    126             //            Return values starting from this key.
    127             //        endkey: String|Array|Object
    128             //            Return values with key lower than this key.
    129             //        include_docs: true|false
    130             //            Return the full documents instead of the view
    131             //            values.
    132             //        reduce: true|false
    133             //            Execute reduce on the view or not. Default depends
    134             //            on if a reduce function is defined on the view.
    135             //        group: true|false
    136             //            Should values be grouped per key or not? Default
    137             //            is false.
    138             //        group_level: Number
    139             //            When group = true and the key is an array,
    140             //            determines which elements starting from the first
    141             //            are used for grouping. Default is 0.
    142             //        get_keys: true|false
    143             //            Instead of returning the values or documents,
    144             //            return the array of keys as the result.
    145             //            This does not affect the forPairs function.
    146             options = options || {};
    147 
    148             var dfd = new Deferred();
    149             var queryOpts = {};
    150             if ( !query ) {
    151                 query = '_all_docs';
    152             }
    153 
    154             if (!lang.isString(query)) {
    155                 console.warn("Query must be a view name");
    156             }
    157 
    158             // Standard options
    159             if (options.start >= 0) {
    160                 queryOpts.skip = options.start;
    161             }
    162             if (options.count >= 0) {
    163                 queryOpts.limit = options.count;
    164             }
    165             if (options.sort) {
    166                 if (options.sort[0]) {
    167                     if (options.sort[0].attribute && options.sort[0].attribute !== "key") {
    168                         console.warn("Can only sort on key");
    169                     }
    170                     if (options.sort[0].descending) {
    171                         queryOpts.descending = true;
    172                     }
    173                 }
    174                 if (options.sort.length > 1) {
    175                     console.warn("multiple sort fields not supported");
    176                 }
    177             }
    178 
    179             // Custom options
    180             if (options.key !== undefined) {
    181                 queryOpts.key = options.key;
    182             } else if (options.keys !== undefined) {
    183                 queryOpts.keys = options.keys;
    184             } else if (options.startkey !== undefined || options.endkey !== undefined) {
    185                 queryOpts.startkey = options.startkey;
    186                 queryOpts.endkey = options.endkey;
    187             }
    188             if (options.include_docs !== undefined) {
    189                 queryOpts.include_docs = options.include_docs;
    190             }
    191             if (options.reduce !== undefined) {
    192                 queryOpts.reduce = options.reduce;
    193             }
    194             if (options.group !== undefined) {
    195                 queryOpts.group = options.group;
    196                 if (options.group_level !== undefined) {
    197                     queryOpts.group_level = options.group_level;
    198                 }
    199             }
    200 
    201             for (var qp in queryOpts) {
    202                 queryOpts[qp] = json.toJson(queryOpts[qp]);
    203             }
    204             query += '?' + xhr.objectToQuery(queryOpts);
    205 
    206             xhr("GET", {
    207                 url: this.target + query,
    208                 handleAs: "json",
    209                 headers: {
    210                     Accept: this.accepts
    211                 }
    212             }).then(function(result){
    213                 if (result.error) {
    214                     dfd.reject(result.reason);
    215                 } else  {
    216                     var results;
    217                     var values = array.map(result.rows,function(result){
    218                         return options.include_docs === true ? result.doc : result.value;
    219                     });
    220                     var keys = array.map(result.rows,function(result){
    221                         return result.key;
    222                     });
    223                     if (options.get_keys === true) {
    224                         results = keys;
    225                         results.values = values;
    226                     } else {
    227                         results = values;
    228                         results.keys = keys;
    229                     }
    230                     dfd.resolve(results);
    231                 }
    232             },function(err){
    233                 dfd.reject(err);
    234             });
    235             return CouchResults(dfd.promise);
    236         }
    237     });
    238 
    239     function CouchResults(results) {
    240         results = QueryResults(results);
    241         results.forPairs = function(callback,thisObject) {
    242             callback = lang.hitch(thisObject,callback);
    243             return Deferred.when(results,function(results) {
    244                 var values = results.values || results;
    245                 var keys = results.keys || results;
    246                 return array.forEach(values, function(value,index) {
    247                     callback(value,keys[index],index);
    248                 });
    249             });
    250         };
    251         return results;
    252     }
    253 
    254     return new CouchStore({target: 'data/rft/'});
     6    var store = new CouchStore({target: 'data/couch/'});
     7    store.formatDate = function(date){
     8        return stamp.toISOString(date,{zulu:true});
     9    };
     10    store.parseDate = function(dateString){
     11        return stamp.fromISOString(dateString);
     12    };
     13    store.timestamp = function() {
     14        return this.formatDate(new Date());
     15    };
     16    return store;
    25517
    25618});
  • Dev/branches/rest-dojo-ui/client/rft/store/ElasticReadStore.js

    r407 r410  
    55    'dojo/_base/xhr',
    66    'dojox/data/QueryReadStore'
    7     ],function(declare, json, lang, xhr, QueryReadStore) {
    8 
     7],function(declare, json, lang, xhr, QueryReadStore) {
    98    return declare(QueryReadStore, {
    109        fetch:function(request){
    1110            var attr = Object.keys(request.query)[0];
    12             if (request.query[attr].length == 0) {
     11            if (request.query[attr].length === 0) {
    1312                return 0;
    1413            }
     
    5150        }
    5251    });
    53 })
     52});
  • Dev/branches/rest-dojo-ui/client/rft/ui/Breadcrumbs.js

    r407 r410  
    66    'dojo/topic',
    77    'dijit/_WidgetBase',
    8     '../app/Controller'
    9 ], function(declare, baseArray, Button, domClass, topic, _WidgetBase,Controller){
     8    '../app/Router'
     9], function(declare, baseArray, Button, domClass, topic, _WidgetBase,Router){
    1010    return declare([_WidgetBase], {
    1111        _crumbs: [],
     
    6161                iconClass: "dijitNoIcon",
    6262                onClick: lang.hitch(this, function(){
    63                     Controller.go(path);  // TODO: fix this call!
     63                    Router.go(path);  // TODO: fix this call!
    6464                })
    6565            });
  • Dev/branches/rest-dojo-ui/client/rft/ui/LoginDialog.js

    r408 r410  
    11define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/event','dijit/Dialog',
    22    'dijit/_WidgetsInTemplateMixin','../auth', 'dojo/text!./templates/LoginDialog.html',
    3     '../app/Controller','dijit/form/Form','dijit/form/Button','dijit/form/TextBox'],
     3    '../app/Router','dijit/form/Form','dijit/form/Button','dijit/form/TextBox'],
    44    function (declare, lang, event, Dialog, _WidgetsInTemplateMixin, auth, template, content) {
    55        return declare([Dialog,_WidgetsInTemplateMixin], {
  • Dev/branches/rest-dojo-ui/client/rft/ui/MenuBarLink.js

    r407 r410  
    1 define(['dojo/_base/declare','dijit/MenuBarItem','../app/Controller'],
    2 function(declare,MenuBarItem,Controller){
     1define(['dojo/_base/declare','dijit/MenuBarItem','../app/Router'],
     2function(declare,MenuBarItem,Router){
    33    return declare([MenuBarItem],{
    44        options:{
     
    66        },
    77        onClick: function(){
    8             this.path && Controller.go(this.path);
     8            this.path && Router.go(this.path);
    99        }
    1010    });
  • Dev/branches/rest-dojo-ui/client/rft/ui/MenuLink.js

    r407 r410  
    1 define(['dojo/_base/declare','dijit/MenuItem','../app/Controller'],
    2 function(declare,MenuItem,Controller){
     1define(['dojo/_base/declare','dijit/MenuItem','../app/Router'],
     2function(declare,MenuItem,Router){
    33    return declare([MenuItem],{
    44        options:{
     
    66        },
    77        onClick: function(){
    8             this.path && Controller.go(this.path);
     8            this.path && Router.go(this.path);
    99        }
    1010    });
  • Dev/branches/rest-dojo-ui/client/rft/ui/Notifications.js

    r407 r410  
    1 define(['dojo/_base/declare','dojo/_base/lang','dojo/_base/connect','dojox/widget/Toaster'],
    2     function(declare,lang,connect,Toaster){
    3         return declare([Toaster],{
    4             positionDirection: "br-up",
    5             duration: 1000,
    6             postCreate: function() {
    7                 this.inherited(arguments);
    8                 this.handle = connect.subscribe('/rft/notify',lang.hitch(this,function(notification){
    9                     this.setContent(notification.text,notification.type || 'message');
    10                 }));
    11             },
    12             destroy: function() {
    13                 connect.unsubscribe(this.handle);
    14                 this.inherited(arguments);
    15             }
    16         });
     1define(['dojo/_base/declare','dojo/_base/lang','dojox/widget/Toaster'],
     2function(declare,lang,Toaster){
     3    return declare([Toaster],{
     4        positionDirection: "br-up",
     5        duration: 1000
    176    });
     7});
  • Dev/branches/rest-dojo-ui/client/rft/ui/QuestionEditorToolkit.js

    r407 r410  
    129129            _setupCategories: function() {
    130130                this._categoryStore = new Memory({data: [] });
    131                 store.query("_design/default/_view/questions", {reduce:true, group:false, group_level:1})
     131                store.query("_design/questions/_view/all", {reduce:true, group:false, group_level:1})
    132132                .forPairs(lang.hitch(this, function(value, key) {
    133133                    this._categoryStore.put({ id: key[0] });
     
    143143            _setupTopic: function(topic) {
    144144                this._topicStore = new Memory( {data: [] });
    145                 store.query("_design/default/_view/topics", {reduce:true, group:true})
     145                store.query("_design/questions/_view/all_topics", {reduce:true, group:true})
    146146                .forPairs(lang.hitch(this, function(value, key) {
    147147                    this._topicStore.put({ id: key });
  • Dev/branches/rest-dojo-ui/client/rft/ui/Selector.js

    r407 r410  
    149149        },
    150150
    151         addItem: function(item) {
     151        addItem: function(item,displayTitle) {
    152152            var actions = {};
    153153            var action;
     
    156156                    action = this.itemActions[actionName];
    157157                    actions[actionName] = {
    158                         callback: function(){
    159                             action.callback && action.callback(item);
    160                         },
     158                        callback: action.callback && lang.partial(action.callback,item),
    161159                        properties: {
    162160                            blockButton: false,
     
    165163                            tooltip: action.description
    166164                        }
    167                     }
     165                    };
    168166                }
    169167            }
    170168            var w = new LineWithActionsWidget({
    171                 title: item.title,
     169                title: displayTitle || item.title,
    172170                actions: actions
    173171            }).placeAt(this.optionsNode);
  • Dev/branches/rest-dojo-ui/client/rft/ui/TabbedQuestionBrowser.js

    r407 r410  
    99    'rft/ui/Selector',
    1010    'dojo/domReady!'
    11     ],
    12     function(declare,lang,win,ContentPane,TabContainer,Standby,store,Selector){
    13         return declare([TabContainer],{
    14             tabPosition: 'left-h',
     11],function(declare,lang,win,ContentPane,TabContainer,Standby,store,Selector){
     12    return declare([TabContainer],{
     13        tabPosition: 'left-h',
     14        include: 'all',
    1515
    16             selectedActions: null,
    17             itemActions: null,
     16        selectedActions: null,
     17        itemActions: null,
    1818
    19             _dataMap: null,
    20             _busyCount: 0,
    21             constructor: function(){
    22                 this.inherited(arguments);
    23                 this._dataMap = {};
    24             },
    25             startup: function() {
    26                 if ( this._started ){ return; }
    27                 this.inherited(arguments);
    28                 this._busyWidget = new Standby({
    29                     target: this.domNode,
    30                     duration: 200
    31                 }).placeAt(win.body());
    32                 this._busyWidget.startup();
    33                 this.watch("selectedChildWidget",lang.hitch(this,function(name,oldTab,newTab){
    34                     this._fillCategoryTab(newTab.__category);
     19        _dataMap: null,
     20        _busyCount: 0,
     21        constructor: function(){
     22            this.inherited(arguments);
     23            this._dataMap = {};
     24        },
     25        postCreate: function() {
     26            this.inherited(arguments);
     27            this._query = '_design/questions/_view/'+this.include;
     28        },
     29        startup: function() {
     30            if ( this._started ){ return; }
     31            this.inherited(arguments);
     32            this._busyWidget = new Standby({
     33                target: this.domNode,
     34                duration: 200
     35            }).placeAt(win.body());
     36            this._busyWidget.startup();
     37            this.watch("selectedChildWidget",lang.hitch(this,function(name,oldTab,newTab){
     38                this._fillCategoryTab(newTab.__category);
     39            }));
     40            store.query(this._query, {reduce:true,group:true,group_level:1})
     41            .forPairs(lang.hitch(this,function(value,key){
     42                this._createCategoryTab(key[0],value);
     43            }));
     44        },
     45        _createCategoryTab: function(category,count) {
     46            if (this._dataMap[category] === undefined) {
     47                var categoryTab = new ContentPane({
     48                    __category: category,
     49                    title: (category || '[No category]')+" ("+count+")"
     50                });
     51                categoryTab.startup();
     52                this._dataMap[category] = {
     53                    _widget: categoryTab
     54                };
     55                this.addChild(categoryTab);
     56            }
     57        },
     58        _fillCategoryTab: function(category) {
     59            var categoryMap = this._dataMap[category];
     60            if (!categoryMap._filled) {
     61                this._busy();
     62                categoryMap._filled = true;
     63                store.query(this._query, {reduce:true,group:true,group_level:2,startkey:[category],endkey:[category,{}]})
     64                .forPairs(lang.hitch(this,function(value,key){
     65                    this._createTopicSelector(key[1],category,value);
     66                })).then(lang.hitch(this,function(){
     67                    this._done();
    3568                }));
    36                 store.query('_design/default/_view/questions', {reduce:true,group:true,group_level:1})
    37                 .forPairs(lang.hitch(this,function(value,key){
    38                     this._createCategoryTab(key[0],value);
     69            }
     70        },
     71        _createTopicSelector: function(topic,category,count){
     72            var categoryMap = this._dataMap[category];
     73            if (categoryMap[topic] === undefined) {
     74                var w = new Selector({
     75                    __category: category,
     76                    __topic: topic,
     77                    title: (topic || '[No topic]')+" ("+count+")",
     78                    selectedActions: this.selectedActions,
     79                    itemActions: this.itemActions
     80                }).placeAt(categoryMap._widget.containerNode);
     81                w.startup();
     82                categoryMap[topic] = {
     83                    _widget: w
     84                };
     85                this._fillTopicSelector(topic,category);
     86            }
     87        },
     88        _fillTopicSelector: function(topic,category) {
     89            var categoryMap = this._dataMap[category];
     90            var topicMap = categoryMap[topic];
     91            if (!topicMap._filled) {
     92                topicMap._filled = true;
     93                this._busy();
     94                store.query(this._query, {reduce:false,include_docs:true,key:[category,topic]})
     95                .forEach(lang.hitch(this,function(value){
     96                    var title;
     97                    if ( this.include === 'all' ) {
     98                        title = value.title+(value.publicationDate?' (published on '+value.publicationDate+')':' (unpublished)');
     99                    }
     100                    topicMap._widget.addItem(value,title);
     101                })).then(lang.hitch(this,function(){
     102                    this._done();
    39103                }));
    40             },
    41             _createCategoryTab: function(category,count) {
    42                 if (this._dataMap[category] === undefined) {
    43                     var categoryTab = new ContentPane({
    44                         __category: category,
    45                         title: (category || '[No category]')+" ("+count+")"
    46                     });
    47                     categoryTab.startup();
    48                     this._dataMap[category] = {
    49                         _widget: categoryTab
    50                     };
    51                     this.addChild(categoryTab);
     104            }
     105        },
     106        _busy: function() {
     107            if ( this._busyCount === 0 ) {
     108                this._busyWidget.show();
     109            }
     110            this._busyCount++;
     111        },
     112        _done: function() {
     113            if ( this._busyCount > 0 ) {
     114                this._busyCount--;
     115                if ( this._busyCount === 0 ) {
     116                    this._busyWidget.hide();
    52117                }
    53             },
    54             _fillCategoryTab: function(category) {
    55                 var categoryMap = this._dataMap[category];
    56                 if (!categoryMap._filled) {
    57                     this._busy();
    58                     categoryMap._filled = true;
    59                     store.query('_design/default/_view/questions', {reduce:true,group:true,group_level:2,startkey:[category],endkey:[category,{}]})
    60                     .forPairs(lang.hitch(this,function(value,key){
    61                         this._createTopicSelector(key[1],category,value);
    62                     })).then(lang.hitch(this,function(){
    63                         this._done();
    64                     }));
    65                 }
    66             },
    67             _createTopicSelector: function(topic,category,count){
    68                 var categoryMap = this._dataMap[category];
    69                 if (categoryMap[topic] === undefined) {
    70                     var w = new Selector({
    71                         __category: category,
    72                         __topic: topic,
    73                         title: (topic || '[No topic]')+" ("+count+")",
    74                         selectedActions: this.selectedActions,
    75                         itemActions: this.itemActions
    76                     }).placeAt(categoryMap._widget.containerNode);
    77                     w.startup();
    78                     categoryMap[topic] = {
    79                         _widget: w
    80                     };
    81                     this._fillTopicSelector(topic,category);
    82                 }
    83             },
    84             _fillTopicSelector: function(topic,category) {
    85                 var categoryMap = this._dataMap[category];
    86                 var topicMap = categoryMap[topic];
    87                 if (!topicMap._filled) {
    88                     topicMap._filled = true;
    89                     this._busy();
    90                     store.query('_design/default/_view/questions', {reduce:false,include_docs:true,key:[category,topic]})
    91                     .forEach(lang.hitch(this,function(value){
    92                         topicMap._widget.addItem(value);
    93                     })).then(lang.hitch(this,function(){
    94                         this._done();
    95                     }));
    96                 }
    97             },
    98             _busy: function() {
    99                 if ( this._busyCount === 0 ) {
    100                     this._busyWidget.show();
    101                 }
    102                 this._busyCount++;
    103             },
    104             _done: function() {
    105                 if ( this._busyCount > 0 ) {
    106                     this._busyCount--;
    107                     if ( this._busyCount === 0 ) {
    108                         this._busyWidget.hide();
    109                     }
    110                 } else {
    111                     console.warn('_done() was called more times than _busy().');
    112                 }
    113             },
    114             destroy: function() {
    115                 this._busyWidget.destroyRecursive();
    116                 this.inherited(arguments);
     118            } else {
     119                console.warn('_done() was called more times than _busy().');
    117120            }
    118         });
     121        },
     122        destroy: function() {
     123            this._busyWidget.destroyRecursive();
     124            this.inherited(arguments);
     125        }
    119126    });
     127});
  • Dev/branches/rest-dojo-ui/client/rft/ui/ThresholdFilteringSelect.js

    r407 r410  
    1616         }
    1717    });
    18 })
     18});
  • Dev/branches/rest-dojo-ui/client/rft/view.js

    r407 r410  
    11require([
     2    'dojo/hash',
    23    'dojo/parser',
    3     'rft/stddeps',
    4     'dojo/domReady!'
    5 ],function(parser) {
     4    'rft/app/Content',
     5    'rft/app/Page',
     6    'rft/pages/viewSurvey',
     7    'dojo/domReady!',
     8    'rft/stddeps'
     9],function(hash,parser,Content,Page,viewSurvey) {
    610    parser.parse();
     11    Content.startup();
     12
     13    var match = /^!\/(\w+)$/g.exec(hash());
     14    if ( !match ) {
     15        Content.set(new Page({
     16            templateString: "<div>Something is wrong with the URL, don't know what survey to show you. Sorry.</div>"
     17        }));
     18        return;
     19    }
     20    var surveyId = match[1];
     21
    722    // read options from hash/url
     23    //
    824    // authenticate
    9     // set content
    10     // go for it
     25
     26    Content.set(new viewSurvey({
     27        surveyId: surveyId
     28    }));
    1129});
  • Dev/branches/rest-dojo-ui/client/view.html

    r407 r410  
    99        <script type="text/javascript" src="dojo/dojo.js" data-dojo-config="async: true, parseOnLoad: false, isDebug: true"></script>
    1010        <script type="text/javascript" src="rft/view.js"></script>
    11         <div class="page" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region:'center'" style="width: 100%; height: 100%;">
     11        <div id="content" class="page" data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="region:'center'" style="width: 100%; height: 100%;">
    1212            <div class="topbar" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'">
    1313                <h1>Survey</h1>
    14             </div>
    15             <div id="content" class="content" data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'">
    1614            </div>
    1715        </div>
  • Dev/branches/rest-dojo-ui/docs/jsonformat.txt

    r384 r410  
    22========
    33{
    4     type: 'SessionTemplate',
    5     title: '',
    6     description: '',
    7     plannedDate: '', /* ISO UTC datetime */
     4    type: 'SessionTemplate'
     5    title: ''
     6    description: ''
     7    plannedDate: '' /* ISO UTC datetime */
    88    accounts: [ /* Account ids */ ]
    99}
    1010
    1111{
    12     type: 'SessionInstance',
    13     title: '',
    14     description: '',
    15     publishedDate: '', /* ISO UTC datetime */
     12    type: 'SessionInstance'
     13    title: ''
     14    description: ''
     15    publishedDate: '' /* ISO UTC datetime */
    1616    accounts: [ /* Account ids */ ]
    1717}
     
    2121{
    2222    type: 'Survey'
    23     title: '',
    24     description: '',
     23    title: ''
     24    description: ''
    2525    questions: [ /* Question ids */ ]
     26    publishedDate: ''
     27}
     28
     29{
     30    type: 'SurveyInstance'
     31    surveyId: '' // String
     32    publishedDate: '' // ISO datetime
     33    startDate: '' // can fill in after
     34    endDate: '' // can fill in until
    2635}
    2736
     
    3039{
    3140    type: 'Question'
    32     title: '',
    33     description: '',
    34     topic: '',
    35     categories: [],
     41    title: ''
     42    description: ''
     43    topic: ''
     44    categories: []
    3645    content: [{ type:'contentTypeId', /* custom content element fields */ } /* and more ... */]
    3746}
Note: See TracChangeset for help on using the changeset viewer.