Changeset 495


Ignore:
Timestamp:
03/10/14 00:47:38 (11 years ago)
Author:
hendrikvanantwerpen
Message:
Location:
Dev/trunk/src
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • Dev/trunk/src/client/qed-client/model/widgets/TabbedQuestionBrowser.js

    r490 r495  
    11define([
    2     "../../widgets/Selector",
     2    "../../widgets/TabbedBrowser",
    33    "../classes/categories",
    44    "../classes/questions",
    55    "../classes/topics",
    6     "dijit/layout/ContentPane",
    7     "dijit/layout/TabContainer",
     6    "dojo/_base/array",
    87    "dojo/_base/declare",
    9     "dojo/_base/lang",
    10     "dojo/_base/window",
    11     "dojox/widget/Standby"
    12 ], function(Selector, categories, questions, topics, ContentPane, TabContainer, declare, lang, win, Standby) {
    13     return declare([TabContainer],{
     8    "dojo/_base/lang"
     9], function(TabbedBrowser, categories, questions, topics, array, declare, lang) {
     10    return declare([TabbedBrowser],{
    1411        tabPosition: 'left-h',
    15         include: 'all',
    16 
    17         selectedActions: null,
    18         itemActions: null,
     12        include: null,
    1913        dndType: "question",
    20 
    21         _dataMap: null,
    22         _busyCount: 0,
    23         constructor: function(){
    24             this.inherited(arguments);
    25             this._dataMap = {};
     14        getCategories: function(){
     15            return categories.query();
    2616        },
    27         startup: function() {
    28             if ( this._started ){ return; }
    29             this.inherited(arguments);
    30             this._busyWidget = new Standby({
    31                 target: this.domNode,
    32                 duration: 200
    33             }).placeAt(win.body());
    34             this._busyWidget.startup();
    35             this.watch("selectedChildWidget",lang.hitch(this,function(name,oldTab,newTab){
    36                 this._fillCategoryTab(newTab.__category);
    37             }));
    38             categories.query()
    39             .forEach(lang.hitch(this,function(cat){
    40                 this._createCategoryTab(cat.name,cat.count);
     17        getCategoryName: function(category){ return category.name; },
     18        getCategoryCount: function(category){ return category.count; },
     19        getTopics: function(category) {
     20            return topics.query({category:category.name});
     21        },
     22        getTopicName: function(topic){ return topic.name; },
     23        getTopicCount: function(topic){ return topic.count; },
     24        getItems: function(category,topic) {
     25            return questions.query({category:category.name,topic:topic.name})
     26            .then(lang.hitch(this,function(items){
     27                return array.filter(items, function(item){
     28                    return (this.include === 'published' && item.publicationDate) ||
     29                           (this.include === 'drafts' && !item.publicationDate) ||
     30                           true;
     31                }, this);
    4132            }));
    4233        },
    43         _createCategoryTab: function(category,count) {
    44             if (this._dataMap[category] === undefined) {
    45                 var categoryTab = new ContentPane({
    46                     __category: category,
    47                     title: (category || '[No category]')+" ("+count+")"
    48                 });
    49                 categoryTab.startup();
    50                 this._dataMap[category] = {
    51                     _widget: categoryTab
    52                 };
    53                 this.addChild(categoryTab);
    54             }
    55         },
    56         _fillCategoryTab: function(category) {
    57             var categoryMap = this._dataMap[category];
    58             if (!categoryMap._filled) {
    59                 this._busy();
    60                 categoryMap._filled = true;
    61                 topics.query({category:category})
    62                 .forEach(lang.hitch(this,function(topic){
    63                     this._createTopicSelector(topic.name,category,topic.count);
    64                 })).then(lang.hitch(this,function(){
    65                     this._done();
    66                 }));
    67             }
    68         },
    69         _createTopicSelector: function(topic,category,count){
    70             var categoryMap = this._dataMap[category];
    71             if (categoryMap[topic] === undefined) {
    72                 var w = new Selector({
    73                     __category: category,
    74                     __topic: topic,
    75                     dndType: this.dndType,
    76                     title: (topic || '[No topic]')+" ("+count+")",
    77                     selectedActions: this.selectedActions,
    78                     itemActions: this.itemActions,
    79                     itemTitle: this._itemTitle
    80                 }).placeAt(categoryMap._widget.containerNode);
    81                 w.startup();
    82                 categoryMap[topic] = {
    83                     _widget: w
    84                 };
    85                 this._fillTopicSelector(topic,category);
    86             }
    87         },
    88         _itemTitle: function(item) {
     34        getItemName: function(item) {
    8935            var title = '['+item.code+']'+item.title;
    90             if ( this.include === 'all' ) {
    91                 title += (item.publicationDate?' (published on '+item.publicationDate+')':' (unpublished)');
     36            if ( !this.include ) {
     37                title += (item.publicationDate ?' (published on '+item.publicationDate+')':' (unpublished)');
    9238            }
    9339            return title;
    9440        },
    95         _fillTopicSelector: function(topic,category) {
    96             var categoryMap = this._dataMap[category];
    97             var topicMap = categoryMap[topic];
    98             if (!topicMap._filled) {
    99                 topicMap._filled = true;
    100                 this._busy();
    101                 questions.query({category:category,topic:topic})
    102                 .forEach(lang.hitch(this,function(value){
    103                     topicMap._widget.addItem(value);
    104                 })).then(lang.hitch(this,function(){
    105                     this._done();
    106                 }));
    107             }
    108         },
    109         _busy: function() {
    110             if ( this._busyCount === 0 ) {
    111                 this._busyWidget.show();
    112             }
    113             this._busyCount++;
    114         },
    115         _done: function() {
    116             if ( this._busyCount > 0 ) {
    117                 this._busyCount--;
    118                 if ( this._busyCount === 0 ) {
    119                     this._busyWidget.hide();
    120                 }
    121             } else {
    122                 console.warn('_done() was called more times than _busy().');
    123             }
    124         },
    125         destroy: function() {
    126             this._busyWidget.destroyRecursive();
    127             this.inherited(arguments);
     41        areItemsEqual: function(i1,i2) {
     42            return questions.getId(i1) === questions.getId(i2);
    12843        }
    12944    });
  • Dev/trunk/src/client/qed-client/model/widgets/questions/MultipleChoiceInputWidget.js

    r462 r495  
    3535                return value;
    3636            } else {
    37                 return value.choice;
     37                return value.choice.length > 0;
    3838            }
    3939        },
     
    4343                inherited.call(this,value);
    4444            } else {
    45                 inherited.call(this,{choice:value});
     45                inherited.call(this,{choice:value ? ["on"] : []});
    4646            }
    4747        }
  • Dev/trunk/src/client/qed-client/pages/questions.js

    r490 r495  
    1919                'class': 'orange',
    2020                dndType: null,
    21                 itemActions: {
    22                     Delete: {
    23                         callback: lang.hitch(this,"onDeleteQuestion"),
    24                         icon: 'Delete',
    25                         description: 'Delete question'
    26                     },
    27                     Edit: {
    28                         callback: lang.hitch(this,"onEditQuestion"),
    29                         icon: 'Edit',
    30                         description: 'Edit question'
    31                     },
    32                     Publish: {
    33                         callback: lang.hitch(this,"onPublishQuestion"),
    34                         icon: 'Publish',
    35                         description: 'Publish question'
     21                getItemActions: lang.hitch(this,function(item) {
     22                    var actions = {
     23                        Edit: {
     24                            callback: lang.hitch(this,"onEditQuestion"),
     25                            icon: 'Edit',
     26                            description: 'Edit question'
     27                        }
     28                    };
     29                    if ( !item.publicationDate ) {
     30                        lang.mixin(actions,{
     31                            Delete: {
     32                                callback: lang.hitch(this,"onDeleteQuestion"),
     33                                icon: 'Delete',
     34                                description: 'Delete question'
     35                            },
     36                            Publish: {
     37                                callback: lang.hitch(this,"onPublishQuestion"),
     38                                icon: 'Publish',
     39                                description: 'Publish question'
     40                            }
     41                        });
    3642                    }
    37                 }
     43                    return actions;
     44                })
    3845            },this.questionBrowser);
    3946            this.questionBrowser.startup();
     
    4552            questions.remove(question)
    4653            .then(lang.hitch(this,function(){
     54                this.questionBrowser.removeItem(question);
    4755                this.notify("Question deleted.");
    4856            }),lang.hitch(this,function(err){
  • Dev/trunk/src/client/qed-client/pages/survey.js

    r494 r495  
    3131                'class': 'blue',
    3232                include: 'published',
    33                 selectedActions: {
    34                     "Include": {
    35                         callback: lang.hitch(this,this._includeQuestion),
    36                         icon: "Accept",
    37                         description: "Include in survey"
    38                     }
    39                 },
    40                 itemActions: {
    41                     "Info": {
    42                         callback: function(item){
    43                             if ( item.description ) { alert(item.description); }
    44                         },
    45                         icon: "Inspect",
    46                         description: "Show item description"
    47                     }
    48                 }
     33                getSelectedItemActions: lang.hitch(this,function() {
     34                    return {
     35                        "Include": {
     36                            callback: lang.hitch(this,this._includeQuestion),
     37                            icon: "Accept",
     38                            description: "Include in survey"
     39                        }
     40                    };
     41                }),
     42                getItemActions: lang.hitch(this,function(item) {
     43                    return {
     44                        "Info": {
     45                            callback: lang.hitch(this,function(item){
     46                                if ( item.description ) { alert(item.description); }
     47                            }),
     48                            icon: "Inspect",
     49                            description: "Show item description"
     50                        }
     51                    };
     52                })
    4953            },this.questionBrowser);
    5054            this.questionBrowser.startup();
  • Dev/trunk/src/client/qed-client/widgets/Selector.js

    r494 r495  
    6464            var actions = {};
    6565            var action = null;
    66             if ( this.selectedActions !== null ) {
    67                 for (var actionName in this.selectedActions) {
    68                     if ( this.selectedActions.hasOwnProperty(actionName) ) {
    69                         action = this.selectedActions[actionName];
     66            var userActions =
     67                    lang.isFunction(this.selectedActions) ?
     68                    this.selectedActions() :
     69                    this.selectedActions;
     70            if ( userActions ) {
     71                for (var actionName in userActions) {
     72                    if ( userActions.hasOwnProperty(actionName) ) {
     73                        action = userActions[actionName];
    7074                        actions[actionName] = {
    7175                            callback: action.callback &&
    72                                     lang.hitch(this,this._onSelectedAction,
    73                                             action.callback),
     76                                      lang.hitch(this,this._onSelectedAction,
     77                                                 action.callback),
    7478                            properties: {
    7579                                blockButton: true,
     
    135139        _onSelectedAction: function(callback) {
    136140            if (this._selectedItem && callback) {
    137                 callback(this._selectedItem);
     141                callback(this._selectedItem,this);
    138142            }
    139143        },
     
    171175            }
    172176        },
     177        removeItem: function(item) {
     178            var nodes = this._source ?
     179                        this._source.getAllNodes() :
     180                        this.optionsNode.childNodes;
     181            baseArray.forEach(nodes, function(node) {
     182                var widget = registry.byNode(node);
     183                if ( widget && this.itemEquals ?
     184                               this.itemEquals(widget.__item,item) :
     185                               widget.__item === item ) {
     186                    widget.destroyRecursive();
     187                    if ( this._source ) { this._source.delItem(widget.id); }
     188                }
     189            }, this);
     190        },
    173191        _createNode: function(item, hint) {
    174192            var node = hint === "avatar" ?
     
    188206        _createLineNode: function(item) {
    189207            var actions = {};
    190             var action;
    191             if (this.itemActions) {
    192                 for (var actionName in this.itemActions) {
    193                     if ( this.itemActions.hasOwnProperty(actionName) ) {
    194                         action = this.itemActions[actionName];
     208            var userActions =
     209                    lang.isFunction(this.itemActions) ?
     210                    this.itemActions(item) :
     211                    this.itemActions;
     212            if (userActions) {
     213                for (var actionName in userActions) {
     214                    if ( userActions.hasOwnProperty(actionName) ) {
     215                        var action = userActions[actionName];
    195216                        actions[actionName] = {
    196                             callback: action.callback && lang.partial(action.callback,item),
     217                            callback: action.callback &&
     218                                      lang.partial(action.callback,item,this),
    197219                            properties: {
    198220                                blockButton: false,
     
    207229            var w = new LineWithActionsWidget({
    208230                title: get(this.itemTitle,item),
    209                 actions: actions
     231                actions: actions,
     232                __item: item
    210233            });
    211234            w.startup();
     
    214237        },
    215238
    216         onSelect: function(/*item*/) {}
     239        onSelect: function(/*item*/) {},
     240
     241        destroy: function() {
     242            if ( this._source ) { this._source.destroy(); }
     243            this.inherited(arguments);
     244        }
    217245    });
    218246});
  • Dev/trunk/src/server/app.js

    r492 r495  
    148148
    149149    function identity(obj) { return obj; }
    150     function handleUnknownResponse(status,error){
     150    function handleUnknownResponse(status,error) {
    151151        return new HTTPResult(500,{error: error.reason});
    152152    }
     
    444444
    445445    // Categories and topics
     446    function getTopicsWithCategory(category) {
     447        var url = '_design/questions/_view/all';
     448        return HTTPResult.fromResponsePromise(couch.get(url,{query:{reduce:true,group:true,group_level:2,startkey:[category],endkey:[category,{}]}}).response,
     449                                       handleUnknownError)
     450        .handle({
     451            200: function(result) {
     452                return _.map(result.rows, function(item) { return { name:item.key[1], count:item.value }; });
     453            },
     454            default: handleUnknownResponse
     455        });
     456    }
    446457    app.get('/api/categories',
    447458        ensureAuthenticated,
     
    466477        function(req,res) {
    467478            var category = req.params.category;
    468             var url = '_design/questions/_view/all';
    469             HTTPResult.fromResponsePromise(couch.get(url,{query:{reduce:true,group:true,group_level:2,startkey:[category],endkey:[category,{}]}}).response,
    470                                            handleUnknownError)
    471             .handle({
    472                 200: function(result) {
    473                     return _.map(result.rows, function(item) { return { name:item.key[1], count:item.value }; });
    474                 },
    475                 default: handleUnknownResponse
    476             })
     479            getTopicsWithCategory(category)
    477480            .handle(res.send.bind(res));
    478481        });
     
    482485        function(req,res) {
    483486            var url = '_design/questions/_view/all_topics';
    484             HTTPResult.fromResponsePromise(couch.get(url,{query:{reduce:true,group:true}}).response,
    485                                            handleUnknownError)
    486             .handle({
    487                 200: function(result) {
    488                     return _.map(result.rows, function(item) { return {name:item.key, count:item.value}; });
    489                 },
    490                 default: handleUnknownResponse
    491             })
    492             .handle(res.send.bind(res));
     487            var hr;
     488            if ( 'category' in req.query ) {
     489                hr = getTopicsWithCategory(req.query.category);
     490            } else {
     491                hr = HTTPResult.fromResponsePromise(couch.get(url,{query:{reduce:true,group:true}}).response,
     492                                                    handleUnknownError)
     493                .handle({
     494                    200: function(result) {
     495                        return _.map(result.rows, function(item) { return {name:item.key, count:item.value}; });
     496                    },
     497                    default: handleUnknownResponse
     498                });
     499            }
     500            hr.handle(res.send.bind(res));
    493501        });
    494502
Note: See TracChangeset for help on using the changeset viewer.