Changeset 492 for Dev


Ignore:
Timestamp:
03/09/14 14:23:42 (11 years ago)
Author:
hendrikvanantwerpen
Message:
  • Enable/disable buttons on content change.
  • One place to do date formatting, because it was going wrong again.
  • Serialize questions in survey properly.
  • _ComplexValueMixin consumes submit events, but does trigger outer forms if present.
  • Trigger dialog show/hide for login only after previous effect is finished.
  • Check that documents are actually valid, not just that validator returned a result.
  • Validate email and timestamp formats.
  • Prepared for live runs.
Location:
Dev/trunk/src
Files:
1 added
33 edited

Legend:

Unmodified
Added
Removed
  • Dev/trunk/src/client/qed-client/app/Notifications.js

    r443 r492  
    33    return declare([Toaster],{
    44        positionDirection: "br-up",
    5         duration: 3000
     5        duration: 7000
    66    });
    77});
  • Dev/trunk/src/client/qed-client/app/Page.js

    r491 r492  
    1616        notify: lang.hitch(Content,'notify'),
    1717        markDirty: lang.hitch(Content,'markDirty'),
    18         markClean: lang.hitch(Content,'markClean')
     18        markClean: lang.hitch(Content,'markClean'),
     19        isDirty: lang.hitch(Content,'isDirty')
    1920    });
    2021    return Page;
  • Dev/trunk/src/client/qed-client/css/variables.less

    r443 r492  
    66@headers: #999999;
    77@text: #ffffff;
     8@disabledtext: #777777;
    89
    910// Colours
  • Dev/trunk/src/client/qed-client/css/widgets/BlockButton.less

    r443 r492  
    55    height: @button_block_height;
    66    vertical-align: top;
     7    color: @text;
     8
     9    &.dijitDisabled {
     10        color: @disabledtext;
     11    }
    712
    813    .dijitButtonContents {
     
    1823        padding: 0 @std_offset;
    1924        border: none;
    20         color: @text;
    2125        font-size: @button_block_font_size;
    2226
  • Dev/trunk/src/client/qed-client/css/widgets/InlineButton.less

    r443 r492  
    33    height: @button_inline_height;
    44    width: @button_inline_height;
     5    color: @text;
     6
     7    &.dijitDisabled {
     8        color: @disabledtext;
     9    }
    510
    611    .dijitButtonNode {
  • Dev/trunk/src/client/qed-client/css/widgets/LargeButton.less

    r443 r492  
    77        height: @button_large_height;
    88        padding: 3px;
     9        color: @text;
    910
    1011        &*, * {
     
    1516        }
    1617
     18        &.dijitDisabled {
     19            color: @disabledtext;
     20        }
     21
    1722        .dijitButtonNode {
    1823
     
    2126            height: @button_large_height;
    2227            background: transparent;
    23             color: @headers;
    2428            font-size: @button_large_font_size;
    2529            .transition(0.3s);
  • Dev/trunk/src/client/qed-client/model/classes/_Class.js

    r490 r492  
    22    "./_View",
    33    "dojo/_base/declare",
    4     "dojo/_base/lang"
    5 ], function(_View, declare, lang) {
     4    "dojo/_base/lang",
     5    "dojo/date/stamp"
     6], function(_View, declare, lang, stamp) {
    67
    78    var _Class = declare([_View],{
     
    5657                                             idOrObj :
    5758                                             this.getId(idOrObj));
     59        },
     60        _formatDate: function(date) {
     61            return stamp.toISOString(date,{zulu:true,milliseconds:false});
    5862        }
    5963    });
  • Dev/trunk/src/client/qed-client/model/classes/_View.js

    r490 r492  
    55    "dojo/_base/json",
    66    "dojo/_base/lang",
     7    "dojo/date/stamp",
    78    "dojo/store/util/QueryResults"
    8 ], function(JsonRest, Deferred, declare, json, lang, queryResults) {
     9], function(JsonRest, Deferred, declare, json, lang, stamp, queryResults) {
    910
    1011    var _View = declare([],{
     
    3839        getCollectionPath: function() {
    3940            return '/'+this._collection;
     41        },
     42        _parseDate: function(str) {
     43            return stamp.fromISOString(str);
    4044        }
    4145    });
  • Dev/trunk/src/client/qed-client/model/classes/questions.js

    r487 r492  
    11define([
    22    "./_Class",
    3     "dojo/_base/declare",
    4     "dojo/date/stamp"
    5 ], function(_Class, declare, stamp) {
     3    "dojo/_base/declare"
     4], function(_Class, declare) {
    65
    76    var Questions = declare([_Class],{
     
    2019        _deserialize: function(obj) {
    2120            if (obj.publicationDate) {
    22                 obj.publicationDate = stamp.fromISOString(obj.publicationDate);
     21                obj.publicationDate = this._parseDate(obj.publicationDate);
    2322            }
    2423        },
    2524        _serialize: function(obj) {
    2625            if (obj.publicationDate) {
    27                 obj.publicationDate = stamp.toISOString(obj.publicationDate);
     26                obj.publicationDate = this._formatDate(obj.publicationDate);
    2827            }
    2928        }
  • Dev/trunk/src/client/qed-client/model/classes/responses.js

    r490 r492  
    66    "dojo/_base/json",
    77    "dojo/_base/lang",
    8     "dojo/_base/xhr",
    9     "dojo/date/stamp"
    10 ], function(_Class, surveyRuns, Deferred, declare, json, lang, xhr, stamp) {
     8    "dojo/_base/xhr"
     9], function(_Class, surveyRuns, Deferred, declare, json, lang, xhr) {
    1110
    1211    var Responses = declare([_Class],{
     
    2625            }
    2726            if (obj.publicationDate) {
    28                 obj.publicationDate = stamp.fromISOString(obj.publicationDate);
     27                obj.publicationDate = this._parseDate(obj.publicationDate);
    2928            }
    3029        },
     
    3433            }
    3534            if (obj.publicationDate) {
    36                 obj.publicationDate = stamp.toISOString(obj.publicationDate);
     35                obj.publicationDate = this._formatDate(obj.publicationDate);
    3736            }
    3837        },
  • Dev/trunk/src/client/qed-client/model/classes/surveyRuns.js

    r487 r492  
    22    "./_Class",
    33    "./surveys",
    4     "dojo/_base/declare",
    5     "dojo/date/stamp"
    6 ], function(_Class, surveys, declare, stamp) {
     4    "dojo/_base/declare"
     5], function(_Class, surveys, declare) {
    76
    87    var SurveyRuns = declare([_Class],{
     
    2120        _deserialize: function(obj) {
    2221            if (obj.endDate) {
    23                 obj.endDate = stamp.fromISOString(obj.endDate);
     22                obj.endDate = this._parseDate(obj.endDate);
    2423            }
    2524            if (obj.startDate) {
    26                 obj.startDate = stamp.fromISOString(obj.startDate);
     25                obj.startDate = this._parseDate(obj.startDate);
    2726            }
    2827            if (obj.survey) {
     
    3231        _serialize: function(obj) {
    3332            if (obj.endDate) {
    34                 obj.endDate = stamp.toISOString(obj.endDate);
     33                obj.endDate = this._formatDate(obj.endDate);
    3534            }
    3635            if (obj.startDate) {
    37                 obj.startDate = stamp.toISOString(obj.startDate);
     36                obj.startDate = this._formatDate(obj.startDate);
    3837            }
    3938            if (obj.survey) {
  • Dev/trunk/src/client/qed-client/model/classes/surveys.js

    r490 r492  
    11define([
    22    "./_Class",
     3    "./questions",
     4    "dojo/_base/array",
    35    "dojo/_base/declare",
    4     "dojo/date/stamp",
    5     "dojo/store/JsonRest"
    6 ], function(_Class, declare, stamp, JsonRest) {
     6    "dojo/_base/lang"
     7], function(_Class, questions, array, declare, lang) {
    78
    89    var Surveys = declare([_Class],{
     
    1819        },
    1920        _deserialize: function(obj) {
     21            obj.questions = array.map(obj.questions,
     22                                      lang.hitch(questions,'_doDeserialize'));
    2023            if (obj.publicationDate) {
    21                 obj.publicationDate = stamp.fromISOString(obj.publicationDate);
     24                obj.publicationDate = this._parseDate(obj.publicationDate);
    2225            }
    2326        },
    2427        _serialize: function(obj) {
     28            obj.questions = array.map(obj.questions,
     29                                      lang.hitch(questions,'_doSerialize'));
    2530            if (obj.publicationDate) {
    26                 obj.publicationDate = stamp.toISOString(obj.publicationDate);
     31                obj.publicationDate = this._formatDate(obj.publicationDate);
    2732            }
    2833        },
  • Dev/trunk/src/client/qed-client/model/widgets/SurveyRunWidget.js

    r457 r492  
    1212                endDateBox.constraints.min  = value;
    1313            });
     14        },
     15        _getValueAttr: function() {
     16            var value = this.inherited(arguments);
     17            if ( !value.startDate ) { delete value.startDate; }
     18            if ( !value.endDate ) { delete value.endDate; }
     19            value.respondentCanDeleteOwnResponse = value.respondentCanDeleteOwnResponse[0] === true;
     20            return value;
    1421        }
    1522    });
  • Dev/trunk/src/client/qed-client/model/widgets/questions/templates/TextInputWidget.html

    r461 r492  
    11<form>
    22  <p>${text}</p>
    3   <div class="qedField" data-dojo-attach-point="textArea" data-dojo-type="dijit/form/Textarea" name="text"></div>
     3  <textarea class="qedField" data-dojo-attach-point="textArea" data-dojo-type="dijit/form/Textarea" name="text"></textarea>
    44</form>
  • Dev/trunk/src/client/qed-client/model/widgets/templates/QuestionWidget.html

    r443 r492  
    77            <input data-dojo-type="dijit/form/TextBox" name="title" type="text" class="loginInput" />
    88            <label for="question" class="loginLabel">Description</label>
    9             <input data-dojo-type="dijit/form/Textarea" name="description" type="text" class="loginInput"/>
     9            <textarea data-dojo-type="dijit/form/Textarea" name="description" type="text" class="loginInput"></textarea>
    1010            <label for="category" class="loginLabel">Category</label>
    1111            <input data-dojo-type="dijit/form/TextBox" name="category" type="text" class="loginInput" />
  • Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyRunWidget.html

    r461 r492  
    33    <div>
    44        <label for="mode" class="qedLabel">Description</label>
    5         <textarea name="description" class="qedField" data-dojo-type="dijit/form/Textarea"></textarea>
     5        <textarea name="description" class="qedField"
     6                  data-dojo-type="dijit/form/Textarea"></textarea>
    67    </div>
    78
    89    <div>
    910        <label for="startDate" class="qedLabel">Start date</label>
    10         <input type="text" name="startDate" class="qedField" data-dojo-type="dijit/form/DateTextBox" data-dojo-attach-point="startDateBox" />
     11        <input type="text" name="startDate" class="qedField"
     12               data-dojo-type="dijit/form/DateTextBox"
     13               data-dojo-attach-point="startDateBox" />
    1114    </div>
    1215
    1316    <div>
    1417        <label for="endDate" class="qedLabel">End date</label>
    15         <input type="text" name="endDate" class="qedField" data-dojo-type="dijit/form/DateTextBox" data-dojo-attach-point="endDateBox" />
     18        <input type="text" name="endDate" class="qedField"
     19               data-dojo-type="dijit/form/DateTextBox"
     20               data-dojo-attach-point="endDateBox" />
     21    </div>
     22
     23    <div>
     24        <label for="endDate" class="qedLabel">Allow respondents to delete their unsubmitted response</label>
     25        <input type="text" name="respondentCanDeleteOwnResponse"
     26               class="qedField"
     27               data-dojo-type="dijit/form/CheckBox"
     28               data-dojo-props="'value':true" />
    1629    </div>
    1730
  • Dev/trunk/src/client/qed-client/model/widgets/templates/SurveyWidget.html

    r461 r492  
    33    <input data-dojo-type="dijit/form/TextBox" name="title"/><br/>
    44    <label for="description">Description</label>
    5     <input data-dojo-type="dijit/form/Textarea" name="description"/><br/>
     5    <textarea data-dojo-type="dijit/form/Textarea" name="description"></textarea><br/>
    66</form>
  • Dev/trunk/src/client/qed-client/pages/_ObjectPage.js

    r491 r492  
    1111        classStore: null,
    1212        constructor: function() {
    13             if ( !this.classStore ) { throw new Error("Subclasses must specify a classStore."); }
     13            if ( !this.classStore ) {
     14                throw new Error("Subclasses must specify a classStore.");
     15            }
     16        },
     17        startup: function() {
     18            if ( this._started ) { return; }
     19            this.inherited(arguments);
     20            this.markClean();
    1421        },
    1522        _load: function() {
  • Dev/trunk/src/client/qed-client/pages/question.js

    r490 r492  
    2929        },
    3030        _handlePropertiesChange: function() {
    31             if ( this.propertiesForm.validate() ) {
    32                 lang.mixin(this.object,this.propertiesForm.get('value'));
    33             }
     31            lang.mixin(this.object,this.propertiesForm.get('value'));
    3432            this.markDirty();
     33            this._refresh();
    3534        },
    3635        _handleContentChange: function() {
    37             if ( this.contentList.validate() ) {
    38                 this.object.content = this.contentList.get('value');
    39             }
     36            this.object.content = this.contentList.get('value');
    4037            this.markDirty();
     38            this._refresh();
    4139        },
    4240        _save: function() {
    43             if ( this.propertiesForm.validate() && this.contentList.validate() ) {
    44                 lang.mixin(this.object,this.propertiesForm.get('value'));
    45                 this.object.content = this.contentList.get('value');
     41            if ( this._isValid ) {
    4642                return this.inherited(arguments);
    4743            } else {
     
    6864            return false;
    6965        },
     66        markDirty: function() {
     67            this._isValid = this.propertiesForm.validate() &&
     68                            this.contentList.validate();
     69            this.saveBtn.set('disabled',!this._isValid);
     70            this.saveAndCloseBtn.set('disabled',!this._isValid);
     71            this.discardBtn.set('label','Discard & Close');
     72            this.inherited(arguments);
     73        },
     74        markClean: function() {
     75            this._isValid = true;
     76            this.saveBtn.set('disabled',true);
     77            this.saveAndCloseBtn.set('disabled',true);
     78            this.discardBtn.set('label','Close');
     79            this.inherited(arguments);
     80        },
    7081        _ignore: function(evt) {
    7182            if ( evt ) { event.stop( evt ); }
  • Dev/trunk/src/client/qed-client/pages/response.js

    r490 r492  
    4040            this.submitButton.set('disabled',false);
    4141            this.continueButton.set('disabled',false);
    42             this.cancelButton.set('disabled',false);
     42            var canDelete = (this.response &&
     43                             this.response._surveyRun.respondentCanDeleteOwnResponse);
     44            this.cancelButton.set('disabled',canDelete||false);
    4345            this.surveyWidget.set('disabled', false);
    4446        },
  • Dev/trunk/src/client/qed-client/pages/survey.js

    r491 r492  
    2323            this._setupQuestionBrowser();
    2424            this._setupListView();
     25            this.questionList.on('change',lang.hitch(this,'_handleQuestionsChange'));
    2526            this._load();
    2627        },
     
    5859        _refresh: function() {
    5960            this.titleNode.innerHTML = this.object.title || "(set title in properties)";
    60             this.propertiesDialog.set('value',{survey:this.object});
     61            this.propertiesForm.set('value',{survey:this.object});
    6162            this.questionList.set('value',
    6263                                  this.object.questions);
    6364        },
    64         _save: function() {
    65             this.object.questions = this.questionList.get('value');
    66             return this.inherited(arguments);
    67         },
    6865        _includeQuestion: function(question) {
    6966            this.questionList.appendItem(question);
     67        },
     68        _handleQuestionsChange: function() {
     69            this.object.questions = this.questionList.get('value');
     70            this.markDirty();
     71            this._refresh();
    7072        },
    7173        _onShowProperties: function(evt) {
     
    7678        _onPropertiesOk: function(evt) {
    7779            this.propertiesDialog.hide();
    78             lang.mixin(this.object, this.propertiesDialog.get('value').survey);
     80            lang.mixin(this.object, this.propertiesForm.get('value').survey);
    7981            this.markDirty();
    8082            this._refresh();
     
    8486        _onPropertiesCancel: function(evt) {
    8587            this.propertiesDialog.hide();
    86             this.propertiesDialog.set('value',{survey:this.object});
     88            this.propertiesForm.set('value',{survey:this.object});
    8789            if ( evt ) { event.stop(evt); }
    8890            return false;
     
    109111                preview: true
    110112            });
     113        },
     114        markDirty: function() {
     115            this.saveBtn.set('disabled',false);
     116            this.saveAndCloseBtn.set('disabled',false);
     117            this.discardBtn.set('label','Discard & Close');
     118            this.inherited(arguments);
     119        },
     120        markClean: function() {
     121            this.saveBtn.set('disabled',true);
     122            this.saveAndCloseBtn.set('disabled',true);
     123            this.discardBtn.set('label','Close');
     124            this.inherited(arguments);
    111125        }
    112126    });
  • Dev/trunk/src/client/qed-client/pages/surveyRun.js

    r490 r492  
    7474        },
    7575        _onPropChange: function(e) {
    76             if ( this.surveyRunWidget.validate() ) {
    77                 lang.mixin(this.object,this.surveyRunWidget.get('value'));
     76            if ( this._updateObject() ) {
    7877                this._refreshURL();
    7978            }
     
    9089        },
    9190        _save: function() {
    92             if ( this.surveyRunWidget.validate() ) {
    93                 lang.mixin(this.object,this.surveyRunWidget.get('value'));
     91            if ( this._updateObject() ) {
    9492                return this.inherited(arguments);
    9593            } else {
    9694                return new Deferred.reject();
    9795            }
     96        },
     97        _updateObject: function() {
     98            var valid = this.surveyRunWidget.validate();
     99            if ( valid ) {
     100                lang.mixin(this.object,this.surveyRunWidget.get('value'));
     101            }
     102            return valid;
    98103        },
    99104        _onSave: function(evt) {
     
    115120            if ( evt ) { event.stop(evt); }
    116121            return false;
     122        },
     123        markDirty: function() {
     124            this.saveBtn.set('disabled',false);
     125            this.saveAndCloseBtn.set('disabled',false);
     126            this.discardBtn.set('label','Discard & Close');
     127            this.inherited(arguments);
     128        },
     129        markClean: function() {
     130            this.saveBtn.set('disabled',true);
     131            this.saveAndCloseBtn.set('disabled',true);
     132            this.discardBtn.set('label','Close');
     133            this.inherited(arguments);
    117134        }
    118135    });
  • Dev/trunk/src/client/qed-client/pages/templates/question.html

    r490 r492  
    1818                <button data-dojo-type="dijit/form/Button"
    1919                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'"
     20                        data-dojo-attach-point="saveBtn"
    2021                        data-dojo-attach-event="onClick:_onSave">
    2122                  Save</button>
    2223                <button data-dojo-type="dijit/form/Button"
    2324                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'"
     25                        data-dojo-attach-point="saveAndCloseBtn"
    2426                        data-dojo-attach-event="onClick:_onSaveAndClose">
    2527                  Save &amp; Close</button>
    2628                <button data-dojo-type="dijit/form/Button"
    2729                        data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'"
     30                        data-dojo-attach-point="discardBtn"
    2831                        data-dojo-attach-event="onClick:_onDiscard">
    2932                  Discard &amp; Close</button>
  • Dev/trunk/src/client/qed-client/pages/templates/survey.html

    r491 r492  
    2323            <button data-dojo-type="dijit/form/Button"
    2424                    data-dojo-attach-event="onClick:_onSave"
     25                    data-dojo-attach-point="saveBtn"
    2526                    data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'">
    2627                Save</button>
    2728            <button data-dojo-type="dijit/form/Button"
    2829                    data-dojo-attach-event="onClick:_onSaveAndClose"
     30                    data-dojo-attach-point="saveAndCloseBtn"
    2931                    data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconAccept'">
    3032                Save &amp; Close</button>
    3133            <button data-dojo-type="dijit/form/Button"
    3234                    data-dojo-attach-event="onClick:_onDiscardAndClose"
     35                    data-dojo-attach-point="discardBtn"
    3336                    data-dojo-props="baseClass: 'rftLargeButton', iconClass: 'rftIcon rftIconCancel'">
    3437                Discard &amp; Close</button>
     
    4144
    4245    <div data-dojo-type="dijit/Dialog"
    43          title="Survey properties"
    44          data-dojo-attach-point="propertiesDialog"
    45          data-dojo-attach-event="onSubmit:_onPropertiesOk">
    46         <fieldset class="qedFieldset">
    47             <div data-dojo-type="../model/widgets/SurveyWidget" data-dojo-props="name:'survey'"></div>
    48         </fieldset>
    49         <button data-dojo-type="dijit/form/Button"
    50                 type="submit"
    51                 data-dojo-attach-event="onClick:_onPropertiesOk">
    52             OK</button>
    53         <button data-dojo-type="dijit/form/Button"
    54                 type="button"
    55                 data-dojo-attach-event="onClick:_onPropertiesCancel">
    56             Cancel</button>
     46         data-dojo-props="'title':'Survey properties'"
     47         data-dojo-attach-point="propertiesDialog">
     48        <form data-dojo-type="dijit/form/Form"
     49              data-dojo-attach-point="propertiesForm"
     50              data-dojo-attach-event="onSubmit:_onPropertiesOk">
     51            <fieldset class="qedFieldset">
     52                <div data-dojo-type="../model/widgets/SurveyWidget" data-dojo-props="name:'survey'"></div>
     53            </fieldset>
     54            <button data-dojo-type="dijit/form/Button"
     55                    type="submit"
     56                    data-dojo-attach-event="onClick:_onPropertiesOk">
     57                OK</button>
     58            <button data-dojo-type="dijit/form/Button"
     59                    type="button"
     60                    data-dojo-attach-event="onClick:_onPropertiesCancel">
     61                Cancel</button>
     62        </form>
    5763    </div>
    5864
  • Dev/trunk/src/client/qed-client/pages/templates/surveyRun.html

    r490 r492  
    5555                class="blue"
    5656                data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
     57                data-dojo-attach-point="saveBtn"
    5758                data-dojo-attach-event="onClick:_onSave">Save</button>
    5859        <button data-dojo-type="dijit/form/Button"
    5960                class="blue"
    6061                data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconSave'"
     62                data-dojo-attach-point="saveAndCloseBtn"
    6163                data-dojo-attach-event="onClick:_onSaveAndClose">Save &amp; Close</button>
    6264        <button data-dojo-type="dijit/form/Button"
    6365                class="blue"
    6466                data-dojo-props="baseClass: 'rftBlockButton', iconClass: 'rftIcon rftIconClose'"
     67                data-dojo-attach-point="discardBtn"
    6568                data-dojo-attach-event="onClick:_onDiscard">Discard &amp; Close</button>
    6669    </div>
  • Dev/trunk/src/client/qed-client/ui/LoginDialogWrapper.coffee

    r487 r492  
    99    "dojo/_base/lang",
    1010    "dojo/on",
     11    "dojo/when",
    1112    "dojo/text!./templates/LoginDialogWrapper.html"
    1213], (session, _WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin,
    13     registry, declare, event, lang, _on, template) ->
     14    registry, declare, event, lang, _on, _when, template) ->
    1415    declare [_WidgetBase,_TemplatedMixin,_WidgetsInTemplateMixin],
    1516        templateString: template
     17        _fx: null
    1618        startup: () ->
    1719            if @_started then return
     
    2527                              value.password
    2628                .then () =>
    27                     @loginDialog.hide()
     29                    @_fx = _when(@_fx)
     30                    .then () =>
     31                        @loginDialog.hide()
    2832                , () =>
    2933                    alert "Login failed!"
     
    3135            false
    3236        onUserChange: (user) ->
    33             if user
    34                 @loginDialog.hide()
    35             else
    36                 @loginDialog.show()
     37            @_fx = _when(@_fx)
     38            .then () =>
     39                if user
     40                    @loginDialog.hide()
     41                else
     42                    @loginDialog.show()
    3743            null
  • Dev/trunk/src/client/qed-client/ui/templates/LoginDialogWrapper.html

    r468 r492  
    2525            <div data-dojo-type="dijit/form/Button"
    2626                 type="submit"
    27                  data-dojo-attach-event="onLogin">Login</div>
     27                 data-dojo-attach-event="onClick:onLogin">Login</div>
    2828        </form>
    2929    </div>
  • Dev/trunk/src/client/qed-client/widgets/_ComplexValueMixin.coffee

    r472 r492  
    22    "dijit/_Container",
    33    "dijit/form/_FormMixin",
     4    "dijit/registry",
    45    "dojo/_base/array",
    56    "dojo/_base/declare",
    6     "dojo/_base/event"
    7 ], (_Container, _FormMixin, array, declare, event) ->
     7    "dojo/_base/event",
     8    "dojo/on"
     9], (_Container, _FormMixin, registry, array, declare, event, _on) ->
    810    declare [_Container,_FormMixin],
    911        name: ""
     
    2022                        It is recommended to use <form> as the root
    2123                        element in your template for", @declaredClass
     24            @own ( _on @domNode, 'submit', (evt) => @_handleSubmit evt )
    2225
    2326        _setDisabledAttr: (value) ->
     
    3538            children[0].focus() if children.length > 0
    3639
    37         onSubmit: (e) =>
    38             # since this widget is used to create more complex
    39             # widgets within other forms, the onSubmit must either be
    40             # ignored or propagated, but not handled here.
    41             event.stop e if e
     40        _handleSubmit: (evt) ->
     41            node = @domNode
     42            until not node or ( widget and
     43                                typeof widget._onSubmit is "function" )
     44                node = node.parentNode
     45                widget = registry.byNode node if node
     46            widget._onSubmit(evt) if widget
     47            # we always stop the event, since this is a widget after all
     48            event.stop evt if evt
    4249            false
    43 
    44         _onSubmit: (e) =>
    45             # since this widget is used to create more complex
    46             # widgets within other forms, the onSubmit must either be
    47             # ignored or propagated, but not handled here.
    48             event.stop e if e
    49             false
  • Dev/trunk/src/server/app.js

    r490 r492  
    88  , CouchDB = require('./util/couch').CouchDB
    99  , _ = require("underscore")
    10   , tv4 = require("tv4")
     10  , validator = require("./util/validator")
    1111  , HTTPResult = require("./util/http-result")
    1212  , etags = require("./util/etags")
     
    151151        return new HTTPResult(500,{error: error.reason});
    152152    }
    153     function handleUnknownError(error){
     153    function handleUnknownError(error) {
    154154        return new HTTPResult(500, {error: "Unknown error", innerError: error});
    155155    }
     
    159159    function handleRowDocs(result) {
    160160        return _.map(result.rows, function(item) { return item.doc; });
     161    }
     162    function handleRowFirstDoc(result) {
     163        if ( result.rows.length > 0 ) {
     164            return result.rows[0].doc;
     165        } else {
     166            return new HTTPResult(404,{error:"No document found."});
     167        }
     168    }
     169    function handleRowFirstValue(result) {
     170        if ( result.rows.length > 0 ) {
     171            return result.rows[0].value;
     172        } else {
     173            return new HTTPResult(404,{error:"No document found."});
     174        }
     175    }
     176    function handleRowDictOfDocs(result) {
     177        return _.reduce(result.rows, function(dict,item) {
     178            dict[item.key] = item.doc;
     179            return dict;
     180        }, {});
     181    }
     182    function handleRowDictOfValues(result) {
     183        return _.reduce(result.rows, function(dict,item) {
     184            dict[item.key] = item.value;
     185            return dict;
     186        }, {});
    161187    }
    162188
     
    199225    function putDocument(id,rev,type,doc) {
    200226        var priv = stripAndReturnPrivates(doc);
    201         if ( doc.type === type && tv4.validateResult(doc, schema) ) {
     227        if ( doc.type === type && validator(doc, schema).valid ) {
    202228            var opts = rev ? {headers:{'If-Match':'"'+rev+'"'}} : {};
    203229            return HTTPResult.fromResponsePromise(couch.put(id,doc,opts).response,
     
    236262    function postDocument(type,doc) {
    237263        var priv = stripAndReturnPrivates(doc);
    238         if ( doc.type === type && tv4.validateResult(doc, schema) ) {
     264        if ( doc.type === type && validator(doc, schema).valid ) {
    239265            return HTTPResult.fromResponsePromise(couch.post(doc).response,
    240266                                                  handleUnknownError)
     
    321347        .handle({
    322348            200: handleRowDocs,
     349            default: handleUnknownResponse
     350        });
     351    }
     352    function getQuestionsAndCodes() {
     353        var url = '_design/questions/_view/by_code';
     354        var query = {include_docs:true};
     355        return HTTPResult.fromResponsePromise(couch.get(url,{query:query}).response,
     356                                              handleUnknownError)
     357        .handle({
     358            200: handleRowDictOfDocs,
    323359            default: handleUnknownResponse
    324360        });
     
    760796                        return new HTTPResult(403,{error: "Secrets are not the same."});
    761797                    } else {
    762                         return deleteDocument(id,rev,doc);
     798                        return getDocument(doc.surveyRunId,[],'SurveyRun')
     799                        .handle({
     800                            200: function(surveyRun) {
     801                                if ( surveyRun.respondentCanDeleteOwnResponse === true ) {
     802                                    return deleteDocument(id,rev,doc);
     803                                } else {
     804                                    return new HTTPResult(403,{error:"Not allowed to delete response."});
     805                                }
     806                            }
     807                        });
    763808                    }
    764809                }
  • Dev/trunk/src/server/config/check-couchdb.js

    r487 r492  
    11var Q = require('q')
    22  , _ = require('underscore')
    3   , tv4 = require('tv4')
     3  , validator = require('../util/validator')
    44  , CouchDB = require('../util/couch').CouchDB
    55  ;
     
    1010    var server = new CouchDB(couchServerURL,dbName);
    1111    var designRe = /^_design\//;
     12
     13    var codes = {};
     14    function codeUnique(code) {
     15        if ( code in codes ) {
     16            return false;
     17        } else {
     18            codes[code] = true;
     19            return true;
     20        }
     21    }
     22
    1223    return server.get('/_all_docs')
    1324    .then(function(allDocs){
     
    2031                return server.get(doc.id)
    2132                .then(function(doc){
    22                     var valid = tv4.validateResult(doc,schema);
     33                    var valid = validator(doc,schema);
     34                    if ( doc.type === "Question" && !codeUnique(doc.code) ) {
     35                        valid.valid = false;
     36                        valid.error = "Question code "+doc.code+" is not unique.";
     37                    }
    2338                    result[doc._id] = valid;
    2439                    return result;
  • Dev/trunk/src/server/config/couchdb-design-docs.js

    r487 r492  
    125125    },
    126126
     127    "qed/_design/surveyRuns": {
     128        __configAction: "replace",
     129        _id: "_design/surveys",
     130        language: "javascript",
     131        views: {
     132            by_dates: {
     133                map: function(doc){
     134                    if ( doc.type !== 'SurveyRun' ) { return; }
     135                    var startDate = doc.startDate || "";
     136                    var endDate = doc.endDate || {};
     137                    emit([startDate,endDate,doc.liveName||null],doc);
     138                }
     139            }
     140        }
     141    },
     142
    127143    "qed/_design/responses": {
    128144        __configAction: "replace",
  • Dev/trunk/src/server/config/couchdb-schema.json

    r487 r492  
    3636          "_rev": { "type": "string" },
    3737          "categories": { "type": "array", "items": { "type": "string" } },
    38           "code": { "type": "string" },
     38          "code": { "type": "string", "minLength": 1 },
    3939          "content": { "type": "array", "items": { "$ref": "#/definitions/content/any" } },
    4040          "description": { "type": "string" },
     
    5252          "_id": { "type": "string" },
    5353          "_rev": { "type": "string" },
     54          "description": { "type": "string" },
    5455          "publicationDate": { "type": "string", "format": "datetime" },
    5556          "questions": { "type": "array", "items": { "$ref": "#/definitions/docs/Question" } },
     
    6768          "description": { "type": "string" },
    6869          "endDate": { "type": "string", "format": "datetime" },
     70          "liveName": { "type": "string" },
    6971          "mode": { "type": "string", "enum": [ "open", "closed" ] },
    70           "secret": { "type": "string", "minLength": 8 },
     72          "respondentCanDeleteOwnResponse": { "type": "boolean" },
     73          "secret": { "type": "string", "minLength": 1 },
    7174          "startDate": { "type": "string", "format": "datetime" },
    7275          "survey": { "$ref": "#/definitions/docs/Survey" },
     
    8386          "_rev": { "type": "string" },
    8487          "answers": { "type": "object" },
     88          "email": { "type": "string", "format": "email" },
    8589          "publicationDate": { "type": "string", "format": "datetime" },
    86           "secret": { "type": "string", "minLength": 8 },
     90          "secret": { "type": "string", "minLength": 1 },
    8791          "surveyRunId": { "type": "string" }
    8892        },
  • Dev/trunk/src/server/config/upgrade-couchdb.js

    r487 r492  
    11var Q = require('q')
    22  , _ = require('underscore')
    3   , tv4 = require('tv4')
    43  , CouchDB = require('../util/couch').CouchDB
    54  ;
Note: See TracChangeset for help on using the changeset viewer.